Chromium Code Reviews| Index: src/frames.cc |
| diff --git a/src/frames.cc b/src/frames.cc |
| index 890e77ad63608f7bb178bfd4693146858a9533b2..ae0778936cbaec1ef0034a275f82a9ef22fae497 100644 |
| --- a/src/frames.cc |
| +++ b/src/frames.cc |
| @@ -36,6 +36,7 @@ |
| #include "safepoint-table.h" |
| #include "scopeinfo.h" |
| #include "string-stream.h" |
| +#include "vm-state-inl.h" |
| #include "allocation-inl.h" |
| @@ -221,7 +222,8 @@ SafeStackFrameIterator::SafeStackFrameIterator( |
| : StackFrameIteratorBase(isolate, false), |
| low_bound_(sp), |
| high_bound_(js_entry_sp), |
| - top_frame_type_(StackFrame::NONE) { |
| + top_frame_type_(StackFrame::NONE), |
| + external_callback_scope_(isolate->external_callback_scope()) { |
| StackFrame::State state; |
| StackFrame::Type type; |
| ThreadLocalTop* top = isolate->thread_local_top(); |
| @@ -256,16 +258,28 @@ SafeStackFrameIterator::SafeStackFrameIterator( |
| } |
| if (SingletonFor(type) == NULL) return; |
| frame_ = SingletonFor(type, &state); |
| + if (frame_ == NULL) return; |
| + |
| + Advance(); |
| - if (!done()) Advance(); |
| + if (frame_ != NULL && !frame_->is_exit() && |
| + external_callback_scope_ != NULL && |
| + external_callback_scope_->scope_address() < frame_->fp()) { |
| + // Skip top ExternalCallbackScope if we already advanced to a JS frame |
| + // under it. Sampler will anyways take this top external callback. |
| + external_callback_scope_ = external_callback_scope_->previous(); |
| + } |
| } |
| bool SafeStackFrameIterator::IsValidTop(ThreadLocalTop* top) const { |
| - Address fp = Isolate::c_entry_fp(top); |
| - if (!IsValidExitFrame(fp)) return false; |
| + Address c_entry_fp = Isolate::c_entry_fp(top); |
| + if (!IsValidExitFrame(c_entry_fp)) return false; |
| // There should be at least one JS_ENTRY stack handler. |
| - return Isolate::handler(top) != NULL; |
| + Address handler = Isolate::handler(top); |
| + if (handler == NULL) return false; |
| + // Check that there are no js frames on top of the native frames. |
| + return c_entry_fp < handler; |
| } |
| @@ -340,6 +354,22 @@ void SafeStackFrameIterator::Advance() { |
| AdvanceOneFrame(); |
| if (done()) return; |
| if (frame_->is_java_script()) return; |
| + if (frame_->is_exit() && external_callback_scope_) { |
| + // Some of the EXIT frames may have ExternalCallbackScope allocated on |
| + // top of them. In that case the scope corresponds to the first EXIT |
| + // frame beneath it. There may be other EXIT frames on top of the |
| + // ExternalCallbackScope, just skip them as we cannot collect any useful |
| + // information about them. |
| + if (external_callback_scope_->scope_address() < frame_->fp()) { |
| + Address* callback_address = |
| + external_callback_scope_->callback_address(); |
| + if (*callback_address != NULL) { |
| + frame_->state_.pc_address = callback_address; |
| + } |
| + external_callback_scope_ = external_callback_scope_->previous(); |
|
Yang
2013/07/23 12:15:12
If I understood correctly, the previous external c
yurys
2013/07/23 12:28:23
That's correct. In theory one can allocate two Ext
|
| + return; |
| + } |
| + } |
| } |
| } |