LCOV - code coverage report
Current view: top level - src/base/platform - platform.h (source / functions) Hit Total Coverage
Test: app.info Lines: 38 42 90.5 %
Date: 2017-04-26 Functions: 5 7 71.4 %

          Line data    Source code
       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/base-export.h"
      29             : #include "src/base/build_config.h"
      30             : #include "src/base/compiler-specific.h"
      31             : #include "src/base/platform/mutex.h"
      32             : #include "src/base/platform/semaphore.h"
      33             : 
      34             : #if V8_OS_QNX
      35             : #include "src/base/qnx-math.h"
      36             : #endif
      37             : 
      38             : namespace v8 {
      39             : namespace base {
      40             : 
      41             : // ----------------------------------------------------------------------------
      42             : // Fast TLS support
      43             : 
      44             : #ifndef V8_NO_FAST_TLS
      45             : 
      46             : #if V8_CC_MSVC && V8_HOST_ARCH_IA32
      47             : 
      48             : #define V8_FAST_TLS_SUPPORTED 1
      49             : 
      50             : INLINE(intptr_t InternalGetExistingThreadLocal(intptr_t index));
      51             : 
      52             : inline intptr_t InternalGetExistingThreadLocal(intptr_t index) {
      53             :   const intptr_t kTibInlineTlsOffset = 0xE10;
      54             :   const intptr_t kTibExtraTlsOffset = 0xF94;
      55             :   const intptr_t kMaxInlineSlots = 64;
      56             :   const intptr_t kMaxSlots = kMaxInlineSlots + 1024;
      57             :   const intptr_t kPointerSize = sizeof(void*);
      58             :   DCHECK(0 <= index && index < kMaxSlots);
      59             :   USE(kMaxSlots);
      60             :   if (index < kMaxInlineSlots) {
      61             :     return static_cast<intptr_t>(__readfsdword(kTibInlineTlsOffset +
      62             :                                                kPointerSize * index));
      63             :   }
      64             :   intptr_t extra = static_cast<intptr_t>(__readfsdword(kTibExtraTlsOffset));
      65             :   DCHECK(extra != 0);
      66             :   return *reinterpret_cast<intptr_t*>(extra +
      67             :                                       kPointerSize * (index - kMaxInlineSlots));
      68             : }
      69             : 
      70             : #elif defined(__APPLE__) && (V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64)
      71             : 
      72             : #define V8_FAST_TLS_SUPPORTED 1
      73             : 
      74             : extern V8_BASE_EXPORT intptr_t kMacTlsBaseOffset;
      75             : 
      76             : INLINE(intptr_t InternalGetExistingThreadLocal(intptr_t index));
      77             : 
      78             : inline intptr_t InternalGetExistingThreadLocal(intptr_t index) {
      79             :   intptr_t result;
      80             : #if V8_HOST_ARCH_IA32
      81             :   asm("movl %%gs:(%1,%2,4), %0;"
      82             :       :"=r"(result)  // Output must be a writable register.
      83             :       :"r"(kMacTlsBaseOffset), "r"(index));
      84             : #else
      85             :   asm("movq %%gs:(%1,%2,8), %0;"
      86             :       :"=r"(result)
      87             :       :"r"(kMacTlsBaseOffset), "r"(index));
      88             : #endif
      89             :   return result;
      90             : }
      91             : 
      92             : #endif
      93             : 
      94             : #endif  // V8_NO_FAST_TLS
      95             : 
      96             : 
      97             : class TimezoneCache;
      98             : 
      99             : 
     100             : // ----------------------------------------------------------------------------
     101             : // OS
     102             : //
     103             : // This class has static methods for the different platform specific
     104             : // functions. Add methods here to cope with differences between the
     105             : // supported platforms.
     106             : 
     107             : class V8_BASE_EXPORT OS {
     108             :  public:
     109             :   // Initialize the OS class.
     110             :   // - random_seed: Used for the GetRandomMmapAddress() if non-zero.
     111             :   // - hard_abort: If true, OS::Abort() will crash instead of aborting.
     112             :   // - gc_fake_mmap: Name of the file for fake gc mmap used in ll_prof.
     113             :   static void Initialize(int64_t random_seed,
     114             :                          bool hard_abort,
     115             :                          const char* const gc_fake_mmap);
     116             : 
     117             :   // Returns the accumulated user time for thread. This routine
     118             :   // can be used for profiling. The implementation should
     119             :   // strive for high-precision timer resolution, preferable
     120             :   // micro-second resolution.
     121             :   static int GetUserTime(uint32_t* secs,  uint32_t* usecs);
     122             : 
     123             :   // Returns current time as the number of milliseconds since
     124             :   // 00:00:00 UTC, January 1, 1970.
     125             :   static double TimeCurrentMillis();
     126             : 
     127             :   static TimezoneCache* CreateTimezoneCache();
     128             : 
     129             :   // Returns last OS error.
     130             :   static int GetLastError();
     131             : 
     132             :   static FILE* FOpen(const char* path, const char* mode);
     133             :   static bool Remove(const char* path);
     134             : 
     135             :   static char DirectorySeparator();
     136             :   static bool isDirectorySeparator(const char ch);
     137             : 
     138             :   // Opens a temporary file, the file is auto removed on close.
     139             :   static FILE* OpenTemporaryFile();
     140             : 
     141             :   // Log file open mode is platform-dependent due to line ends issues.
     142             :   static const char* const LogFileOpenMode;
     143             : 
     144             :   // Print output to console. This is mostly used for debugging output.
     145             :   // On platforms that has standard terminal output, the output
     146             :   // should go to stdout.
     147             :   static PRINTF_FORMAT(1, 2) void Print(const char* format, ...);
     148             :   static PRINTF_FORMAT(1, 0) void VPrint(const char* format, va_list args);
     149             : 
     150             :   // Print output to a file. This is mostly used for debugging output.
     151             :   static PRINTF_FORMAT(2, 3) void FPrint(FILE* out, const char* format, ...);
     152             :   static PRINTF_FORMAT(2, 0) void VFPrint(FILE* out, const char* format,
     153             :                                           va_list args);
     154             : 
     155             :   // Print error output to console. This is mostly used for error message
     156             :   // output. On platforms that has standard terminal output, the output
     157             :   // should go to stderr.
     158             :   static PRINTF_FORMAT(1, 2) void PrintError(const char* format, ...);
     159             :   static PRINTF_FORMAT(1, 0) void VPrintError(const char* format, va_list args);
     160             : 
     161             :   // Allocate/Free memory used by JS heap. Pages are readable/writable, but
     162             :   // they are not guaranteed to be executable unless 'executable' is true.
     163             :   // Returns the address of allocated memory, or NULL if failed.
     164             :   static void* Allocate(const size_t requested,
     165             :                         size_t* allocated,
     166             :                         bool is_executable);
     167             :   static void Free(void* address, const size_t size);
     168             : 
     169             :   // Allocates a region of memory that is inaccessible. On Windows this reserves
     170             :   // but does not commit the memory. On Linux, it is equivalent to a call to
     171             :   // Allocate() followed by Guard().
     172             :   static void* AllocateGuarded(const size_t requested);
     173             : 
     174             :   // This is the granularity at which the ProtectCode(...) call can set page
     175             :   // permissions.
     176             :   static intptr_t CommitPageSize();
     177             : 
     178             :   // Mark code segments non-writable.
     179             :   static void ProtectCode(void* address, const size_t size);
     180             : 
     181             :   // Assign memory as a guard page so that access will cause an exception.
     182             :   static void Guard(void* address, const size_t size);
     183             : 
     184             :   // Make a region of memory readable and writable.
     185             :   static void Unprotect(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 specified time interval.
     194             :   static void Sleep(TimeDelta interval);
     195             : 
     196             :   // Abort the current process.
     197             :   V8_NORETURN 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           0 :   class V8_BASE_EXPORT MemoryMappedFile {
     212             :    public:
     213           0 :     virtual ~MemoryMappedFile() {}
     214             :     virtual void* memory() const = 0;
     215             :     virtual size_t size() const = 0;
     216             : 
     217             :     static MemoryMappedFile* open(const char* name);
     218             :     static MemoryMappedFile* create(const char* name, size_t size,
     219             :                                     void* initial);
     220             :   };
     221             : 
     222             :   // Safe formatting print. Ensures that str is always null-terminated.
     223             :   // Returns the number of chars written, or -1 if output was truncated.
     224             :   static PRINTF_FORMAT(3, 4) int SNPrintF(char* str, int length,
     225             :                                           const char* format, ...);
     226             :   static PRINTF_FORMAT(3, 0) int VSNPrintF(char* str, int length,
     227             :                                            const char* format, va_list args);
     228             : 
     229             :   static char* StrChr(char* str, int c);
     230             :   static void StrNCpy(char* dest, int length, const char* src, size_t n);
     231             : 
     232             :   // Support for the profiler.  Can do nothing, in which case ticks
     233             :   // occuring in shared libraries will not be properly accounted for.
     234           0 :   struct SharedLibraryAddress {
     235             :     SharedLibraryAddress(const std::string& library_path, uintptr_t start,
     236             :                          uintptr_t end)
     237           0 :         : library_path(library_path), start(start), end(end), aslr_slide(0) {}
     238             :     SharedLibraryAddress(const std::string& library_path, uintptr_t start,
     239             :                          uintptr_t end, intptr_t aslr_slide)
     240             :         : library_path(library_path),
     241             :           start(start),
     242             :           end(end),
     243             :           aslr_slide(aslr_slide) {}
     244             : 
     245             :     std::string library_path;
     246             :     uintptr_t start;
     247             :     uintptr_t end;
     248             :     intptr_t aslr_slide;
     249             :   };
     250             : 
     251             :   static std::vector<SharedLibraryAddress> GetSharedLibraryAddresses();
     252             : 
     253             :   // Support for the profiler.  Notifies the external profiling
     254             :   // process that a code moving garbage collection starts.  Can do
     255             :   // nothing, in which case the code objects must not move (e.g., by
     256             :   // using --never-compact) if accurate profiling is desired.
     257             :   static void SignalCodeMovingGC();
     258             : 
     259             :   // Support runtime detection of whether the hard float option of the
     260             :   // EABI is used.
     261             :   static bool ArmUsingHardFloat();
     262             : 
     263             :   // Returns the activation frame alignment constraint or zero if
     264             :   // the platform doesn't care. Guaranteed to be a power of two.
     265             :   static int ActivationFrameAlignment();
     266             : 
     267             :   static int GetCurrentProcessId();
     268             : 
     269             :   static int GetCurrentThreadId();
     270             : 
     271             :  private:
     272             :   static const int msPerSecond = 1000;
     273             : 
     274             : #if V8_OS_POSIX
     275             :   static const char* GetGCFakeMMapFile();
     276             : #endif
     277             : 
     278             :   DISALLOW_IMPLICIT_CONSTRUCTORS(OS);
     279             : };
     280             : 
     281             : 
     282             : // Represents and controls an area of reserved memory.
     283             : // Control of the reserved memory can be assigned to another VirtualMemory
     284             : // object by assignment or copy-contructing. This removes the reserved memory
     285             : // from the original object.
     286             : class V8_BASE_EXPORT VirtualMemory {
     287             :  public:
     288             :   // Empty VirtualMemory object, controlling no reserved memory.
     289             :   VirtualMemory();
     290             : 
     291             :   // Reserves virtual memory with size.
     292             :   explicit VirtualMemory(size_t size);
     293             : 
     294             :   // Reserves virtual memory containing an area of the given size that
     295             :   // is aligned per alignment. This may not be at the position returned
     296             :   // by address().
     297             :   VirtualMemory(size_t size, size_t alignment);
     298             : 
     299             :   // Construct a virtual memory by assigning it some already mapped address
     300             :   // and size.
     301       15980 :   VirtualMemory(void* address, size_t size) : address_(address), size_(size) {}
     302             : 
     303             :   // Releases the reserved memory, if any, controlled by this VirtualMemory
     304             :   // object.
     305             :   ~VirtualMemory();
     306             : 
     307             :   // Returns whether the memory has been reserved.
     308             :   bool IsReserved();
     309             : 
     310             :   // Initialize or resets an embedded VirtualMemory object.
     311             :   void Reset();
     312             : 
     313             :   // Returns the start address of the reserved memory.
     314             :   // If the memory was reserved with an alignment, this address is not
     315             :   // necessarily aligned. The user might need to round it up to a multiple of
     316             :   // the alignment to get the start of the aligned block.
     317             :   void* address() {
     318             :     DCHECK(IsReserved());
     319             :     return address_;
     320             :   }
     321             : 
     322             :   // Returns the size of the reserved memory. The returned value is only
     323             :   // meaningful when IsReserved() returns true.
     324             :   // If the memory was reserved with an alignment, this size may be larger
     325             :   // than the requested size.
     326             :   size_t size() { return size_; }
     327             : 
     328             :   // Commits real memory. Returns whether the operation succeeded.
     329             :   bool Commit(void* address, size_t size, bool is_executable);
     330             : 
     331             :   // Uncommit real memory.  Returns whether the operation succeeded.
     332             :   bool Uncommit(void* address, size_t size);
     333             : 
     334             :   // Creates a single guard page at the given address.
     335             :   bool Guard(void* address);
     336             : 
     337             :   // Releases the memory after |free_start|.
     338          37 :   void ReleasePartial(void* free_start) {
     339             :     DCHECK(IsReserved());
     340             :     // Notice: Order is important here. The VirtualMemory object might live
     341             :     // inside the allocated region.
     342          37 :     size_t size = size_ - (reinterpret_cast<size_t>(free_start) -
     343          37 :                            reinterpret_cast<size_t>(address_));
     344          37 :     CHECK(InVM(free_start, size));
     345             :     DCHECK_LT(address_, free_start);
     346             :     DCHECK_LT(free_start, reinterpret_cast<void*>(
     347             :                               reinterpret_cast<size_t>(address_) + size_));
     348          37 :     bool result = ReleasePartialRegion(address_, size_, free_start, size);
     349             :     USE(result);
     350             :     DCHECK(result);
     351          37 :     size_ -= size;
     352          37 :   }
     353             : 
     354      300525 :   void Release() {
     355             :     DCHECK(IsReserved());
     356             :     // Notice: Order is important here. The VirtualMemory object might live
     357             :     // inside the allocated region.
     358      300525 :     void* address = address_;
     359      300525 :     size_t size = size_;
     360      300525 :     CHECK(InVM(address, size));
     361      300525 :     Reset();
     362      300527 :     bool result = ReleaseRegion(address, size);
     363             :     USE(result);
     364             :     DCHECK(result);
     365      300532 :   }
     366             : 
     367             :   // Assign control of the reserved region to a different VirtualMemory object.
     368             :   // The old object is no longer functional (IsReserved() returns false).
     369             :   void TakeControl(VirtualMemory* from) {
     370             :     DCHECK(!IsReserved());
     371     1860532 :     address_ = from->address_;
     372     1860532 :     size_ = from->size_;
     373     1860532 :     from->Reset();
     374             :   }
     375             : 
     376             :   static void* ReserveRegion(size_t size);
     377             : 
     378             :   static bool CommitRegion(void* base, size_t size, bool is_executable);
     379             : 
     380             :   static bool UncommitRegion(void* base, size_t size);
     381             : 
     382             :   // Must be called with a base pointer that has been returned by ReserveRegion
     383             :   // and the same size it was reserved with.
     384             :   static bool ReleaseRegion(void* base, size_t size);
     385             : 
     386             :   // Must be called with a base pointer that has been returned by ReserveRegion
     387             :   // and the same size it was reserved with.
     388             :   // [free_start, free_start + free_size] is the memory that will be released.
     389             :   static bool ReleasePartialRegion(void* base, size_t size, void* free_start,
     390             :                                    size_t free_size);
     391             : 
     392             :   // Returns true if OS performs lazy commits, i.e. the memory allocation call
     393             :   // defers actual physical memory allocation till the first memory access.
     394             :   // Otherwise returns false.
     395             :   static bool HasLazyCommits();
     396             : 
     397             :  private:
     398             :   bool InVM(void* address, size_t size) {
     399     2665826 :     return (reinterpret_cast<uintptr_t>(address_) <=
     400     5331725 :             reinterpret_cast<uintptr_t>(address)) &&
     401     2665862 :            ((reinterpret_cast<uintptr_t>(address_) + size_) >=
     402     2665862 :             (reinterpret_cast<uintptr_t>(address) + size));
     403             :   }
     404             : 
     405             :   void* address_;  // Start address of the virtual memory.
     406             :   size_t size_;  // Size of the virtual memory.
     407             : };
     408             : 
     409             : 
     410             : // ----------------------------------------------------------------------------
     411             : // Thread
     412             : //
     413             : // Thread objects are used for creating and running threads. When the start()
     414             : // method is called the new thread starts running the run() method in the new
     415             : // thread. The Thread object should not be deallocated before the thread has
     416             : // terminated.
     417             : 
     418             : class V8_BASE_EXPORT Thread {
     419             :  public:
     420             :   // Opaque data type for thread-local storage keys.
     421             :   typedef int32_t LocalStorageKey;
     422             : 
     423             :   class Options {
     424             :    public:
     425             :     Options() : name_("v8:<unknown>"), stack_size_(0) {}
     426             :     explicit Options(const char* name, int stack_size = 0)
     427      478108 :         : name_(name), stack_size_(stack_size) {}
     428             : 
     429             :     const char* name() const { return name_; }
     430             :     int stack_size() const { return stack_size_; }
     431             : 
     432             :    private:
     433             :     const char* name_;
     434             :     int stack_size_;
     435             :   };
     436             : 
     437             :   // Create new thread.
     438             :   explicit Thread(const Options& options);
     439             :   virtual ~Thread();
     440             : 
     441             :   // Start new thread by calling the Run() method on the new thread.
     442             :   void Start();
     443             : 
     444             :   // Start new thread and wait until Run() method is called on the new thread.
     445         294 :   void StartSynchronously() {
     446         294 :     start_semaphore_ = new Semaphore(0);
     447         294 :     Start();
     448         294 :     start_semaphore_->Wait();
     449         294 :     delete start_semaphore_;
     450         294 :     start_semaphore_ = NULL;
     451         294 :   }
     452             : 
     453             :   // Wait until thread terminates.
     454             :   void Join();
     455             : 
     456             :   inline const char* name() const {
     457             :     return name_;
     458             :   }
     459             : 
     460             :   // Abstract method for run handler.
     461             :   virtual void Run() = 0;
     462             : 
     463             :   // Thread-local storage.
     464             :   static LocalStorageKey CreateThreadLocalKey();
     465             :   static void DeleteThreadLocalKey(LocalStorageKey key);
     466             :   static void* GetThreadLocal(LocalStorageKey key);
     467             :   static int GetThreadLocalInt(LocalStorageKey key) {
     468     3376670 :     return static_cast<int>(reinterpret_cast<intptr_t>(GetThreadLocal(key)));
     469             :   }
     470             :   static void SetThreadLocal(LocalStorageKey key, void* value);
     471             :   static void SetThreadLocalInt(LocalStorageKey key, int value) {
     472       77847 :     SetThreadLocal(key, reinterpret_cast<void*>(static_cast<intptr_t>(value)));
     473             :   }
     474             :   static bool HasThreadLocal(LocalStorageKey key) {
     475             :     return GetThreadLocal(key) != NULL;
     476             :   }
     477             : 
     478             : #ifdef V8_FAST_TLS_SUPPORTED
     479             :   static inline void* GetExistingThreadLocal(LocalStorageKey key) {
     480             :     void* result = reinterpret_cast<void*>(
     481             :         InternalGetExistingThreadLocal(static_cast<intptr_t>(key)));
     482             :     DCHECK(result == GetThreadLocal(key));
     483             :     return result;
     484             :   }
     485             : #else
     486    12382412 :   static inline void* GetExistingThreadLocal(LocalStorageKey key) {
     487    12382412 :     return GetThreadLocal(key);
     488             :   }
     489             : #endif
     490             : 
     491             :   // The thread name length is limited to 16 based on Linux's implementation of
     492             :   // prctl().
     493             :   static const int kMaxThreadNameLength = 16;
     494             : 
     495             :   class PlatformData;
     496             :   PlatformData* data() { return data_; }
     497             : 
     498      426023 :   void NotifyStartedAndRun() {
     499      426023 :     if (start_semaphore_) start_semaphore_->Signal();
     500      426023 :     Run();
     501      421477 :   }
     502             : 
     503             :  private:
     504             :   void set_name(const char* name);
     505             : 
     506             :   PlatformData* data_;
     507             : 
     508             :   char name_[kMaxThreadNameLength];
     509             :   int stack_size_;
     510             :   Semaphore* start_semaphore_;
     511             : 
     512             :   DISALLOW_COPY_AND_ASSIGN(Thread);
     513             : };
     514             : 
     515             : }  // namespace base
     516             : }  // namespace v8
     517             : 
     518             : #endif  // V8_BASE_PLATFORM_PLATFORM_H_

Generated by: LCOV version 1.10