blob: 5fde6a009aa40a01e548429894810de9a45b5b90 [file] [log] [blame]
ulan@chromium.org0e3f88b2012-05-22 09:16:05 +00001// Copyright 2012 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//
ager@chromium.org32912102009-01-16 10:38:43 +000036// This design has been chosen because it is simple and fast. Alternatively,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000037// 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
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +000047#ifdef __sun
48# ifndef signbit
49int signbit(double x);
50# endif
51#endif
52
iposva@chromium.org245aa852009-02-10 00:49:54 +000053// GCC specific stuff
54#ifdef __GNUC__
ager@chromium.org3e875802009-06-29 08:26:34 +000055
56// Needed for va_list on at least MinGW and Android.
57#include <stdarg.h>
58
iposva@chromium.org245aa852009-02-10 00:49:54 +000059#define __GNUC_VERSION__ (__GNUC__ * 10000 + __GNUC_MINOR__ * 100)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000060
iposva@chromium.org245aa852009-02-10 00:49:54 +000061#endif // __GNUC__
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000062
ricow@chromium.org55ee8072011-09-08 16:33:10 +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
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000074inline int lrint(double flt) {
75 int intgr;
76#if defined(V8_TARGET_ARCH_IA32)
77 __asm {
78 fld flt
79 fistp intgr
80 };
81#else
82 intgr = static_cast<int>(flt + 0.5);
83 if ((intgr & 1) != 0 && intgr - flt == 0.5) {
84 // If the number is halfway between two integers, round to the even one.
85 intgr--;
86 }
87#endif
88 return intgr;
89}
90
91
ricow@chromium.org55ee8072011-09-08 16:33:10 +000092#endif // _MSC_VER
93
94// Random is missing on both Visual Studio and MinGW.
95int random();
96
97#endif // WIN32
98
kasperl@chromium.orga5551262010-12-07 12:49:48 +000099#include "atomicops.h"
jkummerow@chromium.org1456e702012-03-30 08:38:13 +0000100#include "lazy-instance.h"
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000101#include "platform-tls.h"
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000102#include "utils.h"
103#include "v8globals.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000104
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000105namespace v8 {
106namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000107
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000108// Use AtomicWord for a machine-sized pointer. It is assumed that
109// reads and writes of naturally aligned values of this type are atomic.
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000110#if defined(__OpenBSD__) && defined(__i386__)
111typedef Atomic32 AtomicWord;
112#else
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000113typedef intptr_t AtomicWord;
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000114#endif
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000115
ager@chromium.org3e875802009-06-29 08:26:34 +0000116class Semaphore;
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000117class Mutex;
ager@chromium.org3e875802009-06-29 08:26:34 +0000118
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000119double ceiling(double x);
ager@chromium.org3811b432009-10-28 14:53:37 +0000120double modulo(double x, double y);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000121
danno@chromium.org1f34ad32012-11-26 14:53:56 +0000122// Custom implementation of math functions.
ulan@chromium.org9a21ec42012-03-06 08:42:24 +0000123double fast_sin(double input);
124double fast_cos(double input);
125double fast_tan(double input);
126double fast_log(double input);
danno@chromium.org1f34ad32012-11-26 14:53:56 +0000127double fast_exp(double input);
yangguo@chromium.org154ff992012-03-13 08:09:54 +0000128double fast_sqrt(double input);
danno@chromium.org1f34ad32012-11-26 14:53:56 +0000129// The custom exp implementation needs 16KB of lookup data; initialize it
130// on demand.
131void lazily_initialize_fast_exp();
ulan@chromium.org9a21ec42012-03-06 08:42:24 +0000132
ager@chromium.org381abbb2009-02-25 13:23:22 +0000133// Forward declarations.
134class Socket;
135
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000136// ----------------------------------------------------------------------------
137// OS
138//
139// This class has static methods for the different platform specific
140// functions. Add methods here to cope with differences between the
141// supported platforms.
142
143class OS {
144 public:
145 // Initializes the platform OS support. Called once at VM startup.
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000146 static void SetUp();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000147
danno@chromium.org8c0a43f2012-04-03 08:37:53 +0000148 // Initializes the platform OS support that depend on CPU features. This is
149 // called after CPU initialization.
150 static void PostSetUp();
151
erik.corry@gmail.comed49e962012-04-17 11:57:53 +0000152 // Clean up platform-OS-related things. Called once at VM shutdown.
153 static void TearDown();
154
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000155 // Returns the accumulated user time for thread. This routine
156 // can be used for profiling. The implementation should
157 // strive for high-precision timer resolution, preferable
158 // micro-second resolution.
159 static int GetUserTime(uint32_t* secs, uint32_t* usecs);
160
161 // Get a tick counter normalized to one tick per microsecond.
162 // Used for calculating time intervals.
163 static int64_t Ticks();
164
165 // Returns current time as the number of milliseconds since
166 // 00:00:00 UTC, January 1, 1970.
167 static double TimeCurrentMillis();
168
169 // Returns a string identifying the current time zone. The
170 // timestamp is used for determining if DST is in effect.
sgjesse@chromium.orgb9d7da12009-08-05 08:38:10 +0000171 static const char* LocalTimezone(double time);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000172
173 // Returns the local time offset in milliseconds east of UTC without
174 // taking daylight savings time into account.
175 static double LocalTimeOffset();
176
177 // Returns the daylight savings offset for the given time.
178 static double DaylightSavingsOffset(double time);
179
ager@chromium.orgea4f62e2010-08-16 16:28:43 +0000180 // Returns last OS error.
181 static int GetLastError();
182
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000183 static FILE* FOpen(const char* path, const char* mode);
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000184 static bool Remove(const char* path);
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000185
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000186 // Opens a temporary file, the file is auto removed on close.
187 static FILE* OpenTemporaryFile();
188
ager@chromium.org71daaf62009-04-01 07:22:49 +0000189 // Log file open mode is platform-dependent due to line ends issues.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000190 static const char* const LogFileOpenMode;
ager@chromium.org71daaf62009-04-01 07:22:49 +0000191
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000192 // Print output to console. This is mostly used for debugging output.
193 // On platforms that has standard terminal output, the output
194 // should go to stdout.
195 static void Print(const char* format, ...);
196 static void VPrint(const char* format, va_list args);
197
whesse@chromium.org023421e2010-12-21 12:19:12 +0000198 // Print output to a file. This is mostly used for debugging output.
199 static void FPrint(FILE* out, const char* format, ...);
200 static void VFPrint(FILE* out, const char* format, va_list args);
201
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000202 // Print error output to console. This is mostly used for error message
203 // output. On platforms that has standard terminal output, the output
204 // should go to stderr.
205 static void PrintError(const char* format, ...);
206 static void VPrintError(const char* format, va_list args);
207
ager@chromium.org32912102009-01-16 10:38:43 +0000208 // Allocate/Free memory used by JS heap. Pages are readable/writable, but
kasper.lund7276f142008-07-30 08:49:36 +0000209 // they are not guaranteed to be executable unless 'executable' is true.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000210 // Returns the address of allocated memory, or NULL if failed.
kasper.lund7276f142008-07-30 08:49:36 +0000211 static void* Allocate(const size_t requested,
212 size_t* allocated,
kasperl@chromium.orgf5aa8372009-03-24 14:47:14 +0000213 bool is_executable);
214 static void Free(void* address, const size_t size);
rossberg@chromium.org717967f2011-07-20 13:44:42 +0000215
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +0000216 // This is the granularity at which the ProtectCode(...) call can set page
217 // permissions.
218 static intptr_t CommitPageSize();
219
lrn@chromium.orgd4e9e222011-08-03 12:01:58 +0000220 // Mark code segments non-writable.
221 static void ProtectCode(void* address, const size_t size);
222
rossberg@chromium.org717967f2011-07-20 13:44:42 +0000223 // Assign memory as a guard page so that access will cause an exception.
224 static void Guard(void* address, const size_t size);
225
rossberg@chromium.orgb4b2aa62011-10-13 09:49:59 +0000226 // Generate a random address to be used for hinting mmap().
227 static void* GetRandomMmapAddr();
228
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000229 // Get the Alignment guaranteed by Allocate().
230 static size_t AllocateAlignment();
231
232 // Returns an indication of whether a pointer is in a space that
233 // has been allocated by Allocate(). This method may conservatively
234 // always return false, but giving more accurate information may
235 // improve the robustness of the stack dump code in the presence of
236 // heap corruption.
237 static bool IsOutsideAllocatedSpace(void* pointer);
238
ager@chromium.org32912102009-01-16 10:38:43 +0000239 // Sleep for a number of milliseconds.
240 static void Sleep(const int milliseconds);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000241
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +0000242 static int NumberOfCores();
243
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000244 // Abort the current process.
245 static void Abort();
246
kasper.lund7276f142008-07-30 08:49:36 +0000247 // Debug break.
248 static void DebugBreak();
249
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000250 // Dump C++ current stack trace (only functional on Linux).
251 static void DumpBacktrace();
252
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000253 // Walk the stack.
254 static const int kStackWalkError = -1;
255 static const int kStackWalkMaxNameLen = 256;
256 static const int kStackWalkMaxTextLen = 256;
257 struct StackFrame {
258 void* address;
259 char text[kStackWalkMaxTextLen];
260 };
261
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000262 static int StackWalk(Vector<StackFrame> frames);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000263
264 // Factory method for creating platform dependent Mutex.
265 // Please use delete to reclaim the storage for the returned Mutex.
266 static Mutex* CreateMutex();
267
268 // Factory method for creating platform dependent Semaphore.
269 // Please use delete to reclaim the storage for the returned Semaphore.
270 static Semaphore* CreateSemaphore(int count);
271
ager@chromium.org381abbb2009-02-25 13:23:22 +0000272 // Factory method for creating platform dependent Socket.
273 // Please use delete to reclaim the storage for the returned Socket.
274 static Socket* CreateSocket();
275
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000276 class MemoryMappedFile {
277 public:
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000278 static MemoryMappedFile* open(const char* name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000279 static MemoryMappedFile* create(const char* name, int size, void* initial);
280 virtual ~MemoryMappedFile() { }
281 virtual void* memory() = 0;
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000282 virtual int size() = 0;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000283 };
284
kasper.lund7276f142008-07-30 08:49:36 +0000285 // Safe formatting print. Ensures that str is always null-terminated.
286 // Returns the number of chars written, or -1 if output was truncated.
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000287 static int SNPrintF(Vector<char> str, const char* format, ...);
288 static int VSNPrintF(Vector<char> str,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000289 const char* format,
290 va_list args);
291
ager@chromium.org381abbb2009-02-25 13:23:22 +0000292 static char* StrChr(char* str, int c);
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000293 static void StrNCpy(Vector<char> dest, const char* src, size_t n);
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000294
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000295 // Support for the profiler. Can do nothing, in which case ticks
296 // occuring in shared libraries will not be properly accounted for.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000297 static void LogSharedLibraryAddresses();
298
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000299 // Support for the profiler. Notifies the external profiling
300 // process that a code moving garbage collection starts. Can do
301 // nothing, in which case the code objects must not move (e.g., by
302 // using --never-compact) if accurate profiling is desired.
303 static void SignalCodeMovingGC();
304
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000305 // The return value indicates the CPU features we are sure of because of the
306 // OS. For example MacOSX doesn't run on any x86 CPUs that don't have SSE2
307 // instructions.
308 // This is a little messy because the interpretation is subject to the cross
309 // of the CPU and the OS. The bits in the answer correspond to the bit
310 // positions indicated by the members of the CpuFeature enum from globals.h
311 static uint64_t CpuFeaturesImpliedByPlatform();
312
lrn@chromium.orgac2828d2011-06-23 06:29:21 +0000313 // Maximum size of the virtual memory. 0 means there is no artificial
314 // limit.
315 static intptr_t MaxVirtualMemory();
316
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000317 // Returns the double constant NAN
318 static double nan_value();
319
rossberg@chromium.org89e18f52012-10-22 13:09:53 +0000320 // Support runtime detection of Cpu implementer
321 static CpuImplementer GetCpuImplementer();
322
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000323 // Support runtime detection of VFP3 on ARM CPUs.
324 static bool ArmCpuHasFeature(CpuFeature feature);
325
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000326 // Support runtime detection of whether the hard float option of the
327 // EABI is used.
328 static bool ArmUsingHardFloat();
329
lrn@chromium.org7516f052011-03-30 08:52:27 +0000330 // Support runtime detection of FPU on MIPS CPUs.
331 static bool MipsCpuHasFeature(CpuFeature feature);
332
ager@chromium.org236ad962008-09-25 09:45:57 +0000333 // Returns the activation frame alignment constraint or zero if
334 // the platform doesn't care. Guaranteed to be a power of two.
335 static int ActivationFrameAlignment();
336
kmillikin@chromium.org9155e252010-05-26 13:27:57 +0000337 static void ReleaseStore(volatile AtomicWord* ptr, AtomicWord value);
338
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000339#if defined(V8_TARGET_ARCH_IA32)
340 // Copy memory area to disjoint memory area.
341 static void MemCopy(void* dest, const void* src, size_t size);
342 // Limit below which the extra overhead of the MemCopy function is likely
343 // to outweigh the benefits of faster copying.
344 static const int kMinComplexMemCopy = 64;
345 typedef void (*MemCopyFunction)(void* dest, const void* src, size_t size);
346
347#else // V8_TARGET_ARCH_IA32
348 static void MemCopy(void* dest, const void* src, size_t size) {
349 memcpy(dest, src, size);
350 }
351 static const int kMinComplexMemCopy = 256;
352#endif // V8_TARGET_ARCH_IA32
353
rossberg@chromium.org657d53b2012-07-12 11:06:03 +0000354 static int GetCurrentProcessId();
355
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000356 private:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000357 static const int msPerSecond = 1000;
mads.s.ager31e71382008-08-13 09:32:07 +0000358
359 DISALLOW_IMPLICIT_CONSTRUCTORS(OS);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000360};
361
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000362// Represents and controls an area of reserved memory.
363// Control of the reserved memory can be assigned to another VirtualMemory
364// object by assignment or copy-contructing. This removes the reserved memory
365// from the original object.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000366class VirtualMemory {
367 public:
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000368 // Empty VirtualMemory object, controlling no reserved memory.
369 VirtualMemory();
370
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000371 // Reserves virtual memory with size.
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000372 explicit VirtualMemory(size_t size);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000373
374 // Reserves virtual memory containing an area of the given size that
375 // is aligned per alignment. This may not be at the position returned
376 // by address().
377 VirtualMemory(size_t size, size_t alignment);
378
379 // Releases the reserved memory, if any, controlled by this VirtualMemory
380 // object.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000381 ~VirtualMemory();
382
383 // Returns whether the memory has been reserved.
384 bool IsReserved();
385
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000386 // Initialize or resets an embedded VirtualMemory object.
387 void Reset();
388
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000389 // Returns the start address of the reserved memory.
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000390 // If the memory was reserved with an alignment, this address is not
391 // necessarily aligned. The user might need to round it up to a multiple of
392 // the alignment to get the start of the aligned block.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000393 void* address() {
394 ASSERT(IsReserved());
395 return address_;
kmillikin@chromium.org3cdd9e12010-09-06 11:39:48 +0000396 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000397
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000398 // Returns the size of the reserved memory. The returned value is only
399 // meaningful when IsReserved() returns true.
400 // If the memory was reserved with an alignment, this size may be larger
401 // than the requested size.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000402 size_t size() { return size_; }
403
404 // Commits real memory. Returns whether the operation succeeded.
kasperl@chromium.orgf5aa8372009-03-24 14:47:14 +0000405 bool Commit(void* address, size_t size, bool is_executable);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000406
407 // Uncommit real memory. Returns whether the operation succeeded.
408 bool Uncommit(void* address, size_t size);
409
yangguo@chromium.orgab30bb82012-02-24 14:41:46 +0000410 // Creates a single guard page at the given address.
411 bool Guard(void* address);
412
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000413 void Release() {
414 ASSERT(IsReserved());
415 // Notice: Order is important here. The VirtualMemory object might live
416 // inside the allocated region.
417 void* address = address_;
418 size_t size = size_;
419 Reset();
420 bool result = ReleaseRegion(address, size);
421 USE(result);
422 ASSERT(result);
423 }
424
425 // Assign control of the reserved region to a different VirtualMemory object.
426 // The old object is no longer functional (IsReserved() returns false).
427 void TakeControl(VirtualMemory* from) {
428 ASSERT(!IsReserved());
429 address_ = from->address_;
430 size_ = from->size_;
431 from->Reset();
432 }
433
434 static void* ReserveRegion(size_t size);
435
436 static bool CommitRegion(void* base, size_t size, bool is_executable);
437
438 static bool UncommitRegion(void* base, size_t size);
439
440 // Must be called with a base pointer that has been returned by ReserveRegion
441 // and the same size it was reserved with.
442 static bool ReleaseRegion(void* base, size_t size);
443
danno@chromium.org72204d52012-10-31 10:02:10 +0000444 // Returns true if OS performs lazy commits, i.e. the memory allocation call
445 // defers actual physical memory allocation till the first memory access.
446 // Otherwise returns false.
447 static bool HasLazyCommits();
448
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000449 private:
450 void* address_; // Start address of the virtual memory.
451 size_t size_; // Size of the virtual memory.
452};
453
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000454
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000455// ----------------------------------------------------------------------------
456// Thread
457//
458// Thread objects are used for creating and running threads. When the start()
459// method is called the new thread starts running the run() method in the new
460// thread. The Thread object should not be deallocated before the thread has
461// terminated.
462
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +0000463class Thread {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000464 public:
465 // Opaque data type for thread-local storage keys.
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000466 // LOCAL_STORAGE_KEY_MIN_VALUE and LOCAL_STORAGE_KEY_MAX_VALUE are specified
467 // to ensure that enumeration type has correct value range (see Issue 830 for
468 // more details).
469 enum LocalStorageKey {
470 LOCAL_STORAGE_KEY_MIN_VALUE = kMinInt,
471 LOCAL_STORAGE_KEY_MAX_VALUE = kMaxInt
472 };
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000473
yangguo@chromium.org659ceec2012-01-26 07:37:54 +0000474 class Options {
475 public:
476 Options() : name_("v8:<unknown>"), stack_size_(0) {}
477 Options(const char* name, int stack_size = 0)
478 : name_(name), stack_size_(stack_size) {}
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000479
yangguo@chromium.org659ceec2012-01-26 07:37:54 +0000480 const char* name() const { return name_; }
481 int stack_size() const { return stack_size_; }
482
483 private:
484 const char* name_;
485 int stack_size_;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000486 };
487
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000488 // Create new thread.
489 explicit Thread(const Options& options);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000490 virtual ~Thread();
491
492 // Start new thread by calling the Run() method in the new thread.
493 void Start();
494
495 // Wait until thread terminates.
496 void Join();
497
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000498 inline const char* name() const {
499 return name_;
500 }
501
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000502 // Abstract method for run handler.
503 virtual void Run() = 0;
504
505 // Thread-local storage.
506 static LocalStorageKey CreateThreadLocalKey();
507 static void DeleteThreadLocalKey(LocalStorageKey key);
508 static void* GetThreadLocal(LocalStorageKey key);
ager@chromium.org9085a012009-05-11 19:22:57 +0000509 static int GetThreadLocalInt(LocalStorageKey key) {
510 return static_cast<int>(reinterpret_cast<intptr_t>(GetThreadLocal(key)));
511 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000512 static void SetThreadLocal(LocalStorageKey key, void* value);
ager@chromium.org9085a012009-05-11 19:22:57 +0000513 static void SetThreadLocalInt(LocalStorageKey key, int value) {
514 SetThreadLocal(key, reinterpret_cast<void*>(static_cast<intptr_t>(value)));
515 }
516 static bool HasThreadLocal(LocalStorageKey key) {
517 return GetThreadLocal(key) != NULL;
518 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000519
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000520#ifdef V8_FAST_TLS_SUPPORTED
521 static inline void* GetExistingThreadLocal(LocalStorageKey key) {
522 void* result = reinterpret_cast<void*>(
523 InternalGetExistingThreadLocal(static_cast<intptr_t>(key)));
524 ASSERT(result == GetThreadLocal(key));
525 return result;
526 }
527#else
528 static inline void* GetExistingThreadLocal(LocalStorageKey key) {
529 return GetThreadLocal(key);
530 }
531#endif
532
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000533 // A hint to the scheduler to let another thread run.
534 static void YieldCPU();
535
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000536
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000537 // The thread name length is limited to 16 based on Linux's implementation of
538 // prctl().
539 static const int kMaxThreadNameLength = 16;
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +0000540
541 class PlatformData;
542 PlatformData* data() { return data_; }
543
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000544 private:
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000545 void set_name(const char* name);
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000546
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000547 PlatformData* data_;
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +0000548
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000549 char name_[kMaxThreadNameLength];
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000550 int stack_size_;
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000551
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000552 DISALLOW_COPY_AND_ASSIGN(Thread);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000553};
554
555
556// ----------------------------------------------------------------------------
557// Mutex
558//
559// Mutexes are used for serializing access to non-reentrant sections of code.
560// The implementations of mutex should allow for nested/recursive locking.
561
562class Mutex {
563 public:
564 virtual ~Mutex() {}
565
566 // Locks the given mutex. If the mutex is currently unlocked, it becomes
567 // locked and owned by the calling thread, and immediately. If the mutex
568 // is already locked by another thread, suspends the calling thread until
569 // the mutex is unlocked.
570 virtual int Lock() = 0;
571
572 // Unlocks the given mutex. The mutex is assumed to be locked and owned by
573 // the calling thread on entrance.
574 virtual int Unlock() = 0;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000575
576 // Tries to lock the given mutex. Returns whether the mutex was
577 // successfully locked.
578 virtual bool TryLock() = 0;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000579};
580
jkummerow@chromium.org1456e702012-03-30 08:38:13 +0000581struct CreateMutexTrait {
582 static Mutex* Create() {
583 return OS::CreateMutex();
584 }
585};
586
587// POD Mutex initialized lazily (i.e. the first time Pointer() is called).
588// Usage:
589// static LazyMutex my_mutex = LAZY_MUTEX_INITIALIZER;
590//
591// void my_function() {
592// ScopedLock my_lock(my_mutex.Pointer());
593// // Do something.
594// }
595//
danno@chromium.org8c0a43f2012-04-03 08:37:53 +0000596typedef LazyDynamicInstance<
597 Mutex, CreateMutexTrait, ThreadSafeInitOnceTrait>::type LazyMutex;
jkummerow@chromium.org1456e702012-03-30 08:38:13 +0000598
599#define LAZY_MUTEX_INITIALIZER LAZY_DYNAMIC_INSTANCE_INITIALIZER
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000600
601// ----------------------------------------------------------------------------
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000602// ScopedLock
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000603//
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000604// Stack-allocated ScopedLocks provide block-scoped locking and
605// unlocking of a mutex.
kasper.lund7276f142008-07-30 08:49:36 +0000606class ScopedLock {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000607 public:
kasper.lund7276f142008-07-30 08:49:36 +0000608 explicit ScopedLock(Mutex* mutex): mutex_(mutex) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000609 ASSERT(mutex_ != NULL);
kasper.lund7276f142008-07-30 08:49:36 +0000610 mutex_->Lock();
611 }
612 ~ScopedLock() {
613 mutex_->Unlock();
614 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000615
616 private:
kasper.lund7276f142008-07-30 08:49:36 +0000617 Mutex* mutex_;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000618 DISALLOW_COPY_AND_ASSIGN(ScopedLock);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000619};
620
621
622// ----------------------------------------------------------------------------
623// Semaphore
624//
625// A semaphore object is a synchronization object that maintains a count. The
626// count is decremented each time a thread completes a wait for the semaphore
627// object and incremented each time a thread signals the semaphore. When the
628// count reaches zero, threads waiting for the semaphore blocks until the
629// count becomes non-zero.
630
631class Semaphore {
632 public:
633 virtual ~Semaphore() {}
634
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000635 // Suspends the calling thread until the semaphore counter is non zero
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000636 // and then decrements the semaphore counter.
637 virtual void Wait() = 0;
638
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000639 // Suspends the calling thread until the counter is non zero or the timeout
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000640 // time has passed. If timeout happens the return value is false and the
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000641 // counter is unchanged. Otherwise the semaphore counter is decremented and
642 // true is returned. The timeout value is specified in microseconds.
643 virtual bool Wait(int timeout) = 0;
644
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000645 // Increments the semaphore counter.
646 virtual void Signal() = 0;
647};
648
jkummerow@chromium.org1456e702012-03-30 08:38:13 +0000649template <int InitialValue>
650struct CreateSemaphoreTrait {
651 static Semaphore* Create() {
652 return OS::CreateSemaphore(InitialValue);
653 }
654};
655
656// POD Semaphore initialized lazily (i.e. the first time Pointer() is called).
657// Usage:
658// // The following semaphore starts at 0.
659// static LazySemaphore<0>::type my_semaphore = LAZY_SEMAPHORE_INITIALIZER;
660//
661// void my_function() {
662// // Do something with my_semaphore.Pointer().
663// }
664//
665template <int InitialValue>
666struct LazySemaphore {
667 typedef typename LazyDynamicInstance<
danno@chromium.org8c0a43f2012-04-03 08:37:53 +0000668 Semaphore, CreateSemaphoreTrait<InitialValue>,
669 ThreadSafeInitOnceTrait>::type type;
jkummerow@chromium.org1456e702012-03-30 08:38:13 +0000670};
671
672#define LAZY_SEMAPHORE_INITIALIZER LAZY_DYNAMIC_INSTANCE_INITIALIZER
673
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000674
ager@chromium.org381abbb2009-02-25 13:23:22 +0000675// ----------------------------------------------------------------------------
676// Socket
677//
678
679class Socket {
680 public:
681 virtual ~Socket() {}
682
683 // Server initialization.
684 virtual bool Bind(const int port) = 0;
685 virtual bool Listen(int backlog) const = 0;
686 virtual Socket* Accept() const = 0;
687
688 // Client initialization.
689 virtual bool Connect(const char* host, const char* port) = 0;
690
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000691 // Shutdown socket for both read and write. This causes blocking Send and
692 // Receive calls to exit. After Shutdown the Socket object cannot be used for
693 // any communication.
694 virtual bool Shutdown() = 0;
695
ager@chromium.org381abbb2009-02-25 13:23:22 +0000696 // Data Transimission
ulan@chromium.org0e3f88b2012-05-22 09:16:05 +0000697 // Return 0 on failure.
ager@chromium.org381abbb2009-02-25 13:23:22 +0000698 virtual int Send(const char* data, int len) const = 0;
ager@chromium.org381abbb2009-02-25 13:23:22 +0000699 virtual int Receive(char* data, int len) const = 0;
700
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000701 // Set the value of the SO_REUSEADDR socket option.
702 virtual bool SetReuseAddress(bool reuse_address) = 0;
703
ager@chromium.org381abbb2009-02-25 13:23:22 +0000704 virtual bool IsValid() const = 0;
705
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000706 static bool SetUp();
ager@chromium.org381abbb2009-02-25 13:23:22 +0000707 static int LastError();
708 static uint16_t HToN(uint16_t value);
709 static uint16_t NToH(uint16_t value);
710 static uint32_t HToN(uint32_t value);
711 static uint32_t NToH(uint32_t value);
712};
713
714
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000715// ----------------------------------------------------------------------------
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000716// Sampler
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000717//
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000718// A sampler periodically samples the state of the VM and optionally
719// (if used for profiling) the program counter and stack pointer for
720// the thread that created it.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000721
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000722// TickSample captures the information collected for each sample.
723class TickSample {
724 public:
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000725 TickSample()
ager@chromium.org357bf652010-04-12 11:30:10 +0000726 : state(OTHER),
727 pc(NULL),
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000728 sp(NULL),
729 fp(NULL),
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000730 tos(NULL),
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000731 frames_count(0),
732 has_external_callback(false) {}
ager@chromium.org357bf652010-04-12 11:30:10 +0000733 StateTag state; // The state of the VM.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000734 Address pc; // Instruction pointer.
735 Address sp; // Stack pointer.
736 Address fp; // Frame pointer.
737 union {
738 Address tos; // Top stack value (*sp).
739 Address external_callback;
740 };
lrn@chromium.org25156de2010-04-06 13:10:27 +0000741 static const int kMaxFramesCount = 64;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000742 Address stack[kMaxFramesCount]; // Call stack.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000743 int frames_count : 8; // Number of captured frames.
744 bool has_external_callback : 1;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000745};
746
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000747class Sampler {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000748 public:
749 // Initialize sampler.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000750 Sampler(Isolate* isolate, int interval);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000751 virtual ~Sampler();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000752
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000753 int interval() const { return interval_; }
754
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000755 // Performs stack sampling.
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000756 void SampleStack(TickSample* sample) {
757 DoSampleStack(sample);
758 IncSamplesTaken();
759 }
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000760
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000761 // This method is called for each sampling period with the current
762 // program counter.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000763 virtual void Tick(TickSample* sample) = 0;
764
765 // Start and stop sampler.
766 void Start();
767 void Stop();
768
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +0000769 // Whether the sampling thread should use this Sampler for CPU profiling?
770 bool IsProfiling() const {
771 return NoBarrier_Load(&profiling_) > 0 &&
772 !NoBarrier_Load(&has_processing_thread_);
773 }
774 void IncreaseProfilingDepth() {
775 if (NoBarrier_AtomicIncrement(&profiling_, 1) == 1) StartProfiling();
776 }
777 void DecreaseProfilingDepth() {
778 if (!NoBarrier_AtomicIncrement(&profiling_, -1)) StopProfiling();
779 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000780
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000781 // Whether the sampler is running (that is, consumes resources).
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000782 bool IsActive() const { return NoBarrier_Load(&active_); }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000783
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000784 Isolate* isolate() { return isolate_; }
785
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000786 // Used in tests to make sure that stack sampling is performed.
787 int samples_taken() const { return samples_taken_; }
788 void ResetSamplesTaken() { samples_taken_ = 0; }
789
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000790 class PlatformData;
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000791 PlatformData* data() { return data_; }
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000792
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000793 PlatformData* platform_data() { return data_; }
794
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +0000795 // If true next sample must be initiated on the profiler event processor
796 // thread right after latest sample is processed.
797 static bool CanSampleOnProfilerEventsProcessorThread();
798 void DoSample();
799 void SetHasProcessingThread(bool value) {
800 NoBarrier_Store(&has_processing_thread_, value);
801 }
802
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000803 protected:
804 virtual void DoSampleStack(TickSample* sample) = 0;
805
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000806 private:
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000807 void SetActive(bool value) { NoBarrier_Store(&active_, value); }
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000808 void IncSamplesTaken() { if (++samples_taken_ < 0) samples_taken_ = 0; }
809
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +0000810 // Perform platform-specific initialization before DoSample() may be invoked.
811 void StartProfiling();
812 // Perform platform-specific cleanup after profiling.
813 void StopProfiling();
814
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000815 Isolate* isolate_;
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000816 const int interval_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000817 Atomic32 profiling_;
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +0000818 Atomic32 has_processing_thread_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000819 Atomic32 active_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000820 PlatformData* data_; // Platform specific data.
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000821 int samples_taken_; // Counts stack samples taken.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000822 DISALLOW_IMPLICIT_CONSTRUCTORS(Sampler);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000823};
824
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000825
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000826} } // namespace v8::internal
827
828#endif // V8_PLATFORM_H_