Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(6)

Side by Side Diff: src/sampler.cc

Issue 422593003: Initial GetSample implementation. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Moved the thread pausing logic inside Sampler::GetSample Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« include/v8-sampler.h ('K') | « src/sampler.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
OLDNEW
« include/v8-sampler.h ('K') | « src/sampler.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698