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