Index: src/sampler.cc |
diff --git a/src/sampler.cc b/src/sampler.cc |
index c3268a3d73e9f963faa70d5483ea302f3d055051..5fee225b39290870a5dd2ed18b59c2c5bbf21ed0 100644 |
--- a/src/sampler.cc |
+++ b/src/sampler.cc |
@@ -231,44 +231,36 @@ class Sampler::PlatformData : public PlatformDataCommon { |
#endif |
-class SampleHelper { |
- public: |
- inline TickSample* Init(Sampler* sampler, Isolate* isolate) { |
#if defined(USE_SIMULATOR) |
+class SimulatorHelper { |
+ public: |
+ inline bool Init(Sampler* sampler, Isolate* isolate) { |
ThreadId thread_id = sampler->platform_data()->profiled_thread_id(); |
Isolate::PerIsolateThreadData* per_thread_data = isolate-> |
FindPerThreadDataForThread(thread_id); |
- if (!per_thread_data) return NULL; |
+ if (!per_thread_data) return false; |
simulator_ = per_thread_data->simulator(); |
- // Check if there is active simulator before allocating TickSample. |
- if (!simulator_) return NULL; |
-#endif // USE_SIMULATOR |
- TickSample* sample = isolate->cpu_profiler()->TickSampleEvent(); |
- if (sample == NULL) sample = &sample_obj; |
- return sample; |
+ // Check if there is active simulator. |
+ return simulator_ != NULL; |
} |
-#if defined(USE_SIMULATOR) |
- inline void FillRegisters(TickSample* sample) { |
- sample->pc = reinterpret_cast<Address>(simulator_->get_pc()); |
- sample->sp = reinterpret_cast<Address>(simulator_->get_register( |
+ inline void FillRegisters(RegisterState* state) { |
+ state->pc = reinterpret_cast<Address>(simulator_->get_pc()); |
+ state->sp = reinterpret_cast<Address>(simulator_->get_register( |
Simulator::sp)); |
#if V8_TARGET_ARCH_ARM |
- sample->fp = reinterpret_cast<Address>(simulator_->get_register( |
+ state->fp = reinterpret_cast<Address>(simulator_->get_register( |
Simulator::r11)); |
#elif V8_TARGET_ARCH_MIPS |
- sample->fp = reinterpret_cast<Address>(simulator_->get_register( |
+ state->fp = reinterpret_cast<Address>(simulator_->get_register( |
Simulator::fp)); |
#endif |
} |
-#endif // USE_SIMULATOR |
private: |
-#if defined(USE_SIMULATOR) |
Simulator* simulator_; |
-#endif |
- TickSample sample_obj; |
}; |
+#endif // USE_SIMULATOR |
#if defined(USE_SIGNALS) |
@@ -328,89 +320,86 @@ void SignalHandler::HandleProfilerSignal(int signal, siginfo_t* info, |
Sampler* sampler = isolate->logger()->sampler(); |
if (sampler == NULL || !sampler->IsActive()) return; |
- SampleHelper helper; |
- TickSample* sample = helper.Init(sampler, isolate); |
- if (sample == NULL) return; |
+ RegisterState state; |
#if defined(USE_SIMULATOR) |
- helper.FillRegisters(sample); |
+ SimulatorHelper helper; |
+ if (!helper.Init(sampler, isolate)) return; |
+ helper.FillRegisters(&state); |
#else |
// Extracting the sample from the context is extremely machine dependent. |
ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context); |
mcontext_t& mcontext = ucontext->uc_mcontext; |
- sample->state = isolate->current_vm_state(); |
#if defined(__linux__) || defined(__ANDROID__) |
#if V8_HOST_ARCH_IA32 |
- sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_EIP]); |
- sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_ESP]); |
- sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_EBP]); |
+ state.pc = reinterpret_cast<Address>(mcontext.gregs[REG_EIP]); |
+ state.sp = reinterpret_cast<Address>(mcontext.gregs[REG_ESP]); |
+ state.fp = reinterpret_cast<Address>(mcontext.gregs[REG_EBP]); |
#elif V8_HOST_ARCH_X64 |
- sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_RIP]); |
- sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_RSP]); |
- sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_RBP]); |
+ state.pc = reinterpret_cast<Address>(mcontext.gregs[REG_RIP]); |
+ state.sp = reinterpret_cast<Address>(mcontext.gregs[REG_RSP]); |
+ state.fp = reinterpret_cast<Address>(mcontext.gregs[REG_RBP]); |
#elif V8_HOST_ARCH_ARM |
#if defined(__GLIBC__) && !defined(__UCLIBC__) && \ |
(__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3)) |
// Old GLibc ARM versions used a gregs[] array to access the register |
// values from mcontext_t. |
- sample->pc = reinterpret_cast<Address>(mcontext.gregs[R15]); |
- sample->sp = reinterpret_cast<Address>(mcontext.gregs[R13]); |
- sample->fp = reinterpret_cast<Address>(mcontext.gregs[R11]); |
+ state.pc = reinterpret_cast<Address>(mcontext.gregs[R15]); |
+ state.sp = reinterpret_cast<Address>(mcontext.gregs[R13]); |
+ state.fp = reinterpret_cast<Address>(mcontext.gregs[R11]); |
#else |
- sample->pc = reinterpret_cast<Address>(mcontext.arm_pc); |
- sample->sp = reinterpret_cast<Address>(mcontext.arm_sp); |
- sample->fp = reinterpret_cast<Address>(mcontext.arm_fp); |
+ state.pc = reinterpret_cast<Address>(mcontext.arm_pc); |
+ state.sp = reinterpret_cast<Address>(mcontext.arm_sp); |
+ state.fp = reinterpret_cast<Address>(mcontext.arm_fp); |
#endif // defined(__GLIBC__) && !defined(__UCLIBC__) && |
// (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3)) |
#elif V8_HOST_ARCH_MIPS |
- sample->pc = reinterpret_cast<Address>(mcontext.pc); |
- sample->sp = reinterpret_cast<Address>(mcontext.gregs[29]); |
- sample->fp = reinterpret_cast<Address>(mcontext.gregs[30]); |
+ state.pc = reinterpret_cast<Address>(mcontext.pc); |
+ state.sp = reinterpret_cast<Address>(mcontext.gregs[29]); |
+ state.fp = reinterpret_cast<Address>(mcontext.gregs[30]); |
#endif // V8_HOST_ARCH_* |
#elif defined(__FreeBSD__) |
#if V8_HOST_ARCH_IA32 |
- sample->pc = reinterpret_cast<Address>(mcontext.mc_eip); |
- sample->sp = reinterpret_cast<Address>(mcontext.mc_esp); |
- sample->fp = reinterpret_cast<Address>(mcontext.mc_ebp); |
+ state.pc = reinterpret_cast<Address>(mcontext.mc_eip); |
+ state.sp = reinterpret_cast<Address>(mcontext.mc_esp); |
+ state.fp = reinterpret_cast<Address>(mcontext.mc_ebp); |
#elif V8_HOST_ARCH_X64 |
- sample->pc = reinterpret_cast<Address>(mcontext.mc_rip); |
- sample->sp = reinterpret_cast<Address>(mcontext.mc_rsp); |
- sample->fp = reinterpret_cast<Address>(mcontext.mc_rbp); |
+ state.pc = reinterpret_cast<Address>(mcontext.mc_rip); |
+ state.sp = reinterpret_cast<Address>(mcontext.mc_rsp); |
+ state.fp = reinterpret_cast<Address>(mcontext.mc_rbp); |
#elif V8_HOST_ARCH_ARM |
- sample->pc = reinterpret_cast<Address>(mcontext.mc_r15); |
- sample->sp = reinterpret_cast<Address>(mcontext.mc_r13); |
- sample->fp = reinterpret_cast<Address>(mcontext.mc_r11); |
+ state.pc = reinterpret_cast<Address>(mcontext.mc_r15); |
+ state.sp = reinterpret_cast<Address>(mcontext.mc_r13); |
+ state.fp = reinterpret_cast<Address>(mcontext.mc_r11); |
#endif // V8_HOST_ARCH_* |
#elif defined(__NetBSD__) |
#if V8_HOST_ARCH_IA32 |
- sample->pc = reinterpret_cast<Address>(mcontext.__gregs[_REG_EIP]); |
- sample->sp = reinterpret_cast<Address>(mcontext.__gregs[_REG_ESP]); |
- sample->fp = reinterpret_cast<Address>(mcontext.__gregs[_REG_EBP]); |
+ state.pc = reinterpret_cast<Address>(mcontext.__gregs[_REG_EIP]); |
+ state.sp = reinterpret_cast<Address>(mcontext.__gregs[_REG_ESP]); |
+ state.fp = reinterpret_cast<Address>(mcontext.__gregs[_REG_EBP]); |
#elif V8_HOST_ARCH_X64 |
- sample->pc = reinterpret_cast<Address>(mcontext.__gregs[_REG_RIP]); |
- sample->sp = reinterpret_cast<Address>(mcontext.__gregs[_REG_RSP]); |
- sample->fp = reinterpret_cast<Address>(mcontext.__gregs[_REG_RBP]); |
+ state.pc = reinterpret_cast<Address>(mcontext.__gregs[_REG_RIP]); |
+ state.sp = reinterpret_cast<Address>(mcontext.__gregs[_REG_RSP]); |
+ state.fp = reinterpret_cast<Address>(mcontext.__gregs[_REG_RBP]); |
#endif // V8_HOST_ARCH_* |
#elif defined(__OpenBSD__) |
USE(mcontext); |
#if V8_HOST_ARCH_IA32 |
- sample->pc = reinterpret_cast<Address>(ucontext->sc_eip); |
- sample->sp = reinterpret_cast<Address>(ucontext->sc_esp); |
- sample->fp = reinterpret_cast<Address>(ucontext->sc_ebp); |
+ state.pc = reinterpret_cast<Address>(ucontext->sc_eip); |
+ state.sp = reinterpret_cast<Address>(ucontext->sc_esp); |
+ state.fp = reinterpret_cast<Address>(ucontext->sc_ebp); |
#elif V8_HOST_ARCH_X64 |
- sample->pc = reinterpret_cast<Address>(ucontext->sc_rip); |
- sample->sp = reinterpret_cast<Address>(ucontext->sc_rsp); |
- sample->fp = reinterpret_cast<Address>(ucontext->sc_rbp); |
+ state.pc = reinterpret_cast<Address>(ucontext->sc_rip); |
+ state.sp = reinterpret_cast<Address>(ucontext->sc_rsp); |
+ state.fp = reinterpret_cast<Address>(ucontext->sc_rbp); |
#endif // V8_HOST_ARCH_* |
#elif defined(__sun) |
- sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_PC]); |
- sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_SP]); |
- sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_FP]); |
+ state.pc = reinterpret_cast<Address>(mcontext.gregs[REG_PC]); |
+ state.sp = reinterpret_cast<Address>(mcontext.gregs[REG_SP]); |
+ state.fp = reinterpret_cast<Address>(mcontext.gregs[REG_FP]); |
#endif // __sun |
#endif // USE_SIMULATOR |
- |
- sampler->SampleStack(sample); |
- sampler->Tick(sample); |
+ sampler->SampleStack(state); |
#endif // __native_client__ |
} |
@@ -509,9 +498,10 @@ class SamplerThread : public Thread { |
thread_act_t profiled_thread = sampler->platform_data()->profiled_thread(); |
Isolate* isolate = sampler->isolate(); |
- SampleHelper helper; |
- TickSample* sample = helper.Init(sampler, isolate); |
- if (sample == NULL) return; |
+#if defined(USE_SIMULATOR) |
+ SimulatorHelper helper; |
+ if (!helper.Init(sampler, isolate)) return; |
+#endif |
if (KERN_SUCCESS != thread_suspend(profiled_thread)) return; |
@@ -541,17 +531,16 @@ class SamplerThread : public Thread { |
flavor, |
reinterpret_cast<natural_t*>(&state), |
&count) == KERN_SUCCESS) { |
- sample->state = isolate->current_vm_state(); |
+ RegisterState state; |
#if defined(USE_SIMULATOR) |
- helper.FillRegisters(sample); |
+ helper.FillRegisters(&state); |
#else |
- sample->pc = reinterpret_cast<Address>(state.REGISTER_FIELD(ip)); |
- sample->sp = reinterpret_cast<Address>(state.REGISTER_FIELD(sp)); |
- sample->fp = reinterpret_cast<Address>(state.REGISTER_FIELD(bp)); |
+ state.pc = reinterpret_cast<Address>(state.REGISTER_FIELD(ip)); |
+ state.sp = reinterpret_cast<Address>(state.REGISTER_FIELD(sp)); |
+ state.fp = reinterpret_cast<Address>(state.REGISTER_FIELD(bp)); |
#endif // USE_SIMULATOR |
#undef REGISTER_FIELD |
- sampler->SampleStack(sample); |
- sampler->Tick(sample); |
+ sampler->SampleStack(state); |
} |
thread_resume(profiled_thread); |
} |
@@ -563,34 +552,34 @@ class SamplerThread : public Thread { |
if (profiled_thread == NULL) return; |
Isolate* isolate = sampler->isolate(); |
- SampleHelper helper; |
- TickSample* sample = helper.Init(sampler, isolate); |
- if (sample == NULL) return; |
+#if defined(USE_SIMULATOR) |
+ SimulatorHelper helper; |
+ if (!helper.Init(sampler, isolate)) return; |
+#endif |
const DWORD kSuspendFailed = static_cast<DWORD>(-1); |
if (SuspendThread(profiled_thread) == kSuspendFailed) return; |
- sample->state = isolate->current_vm_state(); |
// Context used for sampling the register state of the profiled thread. |
CONTEXT context; |
memset(&context, 0, sizeof(context)); |
context.ContextFlags = CONTEXT_FULL; |
if (GetThreadContext(profiled_thread, &context) != 0) { |
+ RegisterState state; |
#if defined(USE_SIMULATOR) |
- helper.FillRegisters(sample); |
+ helper.FillRegisters(&state); |
#else |
#if V8_HOST_ARCH_X64 |
- sample->pc = reinterpret_cast<Address>(context.Rip); |
- sample->sp = reinterpret_cast<Address>(context.Rsp); |
- sample->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 |
- sample->pc = reinterpret_cast<Address>(context.Eip); |
- sample->sp = reinterpret_cast<Address>(context.Esp); |
- sample->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 |
- sampler->SampleStack(sample); |
- sampler->Tick(sample); |
+ sampler->SampleStack(state); |
} |
ResumeThread(profiled_thread); |
} |
@@ -616,8 +605,11 @@ SamplerThread* SamplerThread::instance_ = NULL; |
// |
// StackTracer implementation |
// |
-DISABLE_ASAN void TickSample::Trace(Isolate* isolate) { |
+DISABLE_ASAN void TickSample::Init(Isolate* isolate, |
+ const RegisterState& regs) { |
ASSERT(isolate->IsInitialized()); |
+ pc = regs.pc; |
+ state = isolate->current_vm_state(); |
// Avoid collecting traces while doing GC. |
if (state == GC) return; |
@@ -636,11 +628,11 @@ DISABLE_ASAN void TickSample::Trace(Isolate* isolate) { |
} else { |
// Sample potential return address value for frameless invocation of |
// stubs (we'll figure out later, if this value makes sense). |
- tos = Memory::Address_at(sp); |
+ tos = Memory::Address_at(regs.sp); |
has_external_callback = false; |
} |
- SafeStackFrameIterator it(isolate, fp, sp, sp, js_entry_sp); |
+ SafeStackFrameIterator it(isolate, regs.fp, regs.sp, js_entry_sp); |
top_frame_type = it.top_frame_type(); |
int i = 0; |
while (!it.done() && i < TickSample::kMaxFramesCount) { |
@@ -689,9 +681,13 @@ void Sampler::Stop() { |
SetActive(false); |
} |
-void Sampler::SampleStack(TickSample* sample) { |
- sample->Trace(isolate_); |
+void Sampler::SampleStack(const RegisterState& state) { |
+ TickSample* sample = isolate_->cpu_profiler()->TickSampleEvent(); |
+ TickSample sample_obj; |
+ if (sample == NULL) sample = &sample_obj; |
+ sample->Init(isolate_, state); |
if (++samples_taken_ < 0) samples_taken_ = 0; |
+ Tick(sample); |
} |
} } // namespace v8::internal |