Support profiler stack sampling in any situation. After this change, almost...

Support profiler stack sampling in any situation. After this change, almost all profiler ticks (except GC ones) have a stack sample data associated.

Tested under Linux, OS X, and Windows.

Review URL: http://codereview.chromium.org/50052

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@1565 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent c35bacb2
...@@ -154,11 +154,9 @@ class InternalFrameConstants : public AllStatic { ...@@ -154,11 +154,9 @@ class InternalFrameConstants : public AllStatic {
}; };
inline Object* JavaScriptFrame::function() const { inline Object* JavaScriptFrame::function_slot_object() const {
const int offset = JavaScriptFrameConstants::kFunctionOffset; const int offset = JavaScriptFrameConstants::kFunctionOffset;
Object* result = Memory::Object_at(fp() + offset); return Memory::Object_at(fp() + offset);
ASSERT(result->IsJSFunction());
return result;
} }
......
...@@ -129,11 +129,9 @@ class InternalFrameConstants : public AllStatic { ...@@ -129,11 +129,9 @@ class InternalFrameConstants : public AllStatic {
}; };
inline Object* JavaScriptFrame::function() const { inline Object* JavaScriptFrame::function_slot_object() const {
const int offset = JavaScriptFrameConstants::kFunctionOffset; const int offset = JavaScriptFrameConstants::kFunctionOffset;
Object* result = Memory::Object_at(fp() + offset); return Memory::Object_at(fp() + offset);
ASSERT(result->IsJSFunction());
return result;
} }
......
...@@ -169,6 +169,20 @@ inline bool JavaScriptFrame::has_adapted_arguments() const { ...@@ -169,6 +169,20 @@ inline bool JavaScriptFrame::has_adapted_arguments() const {
} }
inline bool JavaScriptFrame::is_at_function() const {
Object* result = function_slot_object();
return Heap::Contains(reinterpret_cast<Address>(result)) &&
result->IsJSFunction();
}
inline Object* JavaScriptFrame::function() const {
Object* result = function_slot_object();
ASSERT(result->IsJSFunction());
return result;
}
template<typename Iterator> template<typename Iterator>
inline JavaScriptFrame* JavaScriptFrameIteratorTemp<Iterator>::frame() const { inline JavaScriptFrame* JavaScriptFrameIteratorTemp<Iterator>::frame() const {
// TODO(1233797): The frame hierarchy needs to change. It's // TODO(1233797): The frame hierarchy needs to change. It's
......
...@@ -66,23 +66,32 @@ class StackHandlerIterator BASE_EMBEDDED { ...@@ -66,23 +66,32 @@ class StackHandlerIterator BASE_EMBEDDED {
#define INITIALIZE_SINGLETON(type, field) field##_(this), #define INITIALIZE_SINGLETON(type, field) field##_(this),
StackFrameIterator::StackFrameIterator() StackFrameIterator::StackFrameIterator()
: STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON) : STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
frame_(NULL), handler_(NULL), thread_(Top::GetCurrentThread()) { frame_(NULL), handler_(NULL), thread_(Top::GetCurrentThread()),
fp_(NULL), sp_(NULL), advance_(&StackFrameIterator::AdvanceWithHandler) {
Reset(); Reset();
} }
StackFrameIterator::StackFrameIterator(ThreadLocalTop* t) StackFrameIterator::StackFrameIterator(ThreadLocalTop* t)
: STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON) : STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
frame_(NULL), handler_(NULL), thread_(t) { frame_(NULL), handler_(NULL), thread_(t),
fp_(NULL), sp_(NULL), advance_(&StackFrameIterator::AdvanceWithHandler) {
Reset(); Reset();
} }
StackFrameIterator::StackFrameIterator(bool reset) StackFrameIterator::StackFrameIterator(bool use_top, Address fp, Address sp)
: STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON) : STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
frame_(NULL), handler_(NULL), thread_(Top::GetCurrentThread()) { frame_(NULL), handler_(NULL),
if (reset) Reset(); thread_(use_top ? Top::GetCurrentThread() : NULL),
fp_(use_top ? NULL : fp), sp_(sp),
advance_(use_top ? &StackFrameIterator::AdvanceWithHandler :
&StackFrameIterator::AdvanceWithoutHandler) {
if (use_top || fp != NULL) {
Reset();
}
} }
#undef INITIALIZE_SINGLETON #undef INITIALIZE_SINGLETON
void StackFrameIterator::Advance() { void StackFrameIterator::AdvanceWithHandler() {
ASSERT(!done()); ASSERT(!done());
// Compute the state of the calling frame before restoring // Compute the state of the calling frame before restoring
// callee-saved registers and unwinding handlers. This allows the // callee-saved registers and unwinding handlers. This allows the
...@@ -105,17 +114,45 @@ void StackFrameIterator::Advance() { ...@@ -105,17 +114,45 @@ void StackFrameIterator::Advance() {
} }
void StackFrameIterator::Reset() { void StackFrameIterator::AdvanceWithoutHandler() {
Address fp = Top::c_entry_fp(thread_); // A simpler version of Advance which doesn't care about handler.
ASSERT(!done());
StackFrame::State state; StackFrame::State state;
StackFrame::Type type = ExitFrame::GetStateForFramePointer(fp, &state); StackFrame::Type type = frame_->GetCallerState(&state);
frame_ = SingletonFor(type, &state); frame_ = SingletonFor(type, &state);
}
void StackFrameIterator::Reset() {
StackFrame::State state;
StackFrame::Type type;
if (thread_ != NULL) {
type = ExitFrame::GetStateForFramePointer(Top::c_entry_fp(thread_), &state);
handler_ = StackHandler::FromAddress(Top::handler(thread_)); handler_ = StackHandler::FromAddress(Top::handler(thread_));
} else {
ASSERT(fp_ != NULL);
state.fp = fp_;
state.sp = sp_;
state.pc_address =
reinterpret_cast<Address*>(StandardFrame::ComputePCAddress(fp_));
type = StackFrame::ComputeType(&state);
if (SingletonFor(type) == NULL) return;
}
frame_ = SingletonFor(type, &state);
} }
StackFrame* StackFrameIterator::SingletonFor(StackFrame::Type type, StackFrame* StackFrameIterator::SingletonFor(StackFrame::Type type,
StackFrame::State* state) { StackFrame::State* state) {
if (type == StackFrame::NONE) return NULL;
StackFrame* result = SingletonFor(type);
ASSERT(result != NULL);
result->state_ = *state;
return result;
}
StackFrame* StackFrameIterator::SingletonFor(StackFrame::Type type) {
#define FRAME_TYPE_CASE(type, field) \ #define FRAME_TYPE_CASE(type, field) \
case StackFrame::type: result = &field##_; break; case StackFrame::type: result = &field##_; break;
...@@ -125,8 +162,6 @@ StackFrame* StackFrameIterator::SingletonFor(StackFrame::Type type, ...@@ -125,8 +162,6 @@ StackFrame* StackFrameIterator::SingletonFor(StackFrame::Type type,
STACK_FRAME_TYPE_LIST(FRAME_TYPE_CASE) STACK_FRAME_TYPE_LIST(FRAME_TYPE_CASE)
default: break; default: break;
} }
ASSERT(result != NULL);
result->state_ = *state;
return result; return result;
#undef FRAME_TYPE_CASE #undef FRAME_TYPE_CASE
...@@ -154,29 +189,50 @@ void StackTraceFrameIterator::Advance() { ...@@ -154,29 +189,50 @@ void StackTraceFrameIterator::Advance() {
SafeStackFrameIterator::SafeStackFrameIterator( SafeStackFrameIterator::SafeStackFrameIterator(
Address low_bound, Address high_bound) : Address fp, Address sp, Address low_bound, Address high_bound) :
low_bound_(low_bound), high_bound_(high_bound), low_bound_(low_bound), high_bound_(high_bound),
is_working_iterator_(IsInBounds(low_bound, high_bound, is_valid_top_(
Top::c_entry_fp(Top::GetCurrentThread()))), IsWithinBounds(low_bound, high_bound,
iteration_done_(!is_working_iterator_), iterator_(is_working_iterator_) { Top::c_entry_fp(Top::GetCurrentThread())) &&
Top::handler(Top::GetCurrentThread()) != NULL),
is_valid_fp_(IsWithinBounds(low_bound, high_bound, fp)),
is_working_iterator_(is_valid_top_ || is_valid_fp_),
iteration_done_(!is_working_iterator_),
iterator_(is_valid_top_, is_valid_fp_ ? fp : NULL, sp) {
} }
void SafeStackFrameIterator::Advance() { void SafeStackFrameIterator::Advance() {
ASSERT(is_working_iterator_); ASSERT(is_working_iterator_);
ASSERT(!done()); ASSERT(!done());
StackFrame* frame = iterator_.frame(); StackFrame* last_frame = iterator_.frame();
iteration_done_ = Address last_sp = last_frame->sp(), last_fp = last_frame->fp();
!IsGoodStackAddress(frame->sp()) || !IsGoodStackAddress(frame->fp()); // Before advancing to the next stack frame, perform pointer validity tests
if (!iteration_done_) { iteration_done_ = !IsValidFrame(last_frame) || !IsValidCaller(last_frame);
if (iteration_done_) return;
iterator_.Advance(); iterator_.Advance();
if (!iterator_.done()) { if (iterator_.done()) return;
// Check that we have actually moved to the previous frame in the stack // Check that we have actually moved to the previous frame in the stack
StackFrame* prev_frame = iterator_.frame(); StackFrame* prev_frame = iterator_.frame();
iteration_done_ = iteration_done_ = prev_frame->sp() < last_sp || prev_frame->fp() < last_fp;
prev_frame->sp() < frame->sp() || prev_frame->fp() < frame->fp(); }
}
}
bool SafeStackFrameIterator::IsValidFrame(StackFrame* frame) const {
return IsValidStackAddress(frame->sp()) && IsValidStackAddress(frame->fp()) &&
// JavaScriptFrame uses function shared info to advance, hence it must
// point to a valid function object.
(!frame->is_java_script() ||
reinterpret_cast<JavaScriptFrame*>(frame)->is_at_function());
}
bool SafeStackFrameIterator::IsValidCaller(StackFrame* frame) {
StackFrame::State state;
frame->ComputeCallerState(&state);
return IsValidStackAddress(state.sp) && IsValidStackAddress(state.fp) &&
iterator_.SingletonFor(frame->GetCallerState(&state)) != NULL;
} }
...@@ -193,9 +249,9 @@ void SafeStackFrameIterator::Reset() { ...@@ -193,9 +249,9 @@ void SafeStackFrameIterator::Reset() {
#ifdef ENABLE_LOGGING_AND_PROFILING #ifdef ENABLE_LOGGING_AND_PROFILING
SafeStackTraceFrameIterator::SafeStackTraceFrameIterator( SafeStackTraceFrameIterator::SafeStackTraceFrameIterator(
Address low_bound, Address high_bound) : Address fp, Address sp, Address low_bound, Address high_bound) :
SafeJavaScriptFrameIterator(low_bound, high_bound) { SafeJavaScriptFrameIterator(fp, sp, low_bound, high_bound) {
if (!done() && !frame()->function()->IsJSFunction()) Advance(); if (!done() && !frame()->is_at_function()) Advance();
} }
...@@ -203,7 +259,7 @@ void SafeStackTraceFrameIterator::Advance() { ...@@ -203,7 +259,7 @@ void SafeStackTraceFrameIterator::Advance() {
while (true) { while (true) {
SafeJavaScriptFrameIterator::Advance(); SafeJavaScriptFrameIterator::Advance();
if (done()) return; if (done()) return;
if (frame()->function()->IsJSFunction()) return; if (frame()->is_at_function()) return;
} }
} }
#endif #endif
...@@ -279,11 +335,22 @@ void StackFrame::Uncook() { ...@@ -279,11 +335,22 @@ void StackFrame::Uncook() {
} }
StackFrame::Type StackFrame::GetCallerState(State* state) const {
ComputeCallerState(state);
return ComputeType(state);
}
Code* EntryFrame::code() const { Code* EntryFrame::code() const {
return Heap::js_entry_code(); return Heap::js_entry_code();
} }
void EntryFrame::ComputeCallerState(State* state) const {
GetCallerState(state);
}
StackFrame::Type EntryFrame::GetCallerState(State* state) const { StackFrame::Type EntryFrame::GetCallerState(State* state) const {
const int offset = EntryFrameConstants::kCallerFPOffset; const int offset = EntryFrameConstants::kCallerFPOffset;
Address fp = Memory::Address_at(this->fp() + offset); Address fp = Memory::Address_at(this->fp() + offset);
...@@ -301,13 +368,12 @@ Code* ExitFrame::code() const { ...@@ -301,13 +368,12 @@ Code* ExitFrame::code() const {
} }
StackFrame::Type ExitFrame::GetCallerState(State* state) const { void ExitFrame::ComputeCallerState(State* state) const {
// Setup the caller state. // Setup the caller state.
state->sp = pp(); state->sp = pp();
state->fp = Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset); state->fp = Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset);
state->pc_address state->pc_address
= reinterpret_cast<Address*>(fp() + ExitFrameConstants::kCallerPCOffset); = reinterpret_cast<Address*>(fp() + ExitFrameConstants::kCallerPCOffset);
return ComputeType(state);
} }
...@@ -338,11 +404,10 @@ int StandardFrame::ComputeExpressionsCount() const { ...@@ -338,11 +404,10 @@ int StandardFrame::ComputeExpressionsCount() const {
} }
StackFrame::Type StandardFrame::GetCallerState(State* state) const { void StandardFrame::ComputeCallerState(State* state) const {
state->sp = caller_sp(); state->sp = caller_sp();
state->fp = caller_fp(); state->fp = caller_fp();
state->pc_address = reinterpret_cast<Address*>(ComputePCAddress(fp())); state->pc_address = reinterpret_cast<Address*>(ComputePCAddress(fp()));
return ComputeType(state);
} }
......
...@@ -190,8 +190,11 @@ class StackFrame BASE_EMBEDDED { ...@@ -190,8 +190,11 @@ class StackFrame BASE_EMBEDDED {
const StackFrameIterator* iterator_; const StackFrameIterator* iterator_;
State state_; State state_;
// Fill in the state of the calling frame.
virtual void ComputeCallerState(State* state) const = 0;
// Get the type and the state of the calling frame. // Get the type and the state of the calling frame.
virtual Type GetCallerState(State* state) const = 0; virtual Type GetCallerState(State* state) const;
// Cooking/uncooking support. // Cooking/uncooking support.
void Cook(); void Cook();
...@@ -199,6 +202,7 @@ class StackFrame BASE_EMBEDDED { ...@@ -199,6 +202,7 @@ class StackFrame BASE_EMBEDDED {
friend class StackFrameIterator; friend class StackFrameIterator;
friend class StackHandlerIterator; friend class StackHandlerIterator;
friend class SafeStackFrameIterator;
DISALLOW_IMPLICIT_CONSTRUCTORS(StackFrame); DISALLOW_IMPLICIT_CONSTRUCTORS(StackFrame);
}; };
...@@ -228,6 +232,7 @@ class EntryFrame: public StackFrame { ...@@ -228,6 +232,7 @@ class EntryFrame: public StackFrame {
virtual Address GetCallerStackPointer() const { return 0; } virtual Address GetCallerStackPointer() const { return 0; }
private: private:
virtual void ComputeCallerState(State* state) const;
virtual Type GetCallerState(State* state) const; virtual Type GetCallerState(State* state) const;
friend class StackFrameIterator; friend class StackFrameIterator;
...@@ -280,7 +285,7 @@ class ExitFrame: public StackFrame { ...@@ -280,7 +285,7 @@ class ExitFrame: public StackFrame {
virtual Address GetCallerStackPointer() const; virtual Address GetCallerStackPointer() const;
private: private:
virtual Type GetCallerState(State* state) const; virtual void ComputeCallerState(State* state) const;
friend class StackFrameIterator; friend class StackFrameIterator;
}; };
...@@ -328,7 +333,7 @@ class StandardFrame: public StackFrame { ...@@ -328,7 +333,7 @@ class StandardFrame: public StackFrame {
explicit StandardFrame(StackFrameIterator* iterator) explicit StandardFrame(StackFrameIterator* iterator)
: StackFrame(iterator) { } : StackFrame(iterator) { }
virtual Type GetCallerState(State* state) const; virtual void ComputeCallerState(State* state) const;
// Accessors. // Accessors.
inline Address caller_sp() const; inline Address caller_sp() const;
...@@ -368,6 +373,7 @@ class JavaScriptFrame: public StandardFrame { ...@@ -368,6 +373,7 @@ class JavaScriptFrame: public StandardFrame {
virtual Type type() const { return JAVA_SCRIPT; } virtual Type type() const { return JAVA_SCRIPT; }
// Accessors. // Accessors.
inline bool is_at_function() const;
inline Object* function() const; inline Object* function() const;
inline Object* receiver() const; inline Object* receiver() const;
inline void set_receiver(Object* value); inline void set_receiver(Object* value);
...@@ -413,6 +419,8 @@ class JavaScriptFrame: public StandardFrame { ...@@ -413,6 +419,8 @@ class JavaScriptFrame: public StandardFrame {
virtual Address GetCallerStackPointer() const; virtual Address GetCallerStackPointer() const;
private: private:
inline Object* function_slot_object() const;
friend class StackFrameIterator; friend class StackFrameIterator;
}; };
...@@ -509,8 +517,10 @@ class StackFrameIterator BASE_EMBEDDED { ...@@ -509,8 +517,10 @@ class StackFrameIterator BASE_EMBEDDED {
// An iterator that iterates over a given thread's stack. // An iterator that iterates over a given thread's stack.
explicit StackFrameIterator(ThreadLocalTop* thread); explicit StackFrameIterator(ThreadLocalTop* thread);
// An iterator that conditionally resets itself on init. // An iterator that can start from a given FP address.
explicit StackFrameIterator(bool reset); // If use_top, then work as usual, if fp isn't NULL, use it,
// otherwise, do nothing.
StackFrameIterator(bool use_top, Address fp, Address sp);
StackFrame* frame() const { StackFrame* frame() const {
ASSERT(!done()); ASSERT(!done());
...@@ -518,7 +528,7 @@ class StackFrameIterator BASE_EMBEDDED { ...@@ -518,7 +528,7 @@ class StackFrameIterator BASE_EMBEDDED {
} }
bool done() const { return frame_ == NULL; } bool done() const { return frame_ == NULL; }
void Advance(); void Advance() { (this->*advance_)(); }
// Go back to the first frame. // Go back to the first frame.
void Reset(); void Reset();
...@@ -530,6 +540,9 @@ class StackFrameIterator BASE_EMBEDDED { ...@@ -530,6 +540,9 @@ class StackFrameIterator BASE_EMBEDDED {
StackFrame* frame_; StackFrame* frame_;
StackHandler* handler_; StackHandler* handler_;
ThreadLocalTop* thread_; ThreadLocalTop* thread_;
Address fp_;
Address sp_;
void (StackFrameIterator::*advance_)();
StackHandler* handler() const { StackHandler* handler() const {
ASSERT(!done()); ASSERT(!done());
...@@ -538,8 +551,14 @@ class StackFrameIterator BASE_EMBEDDED { ...@@ -538,8 +551,14 @@ class StackFrameIterator BASE_EMBEDDED {
// Get the type-specific frame singleton in a given state. // Get the type-specific frame singleton in a given state.
StackFrame* SingletonFor(StackFrame::Type type, StackFrame::State* state); StackFrame* SingletonFor(StackFrame::Type type, StackFrame::State* state);
// A helper function, can return a NULL pointer.
StackFrame* SingletonFor(StackFrame::Type type);
void AdvanceWithHandler();
void AdvanceWithoutHandler();
friend class StackFrame; friend class StackFrame;
friend class SafeStackFrameIterator;
DISALLOW_COPY_AND_ASSIGN(StackFrameIterator); DISALLOW_COPY_AND_ASSIGN(StackFrameIterator);
}; };
...@@ -558,8 +577,11 @@ class JavaScriptFrameIteratorTemp BASE_EMBEDDED { ...@@ -558,8 +577,11 @@ class JavaScriptFrameIteratorTemp BASE_EMBEDDED {
// Skip frames until the frame with the given id is reached. // Skip frames until the frame with the given id is reached.
explicit JavaScriptFrameIteratorTemp(StackFrame::Id id); explicit JavaScriptFrameIteratorTemp(StackFrame::Id id);
explicit JavaScriptFrameIteratorTemp(Address low_bound, Address high_bound) : JavaScriptFrameIteratorTemp(Address fp, Address sp,
iterator_(low_bound, high_bound) { if (!done()) Advance(); } Address low_bound, Address high_bound) :
iterator_(fp, sp, low_bound, high_bound) {
if (!done()) Advance();
}
inline JavaScriptFrame* frame() const; inline JavaScriptFrame* frame() const;
...@@ -595,7 +617,8 @@ class StackTraceFrameIterator: public JavaScriptFrameIterator { ...@@ -595,7 +617,8 @@ class StackTraceFrameIterator: public JavaScriptFrameIterator {
class SafeStackFrameIterator BASE_EMBEDDED { class SafeStackFrameIterator BASE_EMBEDDED {
public: public:
explicit SafeStackFrameIterator(Address low_bound, Address high_bound); SafeStackFrameIterator(Address fp, Address sp,
Address low_bound, Address high_bound);
StackFrame* frame() const { StackFrame* frame() const {
ASSERT(is_working_iterator_); ASSERT(is_working_iterator_);
...@@ -608,16 +631,20 @@ class SafeStackFrameIterator BASE_EMBEDDED { ...@@ -608,16 +631,20 @@ class SafeStackFrameIterator BASE_EMBEDDED {
void Reset(); void Reset();
private: private:
static bool IsInBounds( static bool IsWithinBounds(
Address low_bound, Address high_bound, Address addr) { Address low_bound, Address high_bound, Address addr) {
return low_bound <= addr && addr <= high_bound; return low_bound <= addr && addr <= high_bound;
} }
bool IsGoodStackAddress(Address addr) const { bool IsValidStackAddress(Address addr) const {
return IsInBounds(low_bound_, high_bound_, addr); return IsWithinBounds(low_bound_, high_bound_, addr);
} }
bool IsValidFrame(StackFrame* frame) const;
bool IsValidCaller(StackFrame* frame);
Address low_bound_; Address low_bound_;
Address high_bound_; Address high_bound_;
const bool is_valid_top_;
const bool is_valid_fp_;
const bool is_working_iterator_; const bool is_working_iterator_;
bool iteration_done_; bool iteration_done_;
StackFrameIterator iterator_; StackFrameIterator iterator_;
...@@ -631,7 +658,8 @@ typedef JavaScriptFrameIteratorTemp<SafeStackFrameIterator> ...@@ -631,7 +658,8 @@ typedef JavaScriptFrameIteratorTemp<SafeStackFrameIterator>
class SafeStackTraceFrameIterator: public SafeJavaScriptFrameIterator { class SafeStackTraceFrameIterator: public SafeJavaScriptFrameIterator {
public: public:
explicit SafeStackTraceFrameIterator(Address low_bound, Address high_bound); explicit SafeStackTraceFrameIterator(Address fp, Address sp,
Address low_bound, Address high_bound);
void Advance(); void Advance();
}; };
#endif #endif
......
...@@ -142,10 +142,9 @@ void StackTracer::Trace(TickSample* sample) { ...@@ -142,10 +142,9 @@ void StackTracer::Trace(TickSample* sample) {
return; return;
} }
// If c_entry_fp is available, this means that we are inside a C++
// function and sample->fp value isn't reliable due to FPO.
if (Top::c_entry_fp(Top::GetCurrentThread()) != NULL) {
SafeStackTraceFrameIterator it( SafeStackTraceFrameIterator it(
reinterpret_cast<Address>(sample->fp),
reinterpret_cast<Address>(sample->sp),
reinterpret_cast<Address>(sample->sp), reinterpret_cast<Address>(sample->sp),
reinterpret_cast<Address>(low_stack_bound_)); reinterpret_cast<Address>(low_stack_bound_));
int i = 0; int i = 0;
...@@ -154,16 +153,6 @@ void StackTracer::Trace(TickSample* sample) { ...@@ -154,16 +153,6 @@ void StackTracer::Trace(TickSample* sample) {
it.Advance(); it.Advance();
} }
sample->frames_count = i; sample->frames_count = i;
} else if (sample->sp < sample->fp && sample->fp < low_stack_bound_) {
// The check assumes that stack grows from lower addresses.
sample->stack[0] = Memory::Address_at(
(Address)(sample->fp + StandardFrameConstants::kCallerPCOffset));
sample->frames_count = 1;
} else {
// FP seems to be in some intermediate state,
// better discard this sample
sample->frames_count = 0;
}
} }
...@@ -936,7 +925,7 @@ void Logger::TickEvent(TickSample* sample, bool overflow) { ...@@ -936,7 +925,7 @@ void Logger::TickEvent(TickSample* sample, bool overflow) {
msg.Append(",overflow"); msg.Append(",overflow");
} }
for (int i = 0; i < sample->frames_count; ++i) { for (int i = 0; i < sample->frames_count; ++i) {
msg.Append(",%p", sample->stack[i]); msg.Append(",0x%x", reinterpret_cast<uint32_t>(sample->stack[i]));
} }
msg.Append('\n'); msg.Append('\n');
msg.WriteToLogFile(); msg.WriteToLogFile();
......
...@@ -270,7 +270,7 @@ class Logger { ...@@ -270,7 +270,7 @@ class Logger {
}; };
// Class that extracts stack trace, used for profiling // Class that extracts stack trace, used for profiling.
class StackTracer BASE_EMBEDDED { class StackTracer BASE_EMBEDDED {
public: public:
explicit StackTracer(unsigned int low_stack_bound) explicit StackTracer(unsigned int low_stack_bound)
......
...@@ -1750,7 +1750,6 @@ class Sampler::PlatformData : public Malloced { ...@@ -1750,7 +1750,6 @@ class Sampler::PlatformData : public Malloced {
SuspendThread(profiled_thread_); SuspendThread(profiled_thread_);
context.ContextFlags = CONTEXT_FULL; context.ContextFlags = CONTEXT_FULL;
GetThreadContext(profiled_thread_, &context); GetThreadContext(profiled_thread_, &context);
ResumeThread(profiled_thread_);
// Invoke tick handler with program counter and stack pointer. // Invoke tick handler with program counter and stack pointer.
sample.pc = context.Eip; sample.pc = context.Eip;
sample.sp = context.Esp; sample.sp = context.Esp;
...@@ -1761,6 +1760,10 @@ class Sampler::PlatformData : public Malloced { ...@@ -1761,6 +1760,10 @@ class Sampler::PlatformData : public Malloced {
sample.state = Logger::state(); sample.state = Logger::state();
sampler_->Tick(&sample); sampler_->Tick(&sample);
if (sampler_->IsProfiling()) {
ResumeThread(profiled_thread_);
}
// Wait until next sampling. // Wait until next sampling.
Sleep(sampler_->interval_); Sleep(sampler_->interval_);
} }
......
This diff is collapsed.
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