Home | History | Annotate | Download | only in src
      1 // Copyright 2011 the V8 project authors. All rights reserved.
      2 // Redistribution and use in source and binary forms, with or without
      3 // modification, are permitted provided that the following conditions are
      4 // met:
      5 //
      6 //     * Redistributions of source code must retain the above copyright
      7 //       notice, this list of conditions and the following disclaimer.
      8 //     * Redistributions in binary form must reproduce the above
      9 //       copyright notice, this list of conditions and the following
     10 //       disclaimer in the documentation and/or other materials provided
     11 //       with the distribution.
     12 //     * Neither the name of Google Inc. nor the names of its
     13 //       contributors may be used to endorse or promote products derived
     14 //       from this software without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 
     28 // This module contains the platform-specific code. This make the rest of the
     29 // code less dependent on operating system, compilers and runtime libraries.
     30 // This module does specifically not deal with differences between different
     31 // processor architecture.
     32 // The platform classes have the same definition for all platforms. The
     33 // implementation for a particular platform is put in platform_<os>.cc.
     34 // The build system then uses the implementation for the target platform.
     35 //
     36 // This design has been chosen because it is simple and fast. Alternatively,
     37 // the platform dependent classes could have been implemented using abstract
     38 // superclasses with virtual methods and having specializations for each
     39 // platform. This design was rejected because it was more complicated and
     40 // slower. It would require factory methods for selecting the right
     41 // implementation and the overhead of virtual methods for performance
     42 // sensitive like mutex locking/unlocking.
     43 
     44 #ifndef V8_PLATFORM_H_
     45 #define V8_PLATFORM_H_
     46 
     47 #define V8_INFINITY INFINITY
     48 
     49 // Windows specific stuff.
     50 #ifdef WIN32
     51 
     52 // Microsoft Visual C++ specific stuff.
     53 #ifdef _MSC_VER
     54 
     55 enum {
     56   FP_NAN,
     57   FP_INFINITE,
     58   FP_ZERO,
     59   FP_SUBNORMAL,
     60   FP_NORMAL
     61 };
     62 
     63 #undef V8_INFINITY
     64 #define V8_INFINITY HUGE_VAL
     65 
     66 namespace v8 {
     67 namespace internal {
     68 int isfinite(double x);
     69 } }
     70 int isnan(double x);
     71 int isinf(double x);
     72 int isless(double x, double y);
     73 int isgreater(double x, double y);
     74 int fpclassify(double x);
     75 int signbit(double x);
     76 
     77 int strncasecmp(const char* s1, const char* s2, int n);
     78 
     79 #endif  // _MSC_VER
     80 
     81 // Random is missing on both Visual Studio and MinGW.
     82 int random();
     83 
     84 #endif  // WIN32
     85 
     86 
     87 #ifdef __sun
     88 # ifndef signbit
     89 int signbit(double x);
     90 # endif
     91 #endif
     92 
     93 
     94 // GCC specific stuff
     95 #ifdef __GNUC__
     96 
     97 // Needed for va_list on at least MinGW and Android.
     98 #include <stdarg.h>
     99 
    100 #define __GNUC_VERSION__ (__GNUC__ * 10000 + __GNUC_MINOR__ * 100)
    101 
    102 // Unfortunately, the INFINITY macro cannot be used with the '-pedantic'
    103 // warning flag and certain versions of GCC due to a bug:
    104 // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11931
    105 // For now, we use the more involved template-based version from <limits>, but
    106 // only when compiling with GCC versions affected by the bug (2.96.x - 4.0.x)
    107 // __GNUC_PREREQ is not defined in GCC for Mac OS X, so we define our own macro
    108 #if __GNUC_VERSION__ >= 29600 && __GNUC_VERSION__ < 40100
    109 #include <limits>
    110 #undef V8_INFINITY
    111 #define V8_INFINITY std::numeric_limits<double>::infinity()
    112 #endif
    113 
    114 #endif  // __GNUC__
    115 
    116 #include "atomicops.h"
    117 #include "platform-tls.h"
    118 #include "utils.h"
    119 #include "v8globals.h"
    120 
    121 namespace v8 {
    122 namespace internal {
    123 
    124 // Use AtomicWord for a machine-sized pointer. It is assumed that
    125 // reads and writes of naturally aligned values of this type are atomic.
    126 typedef intptr_t AtomicWord;
    127 
    128 class Semaphore;
    129 class Mutex;
    130 
    131 double ceiling(double x);
    132 double modulo(double x, double y);
    133 
    134 // Forward declarations.
    135 class Socket;
    136 
    137 // ----------------------------------------------------------------------------
    138 // OS
    139 //
    140 // This class has static methods for the different platform specific
    141 // functions. Add methods here to cope with differences between the
    142 // supported platforms.
    143 
    144 class OS {
    145  public:
    146   // Initializes the platform OS support. Called once at VM startup.
    147   static void Setup();
    148 
    149   // Returns the accumulated user time for thread. This routine
    150   // can be used for profiling. The implementation should
    151   // strive for high-precision timer resolution, preferable
    152   // micro-second resolution.
    153   static int GetUserTime(uint32_t* secs,  uint32_t* usecs);
    154 
    155   // Get a tick counter normalized to one tick per microsecond.
    156   // Used for calculating time intervals.
    157   static int64_t Ticks();
    158 
    159   // Returns current time as the number of milliseconds since
    160   // 00:00:00 UTC, January 1, 1970.
    161   static double TimeCurrentMillis();
    162 
    163   // Returns a string identifying the current time zone. The
    164   // timestamp is used for determining if DST is in effect.
    165   static const char* LocalTimezone(double time);
    166 
    167   // Returns the local time offset in milliseconds east of UTC without
    168   // taking daylight savings time into account.
    169   static double LocalTimeOffset();
    170 
    171   // Returns the daylight savings offset for the given time.
    172   static double DaylightSavingsOffset(double time);
    173 
    174   // Returns last OS error.
    175   static int GetLastError();
    176 
    177   static FILE* FOpen(const char* path, const char* mode);
    178   static bool Remove(const char* path);
    179 
    180   // Log file open mode is platform-dependent due to line ends issues.
    181   static const char* const LogFileOpenMode;
    182 
    183   // Print output to console. This is mostly used for debugging output.
    184   // On platforms that has standard terminal output, the output
    185   // should go to stdout.
    186   static void Print(const char* format, ...);
    187   static void VPrint(const char* format, va_list args);
    188 
    189   // Print output to a file. This is mostly used for debugging output.
    190   static void FPrint(FILE* out, const char* format, ...);
    191   static void VFPrint(FILE* out, const char* format, va_list args);
    192 
    193   // Print error output to console. This is mostly used for error message
    194   // output. On platforms that has standard terminal output, the output
    195   // should go to stderr.
    196   static void PrintError(const char* format, ...);
    197   static void VPrintError(const char* format, va_list args);
    198 
    199   // Allocate/Free memory used by JS heap. Pages are readable/writable, but
    200   // they are not guaranteed to be executable unless 'executable' is true.
    201   // Returns the address of allocated memory, or NULL if failed.
    202   static void* Allocate(const size_t requested,
    203                         size_t* allocated,
    204                         bool is_executable);
    205   static void Free(void* address, const size_t size);
    206   // Get the Alignment guaranteed by Allocate().
    207   static size_t AllocateAlignment();
    208 
    209 #ifdef ENABLE_HEAP_PROTECTION
    210   // Protect/unprotect a block of memory by marking it read-only/writable.
    211   static void Protect(void* address, size_t size);
    212   static void Unprotect(void* address, size_t size, bool is_executable);
    213 #endif
    214 
    215   // Returns an indication of whether a pointer is in a space that
    216   // has been allocated by Allocate().  This method may conservatively
    217   // always return false, but giving more accurate information may
    218   // improve the robustness of the stack dump code in the presence of
    219   // heap corruption.
    220   static bool IsOutsideAllocatedSpace(void* pointer);
    221 
    222   // Sleep for a number of milliseconds.
    223   static void Sleep(const int milliseconds);
    224 
    225   // Abort the current process.
    226   static void Abort();
    227 
    228   // Debug break.
    229   static void DebugBreak();
    230 
    231   // Walk the stack.
    232   static const int kStackWalkError = -1;
    233   static const int kStackWalkMaxNameLen = 256;
    234   static const int kStackWalkMaxTextLen = 256;
    235   struct StackFrame {
    236     void* address;
    237     char text[kStackWalkMaxTextLen];
    238   };
    239 
    240   static int StackWalk(Vector<StackFrame> frames);
    241 
    242   // Factory method for creating platform dependent Mutex.
    243   // Please use delete to reclaim the storage for the returned Mutex.
    244   static Mutex* CreateMutex();
    245 
    246   // Factory method for creating platform dependent Semaphore.
    247   // Please use delete to reclaim the storage for the returned Semaphore.
    248   static Semaphore* CreateSemaphore(int count);
    249 
    250   // Factory method for creating platform dependent Socket.
    251   // Please use delete to reclaim the storage for the returned Socket.
    252   static Socket* CreateSocket();
    253 
    254   class MemoryMappedFile {
    255    public:
    256     static MemoryMappedFile* open(const char* name);
    257     static MemoryMappedFile* create(const char* name, int size, void* initial);
    258     virtual ~MemoryMappedFile() { }
    259     virtual void* memory() = 0;
    260     virtual int size() = 0;
    261   };
    262 
    263   // Safe formatting print. Ensures that str is always null-terminated.
    264   // Returns the number of chars written, or -1 if output was truncated.
    265   static int SNPrintF(Vector<char> str, const char* format, ...);
    266   static int VSNPrintF(Vector<char> str,
    267                        const char* format,
    268                        va_list args);
    269 
    270   static char* StrChr(char* str, int c);
    271   static void StrNCpy(Vector<char> dest, const char* src, size_t n);
    272 
    273   // Support for the profiler.  Can do nothing, in which case ticks
    274   // occuring in shared libraries will not be properly accounted for.
    275   static void LogSharedLibraryAddresses();
    276 
    277   // Support for the profiler.  Notifies the external profiling
    278   // process that a code moving garbage collection starts.  Can do
    279   // nothing, in which case the code objects must not move (e.g., by
    280   // using --never-compact) if accurate profiling is desired.
    281   static void SignalCodeMovingGC();
    282 
    283   // The return value indicates the CPU features we are sure of because of the
    284   // OS.  For example MacOSX doesn't run on any x86 CPUs that don't have SSE2
    285   // instructions.
    286   // This is a little messy because the interpretation is subject to the cross
    287   // of the CPU and the OS.  The bits in the answer correspond to the bit
    288   // positions indicated by the members of the CpuFeature enum from globals.h
    289   static uint64_t CpuFeaturesImpliedByPlatform();
    290 
    291   // Returns the double constant NAN
    292   static double nan_value();
    293 
    294   // Support runtime detection of VFP3 on ARM CPUs.
    295   static bool ArmCpuHasFeature(CpuFeature feature);
    296 
    297   // Support runtime detection of FPU on MIPS CPUs.
    298   static bool MipsCpuHasFeature(CpuFeature feature);
    299 
    300   // Returns the activation frame alignment constraint or zero if
    301   // the platform doesn't care. Guaranteed to be a power of two.
    302   static int ActivationFrameAlignment();
    303 
    304   static void ReleaseStore(volatile AtomicWord* ptr, AtomicWord value);
    305 
    306 #if defined(V8_TARGET_ARCH_IA32)
    307   // Copy memory area to disjoint memory area.
    308   static void MemCopy(void* dest, const void* src, size_t size);
    309   // Limit below which the extra overhead of the MemCopy function is likely
    310   // to outweigh the benefits of faster copying.
    311   static const int kMinComplexMemCopy = 64;
    312   typedef void (*MemCopyFunction)(void* dest, const void* src, size_t size);
    313 
    314 #else  // V8_TARGET_ARCH_IA32
    315   static void MemCopy(void* dest, const void* src, size_t size) {
    316     memcpy(dest, src, size);
    317   }
    318   static const int kMinComplexMemCopy = 256;
    319 #endif  // V8_TARGET_ARCH_IA32
    320 
    321  private:
    322   static const int msPerSecond = 1000;
    323 
    324   DISALLOW_IMPLICIT_CONSTRUCTORS(OS);
    325 };
    326 
    327 
    328 class VirtualMemory {
    329  public:
    330   // Reserves virtual memory with size.
    331   explicit VirtualMemory(size_t size);
    332   ~VirtualMemory();
    333 
    334   // Returns whether the memory has been reserved.
    335   bool IsReserved();
    336 
    337   // Returns the start address of the reserved memory.
    338   void* address() {
    339     ASSERT(IsReserved());
    340     return address_;
    341   }
    342 
    343   // Returns the size of the reserved memory.
    344   size_t size() { return size_; }
    345 
    346   // Commits real memory. Returns whether the operation succeeded.
    347   bool Commit(void* address, size_t size, bool is_executable);
    348 
    349   // Uncommit real memory.  Returns whether the operation succeeded.
    350   bool Uncommit(void* address, size_t size);
    351 
    352  private:
    353   void* address_;  // Start address of the virtual memory.
    354   size_t size_;  // Size of the virtual memory.
    355 };
    356 
    357 // ----------------------------------------------------------------------------
    358 // Thread
    359 //
    360 // Thread objects are used for creating and running threads. When the start()
    361 // method is called the new thread starts running the run() method in the new
    362 // thread. The Thread object should not be deallocated before the thread has
    363 // terminated.
    364 
    365 class Thread {
    366  public:
    367   // Opaque data type for thread-local storage keys.
    368   // LOCAL_STORAGE_KEY_MIN_VALUE and LOCAL_STORAGE_KEY_MAX_VALUE are specified
    369   // to ensure that enumeration type has correct value range (see Issue 830 for
    370   // more details).
    371   enum LocalStorageKey {
    372     LOCAL_STORAGE_KEY_MIN_VALUE = kMinInt,
    373     LOCAL_STORAGE_KEY_MAX_VALUE = kMaxInt
    374   };
    375 
    376   struct Options {
    377     Options() : name("v8:<unknown>"), stack_size(0) {}
    378 
    379     const char* name;
    380     int stack_size;
    381   };
    382 
    383   // Create new thread (with a value for storing in the TLS isolate field).
    384   Thread(Isolate* isolate, const Options& options);
    385   Thread(Isolate* isolate, const char* name);
    386   virtual ~Thread();
    387 
    388   // Start new thread by calling the Run() method in the new thread.
    389   void Start();
    390 
    391   // Wait until thread terminates.
    392   void Join();
    393 
    394   inline const char* name() const {
    395     return name_;
    396   }
    397 
    398   // Abstract method for run handler.
    399   virtual void Run() = 0;
    400 
    401   // Thread-local storage.
    402   static LocalStorageKey CreateThreadLocalKey();
    403   static void DeleteThreadLocalKey(LocalStorageKey key);
    404   static void* GetThreadLocal(LocalStorageKey key);
    405   static int GetThreadLocalInt(LocalStorageKey key) {
    406     return static_cast<int>(reinterpret_cast<intptr_t>(GetThreadLocal(key)));
    407   }
    408   static void SetThreadLocal(LocalStorageKey key, void* value);
    409   static void SetThreadLocalInt(LocalStorageKey key, int value) {
    410     SetThreadLocal(key, reinterpret_cast<void*>(static_cast<intptr_t>(value)));
    411   }
    412   static bool HasThreadLocal(LocalStorageKey key) {
    413     return GetThreadLocal(key) != NULL;
    414   }
    415 
    416 #ifdef V8_FAST_TLS_SUPPORTED
    417   static inline void* GetExistingThreadLocal(LocalStorageKey key) {
    418     void* result = reinterpret_cast<void*>(
    419         InternalGetExistingThreadLocal(static_cast<intptr_t>(key)));
    420     ASSERT(result == GetThreadLocal(key));
    421     return result;
    422   }
    423 #else
    424   static inline void* GetExistingThreadLocal(LocalStorageKey key) {
    425     return GetThreadLocal(key);
    426   }
    427 #endif
    428 
    429   // A hint to the scheduler to let another thread run.
    430   static void YieldCPU();
    431 
    432   Isolate* isolate() const { return isolate_; }
    433 
    434   // The thread name length is limited to 16 based on Linux's implementation of
    435   // prctl().
    436   static const int kMaxThreadNameLength = 16;
    437 
    438   class PlatformData;
    439   PlatformData* data() { return data_; }
    440 
    441  private:
    442   void set_name(const char *name);
    443 
    444   PlatformData* data_;
    445 
    446   Isolate* isolate_;
    447   char name_[kMaxThreadNameLength];
    448   int stack_size_;
    449 
    450   DISALLOW_COPY_AND_ASSIGN(Thread);
    451 };
    452 
    453 
    454 // ----------------------------------------------------------------------------
    455 // Mutex
    456 //
    457 // Mutexes are used for serializing access to non-reentrant sections of code.
    458 // The implementations of mutex should allow for nested/recursive locking.
    459 
    460 class Mutex {
    461  public:
    462   virtual ~Mutex() {}
    463 
    464   // Locks the given mutex. If the mutex is currently unlocked, it becomes
    465   // locked and owned by the calling thread, and immediately. If the mutex
    466   // is already locked by another thread, suspends the calling thread until
    467   // the mutex is unlocked.
    468   virtual int Lock() = 0;
    469 
    470   // Unlocks the given mutex. The mutex is assumed to be locked and owned by
    471   // the calling thread on entrance.
    472   virtual int Unlock() = 0;
    473 
    474   // Tries to lock the given mutex. Returns whether the mutex was
    475   // successfully locked.
    476   virtual bool TryLock() = 0;
    477 };
    478 
    479 
    480 // ----------------------------------------------------------------------------
    481 // ScopedLock
    482 //
    483 // Stack-allocated ScopedLocks provide block-scoped locking and
    484 // unlocking of a mutex.
    485 class ScopedLock {
    486  public:
    487   explicit ScopedLock(Mutex* mutex): mutex_(mutex) {
    488     ASSERT(mutex_ != NULL);
    489     mutex_->Lock();
    490   }
    491   ~ScopedLock() {
    492     mutex_->Unlock();
    493   }
    494 
    495  private:
    496   Mutex* mutex_;
    497   DISALLOW_COPY_AND_ASSIGN(ScopedLock);
    498 };
    499 
    500 
    501 // ----------------------------------------------------------------------------
    502 // Semaphore
    503 //
    504 // A semaphore object is a synchronization object that maintains a count. The
    505 // count is decremented each time a thread completes a wait for the semaphore
    506 // object and incremented each time a thread signals the semaphore. When the
    507 // count reaches zero,  threads waiting for the semaphore blocks until the
    508 // count becomes non-zero.
    509 
    510 class Semaphore {
    511  public:
    512   virtual ~Semaphore() {}
    513 
    514   // Suspends the calling thread until the semaphore counter is non zero
    515   // and then decrements the semaphore counter.
    516   virtual void Wait() = 0;
    517 
    518   // Suspends the calling thread until the counter is non zero or the timeout
    519   // time has passsed. If timeout happens the return value is false and the
    520   // counter is unchanged. Otherwise the semaphore counter is decremented and
    521   // true is returned. The timeout value is specified in microseconds.
    522   virtual bool Wait(int timeout) = 0;
    523 
    524   // Increments the semaphore counter.
    525   virtual void Signal() = 0;
    526 };
    527 
    528 
    529 // ----------------------------------------------------------------------------
    530 // Socket
    531 //
    532 
    533 class Socket {
    534  public:
    535   virtual ~Socket() {}
    536 
    537   // Server initialization.
    538   virtual bool Bind(const int port) = 0;
    539   virtual bool Listen(int backlog) const = 0;
    540   virtual Socket* Accept() const = 0;
    541 
    542   // Client initialization.
    543   virtual bool Connect(const char* host, const char* port) = 0;
    544 
    545   // Shutdown socket for both read and write. This causes blocking Send and
    546   // Receive calls to exit. After Shutdown the Socket object cannot be used for
    547   // any communication.
    548   virtual bool Shutdown() = 0;
    549 
    550   // Data Transimission
    551   virtual int Send(const char* data, int len) const = 0;
    552   virtual int Receive(char* data, int len) const = 0;
    553 
    554   // Set the value of the SO_REUSEADDR socket option.
    555   virtual bool SetReuseAddress(bool reuse_address) = 0;
    556 
    557   virtual bool IsValid() const = 0;
    558 
    559   static bool Setup();
    560   static int LastError();
    561   static uint16_t HToN(uint16_t value);
    562   static uint16_t NToH(uint16_t value);
    563   static uint32_t HToN(uint32_t value);
    564   static uint32_t NToH(uint32_t value);
    565 };
    566 
    567 
    568 // ----------------------------------------------------------------------------
    569 // Sampler
    570 //
    571 // A sampler periodically samples the state of the VM and optionally
    572 // (if used for profiling) the program counter and stack pointer for
    573 // the thread that created it.
    574 
    575 // TickSample captures the information collected for each sample.
    576 class TickSample {
    577  public:
    578   TickSample()
    579       : state(OTHER),
    580         pc(NULL),
    581         sp(NULL),
    582         fp(NULL),
    583         tos(NULL),
    584         frames_count(0),
    585         has_external_callback(false) {}
    586   StateTag state;  // The state of the VM.
    587   Address pc;      // Instruction pointer.
    588   Address sp;      // Stack pointer.
    589   Address fp;      // Frame pointer.
    590   union {
    591     Address tos;   // Top stack value (*sp).
    592     Address external_callback;
    593   };
    594   static const int kMaxFramesCount = 64;
    595   Address stack[kMaxFramesCount];  // Call stack.
    596   int frames_count : 8;  // Number of captured frames.
    597   bool has_external_callback : 1;
    598 };
    599 
    600 #ifdef ENABLE_LOGGING_AND_PROFILING
    601 class Sampler {
    602  public:
    603   // Initialize sampler.
    604   Sampler(Isolate* isolate, int interval);
    605   virtual ~Sampler();
    606 
    607   int interval() const { return interval_; }
    608 
    609   // Performs stack sampling.
    610   void SampleStack(TickSample* sample) {
    611     DoSampleStack(sample);
    612     IncSamplesTaken();
    613   }
    614 
    615   // This method is called for each sampling period with the current
    616   // program counter.
    617   virtual void Tick(TickSample* sample) = 0;
    618 
    619   // Start and stop sampler.
    620   void Start();
    621   void Stop();
    622 
    623   // Is the sampler used for profiling?
    624   bool IsProfiling() const { return NoBarrier_Load(&profiling_) > 0; }
    625   void IncreaseProfilingDepth() { NoBarrier_AtomicIncrement(&profiling_, 1); }
    626   void DecreaseProfilingDepth() { NoBarrier_AtomicIncrement(&profiling_, -1); }
    627 
    628   // Whether the sampler is running (that is, consumes resources).
    629   bool IsActive() const { return NoBarrier_Load(&active_); }
    630 
    631   Isolate* isolate() { return isolate_; }
    632 
    633   // Used in tests to make sure that stack sampling is performed.
    634   int samples_taken() const { return samples_taken_; }
    635   void ResetSamplesTaken() { samples_taken_ = 0; }
    636 
    637   class PlatformData;
    638   PlatformData* data() { return data_; }
    639 
    640   PlatformData* platform_data() { return data_; }
    641 
    642  protected:
    643   virtual void DoSampleStack(TickSample* sample) = 0;
    644 
    645  private:
    646   void SetActive(bool value) { NoBarrier_Store(&active_, value); }
    647   void IncSamplesTaken() { if (++samples_taken_ < 0) samples_taken_ = 0; }
    648 
    649   Isolate* isolate_;
    650   const int interval_;
    651   Atomic32 profiling_;
    652   Atomic32 active_;
    653   PlatformData* data_;  // Platform specific data.
    654   int samples_taken_;  // Counts stack samples taken.
    655   DISALLOW_IMPLICIT_CONSTRUCTORS(Sampler);
    656 };
    657 
    658 
    659 #endif  // ENABLE_LOGGING_AND_PROFILING
    660 
    661 } }  // namespace v8::internal
    662 
    663 #endif  // V8_PLATFORM_H_
    664