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