| Index: src/frames.cc
|
| diff --git a/src/frames.cc b/src/frames.cc
|
| index 890e77ad63608f7bb178bfd4693146858a9533b2..85293f5b7f974098d1b3b403b8db4ea0e6667098 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,24 @@ 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();
|
| + ASSERT(external_callback_scope_ == NULL ||
|
| + external_callback_scope_->scope_address() > frame_->fp());
|
| + return;
|
| + }
|
| + }
|
| }
|
| }
|
|
|
|
|