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

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: Rebased on bleeding_edge Created 6 years, 3 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
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
alph 2014/09/09 13:54:37 Please 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
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 211 matching lines...) Expand 10 before | Expand all | Expand 10 after
268 private: 268 private:
269 Simulator* simulator_; 269 Simulator* simulator_;
270 }; 270 };
271 #endif // USE_SIMULATOR 271 #endif // USE_SIMULATOR
272 272
273 273
274 #if defined(USE_SIGNALS) 274 #if defined(USE_SIGNALS)
275 275
276 class SignalHandler : public AllStatic { 276 class SignalHandler : public AllStatic {
277 public: 277 public:
278 static void SetUp() { if (!mutex_) mutex_ = new base::Mutex(); } 278 static void SetUp() {
279 static void TearDown() { delete mutex_; mutex_ = NULL; } 279 CHECK_EQ(NULL, mutex_);
280 CHECK_EQ(NULL, sampling_semaphore_);
281
282 mutex_ = new base::Mutex();
283 sampling_semaphore_ = new base::Semaphore(0);
284 }
285
286 static void TearDown() {
287 delete mutex_;
288 delete sampling_semaphore_;
289
290 mutex_ = NULL;
291 sampling_semaphore_ = NULL;
292 }
280 293
281 static void IncreaseSamplerCount() { 294 static void IncreaseSamplerCount() {
282 base::LockGuard<base::Mutex> lock_guard(mutex_); 295 base::LockGuard<base::Mutex> lock_guard(mutex_);
283 if (++client_count_ == 1) Install(); 296 if (++client_count_ == 1) Install();
284 } 297 }
285 298
286 static void DecreaseSamplerCount() { 299 static void DecreaseSamplerCount() {
287 base::LockGuard<base::Mutex> lock_guard(mutex_); 300 base::LockGuard<base::Mutex> lock_guard(mutex_);
288 if (--client_count_ == 0) Restore(); 301 if (--client_count_ == 0) Restore();
289 } 302 }
(...skipping 23 matching lines...) Expand all
313 if (signal_handler_installed_) { 326 if (signal_handler_installed_) {
314 sigaction(SIGPROF, &old_signal_handler_, 0); 327 sigaction(SIGPROF, &old_signal_handler_, 0);
315 signal_handler_installed_ = false; 328 signal_handler_installed_ = false;
316 } 329 }
317 #endif 330 #endif
318 } 331 }
319 332
320 #if !V8_OS_NACL 333 #if !V8_OS_NACL
321 static void HandleProfilerSignal(int signal, siginfo_t* info, void* context); 334 static void HandleProfilerSignal(int signal, siginfo_t* info, void* context);
322 #endif 335 #endif
336
337 // The SIGPROF could have come from DoSample or from GetSample.
338 // GetSample is the internal endpoint for the public
339 // GetSample API, which aims to bypass all the internal buffers
340 // and return just one sample instead, rightaway.
341 // TODO(gholap): Eventually, get rid of DoSample.
342 // Only GetSample should remain.
343
344 // This is the sample which will be filled by the call from GetSample.
345 static TickSample sample_;
346
347 // For the SIGPROF handler to know whether the call was from GetSample.
348 static volatile bool called_from_get_sample_;
349
350 // GetSample waits synchronously till the SIGPROF handler returns.
351 // this semaphore is used to signal GetSample.
352 static base::Semaphore* sampling_semaphore_;
353
354 // It is not that every time HandleProfilerSignal is invoked,
355 // it succeeds in obtaining a sample.
356 // This provides GetSample with the information whether
357 // the handler finished with or without getting the sample.
358 static bool sample_available_;
359
323 // Protects the process wide state below. 360 // Protects the process wide state below.
324 static base::Mutex* mutex_; 361 static base::Mutex* mutex_;
325 static int client_count_; 362 static int client_count_;
326 static bool signal_handler_installed_; 363 static bool signal_handler_installed_;
327 static struct sigaction old_signal_handler_; 364 static struct sigaction old_signal_handler_;
365
366 friend class Sampler;
328 }; 367 };
329 368
330 369
370 TickSample SignalHandler::sample_;
371 volatile bool SignalHandler::called_from_get_sample_ = false;
372 base::Semaphore* SignalHandler::sampling_semaphore_ = NULL;
373 bool SignalHandler::sample_available_ = false;
374
331 base::Mutex* SignalHandler::mutex_ = NULL; 375 base::Mutex* SignalHandler::mutex_ = NULL;
332 int SignalHandler::client_count_ = 0; 376 int SignalHandler::client_count_ = 0;
333 struct sigaction SignalHandler::old_signal_handler_; 377 struct sigaction SignalHandler::old_signal_handler_;
334 bool SignalHandler::signal_handler_installed_ = false; 378 bool SignalHandler::signal_handler_installed_ = false;
335 379
336 380
337 // As Native Client does not support signal handling, profiling is disabled. 381 // As Native Client does not support signal handling, profiling is disabled.
338 #if !V8_OS_NACL 382 #if !V8_OS_NACL
339 void SignalHandler::HandleProfilerSignal(int signal, siginfo_t* info, 383 void SignalHandler::HandleProfilerSignal(int signal, siginfo_t* info,
340 void* context) { 384 void* context) {
385 // Even if we return prematurely,
386 // we need to signal the sampling_semaphore_
387 sample_available_ = false;
388 ScopedSemaphore scoped_semaphore(sampling_semaphore_);
389
341 USE(info); 390 USE(info);
342 if (signal != SIGPROF) return; 391 if (signal != SIGPROF) return;
343 Isolate* isolate = Isolate::UnsafeCurrent(); 392 Isolate* isolate = Isolate::UnsafeCurrent();
344 if (isolate == NULL || !isolate->IsInitialized() || !isolate->IsInUse()) { 393 if (isolate == NULL || !isolate->IsInitialized() || !isolate->IsInUse()) {
345 // We require a fully initialized and entered isolate. 394 // We require a fully initialized and entered isolate.
346 return; 395 return;
347 } 396 }
348 if (v8::Locker::IsActive() && 397 if (v8::Locker::IsActive() &&
349 !isolate->thread_manager()->IsLockedByCurrentThread()) { 398 !isolate->thread_manager()->IsLockedByCurrentThread()) {
350 return; 399 return;
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
472 state.pc = reinterpret_cast<Address>(mcontext.cpu.eip); 521 state.pc = reinterpret_cast<Address>(mcontext.cpu.eip);
473 state.sp = reinterpret_cast<Address>(mcontext.cpu.esp); 522 state.sp = reinterpret_cast<Address>(mcontext.cpu.esp);
474 state.fp = reinterpret_cast<Address>(mcontext.cpu.ebp); 523 state.fp = reinterpret_cast<Address>(mcontext.cpu.ebp);
475 #elif V8_HOST_ARCH_ARM 524 #elif V8_HOST_ARCH_ARM
476 state.pc = reinterpret_cast<Address>(mcontext.cpu.gpr[ARM_REG_PC]); 525 state.pc = reinterpret_cast<Address>(mcontext.cpu.gpr[ARM_REG_PC]);
477 state.sp = reinterpret_cast<Address>(mcontext.cpu.gpr[ARM_REG_SP]); 526 state.sp = reinterpret_cast<Address>(mcontext.cpu.gpr[ARM_REG_SP]);
478 state.fp = reinterpret_cast<Address>(mcontext.cpu.gpr[ARM_REG_FP]); 527 state.fp = reinterpret_cast<Address>(mcontext.cpu.gpr[ARM_REG_FP]);
479 #endif // V8_HOST_ARCH_* 528 #endif // V8_HOST_ARCH_*
480 #endif // V8_OS_QNX 529 #endif // V8_OS_QNX
481 #endif // USE_SIMULATOR 530 #endif // USE_SIMULATOR
482 sampler->SampleStack(state); 531 if (called_from_get_sample_) {
532 sample_.Init(sampler->isolate(), state);
533 } else {
534 sampler->SampleStack(state);
535 }
536 sample_available_ = true;
483 } 537 }
484 #endif // V8_OS_NACL 538 #endif // V8_OS_NACL
485 539
486 #endif 540 #endif
487 541
488 542
489 class SamplerThread : public base::Thread { 543 class SamplerThread : public base::Thread {
490 public: 544 public:
491 static const int kSamplerThreadStackSize = 64 * KB; 545 static const int kSamplerThreadStackSize = 64 * KB;
492 546
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
575 629
576 // 630 //
577 // StackTracer implementation 631 // StackTracer implementation
578 // 632 //
579 DISABLE_ASAN void TickSample::Init(Isolate* isolate, 633 DISABLE_ASAN void TickSample::Init(Isolate* isolate,
580 const RegisterState& regs) { 634 const RegisterState& regs) {
581 DCHECK(isolate->IsInitialized()); 635 DCHECK(isolate->IsInitialized());
582 timestamp = base::TimeTicks::HighResolutionNow(); 636 timestamp = base::TimeTicks::HighResolutionNow();
583 pc = regs.pc; 637 pc = regs.pc;
584 state = isolate->current_vm_state(); 638 state = isolate->current_vm_state();
639 frames_count = 0;
585 640
586 // Avoid collecting traces while doing GC. 641 // Avoid collecting traces while doing GC.
587 if (state == GC) return; 642 if (state == GC) return;
588 643
589 Address js_entry_sp = isolate->js_entry_sp(); 644 Address js_entry_sp = isolate->js_entry_sp();
590 if (js_entry_sp == 0) { 645 if (js_entry_sp == 0) {
591 // Not executing JS now. 646 // Not executing JS now.
592 return; 647 return;
593 } 648 }
594 649
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
699 } 754 }
700 755
701 756
702 #if defined(USE_SIGNALS) 757 #if defined(USE_SIGNALS)
703 758
704 void Sampler::DoSample() { 759 void Sampler::DoSample() {
705 if (!SignalHandler::Installed()) return; 760 if (!SignalHandler::Installed()) return;
706 pthread_kill(platform_data()->vm_tid(), SIGPROF); 761 pthread_kill(platform_data()->vm_tid(), SIGPROF);
707 } 762 }
708 763
764
765 void Sampler::GetSample(v8::Sample* sample) {
766 SignalHandler::called_from_get_sample_ = true;
767 pthread_kill(platform_data()->vm_tid(), SIGPROF);
768 SignalHandler::sampling_semaphore_->Wait();
769 if (SignalHandler::sample_available_) {
770 sample = new (sample) v8::Sample(
771 &SignalHandler::sample_.stack[0],
772 &SignalHandler::sample_.stack[SignalHandler::sample_.frames_count]);
773 }
774 SignalHandler::called_from_get_sample_ = false;
775 }
776
709 #elif V8_OS_WIN || V8_OS_CYGWIN 777 #elif V8_OS_WIN || V8_OS_CYGWIN
710 778
711 void Sampler::DoSample() { 779 void Sampler::GetSampleHelper(TickSample* sample, bool called_from_get_sample) {
alph 2014/09/09 13:54:37 nit: you can get rid of the called_from_get_sample
gholap 2014/09/17 02:35:06 Done.
712 HANDLE profiled_thread = platform_data()->profiled_thread(); 780 HANDLE profiled_thread = platform_data()->profiled_thread();
713 if (profiled_thread == NULL) return; 781 if (profiled_thread == NULL) return;
714 782
715 #if defined(USE_SIMULATOR) 783 #if defined(USE_SIMULATOR)
716 SimulatorHelper helper; 784 SimulatorHelper helper;
717 if (!helper.Init(this, isolate())) return; 785 if (!helper.Init(this, isolate())) return;
718 #endif 786 #endif
719 787
720 const DWORD kSuspendFailed = static_cast<DWORD>(-1); 788 const DWORD kSuspendFailed = static_cast<DWORD>(-1);
721 if (SuspendThread(profiled_thread) == kSuspendFailed) return; 789 if (SuspendThread(profiled_thread) == kSuspendFailed) return;
(...skipping 10 matching lines...) Expand all
732 #if V8_HOST_ARCH_X64 800 #if V8_HOST_ARCH_X64
733 state.pc = reinterpret_cast<Address>(context.Rip); 801 state.pc = reinterpret_cast<Address>(context.Rip);
734 state.sp = reinterpret_cast<Address>(context.Rsp); 802 state.sp = reinterpret_cast<Address>(context.Rsp);
735 state.fp = reinterpret_cast<Address>(context.Rbp); 803 state.fp = reinterpret_cast<Address>(context.Rbp);
736 #else 804 #else
737 state.pc = reinterpret_cast<Address>(context.Eip); 805 state.pc = reinterpret_cast<Address>(context.Eip);
738 state.sp = reinterpret_cast<Address>(context.Esp); 806 state.sp = reinterpret_cast<Address>(context.Esp);
739 state.fp = reinterpret_cast<Address>(context.Ebp); 807 state.fp = reinterpret_cast<Address>(context.Ebp);
740 #endif 808 #endif
741 #endif // USE_SIMULATOR 809 #endif // USE_SIMULATOR
742 SampleStack(state); 810 if (called_from_get_sample) {
811 sample->Init(isolate_, state);
812 } else {
813 SampleStack(state);
814 }
743 } 815 }
744 ResumeThread(profiled_thread); 816 ResumeThread(profiled_thread);
745 } 817 }
746 818
819
820 void Sampler::DoSample() { GetSampleHelper(NULL, false); }
821
822
823 void Sampler::GetSample(v8::Sample* sample) {
824 // We need this tick_sample because,
825 // GetSampleHelper calls Init, which must be called on
826 // a TickSample and never on Sample.
alph 2014/09/09 13:54:37 nit: I don't think this comment adds something her
gholap 2014/09/17 02:35:06 Acknowledged.
827 TickSample tick_sample;
828 GetSampleHelper(&tick_sample, true);
829 sample = new (sample) v8::Sample(
830 &tick_sample.stack[0], &tick_sample.stack[tick_sample.frames_count]);
831 }
832
747 #endif // USE_SIGNALS 833 #endif // USE_SIGNALS
748 834
749 835
750 } } // namespace v8::internal 836 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698