113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch// Copyright 2016 the V8 project authors. All rights reserved.
213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch// Use of this source code is governed by a BSD-style license that can be
313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch// found in the LICENSE file.
413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
5f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include "src/libsampler/sampler.h"
613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#if V8_OS_POSIX && !V8_OS_CYGWIN
813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#define USE_SIGNALS
1013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
1113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#include <errno.h>
1213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#include <pthread.h>
1313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#include <signal.h>
1413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#include <sys/time.h>
1513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
16f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#if !V8_OS_QNX && !V8_OS_AIX
1713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#include <sys/syscall.h>  // NOLINT
1813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#endif
1913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
2013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#if V8_OS_MACOSX
2113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#include <mach/mach.h>
2213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch// OpenBSD doesn't have <ucontext.h>. ucontext_t lives in <signal.h>
2313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch// and is a typedef for struct sigcontext. There is no uc_mcontext.
24f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#elif(!V8_OS_ANDROID || defined(__BIONIC_HAVE_UCONTEXT_T)) && !V8_OS_OPENBSD
2513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#include <ucontext.h>
2613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#endif
2713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
2813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#include <unistd.h>
2913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
3013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch// GLibc on ARM defines mcontext_t has a typedef for 'struct sigcontext'.
3113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch// Old versions of the C library <signal.h> didn't define the type.
3213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#if V8_OS_ANDROID && !defined(__BIONIC_HAVE_UCONTEXT_T) && \
3313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    (defined(__arm__) || defined(__aarch64__)) && \
3413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    !defined(__BIONIC_HAVE_STRUCT_SIGCONTEXT)
3513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#include <asm/sigcontext.h>  // NOLINT
3613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#endif
3713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
3813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#elif V8_OS_WIN || V8_OS_CYGWIN
3913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
4013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#include "src/base/win32-headers.h"
4113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
4213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#endif
4313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
4413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#include <algorithm>
4513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#include <vector>
4613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#include <map>
4713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
4813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#include "src/base/atomic-utils.h"
4913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#include "src/base/hashmap.h"
5013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#include "src/base/platform/platform.h"
5113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
5213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#if V8_OS_ANDROID && !defined(__BIONIC_HAVE_UCONTEXT_T)
5313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
5413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch// Not all versions of Android's C library provide ucontext_t.
5513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch// Detect this and provide custom but compatible definitions. Note that these
5613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch// follow the GLibc naming convention to access register values from
5713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch// mcontext_t.
5813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch//
5913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch// See http://code.google.com/p/android/issues/detail?id=34784
6013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
6113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#if defined(__arm__)
6213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
6313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochtypedef struct sigcontext mcontext_t;
6413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
6513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochtypedef struct ucontext {
6613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  uint32_t uc_flags;
6713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  struct ucontext* uc_link;
6813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  stack_t uc_stack;
6913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  mcontext_t uc_mcontext;
7013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // Other fields are not used by V8, don't define them here.
7113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} ucontext_t;
7213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
7313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#elif defined(__aarch64__)
7413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
7513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochtypedef struct sigcontext mcontext_t;
7613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
7713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochtypedef struct ucontext {
7813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  uint64_t uc_flags;
7913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  struct ucontext *uc_link;
8013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  stack_t uc_stack;
8113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  mcontext_t uc_mcontext;
8213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // Other fields are not used by V8, don't define them here.
8313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} ucontext_t;
8413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
8513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#elif defined(__mips__)
8613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch// MIPS version of sigcontext, for Android bionic.
8713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochtypedef struct {
8813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  uint32_t regmask;
8913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  uint32_t status;
9013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  uint64_t pc;
9113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  uint64_t gregs[32];
9213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  uint64_t fpregs[32];
9313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  uint32_t acx;
9413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  uint32_t fpc_csr;
9513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  uint32_t fpc_eir;
9613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  uint32_t used_math;
9713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  uint32_t dsp;
9813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  uint64_t mdhi;
9913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  uint64_t mdlo;
10013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  uint32_t hi1;
10113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  uint32_t lo1;
10213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  uint32_t hi2;
10313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  uint32_t lo2;
10413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  uint32_t hi3;
10513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  uint32_t lo3;
10613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} mcontext_t;
10713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
10813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochtypedef struct ucontext {
10913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  uint32_t uc_flags;
11013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  struct ucontext* uc_link;
11113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  stack_t uc_stack;
11213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  mcontext_t uc_mcontext;
11313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // Other fields are not used by V8, don't define them here.
11413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} ucontext_t;
11513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
11613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#elif defined(__i386__)
11713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch// x86 version for Android.
11813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochtypedef struct {
11913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  uint32_t gregs[19];
12013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  void* fpregs;
12113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  uint32_t oldmask;
12213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  uint32_t cr2;
12313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} mcontext_t;
12413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
12513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochtypedef uint32_t kernel_sigset_t[2];  // x86 kernel uses 64-bit signal masks
12613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochtypedef struct ucontext {
12713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  uint32_t uc_flags;
12813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  struct ucontext* uc_link;
12913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  stack_t uc_stack;
13013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  mcontext_t uc_mcontext;
13113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // Other fields are not used by V8, don't define them here.
13213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} ucontext_t;
13313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochenum { REG_EBP = 6, REG_ESP = 7, REG_EIP = 14 };
13413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
13513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#elif defined(__x86_64__)
13613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch// x64 version for Android.
13713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochtypedef struct {
13813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  uint64_t gregs[23];
13913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  void* fpregs;
14013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  uint64_t __reserved1[8];
14113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} mcontext_t;
14213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
14313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochtypedef struct ucontext {
14413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  uint64_t uc_flags;
14513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  struct ucontext *uc_link;
14613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  stack_t uc_stack;
14713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  mcontext_t uc_mcontext;
14813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // Other fields are not used by V8, don't define them here.
14913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} ucontext_t;
15013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochenum { REG_RBP = 10, REG_RSP = 15, REG_RIP = 16 };
15113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#endif
15213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
15313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#endif  // V8_OS_ANDROID && !defined(__BIONIC_HAVE_UCONTEXT_T)
15413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
15513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
15613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochnamespace v8 {
15713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochnamespace sampler {
15813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
15913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochnamespace {
16013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
16113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#if defined(USE_SIGNALS)
16213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochtypedef std::vector<Sampler*> SamplerList;
16313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochtypedef SamplerList::iterator SamplerListIterator;
16413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochtypedef base::AtomicValue<bool> AtomicMutex;
16513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
16613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochclass AtomicGuard {
16713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch public:
16813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  explicit AtomicGuard(AtomicMutex* atomic, bool is_blocking = true)
16913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      : atomic_(atomic), is_success_(false) {
17013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    do {
17113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      // Use Acquire_Load to gain mutual exclusion.
17213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      USE(atomic_->Value());
17313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      is_success_ = atomic_->TrySetValue(false, true);
17413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    } while (is_blocking && !is_success_);
17513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
17613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
17713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  bool is_success() const { return is_success_; }
17813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
17913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  ~AtomicGuard() {
18013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (!is_success_) return;
18113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    atomic_->SetValue(false);
18213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
18313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
18413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch private:
18513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  AtomicMutex* const atomic_;
18613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  bool is_success_;
18713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch};
18813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
18913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch// Returns key for hash map.
19013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid* ThreadKey(pthread_t thread_id) {
19113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  return reinterpret_cast<void*>(thread_id);
19213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
19313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
19413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch// Returns hash value for hash map.
19513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochuint32_t ThreadHash(pthread_t thread_id) {
196f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#if V8_OS_BSD
19713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  return static_cast<uint32_t>(reinterpret_cast<intptr_t>(thread_id));
19813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#else
19913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  return static_cast<uint32_t>(thread_id);
20013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#endif
20113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
20213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
20313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#endif  // USE_SIGNALS
20413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
20513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}  // namespace
20613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
20713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#if defined(USE_SIGNALS)
20813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
20913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochclass Sampler::PlatformData {
21013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch public:
21113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  PlatformData() : vm_tid_(pthread_self()) {}
21213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  pthread_t vm_tid() const { return vm_tid_; }
21313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
21413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch private:
21513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  pthread_t vm_tid_;
21613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch};
21713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
21813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochclass SamplerManager {
21913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch public:
220f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  SamplerManager() : sampler_map_() {}
22113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
22213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  void AddSampler(Sampler* sampler) {
22313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    AtomicGuard atomic_guard(&samplers_access_counter_);
22413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    DCHECK(sampler->IsActive() || !sampler->IsRegistered());
22513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // Add sampler into map if needed.
22613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    pthread_t thread_id = sampler->platform_data()->vm_tid();
22713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    base::HashMap::Entry* entry =
22813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch            sampler_map_.LookupOrInsert(ThreadKey(thread_id),
22913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                                        ThreadHash(thread_id));
23013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    DCHECK(entry != nullptr);
23113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (entry->value == nullptr) {
23213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      SamplerList* samplers = new SamplerList();
23313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      samplers->push_back(sampler);
23413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      entry->value = samplers;
23513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    } else {
23613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      SamplerList* samplers = reinterpret_cast<SamplerList*>(entry->value);
23713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      bool exists = false;
23813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      for (SamplerListIterator iter = samplers->begin();
23913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch           iter != samplers->end(); ++iter) {
24013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        if (*iter == sampler) {
24113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          exists = true;
24213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          break;
24313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        }
24413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      }
24513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      if (!exists) {
24613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        samplers->push_back(sampler);
24713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      }
24813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
24913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
25013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
25113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  void RemoveSampler(Sampler* sampler) {
25213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    AtomicGuard atomic_guard(&samplers_access_counter_);
25313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    DCHECK(sampler->IsActive() || sampler->IsRegistered());
25413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // Remove sampler from map.
25513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    pthread_t thread_id = sampler->platform_data()->vm_tid();
25613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    void* thread_key = ThreadKey(thread_id);
25713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    uint32_t thread_hash = ThreadHash(thread_id);
25813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    base::HashMap::Entry* entry = sampler_map_.Lookup(thread_key, thread_hash);
25913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    DCHECK(entry != nullptr);
26013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    SamplerList* samplers = reinterpret_cast<SamplerList*>(entry->value);
26113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    for (SamplerListIterator iter = samplers->begin(); iter != samplers->end();
26213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch         ++iter) {
26313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      if (*iter == sampler) {
26413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        samplers->erase(iter);
26513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        break;
26613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      }
26713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
26813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (samplers->empty()) {
26913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      sampler_map_.Remove(thread_key, thread_hash);
27013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      delete samplers;
27113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
27213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
27313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
27413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#if defined(USE_SIGNALS)
27513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  void DoSample(const v8::RegisterState& state) {
27613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    AtomicGuard atomic_guard(&SamplerManager::samplers_access_counter_, false);
27713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (!atomic_guard.is_success()) return;
27813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    pthread_t thread_id = pthread_self();
27913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    base::HashMap::Entry* entry =
28013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        sampler_map_.Lookup(ThreadKey(thread_id), ThreadHash(thread_id));
28113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (!entry) return;
28213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    SamplerList& samplers = *static_cast<SamplerList*>(entry->value);
28313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
284c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    for (size_t i = 0; i < samplers.size(); ++i) {
28513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      Sampler* sampler = samplers[i];
28613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      Isolate* isolate = sampler->isolate();
28713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      // We require a fully initialized and entered isolate.
28813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      if (isolate == nullptr || !isolate->IsInUse()) continue;
28913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      if (v8::Locker::IsActive() && !Locker::IsLocked(isolate)) continue;
29013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      sampler->SampleStack(state);
29113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
29213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
29313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#endif
29413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
29513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static SamplerManager* instance() { return instance_.Pointer(); }
29613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
29713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch private:
29813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  base::HashMap sampler_map_;
29913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static AtomicMutex samplers_access_counter_;
30013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static base::LazyInstance<SamplerManager>::type instance_;
30113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch};
30213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
30313e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochAtomicMutex SamplerManager::samplers_access_counter_;
30413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochbase::LazyInstance<SamplerManager>::type SamplerManager::instance_ =
30513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    LAZY_INSTANCE_INITIALIZER;
30613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
30713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#elif V8_OS_WIN || V8_OS_CYGWIN
30813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
30913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch// ----------------------------------------------------------------------------
31013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch// Win32 profiler support. On Cygwin we use the same sampler implementation as
31113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch// on Win32.
31213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
31313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochclass Sampler::PlatformData {
31413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch public:
31513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // Get a handle to the calling thread. This is the thread that we are
31613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // going to profile. We need to make a copy of the handle because we are
31713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // going to use it in the sampler thread. Using GetThreadHandle() will
31813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // not work in this case. We're using OpenThread because DuplicateHandle
31913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // for some reason doesn't work in Chrome's sandbox.
32013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  PlatformData()
32113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      : profiled_thread_(OpenThread(THREAD_GET_CONTEXT |
32213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                                    THREAD_SUSPEND_RESUME |
32313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                                    THREAD_QUERY_INFORMATION,
32413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                                    false,
32513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                                    GetCurrentThreadId())) {}
32613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
32713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  ~PlatformData() {
32813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (profiled_thread_ != nullptr) {
32913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      CloseHandle(profiled_thread_);
33013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      profiled_thread_ = nullptr;
33113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
33213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
33313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
33413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  HANDLE profiled_thread() { return profiled_thread_; }
33513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
33613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch private:
33713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  HANDLE profiled_thread_;
33813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch};
33913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#endif  // USE_SIGNALS
34013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
34113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
34213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#if defined(USE_SIGNALS)
34313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochclass SignalHandler {
34413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch public:
34513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static void SetUp() { if (!mutex_) mutex_ = new base::Mutex(); }
34613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static void TearDown() {
34713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    delete mutex_;
34813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    mutex_ = nullptr;
34913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
35013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
35113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static void IncreaseSamplerCount() {
35213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    base::LockGuard<base::Mutex> lock_guard(mutex_);
35313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (++client_count_ == 1) Install();
35413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
35513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
35613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static void DecreaseSamplerCount() {
35713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    base::LockGuard<base::Mutex> lock_guard(mutex_);
35813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (--client_count_ == 0) Restore();
35913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
36013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
36113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static bool Installed() {
36213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    base::LockGuard<base::Mutex> lock_guard(mutex_);
36313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return signal_handler_installed_;
36413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
36513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
36613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch private:
36713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static void Install() {
36813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    struct sigaction sa;
36913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    sa.sa_sigaction = &HandleProfilerSignal;
37013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    sigemptyset(&sa.sa_mask);
37113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#if V8_OS_QNX
37213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    sa.sa_flags = SA_SIGINFO;
37313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#else
37413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    sa.sa_flags = SA_RESTART | SA_SIGINFO;
37513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#endif
37613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    signal_handler_installed_ =
37713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        (sigaction(SIGPROF, &sa, &old_signal_handler_) == 0);
37813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
37913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
38013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static void Restore() {
38113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (signal_handler_installed_) {
38213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      sigaction(SIGPROF, &old_signal_handler_, 0);
38313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      signal_handler_installed_ = false;
38413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
38513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
38613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
38713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static void FillRegisterState(void* context, RegisterState* regs);
38813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static void HandleProfilerSignal(int signal, siginfo_t* info, void* context);
389f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
39013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // Protects the process wide state below.
39113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static base::Mutex* mutex_;
39213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static int client_count_;
39313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static bool signal_handler_installed_;
39413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static struct sigaction old_signal_handler_;
39513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch};
39613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
39713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochbase::Mutex* SignalHandler::mutex_ = nullptr;
39813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochint SignalHandler::client_count_ = 0;
39913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochstruct sigaction SignalHandler::old_signal_handler_;
40013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochbool SignalHandler::signal_handler_installed_ = false;
40113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
40213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
40313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid SignalHandler::HandleProfilerSignal(int signal, siginfo_t* info,
40413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                                         void* context) {
40513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  USE(info);
40613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (signal != SIGPROF) return;
40713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  v8::RegisterState state;
40813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  FillRegisterState(context, &state);
40913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  SamplerManager::instance()->DoSample(state);
41013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
41113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
41213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid SignalHandler::FillRegisterState(void* context, RegisterState* state) {
41313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // Extracting the sample from the context is extremely machine dependent.
41413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
41513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#if !(V8_OS_OPENBSD || (V8_OS_LINUX && (V8_HOST_ARCH_PPC || V8_HOST_ARCH_S390)))
41613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  mcontext_t& mcontext = ucontext->uc_mcontext;
41713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#endif
41813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#if V8_OS_LINUX
41913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#if V8_HOST_ARCH_IA32
42013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->pc = reinterpret_cast<void*>(mcontext.gregs[REG_EIP]);
42113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->sp = reinterpret_cast<void*>(mcontext.gregs[REG_ESP]);
42213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->fp = reinterpret_cast<void*>(mcontext.gregs[REG_EBP]);
42313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#elif V8_HOST_ARCH_X64
42413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->pc = reinterpret_cast<void*>(mcontext.gregs[REG_RIP]);
42513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->sp = reinterpret_cast<void*>(mcontext.gregs[REG_RSP]);
42613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->fp = reinterpret_cast<void*>(mcontext.gregs[REG_RBP]);
42713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#elif V8_HOST_ARCH_ARM
42813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#if V8_LIBC_GLIBC && !V8_GLIBC_PREREQ(2, 4)
42913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // Old GLibc ARM versions used a gregs[] array to access the register
43013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // values from mcontext_t.
43113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->pc = reinterpret_cast<void*>(mcontext.gregs[R15]);
43213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->sp = reinterpret_cast<void*>(mcontext.gregs[R13]);
43313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->fp = reinterpret_cast<void*>(mcontext.gregs[R11]);
43413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#else
43513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->pc = reinterpret_cast<void*>(mcontext.arm_pc);
43613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->sp = reinterpret_cast<void*>(mcontext.arm_sp);
43713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->fp = reinterpret_cast<void*>(mcontext.arm_fp);
43813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#endif  // V8_LIBC_GLIBC && !V8_GLIBC_PREREQ(2, 4)
43913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#elif V8_HOST_ARCH_ARM64
44013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->pc = reinterpret_cast<void*>(mcontext.pc);
44113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->sp = reinterpret_cast<void*>(mcontext.sp);
44213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // FP is an alias for x29.
44313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->fp = reinterpret_cast<void*>(mcontext.regs[29]);
44413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#elif V8_HOST_ARCH_MIPS
44513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->pc = reinterpret_cast<void*>(mcontext.pc);
44613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->sp = reinterpret_cast<void*>(mcontext.gregs[29]);
44713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->fp = reinterpret_cast<void*>(mcontext.gregs[30]);
44813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#elif V8_HOST_ARCH_MIPS64
44913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->pc = reinterpret_cast<void*>(mcontext.pc);
45013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->sp = reinterpret_cast<void*>(mcontext.gregs[29]);
45113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->fp = reinterpret_cast<void*>(mcontext.gregs[30]);
45213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#elif V8_HOST_ARCH_PPC
45313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->pc = reinterpret_cast<void*>(ucontext->uc_mcontext.regs->nip);
45413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->sp =
45513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      reinterpret_cast<void*>(ucontext->uc_mcontext.regs->gpr[PT_R1]);
45613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->fp =
45713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      reinterpret_cast<void*>(ucontext->uc_mcontext.regs->gpr[PT_R31]);
45813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#elif V8_HOST_ARCH_S390
45913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#if V8_TARGET_ARCH_32_BIT
46013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // 31-bit target will have bit 0 (MSB) of the PSW set to denote addressing
46113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // mode.  This bit needs to be masked out to resolve actual address.
46213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->pc =
46313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      reinterpret_cast<void*>(ucontext->uc_mcontext.psw.addr & 0x7FFFFFFF);
46413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#else
46513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->pc = reinterpret_cast<void*>(ucontext->uc_mcontext.psw.addr);
46613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#endif  // V8_TARGET_ARCH_32_BIT
46713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->sp = reinterpret_cast<void*>(ucontext->uc_mcontext.gregs[15]);
46813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->fp = reinterpret_cast<void*>(ucontext->uc_mcontext.gregs[11]);
46913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#endif  // V8_HOST_ARCH_*
47013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#elif V8_OS_MACOSX
47113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#if V8_HOST_ARCH_X64
47213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#if __DARWIN_UNIX03
47313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->pc = reinterpret_cast<void*>(mcontext->__ss.__rip);
47413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->sp = reinterpret_cast<void*>(mcontext->__ss.__rsp);
47513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->fp = reinterpret_cast<void*>(mcontext->__ss.__rbp);
47613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#else  // !__DARWIN_UNIX03
47713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->pc = reinterpret_cast<void*>(mcontext->ss.rip);
47813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->sp = reinterpret_cast<void*>(mcontext->ss.rsp);
47913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->fp = reinterpret_cast<void*>(mcontext->ss.rbp);
48013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#endif  // __DARWIN_UNIX03
48113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#elif V8_HOST_ARCH_IA32
48213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#if __DARWIN_UNIX03
48313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->pc = reinterpret_cast<void*>(mcontext->__ss.__eip);
48413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->sp = reinterpret_cast<void*>(mcontext->__ss.__esp);
48513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->fp = reinterpret_cast<void*>(mcontext->__ss.__ebp);
48613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#else  // !__DARWIN_UNIX03
48713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->pc = reinterpret_cast<void*>(mcontext->ss.eip);
48813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->sp = reinterpret_cast<void*>(mcontext->ss.esp);
48913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->fp = reinterpret_cast<void*>(mcontext->ss.ebp);
49013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#endif  // __DARWIN_UNIX03
49113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#endif  // V8_HOST_ARCH_IA32
49213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#elif V8_OS_FREEBSD
49313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#if V8_HOST_ARCH_IA32
49413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->pc = reinterpret_cast<void*>(mcontext.mc_eip);
49513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->sp = reinterpret_cast<void*>(mcontext.mc_esp);
49613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->fp = reinterpret_cast<void*>(mcontext.mc_ebp);
49713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#elif V8_HOST_ARCH_X64
49813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->pc = reinterpret_cast<void*>(mcontext.mc_rip);
49913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->sp = reinterpret_cast<void*>(mcontext.mc_rsp);
50013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->fp = reinterpret_cast<void*>(mcontext.mc_rbp);
50113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#elif V8_HOST_ARCH_ARM
50213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->pc = reinterpret_cast<void*>(mcontext.mc_r15);
50313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->sp = reinterpret_cast<void*>(mcontext.mc_r13);
50413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->fp = reinterpret_cast<void*>(mcontext.mc_r11);
50513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#endif  // V8_HOST_ARCH_*
50613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#elif V8_OS_NETBSD
50713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#if V8_HOST_ARCH_IA32
50813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->pc = reinterpret_cast<void*>(mcontext.__gregs[_REG_EIP]);
50913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->sp = reinterpret_cast<void*>(mcontext.__gregs[_REG_ESP]);
51013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->fp = reinterpret_cast<void*>(mcontext.__gregs[_REG_EBP]);
51113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#elif V8_HOST_ARCH_X64
51213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->pc = reinterpret_cast<void*>(mcontext.__gregs[_REG_RIP]);
51313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->sp = reinterpret_cast<void*>(mcontext.__gregs[_REG_RSP]);
51413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->fp = reinterpret_cast<void*>(mcontext.__gregs[_REG_RBP]);
51513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#endif  // V8_HOST_ARCH_*
51613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#elif V8_OS_OPENBSD
51713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#if V8_HOST_ARCH_IA32
51813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->pc = reinterpret_cast<void*>(ucontext->sc_eip);
51913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->sp = reinterpret_cast<void*>(ucontext->sc_esp);
52013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->fp = reinterpret_cast<void*>(ucontext->sc_ebp);
52113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#elif V8_HOST_ARCH_X64
52213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->pc = reinterpret_cast<void*>(ucontext->sc_rip);
52313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->sp = reinterpret_cast<void*>(ucontext->sc_rsp);
52413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->fp = reinterpret_cast<void*>(ucontext->sc_rbp);
52513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#endif  // V8_HOST_ARCH_*
52613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#elif V8_OS_SOLARIS
52713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->pc = reinterpret_cast<void*>(mcontext.gregs[REG_PC]);
52813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->sp = reinterpret_cast<void*>(mcontext.gregs[REG_SP]);
52913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->fp = reinterpret_cast<void*>(mcontext.gregs[REG_FP]);
53013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#elif V8_OS_QNX
53113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#if V8_HOST_ARCH_IA32
53213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->pc = reinterpret_cast<void*>(mcontext.cpu.eip);
53313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->sp = reinterpret_cast<void*>(mcontext.cpu.esp);
53413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->fp = reinterpret_cast<void*>(mcontext.cpu.ebp);
53513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#elif V8_HOST_ARCH_ARM
53613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->pc = reinterpret_cast<void*>(mcontext.cpu.gpr[ARM_REG_PC]);
53713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->sp = reinterpret_cast<void*>(mcontext.cpu.gpr[ARM_REG_SP]);
53813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->fp = reinterpret_cast<void*>(mcontext.cpu.gpr[ARM_REG_FP]);
53913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#endif  // V8_HOST_ARCH_*
54013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#elif V8_OS_AIX
54113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->pc = reinterpret_cast<void*>(mcontext.jmp_context.iar);
54213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->sp = reinterpret_cast<void*>(mcontext.jmp_context.gpr[1]);
54313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  state->fp = reinterpret_cast<void*>(mcontext.jmp_context.gpr[31]);
54413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#endif  // V8_OS_AIX
54513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
54613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
54713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#endif  // USE_SIGNALS
54813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
54913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
55013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid Sampler::SetUp() {
55113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#if defined(USE_SIGNALS)
55213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  SignalHandler::SetUp();
55313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#endif
55413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
55513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
55613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
55713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid Sampler::TearDown() {
55813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#if defined(USE_SIGNALS)
55913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  SignalHandler::TearDown();
56013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#endif
56113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
56213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
56313e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochSampler::Sampler(Isolate* isolate)
56413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    : is_counting_samples_(false),
56513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      js_sample_count_(0),
56613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      external_sample_count_(0),
56713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      isolate_(isolate),
56813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      profiling_(false),
56913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      has_processing_thread_(false),
57013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      active_(false),
57113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      registered_(false) {
57213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  data_ = new PlatformData;
57313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
57413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
57513e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochSampler::~Sampler() {
57613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  DCHECK(!IsActive());
57713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#if defined(USE_SIGNALS)
57813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (IsRegistered()) {
57913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    SamplerManager::instance()->RemoveSampler(this);
58013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
58113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#endif
58213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  delete data_;
58313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
58413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
58513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid Sampler::Start() {
58613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  DCHECK(!IsActive());
58713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  SetActive(true);
58813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#if defined(USE_SIGNALS)
58913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  SamplerManager::instance()->AddSampler(this);
59013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#endif
59113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
59213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
59313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
59413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid Sampler::Stop() {
59513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#if defined(USE_SIGNALS)
59613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  SamplerManager::instance()->RemoveSampler(this);
59713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#endif
59813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  DCHECK(IsActive());
59913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  SetActive(false);
60013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  SetRegistered(false);
60113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
60213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
60313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
60413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid Sampler::IncreaseProfilingDepth() {
60513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  base::NoBarrier_AtomicIncrement(&profiling_, 1);
60613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#if defined(USE_SIGNALS)
60713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  SignalHandler::IncreaseSamplerCount();
60813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#endif
60913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
61013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
61113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
61213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid Sampler::DecreaseProfilingDepth() {
61313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#if defined(USE_SIGNALS)
61413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  SignalHandler::DecreaseSamplerCount();
61513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#endif
61613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  base::NoBarrier_AtomicIncrement(&profiling_, -1);
61713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
61813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
61913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
62013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#if defined(USE_SIGNALS)
62113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
62213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid Sampler::DoSample() {
62313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (!SignalHandler::Installed()) return;
62413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (!IsActive() && !IsRegistered()) {
62513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    SamplerManager::instance()->AddSampler(this);
62613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    SetRegistered(true);
62713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
62813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  pthread_kill(platform_data()->vm_tid(), SIGPROF);
62913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
63013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
63113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#elif V8_OS_WIN || V8_OS_CYGWIN
63213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
63313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid Sampler::DoSample() {
63413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  HANDLE profiled_thread = platform_data()->profiled_thread();
63513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (profiled_thread == nullptr) return;
63613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
63713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  const DWORD kSuspendFailed = static_cast<DWORD>(-1);
63813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (SuspendThread(profiled_thread) == kSuspendFailed) return;
63913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
64013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // Context used for sampling the register state of the profiled thread.
64113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  CONTEXT context;
64213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  memset(&context, 0, sizeof(context));
64313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  context.ContextFlags = CONTEXT_FULL;
64413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (GetThreadContext(profiled_thread, &context) != 0) {
64513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    v8::RegisterState state;
64613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#if V8_HOST_ARCH_X64
64713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    state.pc = reinterpret_cast<void*>(context.Rip);
64813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    state.sp = reinterpret_cast<void*>(context.Rsp);
64913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    state.fp = reinterpret_cast<void*>(context.Rbp);
65013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#else
65113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    state.pc = reinterpret_cast<void*>(context.Eip);
65213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    state.sp = reinterpret_cast<void*>(context.Esp);
65313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    state.fp = reinterpret_cast<void*>(context.Ebp);
65413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#endif
65513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    SampleStack(state);
65613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
65713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  ResumeThread(profiled_thread);
65813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
65913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
66013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#endif  // USE_SIGNALS
66113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
66213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}  // namespace sampler
66313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}  // namespace v8
664