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