blob: 726f9ca0a0ee3de6a9741747343aa90e6cee8fe1 [file] [log] [blame]
Ben Murdoch8b112d22011-06-08 16:22:53 +01001// Copyright 2011 the V8 project authors. All rights reserved.
Steve Blocka7e24c12009-10-30 11:49:00 +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 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
Leon Clarkef7060e22010-06-03 12:02:55 +010047#ifdef __sun
48# ifndef signbit
49int signbit(double x);
50# endif
51#endif
52
Steve Blocka7e24c12009-10-30 11:49:00 +000053// GCC specific stuff
54#ifdef __GNUC__
55
56// Needed for va_list on at least MinGW and Android.
57#include <stdarg.h>
58
59#define __GNUC_VERSION__ (__GNUC__ * 10000 + __GNUC_MINOR__ * 100)
60
Steve Blocka7e24c12009-10-30 11:49:00 +000061#endif // __GNUC__
62
Ben Murdoch589d6972011-11-30 16:04:58 +000063
64// Windows specific stuff.
65#ifdef WIN32
66
67// Microsoft Visual C++ specific stuff.
68#ifdef _MSC_VER
69
70#include "win32-math.h"
71
72int strncasecmp(const char* s1, const char* s2, int n);
73
74#endif // _MSC_VER
75
76// Random is missing on both Visual Studio and MinGW.
77int random();
78
79#endif // WIN32
80
Ben Murdochb0fe1622011-05-05 13:52:32 +010081#include "atomicops.h"
Steve Block44f0eee2011-05-26 01:26:41 +010082#include "platform-tls.h"
Ben Murdochb0fe1622011-05-05 13:52:32 +010083#include "utils.h"
84#include "v8globals.h"
85
Steve Blocka7e24c12009-10-30 11:49:00 +000086namespace v8 {
87namespace internal {
88
Steve Block6ded16b2010-05-10 14:33:55 +010089// Use AtomicWord for a machine-sized pointer. It is assumed that
90// reads and writes of naturally aligned values of this type are atomic.
91typedef intptr_t AtomicWord;
92
Steve Blocka7e24c12009-10-30 11:49:00 +000093class Semaphore;
Ben Murdochb0fe1622011-05-05 13:52:32 +010094class Mutex;
Steve Blocka7e24c12009-10-30 11:49:00 +000095
96double ceiling(double x);
Steve Block3ce2e202009-11-05 08:53:23 +000097double modulo(double x, double y);
Steve Blocka7e24c12009-10-30 11:49:00 +000098
99// Forward declarations.
100class Socket;
101
102// ----------------------------------------------------------------------------
103// OS
104//
105// This class has static methods for the different platform specific
106// functions. Add methods here to cope with differences between the
107// supported platforms.
108
109class OS {
110 public:
111 // Initializes the platform OS support. Called once at VM startup.
112 static void Setup();
113
114 // Returns the accumulated user time for thread. This routine
115 // can be used for profiling. The implementation should
116 // strive for high-precision timer resolution, preferable
117 // micro-second resolution.
118 static int GetUserTime(uint32_t* secs, uint32_t* usecs);
119
120 // Get a tick counter normalized to one tick per microsecond.
121 // Used for calculating time intervals.
122 static int64_t Ticks();
123
124 // Returns current time as the number of milliseconds since
125 // 00:00:00 UTC, January 1, 1970.
126 static double TimeCurrentMillis();
127
128 // Returns a string identifying the current time zone. The
129 // timestamp is used for determining if DST is in effect.
130 static const char* LocalTimezone(double time);
131
132 // Returns the local time offset in milliseconds east of UTC without
133 // taking daylight savings time into account.
134 static double LocalTimeOffset();
135
136 // Returns the daylight savings offset for the given time.
137 static double DaylightSavingsOffset(double time);
138
Iain Merrick75681382010-08-19 15:07:18 +0100139 // Returns last OS error.
140 static int GetLastError();
141
Steve Blocka7e24c12009-10-30 11:49:00 +0000142 static FILE* FOpen(const char* path, const char* mode);
Steve Block1e0659c2011-05-24 12:43:12 +0100143 static bool Remove(const char* path);
Steve Blocka7e24c12009-10-30 11:49:00 +0000144
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000145 // Opens a temporary file, the file is auto removed on close.
146 static FILE* OpenTemporaryFile();
147
Steve Blocka7e24c12009-10-30 11:49:00 +0000148 // Log file open mode is platform-dependent due to line ends issues.
Steve Block44f0eee2011-05-26 01:26:41 +0100149 static const char* const LogFileOpenMode;
Steve Blocka7e24c12009-10-30 11:49:00 +0000150
151 // Print output to console. This is mostly used for debugging output.
152 // On platforms that has standard terminal output, the output
153 // should go to stdout.
154 static void Print(const char* format, ...);
155 static void VPrint(const char* format, va_list args);
156
Ben Murdochb0fe1622011-05-05 13:52:32 +0100157 // Print output to a file. This is mostly used for debugging output.
158 static void FPrint(FILE* out, const char* format, ...);
159 static void VFPrint(FILE* out, const char* format, va_list args);
160
Steve Blocka7e24c12009-10-30 11:49:00 +0000161 // Print error output to console. This is mostly used for error message
162 // output. On platforms that has standard terminal output, the output
163 // should go to stderr.
164 static void PrintError(const char* format, ...);
165 static void VPrintError(const char* format, va_list args);
166
167 // Allocate/Free memory used by JS heap. Pages are readable/writable, but
168 // they are not guaranteed to be executable unless 'executable' is true.
169 // Returns the address of allocated memory, or NULL if failed.
170 static void* Allocate(const size_t requested,
171 size_t* allocated,
172 bool is_executable);
173 static void Free(void* address, const size_t size);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000174
175 // Mark code segments non-writable.
176 static void ProtectCode(void* address, const size_t size);
177
178 // Assign memory as a guard page so that access will cause an exception.
179 static void Guard(void* address, const size_t size);
180
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000181 // Generate a random address to be used for hinting mmap().
182 static void* GetRandomMmapAddr();
183
Steve Blocka7e24c12009-10-30 11:49:00 +0000184 // Get the Alignment guaranteed by Allocate().
185 static size_t AllocateAlignment();
186
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000187 static intptr_t CommitPageSize();
188
Steve Blocka7e24c12009-10-30 11:49:00 +0000189 // 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:
Steve Block1e0659c2011-05-24 12:43:12 +0100230 static MemoryMappedFile* open(const char* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000231 static MemoryMappedFile* create(const char* name, int size, void* initial);
232 virtual ~MemoryMappedFile() { }
233 virtual void* memory() = 0;
Steve Block1e0659c2011-05-24 12:43:12 +0100234 virtual int size() = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000235 };
236
237 // Safe formatting print. Ensures that str is always null-terminated.
238 // Returns the number of chars written, or -1 if output was truncated.
239 static int SNPrintF(Vector<char> str, const char* format, ...);
240 static int VSNPrintF(Vector<char> str,
241 const char* format,
242 va_list args);
243
244 static char* StrChr(char* str, int c);
245 static void StrNCpy(Vector<char> dest, const char* src, size_t n);
246
Ben Murdochf87a2032010-10-22 12:50:53 +0100247 // Support for the profiler. Can do nothing, in which case ticks
248 // occuring in shared libraries will not be properly accounted for.
Steve Blocka7e24c12009-10-30 11:49:00 +0000249 static void LogSharedLibraryAddresses();
250
Ben Murdochf87a2032010-10-22 12:50:53 +0100251 // Support for the profiler. Notifies the external profiling
252 // process that a code moving garbage collection starts. Can do
253 // nothing, in which case the code objects must not move (e.g., by
254 // using --never-compact) if accurate profiling is desired.
255 static void SignalCodeMovingGC();
256
Steve Blockd0582a62009-12-15 09:54:21 +0000257 // The return value indicates the CPU features we are sure of because of the
258 // OS. For example MacOSX doesn't run on any x86 CPUs that don't have SSE2
259 // instructions.
260 // This is a little messy because the interpretation is subject to the cross
261 // of the CPU and the OS. The bits in the answer correspond to the bit
262 // positions indicated by the members of the CpuFeature enum from globals.h
263 static uint64_t CpuFeaturesImpliedByPlatform();
264
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000265 // Maximum size of the virtual memory. 0 means there is no artificial
266 // limit.
267 static intptr_t MaxVirtualMemory();
268
Steve Blocka7e24c12009-10-30 11:49:00 +0000269 // Returns the double constant NAN
270 static double nan_value();
271
Steve Blockd0582a62009-12-15 09:54:21 +0000272 // Support runtime detection of VFP3 on ARM CPUs.
273 static bool ArmCpuHasFeature(CpuFeature feature);
274
Ben Murdoch257744e2011-11-30 15:57:28 +0000275 // Support runtime detection of whether the hard float option of the
276 // EABI is used.
277 static bool ArmUsingHardFloat();
278
Steve Block44f0eee2011-05-26 01:26:41 +0100279 // Support runtime detection of FPU on MIPS CPUs.
280 static bool MipsCpuHasFeature(CpuFeature feature);
281
Steve Blocka7e24c12009-10-30 11:49:00 +0000282 // Returns the activation frame alignment constraint or zero if
283 // the platform doesn't care. Guaranteed to be a power of two.
284 static int ActivationFrameAlignment();
285
Leon Clarkef7060e22010-06-03 12:02:55 +0100286 static void ReleaseStore(volatile AtomicWord* ptr, AtomicWord value);
287
Ben Murdoch8b112d22011-06-08 16:22:53 +0100288#if defined(V8_TARGET_ARCH_IA32)
289 // Copy memory area to disjoint memory area.
290 static void MemCopy(void* dest, const void* src, size_t size);
291 // Limit below which the extra overhead of the MemCopy function is likely
292 // to outweigh the benefits of faster copying.
293 static const int kMinComplexMemCopy = 64;
294 typedef void (*MemCopyFunction)(void* dest, const void* src, size_t size);
295
296#else // V8_TARGET_ARCH_IA32
297 static void MemCopy(void* dest, const void* src, size_t size) {
298 memcpy(dest, src, size);
299 }
300 static const int kMinComplexMemCopy = 256;
301#endif // V8_TARGET_ARCH_IA32
302
Steve Blocka7e24c12009-10-30 11:49:00 +0000303 private:
304 static const int msPerSecond = 1000;
305
306 DISALLOW_IMPLICIT_CONSTRUCTORS(OS);
307};
308
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000309// Represents and controls an area of reserved memory.
310// Control of the reserved memory can be assigned to another VirtualMemory
311// object by assignment or copy-contructing. This removes the reserved memory
312// from the original object.
Steve Blocka7e24c12009-10-30 11:49:00 +0000313class VirtualMemory {
314 public:
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000315 // Empty VirtualMemory object, controlling no reserved memory.
316 VirtualMemory();
317
Steve Blocka7e24c12009-10-30 11:49:00 +0000318 // Reserves virtual memory with size.
319 explicit VirtualMemory(size_t size);
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000320
321 // Reserves virtual memory containing an area of the given size that
322 // is aligned per alignment. This may not be at the position returned
323 // by address().
324 VirtualMemory(size_t size, size_t alignment);
325
326 // Releases the reserved memory, if any, controlled by this VirtualMemory
327 // object.
Steve Blocka7e24c12009-10-30 11:49:00 +0000328 ~VirtualMemory();
329
330 // Returns whether the memory has been reserved.
331 bool IsReserved();
332
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000333 // Initialize or resets an embedded VirtualMemory object.
334 void Reset();
335
Steve Blocka7e24c12009-10-30 11:49:00 +0000336 // Returns the start address of the reserved memory.
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000337 // If the memory was reserved with an alignment, this address is not
338 // necessarily aligned. The user might need to round it up to a multiple of
339 // the alignment to get the start of the aligned block.
Steve Blocka7e24c12009-10-30 11:49:00 +0000340 void* address() {
341 ASSERT(IsReserved());
342 return address_;
Iain Merrick9ac36c92010-09-13 15:29:50 +0100343 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000344
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000345 // Returns the size of the reserved memory. The returned value is only
346 // meaningful when IsReserved() returns true.
347 // If the memory was reserved with an alignment, this size may be larger
348 // than the requested size.
Steve Blocka7e24c12009-10-30 11:49:00 +0000349 size_t size() { return size_; }
350
351 // Commits real memory. Returns whether the operation succeeded.
352 bool Commit(void* address, size_t size, bool is_executable);
353
354 // Uncommit real memory. Returns whether the operation succeeded.
355 bool Uncommit(void* address, size_t size);
356
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000357 // Creates a single guard page at the given address.
358 bool Guard(void* address);
359
360 void Release() {
361 ASSERT(IsReserved());
362 // Notice: Order is important here. The VirtualMemory object might live
363 // inside the allocated region.
364 void* address = address_;
365 size_t size = size_;
366 Reset();
367 bool result = ReleaseRegion(address, size);
368 USE(result);
369 ASSERT(result);
370 }
371
372 // Assign control of the reserved region to a different VirtualMemory object.
373 // The old object is no longer functional (IsReserved() returns false).
374 void TakeControl(VirtualMemory* from) {
375 ASSERT(!IsReserved());
376 address_ = from->address_;
377 size_ = from->size_;
378 from->Reset();
379 }
380
381 static void* ReserveRegion(size_t size);
382
383 static bool CommitRegion(void* base, size_t size, bool is_executable);
384
385 static bool UncommitRegion(void* base, size_t size);
386
387 // Must be called with a base pointer that has been returned by ReserveRegion
388 // and the same size it was reserved with.
389 static bool ReleaseRegion(void* base, size_t size);
390
Steve Blocka7e24c12009-10-30 11:49:00 +0000391 private:
392 void* address_; // Start address of the virtual memory.
393 size_t size_; // Size of the virtual memory.
394};
395
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000396
Steve Blocka7e24c12009-10-30 11:49:00 +0000397// ----------------------------------------------------------------------------
398// Thread
399//
400// Thread objects are used for creating and running threads. When the start()
401// method is called the new thread starts running the run() method in the new
402// thread. The Thread object should not be deallocated before the thread has
403// terminated.
404
Ben Murdoch8b112d22011-06-08 16:22:53 +0100405class Thread {
Steve Blocka7e24c12009-10-30 11:49:00 +0000406 public:
407 // Opaque data type for thread-local storage keys.
Iain Merrick75681382010-08-19 15:07:18 +0100408 // LOCAL_STORAGE_KEY_MIN_VALUE and LOCAL_STORAGE_KEY_MAX_VALUE are specified
409 // to ensure that enumeration type has correct value range (see Issue 830 for
410 // more details).
411 enum LocalStorageKey {
412 LOCAL_STORAGE_KEY_MIN_VALUE = kMinInt,
413 LOCAL_STORAGE_KEY_MAX_VALUE = kMaxInt
414 };
Steve Blocka7e24c12009-10-30 11:49:00 +0000415
Steve Block44f0eee2011-05-26 01:26:41 +0100416 struct Options {
417 Options() : name("v8:<unknown>"), stack_size(0) {}
418
419 const char* name;
420 int stack_size;
421 };
422
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000423 // Create new thread.
424 explicit Thread(const Options& options);
425 explicit Thread(const char* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000426 virtual ~Thread();
427
428 // Start new thread by calling the Run() method in the new thread.
429 void Start();
430
431 // Wait until thread terminates.
432 void Join();
433
Steve Block9fac8402011-05-12 15:51:54 +0100434 inline const char* name() const {
435 return name_;
436 }
437
Steve Blocka7e24c12009-10-30 11:49:00 +0000438 // Abstract method for run handler.
439 virtual void Run() = 0;
440
441 // Thread-local storage.
442 static LocalStorageKey CreateThreadLocalKey();
443 static void DeleteThreadLocalKey(LocalStorageKey key);
444 static void* GetThreadLocal(LocalStorageKey key);
445 static int GetThreadLocalInt(LocalStorageKey key) {
446 return static_cast<int>(reinterpret_cast<intptr_t>(GetThreadLocal(key)));
447 }
448 static void SetThreadLocal(LocalStorageKey key, void* value);
449 static void SetThreadLocalInt(LocalStorageKey key, int value) {
450 SetThreadLocal(key, reinterpret_cast<void*>(static_cast<intptr_t>(value)));
451 }
452 static bool HasThreadLocal(LocalStorageKey key) {
453 return GetThreadLocal(key) != NULL;
454 }
455
Steve Block44f0eee2011-05-26 01:26:41 +0100456#ifdef V8_FAST_TLS_SUPPORTED
457 static inline void* GetExistingThreadLocal(LocalStorageKey key) {
458 void* result = reinterpret_cast<void*>(
459 InternalGetExistingThreadLocal(static_cast<intptr_t>(key)));
460 ASSERT(result == GetThreadLocal(key));
461 return result;
462 }
463#else
464 static inline void* GetExistingThreadLocal(LocalStorageKey key) {
465 return GetThreadLocal(key);
466 }
467#endif
468
Steve Blocka7e24c12009-10-30 11:49:00 +0000469 // A hint to the scheduler to let another thread run.
470 static void YieldCPU();
471
Steve Block44f0eee2011-05-26 01:26:41 +0100472
Steve Block9fac8402011-05-12 15:51:54 +0100473 // The thread name length is limited to 16 based on Linux's implementation of
474 // prctl().
475 static const int kMaxThreadNameLength = 16;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100476
477 class PlatformData;
478 PlatformData* data() { return data_; }
479
Steve Blocka7e24c12009-10-30 11:49:00 +0000480 private:
Steve Block9fac8402011-05-12 15:51:54 +0100481 void set_name(const char *name);
482
Steve Blocka7e24c12009-10-30 11:49:00 +0000483 PlatformData* data_;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100484
Steve Block9fac8402011-05-12 15:51:54 +0100485 char name_[kMaxThreadNameLength];
Steve Block44f0eee2011-05-26 01:26:41 +0100486 int stack_size_;
Steve Block9fac8402011-05-12 15:51:54 +0100487
Steve Blocka7e24c12009-10-30 11:49:00 +0000488 DISALLOW_COPY_AND_ASSIGN(Thread);
489};
490
491
492// ----------------------------------------------------------------------------
493// Mutex
494//
495// Mutexes are used for serializing access to non-reentrant sections of code.
496// The implementations of mutex should allow for nested/recursive locking.
497
498class Mutex {
499 public:
500 virtual ~Mutex() {}
501
502 // Locks the given mutex. If the mutex is currently unlocked, it becomes
503 // locked and owned by the calling thread, and immediately. If the mutex
504 // is already locked by another thread, suspends the calling thread until
505 // the mutex is unlocked.
506 virtual int Lock() = 0;
507
508 // Unlocks the given mutex. The mutex is assumed to be locked and owned by
509 // the calling thread on entrance.
510 virtual int Unlock() = 0;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100511
512 // Tries to lock the given mutex. Returns whether the mutex was
513 // successfully locked.
514 virtual bool TryLock() = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000515};
516
517
518// ----------------------------------------------------------------------------
Ben Murdoch8b112d22011-06-08 16:22:53 +0100519// ScopedLock
Steve Blocka7e24c12009-10-30 11:49:00 +0000520//
Ben Murdoch8b112d22011-06-08 16:22:53 +0100521// Stack-allocated ScopedLocks provide block-scoped locking and
522// unlocking of a mutex.
Steve Blocka7e24c12009-10-30 11:49:00 +0000523class ScopedLock {
524 public:
525 explicit ScopedLock(Mutex* mutex): mutex_(mutex) {
Steve Block44f0eee2011-05-26 01:26:41 +0100526 ASSERT(mutex_ != NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000527 mutex_->Lock();
528 }
529 ~ScopedLock() {
530 mutex_->Unlock();
531 }
532
533 private:
534 Mutex* mutex_;
535 DISALLOW_COPY_AND_ASSIGN(ScopedLock);
536};
537
538
539// ----------------------------------------------------------------------------
540// Semaphore
541//
542// A semaphore object is a synchronization object that maintains a count. The
543// count is decremented each time a thread completes a wait for the semaphore
544// object and incremented each time a thread signals the semaphore. When the
545// count reaches zero, threads waiting for the semaphore blocks until the
546// count becomes non-zero.
547
548class Semaphore {
549 public:
550 virtual ~Semaphore() {}
551
552 // Suspends the calling thread until the semaphore counter is non zero
553 // and then decrements the semaphore counter.
554 virtual void Wait() = 0;
555
556 // Suspends the calling thread until the counter is non zero or the timeout
557 // time has passsed. If timeout happens the return value is false and the
558 // counter is unchanged. Otherwise the semaphore counter is decremented and
559 // true is returned. The timeout value is specified in microseconds.
560 virtual bool Wait(int timeout) = 0;
561
562 // Increments the semaphore counter.
563 virtual void Signal() = 0;
564};
565
566
567// ----------------------------------------------------------------------------
568// Socket
569//
570
571class Socket {
572 public:
573 virtual ~Socket() {}
574
575 // Server initialization.
576 virtual bool Bind(const int port) = 0;
577 virtual bool Listen(int backlog) const = 0;
578 virtual Socket* Accept() const = 0;
579
580 // Client initialization.
581 virtual bool Connect(const char* host, const char* port) = 0;
582
583 // Shutdown socket for both read and write. This causes blocking Send and
584 // Receive calls to exit. After Shutdown the Socket object cannot be used for
585 // any communication.
586 virtual bool Shutdown() = 0;
587
588 // Data Transimission
589 virtual int Send(const char* data, int len) const = 0;
590 virtual int Receive(char* data, int len) const = 0;
591
592 // Set the value of the SO_REUSEADDR socket option.
593 virtual bool SetReuseAddress(bool reuse_address) = 0;
594
595 virtual bool IsValid() const = 0;
596
597 static bool Setup();
598 static int LastError();
599 static uint16_t HToN(uint16_t value);
600 static uint16_t NToH(uint16_t value);
601 static uint32_t HToN(uint32_t value);
602 static uint32_t NToH(uint32_t value);
603};
604
605
Steve Blocka7e24c12009-10-30 11:49:00 +0000606// ----------------------------------------------------------------------------
607// Sampler
608//
609// A sampler periodically samples the state of the VM and optionally
610// (if used for profiling) the program counter and stack pointer for
611// the thread that created it.
612
613// TickSample captures the information collected for each sample.
614class TickSample {
615 public:
Leon Clarked91b9f72010-01-27 17:25:45 +0000616 TickSample()
Steve Block6ded16b2010-05-10 14:33:55 +0100617 : state(OTHER),
618 pc(NULL),
Leon Clarked91b9f72010-01-27 17:25:45 +0000619 sp(NULL),
620 fp(NULL),
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100621 tos(NULL),
Ben Murdoch8b112d22011-06-08 16:22:53 +0100622 frames_count(0),
623 has_external_callback(false) {}
Steve Block6ded16b2010-05-10 14:33:55 +0100624 StateTag state; // The state of the VM.
Steve Block44f0eee2011-05-26 01:26:41 +0100625 Address pc; // Instruction pointer.
626 Address sp; // Stack pointer.
627 Address fp; // Frame pointer.
628 union {
629 Address tos; // Top stack value (*sp).
630 Address external_callback;
631 };
Steve Block6ded16b2010-05-10 14:33:55 +0100632 static const int kMaxFramesCount = 64;
633 Address stack[kMaxFramesCount]; // Call stack.
Steve Block44f0eee2011-05-26 01:26:41 +0100634 int frames_count : 8; // Number of captured frames.
635 bool has_external_callback : 1;
Steve Blocka7e24c12009-10-30 11:49:00 +0000636};
637
Steve Blocka7e24c12009-10-30 11:49:00 +0000638class Sampler {
639 public:
640 // Initialize sampler.
Steve Block44f0eee2011-05-26 01:26:41 +0100641 Sampler(Isolate* isolate, int interval);
Steve Blocka7e24c12009-10-30 11:49:00 +0000642 virtual ~Sampler();
643
Steve Block44f0eee2011-05-26 01:26:41 +0100644 int interval() const { return interval_; }
645
Steve Blocka7e24c12009-10-30 11:49:00 +0000646 // Performs stack sampling.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800647 void SampleStack(TickSample* sample) {
648 DoSampleStack(sample);
649 IncSamplesTaken();
650 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000651
652 // This method is called for each sampling period with the current
653 // program counter.
654 virtual void Tick(TickSample* sample) = 0;
655
656 // Start and stop sampler.
657 void Start();
658 void Stop();
659
Ben Murdochf87a2032010-10-22 12:50:53 +0100660 // Is the sampler used for profiling?
Ben Murdochb0fe1622011-05-05 13:52:32 +0100661 bool IsProfiling() const { return NoBarrier_Load(&profiling_) > 0; }
662 void IncreaseProfilingDepth() { NoBarrier_AtomicIncrement(&profiling_, 1); }
663 void DecreaseProfilingDepth() { NoBarrier_AtomicIncrement(&profiling_, -1); }
Steve Blocka7e24c12009-10-30 11:49:00 +0000664
665 // Whether the sampler is running (that is, consumes resources).
Ben Murdochb0fe1622011-05-05 13:52:32 +0100666 bool IsActive() const { return NoBarrier_Load(&active_); }
Steve Blocka7e24c12009-10-30 11:49:00 +0000667
Steve Block44f0eee2011-05-26 01:26:41 +0100668 Isolate* isolate() { return isolate_; }
669
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800670 // Used in tests to make sure that stack sampling is performed.
671 int samples_taken() const { return samples_taken_; }
672 void ResetSamplesTaken() { samples_taken_ = 0; }
673
Steve Blocka7e24c12009-10-30 11:49:00 +0000674 class PlatformData;
Steve Block44f0eee2011-05-26 01:26:41 +0100675 PlatformData* data() { return data_; }
676
677 PlatformData* platform_data() { return data_; }
Steve Blocka7e24c12009-10-30 11:49:00 +0000678
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800679 protected:
680 virtual void DoSampleStack(TickSample* sample) = 0;
681
Steve Blocka7e24c12009-10-30 11:49:00 +0000682 private:
Ben Murdochb0fe1622011-05-05 13:52:32 +0100683 void SetActive(bool value) { NoBarrier_Store(&active_, value); }
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800684 void IncSamplesTaken() { if (++samples_taken_ < 0) samples_taken_ = 0; }
685
Steve Block44f0eee2011-05-26 01:26:41 +0100686 Isolate* isolate_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000687 const int interval_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100688 Atomic32 profiling_;
689 Atomic32 active_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000690 PlatformData* data_; // Platform specific data.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800691 int samples_taken_; // Counts stack samples taken.
Steve Blocka7e24c12009-10-30 11:49:00 +0000692 DISALLOW_IMPLICIT_CONSTRUCTORS(Sampler);
693};
694
Steve Block44f0eee2011-05-26 01:26:41 +0100695
Steve Blocka7e24c12009-10-30 11:49:00 +0000696} } // namespace v8::internal
697
698#endif // V8_PLATFORM_H_