The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / deps / v8 / src / platform.h @ f230a1cf

History | View | Annotate | Download (20.2 KB)

1
// Copyright 2012 the V8 project authors. All rights reserved.
2
// Redistribution and use in source and binary forms, with or without
3
// modification, are permitted provided that the following conditions are
4
// met:
5
//
6
//     * Redistributions of source code must retain the above copyright
7
//       notice, this list of conditions and the following disclaimer.
8
//     * Redistributions in binary form must reproduce the above
9
//       copyright notice, this list of conditions and the following
10
//       disclaimer in the documentation and/or other materials provided
11
//       with the distribution.
12
//     * Neither the name of Google Inc. nor the names of its
13
//       contributors may be used to endorse or promote products derived
14
//       from this software without specific prior written permission.
15
//
16
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27

    
28
// This module contains the platform-specific code. This make the rest of the
29
// code less dependent on operating system, compilers and runtime libraries.
30
// This module does specifically not deal with differences between different
31
// processor architecture.
32
// The platform classes have the same definition for all platforms. The
33
// implementation for a particular platform is put in platform_<os>.cc.
34
// The build system then uses the implementation for the target platform.
35
//
36
// This design has been chosen because it is simple and fast. Alternatively,
37
// the platform dependent classes could have been implemented using abstract
38
// superclasses with virtual methods and having specializations for each
39
// platform. This design was rejected because it was more complicated and
40
// slower. It would require factory methods for selecting the right
41
// implementation and the overhead of virtual methods for performance
42
// sensitive like mutex locking/unlocking.
43

    
44
#ifndef V8_PLATFORM_H_
45
#define V8_PLATFORM_H_
46

    
47
#include <cstdarg>
48

    
49
#include "platform/mutex.h"
50
#include "platform/semaphore.h"
51
#include "utils.h"
52
#include "v8globals.h"
53

    
54
#ifdef __sun
55
# ifndef signbit
56
namespace std {
57
int signbit(double x);
58
}
59
# endif
60
#endif
61

    
62
// Microsoft Visual C++ specific stuff.
63
#if V8_CC_MSVC
64

    
65
#include "win32-headers.h"
66
#include "win32-math.h"
67

    
68
int strncasecmp(const char* s1, const char* s2, int n);
69

    
70
// Visual C++ 2013 and higher implement this function.
71
#if (_MSC_VER < 1800)
72
inline int lrint(double flt) {
73
  int intgr;
74
#if V8_TARGET_ARCH_IA32
75
  __asm {
76
    fld flt
77
    fistp intgr
78
  };
79
#else
80
  intgr = static_cast<int>(flt + 0.5);
81
  if ((intgr & 1) != 0 && intgr - flt == 0.5) {
82
    // If the number is halfway between two integers, round to the even one.
83
    intgr--;
84
  }
85
#endif
86
  return intgr;
87
}
88

    
89
#endif  // _MSC_VER < 1800
90

    
91
#endif  // V8_CC_MSVC
92

    
93
namespace v8 {
94
namespace internal {
95

    
96
double ceiling(double x);
97
double modulo(double x, double y);
98

    
99
// Custom implementation of math functions.
100
double fast_sin(double input);
101
double fast_cos(double input);
102
double fast_tan(double input);
103
double fast_log(double input);
104
double fast_exp(double input);
105
double fast_sqrt(double input);
106
// The custom exp implementation needs 16KB of lookup data; initialize it
107
// on demand.
108
void lazily_initialize_fast_exp();
109

    
110
// ----------------------------------------------------------------------------
111
// Fast TLS support
112

    
113
#ifndef V8_NO_FAST_TLS
114

    
115
#if defined(_MSC_VER) && V8_HOST_ARCH_IA32
116

    
117
#define V8_FAST_TLS_SUPPORTED 1
118

    
119
INLINE(intptr_t InternalGetExistingThreadLocal(intptr_t index));
120

    
121
inline intptr_t InternalGetExistingThreadLocal(intptr_t index) {
122
  const intptr_t kTibInlineTlsOffset = 0xE10;
123
  const intptr_t kTibExtraTlsOffset = 0xF94;
124
  const intptr_t kMaxInlineSlots = 64;
125
  const intptr_t kMaxSlots = kMaxInlineSlots + 1024;
126
  ASSERT(0 <= index && index < kMaxSlots);
127
  if (index < kMaxInlineSlots) {
128
    return static_cast<intptr_t>(__readfsdword(kTibInlineTlsOffset +
129
                                               kPointerSize * index));
130
  }
131
  intptr_t extra = static_cast<intptr_t>(__readfsdword(kTibExtraTlsOffset));
132
  ASSERT(extra != 0);
133
  return *reinterpret_cast<intptr_t*>(extra +
134
                                      kPointerSize * (index - kMaxInlineSlots));
135
}
136

    
137
#elif defined(__APPLE__) && (V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64)
138

    
139
#define V8_FAST_TLS_SUPPORTED 1
140

    
141
extern intptr_t kMacTlsBaseOffset;
142

    
143
INLINE(intptr_t InternalGetExistingThreadLocal(intptr_t index));
144

    
145
inline intptr_t InternalGetExistingThreadLocal(intptr_t index) {
146
  intptr_t result;
147
#if V8_HOST_ARCH_IA32
148
  asm("movl %%gs:(%1,%2,4), %0;"
149
      :"=r"(result)  // Output must be a writable register.
150
      :"r"(kMacTlsBaseOffset), "r"(index));
151
#else
152
  asm("movq %%gs:(%1,%2,8), %0;"
153
      :"=r"(result)
154
      :"r"(kMacTlsBaseOffset), "r"(index));
155
#endif
156
  return result;
157
}
158

    
159
#endif
160

    
161
#endif  // V8_NO_FAST_TLS
162

    
163

    
164
// ----------------------------------------------------------------------------
165
// OS
166
//
167
// This class has static methods for the different platform specific
168
// functions. Add methods here to cope with differences between the
169
// supported platforms.
170

    
171
class OS {
172
 public:
173
  // Initializes the platform OS support that depend on CPU features. This is
174
  // called after CPU initialization.
175
  static void PostSetUp();
176

    
177
  // Returns the accumulated user time for thread. This routine
178
  // can be used for profiling. The implementation should
179
  // strive for high-precision timer resolution, preferable
180
  // micro-second resolution.
181
  static int GetUserTime(uint32_t* secs,  uint32_t* usecs);
182

    
183
  // Returns current time as the number of milliseconds since
184
  // 00:00:00 UTC, January 1, 1970.
185
  static double TimeCurrentMillis();
186

    
187
  // Returns a string identifying the current time zone. The
188
  // timestamp is used for determining if DST is in effect.
189
  static const char* LocalTimezone(double time);
190

    
191
  // Returns the local time offset in milliseconds east of UTC without
192
  // taking daylight savings time into account.
193
  static double LocalTimeOffset();
194

    
195
  // Returns the daylight savings offset for the given time.
196
  static double DaylightSavingsOffset(double time);
197

    
198
  // Returns last OS error.
199
  static int GetLastError();
200

    
201
  static FILE* FOpen(const char* path, const char* mode);
202
  static bool Remove(const char* path);
203

    
204
  // Opens a temporary file, the file is auto removed on close.
205
  static FILE* OpenTemporaryFile();
206

    
207
  // Log file open mode is platform-dependent due to line ends issues.
208
  static const char* const LogFileOpenMode;
209

    
210
  // Print output to console. This is mostly used for debugging output.
211
  // On platforms that has standard terminal output, the output
212
  // should go to stdout.
213
  static void Print(const char* format, ...);
214
  static void VPrint(const char* format, va_list args);
215

    
216
  // Print output to a file. This is mostly used for debugging output.
217
  static void FPrint(FILE* out, const char* format, ...);
218
  static void VFPrint(FILE* out, const char* format, va_list args);
219

    
220
  // Print error output to console. This is mostly used for error message
221
  // output. On platforms that has standard terminal output, the output
222
  // should go to stderr.
223
  static void PrintError(const char* format, ...);
224
  static void VPrintError(const char* format, va_list args);
225

    
226
  // Allocate/Free memory used by JS heap. Pages are readable/writable, but
227
  // they are not guaranteed to be executable unless 'executable' is true.
228
  // Returns the address of allocated memory, or NULL if failed.
229
  static void* Allocate(const size_t requested,
230
                        size_t* allocated,
231
                        bool is_executable);
232
  static void Free(void* address, const size_t size);
233

    
234
  // This is the granularity at which the ProtectCode(...) call can set page
235
  // permissions.
236
  static intptr_t CommitPageSize();
237

    
238
  // Mark code segments non-writable.
239
  static void ProtectCode(void* address, const size_t size);
240

    
241
  // Assign memory as a guard page so that access will cause an exception.
242
  static void Guard(void* address, const size_t size);
243

    
244
  // Generate a random address to be used for hinting mmap().
245
  static void* GetRandomMmapAddr();
246

    
247
  // Get the Alignment guaranteed by Allocate().
248
  static size_t AllocateAlignment();
249

    
250
  // Sleep for a number of milliseconds.
251
  static void Sleep(const int milliseconds);
252

    
253
  // Abort the current process.
254
  static void Abort();
255

    
256
  // Debug break.
257
  static void DebugBreak();
258

    
259
  // Walk the stack.
260
  static const int kStackWalkError = -1;
261
  static const int kStackWalkMaxNameLen = 256;
262
  static const int kStackWalkMaxTextLen = 256;
263
  struct StackFrame {
264
    void* address;
265
    char text[kStackWalkMaxTextLen];
266
  };
267

    
268
  class MemoryMappedFile {
269
   public:
270
    static MemoryMappedFile* open(const char* name);
271
    static MemoryMappedFile* create(const char* name, int size, void* initial);
272
    virtual ~MemoryMappedFile() { }
273
    virtual void* memory() = 0;
274
    virtual int size() = 0;
275
  };
276

    
277
  // Safe formatting print. Ensures that str is always null-terminated.
278
  // Returns the number of chars written, or -1 if output was truncated.
279
  static int SNPrintF(Vector<char> str, const char* format, ...);
280
  static int VSNPrintF(Vector<char> str,
281
                       const char* format,
282
                       va_list args);
283

    
284
  static char* StrChr(char* str, int c);
285
  static void StrNCpy(Vector<char> dest, const char* src, size_t n);
286

    
287
  // Support for the profiler.  Can do nothing, in which case ticks
288
  // occuring in shared libraries will not be properly accounted for.
289
  static void LogSharedLibraryAddresses(Isolate* isolate);
290

    
291
  // Support for the profiler.  Notifies the external profiling
292
  // process that a code moving garbage collection starts.  Can do
293
  // nothing, in which case the code objects must not move (e.g., by
294
  // using --never-compact) if accurate profiling is desired.
295
  static void SignalCodeMovingGC();
296

    
297
  // The return value indicates the CPU features we are sure of because of the
298
  // OS.  For example MacOSX doesn't run on any x86 CPUs that don't have SSE2
299
  // instructions.
300
  // This is a little messy because the interpretation is subject to the cross
301
  // of the CPU and the OS.  The bits in the answer correspond to the bit
302
  // positions indicated by the members of the CpuFeature enum from globals.h
303
  static uint64_t CpuFeaturesImpliedByPlatform();
304

    
305
  // The total amount of physical memory available on the current system.
306
  static uint64_t TotalPhysicalMemory();
307

    
308
  // Maximum size of the virtual memory.  0 means there is no artificial
309
  // limit.
310
  static intptr_t MaxVirtualMemory();
311

    
312
  // Returns the double constant NAN
313
  static double nan_value();
314

    
315
  // Support runtime detection of whether the hard float option of the
316
  // EABI is used.
317
  static bool ArmUsingHardFloat();
318

    
319
  // Returns the activation frame alignment constraint or zero if
320
  // the platform doesn't care. Guaranteed to be a power of two.
321
  static int ActivationFrameAlignment();
322

    
323
#if defined(V8_TARGET_ARCH_IA32)
324
  // Limit below which the extra overhead of the MemCopy function is likely
325
  // to outweigh the benefits of faster copying.
326
  static const int kMinComplexMemCopy = 64;
327

    
328
  // Copy memory area. No restrictions.
329
  static void MemMove(void* dest, const void* src, size_t size);
330
  typedef void (*MemMoveFunction)(void* dest, const void* src, size_t size);
331

    
332
  // Keep the distinction of "move" vs. "copy" for the benefit of other
333
  // architectures.
334
  static void MemCopy(void* dest, const void* src, size_t size) {
335
    MemMove(dest, src, size);
336
  }
337
#elif defined(V8_HOST_ARCH_ARM)
338
  typedef void (*MemCopyUint8Function)(uint8_t* dest,
339
                                       const uint8_t* src,
340
                                       size_t size);
341
  static MemCopyUint8Function memcopy_uint8_function;
342
  static void MemCopyUint8Wrapper(uint8_t* dest,
343
                                  const uint8_t* src,
344
                                  size_t chars) {
345
    memcpy(dest, src, chars);
346
  }
347
  // For values < 16, the assembler function is slower than the inlined C code.
348
  static const int kMinComplexMemCopy = 16;
349
  static void MemCopy(void* dest, const void* src, size_t size) {
350
    (*memcopy_uint8_function)(reinterpret_cast<uint8_t*>(dest),
351
                              reinterpret_cast<const uint8_t*>(src),
352
                              size);
353
  }
354
  static void MemMove(void* dest, const void* src, size_t size) {
355
    memmove(dest, src, size);
356
  }
357

    
358
  typedef void (*MemCopyUint16Uint8Function)(uint16_t* dest,
359
                                             const uint8_t* src,
360
                                             size_t size);
361
  static MemCopyUint16Uint8Function memcopy_uint16_uint8_function;
362
  static void MemCopyUint16Uint8Wrapper(uint16_t* dest,
363
                                        const uint8_t* src,
364
                                        size_t chars);
365
  // For values < 12, the assembler function is slower than the inlined C code.
366
  static const int kMinComplexConvertMemCopy = 12;
367
  static void MemCopyUint16Uint8(uint16_t* dest,
368
                                 const uint8_t* src,
369
                                 size_t size) {
370
    (*memcopy_uint16_uint8_function)(dest, src, size);
371
  }
372
#else
373
  // Copy memory area to disjoint memory area.
374
  static void MemCopy(void* dest, const void* src, size_t size) {
375
    memcpy(dest, src, size);
376
  }
377
  static void MemMove(void* dest, const void* src, size_t size) {
378
    memmove(dest, src, size);
379
  }
380
  static const int kMinComplexMemCopy = 16 * kPointerSize;
381
#endif  // V8_TARGET_ARCH_IA32
382

    
383
  static int GetCurrentProcessId();
384

    
385
 private:
386
  static const int msPerSecond = 1000;
387

    
388
  DISALLOW_IMPLICIT_CONSTRUCTORS(OS);
389
};
390

    
391
// Represents and controls an area of reserved memory.
392
// Control of the reserved memory can be assigned to another VirtualMemory
393
// object by assignment or copy-contructing. This removes the reserved memory
394
// from the original object.
395
class VirtualMemory {
396
 public:
397
  // Empty VirtualMemory object, controlling no reserved memory.
398
  VirtualMemory();
399

    
400
  // Reserves virtual memory with size.
401
  explicit VirtualMemory(size_t size);
402

    
403
  // Reserves virtual memory containing an area of the given size that
404
  // is aligned per alignment. This may not be at the position returned
405
  // by address().
406
  VirtualMemory(size_t size, size_t alignment);
407

    
408
  // Releases the reserved memory, if any, controlled by this VirtualMemory
409
  // object.
410
  ~VirtualMemory();
411

    
412
  // Returns whether the memory has been reserved.
413
  bool IsReserved();
414

    
415
  // Initialize or resets an embedded VirtualMemory object.
416
  void Reset();
417

    
418
  // Returns the start address of the reserved memory.
419
  // If the memory was reserved with an alignment, this address is not
420
  // necessarily aligned. The user might need to round it up to a multiple of
421
  // the alignment to get the start of the aligned block.
422
  void* address() {
423
    ASSERT(IsReserved());
424
    return address_;
425
  }
426

    
427
  // Returns the size of the reserved memory. The returned value is only
428
  // meaningful when IsReserved() returns true.
429
  // If the memory was reserved with an alignment, this size may be larger
430
  // than the requested size.
431
  size_t size() { return size_; }
432

    
433
  // Commits real memory. Returns whether the operation succeeded.
434
  bool Commit(void* address, size_t size, bool is_executable);
435

    
436
  // Uncommit real memory.  Returns whether the operation succeeded.
437
  bool Uncommit(void* address, size_t size);
438

    
439
  // Creates a single guard page at the given address.
440
  bool Guard(void* address);
441

    
442
  void Release() {
443
    ASSERT(IsReserved());
444
    // Notice: Order is important here. The VirtualMemory object might live
445
    // inside the allocated region.
446
    void* address = address_;
447
    size_t size = size_;
448
    Reset();
449
    bool result = ReleaseRegion(address, size);
450
    USE(result);
451
    ASSERT(result);
452
  }
453

    
454
  // Assign control of the reserved region to a different VirtualMemory object.
455
  // The old object is no longer functional (IsReserved() returns false).
456
  void TakeControl(VirtualMemory* from) {
457
    ASSERT(!IsReserved());
458
    address_ = from->address_;
459
    size_ = from->size_;
460
    from->Reset();
461
  }
462

    
463
  static void* ReserveRegion(size_t size);
464

    
465
  static bool CommitRegion(void* base, size_t size, bool is_executable);
466

    
467
  static bool UncommitRegion(void* base, size_t size);
468

    
469
  // Must be called with a base pointer that has been returned by ReserveRegion
470
  // and the same size it was reserved with.
471
  static bool ReleaseRegion(void* base, size_t size);
472

    
473
  // Returns true if OS performs lazy commits, i.e. the memory allocation call
474
  // defers actual physical memory allocation till the first memory access.
475
  // Otherwise returns false.
476
  static bool HasLazyCommits();
477

    
478
 private:
479
  void* address_;  // Start address of the virtual memory.
480
  size_t size_;  // Size of the virtual memory.
481
};
482

    
483

    
484
// ----------------------------------------------------------------------------
485
// Thread
486
//
487
// Thread objects are used for creating and running threads. When the start()
488
// method is called the new thread starts running the run() method in the new
489
// thread. The Thread object should not be deallocated before the thread has
490
// terminated.
491

    
492
class Thread {
493
 public:
494
  // Opaque data type for thread-local storage keys.
495
  // LOCAL_STORAGE_KEY_MIN_VALUE and LOCAL_STORAGE_KEY_MAX_VALUE are specified
496
  // to ensure that enumeration type has correct value range (see Issue 830 for
497
  // more details).
498
  enum LocalStorageKey {
499
    LOCAL_STORAGE_KEY_MIN_VALUE = kMinInt,
500
    LOCAL_STORAGE_KEY_MAX_VALUE = kMaxInt
501
  };
502

    
503
  class Options {
504
   public:
505
    Options() : name_("v8:<unknown>"), stack_size_(0) {}
506
    Options(const char* name, int stack_size = 0)
507
        : name_(name), stack_size_(stack_size) {}
508

    
509
    const char* name() const { return name_; }
510
    int stack_size() const { return stack_size_; }
511

    
512
   private:
513
    const char* name_;
514
    int stack_size_;
515
  };
516

    
517
  // Create new thread.
518
  explicit Thread(const Options& options);
519
  virtual ~Thread();
520

    
521
  // Start new thread by calling the Run() method on the new thread.
522
  void Start();
523

    
524
  // Start new thread and wait until Run() method is called on the new thread.
525
  void StartSynchronously() {
526
    start_semaphore_ = new Semaphore(0);
527
    Start();
528
    start_semaphore_->Wait();
529
    delete start_semaphore_;
530
    start_semaphore_ = NULL;
531
  }
532

    
533
  // Wait until thread terminates.
534
  void Join();
535

    
536
  inline const char* name() const {
537
    return name_;
538
  }
539

    
540
  // Abstract method for run handler.
541
  virtual void Run() = 0;
542

    
543
  // Thread-local storage.
544
  static LocalStorageKey CreateThreadLocalKey();
545
  static void DeleteThreadLocalKey(LocalStorageKey key);
546
  static void* GetThreadLocal(LocalStorageKey key);
547
  static int GetThreadLocalInt(LocalStorageKey key) {
548
    return static_cast<int>(reinterpret_cast<intptr_t>(GetThreadLocal(key)));
549
  }
550
  static void SetThreadLocal(LocalStorageKey key, void* value);
551
  static void SetThreadLocalInt(LocalStorageKey key, int value) {
552
    SetThreadLocal(key, reinterpret_cast<void*>(static_cast<intptr_t>(value)));
553
  }
554
  static bool HasThreadLocal(LocalStorageKey key) {
555
    return GetThreadLocal(key) != NULL;
556
  }
557

    
558
#ifdef V8_FAST_TLS_SUPPORTED
559
  static inline void* GetExistingThreadLocal(LocalStorageKey key) {
560
    void* result = reinterpret_cast<void*>(
561
        InternalGetExistingThreadLocal(static_cast<intptr_t>(key)));
562
    ASSERT(result == GetThreadLocal(key));
563
    return result;
564
  }
565
#else
566
  static inline void* GetExistingThreadLocal(LocalStorageKey key) {
567
    return GetThreadLocal(key);
568
  }
569
#endif
570

    
571
  // A hint to the scheduler to let another thread run.
572
  static void YieldCPU();
573

    
574

    
575
  // The thread name length is limited to 16 based on Linux's implementation of
576
  // prctl().
577
  static const int kMaxThreadNameLength = 16;
578

    
579
  class PlatformData;
580
  PlatformData* data() { return data_; }
581

    
582
  void NotifyStartedAndRun() {
583
    if (start_semaphore_) start_semaphore_->Signal();
584
    Run();
585
  }
586

    
587
 private:
588
  void set_name(const char* name);
589

    
590
  PlatformData* data_;
591

    
592
  char name_[kMaxThreadNameLength];
593
  int stack_size_;
594
  Semaphore* start_semaphore_;
595

    
596
  DISALLOW_COPY_AND_ASSIGN(Thread);
597
};
598

    
599
} }  // namespace v8::internal
600

    
601
#endif  // V8_PLATFORM_H_