Home | History | Annotate | Download | only in src
      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);
    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.
    291   void* address() {
    292     ASSERT(IsReserved());
    293     return address_;
    294   };
    295 
    296   // Returns the size of the reserved memory.
    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;
    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);
    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);
    378   static void SetThreadLocalInt(LocalStorageKey key, int value) {
    379     SetThreadLocal(key, reinterpret_cast<void*>(static_cast<intptr_t>(value)));
    380   }
    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:
    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:
    424   explicit ScopedLock(Mutex* mutex): mutex_(mutex) {
    425     mutex_->Lock();
    426   }
    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:
    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:
    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:
    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.
    550   inline bool IsProfiling() { return profiling_; }
    551 
    552   // Whether the sampler is running (that is, consumes resources).
    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