Commit 9ef762b6 authored by yurys@chromium.org's avatar yurys@chromium.org

Do not store fp and sp values in TickSample

Their values are not used neither by the tick processor nor by CpuProfiler so it is just a waste of space.

TickSample used to be a transport for grabbed register values to TickSample::Trace, now they are passed in a special structure RegisterState which is allocated on the stack for the sampling period.

Some common pieces were moved from platform-dependent code into Sampler::SampleStack and TickSample::Init.

BUG=None
R=jkummerow@chromium.org, loislo@chromium.org

Review URL: https://codereview.chromium.org/18620002

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@15484 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 91be57a4
...@@ -216,9 +216,10 @@ bool StackTraceFrameIterator::IsValidFrame() { ...@@ -216,9 +216,10 @@ bool StackTraceFrameIterator::IsValidFrame() {
SafeStackFrameIterator::SafeStackFrameIterator( SafeStackFrameIterator::SafeStackFrameIterator(
Isolate* isolate, Isolate* isolate,
Address fp, Address sp, Address low_bound, Address high_bound) : Address fp, Address sp, Address js_entry_sp)
StackFrameIteratorBase(isolate, false), : StackFrameIteratorBase(isolate, false),
low_bound_(low_bound), high_bound_(high_bound), low_bound_(sp),
high_bound_(js_entry_sp),
top_frame_type_(StackFrame::NONE) { top_frame_type_(StackFrame::NONE) {
StackFrame::State state; StackFrame::State state;
StackFrame::Type type; StackFrame::Type type;
......
...@@ -881,7 +881,7 @@ class SafeStackFrameIterator: public StackFrameIteratorBase { ...@@ -881,7 +881,7 @@ class SafeStackFrameIterator: public StackFrameIteratorBase {
public: public:
SafeStackFrameIterator(Isolate* isolate, SafeStackFrameIterator(Isolate* isolate,
Address fp, Address sp, Address fp, Address sp,
Address low_bound, Address high_bound); Address js_entry_sp);
inline JavaScriptFrame* frame() const; inline JavaScriptFrame* frame() const;
void Advance(); void Advance();
......
...@@ -1364,8 +1364,6 @@ void Logger::TickEvent(TickSample* sample, bool overflow) { ...@@ -1364,8 +1364,6 @@ void Logger::TickEvent(TickSample* sample, bool overflow) {
LogMessageBuilder msg(this); LogMessageBuilder msg(this);
msg.Append("%s,", kLogEventsNames[TICK_EVENT]); msg.Append("%s,", kLogEventsNames[TICK_EVENT]);
msg.AppendAddress(sample->pc); msg.AppendAddress(sample->pc);
msg.Append(',');
msg.AppendAddress(sample->sp);
msg.Append(",%ld", static_cast<int>(OS::Ticks() - epoch_)); msg.Append(",%ld", static_cast<int>(OS::Ticks() - epoch_));
if (sample->has_external_callback) { if (sample->has_external_callback) {
msg.Append(",1,"); msg.Append(",1,");
......
...@@ -231,44 +231,36 @@ class Sampler::PlatformData : public PlatformDataCommon { ...@@ -231,44 +231,36 @@ class Sampler::PlatformData : public PlatformDataCommon {
#endif #endif
class SampleHelper {
public:
inline TickSample* Init(Sampler* sampler, Isolate* isolate) {
#if defined(USE_SIMULATOR) #if defined(USE_SIMULATOR)
class SimulatorHelper {
public:
inline bool Init(Sampler* sampler, Isolate* isolate) {
ThreadId thread_id = sampler->platform_data()->profiled_thread_id(); ThreadId thread_id = sampler->platform_data()->profiled_thread_id();
Isolate::PerIsolateThreadData* per_thread_data = isolate-> Isolate::PerIsolateThreadData* per_thread_data = isolate->
FindPerThreadDataForThread(thread_id); FindPerThreadDataForThread(thread_id);
if (!per_thread_data) return NULL; if (!per_thread_data) return false;
simulator_ = per_thread_data->simulator(); simulator_ = per_thread_data->simulator();
// Check if there is active simulator before allocating TickSample. // Check if there is active simulator.
if (!simulator_) return NULL; return simulator_ != NULL;
#endif // USE_SIMULATOR
TickSample* sample = isolate->cpu_profiler()->TickSampleEvent();
if (sample == NULL) sample = &sample_obj;
return sample;
} }
#if defined(USE_SIMULATOR) inline void FillRegisters(RegisterState* state) {
inline void FillRegisters(TickSample* sample) { state->pc = reinterpret_cast<Address>(simulator_->get_pc());
sample->pc = reinterpret_cast<Address>(simulator_->get_pc()); state->sp = reinterpret_cast<Address>(simulator_->get_register(
sample->sp = reinterpret_cast<Address>(simulator_->get_register(
Simulator::sp)); Simulator::sp));
#if V8_TARGET_ARCH_ARM #if V8_TARGET_ARCH_ARM
sample->fp = reinterpret_cast<Address>(simulator_->get_register( state->fp = reinterpret_cast<Address>(simulator_->get_register(
Simulator::r11)); Simulator::r11));
#elif V8_TARGET_ARCH_MIPS #elif V8_TARGET_ARCH_MIPS
sample->fp = reinterpret_cast<Address>(simulator_->get_register( state->fp = reinterpret_cast<Address>(simulator_->get_register(
Simulator::fp)); Simulator::fp));
#endif #endif
} }
#endif // USE_SIMULATOR
private: private:
#if defined(USE_SIMULATOR)
Simulator* simulator_; Simulator* simulator_;
#endif
TickSample sample_obj;
}; };
#endif // USE_SIMULATOR
#if defined(USE_SIGNALS) #if defined(USE_SIGNALS)
...@@ -328,89 +320,86 @@ void SignalHandler::HandleProfilerSignal(int signal, siginfo_t* info, ...@@ -328,89 +320,86 @@ void SignalHandler::HandleProfilerSignal(int signal, siginfo_t* info,
Sampler* sampler = isolate->logger()->sampler(); Sampler* sampler = isolate->logger()->sampler();
if (sampler == NULL || !sampler->IsActive()) return; if (sampler == NULL || !sampler->IsActive()) return;
SampleHelper helper; RegisterState state;
TickSample* sample = helper.Init(sampler, isolate);
if (sample == NULL) return;
#if defined(USE_SIMULATOR) #if defined(USE_SIMULATOR)
helper.FillRegisters(sample); SimulatorHelper helper;
if (!helper.Init(sampler, isolate)) return;
helper.FillRegisters(&state);
#else #else
// Extracting the sample from the context is extremely machine dependent. // Extracting the sample from the context is extremely machine dependent.
ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context); ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
mcontext_t& mcontext = ucontext->uc_mcontext; mcontext_t& mcontext = ucontext->uc_mcontext;
sample->state = isolate->current_vm_state();
#if defined(__linux__) || defined(__ANDROID__) #if defined(__linux__) || defined(__ANDROID__)
#if V8_HOST_ARCH_IA32 #if V8_HOST_ARCH_IA32
sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_EIP]); state.pc = reinterpret_cast<Address>(mcontext.gregs[REG_EIP]);
sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_ESP]); state.sp = reinterpret_cast<Address>(mcontext.gregs[REG_ESP]);
sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_EBP]); state.fp = reinterpret_cast<Address>(mcontext.gregs[REG_EBP]);
#elif V8_HOST_ARCH_X64 #elif V8_HOST_ARCH_X64
sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_RIP]); state.pc = reinterpret_cast<Address>(mcontext.gregs[REG_RIP]);
sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_RSP]); state.sp = reinterpret_cast<Address>(mcontext.gregs[REG_RSP]);
sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_RBP]); state.fp = reinterpret_cast<Address>(mcontext.gregs[REG_RBP]);
#elif V8_HOST_ARCH_ARM #elif V8_HOST_ARCH_ARM
#if defined(__GLIBC__) && !defined(__UCLIBC__) && \ #if defined(__GLIBC__) && !defined(__UCLIBC__) && \
(__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3)) (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
// Old GLibc ARM versions used a gregs[] array to access the register // Old GLibc ARM versions used a gregs[] array to access the register
// values from mcontext_t. // values from mcontext_t.
sample->pc = reinterpret_cast<Address>(mcontext.gregs[R15]); state.pc = reinterpret_cast<Address>(mcontext.gregs[R15]);
sample->sp = reinterpret_cast<Address>(mcontext.gregs[R13]); state.sp = reinterpret_cast<Address>(mcontext.gregs[R13]);
sample->fp = reinterpret_cast<Address>(mcontext.gregs[R11]); state.fp = reinterpret_cast<Address>(mcontext.gregs[R11]);
#else #else
sample->pc = reinterpret_cast<Address>(mcontext.arm_pc); state.pc = reinterpret_cast<Address>(mcontext.arm_pc);
sample->sp = reinterpret_cast<Address>(mcontext.arm_sp); state.sp = reinterpret_cast<Address>(mcontext.arm_sp);
sample->fp = reinterpret_cast<Address>(mcontext.arm_fp); state.fp = reinterpret_cast<Address>(mcontext.arm_fp);
#endif // defined(__GLIBC__) && !defined(__UCLIBC__) && #endif // defined(__GLIBC__) && !defined(__UCLIBC__) &&
// (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3)) // (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
#elif V8_HOST_ARCH_MIPS #elif V8_HOST_ARCH_MIPS
sample->pc = reinterpret_cast<Address>(mcontext.pc); state.pc = reinterpret_cast<Address>(mcontext.pc);
sample->sp = reinterpret_cast<Address>(mcontext.gregs[29]); state.sp = reinterpret_cast<Address>(mcontext.gregs[29]);
sample->fp = reinterpret_cast<Address>(mcontext.gregs[30]); state.fp = reinterpret_cast<Address>(mcontext.gregs[30]);
#endif // V8_HOST_ARCH_* #endif // V8_HOST_ARCH_*
#elif defined(__FreeBSD__) #elif defined(__FreeBSD__)
#if V8_HOST_ARCH_IA32 #if V8_HOST_ARCH_IA32
sample->pc = reinterpret_cast<Address>(mcontext.mc_eip); state.pc = reinterpret_cast<Address>(mcontext.mc_eip);
sample->sp = reinterpret_cast<Address>(mcontext.mc_esp); state.sp = reinterpret_cast<Address>(mcontext.mc_esp);
sample->fp = reinterpret_cast<Address>(mcontext.mc_ebp); state.fp = reinterpret_cast<Address>(mcontext.mc_ebp);
#elif V8_HOST_ARCH_X64 #elif V8_HOST_ARCH_X64
sample->pc = reinterpret_cast<Address>(mcontext.mc_rip); state.pc = reinterpret_cast<Address>(mcontext.mc_rip);
sample->sp = reinterpret_cast<Address>(mcontext.mc_rsp); state.sp = reinterpret_cast<Address>(mcontext.mc_rsp);
sample->fp = reinterpret_cast<Address>(mcontext.mc_rbp); state.fp = reinterpret_cast<Address>(mcontext.mc_rbp);
#elif V8_HOST_ARCH_ARM #elif V8_HOST_ARCH_ARM
sample->pc = reinterpret_cast<Address>(mcontext.mc_r15); state.pc = reinterpret_cast<Address>(mcontext.mc_r15);
sample->sp = reinterpret_cast<Address>(mcontext.mc_r13); state.sp = reinterpret_cast<Address>(mcontext.mc_r13);
sample->fp = reinterpret_cast<Address>(mcontext.mc_r11); state.fp = reinterpret_cast<Address>(mcontext.mc_r11);
#endif // V8_HOST_ARCH_* #endif // V8_HOST_ARCH_*
#elif defined(__NetBSD__) #elif defined(__NetBSD__)
#if V8_HOST_ARCH_IA32 #if V8_HOST_ARCH_IA32
sample->pc = reinterpret_cast<Address>(mcontext.__gregs[_REG_EIP]); state.pc = reinterpret_cast<Address>(mcontext.__gregs[_REG_EIP]);
sample->sp = reinterpret_cast<Address>(mcontext.__gregs[_REG_ESP]); state.sp = reinterpret_cast<Address>(mcontext.__gregs[_REG_ESP]);
sample->fp = reinterpret_cast<Address>(mcontext.__gregs[_REG_EBP]); state.fp = reinterpret_cast<Address>(mcontext.__gregs[_REG_EBP]);
#elif V8_HOST_ARCH_X64 #elif V8_HOST_ARCH_X64
sample->pc = reinterpret_cast<Address>(mcontext.__gregs[_REG_RIP]); state.pc = reinterpret_cast<Address>(mcontext.__gregs[_REG_RIP]);
sample->sp = reinterpret_cast<Address>(mcontext.__gregs[_REG_RSP]); state.sp = reinterpret_cast<Address>(mcontext.__gregs[_REG_RSP]);
sample->fp = reinterpret_cast<Address>(mcontext.__gregs[_REG_RBP]); state.fp = reinterpret_cast<Address>(mcontext.__gregs[_REG_RBP]);
#endif // V8_HOST_ARCH_* #endif // V8_HOST_ARCH_*
#elif defined(__OpenBSD__) #elif defined(__OpenBSD__)
USE(mcontext); USE(mcontext);
#if V8_HOST_ARCH_IA32 #if V8_HOST_ARCH_IA32
sample->pc = reinterpret_cast<Address>(ucontext->sc_eip); state.pc = reinterpret_cast<Address>(ucontext->sc_eip);
sample->sp = reinterpret_cast<Address>(ucontext->sc_esp); state.sp = reinterpret_cast<Address>(ucontext->sc_esp);
sample->fp = reinterpret_cast<Address>(ucontext->sc_ebp); state.fp = reinterpret_cast<Address>(ucontext->sc_ebp);
#elif V8_HOST_ARCH_X64 #elif V8_HOST_ARCH_X64
sample->pc = reinterpret_cast<Address>(ucontext->sc_rip); state.pc = reinterpret_cast<Address>(ucontext->sc_rip);
sample->sp = reinterpret_cast<Address>(ucontext->sc_rsp); state.sp = reinterpret_cast<Address>(ucontext->sc_rsp);
sample->fp = reinterpret_cast<Address>(ucontext->sc_rbp); state.fp = reinterpret_cast<Address>(ucontext->sc_rbp);
#endif // V8_HOST_ARCH_* #endif // V8_HOST_ARCH_*
#elif defined(__sun) #elif defined(__sun)
sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_PC]); state.pc = reinterpret_cast<Address>(mcontext.gregs[REG_PC]);
sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_SP]); state.sp = reinterpret_cast<Address>(mcontext.gregs[REG_SP]);
sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_FP]); state.fp = reinterpret_cast<Address>(mcontext.gregs[REG_FP]);
#endif // __sun #endif // __sun
#endif // USE_SIMULATOR #endif // USE_SIMULATOR
sampler->SampleStack(state);
sampler->SampleStack(sample);
sampler->Tick(sample);
#endif // __native_client__ #endif // __native_client__
} }
...@@ -509,9 +498,10 @@ class SamplerThread : public Thread { ...@@ -509,9 +498,10 @@ class SamplerThread : public Thread {
thread_act_t profiled_thread = sampler->platform_data()->profiled_thread(); thread_act_t profiled_thread = sampler->platform_data()->profiled_thread();
Isolate* isolate = sampler->isolate(); Isolate* isolate = sampler->isolate();
SampleHelper helper; #if defined(USE_SIMULATOR)
TickSample* sample = helper.Init(sampler, isolate); SimulatorHelper helper;
if (sample == NULL) return; if (!helper.Init(sampler, isolate)) return;
#endif
if (KERN_SUCCESS != thread_suspend(profiled_thread)) return; if (KERN_SUCCESS != thread_suspend(profiled_thread)) return;
...@@ -541,17 +531,16 @@ class SamplerThread : public Thread { ...@@ -541,17 +531,16 @@ class SamplerThread : public Thread {
flavor, flavor,
reinterpret_cast<natural_t*>(&state), reinterpret_cast<natural_t*>(&state),
&count) == KERN_SUCCESS) { &count) == KERN_SUCCESS) {
sample->state = isolate->current_vm_state(); RegisterState state;
#if defined(USE_SIMULATOR) #if defined(USE_SIMULATOR)
helper.FillRegisters(sample); helper.FillRegisters(&state);
#else #else
sample->pc = reinterpret_cast<Address>(state.REGISTER_FIELD(ip)); state.pc = reinterpret_cast<Address>(state.REGISTER_FIELD(ip));
sample->sp = reinterpret_cast<Address>(state.REGISTER_FIELD(sp)); state.sp = reinterpret_cast<Address>(state.REGISTER_FIELD(sp));
sample->fp = reinterpret_cast<Address>(state.REGISTER_FIELD(bp)); state.fp = reinterpret_cast<Address>(state.REGISTER_FIELD(bp));
#endif // USE_SIMULATOR #endif // USE_SIMULATOR
#undef REGISTER_FIELD #undef REGISTER_FIELD
sampler->SampleStack(sample); sampler->SampleStack(state);
sampler->Tick(sample);
} }
thread_resume(profiled_thread); thread_resume(profiled_thread);
} }
...@@ -563,34 +552,34 @@ class SamplerThread : public Thread { ...@@ -563,34 +552,34 @@ class SamplerThread : public Thread {
if (profiled_thread == NULL) return; if (profiled_thread == NULL) return;
Isolate* isolate = sampler->isolate(); Isolate* isolate = sampler->isolate();
SampleHelper helper; #if defined(USE_SIMULATOR)
TickSample* sample = helper.Init(sampler, isolate); SimulatorHelper helper;
if (sample == NULL) return; if (!helper.Init(sampler, isolate)) return;
#endif
const DWORD kSuspendFailed = static_cast<DWORD>(-1); const DWORD kSuspendFailed = static_cast<DWORD>(-1);
if (SuspendThread(profiled_thread) == kSuspendFailed) return; if (SuspendThread(profiled_thread) == kSuspendFailed) return;
sample->state = isolate->current_vm_state();
// Context used for sampling the register state of the profiled thread. // Context used for sampling the register state of the profiled thread.
CONTEXT context; CONTEXT context;
memset(&context, 0, sizeof(context)); memset(&context, 0, sizeof(context));
context.ContextFlags = CONTEXT_FULL; context.ContextFlags = CONTEXT_FULL;
if (GetThreadContext(profiled_thread, &context) != 0) { if (GetThreadContext(profiled_thread, &context) != 0) {
RegisterState state;
#if defined(USE_SIMULATOR) #if defined(USE_SIMULATOR)
helper.FillRegisters(sample); helper.FillRegisters(&state);
#else #else
#if V8_HOST_ARCH_X64 #if V8_HOST_ARCH_X64
sample->pc = reinterpret_cast<Address>(context.Rip); state.pc = reinterpret_cast<Address>(context.Rip);
sample->sp = reinterpret_cast<Address>(context.Rsp); state.sp = reinterpret_cast<Address>(context.Rsp);
sample->fp = reinterpret_cast<Address>(context.Rbp); state.fp = reinterpret_cast<Address>(context.Rbp);
#else #else
sample->pc = reinterpret_cast<Address>(context.Eip); state.pc = reinterpret_cast<Address>(context.Eip);
sample->sp = reinterpret_cast<Address>(context.Esp); state.sp = reinterpret_cast<Address>(context.Esp);
sample->fp = reinterpret_cast<Address>(context.Ebp); state.fp = reinterpret_cast<Address>(context.Ebp);
#endif #endif
#endif // USE_SIMULATOR #endif // USE_SIMULATOR
sampler->SampleStack(sample); sampler->SampleStack(state);
sampler->Tick(sample);
} }
ResumeThread(profiled_thread); ResumeThread(profiled_thread);
} }
...@@ -616,8 +605,11 @@ SamplerThread* SamplerThread::instance_ = NULL; ...@@ -616,8 +605,11 @@ SamplerThread* SamplerThread::instance_ = NULL;
// //
// StackTracer implementation // StackTracer implementation
// //
DISABLE_ASAN void TickSample::Trace(Isolate* isolate) { DISABLE_ASAN void TickSample::Init(Isolate* isolate,
const RegisterState& regs) {
ASSERT(isolate->IsInitialized()); ASSERT(isolate->IsInitialized());
pc = regs.pc;
state = isolate->current_vm_state();
// Avoid collecting traces while doing GC. // Avoid collecting traces while doing GC.
if (state == GC) return; if (state == GC) return;
...@@ -636,11 +628,11 @@ DISABLE_ASAN void TickSample::Trace(Isolate* isolate) { ...@@ -636,11 +628,11 @@ DISABLE_ASAN void TickSample::Trace(Isolate* isolate) {
} else { } else {
// Sample potential return address value for frameless invocation of // Sample potential return address value for frameless invocation of
// stubs (we'll figure out later, if this value makes sense). // 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; 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(); top_frame_type = it.top_frame_type();
int i = 0; int i = 0;
while (!it.done() && i < TickSample::kMaxFramesCount) { while (!it.done() && i < TickSample::kMaxFramesCount) {
...@@ -689,9 +681,13 @@ void Sampler::Stop() { ...@@ -689,9 +681,13 @@ void Sampler::Stop() {
SetActive(false); SetActive(false);
} }
void Sampler::SampleStack(TickSample* sample) { void Sampler::SampleStack(const RegisterState& state) {
sample->Trace(isolate_); 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; if (++samples_taken_ < 0) samples_taken_ = 0;
Tick(sample);
} }
} } // namespace v8::internal } } // namespace v8::internal
...@@ -44,22 +44,25 @@ class Isolate; ...@@ -44,22 +44,25 @@ class Isolate;
// (if used for profiling) the program counter and stack pointer for // (if used for profiling) the program counter and stack pointer for
// the thread that created it. // the thread that created it.
struct RegisterState {
RegisterState() : pc(NULL), sp(NULL), fp(NULL) {}
Address pc; // Instruction pointer.
Address sp; // Stack pointer.
Address fp; // Frame pointer.
};
// TickSample captures the information collected for each sample. // TickSample captures the information collected for each sample.
struct TickSample { struct TickSample {
TickSample() TickSample()
: state(OTHER), : state(OTHER),
pc(NULL), pc(NULL),
sp(NULL),
fp(NULL),
external_callback(NULL), external_callback(NULL),
frames_count(0), frames_count(0),
has_external_callback(false), has_external_callback(false),
top_frame_type(StackFrame::NONE) {} top_frame_type(StackFrame::NONE) {}
void Trace(Isolate* isolate); void Init(Isolate* isolate, const RegisterState& state);
StateTag state; // The state of the VM. StateTag state; // The state of the VM.
Address pc; // Instruction pointer. Address pc; // Instruction pointer.
Address sp; // Stack pointer.
Address fp; // Frame pointer.
union { union {
Address tos; // Top stack value (*sp). Address tos; // Top stack value (*sp).
Address external_callback; Address external_callback;
...@@ -85,11 +88,7 @@ class Sampler { ...@@ -85,11 +88,7 @@ class Sampler {
int interval() const { return interval_; } int interval() const { return interval_; }
// Performs stack sampling. // Performs stack sampling.
void SampleStack(TickSample* sample); void SampleStack(const RegisterState& regs);
// This method is called for each sampling period with the current
// program counter.
virtual void Tick(TickSample* sample) = 0;
// Start and stop sampler. // Start and stop sampler.
void Start(); void Start();
...@@ -110,6 +109,11 @@ class Sampler { ...@@ -110,6 +109,11 @@ class Sampler {
class PlatformData; class PlatformData;
PlatformData* platform_data() const { return data_; } PlatformData* platform_data() const { return data_; }
protected:
// This method is called for each sampling period with the current
// program counter.
virtual void Tick(TickSample* sample) = 0;
private: private:
void SetActive(bool value) { NoBarrier_Store(&active_, value); } void SetActive(bool value) { NoBarrier_Store(&active_, value); }
......
...@@ -52,6 +52,7 @@ using v8::internal::Address; ...@@ -52,6 +52,7 @@ using v8::internal::Address;
using v8::internal::Handle; using v8::internal::Handle;
using v8::internal::Isolate; using v8::internal::Isolate;
using v8::internal::JSFunction; using v8::internal::JSFunction;
using v8::internal::RegisterState;
using v8::internal::TickSample; using v8::internal::TickSample;
...@@ -66,11 +67,12 @@ static void InitTraceEnv(TickSample* sample) { ...@@ -66,11 +67,12 @@ static void InitTraceEnv(TickSample* sample) {
static void DoTrace(Address fp) { static void DoTrace(Address fp) {
trace_env.sample->fp = fp; RegisterState regs;
regs.fp = fp;
// sp is only used to define stack high bound // sp is only used to define stack high bound
trace_env.sample->sp = regs.sp =
reinterpret_cast<Address>(trace_env.sample) - 10240; reinterpret_cast<Address>(trace_env.sample) - 10240;
trace_env.sample->Trace(Isolate::Current()); trace_env.sample->Init(Isolate::Current(), regs);
} }
......
...@@ -5,7 +5,7 @@ profiler,"begin",1 ...@@ -5,7 +5,7 @@ profiler,"begin",1
code-creation,Stub,0,0x424260,348,"CompareStub_GE" code-creation,Stub,0,0x424260,348,"CompareStub_GE"
code-creation,LazyCompile,0,0x2a8100,18535,"DrawQube 3d-cube.js:188",0xf43abcac, code-creation,LazyCompile,0,0x2a8100,18535,"DrawQube 3d-cube.js:188",0xf43abcac,
code-creation,LazyCompile,0,0x480100,3908,"DrawLine 3d-cube.js:17",0xf43abc50, code-creation,LazyCompile,0,0x480100,3908,"DrawLine 3d-cube.js:17",0xf43abc50,
tick,0x424284,0xbfffeea0,0,0,0x480600,0,0x2aaaa5 tick,0x424284,0,0,0x480600,0,0x2aaaa5
tick,0x42429f,0xbfffed88,0,0,0x480600,0,0x2aacb4 tick,0x42429f,0,0,0x480600,0,0x2aacb4
tick,0x48063d,0xbfffec7c,0,0,0x2d0f7c,0,0x2aaec6 tick,0x48063d,0,0,0x2d0f7c,0,0x2aaec6
profiler,"end" profiler,"end"
...@@ -9,17 +9,17 @@ code-creation,LazyCompile,0,0xf541d120,145,"exp native math.js:41" ...@@ -9,17 +9,17 @@ code-creation,LazyCompile,0,0xf541d120,145,"exp native math.js:41"
function-creation,0xf441d280,0xf541d120 function-creation,0xf441d280,0xf541d120
code-creation,LoadIC,0,0xf541d280,117,"j" code-creation,LoadIC,0,0xf541d280,117,"j"
code-creation,LoadIC,0,0xf541d360,63,"i" code-creation,LoadIC,0,0xf541d360,63,"i"
tick,0x80f82d1,0xffdfe880,0,0,0,0,0xf541ce5c tick,0x80f82d1,0,0,0,0,0xf541ce5c
tick,0x80f89a1,0xffdfecf0,0,0,0,0,0xf541ce5c tick,0x80f89a1,0,0,0,0,0xf541ce5c
tick,0x8123b5c,0xffdff1a0,0,0,0,0,0xf541d1a1,0xf541ceea tick,0x8123b5c,0,0,0,0,0xf541d1a1,0xf541ceea
tick,0x8123b65,0xffdff1a0,0,0,0,0,0xf541d1a1,0xf541ceea tick,0x8123b65,0,0,0,0,0xf541d1a1,0xf541ceea
tick,0xf541d2be,0xffdff1e4,0,0,0,0 tick,0xf541d2be,0,0,0,0
tick,0xf541d320,0xffdff1dc,0,0,0,0 tick,0xf541d320,0,0,0,0
tick,0xf541d384,0xffdff1d8,0,0,0,0 tick,0xf541d384,0,0,0,0
tick,0xf7db94da,0xffdff0ec,0,0,0,0,0xf541d1a1,0xf541ceea tick,0xf7db94da,0,0,0,0,0xf541d1a1,0xf541ceea
tick,0xf7db951c,0xffdff0f0,0,0,0,0,0xf541d1a1,0xf541ceea tick,0xf7db951c,0,0,0,0,0xf541d1a1,0xf541ceea
tick,0xf7dbc508,0xffdff14c,0,0,0,0,0xf541d1a1,0xf541ceea tick,0xf7dbc508,0,0,0,0,0xf541d1a1,0xf541ceea
tick,0xf7dbff21,0xffdff198,0,0,0,0,0xf541d1a1,0xf541ceea tick,0xf7dbff21,0,0,0,0,0xf541d1a1,0xf541ceea
tick,0xf7edec90,0xffdff0ec,0,0,0,0,0xf541d1a1,0xf541ceea tick,0xf7edec90,0,0,0,0,0xf541d1a1,0xf541ceea
tick,0xffffe402,0xffdff488,0,0,0,0 tick,0xffffe402,0,0,0,0
profiler,"end" profiler,"end"
...@@ -169,7 +169,7 @@ function TickProcessor( ...@@ -169,7 +169,7 @@ function TickProcessor(
'snapshot-pos': { parsers: [parseInt, parseInt], 'snapshot-pos': { parsers: [parseInt, parseInt],
processor: this.processSnapshotPosition }, processor: this.processSnapshotPosition },
'tick': { 'tick': {
parsers: [parseInt, parseInt, parseInt, parseInt, parsers: [parseInt, parseInt, parseInt,
parseInt, parseInt, 'var-args'], parseInt, parseInt, 'var-args'],
processor: this.processTick }, processor: this.processTick },
'heap-sample-begin': { parsers: [null, null, parseInt], 'heap-sample-begin': { parsers: [null, null, parseInt],
...@@ -365,7 +365,6 @@ TickProcessor.prototype.includeTick = function(vmState) { ...@@ -365,7 +365,6 @@ TickProcessor.prototype.includeTick = function(vmState) {
}; };
TickProcessor.prototype.processTick = function(pc, TickProcessor.prototype.processTick = function(pc,
sp,
ns_since_start, ns_since_start,
is_external_callback, is_external_callback,
tos_or_external_callback, tos_or_external_callback,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment