LCOV - code coverage report
Current view: top level - src/base/platform - platform.h (source / functions) Hit Total Coverage
Test: app.info Lines: 19 21 90.5 %
Date: 2019-02-19 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             : 
      40             : namespace base {
      41             : 
      42             : // ----------------------------------------------------------------------------
      43             : // Fast TLS support
      44             : 
      45             : #ifndef V8_NO_FAST_TLS
      46             : 
      47             : #if V8_CC_MSVC && V8_HOST_ARCH_IA32
      48             : 
      49             : #define V8_FAST_TLS_SUPPORTED 1
      50             : 
      51             : V8_INLINE intptr_t InternalGetExistingThreadLocal(intptr_t index);
      52             : 
      53             : inline intptr_t InternalGetExistingThreadLocal(intptr_t index) {
      54             :   const intptr_t kTibInlineTlsOffset = 0xE10;
      55             :   const intptr_t kTibExtraTlsOffset = 0xF94;
      56             :   const intptr_t kMaxInlineSlots = 64;
      57             :   const intptr_t kMaxSlots = kMaxInlineSlots + 1024;
      58             :   const intptr_t kSystemPointerSize = sizeof(void*);
      59             :   DCHECK(0 <= index && index < kMaxSlots);
      60             :   USE(kMaxSlots);
      61             :   if (index < kMaxInlineSlots) {
      62             :     return static_cast<intptr_t>(
      63             :         __readfsdword(kTibInlineTlsOffset + kSystemPointerSize * index));
      64             :   }
      65             :   intptr_t extra = static_cast<intptr_t>(__readfsdword(kTibExtraTlsOffset));
      66             :   DCHECK_NE(extra, 0);
      67             :   return *reinterpret_cast<intptr_t*>(extra + kSystemPointerSize *
      68             :                                                   (index - kMaxInlineSlots));
      69             : }
      70             : 
      71             : #elif defined(__APPLE__) && (V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64)
      72             : 
      73             : #define V8_FAST_TLS_SUPPORTED 1
      74             : 
      75             : extern V8_BASE_EXPORT intptr_t kMacTlsBaseOffset;
      76             : 
      77             : V8_INLINE intptr_t InternalGetExistingThreadLocal(intptr_t index);
      78             : 
      79             : inline intptr_t InternalGetExistingThreadLocal(intptr_t index) {
      80             :   intptr_t result;
      81             : #if V8_HOST_ARCH_IA32
      82             :   asm("movl %%gs:(%1,%2,4), %0;"
      83             :       :"=r"(result)  // Output must be a writable register.
      84             :       :"r"(kMacTlsBaseOffset), "r"(index));
      85             : #else
      86             :   asm("movq %%gs:(%1,%2,8), %0;"
      87             :       :"=r"(result)
      88             :       :"r"(kMacTlsBaseOffset), "r"(index));
      89             : #endif
      90             :   return result;
      91             : }
      92             : 
      93             : #endif
      94             : 
      95             : #endif  // V8_NO_FAST_TLS
      96             : 
      97             : class PageAllocator;
      98             : class TimezoneCache;
      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             :   // - hard_abort: If true, OS::Abort() will crash instead of aborting.
     111             :   // - gc_fake_mmap: Name of the file for fake gc mmap used in ll_prof.
     112             :   static void Initialize(bool hard_abort, 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             : 
     126             :   // Returns last OS error.
     127             :   static int GetLastError();
     128             : 
     129             :   static FILE* FOpen(const char* path, const char* mode);
     130             :   static bool Remove(const char* path);
     131             : 
     132             :   static char DirectorySeparator();
     133             :   static bool isDirectorySeparator(const char ch);
     134             : 
     135             :   // Opens a temporary file, the file is auto removed on close.
     136             :   static FILE* OpenTemporaryFile();
     137             : 
     138             :   // Log file open mode is platform-dependent due to line ends issues.
     139             :   static const char* const LogFileOpenMode;
     140             : 
     141             :   // Print output to console. This is mostly used for debugging output.
     142             :   // On platforms that has standard terminal output, the output
     143             :   // should go to stdout.
     144             :   static PRINTF_FORMAT(1, 2) void Print(const char* format, ...);
     145             :   static PRINTF_FORMAT(1, 0) void VPrint(const char* format, va_list args);
     146             : 
     147             :   // Print output to a file. This is mostly used for debugging output.
     148             :   static PRINTF_FORMAT(2, 3) void FPrint(FILE* out, const char* format, ...);
     149             :   static PRINTF_FORMAT(2, 0) void VFPrint(FILE* out, const char* format,
     150             :                                           va_list args);
     151             : 
     152             :   // Print error output to console. This is mostly used for error message
     153             :   // output. On platforms that has standard terminal output, the output
     154             :   // should go to stderr.
     155             :   static PRINTF_FORMAT(1, 2) void PrintError(const char* format, ...);
     156             :   static PRINTF_FORMAT(1, 0) void VPrintError(const char* format, va_list args);
     157             : 
     158             :   // Memory permissions. These should be kept in sync with the ones in
     159             :   // v8::PageAllocator.
     160             :   enum class MemoryPermission {
     161             :     kNoAccess,
     162             :     kRead,
     163             :     kReadWrite,
     164             :     // TODO(hpayer): Remove this flag. Memory should never be rwx.
     165             :     kReadWriteExecute,
     166             :     kReadExecute
     167             :   };
     168             : 
     169             :   static bool HasLazyCommits();
     170             : 
     171             :   // Sleep for a specified time interval.
     172             :   static void Sleep(TimeDelta interval);
     173             : 
     174             :   // Abort the current process.
     175             :   [[noreturn]] static void Abort();
     176             : 
     177             :   // Debug break.
     178             :   static void DebugBreak();
     179             : 
     180             :   // Walk the stack.
     181             :   static const int kStackWalkError = -1;
     182             :   static const int kStackWalkMaxNameLen = 256;
     183             :   static const int kStackWalkMaxTextLen = 256;
     184             :   struct StackFrame {
     185             :     void* address;
     186             :     char text[kStackWalkMaxTextLen];
     187             :   };
     188             : 
     189      113774 :   class V8_BASE_EXPORT MemoryMappedFile {
     190             :    public:
     191      113774 :     virtual ~MemoryMappedFile() = default;
     192             :     virtual void* memory() const = 0;
     193             :     virtual size_t size() const = 0;
     194             : 
     195             :     static MemoryMappedFile* open(const char* name);
     196             :     static MemoryMappedFile* create(const char* name, size_t size,
     197             :                                     void* initial);
     198             :   };
     199             : 
     200             :   // Safe formatting print. Ensures that str is always null-terminated.
     201             :   // Returns the number of chars written, or -1 if output was truncated.
     202             :   static PRINTF_FORMAT(3, 4) int SNPrintF(char* str, int length,
     203             :                                           const char* format, ...);
     204             :   static PRINTF_FORMAT(3, 0) int VSNPrintF(char* str, int length,
     205             :                                            const char* format, va_list args);
     206             : 
     207             :   static char* StrChr(char* str, int c);
     208             :   static void StrNCpy(char* dest, int length, const char* src, size_t n);
     209             : 
     210             :   // Support for the profiler.  Can do nothing, in which case ticks
     211             :   // occurring in shared libraries will not be properly accounted for.
     212           0 :   struct SharedLibraryAddress {
     213             :     SharedLibraryAddress(const std::string& library_path, uintptr_t start,
     214             :                          uintptr_t end)
     215           0 :         : library_path(library_path), start(start), end(end), aslr_slide(0) {}
     216             :     SharedLibraryAddress(const std::string& library_path, uintptr_t start,
     217             :                          uintptr_t end, intptr_t aslr_slide)
     218             :         : library_path(library_path),
     219             :           start(start),
     220             :           end(end),
     221             :           aslr_slide(aslr_slide) {}
     222             : 
     223             :     std::string library_path;
     224             :     uintptr_t start;
     225             :     uintptr_t end;
     226             :     intptr_t aslr_slide;
     227             :   };
     228             : 
     229             :   static std::vector<SharedLibraryAddress> GetSharedLibraryAddresses();
     230             : 
     231             :   // Support for the profiler.  Notifies the external profiling
     232             :   // process that a code moving garbage collection starts.  Can do
     233             :   // nothing, in which case the code objects must not move (e.g., by
     234             :   // using --never-compact) if accurate profiling is desired.
     235             :   static void SignalCodeMovingGC();
     236             : 
     237             :   // Support runtime detection of whether the hard float option of the
     238             :   // EABI is used.
     239             :   static bool ArmUsingHardFloat();
     240             : 
     241             :   // Returns the activation frame alignment constraint or zero if
     242             :   // the platform doesn't care. Guaranteed to be a power of two.
     243             :   static int ActivationFrameAlignment();
     244             : 
     245             :   static int GetCurrentProcessId();
     246             : 
     247             :   static int GetCurrentThreadId();
     248             : 
     249             :   static void ExitProcess(int exit_code);
     250             : 
     251             :  private:
     252             :   // These classes use the private memory management API below.
     253             :   friend class MemoryMappedFile;
     254             :   friend class PosixMemoryMappedFile;
     255             :   friend class v8::base::PageAllocator;
     256             : 
     257             :   static size_t AllocatePageSize();
     258             : 
     259             :   static size_t CommitPageSize();
     260             : 
     261             :   static void SetRandomMmapSeed(int64_t seed);
     262             : 
     263             :   static void* GetRandomMmapAddr();
     264             : 
     265             :   V8_WARN_UNUSED_RESULT static void* Allocate(void* address, size_t size,
     266             :                                               size_t alignment,
     267             :                                               MemoryPermission access);
     268             : 
     269             :   V8_WARN_UNUSED_RESULT static bool Free(void* address, const size_t size);
     270             : 
     271             :   V8_WARN_UNUSED_RESULT static bool Release(void* address, size_t size);
     272             : 
     273             :   V8_WARN_UNUSED_RESULT static bool SetPermissions(void* address, size_t size,
     274             :                                                    MemoryPermission access);
     275             : 
     276             :   V8_WARN_UNUSED_RESULT static bool DiscardSystemPages(void* address,
     277             :                                                        size_t size);
     278             : 
     279             :   static const int msPerSecond = 1000;
     280             : 
     281             : #if V8_OS_POSIX
     282             :   static const char* GetGCFakeMMapFile();
     283             : #endif
     284             : 
     285             :   DISALLOW_IMPLICIT_CONSTRUCTORS(OS);
     286             : };
     287             : 
     288             : #if (defined(_WIN32) || defined(_WIN64))
     289             : V8_BASE_EXPORT void EnsureConsoleOutputWin32();
     290             : #endif  // (defined(_WIN32) || defined(_WIN64))
     291             : 
     292             : inline void EnsureConsoleOutput() {
     293             : #if (defined(_WIN32) || defined(_WIN64))
     294             :   // Windows requires extra calls to send assert output to the console
     295             :   // rather than a dialog box.
     296             :   EnsureConsoleOutputWin32();
     297             : #endif  // (defined(_WIN32) || defined(_WIN64))
     298             : }
     299             : 
     300             : // ----------------------------------------------------------------------------
     301             : // Thread
     302             : //
     303             : // Thread objects are used for creating and running threads. When the start()
     304             : // method is called the new thread starts running the run() method in the new
     305             : // thread. The Thread object should not be deallocated before the thread has
     306             : // terminated.
     307             : 
     308             : class V8_BASE_EXPORT Thread {
     309             :  public:
     310             :   // Opaque data type for thread-local storage keys.
     311             :   typedef int32_t LocalStorageKey;
     312             : 
     313             :   class Options {
     314             :    public:
     315             :     Options() : name_("v8:<unknown>"), stack_size_(0) {}
     316             :     explicit Options(const char* name, int stack_size = 0)
     317      489639 :         : name_(name), stack_size_(stack_size) {}
     318             : 
     319             :     const char* name() const { return name_; }
     320             :     int stack_size() const { return stack_size_; }
     321             : 
     322             :    private:
     323             :     const char* name_;
     324             :     int stack_size_;
     325             :   };
     326             : 
     327             :   // Create new thread.
     328             :   explicit Thread(const Options& options);
     329             :   virtual ~Thread();
     330             : 
     331             :   // Start new thread by calling the Run() method on the new thread.
     332             :   void Start();
     333             : 
     334             :   // Start new thread and wait until Run() method is called on the new thread.
     335         728 :   void StartSynchronously() {
     336         728 :     start_semaphore_ = new Semaphore(0);
     337         728 :     Start();
     338         728 :     start_semaphore_->Wait();
     339         728 :     delete start_semaphore_;
     340         728 :     start_semaphore_ = nullptr;
     341         728 :   }
     342             : 
     343             :   // Wait until thread terminates.
     344             :   void Join();
     345             : 
     346             :   inline const char* name() const {
     347             :     return name_;
     348             :   }
     349             : 
     350             :   // Abstract method for run handler.
     351             :   virtual void Run() = 0;
     352             : 
     353             :   // Thread-local storage.
     354             :   static LocalStorageKey CreateThreadLocalKey();
     355             :   static void DeleteThreadLocalKey(LocalStorageKey key);
     356             :   static void* GetThreadLocal(LocalStorageKey key);
     357             :   static int GetThreadLocalInt(LocalStorageKey key) {
     358      648398 :     return static_cast<int>(reinterpret_cast<intptr_t>(GetThreadLocal(key)));
     359             :   }
     360             :   static void SetThreadLocal(LocalStorageKey key, void* value);
     361             :   static void SetThreadLocalInt(LocalStorageKey key, int value) {
     362       65796 :     SetThreadLocal(key, reinterpret_cast<void*>(static_cast<intptr_t>(value)));
     363             :   }
     364             :   static bool HasThreadLocal(LocalStorageKey key) {
     365         192 :     return GetThreadLocal(key) != nullptr;
     366             :   }
     367             : 
     368             : #ifdef V8_FAST_TLS_SUPPORTED
     369             :   static inline void* GetExistingThreadLocal(LocalStorageKey key) {
     370             :     void* result = reinterpret_cast<void*>(
     371             :         InternalGetExistingThreadLocal(static_cast<intptr_t>(key)));
     372             :     DCHECK(result == GetThreadLocal(key));
     373             :     return result;
     374             :   }
     375             : #else
     376      904764 :   static inline void* GetExistingThreadLocal(LocalStorageKey key) {
     377      904892 :     return GetThreadLocal(key);
     378             :   }
     379             : #endif
     380             : 
     381             :   // The thread name length is limited to 16 based on Linux's implementation of
     382             :   // prctl().
     383             :   static const int kMaxThreadNameLength = 16;
     384             : 
     385             :   class PlatformData;
     386             :   PlatformData* data() { return data_; }
     387             : 
     388      443322 :   void NotifyStartedAndRun() {
     389      443322 :     if (start_semaphore_) start_semaphore_->Signal();
     390      443322 :     Run();
     391      422452 :   }
     392             : 
     393             :  private:
     394             :   void set_name(const char* name);
     395             : 
     396             :   PlatformData* data_;
     397             : 
     398             :   char name_[kMaxThreadNameLength];
     399             :   int stack_size_;
     400             :   Semaphore* start_semaphore_;
     401             : 
     402             :   DISALLOW_COPY_AND_ASSIGN(Thread);
     403             : };
     404             : 
     405             : }  // namespace base
     406             : }  // namespace v8
     407             : 
     408             : #endif  // V8_BASE_PLATFORM_PLATFORM_H_

Generated by: LCOV version 1.10