OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef V8_SAMPLER_H_ | 5 #ifndef V8_SAMPLER_H_ |
6 #define V8_SAMPLER_H_ | 6 #define V8_SAMPLER_H_ |
7 | 7 |
8 #include "src/base/atomicops.h" | 8 #include "src/base/atomicops.h" |
9 #include "src/frames.h" | 9 #include "src/frames.h" |
10 #include "src/globals.h" | 10 #include "src/globals.h" |
11 | 11 |
| 12 #if V8_OS_POSIX && !V8_OS_CYGWIN |
| 13 |
| 14 #define USE_SIGNALS |
| 15 |
| 16 #include <errno.h> |
| 17 #include <pthread.h> |
| 18 #include <signal.h> |
| 19 #include <sys/time.h> |
| 20 |
| 21 #if !V8_OS_QNX && !V8_OS_NACL |
| 22 #include <sys/syscall.h> // NOLINT |
| 23 #endif |
| 24 |
| 25 #if V8_OS_MACOSX |
| 26 #include <mach/mach.h> |
| 27 // OpenBSD doesn't have <ucontext.h>. ucontext_t lives in <signal.h> |
| 28 // and is a typedef for struct sigcontext. There is no uc_mcontext. |
| 29 #elif(!V8_OS_ANDROID || defined(__BIONIC_HAVE_UCONTEXT_T)) && \ |
| 30 !V8_OS_OPENBSD && !V8_OS_NACL |
| 31 #include <ucontext.h> |
| 32 #endif |
| 33 |
| 34 #include <unistd.h> |
| 35 |
| 36 // GLibc on ARM defines mcontext_t has a typedef for 'struct sigcontext'. |
| 37 // Old versions of the C library <signal.h> didn't define the type. |
| 38 #if V8_OS_ANDROID && !defined(__BIONIC_HAVE_UCONTEXT_T) && \ |
| 39 (defined(__arm__) || defined(__aarch64__)) && \ |
| 40 !defined(__BIONIC_HAVE_STRUCT_SIGCONTEXT) |
| 41 #include <asm/sigcontext.h> // NOLINT |
| 42 #endif |
| 43 |
| 44 #elif V8_OS_WIN || V8_OS_CYGWIN |
| 45 |
| 46 #include "src/base/win32-headers.h" |
| 47 |
| 48 #endif |
| 49 |
| 50 |
| 51 #if V8_OS_ANDROID && !defined(__BIONIC_HAVE_UCONTEXT_T) |
| 52 |
| 53 // Not all versions of Android's C library provide ucontext_t. |
| 54 // Detect this and provide custom but compatible definitions. Note that these |
| 55 // follow the GLibc naming convention to access register values from |
| 56 // mcontext_t. |
| 57 // |
| 58 // See http://code.google.com/p/android/issues/detail?id=34784 |
| 59 |
| 60 #if defined(__arm__) |
| 61 |
| 62 typedef struct sigcontext mcontext_t; |
| 63 |
| 64 typedef struct ucontext { |
| 65 uint32_t uc_flags; |
| 66 struct ucontext* uc_link; |
| 67 stack_t uc_stack; |
| 68 mcontext_t uc_mcontext; |
| 69 // Other fields are not used by V8, don't define them here. |
| 70 } ucontext_t; |
| 71 |
| 72 #elif defined(__aarch64__) |
| 73 |
| 74 typedef struct sigcontext mcontext_t; |
| 75 |
| 76 typedef struct ucontext { |
| 77 uint64_t uc_flags; |
| 78 struct ucontext *uc_link; |
| 79 stack_t uc_stack; |
| 80 mcontext_t uc_mcontext; |
| 81 // Other fields are not used by V8, don't define them here. |
| 82 } ucontext_t; |
| 83 |
| 84 #elif defined(__mips__) |
| 85 // MIPS version of sigcontext, for Android bionic. |
| 86 typedef struct { |
| 87 uint32_t regmask; |
| 88 uint32_t status; |
| 89 uint64_t pc; |
| 90 uint64_t gregs[32]; |
| 91 uint64_t fpregs[32]; |
| 92 uint32_t acx; |
| 93 uint32_t fpc_csr; |
| 94 uint32_t fpc_eir; |
| 95 uint32_t used_math; |
| 96 uint32_t dsp; |
| 97 uint64_t mdhi; |
| 98 uint64_t mdlo; |
| 99 uint32_t hi1; |
| 100 uint32_t lo1; |
| 101 uint32_t hi2; |
| 102 uint32_t lo2; |
| 103 uint32_t hi3; |
| 104 uint32_t lo3; |
| 105 } mcontext_t; |
| 106 |
| 107 typedef struct ucontext { |
| 108 uint32_t uc_flags; |
| 109 struct ucontext* uc_link; |
| 110 stack_t uc_stack; |
| 111 mcontext_t uc_mcontext; |
| 112 // Other fields are not used by V8, don't define them here. |
| 113 } ucontext_t; |
| 114 |
| 115 #elif defined(__i386__) |
| 116 // x86 version for Android. |
| 117 typedef struct { |
| 118 uint32_t gregs[19]; |
| 119 void* fpregs; |
| 120 uint32_t oldmask; |
| 121 uint32_t cr2; |
| 122 } mcontext_t; |
| 123 |
| 124 typedef uint32_t kernel_sigset_t[2]; // x86 kernel uses 64-bit signal masks |
| 125 typedef struct ucontext { |
| 126 uint32_t uc_flags; |
| 127 struct ucontext* uc_link; |
| 128 stack_t uc_stack; |
| 129 mcontext_t uc_mcontext; |
| 130 // Other fields are not used by V8, don't define them here. |
| 131 } ucontext_t; |
| 132 enum { REG_EBP = 6, REG_ESP = 7, REG_EIP = 14 }; |
| 133 |
| 134 #elif defined(__x86_64__) |
| 135 // x64 version for Android. |
| 136 typedef struct { |
| 137 uint64_t gregs[23]; |
| 138 void* fpregs; |
| 139 uint64_t __reserved1[8]; |
| 140 } mcontext_t; |
| 141 |
| 142 typedef struct ucontext { |
| 143 uint64_t uc_flags; |
| 144 struct ucontext *uc_link; |
| 145 stack_t uc_stack; |
| 146 mcontext_t uc_mcontext; |
| 147 // Other fields are not used by V8, don't define them here. |
| 148 } ucontext_t; |
| 149 enum { REG_RBP = 10, REG_RSP = 15, REG_RIP = 16 }; |
| 150 #endif |
| 151 |
| 152 #endif // V8_OS_ANDROID && !defined(__BIONIC_HAVE_UCONTEXT_T) |
| 153 |
| 154 |
12 namespace v8 { | 155 namespace v8 { |
13 namespace internal { | 156 namespace internal { |
14 | 157 |
15 class Isolate; | 158 class Isolate; |
16 | 159 |
17 // ---------------------------------------------------------------------------- | 160 // ---------------------------------------------------------------------------- |
18 // Sampler | 161 // Sampler |
19 // | 162 // |
20 // A sampler periodically samples the state of the VM and optionally | 163 // A sampler periodically samples the state of the VM and optionally |
21 // (if used for profiling) the program counter and stack pointer for | 164 // (if used for profiling) the program counter and stack pointer for |
22 // the thread that created it. | 165 // the thread that created it. |
23 | 166 |
24 struct RegisterState { | |
25 RegisterState() : pc(NULL), sp(NULL), fp(NULL) {} | |
26 Address pc; // Instruction pointer. | |
27 Address sp; // Stack pointer. | |
28 Address fp; // Frame pointer. | |
29 }; | |
30 | |
31 // TickSample captures the information collected for each sample. | 167 // TickSample captures the information collected for each sample. |
32 struct TickSample { | 168 struct TickSample { |
33 TickSample() | 169 TickSample() |
34 : state(OTHER), | 170 : state(OTHER), |
35 pc(NULL), | 171 pc(NULL), |
36 external_callback(NULL), | 172 external_callback(NULL), |
37 frames_count(0), | 173 frames_count(0), |
38 has_external_callback(false), | 174 has_external_callback(false), |
39 top_frame_type(StackFrame::NONE) {} | 175 top_frame_type(StackFrame::NONE) {} |
40 void Init(Isolate* isolate, const RegisterState& state); | 176 void Init(Isolate* isolate, const v8::RegisterState& state); |
41 StateTag state; // The state of the VM. | 177 StateTag state; // The state of the VM. |
42 Address pc; // Instruction pointer. | 178 Address pc; // Instruction pointer. |
43 union { | 179 union { |
44 Address tos; // Top stack value (*sp). | 180 Address tos; // Top stack value (*sp). |
45 Address external_callback; | 181 Address external_callback; |
46 }; | 182 }; |
47 static const unsigned kMaxFramesCountLog2 = 8; | 183 static const unsigned kMaxFramesCountLog2 = 8; |
48 static const unsigned kMaxFramesCount = (1 << kMaxFramesCountLog2) - 1; | 184 static const unsigned kMaxFramesCount = (1 << kMaxFramesCountLog2) - 1; |
49 Address stack[kMaxFramesCount]; // Call stack. | 185 Address stack[kMaxFramesCount]; // Call stack. |
50 base::TimeTicks timestamp; | 186 base::TimeTicks timestamp; |
51 unsigned frames_count : kMaxFramesCountLog2; // Number of captured frames. | 187 unsigned frames_count : kMaxFramesCountLog2; // Number of captured frames. |
52 bool has_external_callback : 1; | 188 bool has_external_callback : 1; |
53 StackFrame::Type top_frame_type : 4; | 189 StackFrame::Type top_frame_type : 4; |
54 }; | 190 }; |
55 | 191 |
56 class Sampler { | 192 class Sampler { |
57 public: | 193 public: |
58 // Initializes the Sampler support. Called once at VM startup. | 194 // Initializes the Sampler support. Called once at VM startup. |
59 static void SetUp(); | 195 static void SetUp(); |
60 static void TearDown(); | 196 static void TearDown(); |
61 | 197 |
62 // Initialize sampler. | 198 // Initialize sampler. |
63 Sampler(Isolate* isolate, int interval); | 199 Sampler(Isolate* isolate, int interval); |
64 virtual ~Sampler(); | 200 virtual ~Sampler(); |
65 | 201 |
66 Isolate* isolate() const { return isolate_; } | 202 Isolate* isolate() const { return isolate_; } |
67 int interval() const { return interval_; } | 203 int interval() const { return interval_; } |
68 | 204 |
69 // Performs stack sampling. | 205 // Performs stack sampling. |
70 void SampleStack(const RegisterState& regs); | 206 void SampleStack(const v8::RegisterState& regs); |
71 | 207 |
72 // Start and stop sampler. | 208 // Start and stop sampler. |
73 void Start(); | 209 void Start(); |
74 void Stop(); | 210 void Stop(); |
75 | 211 |
76 // Whether the sampling thread should use this Sampler for CPU profiling? | 212 // Whether the sampling thread should use this Sampler for CPU profiling? |
77 bool IsProfiling() const { | 213 bool IsProfiling() const { |
78 return base::NoBarrier_Load(&profiling_) > 0 && | 214 return base::NoBarrier_Load(&profiling_) > 0 && |
79 !base::NoBarrier_Load(&has_processing_thread_); | 215 !base::NoBarrier_Load(&has_processing_thread_); |
80 } | 216 } |
81 void IncreaseProfilingDepth(); | 217 void IncreaseProfilingDepth(); |
82 void DecreaseProfilingDepth(); | 218 void DecreaseProfilingDepth(); |
83 | 219 |
84 // Whether the sampler is running (that is, consumes resources). | 220 // Whether the sampler is running (that is, consumes resources). |
85 bool IsActive() const { return base::NoBarrier_Load(&active_); } | 221 bool IsActive() const { return base::NoBarrier_Load(&active_); } |
86 | 222 |
87 void DoSample(); | 223 void DoSample(); |
| 224 |
| 225 static int GetSample(Isolate* isolate, |
| 226 const v8::RegisterState& state, |
| 227 void** buffer, |
| 228 unsigned int depth); |
| 229 |
88 // If true next sample must be initiated on the profiler event processor | 230 // If true next sample must be initiated on the profiler event processor |
89 // thread right after latest sample is processed. | 231 // thread right after latest sample is processed. |
90 void SetHasProcessingThread(bool value) { | 232 void SetHasProcessingThread(bool value) { |
91 base::NoBarrier_Store(&has_processing_thread_, value); | 233 base::NoBarrier_Store(&has_processing_thread_, value); |
92 } | 234 } |
93 | 235 |
94 // Used in tests to make sure that stack sampling is performed. | 236 // Used in tests to make sure that stack sampling is performed. |
95 unsigned js_and_external_sample_count() const { | 237 unsigned js_and_external_sample_count() const { |
96 return js_and_external_sample_count_; | 238 return js_and_external_sample_count_; |
97 } | 239 } |
(...skipping 22 matching lines...) Expand all Loading... |
120 bool is_counting_samples_; | 262 bool is_counting_samples_; |
121 // Counts stack samples taken in JS VM state. | 263 // Counts stack samples taken in JS VM state. |
122 unsigned js_and_external_sample_count_; | 264 unsigned js_and_external_sample_count_; |
123 DISALLOW_IMPLICIT_CONSTRUCTORS(Sampler); | 265 DISALLOW_IMPLICIT_CONSTRUCTORS(Sampler); |
124 }; | 266 }; |
125 | 267 |
126 | 268 |
127 } } // namespace v8::internal | 269 } } // namespace v8::internal |
128 | 270 |
129 #endif // V8_SAMPLER_H_ | 271 #endif // V8_SAMPLER_H_ |
OLD | NEW |