Chromium Code Reviews| Index: src/sampler.cc |
| diff --git a/src/sampler.cc b/src/sampler.cc |
| index 0ed4b379626a9746038b6e05b1661cee522f4f1f..36bce177a79a6ab23aa10499936459cf090360e5 100644 |
| --- a/src/sampler.cc |
| +++ b/src/sampler.cc |
| @@ -1,7 +1,6 @@ |
| // Copyright 2013 the V8 project authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| - |
|
alph
2014/09/17 11:55:43
plz revert.
|
| #include "src/sampler.h" |
| #if V8_OS_POSIX && !V8_OS_CYGWIN |
| @@ -44,6 +43,7 @@ |
| #include "src/v8.h" |
| +#include "src/base/logging.h" |
| #include "src/base/platform/platform.h" |
| #include "src/cpu-profiler-inl.h" |
| #include "src/flags.h" |
| @@ -269,8 +269,24 @@ class SimulatorHelper { |
| class SignalHandler : public AllStatic { |
| public: |
| - static void SetUp() { if (!mutex_) mutex_ = new base::Mutex(); } |
| - static void TearDown() { delete mutex_; } |
| + static void SetUp() { |
| + if (mutex_ != NULL && sampling_semaphore_ != NULL) |
| + return; // Already setup |
|
alph
2014/09/17 11:55:42
no need for the comment.
|
| + |
| + ASSERT_EQ(NULL, mutex_); |
| + ASSERT_EQ(NULL, sampling_semaphore_); |
| + |
| + mutex_ = new base::Mutex(); |
| + sampling_semaphore_ = new base::Semaphore(0); |
| + } |
| + |
| + static void TearDown() { |
| + delete mutex_; |
| + delete sampling_semaphore_; |
| + |
| + mutex_ = NULL; |
| + sampling_semaphore_ = NULL; |
| + } |
| static void IncreaseSamplerCount() { |
| base::LockGuard<base::Mutex> lock_guard(mutex_); |
| @@ -308,14 +324,45 @@ class SignalHandler : public AllStatic { |
| } |
| static void HandleProfilerSignal(int signal, siginfo_t* info, void* context); |
| + |
| + // The SIGPROF could have come from DoSample or from GetSample. |
| + // GetSample is the internal endpoint for the public |
| + // GetSample API, which aims to bypass all the internal buffers |
| + // and return just one sample instead, rightaway. |
| + // |
| + // The origin of SIGPROF is determined by FLAG_new_sampler_api |
| + // |
| + // TODO(gholap): Eventually, get rid of DoSample. |
| + // Only GetSample should remain. |
| + // Then, get rid of FLAG_new_sampler_api too. |
| + |
| + // This is the sample which will be filled by the call from GetSample. |
| + static TickSample sample_; |
| + |
| + // GetSample waits synchronously till the SIGPROF handler returns. |
| + // this semaphore is used to signal GetSample. |
| + static base::Semaphore* sampling_semaphore_; |
| + |
| + // It is not that every time HandleProfilerSignal is invoked, |
| + // it succeeds in obtaining a sample. |
| + // This provides GetSample with the information whether |
| + // the handler finished with or without getting the sample. |
| + static bool sample_available_; |
| + |
| // Protects the process wide state below. |
| static base::Mutex* mutex_; |
| static int client_count_; |
| static bool signal_handler_installed_; |
| static struct sigaction old_signal_handler_; |
| + |
| + friend class Sampler; |
| }; |
| +TickSample SignalHandler::sample_; |
| +base::Semaphore* SignalHandler::sampling_semaphore_ = NULL; |
| +bool SignalHandler::sample_available_ = false; |
| + |
| base::Mutex* SignalHandler::mutex_ = NULL; |
| int SignalHandler::client_count_ = 0; |
| struct sigaction SignalHandler::old_signal_handler_; |
| @@ -329,6 +376,11 @@ void SignalHandler::HandleProfilerSignal(int signal, siginfo_t* info, |
| // is disabled. |
| return; |
| #else |
| + // Even if we return prematurely, |
| + // we need to signal the sampling_semaphore_ |
| + sample_available_ = false; |
| + ScopedSemaphore scoped_semaphore(sampling_semaphore_); |
| + |
| USE(info); |
| if (signal != SIGPROF) return; |
| Isolate* isolate = Isolate::UncheckedReentrantCurrent(); |
| @@ -466,7 +518,12 @@ void SignalHandler::HandleProfilerSignal(int signal, siginfo_t* info, |
| #endif // V8_HOST_ARCH_* |
| #endif // V8_OS_QNX |
| #endif // USE_SIMULATOR |
| - sampler->SampleStack(state); |
| + if (FLAG_new_sampler_api) { |
| + sample_.Init(sampler->isolate(), state); |
| + sample_available_ = true; |
| + } else { |
| + sampler->SampleStack(state); |
| + } |
| #endif // V8_OS_NACL |
| } |
| @@ -569,6 +626,7 @@ DISABLE_ASAN void TickSample::Init(Isolate* isolate, |
| timestamp = base::TimeTicks::HighResolutionNow(); |
| pc = regs.pc; |
| state = isolate->current_vm_state(); |
| + frames_count = 0; |
| // Avoid collecting traces while doing GC. |
| if (state == GC) return; |
| @@ -621,6 +679,16 @@ void Sampler::TearDown() { |
| } |
| +void Sampler::SetUpForNewSamplingAPI() { |
| +#if defined(USE_SIGNALS) |
| + SignalHandler::SetUp(); |
| + if (!SignalHandler::Installed()) |
| + SignalHandler::Install(); |
| +#endif |
| + // Nothing needs to be done for windows. |
| +} |
| + |
| + |
| Sampler::Sampler(Isolate* isolate, int interval) |
| : isolate_(isolate), |
| interval_(interval), |
| @@ -693,8 +761,34 @@ void Sampler::DoSample() { |
| pthread_kill(platform_data()->vm_tid(), SIGPROF); |
| } |
| + |
| +void Sampler::GetSample(v8::Sample* sample) { |
| + SignalHandler::sampling_semaphore_->Wait(); |
| + if (SignalHandler::sample_available_) { |
| + sample = new(sample) v8::Sample( |
| + &SignalHandler::sample_.stack[0], |
| + &SignalHandler::sample_.stack[SignalHandler::sample_.frames_count]); |
| + } |
| + else { |
| + sample = new(sample) v8::Sample(); |
| + } |
| +} |
| + |
| #elif V8_OS_WIN || V8_OS_CYGWIN |
| +#if V8_HOST_ARCH_X64 |
| +#define CONTEXT_TO_STATE(context, state) \ |
| + state.pc = reinterpret_cast<Address>(context.Rip); \ |
| + state.sp = reinterpret_cast<Address>(context.Rsp); \ |
| + state.fp = reinterpret_cast<Address>(context.Rbp) |
| +#else |
| +#define CONTEXT_TO_STATE(context, state) \ |
| + state.pc = reinterpret_cast<Address>(context.Eip); \ |
| + state.sp = reinterpret_cast<Address>(context.Esp); \ |
| + state.fp = reinterpret_cast<Address>(context.Ebp) |
| +#endif |
| + |
| + |
| void Sampler::DoSample() { |
| HANDLE profiled_thread = platform_data()->profiled_thread(); |
| if (profiled_thread == NULL) return; |
| @@ -716,21 +810,25 @@ void Sampler::DoSample() { |
| #if defined(USE_SIMULATOR) |
| helper.FillRegisters(&state); |
| #else |
| -#if V8_HOST_ARCH_X64 |
| - state.pc = reinterpret_cast<Address>(context.Rip); |
| - state.sp = reinterpret_cast<Address>(context.Rsp); |
| - state.fp = reinterpret_cast<Address>(context.Rbp); |
| -#else |
| - state.pc = reinterpret_cast<Address>(context.Eip); |
| - state.sp = reinterpret_cast<Address>(context.Esp); |
| - state.fp = reinterpret_cast<Address>(context.Ebp); |
| -#endif |
| + CONTEXT_TO_STATE(context, state); |
| #endif // USE_SIMULATOR |
| SampleStack(state); |
| } |
| ResumeThread(profiled_thread); |
| } |
| + |
| +void Sampler::GetSample(Isolate* isolate, |
| + const CONTEXT& context, |
| + v8::Sample* sample) { |
| + TickSample tick_sample; |
| + RegisterState state; |
| + CONTEXT_TO_STATE(context, state); |
| + tick_sample.Init(isolate, state); |
| + sample = new(sample) v8::Sample(&tick_sample.stack[0], |
| + &tick_sample.stack[tick_sample.frames_count]); |
| +} |
| + |
| #endif // USE_SIGNALS |