blob: cc44718fd052799077c20b82245cb58f2a2d4293 [file] [log] [blame]
ager@chromium.org9258b6b2008-09-11 09:11:10 +00001// Copyright 2006-2008 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002// 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 choosen 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#ifdef WIN32
48
49enum {
50 FP_NAN,
51 FP_INFINITE,
52 FP_ZERO,
53 FP_SUBNORMAL,
54 FP_NORMAL
55};
56
57#define INFINITY HUGE_VAL
58
59namespace v8 { namespace internal {
60int isfinite(double x);
61} }
62int isnan(double x);
63int isinf(double x);
64int isless(double x, double y);
65int isgreater(double x, double y);
66int fpclassify(double x);
67int signbit(double x);
68
69int random();
70
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000071int strncasecmp(const char* s1, const char* s2, int n);
72
73#else
74
75// Unfortunately, the INFINITY macro cannot be used with the '-pedantic'
76// warning flag and certain versions of GCC due to a bug:
77// http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11931
78// For now, we use the more involved template-based version from <limits>, but
79// only when compiling with GCC versions affected by the bug (2.96.x - 4.0.x)
80// __GNUC_PREREQ is not defined in GCC for Mac OS X, so we define our own macro
81#if defined(__GNUC__)
82#define __GNUC_VERSION__ (__GNUC__ * 10000 + __GNUC_MINOR__ * 100)
83#endif
84
85#if __GNUC_VERSION__ >= 29600 && __GNUC_VERSION__ < 40100
86#include <limits>
87#undef INFINITY
88#define INFINITY std::numeric_limits<double>::infinity()
89#endif
90
91#endif // WIN32
92
93namespace v8 { namespace internal {
94
95double ceiling(double x);
96
97// ----------------------------------------------------------------------------
98// OS
99//
100// This class has static methods for the different platform specific
101// functions. Add methods here to cope with differences between the
102// supported platforms.
103
104class OS {
105 public:
106 // Initializes the platform OS support. Called once at VM startup.
107 static void Setup();
108
109 // Returns the accumulated user time for thread. This routine
110 // can be used for profiling. The implementation should
111 // strive for high-precision timer resolution, preferable
112 // micro-second resolution.
113 static int GetUserTime(uint32_t* secs, uint32_t* usecs);
114
115 // Get a tick counter normalized to one tick per microsecond.
116 // Used for calculating time intervals.
117 static int64_t Ticks();
118
119 // Returns current time as the number of milliseconds since
120 // 00:00:00 UTC, January 1, 1970.
121 static double TimeCurrentMillis();
122
123 // Returns a string identifying the current time zone. The
124 // timestamp is used for determining if DST is in effect.
125 static char* LocalTimezone(double time);
126
127 // Returns the local time offset in milliseconds east of UTC without
128 // taking daylight savings time into account.
129 static double LocalTimeOffset();
130
131 // Returns the daylight savings offset for the given time.
132 static double DaylightSavingsOffset(double time);
133
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000134 static FILE* FOpen(const char* path, const char* mode);
135
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000136 // Print output to console. This is mostly used for debugging output.
137 // On platforms that has standard terminal output, the output
138 // should go to stdout.
139 static void Print(const char* format, ...);
140 static void VPrint(const char* format, va_list args);
141
142 // Print error output to console. This is mostly used for error message
143 // output. On platforms that has standard terminal output, the output
144 // should go to stderr.
145 static void PrintError(const char* format, ...);
146 static void VPrintError(const char* format, va_list args);
147
kasper.lund7276f142008-07-30 08:49:36 +0000148 // Allocate/Free memory used by JS heap. Pages are readable/writeable, but
149 // they are not guaranteed to be executable unless 'executable' is true.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000150 // Returns the address of allocated memory, or NULL if failed.
kasper.lund7276f142008-07-30 08:49:36 +0000151 static void* Allocate(const size_t requested,
152 size_t* allocated,
153 bool executable);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000154 static void Free(void* buf, const size_t length);
155 // Get the Alignment guaranteed by Allocate().
156 static size_t AllocateAlignment();
157
158 // Returns an indication of whether a pointer is in a space that
159 // has been allocated by Allocate(). This method may conservatively
160 // always return false, but giving more accurate information may
161 // improve the robustness of the stack dump code in the presence of
162 // heap corruption.
163 static bool IsOutsideAllocatedSpace(void* pointer);
164
165 // Sleep for a number of miliseconds.
166 static void Sleep(const int miliseconds);
167
168 // Abort the current process.
169 static void Abort();
170
kasper.lund7276f142008-07-30 08:49:36 +0000171 // Debug break.
172 static void DebugBreak();
173
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000174 // Walk the stack.
175 static const int kStackWalkError = -1;
176 static const int kStackWalkMaxNameLen = 256;
177 static const int kStackWalkMaxTextLen = 256;
178 struct StackFrame {
179 void* address;
180 char text[kStackWalkMaxTextLen];
181 };
182
183 static int StackWalk(StackFrame* frames, int frames_size);
184
185 // Factory method for creating platform dependent Mutex.
186 // Please use delete to reclaim the storage for the returned Mutex.
187 static Mutex* CreateMutex();
188
189 // Factory method for creating platform dependent Semaphore.
190 // Please use delete to reclaim the storage for the returned Semaphore.
191 static Semaphore* CreateSemaphore(int count);
192
193 class MemoryMappedFile {
194 public:
195 static MemoryMappedFile* create(const char* name, int size, void* initial);
196 virtual ~MemoryMappedFile() { }
197 virtual void* memory() = 0;
198 };
199
kasper.lund7276f142008-07-30 08:49:36 +0000200 // Safe formatting print. Ensures that str is always null-terminated.
201 // Returns the number of chars written, or -1 if output was truncated.
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000202 static int SNPrintF(Vector<char> str, const char* format, ...);
203 static int VSNPrintF(Vector<char> str,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000204 const char* format,
205 va_list args);
206
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000207 static void StrNCpy(Vector<char> dest, const char* src, size_t n);
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000208 static char* StrDup(const char* str);
209
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000210 // Support for profiler. Can do nothing, in which case ticks
211 // occuring in shared libraries will not be properly accounted
212 // for.
213 static void LogSharedLibraryAddresses();
214
215 // Returns the double constant NAN
216 static double nan_value();
217
ager@chromium.org236ad962008-09-25 09:45:57 +0000218 // Returns the activation frame alignment constraint or zero if
219 // the platform doesn't care. Guaranteed to be a power of two.
220 static int ActivationFrameAlignment();
221
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000222 private:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000223 static const int msPerSecond = 1000;
mads.s.ager31e71382008-08-13 09:32:07 +0000224
225 DISALLOW_IMPLICIT_CONSTRUCTORS(OS);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000226};
227
228
229class VirtualMemory {
230 public:
231 // Reserves virtual memory with size.
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000232 explicit VirtualMemory(size_t size);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000233 ~VirtualMemory();
234
235 // Returns whether the memory has been reserved.
236 bool IsReserved();
237
238 // Returns the start address of the reserved memory.
239 void* address() {
240 ASSERT(IsReserved());
241 return address_;
242 };
243
244 // Returns the size of the reserved memory.
245 size_t size() { return size_; }
246
247 // Commits real memory. Returns whether the operation succeeded.
kasper.lund7276f142008-07-30 08:49:36 +0000248 bool Commit(void* address, size_t size, bool executable);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000249
250 // Uncommit real memory. Returns whether the operation succeeded.
251 bool Uncommit(void* address, size_t size);
252
253 private:
254 void* address_; // Start address of the virtual memory.
255 size_t size_; // Size of the virtual memory.
256};
257
258
259// ----------------------------------------------------------------------------
260// ThreadHandle
261//
262// A ThreadHandle represents a thread identifier for a thread. The ThreadHandle
263// does not own the underlying os handle. Thread handles can be used for
264// refering to threads and testing equality.
265
266class ThreadHandle {
267 public:
268 enum Kind { SELF, INVALID };
269 explicit ThreadHandle(Kind kind);
270
271 // Destructor.
272 ~ThreadHandle();
273
274 // Test for thread running.
275 bool IsSelf() const;
276
277 // Test for valid thread handle.
278 bool IsValid() const;
279
280 // Get platform-specific data.
281 class PlatformData;
282 PlatformData* thread_handle_data() { return data_; }
283
284 // Initialize the handle to kind
285 void Initialize(Kind kind);
286
287 private:
288 PlatformData* data_; // Captures platform dependent data.
289};
290
291
292// ----------------------------------------------------------------------------
293// Thread
294//
295// Thread objects are used for creating and running threads. When the start()
296// method is called the new thread starts running the run() method in the new
297// thread. The Thread object should not be deallocated before the thread has
298// terminated.
299
300class Thread: public ThreadHandle {
301 public:
302 // Opaque data type for thread-local storage keys.
303 enum LocalStorageKey {};
304
305 // Create new thread.
306 Thread();
307 virtual ~Thread();
308
309 // Start new thread by calling the Run() method in the new thread.
310 void Start();
311
312 // Wait until thread terminates.
313 void Join();
314
315 // Abstract method for run handler.
316 virtual void Run() = 0;
317
318 // Thread-local storage.
319 static LocalStorageKey CreateThreadLocalKey();
320 static void DeleteThreadLocalKey(LocalStorageKey key);
321 static void* GetThreadLocal(LocalStorageKey key);
322 static void SetThreadLocal(LocalStorageKey key, void* value);
323
324 // A hint to the scheduler to let another thread run.
325 static void YieldCPU();
326
327 private:
328 class PlatformData;
329 PlatformData* data_;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000330 DISALLOW_COPY_AND_ASSIGN(Thread);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000331};
332
333
334// ----------------------------------------------------------------------------
335// Mutex
336//
337// Mutexes are used for serializing access to non-reentrant sections of code.
338// The implementations of mutex should allow for nested/recursive locking.
339
340class Mutex {
341 public:
342 virtual ~Mutex() {}
343
344 // Locks the given mutex. If the mutex is currently unlocked, it becomes
345 // locked and owned by the calling thread, and immediately. If the mutex
346 // is already locked by another thread, suspends the calling thread until
347 // the mutex is unlocked.
348 virtual int Lock() = 0;
349
350 // Unlocks the given mutex. The mutex is assumed to be locked and owned by
351 // the calling thread on entrance.
352 virtual int Unlock() = 0;
353};
354
355
356// ----------------------------------------------------------------------------
kasper.lund7276f142008-07-30 08:49:36 +0000357// ScopedLock
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000358//
kasper.lund7276f142008-07-30 08:49:36 +0000359// Stack-allocated ScopedLocks provide block-scoped locking and unlocking
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000360// of a mutex.
kasper.lund7276f142008-07-30 08:49:36 +0000361class ScopedLock {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000362 public:
kasper.lund7276f142008-07-30 08:49:36 +0000363 explicit ScopedLock(Mutex* mutex): mutex_(mutex) {
364 mutex_->Lock();
365 }
366 ~ScopedLock() {
367 mutex_->Unlock();
368 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000369
370 private:
kasper.lund7276f142008-07-30 08:49:36 +0000371 Mutex* mutex_;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000372 DISALLOW_COPY_AND_ASSIGN(ScopedLock);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000373};
374
375
376// ----------------------------------------------------------------------------
377// Semaphore
378//
379// A semaphore object is a synchronization object that maintains a count. The
380// count is decremented each time a thread completes a wait for the semaphore
381// object and incremented each time a thread signals the semaphore. When the
382// count reaches zero, threads waiting for the semaphore blocks until the
383// count becomes non-zero.
384
385class Semaphore {
386 public:
387 virtual ~Semaphore() {}
388
389 // Suspends the calling thread until the counter is non zero
390 // and then decrements the semaphore counter.
391 virtual void Wait() = 0;
392
393 // Increments the semaphore counter.
394 virtual void Signal() = 0;
395};
396
397
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000398#ifdef ENABLE_LOGGING_AND_PROFILING
399// ----------------------------------------------------------------------------
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000400// Sampler
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000401//
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000402// A sampler periodically samples the state of the VM and optionally
403// (if used for profiling) the program counter and stack pointer for
404// the thread that created it.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000405
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000406// TickSample captures the information collected for each sample.
407class TickSample {
408 public:
409 TickSample() : pc(0), sp(0), state(OTHER) {}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000410 unsigned int pc; // Instruction pointer.
411 unsigned int sp; // Stack pointer.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000412 StateTag state; // The state of the VM.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000413};
414
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000415class Sampler {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000416 public:
417 // Initialize sampler.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000418 explicit Sampler(int interval, bool profiling);
419 virtual ~Sampler();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000420
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000421 // This method is called for each sampling period with the current
422 // program counter.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000423 virtual void Tick(TickSample* sample) = 0;
424
425 // Start and stop sampler.
426 void Start();
427 void Stop();
428
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000429 // Is the sampler used for profiling.
430 inline bool IsProfiling() { return profiling_; }
431
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000432 class PlatformData;
433 protected:
434 inline bool IsActive() { return active_; }
435
436 private:
437 int interval_;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000438 bool profiling_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000439 bool active_;
440 PlatformData* data_; // Platform specific data.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000441 DISALLOW_IMPLICIT_CONSTRUCTORS(Sampler);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000442};
443
444#endif // ENABLE_LOGGING_AND_PROFILING
445
446} } // namespace v8::internal
447
448#endif // V8_PLATFORM_H_