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