deps: update v8 to 4.3.61.21
[platform/upstream/nodejs.git] / deps / v8 / src / base / platform / platform.h
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // This module contains the platform-specific code. This make the rest of the
6 // code less dependent on operating system, compilers and runtime libraries.
7 // This module does specifically not deal with differences between different
8 // processor architecture.
9 // The platform classes have the same definition for all platforms. The
10 // implementation for a particular platform is put in platform_<os>.cc.
11 // The build system then uses the implementation for the target platform.
12 //
13 // This design has been chosen because it is simple and fast. Alternatively,
14 // the platform dependent classes could have been implemented using abstract
15 // superclasses with virtual methods and having specializations for each
16 // platform. This design was rejected because it was more complicated and
17 // slower. It would require factory methods for selecting the right
18 // implementation and the overhead of virtual methods for performance
19 // sensitive like mutex locking/unlocking.
20
21 #ifndef V8_BASE_PLATFORM_PLATFORM_H_
22 #define V8_BASE_PLATFORM_PLATFORM_H_
23
24 #include <cstdarg>
25 #include <string>
26 #include <vector>
27
28 #include "src/base/build_config.h"
29 #include "src/base/platform/mutex.h"
30 #include "src/base/platform/semaphore.h"
31
32 #if V8_OS_QNX
33 #include "src/base/qnx-math.h"
34 #endif
35
36 namespace v8 {
37 namespace base {
38
39 // ----------------------------------------------------------------------------
40 // Fast TLS support
41
42 #ifndef V8_NO_FAST_TLS
43
44 #if V8_CC_MSVC && V8_HOST_ARCH_IA32
45
46 #define V8_FAST_TLS_SUPPORTED 1
47
48 INLINE(intptr_t InternalGetExistingThreadLocal(intptr_t index));
49
50 inline intptr_t InternalGetExistingThreadLocal(intptr_t index) {
51   const intptr_t kTibInlineTlsOffset = 0xE10;
52   const intptr_t kTibExtraTlsOffset = 0xF94;
53   const intptr_t kMaxInlineSlots = 64;
54   const intptr_t kMaxSlots = kMaxInlineSlots + 1024;
55   const intptr_t kPointerSize = sizeof(void*);
56   DCHECK(0 <= index && index < kMaxSlots);
57   if (index < kMaxInlineSlots) {
58     return static_cast<intptr_t>(__readfsdword(kTibInlineTlsOffset +
59                                                kPointerSize * index));
60   }
61   intptr_t extra = static_cast<intptr_t>(__readfsdword(kTibExtraTlsOffset));
62   DCHECK(extra != 0);
63   return *reinterpret_cast<intptr_t*>(extra +
64                                       kPointerSize * (index - kMaxInlineSlots));
65 }
66
67 #elif defined(__APPLE__) && (V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64)
68
69 #define V8_FAST_TLS_SUPPORTED 1
70
71 extern intptr_t kMacTlsBaseOffset;
72
73 INLINE(intptr_t InternalGetExistingThreadLocal(intptr_t index));
74
75 inline intptr_t InternalGetExistingThreadLocal(intptr_t index) {
76   intptr_t result;
77 #if V8_HOST_ARCH_IA32
78   asm("movl %%gs:(%1,%2,4), %0;"
79       :"=r"(result)  // Output must be a writable register.
80       :"r"(kMacTlsBaseOffset), "r"(index));
81 #else
82   asm("movq %%gs:(%1,%2,8), %0;"
83       :"=r"(result)
84       :"r"(kMacTlsBaseOffset), "r"(index));
85 #endif
86   return result;
87 }
88
89 #endif
90
91 #endif  // V8_NO_FAST_TLS
92
93
94 class TimezoneCache;
95
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
104 class OS {
105  public:
106   // Initialize the OS class.
107   // - random_seed: Used for the GetRandomMmapAddress() if non-zero.
108   // - hard_abort: If true, OS::Abort() will crash instead of aborting.
109   // - gc_fake_mmap: Name of the file for fake gc mmap used in ll_prof.
110   static void Initialize(int64_t random_seed,
111                          bool hard_abort,
112                          const char* const gc_fake_mmap);
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   // Returns current time as the number of milliseconds since
121   // 00:00:00 UTC, January 1, 1970.
122   static double TimeCurrentMillis();
123
124   static TimezoneCache* CreateTimezoneCache();
125   static void DisposeTimezoneCache(TimezoneCache* cache);
126   static void ClearTimezoneCache(TimezoneCache* cache);
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, TimezoneCache* cache);
131
132   // Returns the local time offset in milliseconds east of UTC without
133   // taking daylight savings time into account.
134   static double LocalTimeOffset(TimezoneCache* cache);
135
136   // Returns the daylight savings offset for the given time.
137   static double DaylightSavingsOffset(double time, TimezoneCache* cache);
138
139   // Returns last OS error.
140   static int GetLastError();
141
142   static FILE* FOpen(const char* path, const char* mode);
143   static bool Remove(const char* path);
144
145   static bool isDirectorySeparator(const char ch);
146
147   // Opens a temporary file, the file is auto removed on close.
148   static FILE* OpenTemporaryFile();
149
150   // Log file open mode is platform-dependent due to line ends issues.
151   static const char* const LogFileOpenMode;
152
153   // Print output to console. This is mostly used for debugging output.
154   // On platforms that has standard terminal output, the output
155   // should go to stdout.
156   static void Print(const char* format, ...);
157   static void VPrint(const char* format, va_list args);
158
159   // Print output to a file. This is mostly used for debugging output.
160   static void FPrint(FILE* out, const char* format, ...);
161   static void VFPrint(FILE* out, const char* format, va_list args);
162
163   // Print error output to console. This is mostly used for error message
164   // output. On platforms that has standard terminal output, the output
165   // should go to stderr.
166   static void PrintError(const char* format, ...);
167   static void VPrintError(const char* format, va_list args);
168
169   // Allocate/Free memory used by JS heap. Pages are readable/writable, but
170   // they are not guaranteed to be executable unless 'executable' is true.
171   // Returns the address of allocated memory, or NULL if failed.
172   static void* Allocate(const size_t requested,
173                         size_t* allocated,
174                         bool is_executable);
175   static void Free(void* address, const size_t size);
176
177   // This is the granularity at which the ProtectCode(...) call can set page
178   // permissions.
179   static intptr_t CommitPageSize();
180
181   // Mark code segments non-writable.
182   static void ProtectCode(void* address, const size_t size);
183
184   // Assign memory as a guard page so that access will cause an exception.
185   static void Guard(void* address, const size_t size);
186
187   // Generate a random address to be used for hinting mmap().
188   static void* GetRandomMmapAddr();
189
190   // Get the Alignment guaranteed by Allocate().
191   static size_t AllocateAlignment();
192
193   // Sleep for a number of milliseconds.
194   static void Sleep(const int milliseconds);
195
196   // Abort the current process.
197   static void Abort();
198
199   // Debug break.
200   static void DebugBreak();
201
202   // Walk the stack.
203   static const int kStackWalkError = -1;
204   static const int kStackWalkMaxNameLen = 256;
205   static const int kStackWalkMaxTextLen = 256;
206   struct StackFrame {
207     void* address;
208     char text[kStackWalkMaxTextLen];
209   };
210
211   class MemoryMappedFile {
212    public:
213     static MemoryMappedFile* open(const char* name);
214     static MemoryMappedFile* create(const char* name, int size, void* initial);
215     virtual ~MemoryMappedFile() { }
216     virtual void* memory() = 0;
217     virtual int size() = 0;
218   };
219
220   // Safe formatting print. Ensures that str is always null-terminated.
221   // Returns the number of chars written, or -1 if output was truncated.
222   static int SNPrintF(char* str, int length, const char* format, ...);
223   static int VSNPrintF(char* str,
224                        int length,
225                        const char* format,
226                        va_list args);
227
228   static char* StrChr(char* str, int c);
229   static void StrNCpy(char* dest, int length, const char* src, size_t n);
230
231   // Support for the profiler.  Can do nothing, in which case ticks
232   // occuring in shared libraries will not be properly accounted for.
233   struct SharedLibraryAddress {
234     SharedLibraryAddress(
235         const std::string& library_path, uintptr_t start, uintptr_t end)
236         : library_path(library_path), start(start), end(end) {}
237
238     std::string library_path;
239     uintptr_t start;
240     uintptr_t end;
241   };
242
243   static std::vector<SharedLibraryAddress> GetSharedLibraryAddresses();
244
245   // Support for the profiler.  Notifies the external profiling
246   // process that a code moving garbage collection starts.  Can do
247   // nothing, in which case the code objects must not move (e.g., by
248   // using --never-compact) if accurate profiling is desired.
249   static void SignalCodeMovingGC();
250
251   // Support runtime detection of whether the hard float option of the
252   // EABI is used.
253   static bool ArmUsingHardFloat();
254
255   // Returns the activation frame alignment constraint or zero if
256   // the platform doesn't care. Guaranteed to be a power of two.
257   static int ActivationFrameAlignment();
258
259   static int GetCurrentProcessId();
260
261   static int GetCurrentThreadId();
262
263  private:
264   static const int msPerSecond = 1000;
265
266 #if V8_OS_POSIX
267   static const char* GetGCFakeMMapFile();
268 #endif
269
270   DISALLOW_IMPLICIT_CONSTRUCTORS(OS);
271 };
272
273 // Represents and controls an area of reserved memory.
274 // Control of the reserved memory can be assigned to another VirtualMemory
275 // object by assignment or copy-contructing. This removes the reserved memory
276 // from the original object.
277 class VirtualMemory {
278  public:
279   // Empty VirtualMemory object, controlling no reserved memory.
280   VirtualMemory();
281
282   // Reserves virtual memory with size.
283   explicit VirtualMemory(size_t size);
284
285   // Reserves virtual memory containing an area of the given size that
286   // is aligned per alignment. This may not be at the position returned
287   // by address().
288   VirtualMemory(size_t size, size_t alignment);
289
290   // Releases the reserved memory, if any, controlled by this VirtualMemory
291   // object.
292   ~VirtualMemory();
293
294   // Returns whether the memory has been reserved.
295   bool IsReserved();
296
297   // Initialize or resets an embedded VirtualMemory object.
298   void Reset();
299
300   // Returns the start address of the reserved memory.
301   // If the memory was reserved with an alignment, this address is not
302   // necessarily aligned. The user might need to round it up to a multiple of
303   // the alignment to get the start of the aligned block.
304   void* address() {
305     DCHECK(IsReserved());
306     return address_;
307   }
308
309   // Returns the size of the reserved memory. The returned value is only
310   // meaningful when IsReserved() returns true.
311   // If the memory was reserved with an alignment, this size may be larger
312   // than the requested size.
313   size_t size() { return size_; }
314
315   // Commits real memory. Returns whether the operation succeeded.
316   bool Commit(void* address, size_t size, bool is_executable);
317
318   // Uncommit real memory.  Returns whether the operation succeeded.
319   bool Uncommit(void* address, size_t size);
320
321   // Creates a single guard page at the given address.
322   bool Guard(void* address);
323
324   void Release() {
325     DCHECK(IsReserved());
326     // Notice: Order is important here. The VirtualMemory object might live
327     // inside the allocated region.
328     void* address = address_;
329     size_t size = size_;
330     Reset();
331     bool result = ReleaseRegion(address, size);
332     USE(result);
333     DCHECK(result);
334   }
335
336   // Assign control of the reserved region to a different VirtualMemory object.
337   // The old object is no longer functional (IsReserved() returns false).
338   void TakeControl(VirtualMemory* from) {
339     DCHECK(!IsReserved());
340     address_ = from->address_;
341     size_ = from->size_;
342     from->Reset();
343   }
344
345   static void* ReserveRegion(size_t size);
346
347   static bool CommitRegion(void* base, size_t size, bool is_executable);
348
349   static bool UncommitRegion(void* base, size_t size);
350
351   // Must be called with a base pointer that has been returned by ReserveRegion
352   // and the same size it was reserved with.
353   static bool ReleaseRegion(void* base, size_t size);
354
355   // Returns true if OS performs lazy commits, i.e. the memory allocation call
356   // defers actual physical memory allocation till the first memory access.
357   // Otherwise returns false.
358   static bool HasLazyCommits();
359
360  private:
361   void* address_;  // Start address of the virtual memory.
362   size_t size_;  // Size of the virtual memory.
363 };
364
365
366 // ----------------------------------------------------------------------------
367 // Thread
368 //
369 // Thread objects are used for creating and running threads. When the start()
370 // method is called the new thread starts running the run() method in the new
371 // thread. The Thread object should not be deallocated before the thread has
372 // terminated.
373
374 class Thread {
375  public:
376   // Opaque data type for thread-local storage keys.
377   typedef int32_t LocalStorageKey;
378
379   class Options {
380    public:
381     Options() : name_("v8:<unknown>"), stack_size_(0) {}
382     explicit Options(const char* name, int stack_size = 0)
383         : name_(name), stack_size_(stack_size) {}
384
385     const char* name() const { return name_; }
386     int stack_size() const { return stack_size_; }
387
388    private:
389     const char* name_;
390     int stack_size_;
391   };
392
393   // Create new thread.
394   explicit Thread(const Options& options);
395   virtual ~Thread();
396
397   // Start new thread by calling the Run() method on the new thread.
398   void Start();
399
400   // Start new thread and wait until Run() method is called on the new thread.
401   void StartSynchronously() {
402     start_semaphore_ = new Semaphore(0);
403     Start();
404     start_semaphore_->Wait();
405     delete start_semaphore_;
406     start_semaphore_ = NULL;
407   }
408
409   // Wait until thread terminates.
410   void Join();
411
412   inline const char* name() const {
413     return name_;
414   }
415
416   // Abstract method for run handler.
417   virtual void Run() = 0;
418
419   // Thread-local storage.
420   static LocalStorageKey CreateThreadLocalKey();
421   static void DeleteThreadLocalKey(LocalStorageKey key);
422   static void* GetThreadLocal(LocalStorageKey key);
423   static int GetThreadLocalInt(LocalStorageKey key) {
424     return static_cast<int>(reinterpret_cast<intptr_t>(GetThreadLocal(key)));
425   }
426   static void SetThreadLocal(LocalStorageKey key, void* value);
427   static void SetThreadLocalInt(LocalStorageKey key, int value) {
428     SetThreadLocal(key, reinterpret_cast<void*>(static_cast<intptr_t>(value)));
429   }
430   static bool HasThreadLocal(LocalStorageKey key) {
431     return GetThreadLocal(key) != NULL;
432   }
433
434 #ifdef V8_FAST_TLS_SUPPORTED
435   static inline void* GetExistingThreadLocal(LocalStorageKey key) {
436     void* result = reinterpret_cast<void*>(
437         InternalGetExistingThreadLocal(static_cast<intptr_t>(key)));
438     DCHECK(result == GetThreadLocal(key));
439     return result;
440   }
441 #else
442   static inline void* GetExistingThreadLocal(LocalStorageKey key) {
443     return GetThreadLocal(key);
444   }
445 #endif
446
447   // A hint to the scheduler to let another thread run.
448   static void YieldCPU();
449
450
451   // The thread name length is limited to 16 based on Linux's implementation of
452   // prctl().
453   static const int kMaxThreadNameLength = 16;
454
455   class PlatformData;
456   PlatformData* data() { return data_; }
457
458   void NotifyStartedAndRun() {
459     if (start_semaphore_) start_semaphore_->Signal();
460     Run();
461   }
462
463  private:
464   void set_name(const char* name);
465
466   PlatformData* data_;
467
468   char name_[kMaxThreadNameLength];
469   int stack_size_;
470   Semaphore* start_semaphore_;
471
472   DISALLOW_COPY_AND_ASSIGN(Thread);
473 };
474
475 } }  // namespace v8::base
476
477 #endif  // V8_BASE_PLATFORM_PLATFORM_H_