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 |