blob: b2e0c48c1957fa520c37b487fdab3b20c27131fd [file] [log] [blame]
Steve Blocka7e24c12009-10-30 11:49:00 +00001// Copyright 2006-2008 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
55enum {
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
66namespace v8 {
67namespace internal {
68int isfinite(double x);
69} }
70int isnan(double x);
71int isinf(double x);
72int isless(double x, double y);
73int isgreater(double x, double y);
74int fpclassify(double x);
75int signbit(double x);
76
77int 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.
82int random();
83
84#endif // WIN32
85
Leon Clarkef7060e22010-06-03 12:02:55 +010086
87#ifdef __sun
88# ifndef signbit
89int signbit(double x);
90# endif
91#endif
92
93
Steve Blocka7e24c12009-10-30 11:49:00 +000094// 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
Ben Murdochb0fe1622011-05-05 13:52:32 +0100116#include "atomicops.h"
Steve Block44f0eee2011-05-26 01:26:41 +0100117#include "platform-tls.h"
Ben Murdochb0fe1622011-05-05 13:52:32 +0100118#include "utils.h"
119#include "v8globals.h"
120
Steve Blocka7e24c12009-10-30 11:49:00 +0000121namespace v8 {
122namespace internal {
123
Steve Block6ded16b2010-05-10 14:33:55 +0100124// Use AtomicWord for a machine-sized pointer. It is assumed that
125// reads and writes of naturally aligned values of this type are atomic.
126typedef intptr_t AtomicWord;
127
Steve Blocka7e24c12009-10-30 11:49:00 +0000128class Semaphore;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100129class Mutex;
Steve Blocka7e24c12009-10-30 11:49:00 +0000130
131double ceiling(double x);
Steve Block3ce2e202009-11-05 08:53:23 +0000132double modulo(double x, double y);
Steve Blocka7e24c12009-10-30 11:49:00 +0000133
134// Forward declarations.
135class 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
144class 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
Iain Merrick75681382010-08-19 15:07:18 +0100174 // Returns last OS error.
175 static int GetLastError();
176
Steve Blocka7e24c12009-10-30 11:49:00 +0000177 static FILE* FOpen(const char* path, const char* mode);
Steve Block1e0659c2011-05-24 12:43:12 +0100178 static bool Remove(const char* path);
Steve Blocka7e24c12009-10-30 11:49:00 +0000179
180 // Log file open mode is platform-dependent due to line ends issues.
Steve Block44f0eee2011-05-26 01:26:41 +0100181 static const char* const LogFileOpenMode;
Steve Blocka7e24c12009-10-30 11:49:00 +0000182
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
Ben Murdochb0fe1622011-05-05 13:52:32 +0100189 // 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
Steve Blocka7e24c12009-10-30 11:49:00 +0000193 // 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:
Steve Block1e0659c2011-05-24 12:43:12 +0100256 static MemoryMappedFile* open(const char* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000257 static MemoryMappedFile* create(const char* name, int size, void* initial);
258 virtual ~MemoryMappedFile() { }
259 virtual void* memory() = 0;
Steve Block1e0659c2011-05-24 12:43:12 +0100260 virtual int size() = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000261 };
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
Ben Murdochf87a2032010-10-22 12:50:53 +0100273 // Support for the profiler. Can do nothing, in which case ticks
274 // occuring in shared libraries will not be properly accounted for.
Steve Blocka7e24c12009-10-30 11:49:00 +0000275 static void LogSharedLibraryAddresses();
276
Ben Murdochf87a2032010-10-22 12:50:53 +0100277 // 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
Steve Blockd0582a62009-12-15 09:54:21 +0000283 // 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
Steve Blocka7e24c12009-10-30 11:49:00 +0000291 // Returns the double constant NAN
292 static double nan_value();
293
Steve Blockd0582a62009-12-15 09:54:21 +0000294 // Support runtime detection of VFP3 on ARM CPUs.
295 static bool ArmCpuHasFeature(CpuFeature feature);
296
Steve Block44f0eee2011-05-26 01:26:41 +0100297 // Support runtime detection of FPU on MIPS CPUs.
298 static bool MipsCpuHasFeature(CpuFeature feature);
299
Steve Blocka7e24c12009-10-30 11:49:00 +0000300 // 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
Leon Clarkef7060e22010-06-03 12:02:55 +0100304 static void ReleaseStore(volatile AtomicWord* ptr, AtomicWord value);
305
Steve Blocka7e24c12009-10-30 11:49:00 +0000306 private:
307 static const int msPerSecond = 1000;
308
309 DISALLOW_IMPLICIT_CONSTRUCTORS(OS);
310};
311
312
313class VirtualMemory {
314 public:
315 // Reserves virtual memory with size.
316 explicit VirtualMemory(size_t size);
317 ~VirtualMemory();
318
319 // Returns whether the memory has been reserved.
320 bool IsReserved();
321
322 // Returns the start address of the reserved memory.
323 void* address() {
324 ASSERT(IsReserved());
325 return address_;
Iain Merrick9ac36c92010-09-13 15:29:50 +0100326 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000327
328 // Returns the size of the reserved memory.
329 size_t size() { return size_; }
330
331 // Commits real memory. Returns whether the operation succeeded.
332 bool Commit(void* address, size_t size, bool is_executable);
333
334 // Uncommit real memory. Returns whether the operation succeeded.
335 bool Uncommit(void* address, size_t size);
336
337 private:
338 void* address_; // Start address of the virtual memory.
339 size_t size_; // Size of the virtual memory.
340};
341
342
343// ----------------------------------------------------------------------------
344// ThreadHandle
345//
346// A ThreadHandle represents a thread identifier for a thread. The ThreadHandle
347// does not own the underlying os handle. Thread handles can be used for
348// refering to threads and testing equality.
349
350class ThreadHandle {
351 public:
352 enum Kind { SELF, INVALID };
353 explicit ThreadHandle(Kind kind);
354
355 // Destructor.
356 ~ThreadHandle();
357
358 // Test for thread running.
359 bool IsSelf() const;
360
361 // Test for valid thread handle.
362 bool IsValid() const;
363
364 // Get platform-specific data.
365 class PlatformData;
366 PlatformData* thread_handle_data() { return data_; }
367
368 // Initialize the handle to kind
369 void Initialize(Kind kind);
370
371 private:
372 PlatformData* data_; // Captures platform dependent data.
373};
374
375
376// ----------------------------------------------------------------------------
377// Thread
378//
379// Thread objects are used for creating and running threads. When the start()
380// method is called the new thread starts running the run() method in the new
381// thread. The Thread object should not be deallocated before the thread has
382// terminated.
383
384class Thread: public ThreadHandle {
385 public:
386 // Opaque data type for thread-local storage keys.
Iain Merrick75681382010-08-19 15:07:18 +0100387 // LOCAL_STORAGE_KEY_MIN_VALUE and LOCAL_STORAGE_KEY_MAX_VALUE are specified
388 // to ensure that enumeration type has correct value range (see Issue 830 for
389 // more details).
390 enum LocalStorageKey {
391 LOCAL_STORAGE_KEY_MIN_VALUE = kMinInt,
392 LOCAL_STORAGE_KEY_MAX_VALUE = kMaxInt
393 };
Steve Blocka7e24c12009-10-30 11:49:00 +0000394
Steve Block44f0eee2011-05-26 01:26:41 +0100395 struct Options {
396 Options() : name("v8:<unknown>"), stack_size(0) {}
397
398 const char* name;
399 int stack_size;
400 };
401
402 // Create new thread (with a value for storing in the TLS isolate field).
403 Thread(Isolate* isolate, const Options& options);
404 Thread(Isolate* isolate, const char* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000405 virtual ~Thread();
406
407 // Start new thread by calling the Run() method in the new thread.
408 void Start();
409
410 // Wait until thread terminates.
411 void Join();
412
Steve Block9fac8402011-05-12 15:51:54 +0100413 inline const char* name() const {
414 return name_;
415 }
416
Steve Blocka7e24c12009-10-30 11:49:00 +0000417 // Abstract method for run handler.
418 virtual void Run() = 0;
419
420 // Thread-local storage.
421 static LocalStorageKey CreateThreadLocalKey();
422 static void DeleteThreadLocalKey(LocalStorageKey key);
423 static void* GetThreadLocal(LocalStorageKey key);
424 static int GetThreadLocalInt(LocalStorageKey key) {
425 return static_cast<int>(reinterpret_cast<intptr_t>(GetThreadLocal(key)));
426 }
427 static void SetThreadLocal(LocalStorageKey key, void* value);
428 static void SetThreadLocalInt(LocalStorageKey key, int value) {
429 SetThreadLocal(key, reinterpret_cast<void*>(static_cast<intptr_t>(value)));
430 }
431 static bool HasThreadLocal(LocalStorageKey key) {
432 return GetThreadLocal(key) != NULL;
433 }
434
Steve Block44f0eee2011-05-26 01:26:41 +0100435#ifdef V8_FAST_TLS_SUPPORTED
436 static inline void* GetExistingThreadLocal(LocalStorageKey key) {
437 void* result = reinterpret_cast<void*>(
438 InternalGetExistingThreadLocal(static_cast<intptr_t>(key)));
439 ASSERT(result == GetThreadLocal(key));
440 return result;
441 }
442#else
443 static inline void* GetExistingThreadLocal(LocalStorageKey key) {
444 return GetThreadLocal(key);
445 }
446#endif
447
Steve Blocka7e24c12009-10-30 11:49:00 +0000448 // A hint to the scheduler to let another thread run.
449 static void YieldCPU();
450
Steve Block44f0eee2011-05-26 01:26:41 +0100451 Isolate* isolate() const { return isolate_; }
452
Steve Block9fac8402011-05-12 15:51:54 +0100453 // The thread name length is limited to 16 based on Linux's implementation of
454 // prctl().
455 static const int kMaxThreadNameLength = 16;
Steve Blocka7e24c12009-10-30 11:49:00 +0000456 private:
Steve Block9fac8402011-05-12 15:51:54 +0100457 void set_name(const char *name);
458
Steve Blocka7e24c12009-10-30 11:49:00 +0000459 class PlatformData;
460 PlatformData* data_;
Steve Block44f0eee2011-05-26 01:26:41 +0100461 Isolate* isolate_;
Steve Block9fac8402011-05-12 15:51:54 +0100462 char name_[kMaxThreadNameLength];
Steve Block44f0eee2011-05-26 01:26:41 +0100463 int stack_size_;
Steve Block9fac8402011-05-12 15:51:54 +0100464
Steve Blocka7e24c12009-10-30 11:49:00 +0000465 DISALLOW_COPY_AND_ASSIGN(Thread);
466};
467
468
469// ----------------------------------------------------------------------------
470// Mutex
471//
472// Mutexes are used for serializing access to non-reentrant sections of code.
473// The implementations of mutex should allow for nested/recursive locking.
474
475class Mutex {
476 public:
477 virtual ~Mutex() {}
478
479 // Locks the given mutex. If the mutex is currently unlocked, it becomes
480 // locked and owned by the calling thread, and immediately. If the mutex
481 // is already locked by another thread, suspends the calling thread until
482 // the mutex is unlocked.
483 virtual int Lock() = 0;
484
485 // Unlocks the given mutex. The mutex is assumed to be locked and owned by
486 // the calling thread on entrance.
487 virtual int Unlock() = 0;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100488
489 // Tries to lock the given mutex. Returns whether the mutex was
490 // successfully locked.
491 virtual bool TryLock() = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000492};
493
494
495// ----------------------------------------------------------------------------
Steve Block44f0eee2011-05-26 01:26:41 +0100496// ScopedLock/ScopedUnlock
Steve Blocka7e24c12009-10-30 11:49:00 +0000497//
Steve Block44f0eee2011-05-26 01:26:41 +0100498// Stack-allocated ScopedLocks/ScopedUnlocks provide block-scoped
499// locking and unlocking of a mutex.
Steve Blocka7e24c12009-10-30 11:49:00 +0000500class ScopedLock {
501 public:
502 explicit ScopedLock(Mutex* mutex): mutex_(mutex) {
Steve Block44f0eee2011-05-26 01:26:41 +0100503 ASSERT(mutex_ != NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000504 mutex_->Lock();
505 }
506 ~ScopedLock() {
507 mutex_->Unlock();
508 }
509
510 private:
511 Mutex* mutex_;
512 DISALLOW_COPY_AND_ASSIGN(ScopedLock);
513};
514
515
516// ----------------------------------------------------------------------------
517// Semaphore
518//
519// A semaphore object is a synchronization object that maintains a count. The
520// count is decremented each time a thread completes a wait for the semaphore
521// object and incremented each time a thread signals the semaphore. When the
522// count reaches zero, threads waiting for the semaphore blocks until the
523// count becomes non-zero.
524
525class Semaphore {
526 public:
527 virtual ~Semaphore() {}
528
529 // Suspends the calling thread until the semaphore counter is non zero
530 // and then decrements the semaphore counter.
531 virtual void Wait() = 0;
532
533 // Suspends the calling thread until the counter is non zero or the timeout
534 // time has passsed. If timeout happens the return value is false and the
535 // counter is unchanged. Otherwise the semaphore counter is decremented and
536 // true is returned. The timeout value is specified in microseconds.
537 virtual bool Wait(int timeout) = 0;
538
539 // Increments the semaphore counter.
540 virtual void Signal() = 0;
541};
542
543
544// ----------------------------------------------------------------------------
545// Socket
546//
547
548class Socket {
549 public:
550 virtual ~Socket() {}
551
552 // Server initialization.
553 virtual bool Bind(const int port) = 0;
554 virtual bool Listen(int backlog) const = 0;
555 virtual Socket* Accept() const = 0;
556
557 // Client initialization.
558 virtual bool Connect(const char* host, const char* port) = 0;
559
560 // Shutdown socket for both read and write. This causes blocking Send and
561 // Receive calls to exit. After Shutdown the Socket object cannot be used for
562 // any communication.
563 virtual bool Shutdown() = 0;
564
565 // Data Transimission
566 virtual int Send(const char* data, int len) const = 0;
567 virtual int Receive(char* data, int len) const = 0;
568
569 // Set the value of the SO_REUSEADDR socket option.
570 virtual bool SetReuseAddress(bool reuse_address) = 0;
571
572 virtual bool IsValid() const = 0;
573
574 static bool Setup();
575 static int LastError();
576 static uint16_t HToN(uint16_t value);
577 static uint16_t NToH(uint16_t value);
578 static uint32_t HToN(uint32_t value);
579 static uint32_t NToH(uint32_t value);
580};
581
582
Steve Blocka7e24c12009-10-30 11:49:00 +0000583// ----------------------------------------------------------------------------
584// Sampler
585//
586// A sampler periodically samples the state of the VM and optionally
587// (if used for profiling) the program counter and stack pointer for
588// the thread that created it.
589
590// TickSample captures the information collected for each sample.
591class TickSample {
592 public:
Leon Clarked91b9f72010-01-27 17:25:45 +0000593 TickSample()
Steve Block6ded16b2010-05-10 14:33:55 +0100594 : state(OTHER),
595 pc(NULL),
Leon Clarked91b9f72010-01-27 17:25:45 +0000596 sp(NULL),
597 fp(NULL),
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100598 tos(NULL),
Leon Clarked91b9f72010-01-27 17:25:45 +0000599 frames_count(0) {}
Steve Block6ded16b2010-05-10 14:33:55 +0100600 StateTag state; // The state of the VM.
Steve Block44f0eee2011-05-26 01:26:41 +0100601 Address pc; // Instruction pointer.
602 Address sp; // Stack pointer.
603 Address fp; // Frame pointer.
604 union {
605 Address tos; // Top stack value (*sp).
606 Address external_callback;
607 };
Steve Block6ded16b2010-05-10 14:33:55 +0100608 static const int kMaxFramesCount = 64;
609 Address stack[kMaxFramesCount]; // Call stack.
Steve Block44f0eee2011-05-26 01:26:41 +0100610 int frames_count : 8; // Number of captured frames.
611 bool has_external_callback : 1;
Steve Blocka7e24c12009-10-30 11:49:00 +0000612};
613
Steve Block6ded16b2010-05-10 14:33:55 +0100614#ifdef ENABLE_LOGGING_AND_PROFILING
Steve Blocka7e24c12009-10-30 11:49:00 +0000615class Sampler {
616 public:
617 // Initialize sampler.
Steve Block44f0eee2011-05-26 01:26:41 +0100618 Sampler(Isolate* isolate, int interval);
Steve Blocka7e24c12009-10-30 11:49:00 +0000619 virtual ~Sampler();
620
Steve Block44f0eee2011-05-26 01:26:41 +0100621 int interval() const { return interval_; }
622
Steve Blocka7e24c12009-10-30 11:49:00 +0000623 // Performs stack sampling.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800624 void SampleStack(TickSample* sample) {
625 DoSampleStack(sample);
626 IncSamplesTaken();
627 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000628
629 // This method is called for each sampling period with the current
630 // program counter.
631 virtual void Tick(TickSample* sample) = 0;
632
633 // Start and stop sampler.
634 void Start();
635 void Stop();
636
Ben Murdochf87a2032010-10-22 12:50:53 +0100637 // Is the sampler used for profiling?
Ben Murdochb0fe1622011-05-05 13:52:32 +0100638 bool IsProfiling() const { return NoBarrier_Load(&profiling_) > 0; }
639 void IncreaseProfilingDepth() { NoBarrier_AtomicIncrement(&profiling_, 1); }
640 void DecreaseProfilingDepth() { NoBarrier_AtomicIncrement(&profiling_, -1); }
Steve Blocka7e24c12009-10-30 11:49:00 +0000641
642 // Whether the sampler is running (that is, consumes resources).
Ben Murdochb0fe1622011-05-05 13:52:32 +0100643 bool IsActive() const { return NoBarrier_Load(&active_); }
Steve Blocka7e24c12009-10-30 11:49:00 +0000644
Steve Block44f0eee2011-05-26 01:26:41 +0100645 Isolate* isolate() { return isolate_; }
646
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800647 // Used in tests to make sure that stack sampling is performed.
648 int samples_taken() const { return samples_taken_; }
649 void ResetSamplesTaken() { samples_taken_ = 0; }
650
Steve Blocka7e24c12009-10-30 11:49:00 +0000651 class PlatformData;
Steve Block44f0eee2011-05-26 01:26:41 +0100652 PlatformData* data() { return data_; }
653
654 PlatformData* platform_data() { return data_; }
Steve Blocka7e24c12009-10-30 11:49:00 +0000655
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800656 protected:
657 virtual void DoSampleStack(TickSample* sample) = 0;
658
Steve Blocka7e24c12009-10-30 11:49:00 +0000659 private:
Ben Murdochb0fe1622011-05-05 13:52:32 +0100660 void SetActive(bool value) { NoBarrier_Store(&active_, value); }
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800661 void IncSamplesTaken() { if (++samples_taken_ < 0) samples_taken_ = 0; }
662
Steve Block44f0eee2011-05-26 01:26:41 +0100663 Isolate* isolate_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000664 const int interval_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100665 Atomic32 profiling_;
666 Atomic32 active_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000667 PlatformData* data_; // Platform specific data.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800668 int samples_taken_; // Counts stack samples taken.
Steve Blocka7e24c12009-10-30 11:49:00 +0000669 DISALLOW_IMPLICIT_CONSTRUCTORS(Sampler);
670};
671
Steve Block44f0eee2011-05-26 01:26:41 +0100672
Steve Blocka7e24c12009-10-30 11:49:00 +0000673#endif // ENABLE_LOGGING_AND_PROFILING
674
675} } // namespace v8::internal
676
677#endif // V8_PLATFORM_H_