LCOV - code coverage report
Current view: top level - src/libsampler - sampler.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 120 126 95.2 %
Date: 2017-04-26 Functions: 23 25 92.0 %

          Line data    Source code
       1             : // Copyright 2016 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             : #include "src/libsampler/sampler.h"
       6             : 
       7             : #if V8_OS_POSIX && !V8_OS_CYGWIN
       8             : 
       9             : #define USE_SIGNALS
      10             : 
      11             : #include <errno.h>
      12             : #include <pthread.h>
      13             : #include <signal.h>
      14             : #include <sys/time.h>
      15             : 
      16             : #if !V8_OS_QNX && !V8_OS_AIX
      17             : #include <sys/syscall.h>  // NOLINT
      18             : #endif
      19             : 
      20             : #if V8_OS_MACOSX
      21             : #include <mach/mach.h>
      22             : // OpenBSD doesn't have <ucontext.h>. ucontext_t lives in <signal.h>
      23             : // and is a typedef for struct sigcontext. There is no uc_mcontext.
      24             : #elif(!V8_OS_ANDROID || defined(__BIONIC_HAVE_UCONTEXT_T)) && !V8_OS_OPENBSD
      25             : #include <ucontext.h>
      26             : #endif
      27             : 
      28             : #include <unistd.h>
      29             : 
      30             : // GLibc on ARM defines mcontext_t has a typedef for 'struct sigcontext'.
      31             : // Old versions of the C library <signal.h> didn't define the type.
      32             : #if V8_OS_ANDROID && !defined(__BIONIC_HAVE_UCONTEXT_T) && \
      33             :     (defined(__arm__) || defined(__aarch64__)) && \
      34             :     !defined(__BIONIC_HAVE_STRUCT_SIGCONTEXT)
      35             : #include <asm/sigcontext.h>  // NOLINT
      36             : #endif
      37             : 
      38             : #elif V8_OS_WIN || V8_OS_CYGWIN
      39             : 
      40             : #include "src/base/win32-headers.h"
      41             : 
      42             : #endif
      43             : 
      44             : #include <algorithm>
      45             : #include <vector>
      46             : #include <map>
      47             : 
      48             : #include "src/base/atomic-utils.h"
      49             : #include "src/base/hashmap.h"
      50             : #include "src/base/platform/platform.h"
      51             : 
      52             : #if V8_OS_ANDROID && !defined(__BIONIC_HAVE_UCONTEXT_T)
      53             : 
      54             : // Not all versions of Android's C library provide ucontext_t.
      55             : // Detect this and provide custom but compatible definitions. Note that these
      56             : // follow the GLibc naming convention to access register values from
      57             : // mcontext_t.
      58             : //
      59             : // See http://code.google.com/p/android/issues/detail?id=34784
      60             : 
      61             : #if defined(__arm__)
      62             : 
      63             : typedef struct sigcontext mcontext_t;
      64             : 
      65             : typedef struct ucontext {
      66             :   uint32_t uc_flags;
      67             :   struct ucontext* uc_link;
      68             :   stack_t uc_stack;
      69             :   mcontext_t uc_mcontext;
      70             :   // Other fields are not used by V8, don't define them here.
      71             : } ucontext_t;
      72             : 
      73             : #elif defined(__aarch64__)
      74             : 
      75             : typedef struct sigcontext mcontext_t;
      76             : 
      77             : typedef struct ucontext {
      78             :   uint64_t uc_flags;
      79             :   struct ucontext *uc_link;
      80             :   stack_t uc_stack;
      81             :   mcontext_t uc_mcontext;
      82             :   // Other fields are not used by V8, don't define them here.
      83             : } ucontext_t;
      84             : 
      85             : #elif defined(__mips__)
      86             : // MIPS version of sigcontext, for Android bionic.
      87             : typedef struct {
      88             :   uint32_t regmask;
      89             :   uint32_t status;
      90             :   uint64_t pc;
      91             :   uint64_t gregs[32];
      92             :   uint64_t fpregs[32];
      93             :   uint32_t acx;
      94             :   uint32_t fpc_csr;
      95             :   uint32_t fpc_eir;
      96             :   uint32_t used_math;
      97             :   uint32_t dsp;
      98             :   uint64_t mdhi;
      99             :   uint64_t mdlo;
     100             :   uint32_t hi1;
     101             :   uint32_t lo1;
     102             :   uint32_t hi2;
     103             :   uint32_t lo2;
     104             :   uint32_t hi3;
     105             :   uint32_t lo3;
     106             : } mcontext_t;
     107             : 
     108             : typedef struct ucontext {
     109             :   uint32_t uc_flags;
     110             :   struct ucontext* uc_link;
     111             :   stack_t uc_stack;
     112             :   mcontext_t uc_mcontext;
     113             :   // Other fields are not used by V8, don't define them here.
     114             : } ucontext_t;
     115             : 
     116             : #elif defined(__i386__)
     117             : // x86 version for Android.
     118             : typedef struct {
     119             :   uint32_t gregs[19];
     120             :   void* fpregs;
     121             :   uint32_t oldmask;
     122             :   uint32_t cr2;
     123             : } mcontext_t;
     124             : 
     125             : typedef uint32_t kernel_sigset_t[2];  // x86 kernel uses 64-bit signal masks
     126             : typedef struct ucontext {
     127             :   uint32_t uc_flags;
     128             :   struct ucontext* uc_link;
     129             :   stack_t uc_stack;
     130             :   mcontext_t uc_mcontext;
     131             :   // Other fields are not used by V8, don't define them here.
     132             : } ucontext_t;
     133             : enum { REG_EBP = 6, REG_ESP = 7, REG_EIP = 14 };
     134             : 
     135             : #elif defined(__x86_64__)
     136             : // x64 version for Android.
     137             : typedef struct {
     138             :   uint64_t gregs[23];
     139             :   void* fpregs;
     140             :   uint64_t __reserved1[8];
     141             : } mcontext_t;
     142             : 
     143             : typedef struct ucontext {
     144             :   uint64_t uc_flags;
     145             :   struct ucontext *uc_link;
     146             :   stack_t uc_stack;
     147             :   mcontext_t uc_mcontext;
     148             :   // Other fields are not used by V8, don't define them here.
     149             : } ucontext_t;
     150             : enum { REG_RBP = 10, REG_RSP = 15, REG_RIP = 16 };
     151             : #endif
     152             : 
     153             : #endif  // V8_OS_ANDROID && !defined(__BIONIC_HAVE_UCONTEXT_T)
     154             : 
     155             : 
     156             : namespace v8 {
     157             : namespace sampler {
     158             : 
     159             : namespace {
     160             : 
     161             : #if defined(USE_SIGNALS)
     162             : typedef std::vector<Sampler*> SamplerList;
     163             : typedef SamplerList::iterator SamplerListIterator;
     164             : typedef base::AtomicValue<bool> AtomicMutex;
     165             : 
     166             : class AtomicGuard {
     167             :  public:
     168      239433 :   explicit AtomicGuard(AtomicMutex* atomic, bool is_blocking = true)
     169      239433 :       : atomic_(atomic), is_success_(false) {
     170      239433 :     do {
     171             :       // Use Acquire_Load to gain mutual exclusion.
     172      239433 :       USE(atomic_->Value());
     173      478866 :       is_success_ = atomic_->TrySetValue(false, true);
     174         474 :     } while (is_blocking && !is_success_);
     175      239433 :   }
     176             : 
     177             :   bool is_success() const { return is_success_; }
     178             : 
     179      239433 :   ~AtomicGuard() {
     180      239433 :     if (!is_success_) return;
     181      239433 :     atomic_->SetValue(false);
     182      239433 :   }
     183             : 
     184             :  private:
     185             :   AtomicMutex* const atomic_;
     186             :   bool is_success_;
     187             : };
     188             : 
     189             : // Returns key for hash map.
     190             : void* ThreadKey(pthread_t thread_id) {
     191      239433 :   return reinterpret_cast<void*>(thread_id);
     192             : }
     193             : 
     194             : // Returns hash value for hash map.
     195             : uint32_t ThreadHash(pthread_t thread_id) {
     196             : #if V8_OS_BSD
     197             :   return static_cast<uint32_t>(reinterpret_cast<intptr_t>(thread_id));
     198             : #else
     199      239433 :   return static_cast<uint32_t>(thread_id);
     200             : #endif
     201             : }
     202             : 
     203             : #endif  // USE_SIGNALS
     204             : 
     205             : }  // namespace
     206             : 
     207             : #if defined(USE_SIGNALS)
     208             : 
     209             : class Sampler::PlatformData {
     210             :  public:
     211       61119 :   PlatformData() : vm_tid_(pthread_self()) {}
     212      252573 :   pthread_t vm_tid() const { return vm_tid_; }
     213             : 
     214             :  private:
     215             :   pthread_t vm_tid_;
     216             : };
     217             : 
     218             : class SamplerManager {
     219             :  public:
     220             :   SamplerManager() : sampler_map_() {}
     221             : 
     222         237 :   void AddSampler(Sampler* sampler) {
     223         237 :     AtomicGuard atomic_guard(&samplers_access_counter_);
     224             :     DCHECK(sampler->IsActive() || !sampler->IsRegistered());
     225             :     // Add sampler into map if needed.
     226         237 :     pthread_t thread_id = sampler->platform_data()->vm_tid();
     227             :     base::HashMap::Entry* entry =
     228             :             sampler_map_.LookupOrInsert(ThreadKey(thread_id),
     229         474 :                                         ThreadHash(thread_id));
     230             :     DCHECK(entry != nullptr);
     231         237 :     if (entry->value == nullptr) {
     232         237 :       SamplerList* samplers = new SamplerList();
     233         237 :       samplers->push_back(sampler);
     234         237 :       entry->value = samplers;
     235             :     } else {
     236             :       SamplerList* samplers = reinterpret_cast<SamplerList*>(entry->value);
     237             :       bool exists = false;
     238           0 :       for (SamplerListIterator iter = samplers->begin();
     239             :            iter != samplers->end(); ++iter) {
     240           0 :         if (*iter == sampler) {
     241             :           exists = true;
     242             :           break;
     243             :         }
     244             :       }
     245           0 :       if (!exists) {
     246           0 :         samplers->push_back(sampler);
     247             :       }
     248         237 :     }
     249         237 :   }
     250             : 
     251         474 :   void RemoveSampler(Sampler* sampler) {
     252         237 :     AtomicGuard atomic_guard(&samplers_access_counter_);
     253             :     DCHECK(sampler->IsActive() || sampler->IsRegistered());
     254             :     // Remove sampler from map.
     255             :     pthread_t thread_id = sampler->platform_data()->vm_tid();
     256         237 :     void* thread_key = ThreadKey(thread_id);
     257             :     uint32_t thread_hash = ThreadHash(thread_id);
     258         237 :     base::HashMap::Entry* entry = sampler_map_.Lookup(thread_key, thread_hash);
     259             :     DCHECK(entry != nullptr);
     260         237 :     SamplerList* samplers = reinterpret_cast<SamplerList*>(entry->value);
     261         474 :     for (SamplerListIterator iter = samplers->begin(); iter != samplers->end();
     262             :          ++iter) {
     263         237 :       if (*iter == sampler) {
     264         237 :         samplers->erase(iter);
     265         237 :         break;
     266             :       }
     267             :     }
     268         237 :     if (samplers->empty()) {
     269         237 :       sampler_map_.Remove(thread_key, thread_hash);
     270         474 :       delete samplers;
     271         237 :     }
     272         237 :   }
     273             : 
     274             : #if defined(USE_SIGNALS)
     275      238959 :   void DoSample(const v8::RegisterState& state) {
     276      238959 :     AtomicGuard atomic_guard(&SamplerManager::samplers_access_counter_, false);
     277      238959 :     if (!atomic_guard.is_success()) return;
     278      238959 :     pthread_t thread_id = pthread_self();
     279             :     base::HashMap::Entry* entry =
     280      238959 :         sampler_map_.Lookup(ThreadKey(thread_id), ThreadHash(thread_id));
     281      238959 :     if (!entry) return;
     282      716877 :     SamplerList& samplers = *static_cast<SamplerList*>(entry->value);
     283             : 
     284      955836 :     for (size_t i = 0; i < samplers.size(); ++i) {
     285      238959 :       Sampler* sampler = samplers[i];
     286             :       Isolate* isolate = sampler->isolate();
     287             :       // We require a fully initialized and entered isolate.
     288      238959 :       if (isolate == nullptr || !isolate->IsInUse()) continue;
     289      238937 :       if (v8::Locker::IsActive() && !Locker::IsLocked(isolate)) continue;
     290      238937 :       sampler->SampleStack(state);
     291      238959 :     }
     292             :   }
     293             : #endif
     294             : 
     295             :   static SamplerManager* instance() { return instance_.Pointer(); }
     296             : 
     297             :  private:
     298             :   base::HashMap sampler_map_;
     299             :   static AtomicMutex samplers_access_counter_;
     300             :   static base::LazyInstance<SamplerManager>::type instance_;
     301             : };
     302             : 
     303             : AtomicMutex SamplerManager::samplers_access_counter_;
     304             : base::LazyInstance<SamplerManager>::type SamplerManager::instance_ =
     305             :     LAZY_INSTANCE_INITIALIZER;
     306             : 
     307             : #elif V8_OS_WIN || V8_OS_CYGWIN
     308             : 
     309             : // ----------------------------------------------------------------------------
     310             : // Win32 profiler support. On Cygwin we use the same sampler implementation as
     311             : // on Win32.
     312             : 
     313             : class Sampler::PlatformData {
     314             :  public:
     315             :   // Get a handle to the calling thread. This is the thread that we are
     316             :   // going to profile. We need to make a copy of the handle because we are
     317             :   // going to use it in the sampler thread. Using GetThreadHandle() will
     318             :   // not work in this case. We're using OpenThread because DuplicateHandle
     319             :   // for some reason doesn't work in Chrome's sandbox.
     320             :   PlatformData()
     321             :       : profiled_thread_(OpenThread(THREAD_GET_CONTEXT |
     322             :                                     THREAD_SUSPEND_RESUME |
     323             :                                     THREAD_QUERY_INFORMATION,
     324             :                                     false,
     325             :                                     GetCurrentThreadId())) {}
     326             : 
     327             :   ~PlatformData() {
     328             :     if (profiled_thread_ != nullptr) {
     329             :       CloseHandle(profiled_thread_);
     330             :       profiled_thread_ = nullptr;
     331             :     }
     332             :   }
     333             : 
     334             :   HANDLE profiled_thread() { return profiled_thread_; }
     335             : 
     336             :  private:
     337             :   HANDLE profiled_thread_;
     338             : };
     339             : #endif  // USE_SIGNALS
     340             : 
     341             : 
     342             : #if defined(USE_SIGNALS)
     343             : class SignalHandler {
     344             :  public:
     345       59468 :   static void SetUp() { if (!mutex_) mutex_ = new base::Mutex(); }
     346       32503 :   static void TearDown() {
     347       32503 :     delete mutex_;
     348       32503 :     mutex_ = nullptr;
     349       32503 :   }
     350             : 
     351         337 :   static void IncreaseSamplerCount() {
     352         337 :     base::LockGuard<base::Mutex> lock_guard(mutex_);
     353         337 :     if (++client_count_ == 1) Install();
     354         337 :   }
     355             : 
     356         337 :   static void DecreaseSamplerCount() {
     357         337 :     base::LockGuard<base::Mutex> lock_guard(mutex_);
     358         337 :     if (--client_count_ == 0) Restore();
     359         337 :   }
     360             : 
     361      252099 :   static bool Installed() {
     362      252099 :     base::LockGuard<base::Mutex> lock_guard(mutex_);
     363      504198 :     return signal_handler_installed_;
     364             :   }
     365             : 
     366             :  private:
     367         337 :   static void Install() {
     368             :     struct sigaction sa;
     369         337 :     sa.sa_sigaction = &HandleProfilerSignal;
     370         337 :     sigemptyset(&sa.sa_mask);
     371             : #if V8_OS_QNX
     372             :     sa.sa_flags = SA_SIGINFO;
     373             : #else
     374         337 :     sa.sa_flags = SA_RESTART | SA_SIGINFO;
     375             : #endif
     376             :     signal_handler_installed_ =
     377         337 :         (sigaction(SIGPROF, &sa, &old_signal_handler_) == 0);
     378         337 :   }
     379             : 
     380         337 :   static void Restore() {
     381         337 :     if (signal_handler_installed_) {
     382         337 :       sigaction(SIGPROF, &old_signal_handler_, 0);
     383         337 :       signal_handler_installed_ = false;
     384             :     }
     385         337 :   }
     386             : 
     387             :   static void FillRegisterState(void* context, RegisterState* regs);
     388             :   static void HandleProfilerSignal(int signal, siginfo_t* info, void* context);
     389             : 
     390             :   // Protects the process wide state below.
     391             :   static base::Mutex* mutex_;
     392             :   static int client_count_;
     393             :   static bool signal_handler_installed_;
     394             :   static struct sigaction old_signal_handler_;
     395             : };
     396             : 
     397             : base::Mutex* SignalHandler::mutex_ = nullptr;
     398             : int SignalHandler::client_count_ = 0;
     399             : struct sigaction SignalHandler::old_signal_handler_;
     400             : bool SignalHandler::signal_handler_installed_ = false;
     401             : 
     402             : 
     403      238959 : void SignalHandler::HandleProfilerSignal(int signal, siginfo_t* info,
     404             :                                          void* context) {
     405             :   USE(info);
     406      238959 :   if (signal != SIGPROF) return;
     407             :   v8::RegisterState state;
     408             :   FillRegisterState(context, &state);
     409      238959 :   SamplerManager::instance()->DoSample(state);
     410             : }
     411             : 
     412           0 : void SignalHandler::FillRegisterState(void* context, RegisterState* state) {
     413             :   // Extracting the sample from the context is extremely machine dependent.
     414             :   ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
     415             : #if !(V8_OS_OPENBSD || (V8_OS_LINUX && (V8_HOST_ARCH_PPC || V8_HOST_ARCH_S390)))
     416             :   mcontext_t& mcontext = ucontext->uc_mcontext;
     417             : #endif
     418             : #if V8_OS_LINUX
     419             : #if V8_HOST_ARCH_IA32
     420             :   state->pc = reinterpret_cast<void*>(mcontext.gregs[REG_EIP]);
     421             :   state->sp = reinterpret_cast<void*>(mcontext.gregs[REG_ESP]);
     422             :   state->fp = reinterpret_cast<void*>(mcontext.gregs[REG_EBP]);
     423             : #elif V8_HOST_ARCH_X64
     424      238959 :   state->pc = reinterpret_cast<void*>(mcontext.gregs[REG_RIP]);
     425      238959 :   state->sp = reinterpret_cast<void*>(mcontext.gregs[REG_RSP]);
     426      238959 :   state->fp = reinterpret_cast<void*>(mcontext.gregs[REG_RBP]);
     427             : #elif V8_HOST_ARCH_ARM
     428             : #if V8_LIBC_GLIBC && !V8_GLIBC_PREREQ(2, 4)
     429             :   // Old GLibc ARM versions used a gregs[] array to access the register
     430             :   // values from mcontext_t.
     431             :   state->pc = reinterpret_cast<void*>(mcontext.gregs[R15]);
     432             :   state->sp = reinterpret_cast<void*>(mcontext.gregs[R13]);
     433             :   state->fp = reinterpret_cast<void*>(mcontext.gregs[R11]);
     434             : #else
     435             :   state->pc = reinterpret_cast<void*>(mcontext.arm_pc);
     436             :   state->sp = reinterpret_cast<void*>(mcontext.arm_sp);
     437             :   state->fp = reinterpret_cast<void*>(mcontext.arm_fp);
     438             : #endif  // V8_LIBC_GLIBC && !V8_GLIBC_PREREQ(2, 4)
     439             : #elif V8_HOST_ARCH_ARM64
     440             :   state->pc = reinterpret_cast<void*>(mcontext.pc);
     441             :   state->sp = reinterpret_cast<void*>(mcontext.sp);
     442             :   // FP is an alias for x29.
     443             :   state->fp = reinterpret_cast<void*>(mcontext.regs[29]);
     444             : #elif V8_HOST_ARCH_MIPS
     445             :   state->pc = reinterpret_cast<void*>(mcontext.pc);
     446             :   state->sp = reinterpret_cast<void*>(mcontext.gregs[29]);
     447             :   state->fp = reinterpret_cast<void*>(mcontext.gregs[30]);
     448             : #elif V8_HOST_ARCH_MIPS64
     449             :   state->pc = reinterpret_cast<void*>(mcontext.pc);
     450             :   state->sp = reinterpret_cast<void*>(mcontext.gregs[29]);
     451             :   state->fp = reinterpret_cast<void*>(mcontext.gregs[30]);
     452             : #elif V8_HOST_ARCH_PPC
     453             :   state->pc = reinterpret_cast<void*>(ucontext->uc_mcontext.regs->nip);
     454             :   state->sp =
     455             :       reinterpret_cast<void*>(ucontext->uc_mcontext.regs->gpr[PT_R1]);
     456             :   state->fp =
     457             :       reinterpret_cast<void*>(ucontext->uc_mcontext.regs->gpr[PT_R31]);
     458             : #elif V8_HOST_ARCH_S390
     459             : #if V8_TARGET_ARCH_32_BIT
     460             :   // 31-bit target will have bit 0 (MSB) of the PSW set to denote addressing
     461             :   // mode.  This bit needs to be masked out to resolve actual address.
     462             :   state->pc =
     463             :       reinterpret_cast<void*>(ucontext->uc_mcontext.psw.addr & 0x7FFFFFFF);
     464             : #else
     465             :   state->pc = reinterpret_cast<void*>(ucontext->uc_mcontext.psw.addr);
     466             : #endif  // V8_TARGET_ARCH_32_BIT
     467             :   state->sp = reinterpret_cast<void*>(ucontext->uc_mcontext.gregs[15]);
     468             :   state->fp = reinterpret_cast<void*>(ucontext->uc_mcontext.gregs[11]);
     469             : #endif  // V8_HOST_ARCH_*
     470             : #elif V8_OS_MACOSX
     471             : #if V8_HOST_ARCH_X64
     472             : #if __DARWIN_UNIX03
     473             :   state->pc = reinterpret_cast<void*>(mcontext->__ss.__rip);
     474             :   state->sp = reinterpret_cast<void*>(mcontext->__ss.__rsp);
     475             :   state->fp = reinterpret_cast<void*>(mcontext->__ss.__rbp);
     476             : #else  // !__DARWIN_UNIX03
     477             :   state->pc = reinterpret_cast<void*>(mcontext->ss.rip);
     478             :   state->sp = reinterpret_cast<void*>(mcontext->ss.rsp);
     479             :   state->fp = reinterpret_cast<void*>(mcontext->ss.rbp);
     480             : #endif  // __DARWIN_UNIX03
     481             : #elif V8_HOST_ARCH_IA32
     482             : #if __DARWIN_UNIX03
     483             :   state->pc = reinterpret_cast<void*>(mcontext->__ss.__eip);
     484             :   state->sp = reinterpret_cast<void*>(mcontext->__ss.__esp);
     485             :   state->fp = reinterpret_cast<void*>(mcontext->__ss.__ebp);
     486             : #else  // !__DARWIN_UNIX03
     487             :   state->pc = reinterpret_cast<void*>(mcontext->ss.eip);
     488             :   state->sp = reinterpret_cast<void*>(mcontext->ss.esp);
     489             :   state->fp = reinterpret_cast<void*>(mcontext->ss.ebp);
     490             : #endif  // __DARWIN_UNIX03
     491             : #endif  // V8_HOST_ARCH_IA32
     492             : #elif V8_OS_FREEBSD
     493             : #if V8_HOST_ARCH_IA32
     494             :   state->pc = reinterpret_cast<void*>(mcontext.mc_eip);
     495             :   state->sp = reinterpret_cast<void*>(mcontext.mc_esp);
     496             :   state->fp = reinterpret_cast<void*>(mcontext.mc_ebp);
     497             : #elif V8_HOST_ARCH_X64
     498             :   state->pc = reinterpret_cast<void*>(mcontext.mc_rip);
     499             :   state->sp = reinterpret_cast<void*>(mcontext.mc_rsp);
     500             :   state->fp = reinterpret_cast<void*>(mcontext.mc_rbp);
     501             : #elif V8_HOST_ARCH_ARM
     502             :   state->pc = reinterpret_cast<void*>(mcontext.mc_r15);
     503             :   state->sp = reinterpret_cast<void*>(mcontext.mc_r13);
     504             :   state->fp = reinterpret_cast<void*>(mcontext.mc_r11);
     505             : #endif  // V8_HOST_ARCH_*
     506             : #elif V8_OS_NETBSD
     507             : #if V8_HOST_ARCH_IA32
     508             :   state->pc = reinterpret_cast<void*>(mcontext.__gregs[_REG_EIP]);
     509             :   state->sp = reinterpret_cast<void*>(mcontext.__gregs[_REG_ESP]);
     510             :   state->fp = reinterpret_cast<void*>(mcontext.__gregs[_REG_EBP]);
     511             : #elif V8_HOST_ARCH_X64
     512             :   state->pc = reinterpret_cast<void*>(mcontext.__gregs[_REG_RIP]);
     513             :   state->sp = reinterpret_cast<void*>(mcontext.__gregs[_REG_RSP]);
     514             :   state->fp = reinterpret_cast<void*>(mcontext.__gregs[_REG_RBP]);
     515             : #endif  // V8_HOST_ARCH_*
     516             : #elif V8_OS_OPENBSD
     517             : #if V8_HOST_ARCH_IA32
     518             :   state->pc = reinterpret_cast<void*>(ucontext->sc_eip);
     519             :   state->sp = reinterpret_cast<void*>(ucontext->sc_esp);
     520             :   state->fp = reinterpret_cast<void*>(ucontext->sc_ebp);
     521             : #elif V8_HOST_ARCH_X64
     522             :   state->pc = reinterpret_cast<void*>(ucontext->sc_rip);
     523             :   state->sp = reinterpret_cast<void*>(ucontext->sc_rsp);
     524             :   state->fp = reinterpret_cast<void*>(ucontext->sc_rbp);
     525             : #endif  // V8_HOST_ARCH_*
     526             : #elif V8_OS_SOLARIS
     527             :   state->pc = reinterpret_cast<void*>(mcontext.gregs[REG_PC]);
     528             :   state->sp = reinterpret_cast<void*>(mcontext.gregs[REG_SP]);
     529             :   state->fp = reinterpret_cast<void*>(mcontext.gregs[REG_FP]);
     530             : #elif V8_OS_QNX
     531             : #if V8_HOST_ARCH_IA32
     532             :   state->pc = reinterpret_cast<void*>(mcontext.cpu.eip);
     533             :   state->sp = reinterpret_cast<void*>(mcontext.cpu.esp);
     534             :   state->fp = reinterpret_cast<void*>(mcontext.cpu.ebp);
     535             : #elif V8_HOST_ARCH_ARM
     536             :   state->pc = reinterpret_cast<void*>(mcontext.cpu.gpr[ARM_REG_PC]);
     537             :   state->sp = reinterpret_cast<void*>(mcontext.cpu.gpr[ARM_REG_SP]);
     538             :   state->fp = reinterpret_cast<void*>(mcontext.cpu.gpr[ARM_REG_FP]);
     539             : #endif  // V8_HOST_ARCH_*
     540             : #elif V8_OS_AIX
     541             :   state->pc = reinterpret_cast<void*>(mcontext.jmp_context.iar);
     542             :   state->sp = reinterpret_cast<void*>(mcontext.jmp_context.gpr[1]);
     543             :   state->fp = reinterpret_cast<void*>(mcontext.jmp_context.gpr[31]);
     544             : #endif  // V8_OS_AIX
     545           0 : }
     546             : 
     547             : #endif  // USE_SIGNALS
     548             : 
     549             : 
     550       59468 : void Sampler::SetUp() {
     551             : #if defined(USE_SIGNALS)
     552       59468 :   SignalHandler::SetUp();
     553             : #endif
     554       59468 : }
     555             : 
     556             : 
     557       32503 : void Sampler::TearDown() {
     558             : #if defined(USE_SIGNALS)
     559       32503 :   SignalHandler::TearDown();
     560             : #endif
     561       32503 : }
     562             : 
     563       61119 : Sampler::Sampler(Isolate* isolate)
     564             :     : is_counting_samples_(false),
     565             :       js_sample_count_(0),
     566             :       external_sample_count_(0),
     567             :       isolate_(isolate),
     568             :       profiling_(false),
     569             :       has_processing_thread_(false),
     570             :       active_(false),
     571       61119 :       registered_(false) {
     572      122238 :   data_ = new PlatformData;
     573       61119 : }
     574             : 
     575       59622 : Sampler::~Sampler() {
     576             :   DCHECK(!IsActive());
     577             : #if defined(USE_SIGNALS)
     578       59622 :   if (IsRegistered()) {
     579         230 :     SamplerManager::instance()->RemoveSampler(this);
     580             :   }
     581             : #endif
     582       59622 :   delete data_;
     583       59622 : }
     584             : 
     585           7 : void Sampler::Start() {
     586             :   DCHECK(!IsActive());
     587             :   SetActive(true);
     588             : #if defined(USE_SIGNALS)
     589           7 :   SamplerManager::instance()->AddSampler(this);
     590             : #endif
     591           7 : }
     592             : 
     593             : 
     594           7 : void Sampler::Stop() {
     595             : #if defined(USE_SIGNALS)
     596           7 :   SamplerManager::instance()->RemoveSampler(this);
     597             : #endif
     598             :   DCHECK(IsActive());
     599             :   SetActive(false);
     600             :   SetRegistered(false);
     601           7 : }
     602             : 
     603             : 
     604         337 : void Sampler::IncreaseProfilingDepth() {
     605         337 :   base::NoBarrier_AtomicIncrement(&profiling_, 1);
     606             : #if defined(USE_SIGNALS)
     607         337 :   SignalHandler::IncreaseSamplerCount();
     608             : #endif
     609         337 : }
     610             : 
     611             : 
     612         337 : void Sampler::DecreaseProfilingDepth() {
     613             : #if defined(USE_SIGNALS)
     614         337 :   SignalHandler::DecreaseSamplerCount();
     615             : #endif
     616         337 :   base::NoBarrier_AtomicIncrement(&profiling_, -1);
     617         337 : }
     618             : 
     619             : 
     620             : #if defined(USE_SIGNALS)
     621             : 
     622      504198 : void Sampler::DoSample() {
     623      504198 :   if (!SignalHandler::Installed()) return;
     624      497009 :   if (!IsActive() && !IsRegistered()) {
     625         230 :     SamplerManager::instance()->AddSampler(this);
     626             :     SetRegistered(true);
     627             :   }
     628      252099 :   pthread_kill(platform_data()->vm_tid(), SIGPROF);
     629             : }
     630             : 
     631             : #elif V8_OS_WIN || V8_OS_CYGWIN
     632             : 
     633             : void Sampler::DoSample() {
     634             :   HANDLE profiled_thread = platform_data()->profiled_thread();
     635             :   if (profiled_thread == nullptr) return;
     636             : 
     637             :   const DWORD kSuspendFailed = static_cast<DWORD>(-1);
     638             :   if (SuspendThread(profiled_thread) == kSuspendFailed) return;
     639             : 
     640             :   // Context used for sampling the register state of the profiled thread.
     641             :   CONTEXT context;
     642             :   memset(&context, 0, sizeof(context));
     643             :   context.ContextFlags = CONTEXT_FULL;
     644             :   if (GetThreadContext(profiled_thread, &context) != 0) {
     645             :     v8::RegisterState state;
     646             : #if V8_HOST_ARCH_X64
     647             :     state.pc = reinterpret_cast<void*>(context.Rip);
     648             :     state.sp = reinterpret_cast<void*>(context.Rsp);
     649             :     state.fp = reinterpret_cast<void*>(context.Rbp);
     650             : #else
     651             :     state.pc = reinterpret_cast<void*>(context.Eip);
     652             :     state.sp = reinterpret_cast<void*>(context.Esp);
     653             :     state.fp = reinterpret_cast<void*>(context.Ebp);
     654             : #endif
     655             :     SampleStack(state);
     656             :   }
     657             :   ResumeThread(profiled_thread);
     658             : }
     659             : 
     660             : #endif  // USE_SIGNALS
     661             : 
     662             : }  // namespace sampler
     663      118934 : }  // namespace v8

Generated by: LCOV version 1.10