LCOV - code coverage report
Current view: top level - src/base/platform - platform.h (source / functions) Hit Total Coverage
Test: app.info Lines: 17 21 81.0 %
Date: 2017-10-20 Functions: 3 5 60.0 %

          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_NE(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, bool hard_abort,
     114             :                          const char* const gc_fake_mmap);
     115             : 
     116             :   // Returns the accumulated user time for thread. This routine
     117             :   // can be used for profiling. The implementation should
     118             :   // strive for high-precision timer resolution, preferable
     119             :   // micro-second resolution.
     120             :   static int GetUserTime(uint32_t* secs,  uint32_t* usecs);
     121             : 
     122             :   // Returns current time as the number of milliseconds since
     123             :   // 00:00:00 UTC, January 1, 1970.
     124             :   static double TimeCurrentMillis();
     125             : 
     126             :   static TimezoneCache* CreateTimezoneCache();
     127             : 
     128             :   // Returns last OS error.
     129             :   static int GetLastError();
     130             : 
     131             :   static FILE* FOpen(const char* path, const char* mode);
     132             :   static bool Remove(const char* path);
     133             : 
     134             :   static char DirectorySeparator();
     135             :   static bool isDirectorySeparator(const char ch);
     136             : 
     137             :   // Opens a temporary file, the file is auto removed on close.
     138             :   static FILE* OpenTemporaryFile();
     139             : 
     140             :   // Log file open mode is platform-dependent due to line ends issues.
     141             :   static const char* const LogFileOpenMode;
     142             : 
     143             :   // Print output to console. This is mostly used for debugging output.
     144             :   // On platforms that has standard terminal output, the output
     145             :   // should go to stdout.
     146             :   static PRINTF_FORMAT(1, 2) void Print(const char* format, ...);
     147             :   static PRINTF_FORMAT(1, 0) void VPrint(const char* format, va_list args);
     148             : 
     149             :   // Print output to a file. This is mostly used for debugging output.
     150             :   static PRINTF_FORMAT(2, 3) void FPrint(FILE* out, const char* format, ...);
     151             :   static PRINTF_FORMAT(2, 0) void VFPrint(FILE* out, const char* format,
     152             :                                           va_list args);
     153             : 
     154             :   // Print error output to console. This is mostly used for error message
     155             :   // output. On platforms that has standard terminal output, the output
     156             :   // should go to stderr.
     157             :   static PRINTF_FORMAT(1, 2) void PrintError(const char* format, ...);
     158             :   static PRINTF_FORMAT(1, 0) void VPrintError(const char* format, va_list args);
     159             : 
     160             :   // Memory access permissions. Only the modes currently used by V8 are listed
     161             :   // here even though most systems support additional modes.
     162             :   enum class MemoryPermission { kNoAccess, kReadWrite, kReadWriteExecute };
     163             : 
     164             :   // Allocate/Free memory used by JS heap. Permissions are set according to the
     165             :   // is_* flags. Returns the address of allocated memory, or nullptr if failed.
     166             :   static void* Allocate(const size_t requested, size_t* allocated,
     167             :                         MemoryPermission access, void* hint = nullptr);
     168             :   // Allocate/Free memory used by JS heap. Pages are readable/writable, but
     169             :   // they are not guaranteed to be executable unless 'executable' is true.
     170             :   // Returns the address of allocated memory, or nullptr if failed.
     171             :   static void* Allocate(const size_t requested, size_t* allocated,
     172             :                         bool is_executable, void* hint = nullptr);
     173             :   static void Free(void* address, const size_t size);
     174             : 
     175             :   // Allocates a region of memory that is inaccessible. On Windows this reserves
     176             :   // but does not commit the memory. On POSIX systems it allocates memory as
     177             :   // PROT_NONE, which also prevents it from being committed.
     178             :   static void* AllocateGuarded(const size_t requested);
     179             : 
     180             :   // This is the granularity at which the SetReadAndExecutable(...) call can
     181             :   // set page permissions.
     182             :   static intptr_t CommitPageSize();
     183             : 
     184             :   // Mark a region of memory executable and readable but not writable.
     185             :   static void SetReadAndExecutable(void* address, const size_t size);
     186             : 
     187             :   // Assign memory as a guard page so that access will cause an exception.
     188             :   static void Guard(void* address, const size_t size);
     189             : 
     190             :   // Make a region of memory non-executable but readable and writable.
     191             :   static void SetReadAndWritable(void* address, const size_t size, bool commit);
     192             : 
     193             :   // Generate a random address to be used for hinting mmap().
     194             :   static void* GetRandomMmapAddr();
     195             : 
     196             :   // Get the Alignment guaranteed by Allocate().
     197             :   static size_t AllocateAlignment();
     198             : 
     199             :   static void* ReserveRegion(size_t size, void* hint);
     200             : 
     201             :   static void* ReserveAlignedRegion(size_t size, size_t alignment, void* hint,
     202             :                                     size_t* allocated);
     203             : 
     204             :   static bool CommitRegion(void* address, size_t size, bool is_executable);
     205             : 
     206             :   static bool UncommitRegion(void* address, size_t size);
     207             : 
     208             :   static bool ReleaseRegion(void* address, size_t size);
     209             : 
     210             :   // Release part of a reserved address range.
     211             :   static bool ReleasePartialRegion(void* address, size_t size);
     212             : 
     213             :   static bool HasLazyCommits();
     214             : 
     215             :   // Sleep for a specified time interval.
     216             :   static void Sleep(TimeDelta interval);
     217             : 
     218             :   // Abort the current process.
     219             :   [[noreturn]] static void Abort();
     220             : 
     221             :   // Debug break.
     222             :   static void DebugBreak();
     223             : 
     224             :   // Walk the stack.
     225             :   static const int kStackWalkError = -1;
     226             :   static const int kStackWalkMaxNameLen = 256;
     227             :   static const int kStackWalkMaxTextLen = 256;
     228             :   struct StackFrame {
     229             :     void* address;
     230             :     char text[kStackWalkMaxTextLen];
     231             :   };
     232             : 
     233           0 :   class V8_BASE_EXPORT MemoryMappedFile {
     234             :    public:
     235           0 :     virtual ~MemoryMappedFile() {}
     236             :     virtual void* memory() const = 0;
     237             :     virtual size_t size() const = 0;
     238             : 
     239             :     static MemoryMappedFile* open(const char* name);
     240             :     static MemoryMappedFile* create(const char* name, size_t size,
     241             :                                     void* initial);
     242             :   };
     243             : 
     244             :   // Safe formatting print. Ensures that str is always null-terminated.
     245             :   // Returns the number of chars written, or -1 if output was truncated.
     246             :   static PRINTF_FORMAT(3, 4) int SNPrintF(char* str, int length,
     247             :                                           const char* format, ...);
     248             :   static PRINTF_FORMAT(3, 0) int VSNPrintF(char* str, int length,
     249             :                                            const char* format, va_list args);
     250             : 
     251             :   static char* StrChr(char* str, int c);
     252             :   static void StrNCpy(char* dest, int length, const char* src, size_t n);
     253             : 
     254             :   // Support for the profiler.  Can do nothing, in which case ticks
     255             :   // occurring in shared libraries will not be properly accounted for.
     256           0 :   struct SharedLibraryAddress {
     257             :     SharedLibraryAddress(const std::string& library_path, uintptr_t start,
     258             :                          uintptr_t end)
     259           0 :         : library_path(library_path), start(start), end(end), aslr_slide(0) {}
     260             :     SharedLibraryAddress(const std::string& library_path, uintptr_t start,
     261             :                          uintptr_t end, intptr_t aslr_slide)
     262             :         : library_path(library_path),
     263             :           start(start),
     264             :           end(end),
     265             :           aslr_slide(aslr_slide) {}
     266             : 
     267             :     std::string library_path;
     268             :     uintptr_t start;
     269             :     uintptr_t end;
     270             :     intptr_t aslr_slide;
     271             :   };
     272             : 
     273             :   static std::vector<SharedLibraryAddress> GetSharedLibraryAddresses();
     274             : 
     275             :   // Support for the profiler.  Notifies the external profiling
     276             :   // process that a code moving garbage collection starts.  Can do
     277             :   // nothing, in which case the code objects must not move (e.g., by
     278             :   // using --never-compact) if accurate profiling is desired.
     279             :   static void SignalCodeMovingGC();
     280             : 
     281             :   // Support runtime detection of whether the hard float option of the
     282             :   // EABI is used.
     283             :   static bool ArmUsingHardFloat();
     284             : 
     285             :   // Returns the activation frame alignment constraint or zero if
     286             :   // the platform doesn't care. Guaranteed to be a power of two.
     287             :   static int ActivationFrameAlignment();
     288             : 
     289             :   static int GetCurrentProcessId();
     290             : 
     291             :   static int GetCurrentThreadId();
     292             : 
     293             :  private:
     294             :   static const int msPerSecond = 1000;
     295             : 
     296             : #if V8_OS_POSIX
     297             :   static const char* GetGCFakeMMapFile();
     298             : #endif
     299             : 
     300             :   DISALLOW_IMPLICIT_CONSTRUCTORS(OS);
     301             : };
     302             : 
     303             : // ----------------------------------------------------------------------------
     304             : // Thread
     305             : //
     306             : // Thread objects are used for creating and running threads. When the start()
     307             : // method is called the new thread starts running the run() method in the new
     308             : // thread. The Thread object should not be deallocated before the thread has
     309             : // terminated.
     310             : 
     311             : class V8_BASE_EXPORT Thread {
     312             :  public:
     313             :   // Opaque data type for thread-local storage keys.
     314             :   typedef int32_t LocalStorageKey;
     315             : 
     316             :   class Options {
     317             :    public:
     318             :     Options() : name_("v8:<unknown>"), stack_size_(0) {}
     319             :     explicit Options(const char* name, int stack_size = 0)
     320      440607 :         : name_(name), stack_size_(stack_size) {}
     321             : 
     322             :     const char* name() const { return name_; }
     323             :     int stack_size() const { return stack_size_; }
     324             : 
     325             :    private:
     326             :     const char* name_;
     327             :     int stack_size_;
     328             :   };
     329             : 
     330             :   // Create new thread.
     331             :   explicit Thread(const Options& options);
     332             :   virtual ~Thread();
     333             : 
     334             :   // Start new thread by calling the Run() method on the new thread.
     335             :   void Start();
     336             : 
     337             :   // Start new thread and wait until Run() method is called on the new thread.
     338         245 :   void StartSynchronously() {
     339         245 :     start_semaphore_ = new Semaphore(0);
     340         245 :     Start();
     341         245 :     start_semaphore_->Wait();
     342         245 :     delete start_semaphore_;
     343         245 :     start_semaphore_ = nullptr;
     344         245 :   }
     345             : 
     346             :   // Wait until thread terminates.
     347             :   void Join();
     348             : 
     349             :   inline const char* name() const {
     350             :     return name_;
     351             :   }
     352             : 
     353             :   // Abstract method for run handler.
     354             :   virtual void Run() = 0;
     355             : 
     356             :   // Thread-local storage.
     357             :   static LocalStorageKey CreateThreadLocalKey();
     358             :   static void DeleteThreadLocalKey(LocalStorageKey key);
     359             :   static void* GetThreadLocal(LocalStorageKey key);
     360             :   static int GetThreadLocalInt(LocalStorageKey key) {
     361     3700036 :     return static_cast<int>(reinterpret_cast<intptr_t>(GetThreadLocal(key)));
     362             :   }
     363             :   static void SetThreadLocal(LocalStorageKey key, void* value);
     364             :   static void SetThreadLocalInt(LocalStorageKey key, int value) {
     365       65147 :     SetThreadLocal(key, reinterpret_cast<void*>(static_cast<intptr_t>(value)));
     366             :   }
     367             :   static bool HasThreadLocal(LocalStorageKey key) {
     368         192 :     return GetThreadLocal(key) != nullptr;
     369             :   }
     370             : 
     371             : #ifdef V8_FAST_TLS_SUPPORTED
     372             :   static inline void* GetExistingThreadLocal(LocalStorageKey key) {
     373             :     void* result = reinterpret_cast<void*>(
     374             :         InternalGetExistingThreadLocal(static_cast<intptr_t>(key)));
     375             :     DCHECK(result == GetThreadLocal(key));
     376             :     return result;
     377             :   }
     378             : #else
     379      668074 :   static inline void* GetExistingThreadLocal(LocalStorageKey key) {
     380      668202 :     return GetThreadLocal(key);
     381             :   }
     382             : #endif
     383             : 
     384             :   // The thread name length is limited to 16 based on Linux's implementation of
     385             :   // prctl().
     386             :   static const int kMaxThreadNameLength = 16;
     387             : 
     388             :   class PlatformData;
     389             :   PlatformData* data() { return data_; }
     390             : 
     391      386366 :   void NotifyStartedAndRun() {
     392      386366 :     if (start_semaphore_) start_semaphore_->Signal();
     393      386366 :     Run();
     394      381224 :   }
     395             : 
     396             :  private:
     397             :   void set_name(const char* name);
     398             : 
     399             :   PlatformData* data_;
     400             : 
     401             :   char name_[kMaxThreadNameLength];
     402             :   int stack_size_;
     403             :   Semaphore* start_semaphore_;
     404             : 
     405             :   DISALLOW_COPY_AND_ASSIGN(Thread);
     406             : };
     407             : 
     408             : }  // namespace base
     409             : }  // namespace v8
     410             : 
     411             : #endif  // V8_BASE_PLATFORM_PLATFORM_H_

Generated by: LCOV version 1.10