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 #include "src/sampler.h" | 5 #include "src/sampler.h" |
6 | 6 |
7 #if V8_OS_POSIX && !V8_OS_CYGWIN | 7 #if V8_OS_POSIX && !V8_OS_CYGWIN |
8 | 8 |
9 #define USE_SIGNALS | 9 #define USE_SIGNALS |
10 | 10 |
(...skipping 24 matching lines...) Expand all Loading... |
35 !defined(__BIONIC_HAVE_STRUCT_SIGCONTEXT) | 35 !defined(__BIONIC_HAVE_STRUCT_SIGCONTEXT) |
36 #include <asm/sigcontext.h> // NOLINT | 36 #include <asm/sigcontext.h> // NOLINT |
37 #endif | 37 #endif |
38 | 38 |
39 #elif V8_OS_WIN || V8_OS_CYGWIN | 39 #elif V8_OS_WIN || V8_OS_CYGWIN |
40 | 40 |
41 #include "src/base/win32-headers.h" | 41 #include "src/base/win32-headers.h" |
42 | 42 |
43 #endif | 43 #endif |
44 | 44 |
| 45 #include "include/v8-sampler.h" |
| 46 |
45 #include "src/v8.h" | 47 #include "src/v8.h" |
46 | 48 |
47 #include "src/base/platform/platform.h" | 49 #include "src/base/platform/platform.h" |
48 #include "src/cpu-profiler-inl.h" | 50 #include "src/cpu-profiler-inl.h" |
49 #include "src/flags.h" | 51 #include "src/flags.h" |
50 #include "src/frames-inl.h" | 52 #include "src/frames-inl.h" |
51 #include "src/log.h" | 53 #include "src/log.h" |
52 #include "src/simulator.h" | 54 #include "src/simulator.h" |
53 #include "src/v8threads.h" | 55 #include "src/v8threads.h" |
54 #include "src/vm-state-inl.h" | 56 #include "src/vm-state-inl.h" |
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
262 private: | 264 private: |
263 Simulator* simulator_; | 265 Simulator* simulator_; |
264 }; | 266 }; |
265 #endif // USE_SIMULATOR | 267 #endif // USE_SIMULATOR |
266 | 268 |
267 | 269 |
268 #if defined(USE_SIGNALS) | 270 #if defined(USE_SIGNALS) |
269 | 271 |
270 class SignalHandler : public AllStatic { | 272 class SignalHandler : public AllStatic { |
271 public: | 273 public: |
272 static void SetUp() { if (!mutex_) mutex_ = new base::Mutex(); } | 274 static void SetUp() { |
273 static void TearDown() { delete mutex_; } | 275 if (!mutex_) mutex_ = new base::Mutex(); |
| 276 if (!register_state_semaphore_) |
| 277 register_state_semaphore_ = new base::Semaphore(0); |
| 278 } |
| 279 |
| 280 static void TearDown() { |
| 281 delete mutex_; |
| 282 delete register_state_semaphore_; |
| 283 } |
274 | 284 |
275 static void IncreaseSamplerCount() { | 285 static void IncreaseSamplerCount() { |
276 base::LockGuard<base::Mutex> lock_guard(mutex_); | 286 base::LockGuard<base::Mutex> lock_guard(mutex_); |
277 if (++client_count_ == 1) Install(); | 287 if (++client_count_ == 1) Install(); |
278 } | 288 } |
279 | 289 |
280 static void DecreaseSamplerCount() { | 290 static void DecreaseSamplerCount() { |
281 base::LockGuard<base::Mutex> lock_guard(mutex_); | 291 base::LockGuard<base::Mutex> lock_guard(mutex_); |
282 if (--client_count_ == 0) Restore(); | 292 if (--client_count_ == 0) Restore(); |
283 } | 293 } |
284 | 294 |
285 static bool Installed() { | 295 static bool Installed() { |
286 return signal_handler_installed_; | 296 return signal_handler_installed_; |
287 } | 297 } |
288 | 298 |
| 299 static RegisterState GetRegisterState() { |
| 300 register_state_semaphore_->Wait(); |
| 301 register_state_updated_ = false; |
| 302 return register_state_; |
| 303 } |
| 304 |
| 305 static bool WasRegisterStateUpdated() { |
| 306 return register_state_updated_; |
| 307 } |
| 308 |
| 309 |
289 private: | 310 private: |
290 static void Install() { | 311 static void Install() { |
291 struct sigaction sa; | 312 struct sigaction sa; |
292 sa.sa_sigaction = &HandleProfilerSignal; | 313 sa.sa_sigaction = &HandleProfilerSignal; |
293 sigemptyset(&sa.sa_mask); | 314 sigemptyset(&sa.sa_mask); |
294 #if V8_OS_QNX | 315 #if V8_OS_QNX |
295 sa.sa_flags = SA_SIGINFO; | 316 sa.sa_flags = SA_SIGINFO; |
296 #else | 317 #else |
297 sa.sa_flags = SA_RESTART | SA_SIGINFO; | 318 sa.sa_flags = SA_RESTART | SA_SIGINFO; |
298 #endif | 319 #endif |
299 signal_handler_installed_ = | 320 signal_handler_installed_ = |
300 (sigaction(SIGPROF, &sa, &old_signal_handler_) == 0); | 321 (sigaction(SIGPROF, &sa, &old_signal_handler_) == 0); |
301 } | 322 } |
302 | 323 |
303 static void Restore() { | 324 static void Restore() { |
304 if (signal_handler_installed_) { | 325 if (signal_handler_installed_) { |
305 sigaction(SIGPROF, &old_signal_handler_, 0); | 326 sigaction(SIGPROF, &old_signal_handler_, 0); |
306 signal_handler_installed_ = false; | 327 signal_handler_installed_ = false; |
307 } | 328 } |
308 } | 329 } |
309 | 330 |
310 static void HandleProfilerSignal(int signal, siginfo_t* info, void* context); | 331 static void HandleProfilerSignal(int signal, siginfo_t* info, void* context); |
| 332 |
| 333 // HandleProfilerSignal puts the state of registers into |
| 334 // register_state_ and then signals on the semaphore, |
| 335 // so that DoSample can use it. |
| 336 static base::Semaphore* register_state_semaphore_; |
| 337 static RegisterState register_state_; |
| 338 // It is not that every time HandleProfilerSignal is invoked, |
| 339 // the register state is guarenteed to be updated. |
| 340 // This provides the SIGPROF sender with the information whether |
| 341 // the handler finished with or without updating the register state. |
| 342 static bool register_state_updated_; |
| 343 |
311 // Protects the process wide state below. | 344 // Protects the process wide state below. |
312 static base::Mutex* mutex_; | 345 static base::Mutex* mutex_; |
313 static int client_count_; | 346 static int client_count_; |
314 static bool signal_handler_installed_; | 347 static bool signal_handler_installed_; |
315 static struct sigaction old_signal_handler_; | 348 static struct sigaction old_signal_handler_; |
316 }; | 349 }; |
317 | 350 |
318 | 351 |
319 base::Mutex* SignalHandler::mutex_ = NULL; | 352 base::Mutex* SignalHandler::mutex_ = NULL; |
320 int SignalHandler::client_count_ = 0; | 353 int SignalHandler::client_count_ = 0; |
321 struct sigaction SignalHandler::old_signal_handler_; | 354 struct sigaction SignalHandler::old_signal_handler_; |
322 bool SignalHandler::signal_handler_installed_ = false; | 355 bool SignalHandler::signal_handler_installed_ = false; |
323 | 356 |
| 357 base::Semaphore* SignalHandler::register_state_semaphore_ = NULL; |
| 358 RegisterState SignalHandler::register_state_; |
| 359 bool SignalHandler::register_state_updated_ = false; |
324 | 360 |
325 void SignalHandler::HandleProfilerSignal(int signal, siginfo_t* info, | 361 void SignalHandler::HandleProfilerSignal(int signal, siginfo_t* info, |
326 void* context) { | 362 void* context) { |
327 #if V8_OS_NACL | 363 #if V8_OS_NACL |
328 // As Native Client does not support signal handling, profiling | 364 // As Native Client does not support signal handling, profiling |
329 // is disabled. | 365 // is disabled. |
330 return; | 366 return; |
331 #else | 367 #else |
332 USE(info); | 368 USE(info); |
333 if (signal != SIGPROF) return; | 369 if (signal != SIGPROF) return; |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
459 state.pc = reinterpret_cast<Address>(mcontext.cpu.eip); | 495 state.pc = reinterpret_cast<Address>(mcontext.cpu.eip); |
460 state.sp = reinterpret_cast<Address>(mcontext.cpu.esp); | 496 state.sp = reinterpret_cast<Address>(mcontext.cpu.esp); |
461 state.fp = reinterpret_cast<Address>(mcontext.cpu.ebp); | 497 state.fp = reinterpret_cast<Address>(mcontext.cpu.ebp); |
462 #elif V8_HOST_ARCH_ARM | 498 #elif V8_HOST_ARCH_ARM |
463 state.pc = reinterpret_cast<Address>(mcontext.cpu.gpr[ARM_REG_PC]); | 499 state.pc = reinterpret_cast<Address>(mcontext.cpu.gpr[ARM_REG_PC]); |
464 state.sp = reinterpret_cast<Address>(mcontext.cpu.gpr[ARM_REG_SP]); | 500 state.sp = reinterpret_cast<Address>(mcontext.cpu.gpr[ARM_REG_SP]); |
465 state.fp = reinterpret_cast<Address>(mcontext.cpu.gpr[ARM_REG_FP]); | 501 state.fp = reinterpret_cast<Address>(mcontext.cpu.gpr[ARM_REG_FP]); |
466 #endif // V8_HOST_ARCH_* | 502 #endif // V8_HOST_ARCH_* |
467 #endif // V8_OS_QNX | 503 #endif // V8_OS_QNX |
468 #endif // USE_SIMULATOR | 504 #endif // USE_SIMULATOR |
469 sampler->SampleStack(state); | 505 register_state_ = state; |
| 506 register_state_updated_ = true; |
| 507 register_state_semaphore_->Signal(); |
470 #endif // V8_OS_NACL | 508 #endif // V8_OS_NACL |
471 } | 509 } |
472 | 510 |
473 #endif | 511 #endif |
474 | 512 |
475 | 513 |
476 class SamplerThread : public base::Thread { | 514 class SamplerThread : public base::Thread { |
477 public: | 515 public: |
478 static const int kSamplerThreadStackSize = 64 * KB; | 516 static const int kSamplerThreadStackSize = 64 * KB; |
479 | 517 |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
557 | 595 |
558 | 596 |
559 base::Mutex* SamplerThread::mutex_ = NULL; | 597 base::Mutex* SamplerThread::mutex_ = NULL; |
560 SamplerThread* SamplerThread::instance_ = NULL; | 598 SamplerThread* SamplerThread::instance_ = NULL; |
561 | 599 |
562 | 600 |
563 // | 601 // |
564 // StackTracer implementation | 602 // StackTracer implementation |
565 // | 603 // |
566 DISABLE_ASAN void TickSample::Init(Isolate* isolate, | 604 DISABLE_ASAN void TickSample::Init(Isolate* isolate, |
567 const RegisterState& regs) { | 605 const RegisterState& regs, |
| 606 unsigned max_frame_count) { |
568 ASSERT(isolate->IsInitialized()); | 607 ASSERT(isolate->IsInitialized()); |
569 timestamp = base::TimeTicks::HighResolutionNow(); | 608 timestamp = base::TimeTicks::HighResolutionNow(); |
570 pc = regs.pc; | 609 pc = regs.pc; |
571 state = isolate->current_vm_state(); | 610 state = isolate->current_vm_state(); |
572 | 611 |
573 // Avoid collecting traces while doing GC. | 612 // Avoid collecting traces while doing GC. |
574 if (state == GC) return; | 613 if (state == GC) return; |
575 | 614 |
576 Address js_entry_sp = isolate->js_entry_sp(); | 615 Address js_entry_sp = isolate->js_entry_sp(); |
577 if (js_entry_sp == 0) { | 616 if (js_entry_sp == 0) { |
(...skipping 12 matching lines...) Expand all Loading... |
590 } else { | 629 } else { |
591 // Sample potential return address value for frameless invocation of | 630 // Sample potential return address value for frameless invocation of |
592 // stubs (we'll figure out later, if this value makes sense). | 631 // stubs (we'll figure out later, if this value makes sense). |
593 tos = Memory::Address_at(regs.sp); | 632 tos = Memory::Address_at(regs.sp); |
594 has_external_callback = false; | 633 has_external_callback = false; |
595 } | 634 } |
596 | 635 |
597 SafeStackFrameIterator it(isolate, regs.fp, regs.sp, js_entry_sp); | 636 SafeStackFrameIterator it(isolate, regs.fp, regs.sp, js_entry_sp); |
598 top_frame_type = it.top_frame_type(); | 637 top_frame_type = it.top_frame_type(); |
599 unsigned i = 0; | 638 unsigned i = 0; |
600 while (!it.done() && i < TickSample::kMaxFramesCount) { | 639 if (max_frame_count > kMaxFramesCount) |
| 640 max_frame_count = kMaxFramesCount; |
| 641 while (!it.done() && i < max_frame_count) { |
601 stack[i++] = it.frame()->pc(); | 642 stack[i++] = it.frame()->pc(); |
602 it.Advance(); | 643 it.Advance(); |
603 } | 644 } |
604 frames_count = i; | 645 frames_count = i; |
605 } | 646 } |
606 | 647 |
607 | 648 |
608 void Sampler::SetUp() { | 649 void Sampler::SetUp() { |
609 #if defined(USE_SIGNALS) | 650 #if defined(USE_SIGNALS) |
610 SignalHandler::SetUp(); | 651 SignalHandler::SetUp(); |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
681 } | 722 } |
682 Tick(sample); | 723 Tick(sample); |
683 if (sample != &sample_obj) { | 724 if (sample != &sample_obj) { |
684 isolate_->cpu_profiler()->FinishTickSample(); | 725 isolate_->cpu_profiler()->FinishTickSample(); |
685 } | 726 } |
686 } | 727 } |
687 | 728 |
688 | 729 |
689 #if defined(USE_SIGNALS) | 730 #if defined(USE_SIGNALS) |
690 | 731 |
691 void Sampler::DoSample() { | 732 void Sampler::CaptureRegisterState_() { |
692 if (!SignalHandler::Installed()) return; | 733 if (!SignalHandler::Installed()) return; |
693 pthread_kill(platform_data()->vm_tid(), SIGPROF); | 734 pthread_kill(platform_data()->vm_tid(), SIGPROF); |
694 } | 735 } |
695 | 736 |
| 737 |
| 738 void Sampler::DoSample() { |
| 739 CaptureRegisterState_(); |
| 740 if (SignalHandler::WasRegisterStateUpdated()) |
| 741 SampleStack(SignalHandler::GetRegisterState()); |
| 742 } |
| 743 |
| 744 |
| 745 void Sampler::GetSample(TickSample* sample, unsigned max_frame_count) { |
| 746 CaptureRegisterState_(); |
| 747 if (SignalHandler::WasRegisterStateUpdated()) |
| 748 sample->Init(isolate_, |
| 749 SignalHandler::GetRegisterState(), |
| 750 max_frame_count); |
| 751 } |
| 752 |
696 #elif V8_OS_WIN || V8_OS_CYGWIN | 753 #elif V8_OS_WIN || V8_OS_CYGWIN |
697 | 754 |
698 void Sampler::DoSample() { | 755 void Sampler::CaptureRegisterState_(RegisterState* state, |
| 756 bool* captured_successfully) { |
| 757 *captured_successfully = false; |
| 758 |
699 HANDLE profiled_thread = platform_data()->profiled_thread(); | 759 HANDLE profiled_thread = platform_data()->profiled_thread(); |
700 if (profiled_thread == NULL) return; | 760 if (profiled_thread == NULL) return; |
701 | 761 |
702 #if defined(USE_SIMULATOR) | 762 #if defined(USE_SIMULATOR) |
703 SimulatorHelper helper; | 763 SimulatorHelper helper; |
704 if (!helper.Init(this, isolate())) return; | 764 if (!helper.Init(this, isolate())) return; |
705 #endif | 765 #endif |
706 | 766 |
707 const DWORD kSuspendFailed = static_cast<DWORD>(-1); | 767 const DWORD kSuspendFailed = static_cast<DWORD>(-1); |
708 if (SuspendThread(profiled_thread) == kSuspendFailed) return; | 768 if (SuspendThread(profiled_thread) == kSuspendFailed) return; |
709 | 769 |
710 // Context used for sampling the register state of the profiled thread. | 770 // Context used for sampling the register state of the profiled thread. |
711 CONTEXT context; | 771 CONTEXT context; |
712 memset(&context, 0, sizeof(context)); | 772 memset(&context, 0, sizeof(context)); |
713 context.ContextFlags = CONTEXT_FULL; | 773 context.ContextFlags = CONTEXT_FULL; |
714 if (GetThreadContext(profiled_thread, &context) != 0) { | 774 if (GetThreadContext(profiled_thread, &context) != 0) { |
715 RegisterState state; | |
716 #if defined(USE_SIMULATOR) | 775 #if defined(USE_SIMULATOR) |
717 helper.FillRegisters(&state); | 776 helper.FillRegisters(&state); |
718 #else | 777 #else |
719 #if V8_HOST_ARCH_X64 | 778 #if V8_HOST_ARCH_X64 |
720 state.pc = reinterpret_cast<Address>(context.Rip); | 779 state->pc = reinterpret_cast<Address>(context.Rip); |
721 state.sp = reinterpret_cast<Address>(context.Rsp); | 780 state->sp = reinterpret_cast<Address>(context.Rsp); |
722 state.fp = reinterpret_cast<Address>(context.Rbp); | 781 state->fp = reinterpret_cast<Address>(context.Rbp); |
723 #else | 782 #else |
724 state.pc = reinterpret_cast<Address>(context.Eip); | 783 state->pc = reinterpret_cast<Address>(context.Eip); |
725 state.sp = reinterpret_cast<Address>(context.Esp); | 784 state->sp = reinterpret_cast<Address>(context.Esp); |
726 state.fp = reinterpret_cast<Address>(context.Ebp); | 785 state->fp = reinterpret_cast<Address>(context.Ebp); |
727 #endif | 786 #endif |
728 #endif // USE_SIMULATOR | 787 #endif // USE_SIMULATOR |
729 SampleStack(state); | 788 *captured_successfully = true; |
730 } | 789 } |
731 ResumeThread(profiled_thread); | 790 ResumeThread(profiled_thread); |
732 } | 791 } |
733 | 792 |
| 793 |
| 794 void Sampler::DoSample() { |
| 795 bool register_state_captured; |
| 796 RegisterState state; |
| 797 CaptureRegisterState_(state, register_state_captured); |
| 798 if (register_state_captured) SampleStack(state); |
| 799 } |
| 800 |
| 801 |
| 802 void Sampler::GetSample(TickSample* sample, unsigned max_frame_count) { |
| 803 bool register_state_captured; |
| 804 RegisterState state; |
| 805 CaptureRegisterState_(state, register_state_captured); |
| 806 if (register_state_captured) |
| 807 sample->Init(isolate_, state, max_frame_count); |
| 808 } |
| 809 |
734 #endif // USE_SIGNALS | 810 #endif // USE_SIGNALS |
735 | 811 |
736 | 812 |
737 } } // namespace v8::internal | 813 } } // namespace v8::internal |
OLD | NEW |