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
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.
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.
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.
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.
44
#ifndef V8_PLATFORM_H_
45
#define V8_PLATFORM_H_
47
#define V8_INFINITY INFINITY
49
// Windows specific stuff.
52
// Microsoft Visual C++ specific stuff.
64
#define V8_INFINITY HUGE_VAL
68
int isfinite(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);
77
int strncasecmp(const char* s1, const char* s2, int n);
81
// Random is missing on both Visual Studio and MinGW.
89
int signbit(double x);
97
// Needed for va_list on at least MinGW and Android.
100
#define __GNUC_VERSION__ (__GNUC__ * 10000 + __GNUC_MINOR__ * 100)
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
111
#define V8_INFINITY std::numeric_limits<double>::infinity()
119
// Use AtomicWord for a machine-sized pointer. It is assumed that
120
// reads and writes of naturally aligned values of this type are atomic.
121
typedef intptr_t AtomicWord;
125
double ceiling(double x);
126
double modulo(double x, double y);
128
// Forward declarations.
131
// ----------------------------------------------------------------------------
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.
140
// Initializes the platform OS support. Called once at VM startup.
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);
149
// Get a tick counter normalized to one tick per microsecond.
150
// Used for calculating time intervals.
151
static int64_t Ticks();
153
// Returns current time as the number of milliseconds since
154
// 00:00:00 UTC, January 1, 1970.
155
static double TimeCurrentMillis();
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);
161
// Returns the local time offset in milliseconds east of UTC without
162
// taking daylight savings time into account.
163
static double LocalTimeOffset();
165
// Returns the daylight savings offset for the given time.
166
static double DaylightSavingsOffset(double time);
168
// Returns last OS error.
169
static int GetLastError();
171
static FILE* FOpen(const char* path, const char* mode);
173
// Log file open mode is platform-dependent due to line ends issues.
174
static const char* LogFileOpenMode;
176
// Print output to console. This is mostly used for debugging output.
177
// On platforms that has standard terminal output, the output
178
// should go to stdout.
179
static void Print(const char* format, ...);
180
static void VPrint(const char* format, va_list args);
182
// Print error output to console. This is mostly used for error message
183
// output. On platforms that has standard terminal output, the output
184
// should go to stderr.
185
static void PrintError(const char* format, ...);
186
static void VPrintError(const char* format, va_list args);
188
// Allocate/Free memory used by JS heap. Pages are readable/writable, but
189
// they are not guaranteed to be executable unless 'executable' is true.
190
// Returns the address of allocated memory, or NULL if failed.
191
static void* Allocate(const size_t requested,
194
static void Free(void* address, const size_t size);
195
// Get the Alignment guaranteed by Allocate().
196
static size_t AllocateAlignment();
198
#ifdef ENABLE_HEAP_PROTECTION
199
// Protect/unprotect a block of memory by marking it read-only/writable.
200
static void Protect(void* address, size_t size);
201
static void Unprotect(void* address, size_t size, bool is_executable);
204
// Returns an indication of whether a pointer is in a space that
205
// has been allocated by Allocate(). This method may conservatively
206
// always return false, but giving more accurate information may
207
// improve the robustness of the stack dump code in the presence of
209
static bool IsOutsideAllocatedSpace(void* pointer);
211
// Sleep for a number of milliseconds.
212
static void Sleep(const int milliseconds);
214
// Abort the current process.
218
static void DebugBreak();
221
static const int kStackWalkError = -1;
222
static const int kStackWalkMaxNameLen = 256;
223
static const int kStackWalkMaxTextLen = 256;
226
char text[kStackWalkMaxTextLen];
229
static int StackWalk(Vector<StackFrame> frames);
231
// Factory method for creating platform dependent Mutex.
232
// Please use delete to reclaim the storage for the returned Mutex.
233
static Mutex* CreateMutex();
235
// Factory method for creating platform dependent Semaphore.
236
// Please use delete to reclaim the storage for the returned Semaphore.
237
static Semaphore* CreateSemaphore(int count);
239
// Factory method for creating platform dependent Socket.
240
// Please use delete to reclaim the storage for the returned Socket.
241
static Socket* CreateSocket();
243
class MemoryMappedFile {
245
static MemoryMappedFile* create(const char* name, int size, void* initial);
246
virtual ~MemoryMappedFile() { }
247
virtual void* memory() = 0;
250
// Safe formatting print. Ensures that str is always null-terminated.
251
// Returns the number of chars written, or -1 if output was truncated.
252
static int SNPrintF(Vector<char> str, const char* format, ...);
253
static int VSNPrintF(Vector<char> str,
257
static char* StrChr(char* str, int c);
258
static void StrNCpy(Vector<char> dest, const char* src, size_t n);
260
// Support for profiler. Can do nothing, in which case ticks
261
// occuring in shared libraries will not be properly accounted
263
static void LogSharedLibraryAddresses();
265
// The return value indicates the CPU features we are sure of because of the
266
// OS. For example MacOSX doesn't run on any x86 CPUs that don't have SSE2
268
// This is a little messy because the interpretation is subject to the cross
269
// of the CPU and the OS. The bits in the answer correspond to the bit
270
// positions indicated by the members of the CpuFeature enum from globals.h
271
static uint64_t CpuFeaturesImpliedByPlatform();
273
// Returns the double constant NAN
274
static double nan_value();
276
// Support runtime detection of VFP3 on ARM CPUs.
277
static bool ArmCpuHasFeature(CpuFeature feature);
279
// Returns the activation frame alignment constraint or zero if
280
// the platform doesn't care. Guaranteed to be a power of two.
281
static int ActivationFrameAlignment();
283
static void ReleaseStore(volatile AtomicWord* ptr, AtomicWord value);
286
static const int msPerSecond = 1000;
288
DISALLOW_IMPLICIT_CONSTRUCTORS(OS);
292
class VirtualMemory {
294
// Reserves virtual memory with size.
295
explicit VirtualMemory(size_t size);
298
// Returns whether the memory has been reserved.
301
// Returns the start address of the reserved memory.
303
ASSERT(IsReserved());
307
// Returns the size of the reserved memory.
308
size_t size() { return size_; }
310
// Commits real memory. Returns whether the operation succeeded.
311
bool Commit(void* address, size_t size, bool is_executable);
313
// Uncommit real memory. Returns whether the operation succeeded.
314
bool Uncommit(void* address, size_t size);
317
void* address_; // Start address of the virtual memory.
318
size_t size_; // Size of the virtual memory.
322
// ----------------------------------------------------------------------------
325
// A ThreadHandle represents a thread identifier for a thread. The ThreadHandle
326
// does not own the underlying os handle. Thread handles can be used for
327
// refering to threads and testing equality.
331
enum Kind { SELF, INVALID };
332
explicit ThreadHandle(Kind kind);
337
// Test for thread running.
340
// Test for valid thread handle.
341
bool IsValid() const;
343
// Get platform-specific data.
345
PlatformData* thread_handle_data() { return data_; }
347
// Initialize the handle to kind
348
void Initialize(Kind kind);
351
PlatformData* data_; // Captures platform dependent data.
355
// ----------------------------------------------------------------------------
358
// Thread objects are used for creating and running threads. When the start()
359
// method is called the new thread starts running the run() method in the new
360
// thread. The Thread object should not be deallocated before the thread has
363
class Thread: public ThreadHandle {
365
// Opaque data type for thread-local storage keys.
366
enum LocalStorageKey {};
368
// Create new thread.
372
// Start new thread by calling the Run() method in the new thread.
375
// Wait until thread terminates.
378
// Abstract method for run handler.
379
virtual void Run() = 0;
381
// Thread-local storage.
382
static LocalStorageKey CreateThreadLocalKey();
383
static void DeleteThreadLocalKey(LocalStorageKey key);
384
static void* GetThreadLocal(LocalStorageKey key);
385
static int GetThreadLocalInt(LocalStorageKey key) {
386
return static_cast<int>(reinterpret_cast<intptr_t>(GetThreadLocal(key)));
388
static void SetThreadLocal(LocalStorageKey key, void* value);
389
static void SetThreadLocalInt(LocalStorageKey key, int value) {
390
SetThreadLocal(key, reinterpret_cast<void*>(static_cast<intptr_t>(value)));
392
static bool HasThreadLocal(LocalStorageKey key) {
393
return GetThreadLocal(key) != NULL;
396
// A hint to the scheduler to let another thread run.
397
static void YieldCPU();
402
DISALLOW_COPY_AND_ASSIGN(Thread);
406
// ----------------------------------------------------------------------------
409
// Mutexes are used for serializing access to non-reentrant sections of code.
410
// The implementations of mutex should allow for nested/recursive locking.
416
// Locks the given mutex. If the mutex is currently unlocked, it becomes
417
// locked and owned by the calling thread, and immediately. If the mutex
418
// is already locked by another thread, suspends the calling thread until
419
// the mutex is unlocked.
420
virtual int Lock() = 0;
422
// Unlocks the given mutex. The mutex is assumed to be locked and owned by
423
// the calling thread on entrance.
424
virtual int Unlock() = 0;
428
// ----------------------------------------------------------------------------
431
// Stack-allocated ScopedLocks provide block-scoped locking and unlocking
435
explicit ScopedLock(Mutex* mutex): mutex_(mutex) {
444
DISALLOW_COPY_AND_ASSIGN(ScopedLock);
448
// ----------------------------------------------------------------------------
451
// A semaphore object is a synchronization object that maintains a count. The
452
// count is decremented each time a thread completes a wait for the semaphore
453
// object and incremented each time a thread signals the semaphore. When the
454
// count reaches zero, threads waiting for the semaphore blocks until the
455
// count becomes non-zero.
459
virtual ~Semaphore() {}
461
// Suspends the calling thread until the semaphore counter is non zero
462
// and then decrements the semaphore counter.
463
virtual void Wait() = 0;
465
// Suspends the calling thread until the counter is non zero or the timeout
466
// time has passsed. If timeout happens the return value is false and the
467
// counter is unchanged. Otherwise the semaphore counter is decremented and
468
// true is returned. The timeout value is specified in microseconds.
469
virtual bool Wait(int timeout) = 0;
471
// Increments the semaphore counter.
472
virtual void Signal() = 0;
476
// ----------------------------------------------------------------------------
484
// Server initialization.
485
virtual bool Bind(const int port) = 0;
486
virtual bool Listen(int backlog) const = 0;
487
virtual Socket* Accept() const = 0;
489
// Client initialization.
490
virtual bool Connect(const char* host, const char* port) = 0;
492
// Shutdown socket for both read and write. This causes blocking Send and
493
// Receive calls to exit. After Shutdown the Socket object cannot be used for
494
// any communication.
495
virtual bool Shutdown() = 0;
497
// Data Transimission
498
virtual int Send(const char* data, int len) const = 0;
499
virtual int Receive(char* data, int len) const = 0;
501
// Set the value of the SO_REUSEADDR socket option.
502
virtual bool SetReuseAddress(bool reuse_address) = 0;
504
virtual bool IsValid() const = 0;
507
static int LastError();
508
static uint16_t HToN(uint16_t value);
509
static uint16_t NToH(uint16_t value);
510
static uint32_t HToN(uint32_t value);
511
static uint32_t NToH(uint32_t value);
515
// ----------------------------------------------------------------------------
518
// A sampler periodically samples the state of the VM and optionally
519
// (if used for profiling) the program counter and stack pointer for
520
// the thread that created it.
522
// TickSample captures the information collected for each sample.
532
StateTag state; // The state of the VM.
533
Address pc; // Instruction pointer.
534
Address sp; // Stack pointer.
535
Address fp; // Frame pointer.
536
Address function; // The last called JS function.
537
static const int kMaxFramesCount = 64;
538
Address stack[kMaxFramesCount]; // Call stack.
539
int frames_count; // Number of captured frames.
542
#ifdef ENABLE_LOGGING_AND_PROFILING
545
// Initialize sampler.
546
explicit Sampler(int interval, bool profiling);
549
// Performs stack sampling.
550
virtual void SampleStack(TickSample* sample) = 0;
552
// This method is called for each sampling period with the current
554
virtual void Tick(TickSample* sample) = 0;
556
// Start and stop sampler.
560
// Is the sampler used for profiling.
561
inline bool IsProfiling() { return profiling_; }
563
// Whether the sampler is running (that is, consumes resources).
564
inline bool IsActive() { return active_; }
570
const bool profiling_;
572
PlatformData* data_; // Platform specific data.
573
DISALLOW_IMPLICIT_CONSTRUCTORS(Sampler);
576
#endif // ENABLE_LOGGING_AND_PROFILING
578
} } // namespace v8::internal
580
#endif // V8_PLATFORM_H_