OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
11 // with the distribution. | 11 // with the distribution. |
12 // * Neither the name of Google Inc. nor the names of its | 12 // * Neither the name of Google Inc. nor the names of its |
13 // contributors may be used to endorse or promote products derived | 13 // contributors may be used to endorse or promote products derived |
14 // from this software without specific prior written permission. | 14 // from this software without specific prior written permission. |
15 // | 15 // |
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | 27 |
| 28 #include "sampler.h" |
| 29 |
28 #if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) \ | 30 #if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) \ |
29 || defined(__NetBSD__) || defined(__sun) || defined(__ANDROID__) \ | 31 || defined(__NetBSD__) || defined(__sun) || defined(__ANDROID__) \ |
30 || defined(__native_client__) | 32 || defined(__native_client__) |
31 | 33 |
32 #define USE_SIGNALS | 34 #define USE_SIGNALS |
33 | 35 |
34 #include <errno.h> | 36 #include <errno.h> |
35 #include <pthread.h> | 37 #include <pthread.h> |
36 #include <signal.h> | 38 #include <signal.h> |
37 #include <sys/time.h> | 39 #include <sys/time.h> |
(...skipping 15 matching lines...) Expand all Loading... |
53 #include <mach/mach.h> | 55 #include <mach/mach.h> |
54 | 56 |
55 #elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__) | 57 #elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__) |
56 | 58 |
57 #include "win32-headers.h" | 59 #include "win32-headers.h" |
58 | 60 |
59 #endif | 61 #endif |
60 | 62 |
61 #include "v8.h" | 63 #include "v8.h" |
62 | 64 |
| 65 #include "cpu-profiler.h" |
| 66 #include "flags.h" |
63 #include "frames-inl.h" | 67 #include "frames-inl.h" |
64 #include "log.h" | 68 #include "log.h" |
65 #include "platform.h" | 69 #include "platform.h" |
66 #include "simulator.h" | 70 #include "simulator.h" |
67 #include "v8threads.h" | 71 #include "v8threads.h" |
68 | 72 |
69 | 73 |
70 #if defined(__ANDROID__) && !defined(__BIONIC_HAVE_UCONTEXT_T) | 74 #if defined(__ANDROID__) && !defined(__BIONIC_HAVE_UCONTEXT_T) |
71 | 75 |
72 // Not all versions of Android's C library provide ucontext_t. | 76 // Not all versions of Android's C library provide ucontext_t. |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
223 } | 227 } |
224 | 228 |
225 HANDLE profiled_thread() { return profiled_thread_; } | 229 HANDLE profiled_thread() { return profiled_thread_; } |
226 | 230 |
227 private: | 231 private: |
228 HANDLE profiled_thread_; | 232 HANDLE profiled_thread_; |
229 }; | 233 }; |
230 #endif | 234 #endif |
231 | 235 |
232 | 236 |
233 class SampleHelper { | 237 #if defined(USE_SIMULATOR) |
| 238 class SimulatorHelper { |
234 public: | 239 public: |
235 inline TickSample* Init(Sampler* sampler, Isolate* isolate) { | 240 inline bool Init(Sampler* sampler, Isolate* isolate) { |
236 #if defined(USE_SIMULATOR) | |
237 ThreadId thread_id = sampler->platform_data()->profiled_thread_id(); | 241 ThreadId thread_id = sampler->platform_data()->profiled_thread_id(); |
238 Isolate::PerIsolateThreadData* per_thread_data = isolate-> | 242 Isolate::PerIsolateThreadData* per_thread_data = isolate-> |
239 FindPerThreadDataForThread(thread_id); | 243 FindPerThreadDataForThread(thread_id); |
240 if (!per_thread_data) return NULL; | 244 if (!per_thread_data) return false; |
241 simulator_ = per_thread_data->simulator(); | 245 simulator_ = per_thread_data->simulator(); |
242 // Check if there is active simulator before allocating TickSample. | 246 // Check if there is active simulator. |
243 if (!simulator_) return NULL; | 247 return simulator_ != NULL; |
244 #endif // USE_SIMULATOR | |
245 TickSample* sample = isolate->cpu_profiler()->TickSampleEvent(); | |
246 if (sample == NULL) sample = &sample_obj; | |
247 return sample; | |
248 } | 248 } |
249 | 249 |
250 #if defined(USE_SIMULATOR) | 250 inline void FillRegisters(RegisterState* state) { |
251 inline void FillRegisters(TickSample* sample) { | |
252 #if V8_TARGET_ARCH_ARM | 251 #if V8_TARGET_ARCH_ARM |
253 sample->pc = reinterpret_cast<Address>(simulator_->get_pc()); | 252 state->pc = reinterpret_cast<Address>(simulator_->get_pc()); |
254 sample->sp = reinterpret_cast<Address>(simulator_->get_register( | 253 state->sp = reinterpret_cast<Address>(simulator_->get_register( |
255 Simulator::sp)); | 254 Simulator::sp)); |
256 sample->fp = reinterpret_cast<Address>(simulator_->get_register( | 255 state->fp = reinterpret_cast<Address>(simulator_->get_register( |
257 Simulator::r11)); | 256 Simulator::r11)); |
258 #elif V8_TARGET_ARCH_A64 | 257 #elif V8_TARGET_ARCH_A64 |
259 if (simulator_->sp() == 0 || simulator_->fp() == 0) { | 258 if (simulator_->sp() == 0 || simulator_->fp() == 0) { |
260 // It possible that the simulator is interrupted while it is updating | 259 // It possible that the simulator is interrupted while it is updating |
261 // the sp or fp register. A64 simulator does this in two steps: | 260 // the sp or fp register. A64 simulator does this in two steps: |
262 // first setting it to zero and then setting it to the new value. | 261 // first setting it to zero and then setting it to the new value. |
263 // Bailout if sp/fp doesn't contain the new value. | 262 // Bailout if sp/fp doesn't contain the new value. |
264 return; | 263 return; |
265 } | 264 } |
266 sample->pc = reinterpret_cast<Address>(simulator_->pc()); | 265 state->pc = reinterpret_cast<Address>(simulator_->pc()); |
267 sample->sp = reinterpret_cast<Address>(simulator_->sp()); | 266 state->sp = reinterpret_cast<Address>(simulator_->sp()); |
268 sample->fp = reinterpret_cast<Address>(simulator_->fp()); | 267 state->fp = reinterpret_cast<Address>(simulator_->fp()); |
269 #elif V8_TARGET_ARCH_MIPS | 268 #elif V8_TARGET_ARCH_MIPS |
270 sample->pc = reinterpret_cast<Address>(simulator_->get_pc()); | 269 state->pc = reinterpret_cast<Address>(simulator_->get_pc()); |
271 sample->sp = reinterpret_cast<Address>(simulator_->get_register( | 270 state->sp = reinterpret_cast<Address>(simulator_->get_register( |
272 Simulator::sp)); | 271 Simulator::sp)); |
273 sample->fp = reinterpret_cast<Address>(simulator_->get_register( | 272 state->fp = reinterpret_cast<Address>(simulator_->get_register( |
274 Simulator::fp)); | 273 Simulator::fp)); |
275 #endif | 274 #endif |
276 } | 275 } |
277 #endif // USE_SIMULATOR | |
278 | 276 |
279 private: | 277 private: |
280 #if defined(USE_SIMULATOR) | |
281 Simulator* simulator_; | 278 Simulator* simulator_; |
282 #endif | |
283 TickSample sample_obj; | |
284 }; | 279 }; |
| 280 #endif // USE_SIMULATOR |
285 | 281 |
286 | 282 |
287 #if defined(USE_SIGNALS) | 283 #if defined(USE_SIGNALS) |
288 | 284 |
289 class SignalHandler : public AllStatic { | 285 class SignalHandler : public AllStatic { |
290 public: | 286 public: |
291 static inline void EnsureInstalled() { | 287 static inline void EnsureInstalled() { |
292 if (signal_handler_installed_) return; | 288 if (signal_handler_installed_) return; |
293 struct sigaction sa; | 289 struct sigaction sa; |
294 sa.sa_sigaction = &HandleProfilerSignal; | 290 sa.sa_sigaction = &HandleProfilerSignal; |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
334 return; | 330 return; |
335 } | 331 } |
336 if (v8::Locker::IsActive() && | 332 if (v8::Locker::IsActive() && |
337 !isolate->thread_manager()->IsLockedByCurrentThread()) { | 333 !isolate->thread_manager()->IsLockedByCurrentThread()) { |
338 return; | 334 return; |
339 } | 335 } |
340 | 336 |
341 Sampler* sampler = isolate->logger()->sampler(); | 337 Sampler* sampler = isolate->logger()->sampler(); |
342 if (sampler == NULL || !sampler->IsActive()) return; | 338 if (sampler == NULL || !sampler->IsActive()) return; |
343 | 339 |
344 SampleHelper helper; | 340 RegisterState state; |
345 TickSample* sample = helper.Init(sampler, isolate); | |
346 if (sample == NULL) return; | |
347 | 341 |
348 #if defined(USE_SIMULATOR) | 342 #if defined(USE_SIMULATOR) |
349 helper.FillRegisters(sample); | 343 SimulatorHelper helper; |
| 344 if (!helper.Init(sampler, isolate)) return; |
| 345 helper.FillRegisters(&state); |
350 // It possible that the simulator is interrupted while it is updating | 346 // It possible that the simulator is interrupted while it is updating |
351 // the sp or fp register. A64 simulator does this in two steps: | 347 // the sp or fp register. A64 simulator does this in two steps: |
352 // first setting it to zero and then setting it to the new value. | 348 // first setting it to zero and then setting it to the new value. |
353 // Bailout if sp/fp doesn't contain the new value. | 349 // Bailout if sp/fp doesn't contain the new value. |
354 if (sample->sp == 0 || sample->fp == 0) return; | 350 if (state.sp == 0 || state.fp == 0) return; |
355 #else | 351 #else |
356 // Extracting the sample from the context is extremely machine dependent. | 352 // Extracting the sample from the context is extremely machine dependent. |
357 ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context); | 353 ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context); |
358 mcontext_t& mcontext = ucontext->uc_mcontext; | 354 mcontext_t& mcontext = ucontext->uc_mcontext; |
359 sample->state = isolate->current_vm_state(); | |
360 #if defined(__linux__) || defined(__ANDROID__) | 355 #if defined(__linux__) || defined(__ANDROID__) |
361 #if V8_HOST_ARCH_IA32 | 356 #if V8_HOST_ARCH_IA32 |
362 sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_EIP]); | 357 state.pc = reinterpret_cast<Address>(mcontext.gregs[REG_EIP]); |
363 sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_ESP]); | 358 state.sp = reinterpret_cast<Address>(mcontext.gregs[REG_ESP]); |
364 sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_EBP]); | 359 state.fp = reinterpret_cast<Address>(mcontext.gregs[REG_EBP]); |
365 #elif V8_HOST_ARCH_X64 | 360 #elif V8_HOST_ARCH_X64 |
366 sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_RIP]); | 361 state.pc = reinterpret_cast<Address>(mcontext.gregs[REG_RIP]); |
367 sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_RSP]); | 362 state.sp = reinterpret_cast<Address>(mcontext.gregs[REG_RSP]); |
368 sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_RBP]); | 363 state.fp = reinterpret_cast<Address>(mcontext.gregs[REG_RBP]); |
369 #elif V8_HOST_ARCH_ARM | 364 #elif V8_HOST_ARCH_ARM |
370 #if defined(__GLIBC__) && !defined(__UCLIBC__) && \ | 365 #if defined(__GLIBC__) && !defined(__UCLIBC__) && \ |
371 (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3)) | 366 (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3)) |
372 // Old GLibc ARM versions used a gregs[] array to access the register | 367 // Old GLibc ARM versions used a gregs[] array to access the register |
373 // values from mcontext_t. | 368 // values from mcontext_t. |
374 sample->pc = reinterpret_cast<Address>(mcontext.gregs[R15]); | 369 state.pc = reinterpret_cast<Address>(mcontext.gregs[R15]); |
375 sample->sp = reinterpret_cast<Address>(mcontext.gregs[R13]); | 370 state.sp = reinterpret_cast<Address>(mcontext.gregs[R13]); |
376 sample->fp = reinterpret_cast<Address>(mcontext.gregs[R11]); | 371 state.fp = reinterpret_cast<Address>(mcontext.gregs[R11]); |
377 #else | 372 #else |
378 sample->pc = reinterpret_cast<Address>(mcontext.arm_pc); | 373 state.pc = reinterpret_cast<Address>(mcontext.arm_pc); |
379 sample->sp = reinterpret_cast<Address>(mcontext.arm_sp); | 374 state.sp = reinterpret_cast<Address>(mcontext.arm_sp); |
380 sample->fp = reinterpret_cast<Address>(mcontext.arm_fp); | 375 state.fp = reinterpret_cast<Address>(mcontext.arm_fp); |
381 #endif // defined(__GLIBC__) && !defined(__UCLIBC__) && | 376 #endif // defined(__GLIBC__) && !defined(__UCLIBC__) && |
382 // (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3)) | 377 // (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3)) |
383 #elif V8_HOST_ARCH_A64 | 378 #elif V8_HOST_ARCH_A64 |
384 sample->pc = reinterpret_cast<Address>(mcontext.pc); | 379 sample->pc = reinterpret_cast<Address>(mcontext.pc); |
385 sample->sp = reinterpret_cast<Address>(mcontext.sp); | 380 sample->sp = reinterpret_cast<Address>(mcontext.sp); |
386 // FP is an alias for x29. | 381 // FP is an alias for x29. |
387 sample->fp = reinterpret_cast<Address>(mcontext.regs[29]); | 382 sample->fp = reinterpret_cast<Address>(mcontext.regs[29]); |
388 #elif V8_HOST_ARCH_MIPS | 383 #elif V8_HOST_ARCH_MIPS |
389 sample->pc = reinterpret_cast<Address>(mcontext.pc); | 384 state.pc = reinterpret_cast<Address>(mcontext.pc); |
390 sample->sp = reinterpret_cast<Address>(mcontext.gregs[29]); | 385 state.sp = reinterpret_cast<Address>(mcontext.gregs[29]); |
391 sample->fp = reinterpret_cast<Address>(mcontext.gregs[30]); | 386 state.fp = reinterpret_cast<Address>(mcontext.gregs[30]); |
392 #endif // V8_HOST_ARCH_* | 387 #endif // V8_HOST_ARCH_* |
393 #elif defined(__FreeBSD__) | 388 #elif defined(__FreeBSD__) |
394 #if V8_HOST_ARCH_IA32 | 389 #if V8_HOST_ARCH_IA32 |
395 sample->pc = reinterpret_cast<Address>(mcontext.mc_eip); | 390 state.pc = reinterpret_cast<Address>(mcontext.mc_eip); |
396 sample->sp = reinterpret_cast<Address>(mcontext.mc_esp); | 391 state.sp = reinterpret_cast<Address>(mcontext.mc_esp); |
397 sample->fp = reinterpret_cast<Address>(mcontext.mc_ebp); | 392 state.fp = reinterpret_cast<Address>(mcontext.mc_ebp); |
398 #elif V8_HOST_ARCH_X64 | 393 #elif V8_HOST_ARCH_X64 |
399 sample->pc = reinterpret_cast<Address>(mcontext.mc_rip); | 394 state.pc = reinterpret_cast<Address>(mcontext.mc_rip); |
400 sample->sp = reinterpret_cast<Address>(mcontext.mc_rsp); | 395 state.sp = reinterpret_cast<Address>(mcontext.mc_rsp); |
401 sample->fp = reinterpret_cast<Address>(mcontext.mc_rbp); | 396 state.fp = reinterpret_cast<Address>(mcontext.mc_rbp); |
402 #elif V8_HOST_ARCH_ARM | 397 #elif V8_HOST_ARCH_ARM |
403 sample->pc = reinterpret_cast<Address>(mcontext.mc_r15); | 398 state.pc = reinterpret_cast<Address>(mcontext.mc_r15); |
404 sample->sp = reinterpret_cast<Address>(mcontext.mc_r13); | 399 state.sp = reinterpret_cast<Address>(mcontext.mc_r13); |
405 sample->fp = reinterpret_cast<Address>(mcontext.mc_r11); | 400 state.fp = reinterpret_cast<Address>(mcontext.mc_r11); |
406 #endif // V8_HOST_ARCH_* | 401 #endif // V8_HOST_ARCH_* |
407 #elif defined(__NetBSD__) | 402 #elif defined(__NetBSD__) |
408 #if V8_HOST_ARCH_IA32 | 403 #if V8_HOST_ARCH_IA32 |
409 sample->pc = reinterpret_cast<Address>(mcontext.__gregs[_REG_EIP]); | 404 state.pc = reinterpret_cast<Address>(mcontext.__gregs[_REG_EIP]); |
410 sample->sp = reinterpret_cast<Address>(mcontext.__gregs[_REG_ESP]); | 405 state.sp = reinterpret_cast<Address>(mcontext.__gregs[_REG_ESP]); |
411 sample->fp = reinterpret_cast<Address>(mcontext.__gregs[_REG_EBP]); | 406 state.fp = reinterpret_cast<Address>(mcontext.__gregs[_REG_EBP]); |
412 #elif V8_HOST_ARCH_X64 | 407 #elif V8_HOST_ARCH_X64 |
413 sample->pc = reinterpret_cast<Address>(mcontext.__gregs[_REG_RIP]); | 408 state.pc = reinterpret_cast<Address>(mcontext.__gregs[_REG_RIP]); |
414 sample->sp = reinterpret_cast<Address>(mcontext.__gregs[_REG_RSP]); | 409 state.sp = reinterpret_cast<Address>(mcontext.__gregs[_REG_RSP]); |
415 sample->fp = reinterpret_cast<Address>(mcontext.__gregs[_REG_RBP]); | 410 state.fp = reinterpret_cast<Address>(mcontext.__gregs[_REG_RBP]); |
416 #endif // V8_HOST_ARCH_* | 411 #endif // V8_HOST_ARCH_* |
417 #elif defined(__OpenBSD__) | 412 #elif defined(__OpenBSD__) |
418 USE(mcontext); | 413 USE(mcontext); |
419 #if V8_HOST_ARCH_IA32 | 414 #if V8_HOST_ARCH_IA32 |
420 sample->pc = reinterpret_cast<Address>(ucontext->sc_eip); | 415 state.pc = reinterpret_cast<Address>(ucontext->sc_eip); |
421 sample->sp = reinterpret_cast<Address>(ucontext->sc_esp); | 416 state.sp = reinterpret_cast<Address>(ucontext->sc_esp); |
422 sample->fp = reinterpret_cast<Address>(ucontext->sc_ebp); | 417 state.fp = reinterpret_cast<Address>(ucontext->sc_ebp); |
423 #elif V8_HOST_ARCH_X64 | 418 #elif V8_HOST_ARCH_X64 |
424 sample->pc = reinterpret_cast<Address>(ucontext->sc_rip); | 419 state.pc = reinterpret_cast<Address>(ucontext->sc_rip); |
425 sample->sp = reinterpret_cast<Address>(ucontext->sc_rsp); | 420 state.sp = reinterpret_cast<Address>(ucontext->sc_rsp); |
426 sample->fp = reinterpret_cast<Address>(ucontext->sc_rbp); | 421 state.fp = reinterpret_cast<Address>(ucontext->sc_rbp); |
427 #endif // V8_HOST_ARCH_* | 422 #endif // V8_HOST_ARCH_* |
428 #elif defined(__sun) | 423 #elif defined(__sun) |
429 sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_PC]); | 424 state.pc = reinterpret_cast<Address>(mcontext.gregs[REG_PC]); |
430 sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_SP]); | 425 state.sp = reinterpret_cast<Address>(mcontext.gregs[REG_SP]); |
431 sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_FP]); | 426 state.fp = reinterpret_cast<Address>(mcontext.gregs[REG_FP]); |
432 #endif // __sun | 427 #endif // __sun |
433 #endif // USE_SIMULATOR | 428 #endif // USE_SIMULATOR |
434 | 429 sampler->SampleStack(state); |
435 sampler->SampleStack(sample); | |
436 sampler->Tick(sample); | |
437 #endif // __native_client__ | 430 #endif // __native_client__ |
438 } | 431 } |
439 | 432 |
440 #endif | 433 #endif |
441 | 434 |
442 | 435 |
443 class SamplerThread : public Thread { | 436 class SamplerThread : public Thread { |
444 public: | 437 public: |
445 static const int kSamplerThreadStackSize = 64 * KB; | 438 static const int kSamplerThreadStackSize = 64 * KB; |
446 | 439 |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
523 void SampleContext(Sampler* sampler) { | 516 void SampleContext(Sampler* sampler) { |
524 if (!SignalHandler::Installed()) return; | 517 if (!SignalHandler::Installed()) return; |
525 pthread_t tid = sampler->platform_data()->vm_tid(); | 518 pthread_t tid = sampler->platform_data()->vm_tid(); |
526 pthread_kill(tid, SIGPROF); | 519 pthread_kill(tid, SIGPROF); |
527 } | 520 } |
528 | 521 |
529 #elif defined(__MACH__) | 522 #elif defined(__MACH__) |
530 | 523 |
531 void SampleContext(Sampler* sampler) { | 524 void SampleContext(Sampler* sampler) { |
532 thread_act_t profiled_thread = sampler->platform_data()->profiled_thread(); | 525 thread_act_t profiled_thread = sampler->platform_data()->profiled_thread(); |
| 526 |
| 527 #if defined(USE_SIMULATOR) |
| 528 SimulatorHelper helper; |
533 Isolate* isolate = sampler->isolate(); | 529 Isolate* isolate = sampler->isolate(); |
534 | 530 if (!helper.Init(sampler, isolate)) return; |
535 SampleHelper helper; | 531 #endif |
536 TickSample* sample = helper.Init(sampler, isolate); | |
537 if (sample == NULL) return; | |
538 | 532 |
539 if (KERN_SUCCESS != thread_suspend(profiled_thread)) return; | 533 if (KERN_SUCCESS != thread_suspend(profiled_thread)) return; |
540 | 534 |
541 #if V8_HOST_ARCH_X64 | 535 #if V8_HOST_ARCH_X64 |
542 thread_state_flavor_t flavor = x86_THREAD_STATE64; | 536 thread_state_flavor_t flavor = x86_THREAD_STATE64; |
543 x86_thread_state64_t state; | 537 x86_thread_state64_t thread_state; |
544 mach_msg_type_number_t count = x86_THREAD_STATE64_COUNT; | 538 mach_msg_type_number_t count = x86_THREAD_STATE64_COUNT; |
545 #if __DARWIN_UNIX03 | 539 #if __DARWIN_UNIX03 |
546 #define REGISTER_FIELD(name) __r ## name | 540 #define REGISTER_FIELD(name) __r ## name |
547 #else | 541 #else |
548 #define REGISTER_FIELD(name) r ## name | 542 #define REGISTER_FIELD(name) r ## name |
549 #endif // __DARWIN_UNIX03 | 543 #endif // __DARWIN_UNIX03 |
550 #elif V8_HOST_ARCH_IA32 | 544 #elif V8_HOST_ARCH_IA32 |
551 thread_state_flavor_t flavor = i386_THREAD_STATE; | 545 thread_state_flavor_t flavor = i386_THREAD_STATE; |
552 i386_thread_state_t state; | 546 i386_thread_state_t thread_state; |
553 mach_msg_type_number_t count = i386_THREAD_STATE_COUNT; | 547 mach_msg_type_number_t count = i386_THREAD_STATE_COUNT; |
554 #if __DARWIN_UNIX03 | 548 #if __DARWIN_UNIX03 |
555 #define REGISTER_FIELD(name) __e ## name | 549 #define REGISTER_FIELD(name) __e ## name |
556 #else | 550 #else |
557 #define REGISTER_FIELD(name) e ## name | 551 #define REGISTER_FIELD(name) e ## name |
558 #endif // __DARWIN_UNIX03 | 552 #endif // __DARWIN_UNIX03 |
559 #else | 553 #else |
560 #error Unsupported Mac OS X host architecture. | 554 #error Unsupported Mac OS X host architecture. |
561 #endif // V8_HOST_ARCH | 555 #endif // V8_HOST_ARCH |
562 | 556 |
563 if (thread_get_state(profiled_thread, | 557 if (thread_get_state(profiled_thread, |
564 flavor, | 558 flavor, |
565 reinterpret_cast<natural_t*>(&state), | 559 reinterpret_cast<natural_t*>(&thread_state), |
566 &count) == KERN_SUCCESS) { | 560 &count) == KERN_SUCCESS) { |
567 sample->state = isolate->current_vm_state(); | 561 RegisterState state; |
568 #if defined(USE_SIMULATOR) | 562 #if defined(USE_SIMULATOR) |
569 helper.FillRegisters(sample); | 563 helper.FillRegisters(&state); |
570 #else | 564 #else |
571 sample->pc = reinterpret_cast<Address>(state.REGISTER_FIELD(ip)); | 565 state.pc = reinterpret_cast<Address>(thread_state.REGISTER_FIELD(ip)); |
572 sample->sp = reinterpret_cast<Address>(state.REGISTER_FIELD(sp)); | 566 state.sp = reinterpret_cast<Address>(thread_state.REGISTER_FIELD(sp)); |
573 sample->fp = reinterpret_cast<Address>(state.REGISTER_FIELD(bp)); | 567 state.fp = reinterpret_cast<Address>(thread_state.REGISTER_FIELD(bp)); |
574 #endif // USE_SIMULATOR | 568 #endif // USE_SIMULATOR |
575 #undef REGISTER_FIELD | 569 #undef REGISTER_FIELD |
576 sampler->SampleStack(sample); | 570 sampler->SampleStack(state); |
577 sampler->Tick(sample); | |
578 } | 571 } |
579 thread_resume(profiled_thread); | 572 thread_resume(profiled_thread); |
580 } | 573 } |
581 | 574 |
582 #elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__) | 575 #elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__) |
583 | 576 |
584 void SampleContext(Sampler* sampler) { | 577 void SampleContext(Sampler* sampler) { |
585 HANDLE profiled_thread = sampler->platform_data()->profiled_thread(); | 578 HANDLE profiled_thread = sampler->platform_data()->profiled_thread(); |
586 if (profiled_thread == NULL) return; | 579 if (profiled_thread == NULL) return; |
587 | 580 |
588 Isolate* isolate = sampler->isolate(); | 581 Isolate* isolate = sampler->isolate(); |
589 SampleHelper helper; | 582 #if defined(USE_SIMULATOR) |
590 TickSample* sample = helper.Init(sampler, isolate); | 583 SimulatorHelper helper; |
591 if (sample == NULL) return; | 584 if (!helper.Init(sampler, isolate)) return; |
| 585 #endif |
592 | 586 |
593 const DWORD kSuspendFailed = static_cast<DWORD>(-1); | 587 const DWORD kSuspendFailed = static_cast<DWORD>(-1); |
594 if (SuspendThread(profiled_thread) == kSuspendFailed) return; | 588 if (SuspendThread(profiled_thread) == kSuspendFailed) return; |
595 sample->state = isolate->current_vm_state(); | |
596 | 589 |
597 // Context used for sampling the register state of the profiled thread. | 590 // Context used for sampling the register state of the profiled thread. |
598 CONTEXT context; | 591 CONTEXT context; |
599 memset(&context, 0, sizeof(context)); | 592 memset(&context, 0, sizeof(context)); |
600 context.ContextFlags = CONTEXT_FULL; | 593 context.ContextFlags = CONTEXT_FULL; |
601 if (GetThreadContext(profiled_thread, &context) != 0) { | 594 if (GetThreadContext(profiled_thread, &context) != 0) { |
| 595 RegisterState state; |
602 #if defined(USE_SIMULATOR) | 596 #if defined(USE_SIMULATOR) |
603 helper.FillRegisters(sample); | 597 helper.FillRegisters(&state); |
604 #else | 598 #else |
605 #if V8_HOST_ARCH_X64 | 599 #if V8_HOST_ARCH_X64 |
606 sample->pc = reinterpret_cast<Address>(context.Rip); | 600 state.pc = reinterpret_cast<Address>(context.Rip); |
607 sample->sp = reinterpret_cast<Address>(context.Rsp); | 601 state.sp = reinterpret_cast<Address>(context.Rsp); |
608 sample->fp = reinterpret_cast<Address>(context.Rbp); | 602 state.fp = reinterpret_cast<Address>(context.Rbp); |
609 #else | 603 #else |
610 sample->pc = reinterpret_cast<Address>(context.Eip); | 604 state.pc = reinterpret_cast<Address>(context.Eip); |
611 sample->sp = reinterpret_cast<Address>(context.Esp); | 605 state.sp = reinterpret_cast<Address>(context.Esp); |
612 sample->fp = reinterpret_cast<Address>(context.Ebp); | 606 state.fp = reinterpret_cast<Address>(context.Ebp); |
613 #endif | 607 #endif |
614 #endif // USE_SIMULATOR | 608 #endif // USE_SIMULATOR |
615 sampler->SampleStack(sample); | 609 sampler->SampleStack(state); |
616 sampler->Tick(sample); | |
617 } | 610 } |
618 ResumeThread(profiled_thread); | 611 ResumeThread(profiled_thread); |
619 } | 612 } |
620 | 613 |
621 #endif // USE_SIGNALS | 614 #endif // USE_SIGNALS |
622 | 615 |
623 | 616 |
624 // Protects the process wide state below. | 617 // Protects the process wide state below. |
625 static Mutex* mutex_; | 618 static Mutex* mutex_; |
626 static SamplerThread* instance_; | 619 static SamplerThread* instance_; |
627 | 620 |
628 const int interval_; | 621 const int interval_; |
629 List<Sampler*> active_samplers_; | 622 List<Sampler*> active_samplers_; |
630 | 623 |
631 DISALLOW_COPY_AND_ASSIGN(SamplerThread); | 624 DISALLOW_COPY_AND_ASSIGN(SamplerThread); |
632 }; | 625 }; |
633 | 626 |
634 | 627 |
635 Mutex* SamplerThread::mutex_ = NULL; | 628 Mutex* SamplerThread::mutex_ = NULL; |
636 SamplerThread* SamplerThread::instance_ = NULL; | 629 SamplerThread* SamplerThread::instance_ = NULL; |
637 | 630 |
638 | 631 |
639 // | 632 // |
640 // StackTracer implementation | 633 // StackTracer implementation |
641 // | 634 // |
642 DISABLE_ASAN void TickSample::Trace(Isolate* isolate) { | 635 DISABLE_ASAN void TickSample::Init(Isolate* isolate, |
| 636 const RegisterState& regs) { |
643 ASSERT(isolate->IsInitialized()); | 637 ASSERT(isolate->IsInitialized()); |
| 638 pc = regs.pc; |
| 639 state = isolate->current_vm_state(); |
644 | 640 |
645 // Avoid collecting traces while doing GC. | 641 // Avoid collecting traces while doing GC. |
646 if (state == GC) return; | 642 if (state == GC) return; |
647 | 643 |
648 const Address js_entry_sp = | 644 const Address js_entry_sp = |
649 Isolate::js_entry_sp(isolate->thread_local_top()); | 645 Isolate::js_entry_sp(isolate->thread_local_top()); |
650 if (js_entry_sp == 0) { | 646 if (js_entry_sp == 0) { |
651 // Not executing JS now. | 647 // Not executing JS now. |
652 return; | 648 return; |
653 } | 649 } |
654 | 650 |
655 const Address callback = isolate->external_callback(); | 651 const Address callback = isolate->external_callback(); |
656 if (callback != NULL) { | 652 if (callback != NULL) { |
657 external_callback = callback; | 653 external_callback = callback; |
658 has_external_callback = true; | 654 has_external_callback = true; |
659 } else { | 655 } else { |
660 // Sample potential return address value for frameless invocation of | 656 // Sample potential return address value for frameless invocation of |
661 // stubs (we'll figure out later, if this value makes sense). | 657 // stubs (we'll figure out later, if this value makes sense). |
662 tos = Memory::Address_at(sp); | 658 tos = Memory::Address_at(regs.sp); |
663 has_external_callback = false; | 659 has_external_callback = false; |
664 } | 660 } |
665 | 661 |
666 SafeStackFrameIterator it(isolate, fp, sp, sp, js_entry_sp); | 662 SafeStackFrameIterator it(isolate, regs.fp, regs.sp, js_entry_sp); |
| 663 top_frame_type = it.top_frame_type(); |
667 int i = 0; | 664 int i = 0; |
668 while (!it.done() && i < TickSample::kMaxFramesCount) { | 665 while (!it.done() && i < TickSample::kMaxFramesCount) { |
669 stack[i++] = it.frame()->pc(); | 666 stack[i++] = it.frame()->pc(); |
670 it.Advance(); | 667 it.Advance(); |
671 } | 668 } |
672 frames_count = i; | 669 frames_count = i; |
673 } | 670 } |
674 | 671 |
675 | 672 |
676 void Sampler::SetUp() { | 673 void Sampler::SetUp() { |
(...skipping 14 matching lines...) Expand all Loading... |
691 samples_taken_(0) { | 688 samples_taken_(0) { |
692 data_ = new PlatformData; | 689 data_ = new PlatformData; |
693 } | 690 } |
694 | 691 |
695 | 692 |
696 Sampler::~Sampler() { | 693 Sampler::~Sampler() { |
697 ASSERT(!IsActive()); | 694 ASSERT(!IsActive()); |
698 delete data_; | 695 delete data_; |
699 } | 696 } |
700 | 697 |
| 698 |
701 void Sampler::Start() { | 699 void Sampler::Start() { |
702 ASSERT(!IsActive()); | 700 ASSERT(!IsActive()); |
703 SetActive(true); | 701 SetActive(true); |
704 SamplerThread::AddActiveSampler(this); | 702 SamplerThread::AddActiveSampler(this); |
705 } | 703 } |
706 | 704 |
707 | 705 |
708 void Sampler::Stop() { | 706 void Sampler::Stop() { |
709 ASSERT(IsActive()); | 707 ASSERT(IsActive()); |
710 SamplerThread::RemoveActiveSampler(this); | 708 SamplerThread::RemoveActiveSampler(this); |
711 SetActive(false); | 709 SetActive(false); |
712 } | 710 } |
713 | 711 |
714 void Sampler::SampleStack(TickSample* sample) { | 712 |
715 sample->Trace(isolate_); | 713 void Sampler::SampleStack(const RegisterState& state) { |
| 714 TickSample* sample = isolate_->cpu_profiler()->TickSampleEvent(); |
| 715 TickSample sample_obj; |
| 716 if (sample == NULL) sample = &sample_obj; |
| 717 sample->Init(isolate_, state); |
716 if (++samples_taken_ < 0) samples_taken_ = 0; | 718 if (++samples_taken_ < 0) samples_taken_ = 0; |
| 719 Tick(sample); |
717 } | 720 } |
718 | 721 |
719 } } // namespace v8::internal | 722 } } // namespace v8::internal |
OLD | NEW |