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