blob: e9e7c2236749b188c1ff2fb15dac2ec53fc15763 [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
Iain Merrick75681382010-08-19 15:07:18 +0100168 // Returns last OS error.
169 static int GetLastError();
170
Steve Blocka7e24c12009-10-30 11:49:00 +0000171 static FILE* FOpen(const char* path, const char* mode);
172
173 // Log file open mode is platform-dependent due to line ends issues.
174 static const char* LogFileOpenMode;
175
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);
181
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);
187
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,
192 size_t* allocated,
193 bool is_executable);
194 static void Free(void* address, const size_t size);
195 // Get the Alignment guaranteed by Allocate().
196 static size_t AllocateAlignment();
197
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);
202#endif
203
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
208 // heap corruption.
209 static bool IsOutsideAllocatedSpace(void* pointer);
210
211 // Sleep for a number of milliseconds.
212 static void Sleep(const int milliseconds);
213
214 // Abort the current process.
215 static void Abort();
216
217 // Debug break.
218 static void DebugBreak();
219
220 // Walk the stack.
221 static const int kStackWalkError = -1;
222 static const int kStackWalkMaxNameLen = 256;
223 static const int kStackWalkMaxTextLen = 256;
224 struct StackFrame {
225 void* address;
226 char text[kStackWalkMaxTextLen];
227 };
228
229 static int StackWalk(Vector<StackFrame> frames);
230
231 // Factory method for creating platform dependent Mutex.
232 // Please use delete to reclaim the storage for the returned Mutex.
233 static Mutex* CreateMutex();
234
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);
238
239 // Factory method for creating platform dependent Socket.
240 // Please use delete to reclaim the storage for the returned Socket.
241 static Socket* CreateSocket();
242
243 class MemoryMappedFile {
244 public:
245 static MemoryMappedFile* create(const char* name, int size, void* initial);
246 virtual ~MemoryMappedFile() { }
247 virtual void* memory() = 0;
248 };
249
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,
254 const char* format,
255 va_list args);
256
257 static char* StrChr(char* str, int c);
258 static void StrNCpy(Vector<char> dest, const char* src, size_t n);
259
260 // Support for profiler. Can do nothing, in which case ticks
261 // occuring in shared libraries will not be properly accounted
262 // for.
263 static void LogSharedLibraryAddresses();
264
Steve Blockd0582a62009-12-15 09:54:21 +0000265 // 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
267 // instructions.
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();
272
Steve Blocka7e24c12009-10-30 11:49:00 +0000273 // Returns the double constant NAN
274 static double nan_value();
275
Steve Blockd0582a62009-12-15 09:54:21 +0000276 // Support runtime detection of VFP3 on ARM CPUs.
277 static bool ArmCpuHasFeature(CpuFeature feature);
278
Steve Blocka7e24c12009-10-30 11:49:00 +0000279 // 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();
282
Leon Clarkef7060e22010-06-03 12:02:55 +0100283 static void ReleaseStore(volatile AtomicWord* ptr, AtomicWord value);
284
Steve Blocka7e24c12009-10-30 11:49:00 +0000285 private:
286 static const int msPerSecond = 1000;
287
288 DISALLOW_IMPLICIT_CONSTRUCTORS(OS);
289};
290
291
292class VirtualMemory {
293 public:
294 // Reserves virtual memory with size.
295 explicit VirtualMemory(size_t size);
296 ~VirtualMemory();
297
298 // Returns whether the memory has been reserved.
299 bool IsReserved();
300
301 // Returns the start address of the reserved memory.
302 void* address() {
303 ASSERT(IsReserved());
304 return address_;
Iain Merrick9ac36c92010-09-13 15:29:50 +0100305 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000306
307 // Returns the size of the reserved memory.
308 size_t size() { return size_; }
309
310 // Commits real memory. Returns whether the operation succeeded.
311 bool Commit(void* address, size_t size, bool is_executable);
312
313 // Uncommit real memory. Returns whether the operation succeeded.
314 bool Uncommit(void* address, size_t size);
315
316 private:
317 void* address_; // Start address of the virtual memory.
318 size_t size_; // Size of the virtual memory.
319};
320
321
322// ----------------------------------------------------------------------------
323// ThreadHandle
324//
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.
328
329class ThreadHandle {
330 public:
331 enum Kind { SELF, INVALID };
332 explicit ThreadHandle(Kind kind);
333
334 // Destructor.
335 ~ThreadHandle();
336
337 // Test for thread running.
338 bool IsSelf() const;
339
340 // Test for valid thread handle.
341 bool IsValid() const;
342
343 // Get platform-specific data.
344 class PlatformData;
345 PlatformData* thread_handle_data() { return data_; }
346
347 // Initialize the handle to kind
348 void Initialize(Kind kind);
349
350 private:
351 PlatformData* data_; // Captures platform dependent data.
352};
353
354
355// ----------------------------------------------------------------------------
356// Thread
357//
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
361// terminated.
362
363class Thread: public ThreadHandle {
364 public:
365 // Opaque data type for thread-local storage keys.
Iain Merrick75681382010-08-19 15:07:18 +0100366 // LOCAL_STORAGE_KEY_MIN_VALUE and LOCAL_STORAGE_KEY_MAX_VALUE are specified
367 // to ensure that enumeration type has correct value range (see Issue 830 for
368 // more details).
369 enum LocalStorageKey {
370 LOCAL_STORAGE_KEY_MIN_VALUE = kMinInt,
371 LOCAL_STORAGE_KEY_MAX_VALUE = kMaxInt
372 };
Steve Blocka7e24c12009-10-30 11:49:00 +0000373
374 // Create new thread.
375 Thread();
376 virtual ~Thread();
377
378 // Start new thread by calling the Run() method in the new thread.
379 void Start();
380
381 // Wait until thread terminates.
382 void Join();
383
384 // Abstract method for run handler.
385 virtual void Run() = 0;
386
387 // Thread-local storage.
388 static LocalStorageKey CreateThreadLocalKey();
389 static void DeleteThreadLocalKey(LocalStorageKey key);
390 static void* GetThreadLocal(LocalStorageKey key);
391 static int GetThreadLocalInt(LocalStorageKey key) {
392 return static_cast<int>(reinterpret_cast<intptr_t>(GetThreadLocal(key)));
393 }
394 static void SetThreadLocal(LocalStorageKey key, void* value);
395 static void SetThreadLocalInt(LocalStorageKey key, int value) {
396 SetThreadLocal(key, reinterpret_cast<void*>(static_cast<intptr_t>(value)));
397 }
398 static bool HasThreadLocal(LocalStorageKey key) {
399 return GetThreadLocal(key) != NULL;
400 }
401
402 // A hint to the scheduler to let another thread run.
403 static void YieldCPU();
404
405 private:
406 class PlatformData;
407 PlatformData* data_;
408 DISALLOW_COPY_AND_ASSIGN(Thread);
409};
410
411
412// ----------------------------------------------------------------------------
413// Mutex
414//
415// Mutexes are used for serializing access to non-reentrant sections of code.
416// The implementations of mutex should allow for nested/recursive locking.
417
418class Mutex {
419 public:
420 virtual ~Mutex() {}
421
422 // Locks the given mutex. If the mutex is currently unlocked, it becomes
423 // locked and owned by the calling thread, and immediately. If the mutex
424 // is already locked by another thread, suspends the calling thread until
425 // the mutex is unlocked.
426 virtual int Lock() = 0;
427
428 // Unlocks the given mutex. The mutex is assumed to be locked and owned by
429 // the calling thread on entrance.
430 virtual int Unlock() = 0;
431};
432
433
434// ----------------------------------------------------------------------------
435// ScopedLock
436//
437// Stack-allocated ScopedLocks provide block-scoped locking and unlocking
438// of a mutex.
439class ScopedLock {
440 public:
441 explicit ScopedLock(Mutex* mutex): mutex_(mutex) {
442 mutex_->Lock();
443 }
444 ~ScopedLock() {
445 mutex_->Unlock();
446 }
447
448 private:
449 Mutex* mutex_;
450 DISALLOW_COPY_AND_ASSIGN(ScopedLock);
451};
452
453
454// ----------------------------------------------------------------------------
455// Semaphore
456//
457// A semaphore object is a synchronization object that maintains a count. The
458// count is decremented each time a thread completes a wait for the semaphore
459// object and incremented each time a thread signals the semaphore. When the
460// count reaches zero, threads waiting for the semaphore blocks until the
461// count becomes non-zero.
462
463class Semaphore {
464 public:
465 virtual ~Semaphore() {}
466
467 // Suspends the calling thread until the semaphore counter is non zero
468 // and then decrements the semaphore counter.
469 virtual void Wait() = 0;
470
471 // Suspends the calling thread until the counter is non zero or the timeout
472 // time has passsed. If timeout happens the return value is false and the
473 // counter is unchanged. Otherwise the semaphore counter is decremented and
474 // true is returned. The timeout value is specified in microseconds.
475 virtual bool Wait(int timeout) = 0;
476
477 // Increments the semaphore counter.
478 virtual void Signal() = 0;
479};
480
481
482// ----------------------------------------------------------------------------
483// Socket
484//
485
486class Socket {
487 public:
488 virtual ~Socket() {}
489
490 // Server initialization.
491 virtual bool Bind(const int port) = 0;
492 virtual bool Listen(int backlog) const = 0;
493 virtual Socket* Accept() const = 0;
494
495 // Client initialization.
496 virtual bool Connect(const char* host, const char* port) = 0;
497
498 // Shutdown socket for both read and write. This causes blocking Send and
499 // Receive calls to exit. After Shutdown the Socket object cannot be used for
500 // any communication.
501 virtual bool Shutdown() = 0;
502
503 // Data Transimission
504 virtual int Send(const char* data, int len) const = 0;
505 virtual int Receive(char* data, int len) const = 0;
506
507 // Set the value of the SO_REUSEADDR socket option.
508 virtual bool SetReuseAddress(bool reuse_address) = 0;
509
510 virtual bool IsValid() const = 0;
511
512 static bool Setup();
513 static int LastError();
514 static uint16_t HToN(uint16_t value);
515 static uint16_t NToH(uint16_t value);
516 static uint32_t HToN(uint32_t value);
517 static uint32_t NToH(uint32_t value);
518};
519
520
Steve Blocka7e24c12009-10-30 11:49:00 +0000521// ----------------------------------------------------------------------------
522// Sampler
523//
524// A sampler periodically samples the state of the VM and optionally
525// (if used for profiling) the program counter and stack pointer for
526// the thread that created it.
527
528// TickSample captures the information collected for each sample.
529class TickSample {
530 public:
Leon Clarked91b9f72010-01-27 17:25:45 +0000531 TickSample()
Steve Block6ded16b2010-05-10 14:33:55 +0100532 : state(OTHER),
533 pc(NULL),
Leon Clarked91b9f72010-01-27 17:25:45 +0000534 sp(NULL),
535 fp(NULL),
536 function(NULL),
Leon Clarked91b9f72010-01-27 17:25:45 +0000537 frames_count(0) {}
Steve Block6ded16b2010-05-10 14:33:55 +0100538 StateTag state; // The state of the VM.
Leon Clarked91b9f72010-01-27 17:25:45 +0000539 Address pc; // Instruction pointer.
540 Address sp; // Stack pointer.
541 Address fp; // Frame pointer.
542 Address function; // The last called JS function.
Steve Block6ded16b2010-05-10 14:33:55 +0100543 static const int kMaxFramesCount = 64;
544 Address stack[kMaxFramesCount]; // Call stack.
Steve Blocka7e24c12009-10-30 11:49:00 +0000545 int frames_count; // Number of captured frames.
546};
547
Steve Block6ded16b2010-05-10 14:33:55 +0100548#ifdef ENABLE_LOGGING_AND_PROFILING
Steve Blocka7e24c12009-10-30 11:49:00 +0000549class Sampler {
550 public:
551 // Initialize sampler.
552 explicit Sampler(int interval, bool profiling);
553 virtual ~Sampler();
554
555 // Performs stack sampling.
556 virtual void SampleStack(TickSample* sample) = 0;
557
558 // This method is called for each sampling period with the current
559 // program counter.
560 virtual void Tick(TickSample* sample) = 0;
561
562 // Start and stop sampler.
563 void Start();
564 void Stop();
565
566 // Is the sampler used for profiling.
567 inline bool IsProfiling() { return profiling_; }
568
569 // Whether the sampler is running (that is, consumes resources).
570 inline bool IsActive() { return active_; }
571
572 class PlatformData;
573
574 private:
575 const int interval_;
576 const bool profiling_;
577 bool active_;
578 PlatformData* data_; // Platform specific data.
579 DISALLOW_IMPLICIT_CONSTRUCTORS(Sampler);
580};
581
582#endif // ENABLE_LOGGING_AND_PROFILING
583
584} } // namespace v8::internal
585
586#endif // V8_PLATFORM_H_