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 | |
alph
2014/09/17 11:55:43
plz revert.
| |
5 #include "src/sampler.h" | 4 #include "src/sampler.h" |
6 | 5 |
7 #if V8_OS_POSIX && !V8_OS_CYGWIN | 6 #if V8_OS_POSIX && !V8_OS_CYGWIN |
8 | 7 |
9 #define USE_SIGNALS | 8 #define USE_SIGNALS |
10 | 9 |
11 #include <errno.h> | 10 #include <errno.h> |
12 #include <pthread.h> | 11 #include <pthread.h> |
13 #include <signal.h> | 12 #include <signal.h> |
14 #include <sys/time.h> | 13 #include <sys/time.h> |
(...skipping 22 matching lines...) Expand all Loading... | |
37 #endif | 36 #endif |
38 | 37 |
39 #elif V8_OS_WIN || V8_OS_CYGWIN | 38 #elif V8_OS_WIN || V8_OS_CYGWIN |
40 | 39 |
41 #include "src/base/win32-headers.h" | 40 #include "src/base/win32-headers.h" |
42 | 41 |
43 #endif | 42 #endif |
44 | 43 |
45 #include "src/v8.h" | 44 #include "src/v8.h" |
46 | 45 |
46 #include "src/base/logging.h" | |
47 #include "src/base/platform/platform.h" | 47 #include "src/base/platform/platform.h" |
48 #include "src/cpu-profiler-inl.h" | 48 #include "src/cpu-profiler-inl.h" |
49 #include "src/flags.h" | 49 #include "src/flags.h" |
50 #include "src/frames-inl.h" | 50 #include "src/frames-inl.h" |
51 #include "src/log.h" | 51 #include "src/log.h" |
52 #include "src/simulator.h" | 52 #include "src/simulator.h" |
53 #include "src/v8threads.h" | 53 #include "src/v8threads.h" |
54 #include "src/vm-state-inl.h" | 54 #include "src/vm-state-inl.h" |
55 | 55 |
56 | 56 |
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
262 private: | 262 private: |
263 Simulator* simulator_; | 263 Simulator* simulator_; |
264 }; | 264 }; |
265 #endif // USE_SIMULATOR | 265 #endif // USE_SIMULATOR |
266 | 266 |
267 | 267 |
268 #if defined(USE_SIGNALS) | 268 #if defined(USE_SIGNALS) |
269 | 269 |
270 class SignalHandler : public AllStatic { | 270 class SignalHandler : public AllStatic { |
271 public: | 271 public: |
272 static void SetUp() { if (!mutex_) mutex_ = new base::Mutex(); } | 272 static void SetUp() { |
273 static void TearDown() { delete mutex_; } | 273 if (mutex_ != NULL && sampling_semaphore_ != NULL) |
274 return; // Already setup | |
alph
2014/09/17 11:55:42
no need for the comment.
| |
275 | |
276 ASSERT_EQ(NULL, mutex_); | |
277 ASSERT_EQ(NULL, sampling_semaphore_); | |
278 | |
279 mutex_ = new base::Mutex(); | |
280 sampling_semaphore_ = new base::Semaphore(0); | |
281 } | |
282 | |
283 static void TearDown() { | |
284 delete mutex_; | |
285 delete sampling_semaphore_; | |
286 | |
287 mutex_ = NULL; | |
288 sampling_semaphore_ = NULL; | |
289 } | |
274 | 290 |
275 static void IncreaseSamplerCount() { | 291 static void IncreaseSamplerCount() { |
276 base::LockGuard<base::Mutex> lock_guard(mutex_); | 292 base::LockGuard<base::Mutex> lock_guard(mutex_); |
277 if (++client_count_ == 1) Install(); | 293 if (++client_count_ == 1) Install(); |
278 } | 294 } |
279 | 295 |
280 static void DecreaseSamplerCount() { | 296 static void DecreaseSamplerCount() { |
281 base::LockGuard<base::Mutex> lock_guard(mutex_); | 297 base::LockGuard<base::Mutex> lock_guard(mutex_); |
282 if (--client_count_ == 0) Restore(); | 298 if (--client_count_ == 0) Restore(); |
283 } | 299 } |
(...skipping 17 matching lines...) Expand all Loading... | |
301 } | 317 } |
302 | 318 |
303 static void Restore() { | 319 static void Restore() { |
304 if (signal_handler_installed_) { | 320 if (signal_handler_installed_) { |
305 sigaction(SIGPROF, &old_signal_handler_, 0); | 321 sigaction(SIGPROF, &old_signal_handler_, 0); |
306 signal_handler_installed_ = false; | 322 signal_handler_installed_ = false; |
307 } | 323 } |
308 } | 324 } |
309 | 325 |
310 static void HandleProfilerSignal(int signal, siginfo_t* info, void* context); | 326 static void HandleProfilerSignal(int signal, siginfo_t* info, void* context); |
327 | |
328 // The SIGPROF could have come from DoSample or from GetSample. | |
329 // GetSample is the internal endpoint for the public | |
330 // GetSample API, which aims to bypass all the internal buffers | |
331 // and return just one sample instead, rightaway. | |
332 // | |
333 // The origin of SIGPROF is determined by FLAG_new_sampler_api | |
334 // | |
335 // TODO(gholap): Eventually, get rid of DoSample. | |
336 // Only GetSample should remain. | |
337 // Then, get rid of FLAG_new_sampler_api too. | |
338 | |
339 // This is the sample which will be filled by the call from GetSample. | |
340 static TickSample sample_; | |
341 | |
342 // GetSample waits synchronously till the SIGPROF handler returns. | |
343 // this semaphore is used to signal GetSample. | |
344 static base::Semaphore* sampling_semaphore_; | |
345 | |
346 // It is not that every time HandleProfilerSignal is invoked, | |
347 // it succeeds in obtaining a sample. | |
348 // This provides GetSample with the information whether | |
349 // the handler finished with or without getting the sample. | |
350 static bool sample_available_; | |
351 | |
311 // Protects the process wide state below. | 352 // Protects the process wide state below. |
312 static base::Mutex* mutex_; | 353 static base::Mutex* mutex_; |
313 static int client_count_; | 354 static int client_count_; |
314 static bool signal_handler_installed_; | 355 static bool signal_handler_installed_; |
315 static struct sigaction old_signal_handler_; | 356 static struct sigaction old_signal_handler_; |
357 | |
358 friend class Sampler; | |
316 }; | 359 }; |
317 | 360 |
318 | 361 |
362 TickSample SignalHandler::sample_; | |
363 base::Semaphore* SignalHandler::sampling_semaphore_ = NULL; | |
364 bool SignalHandler::sample_available_ = false; | |
365 | |
319 base::Mutex* SignalHandler::mutex_ = NULL; | 366 base::Mutex* SignalHandler::mutex_ = NULL; |
320 int SignalHandler::client_count_ = 0; | 367 int SignalHandler::client_count_ = 0; |
321 struct sigaction SignalHandler::old_signal_handler_; | 368 struct sigaction SignalHandler::old_signal_handler_; |
322 bool SignalHandler::signal_handler_installed_ = false; | 369 bool SignalHandler::signal_handler_installed_ = false; |
323 | 370 |
324 | 371 |
325 void SignalHandler::HandleProfilerSignal(int signal, siginfo_t* info, | 372 void SignalHandler::HandleProfilerSignal(int signal, siginfo_t* info, |
326 void* context) { | 373 void* context) { |
327 #if V8_OS_NACL | 374 #if V8_OS_NACL |
328 // As Native Client does not support signal handling, profiling | 375 // As Native Client does not support signal handling, profiling |
329 // is disabled. | 376 // is disabled. |
330 return; | 377 return; |
331 #else | 378 #else |
379 // Even if we return prematurely, | |
380 // we need to signal the sampling_semaphore_ | |
381 sample_available_ = false; | |
382 ScopedSemaphore scoped_semaphore(sampling_semaphore_); | |
383 | |
332 USE(info); | 384 USE(info); |
333 if (signal != SIGPROF) return; | 385 if (signal != SIGPROF) return; |
334 Isolate* isolate = Isolate::UncheckedReentrantCurrent(); | 386 Isolate* isolate = Isolate::UncheckedReentrantCurrent(); |
335 if (isolate == NULL || !isolate->IsInitialized() || !isolate->IsInUse()) { | 387 if (isolate == NULL || !isolate->IsInitialized() || !isolate->IsInUse()) { |
336 // We require a fully initialized and entered isolate. | 388 // We require a fully initialized and entered isolate. |
337 return; | 389 return; |
338 } | 390 } |
339 if (v8::Locker::IsActive() && | 391 if (v8::Locker::IsActive() && |
340 !isolate->thread_manager()->IsLockedByCurrentThread()) { | 392 !isolate->thread_manager()->IsLockedByCurrentThread()) { |
341 return; | 393 return; |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
459 state.pc = reinterpret_cast<Address>(mcontext.cpu.eip); | 511 state.pc = reinterpret_cast<Address>(mcontext.cpu.eip); |
460 state.sp = reinterpret_cast<Address>(mcontext.cpu.esp); | 512 state.sp = reinterpret_cast<Address>(mcontext.cpu.esp); |
461 state.fp = reinterpret_cast<Address>(mcontext.cpu.ebp); | 513 state.fp = reinterpret_cast<Address>(mcontext.cpu.ebp); |
462 #elif V8_HOST_ARCH_ARM | 514 #elif V8_HOST_ARCH_ARM |
463 state.pc = reinterpret_cast<Address>(mcontext.cpu.gpr[ARM_REG_PC]); | 515 state.pc = reinterpret_cast<Address>(mcontext.cpu.gpr[ARM_REG_PC]); |
464 state.sp = reinterpret_cast<Address>(mcontext.cpu.gpr[ARM_REG_SP]); | 516 state.sp = reinterpret_cast<Address>(mcontext.cpu.gpr[ARM_REG_SP]); |
465 state.fp = reinterpret_cast<Address>(mcontext.cpu.gpr[ARM_REG_FP]); | 517 state.fp = reinterpret_cast<Address>(mcontext.cpu.gpr[ARM_REG_FP]); |
466 #endif // V8_HOST_ARCH_* | 518 #endif // V8_HOST_ARCH_* |
467 #endif // V8_OS_QNX | 519 #endif // V8_OS_QNX |
468 #endif // USE_SIMULATOR | 520 #endif // USE_SIMULATOR |
469 sampler->SampleStack(state); | 521 if (FLAG_new_sampler_api) { |
522 sample_.Init(sampler->isolate(), state); | |
523 sample_available_ = true; | |
524 } else { | |
525 sampler->SampleStack(state); | |
526 } | |
470 #endif // V8_OS_NACL | 527 #endif // V8_OS_NACL |
471 } | 528 } |
472 | 529 |
473 #endif | 530 #endif |
474 | 531 |
475 | 532 |
476 class SamplerThread : public base::Thread { | 533 class SamplerThread : public base::Thread { |
477 public: | 534 public: |
478 static const int kSamplerThreadStackSize = 64 * KB; | 535 static const int kSamplerThreadStackSize = 64 * KB; |
479 | 536 |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
562 | 619 |
563 // | 620 // |
564 // StackTracer implementation | 621 // StackTracer implementation |
565 // | 622 // |
566 DISABLE_ASAN void TickSample::Init(Isolate* isolate, | 623 DISABLE_ASAN void TickSample::Init(Isolate* isolate, |
567 const RegisterState& regs) { | 624 const RegisterState& regs) { |
568 ASSERT(isolate->IsInitialized()); | 625 ASSERT(isolate->IsInitialized()); |
569 timestamp = base::TimeTicks::HighResolutionNow(); | 626 timestamp = base::TimeTicks::HighResolutionNow(); |
570 pc = regs.pc; | 627 pc = regs.pc; |
571 state = isolate->current_vm_state(); | 628 state = isolate->current_vm_state(); |
629 frames_count = 0; | |
572 | 630 |
573 // Avoid collecting traces while doing GC. | 631 // Avoid collecting traces while doing GC. |
574 if (state == GC) return; | 632 if (state == GC) return; |
575 | 633 |
576 Address js_entry_sp = isolate->js_entry_sp(); | 634 Address js_entry_sp = isolate->js_entry_sp(); |
577 if (js_entry_sp == 0) { | 635 if (js_entry_sp == 0) { |
578 // Not executing JS now. | 636 // Not executing JS now. |
579 return; | 637 return; |
580 } | 638 } |
581 | 639 |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
614 | 672 |
615 | 673 |
616 void Sampler::TearDown() { | 674 void Sampler::TearDown() { |
617 SamplerThread::TearDown(); | 675 SamplerThread::TearDown(); |
618 #if defined(USE_SIGNALS) | 676 #if defined(USE_SIGNALS) |
619 SignalHandler::TearDown(); | 677 SignalHandler::TearDown(); |
620 #endif | 678 #endif |
621 } | 679 } |
622 | 680 |
623 | 681 |
682 void Sampler::SetUpForNewSamplingAPI() { | |
683 #if defined(USE_SIGNALS) | |
684 SignalHandler::SetUp(); | |
685 if (!SignalHandler::Installed()) | |
686 SignalHandler::Install(); | |
687 #endif | |
688 // Nothing needs to be done for windows. | |
689 } | |
690 | |
691 | |
624 Sampler::Sampler(Isolate* isolate, int interval) | 692 Sampler::Sampler(Isolate* isolate, int interval) |
625 : isolate_(isolate), | 693 : isolate_(isolate), |
626 interval_(interval), | 694 interval_(interval), |
627 profiling_(false), | 695 profiling_(false), |
628 has_processing_thread_(false), | 696 has_processing_thread_(false), |
629 active_(false), | 697 active_(false), |
630 is_counting_samples_(false), | 698 is_counting_samples_(false), |
631 js_and_external_sample_count_(0) { | 699 js_and_external_sample_count_(0) { |
632 data_ = new PlatformData; | 700 data_ = new PlatformData; |
633 } | 701 } |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
686 } | 754 } |
687 | 755 |
688 | 756 |
689 #if defined(USE_SIGNALS) | 757 #if defined(USE_SIGNALS) |
690 | 758 |
691 void Sampler::DoSample() { | 759 void Sampler::DoSample() { |
692 if (!SignalHandler::Installed()) return; | 760 if (!SignalHandler::Installed()) return; |
693 pthread_kill(platform_data()->vm_tid(), SIGPROF); | 761 pthread_kill(platform_data()->vm_tid(), SIGPROF); |
694 } | 762 } |
695 | 763 |
764 | |
765 void Sampler::GetSample(v8::Sample* sample) { | |
766 SignalHandler::sampling_semaphore_->Wait(); | |
767 if (SignalHandler::sample_available_) { | |
768 sample = new(sample) v8::Sample( | |
769 &SignalHandler::sample_.stack[0], | |
770 &SignalHandler::sample_.stack[SignalHandler::sample_.frames_count]); | |
771 } | |
772 else { | |
773 sample = new(sample) v8::Sample(); | |
774 } | |
775 } | |
776 | |
696 #elif V8_OS_WIN || V8_OS_CYGWIN | 777 #elif V8_OS_WIN || V8_OS_CYGWIN |
697 | 778 |
779 #if V8_HOST_ARCH_X64 | |
780 #define CONTEXT_TO_STATE(context, state) \ | |
781 state.pc = reinterpret_cast<Address>(context.Rip); \ | |
782 state.sp = reinterpret_cast<Address>(context.Rsp); \ | |
783 state.fp = reinterpret_cast<Address>(context.Rbp) | |
784 #else | |
785 #define CONTEXT_TO_STATE(context, state) \ | |
786 state.pc = reinterpret_cast<Address>(context.Eip); \ | |
787 state.sp = reinterpret_cast<Address>(context.Esp); \ | |
788 state.fp = reinterpret_cast<Address>(context.Ebp) | |
789 #endif | |
790 | |
791 | |
698 void Sampler::DoSample() { | 792 void Sampler::DoSample() { |
699 HANDLE profiled_thread = platform_data()->profiled_thread(); | 793 HANDLE profiled_thread = platform_data()->profiled_thread(); |
700 if (profiled_thread == NULL) return; | 794 if (profiled_thread == NULL) return; |
701 | 795 |
702 #if defined(USE_SIMULATOR) | 796 #if defined(USE_SIMULATOR) |
703 SimulatorHelper helper; | 797 SimulatorHelper helper; |
704 if (!helper.Init(this, isolate())) return; | 798 if (!helper.Init(this, isolate())) return; |
705 #endif | 799 #endif |
706 | 800 |
707 const DWORD kSuspendFailed = static_cast<DWORD>(-1); | 801 const DWORD kSuspendFailed = static_cast<DWORD>(-1); |
708 if (SuspendThread(profiled_thread) == kSuspendFailed) return; | 802 if (SuspendThread(profiled_thread) == kSuspendFailed) return; |
709 | 803 |
710 // Context used for sampling the register state of the profiled thread. | 804 // Context used for sampling the register state of the profiled thread. |
711 CONTEXT context; | 805 CONTEXT context; |
712 memset(&context, 0, sizeof(context)); | 806 memset(&context, 0, sizeof(context)); |
713 context.ContextFlags = CONTEXT_FULL; | 807 context.ContextFlags = CONTEXT_FULL; |
714 if (GetThreadContext(profiled_thread, &context) != 0) { | 808 if (GetThreadContext(profiled_thread, &context) != 0) { |
715 RegisterState state; | 809 RegisterState state; |
716 #if defined(USE_SIMULATOR) | 810 #if defined(USE_SIMULATOR) |
717 helper.FillRegisters(&state); | 811 helper.FillRegisters(&state); |
718 #else | 812 #else |
719 #if V8_HOST_ARCH_X64 | 813 CONTEXT_TO_STATE(context, state); |
720 state.pc = reinterpret_cast<Address>(context.Rip); | |
721 state.sp = reinterpret_cast<Address>(context.Rsp); | |
722 state.fp = reinterpret_cast<Address>(context.Rbp); | |
723 #else | |
724 state.pc = reinterpret_cast<Address>(context.Eip); | |
725 state.sp = reinterpret_cast<Address>(context.Esp); | |
726 state.fp = reinterpret_cast<Address>(context.Ebp); | |
727 #endif | |
728 #endif // USE_SIMULATOR | 814 #endif // USE_SIMULATOR |
729 SampleStack(state); | 815 SampleStack(state); |
730 } | 816 } |
731 ResumeThread(profiled_thread); | 817 ResumeThread(profiled_thread); |
732 } | 818 } |
733 | 819 |
820 | |
821 void Sampler::GetSample(Isolate* isolate, | |
822 const CONTEXT& context, | |
823 v8::Sample* sample) { | |
824 TickSample tick_sample; | |
825 RegisterState state; | |
826 CONTEXT_TO_STATE(context, state); | |
827 tick_sample.Init(isolate, state); | |
828 sample = new(sample) v8::Sample(&tick_sample.stack[0], | |
829 &tick_sample.stack[tick_sample.frames_count]); | |
830 } | |
831 | |
734 #endif // USE_SIGNALS | 832 #endif // USE_SIGNALS |
735 | 833 |
736 | 834 |
737 } } // namespace v8::internal | 835 } } // namespace v8::internal |
OLD | NEW |