Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1100)

Unified Diff: src/frames.cc

Issue 50052: Support profiler stack sampling in any situation. (Closed)
Patch Set: Fixes according to comments Created 11 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/frames.h ('k') | src/frames-arm.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/frames.cc
diff --git a/src/frames.cc b/src/frames.cc
index 327079705b007414cd665ed86f996635f442abf4..763ff486eff0d804e4d98bde5d6de5832c4bfe92 100644
--- a/src/frames.cc
+++ b/src/frames.cc
@@ -66,23 +66,32 @@ class StackHandlerIterator BASE_EMBEDDED {
#define INITIALIZE_SINGLETON(type, field) field##_(this),
StackFrameIterator::StackFrameIterator()
: 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();
}
StackFrameIterator::StackFrameIterator(ThreadLocalTop* t)
: 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();
}
-StackFrameIterator::StackFrameIterator(bool reset)
+StackFrameIterator::StackFrameIterator(bool use_top, Address fp, Address sp)
: STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
- frame_(NULL), handler_(NULL), thread_(Top::GetCurrentThread()) {
- if (reset) Reset();
+ frame_(NULL), handler_(NULL),
+ 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
-void StackFrameIterator::Advance() {
+void StackFrameIterator::AdvanceWithHandler() {
ASSERT(!done());
// Compute the state of the calling frame before restoring
// callee-saved registers and unwinding handlers. This allows the
@@ -105,17 +114,45 @@ void StackFrameIterator::Advance() {
}
+void StackFrameIterator::AdvanceWithoutHandler() {
+ // A simpler version of Advance which doesn't care about handler.
+ ASSERT(!done());
+ StackFrame::State state;
+ StackFrame::Type type = frame_->GetCallerState(&state);
+ frame_ = SingletonFor(type, &state);
+}
+
+
void StackFrameIterator::Reset() {
- Address fp = Top::c_entry_fp(thread_);
StackFrame::State state;
- StackFrame::Type type = ExitFrame::GetStateForFramePointer(fp, &state);
+ StackFrame::Type type;
+ if (thread_ != NULL) {
+ type = ExitFrame::GetStateForFramePointer(Top::c_entry_fp(thread_), &state);
+ 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);
- handler_ = StackHandler::FromAddress(Top::handler(thread_));
}
StackFrame* StackFrameIterator::SingletonFor(StackFrame::Type type,
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) \
case StackFrame::type: result = &field##_; break;
@@ -125,8 +162,6 @@ StackFrame* StackFrameIterator::SingletonFor(StackFrame::Type type,
STACK_FRAME_TYPE_LIST(FRAME_TYPE_CASE)
default: break;
}
- ASSERT(result != NULL);
- result->state_ = *state;
return result;
#undef FRAME_TYPE_CASE
@@ -154,29 +189,50 @@ void StackTraceFrameIterator::Advance() {
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),
- is_working_iterator_(IsInBounds(low_bound, high_bound,
- Top::c_entry_fp(Top::GetCurrentThread()))),
- iteration_done_(!is_working_iterator_), iterator_(is_working_iterator_) {
+ is_valid_top_(
+ IsWithinBounds(low_bound, high_bound,
+ 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() {
ASSERT(is_working_iterator_);
ASSERT(!done());
- StackFrame* frame = iterator_.frame();
- iteration_done_ =
- !IsGoodStackAddress(frame->sp()) || !IsGoodStackAddress(frame->fp());
- if (!iteration_done_) {
- iterator_.Advance();
- if (!iterator_.done()) {
- // Check that we have actually moved to the previous frame in the stack
- StackFrame* prev_frame = iterator_.frame();
- iteration_done_ =
- prev_frame->sp() < frame->sp() || prev_frame->fp() < frame->fp();
- }
- }
+ StackFrame* last_frame = iterator_.frame();
+ Address last_sp = last_frame->sp(), last_fp = last_frame->fp();
+ // Before advancing to the next stack frame, perform pointer validity tests
+ iteration_done_ = !IsValidFrame(last_frame) || !IsValidCaller(last_frame);
+ if (iteration_done_) return;
+
+ iterator_.Advance();
+ if (iterator_.done()) return;
+ // Check that we have actually moved to the previous frame in the stack
+ StackFrame* prev_frame = iterator_.frame();
+ iteration_done_ = prev_frame->sp() < last_sp || prev_frame->fp() < last_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() {
#ifdef ENABLE_LOGGING_AND_PROFILING
SafeStackTraceFrameIterator::SafeStackTraceFrameIterator(
- Address low_bound, Address high_bound) :
- SafeJavaScriptFrameIterator(low_bound, high_bound) {
- if (!done() && !frame()->function()->IsJSFunction()) Advance();
+ Address fp, Address sp, Address low_bound, Address high_bound) :
+ SafeJavaScriptFrameIterator(fp, sp, low_bound, high_bound) {
+ if (!done() && !frame()->is_at_function()) Advance();
}
@@ -203,7 +259,7 @@ void SafeStackTraceFrameIterator::Advance() {
while (true) {
SafeJavaScriptFrameIterator::Advance();
if (done()) return;
- if (frame()->function()->IsJSFunction()) return;
+ if (frame()->is_at_function()) return;
}
}
#endif
@@ -279,11 +335,22 @@ void StackFrame::Uncook() {
}
+StackFrame::Type StackFrame::GetCallerState(State* state) const {
+ ComputeCallerState(state);
+ return ComputeType(state);
+}
+
+
Code* EntryFrame::code() const {
return Heap::js_entry_code();
}
+void EntryFrame::ComputeCallerState(State* state) const {
+ GetCallerState(state);
+}
+
+
StackFrame::Type EntryFrame::GetCallerState(State* state) const {
const int offset = EntryFrameConstants::kCallerFPOffset;
Address fp = Memory::Address_at(this->fp() + offset);
@@ -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.
state->sp = pp();
state->fp = Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset);
state->pc_address
= reinterpret_cast<Address*>(fp() + ExitFrameConstants::kCallerPCOffset);
- return ComputeType(state);
}
@@ -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->fp = caller_fp();
state->pc_address = reinterpret_cast<Address*>(ComputePCAddress(fp()));
- return ComputeType(state);
}
« no previous file with comments | « src/frames.h ('k') | src/frames-arm.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698