| Index: src/frames.cc
|
| diff --git a/src/frames.cc b/src/frames.cc
|
| index 4e499455f7eabb15295ba0c5f4e7e0bc19f5c900..275f6f617b10722df12c88047f4fb9a3145d9fda 100644
|
| --- a/src/frames.cc
|
| +++ b/src/frames.cc
|
| @@ -235,16 +235,7 @@ SafeStackFrameIterator::SafeStackFrameIterator(
|
| if (SingletonFor(type) == NULL) return;
|
| frame_ = SingletonFor(type, &state);
|
| DCHECK(frame_);
|
| -
|
| 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();
|
| - }
|
| }
|
|
|
|
|
| @@ -329,22 +320,30 @@ bool SafeStackFrameIterator::IsValidExitFrame(Address fp) const {
|
| void SafeStackFrameIterator::Advance() {
|
| while (true) {
|
| AdvanceOneFrame();
|
| - if (done()) return;
|
| - if (frame_->is_java_script()) return;
|
| - if (frame_->is_exit() && external_callback_scope_) {
|
| + if (done()) break;
|
| + ExternalCallbackScope* last_callback_scope = NULL;
|
| + while (external_callback_scope_ != NULL &&
|
| + external_callback_scope_->scope_address() < frame_->fp()) {
|
| + // As long as the setup of a frame is not atomic, we may happen to be
|
| + // in an interval where an ExternalCallbackScope is already created,
|
| + // but the frame is not yet entered. So we are actually observing
|
| + // the previous frame.
|
| + // Skip all the ExternalCallbackScope's that are below the current fp.
|
| + last_callback_scope = external_callback_scope_;
|
| + external_callback_scope_ = external_callback_scope_->previous();
|
| + }
|
| + if (frame_->is_java_script()) break;
|
| + if (frame_->is_exit()) {
|
| // 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()) {
|
| + if (last_callback_scope) {
|
| frame_->state_.pc_address =
|
| - external_callback_scope_->callback_entrypoint_address();
|
| - external_callback_scope_ = external_callback_scope_->previous();
|
| - DCHECK(external_callback_scope_ == NULL ||
|
| - external_callback_scope_->scope_address() > frame_->fp());
|
| - return;
|
| + last_callback_scope->callback_entrypoint_address();
|
| }
|
| + break;
|
| }
|
| }
|
| }
|
|
|