• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // 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 
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 // GCC specific stuff
87 #ifdef __GNUC__
88 
89 // Needed for va_list on at least MinGW and Android.
90 #include <stdarg.h>
91 
92 #define __GNUC_VERSION__ (__GNUC__ * 10000 + __GNUC_MINOR__ * 100)
93 
94 // Unfortunately, the INFINITY macro cannot be used with the '-pedantic'
95 // warning flag and certain versions of GCC due to a bug:
96 // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11931
97 // For now, we use the more involved template-based version from <limits>, but
98 // only when compiling with GCC versions affected by the bug (2.96.x - 4.0.x)
99 // __GNUC_PREREQ is not defined in GCC for Mac OS X, so we define our own macro
100 #if __GNUC_VERSION__ >= 29600 && __GNUC_VERSION__ < 40100
101 #include <limits>
102 #undef V8_INFINITY
103 #define V8_INFINITY std::numeric_limits<double>::infinity()
104 #endif
105 
106 #endif  // __GNUC__
107 
108 namespace v8 {
109 namespace internal {
110 
111 class Semaphore;
112 
113 double ceiling(double x);
114 
115 // Forward declarations.
116 class Socket;
117 
118 // ----------------------------------------------------------------------------
119 // OS
120 //
121 // This class has static methods for the different platform specific
122 // functions. Add methods here to cope with differences between the
123 // supported platforms.
124 
125 class OS {
126  public:
127   // Initializes the platform OS support. Called once at VM startup.
128   static void Setup();
129 
130   // Returns the accumulated user time for thread. This routine
131   // can be used for profiling. The implementation should
132   // strive for high-precision timer resolution, preferable
133   // micro-second resolution.
134   static int GetUserTime(uint32_t* secs,  uint32_t* usecs);
135 
136   // Get a tick counter normalized to one tick per microsecond.
137   // Used for calculating time intervals.
138   static int64_t Ticks();
139 
140   // Returns current time as the number of milliseconds since
141   // 00:00:00 UTC, January 1, 1970.
142   static double TimeCurrentMillis();
143 
144   // Returns a string identifying the current time zone. The
145   // timestamp is used for determining if DST is in effect.
146   static const char* LocalTimezone(double time);
147 
148   // Returns the local time offset in milliseconds east of UTC without
149   // taking daylight savings time into account.
150   static double LocalTimeOffset();
151 
152   // Returns the daylight savings offset for the given time.
153   static double DaylightSavingsOffset(double time);
154 
155   static FILE* FOpen(const char* path, const char* mode);
156 
157   // Log file open mode is platform-dependent due to line ends issues.
158   static const char* LogFileOpenMode;
159 
160   // Print output to console. This is mostly used for debugging output.
161   // On platforms that has standard terminal output, the output
162   // should go to stdout.
163   static void Print(const char* format, ...);
164   static void VPrint(const char* format, va_list args);
165 
166   // Print error output to console. This is mostly used for error message
167   // output. On platforms that has standard terminal output, the output
168   // should go to stderr.
169   static void PrintError(const char* format, ...);
170   static void VPrintError(const char* format, va_list args);
171 
172   // Allocate/Free memory used by JS heap. Pages are readable/writable, but
173   // they are not guaranteed to be executable unless 'executable' is true.
174   // Returns the address of allocated memory, or NULL if failed.
175   static void* Allocate(const size_t requested,
176                         size_t* allocated,
177                         bool is_executable);
178   static void Free(void* address, const size_t size);
179   // Get the Alignment guaranteed by Allocate().
180   static size_t AllocateAlignment();
181 
182 #ifdef ENABLE_HEAP_PROTECTION
183   // Protect/unprotect a block of memory by marking it read-only/writable.
184   static void Protect(void* address, size_t size);
185   static void Unprotect(void* address, size_t size, bool is_executable);
186 #endif
187 
188   // Returns an indication of whether a pointer is in a space that
189   // has been allocated by Allocate().  This method may conservatively
190   // always return false, but giving more accurate information may
191   // improve the robustness of the stack dump code in the presence of
192   // heap corruption.
193   static bool IsOutsideAllocatedSpace(void* pointer);
194 
195   // Sleep for a number of milliseconds.
196   static void Sleep(const int milliseconds);
197 
198   // Abort the current process.
199   static void Abort();
200 
201   // Debug break.
202   static void DebugBreak();
203 
204   // Walk the stack.
205   static const int kStackWalkError = -1;
206   static const int kStackWalkMaxNameLen = 256;
207   static const int kStackWalkMaxTextLen = 256;
208   struct StackFrame {
209     void* address;
210     char text[kStackWalkMaxTextLen];
211   };
212 
213   static int StackWalk(Vector<StackFrame> frames);
214 
215   // Factory method for creating platform dependent Mutex.
216   // Please use delete to reclaim the storage for the returned Mutex.
217   static Mutex* CreateMutex();
218 
219   // Factory method for creating platform dependent Semaphore.
220   // Please use delete to reclaim the storage for the returned Semaphore.
221   static Semaphore* CreateSemaphore(int count);
222 
223   // Factory method for creating platform dependent Socket.
224   // Please use delete to reclaim the storage for the returned Socket.
225   static Socket* CreateSocket();
226 
227   class MemoryMappedFile {
228    public:
229     static MemoryMappedFile* create(const char* name, int size, void* initial);
~MemoryMappedFile()230     virtual ~MemoryMappedFile() { }
231     virtual void* memory() = 0;
232   };
233 
234   // Safe formatting print. Ensures that str is always null-terminated.
235   // Returns the number of chars written, or -1 if output was truncated.
236   static int SNPrintF(Vector<char> str, const char* format, ...);
237   static int VSNPrintF(Vector<char> str,
238                        const char* format,
239                        va_list args);
240 
241   static char* StrChr(char* str, int c);
242   static void StrNCpy(Vector<char> dest, const char* src, size_t n);
243 
244   // Support for profiler.  Can do nothing, in which case ticks
245   // occuring in shared libraries will not be properly accounted
246   // for.
247   static void LogSharedLibraryAddresses();
248 
249   // Returns the double constant NAN
250   static double nan_value();
251 
252   // Returns the activation frame alignment constraint or zero if
253   // the platform doesn't care. Guaranteed to be a power of two.
254   static int ActivationFrameAlignment();
255 
256  private:
257   static const int msPerSecond = 1000;
258 
259   DISALLOW_IMPLICIT_CONSTRUCTORS(OS);
260 };
261 
262 
263 class VirtualMemory {
264  public:
265   // Reserves virtual memory with size.
266   explicit VirtualMemory(size_t size);
267   ~VirtualMemory();
268 
269   // Returns whether the memory has been reserved.
270   bool IsReserved();
271 
272   // Returns the start address of the reserved memory.
address()273   void* address() {
274     ASSERT(IsReserved());
275     return address_;
276   };
277 
278   // Returns the size of the reserved memory.
size()279   size_t size() { return size_; }
280 
281   // Commits real memory. Returns whether the operation succeeded.
282   bool Commit(void* address, size_t size, bool is_executable);
283 
284   // Uncommit real memory.  Returns whether the operation succeeded.
285   bool Uncommit(void* address, size_t size);
286 
287  private:
288   void* address_;  // Start address of the virtual memory.
289   size_t size_;  // Size of the virtual memory.
290 };
291 
292 
293 // ----------------------------------------------------------------------------
294 // ThreadHandle
295 //
296 // A ThreadHandle represents a thread identifier for a thread. The ThreadHandle
297 // does not own the underlying os handle. Thread handles can be used for
298 // refering to threads and testing equality.
299 
300 class ThreadHandle {
301  public:
302   enum Kind { SELF, INVALID };
303   explicit ThreadHandle(Kind kind);
304 
305   // Destructor.
306   ~ThreadHandle();
307 
308   // Test for thread running.
309   bool IsSelf() const;
310 
311   // Test for valid thread handle.
312   bool IsValid() const;
313 
314   // Get platform-specific data.
315   class PlatformData;
thread_handle_data()316   PlatformData* thread_handle_data() { return data_; }
317 
318   // Initialize the handle to kind
319   void Initialize(Kind kind);
320 
321  private:
322   PlatformData* data_;  // Captures platform dependent data.
323 };
324 
325 
326 // ----------------------------------------------------------------------------
327 // Thread
328 //
329 // Thread objects are used for creating and running threads. When the start()
330 // method is called the new thread starts running the run() method in the new
331 // thread. The Thread object should not be deallocated before the thread has
332 // terminated.
333 
334 class Thread: public ThreadHandle {
335  public:
336   // Opaque data type for thread-local storage keys.
337   enum LocalStorageKey {};
338 
339   // Create new thread.
340   Thread();
341   virtual ~Thread();
342 
343   // Start new thread by calling the Run() method in the new thread.
344   void Start();
345 
346   // Wait until thread terminates.
347   void Join();
348 
349   // Abstract method for run handler.
350   virtual void Run() = 0;
351 
352   // Thread-local storage.
353   static LocalStorageKey CreateThreadLocalKey();
354   static void DeleteThreadLocalKey(LocalStorageKey key);
355   static void* GetThreadLocal(LocalStorageKey key);
GetThreadLocalInt(LocalStorageKey key)356   static int GetThreadLocalInt(LocalStorageKey key) {
357     return static_cast<int>(reinterpret_cast<intptr_t>(GetThreadLocal(key)));
358   }
359   static void SetThreadLocal(LocalStorageKey key, void* value);
SetThreadLocalInt(LocalStorageKey key,int value)360   static void SetThreadLocalInt(LocalStorageKey key, int value) {
361     SetThreadLocal(key, reinterpret_cast<void*>(static_cast<intptr_t>(value)));
362   }
HasThreadLocal(LocalStorageKey key)363   static bool HasThreadLocal(LocalStorageKey key) {
364     return GetThreadLocal(key) != NULL;
365   }
366 
367   // A hint to the scheduler to let another thread run.
368   static void YieldCPU();
369 
370  private:
371   class PlatformData;
372   PlatformData* data_;
373   DISALLOW_COPY_AND_ASSIGN(Thread);
374 };
375 
376 
377 // ----------------------------------------------------------------------------
378 // Mutex
379 //
380 // Mutexes are used for serializing access to non-reentrant sections of code.
381 // The implementations of mutex should allow for nested/recursive locking.
382 
383 class Mutex {
384  public:
~Mutex()385   virtual ~Mutex() {}
386 
387   // Locks the given mutex. If the mutex is currently unlocked, it becomes
388   // locked and owned by the calling thread, and immediately. If the mutex
389   // is already locked by another thread, suspends the calling thread until
390   // the mutex is unlocked.
391   virtual int Lock() = 0;
392 
393   // Unlocks the given mutex. The mutex is assumed to be locked and owned by
394   // the calling thread on entrance.
395   virtual int Unlock() = 0;
396 };
397 
398 
399 // ----------------------------------------------------------------------------
400 // ScopedLock
401 //
402 // Stack-allocated ScopedLocks provide block-scoped locking and unlocking
403 // of a mutex.
404 class ScopedLock {
405  public:
ScopedLock(Mutex * mutex)406   explicit ScopedLock(Mutex* mutex): mutex_(mutex) {
407     mutex_->Lock();
408   }
~ScopedLock()409   ~ScopedLock() {
410     mutex_->Unlock();
411   }
412 
413  private:
414   Mutex* mutex_;
415   DISALLOW_COPY_AND_ASSIGN(ScopedLock);
416 };
417 
418 
419 // ----------------------------------------------------------------------------
420 // Semaphore
421 //
422 // A semaphore object is a synchronization object that maintains a count. The
423 // count is decremented each time a thread completes a wait for the semaphore
424 // object and incremented each time a thread signals the semaphore. When the
425 // count reaches zero,  threads waiting for the semaphore blocks until the
426 // count becomes non-zero.
427 
428 class Semaphore {
429  public:
~Semaphore()430   virtual ~Semaphore() {}
431 
432   // Suspends the calling thread until the semaphore counter is non zero
433   // and then decrements the semaphore counter.
434   virtual void Wait() = 0;
435 
436   // Suspends the calling thread until the counter is non zero or the timeout
437   // time has passsed. If timeout happens the return value is false and the
438   // counter is unchanged. Otherwise the semaphore counter is decremented and
439   // true is returned. The timeout value is specified in microseconds.
440   virtual bool Wait(int timeout) = 0;
441 
442   // Increments the semaphore counter.
443   virtual void Signal() = 0;
444 };
445 
446 
447 // ----------------------------------------------------------------------------
448 // Socket
449 //
450 
451 class Socket {
452  public:
~Socket()453   virtual ~Socket() {}
454 
455   // Server initialization.
456   virtual bool Bind(const int port) = 0;
457   virtual bool Listen(int backlog) const = 0;
458   virtual Socket* Accept() const = 0;
459 
460   // Client initialization.
461   virtual bool Connect(const char* host, const char* port) = 0;
462 
463   // Shutdown socket for both read and write. This causes blocking Send and
464   // Receive calls to exit. After Shutdown the Socket object cannot be used for
465   // any communication.
466   virtual bool Shutdown() = 0;
467 
468   // Data Transimission
469   virtual int Send(const char* data, int len) const = 0;
470   virtual int Receive(char* data, int len) const = 0;
471 
472   // Set the value of the SO_REUSEADDR socket option.
473   virtual bool SetReuseAddress(bool reuse_address) = 0;
474 
475   virtual bool IsValid() const = 0;
476 
477   static bool Setup();
478   static int LastError();
479   static uint16_t HToN(uint16_t value);
480   static uint16_t NToH(uint16_t value);
481   static uint32_t HToN(uint32_t value);
482   static uint32_t NToH(uint32_t value);
483 };
484 
485 
486 #ifdef ENABLE_LOGGING_AND_PROFILING
487 // ----------------------------------------------------------------------------
488 // Sampler
489 //
490 // A sampler periodically samples the state of the VM and optionally
491 // (if used for profiling) the program counter and stack pointer for
492 // the thread that created it.
493 
494 // TickSample captures the information collected for each sample.
495 class TickSample {
496  public:
TickSample()497   TickSample() : pc(0), sp(0), fp(0), state(OTHER), frames_count(0) {}
498   uintptr_t pc;  // Instruction pointer.
499   uintptr_t sp;  // Stack pointer.
500   uintptr_t fp;  // Frame pointer.
501   StateTag state;   // The state of the VM.
502   static const int kMaxFramesCount = 100;
503   EmbeddedVector<Address, kMaxFramesCount> stack;  // Call stack.
504   int frames_count;  // Number of captured frames.
505 };
506 
507 class Sampler {
508  public:
509   // Initialize sampler.
510   explicit Sampler(int interval, bool profiling);
511   virtual ~Sampler();
512 
513   // Performs stack sampling.
514   virtual void SampleStack(TickSample* sample) = 0;
515 
516   // This method is called for each sampling period with the current
517   // program counter.
518   virtual void Tick(TickSample* sample) = 0;
519 
520   // Start and stop sampler.
521   void Start();
522   void Stop();
523 
524   // Is the sampler used for profiling.
IsProfiling()525   inline bool IsProfiling() { return profiling_; }
526 
527   // Whether the sampler is running (that is, consumes resources).
IsActive()528   inline bool IsActive() { return active_; }
529 
530   class PlatformData;
531 
532  private:
533   const int interval_;
534   const bool profiling_;
535   bool active_;
536   PlatformData* data_;  // Platform specific data.
537   DISALLOW_IMPLICIT_CONSTRUCTORS(Sampler);
538 };
539 
540 #endif  // ENABLE_LOGGING_AND_PROFILING
541 
542 } }  // namespace v8::internal
543 
544 #endif  // V8_PLATFORM_H_
545