| Index: src/sampler.cc
|
| diff --git a/src/sampler.cc b/src/sampler.cc
|
| index 0ed4b379626a9746038b6e05b1661cee522f4f1f..c7e7c0f2b6723aed1d90d4e36d25feab12d8b991 100644
|
| --- a/src/sampler.cc
|
| +++ b/src/sampler.cc
|
| @@ -42,6 +42,8 @@
|
|
|
| #endif
|
|
|
| +#include "include/v8-sampler.h"
|
| +
|
| #include "src/v8.h"
|
|
|
| #include "src/base/platform/platform.h"
|
| @@ -269,8 +271,16 @@ 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_) mutex_ = new base::Mutex();
|
| + if (!register_state_semaphore_)
|
| + register_state_semaphore_ = new base::Semaphore(0);
|
| + }
|
| +
|
| + static void TearDown() {
|
| + delete mutex_;
|
| + delete register_state_semaphore_;
|
| + }
|
|
|
| static void IncreaseSamplerCount() {
|
| base::LockGuard<base::Mutex> lock_guard(mutex_);
|
| @@ -286,6 +296,17 @@ class SignalHandler : public AllStatic {
|
| return signal_handler_installed_;
|
| }
|
|
|
| + static RegisterState GetRegisterState() {
|
| + register_state_semaphore_->Wait();
|
| + register_state_updated_ = false;
|
| + return register_state_;
|
| + }
|
| +
|
| + static bool WasRegisterStateUpdated() {
|
| + return register_state_updated_;
|
| + }
|
| +
|
| +
|
| private:
|
| static void Install() {
|
| struct sigaction sa;
|
| @@ -308,6 +329,18 @@ class SignalHandler : public AllStatic {
|
| }
|
|
|
| static void HandleProfilerSignal(int signal, siginfo_t* info, void* context);
|
| +
|
| + // HandleProfilerSignal puts the state of registers into
|
| + // register_state_ and then signals on the semaphore,
|
| + // so that DoSample can use it.
|
| + static base::Semaphore* register_state_semaphore_;
|
| + static RegisterState register_state_;
|
| + // It is not that every time HandleProfilerSignal is invoked,
|
| + // the register state is guarenteed to be updated.
|
| + // This provides the SIGPROF sender with the information whether
|
| + // the handler finished with or without updating the register state.
|
| + static bool register_state_updated_;
|
| +
|
| // Protects the process wide state below.
|
| static base::Mutex* mutex_;
|
| static int client_count_;
|
| @@ -321,6 +354,9 @@ int SignalHandler::client_count_ = 0;
|
| struct sigaction SignalHandler::old_signal_handler_;
|
| bool SignalHandler::signal_handler_installed_ = false;
|
|
|
| +base::Semaphore* SignalHandler::register_state_semaphore_ = NULL;
|
| +RegisterState SignalHandler::register_state_;
|
| +bool SignalHandler::register_state_updated_ = false;
|
|
|
| void SignalHandler::HandleProfilerSignal(int signal, siginfo_t* info,
|
| void* context) {
|
| @@ -466,7 +502,9 @@ void SignalHandler::HandleProfilerSignal(int signal, siginfo_t* info,
|
| #endif // V8_HOST_ARCH_*
|
| #endif // V8_OS_QNX
|
| #endif // USE_SIMULATOR
|
| - sampler->SampleStack(state);
|
| + register_state_ = state;
|
| + register_state_updated_ = true;
|
| + register_state_semaphore_->Signal();
|
| #endif // V8_OS_NACL
|
| }
|
|
|
| @@ -564,7 +602,8 @@ SamplerThread* SamplerThread::instance_ = NULL;
|
| // StackTracer implementation
|
| //
|
| DISABLE_ASAN void TickSample::Init(Isolate* isolate,
|
| - const RegisterState& regs) {
|
| + const RegisterState& regs,
|
| + unsigned max_frame_count) {
|
| ASSERT(isolate->IsInitialized());
|
| timestamp = base::TimeTicks::HighResolutionNow();
|
| pc = regs.pc;
|
| @@ -597,7 +636,9 @@ DISABLE_ASAN void TickSample::Init(Isolate* isolate,
|
| SafeStackFrameIterator it(isolate, regs.fp, regs.sp, js_entry_sp);
|
| top_frame_type = it.top_frame_type();
|
| unsigned i = 0;
|
| - while (!it.done() && i < TickSample::kMaxFramesCount) {
|
| + if (max_frame_count > kMaxFramesCount)
|
| + max_frame_count = kMaxFramesCount;
|
| + while (!it.done() && i < max_frame_count) {
|
| stack[i++] = it.frame()->pc();
|
| it.Advance();
|
| }
|
| @@ -688,14 +729,33 @@ void Sampler::SampleStack(const RegisterState& state) {
|
|
|
| #if defined(USE_SIGNALS)
|
|
|
| -void Sampler::DoSample() {
|
| +void Sampler::CaptureRegisterState_() {
|
| if (!SignalHandler::Installed()) return;
|
| pthread_kill(platform_data()->vm_tid(), SIGPROF);
|
| }
|
|
|
| -#elif V8_OS_WIN || V8_OS_CYGWIN
|
|
|
| void Sampler::DoSample() {
|
| + CaptureRegisterState_();
|
| + if (SignalHandler::WasRegisterStateUpdated())
|
| + SampleStack(SignalHandler::GetRegisterState());
|
| +}
|
| +
|
| +
|
| +void Sampler::GetSample(TickSample* sample, unsigned max_frame_count) {
|
| + CaptureRegisterState_();
|
| + if (SignalHandler::WasRegisterStateUpdated())
|
| + sample->Init(isolate_,
|
| + SignalHandler::GetRegisterState(),
|
| + max_frame_count);
|
| +}
|
| +
|
| +#elif V8_OS_WIN || V8_OS_CYGWIN
|
| +
|
| +void Sampler::CaptureRegisterState_(RegisterState* state,
|
| + bool* captured_successfully) {
|
| + *captured_successfully = false;
|
| +
|
| HANDLE profiled_thread = platform_data()->profiled_thread();
|
| if (profiled_thread == NULL) return;
|
|
|
| @@ -712,25 +772,41 @@ void Sampler::DoSample() {
|
| memset(&context, 0, sizeof(context));
|
| context.ContextFlags = CONTEXT_FULL;
|
| if (GetThreadContext(profiled_thread, &context) != 0) {
|
| - RegisterState state;
|
| #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);
|
| + 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);
|
| + state->pc = reinterpret_cast<Address>(context.Eip);
|
| + state->sp = reinterpret_cast<Address>(context.Esp);
|
| + state->fp = reinterpret_cast<Address>(context.Ebp);
|
| #endif
|
| #endif // USE_SIMULATOR
|
| - SampleStack(state);
|
| + *captured_successfully = true;
|
| }
|
| ResumeThread(profiled_thread);
|
| }
|
|
|
| +
|
| +void Sampler::DoSample() {
|
| + bool register_state_captured;
|
| + RegisterState state;
|
| + CaptureRegisterState_(state, register_state_captured);
|
| + if (register_state_captured) SampleStack(state);
|
| +}
|
| +
|
| +
|
| +void Sampler::GetSample(TickSample* sample, unsigned max_frame_count) {
|
| + bool register_state_captured;
|
| + RegisterState state;
|
| + CaptureRegisterState_(state, register_state_captured);
|
| + if (register_state_captured)
|
| + sample->Init(isolate_, state, max_frame_count);
|
| +}
|
| +
|
| #endif // USE_SIGNALS
|
|
|
|
|
|
|