| Index: runtime/vm/exceptions.cc
|
| diff --git a/runtime/vm/exceptions.cc b/runtime/vm/exceptions.cc
|
| index 125561740b8cd7df193408cb436e26140322a9cc..a0af67e7b747319310bb60c78f65ef9436e365c4 100644
|
| --- a/runtime/vm/exceptions.cc
|
| +++ b/runtime/vm/exceptions.cc
|
| @@ -219,22 +219,57 @@ static void JumpToExceptionHandler(Thread* thread,
|
| #if !defined(TARGET_ARCH_DBC)
|
| MallocGrowableArray<PendingLazyDeopt>* pending_deopts =
|
| thread->isolate()->pending_deopts();
|
| - for (intptr_t i = pending_deopts->length() - 1; i >= 0; i--) {
|
| - if ((*pending_deopts)[i].fp() == frame_pointer) {
|
| - // Frame is scheduled for lazy deopt.
|
| -
|
| - // Deopt should now resume in the catch handler instead of after the call.
|
| - (*pending_deopts)[i].set_pc(program_counter);
|
| -
|
| - // Jump to the deopt stub instead of the catch handler.
|
| - program_counter =
|
| - StubCode::DeoptimizeLazyFromThrow_entry()->EntryPoint();
|
| - if (FLAG_trace_deoptimization) {
|
| - THR_Print("Throwing to frame scheduled for lazy deopt fp=%" Pp "\n",
|
| - frame_pointer);
|
| + if (pending_deopts->length() > 0) {
|
| + // Check if the target frame is scheduled for lazy deopt.
|
| + for (intptr_t i = 0; i < pending_deopts->length(); i++) {
|
| + if ((*pending_deopts)[i].fp() == frame_pointer) {
|
| + // Deopt should now resume in the catch handler instead of after the
|
| + // call.
|
| + (*pending_deopts)[i].set_pc(program_counter);
|
| +
|
| + // Jump to the deopt stub instead of the catch handler.
|
| + program_counter =
|
| + StubCode::DeoptimizeLazyFromThrow_entry()->EntryPoint();
|
| + if (FLAG_trace_deoptimization) {
|
| + THR_Print("Throwing to frame scheduled for lazy deopt fp=%" Pp "\n",
|
| + frame_pointer);
|
| + }
|
| + break;
|
| + }
|
| + }
|
| +
|
| + // We may be jumping over frames scheduled for lazy deopt. Remove these
|
| + // frames from the pending deopt table, but only after unmarking them so
|
| + // any stack walk that happens before the stack is unwound will still work.
|
| + {
|
| + DartFrameIterator frames(thread);
|
| + StackFrame* frame = frames.NextFrame();
|
| + while ((frame != NULL) && (frame->fp() < frame_pointer)) {
|
| + if (frame->IsMarkedForLazyDeopt()) {
|
| + frame->UnmarkForLazyDeopt();
|
| + }
|
| + frame = frames.NextFrame();
|
| + }
|
| + }
|
| +
|
| +#if defined(DEBUG)
|
| + ValidateFrames();
|
| +#endif
|
| +
|
| + for (intptr_t i = 0; i < pending_deopts->length(); i++) {
|
| + if ((*pending_deopts)[i].fp() < frame_pointer) {
|
| + if (FLAG_trace_deoptimization) {
|
| + THR_Print("Lazy deopt skipped due to throw for "
|
| + "fp=%" Pp ", pc=%" Pp "\n",
|
| + (*pending_deopts)[i].fp(), (*pending_deopts)[i].pc());
|
| + }
|
| + pending_deopts->RemoveAt(i);
|
| }
|
| - break;
|
| }
|
| +
|
| +#if defined(DEBUG)
|
| + ValidateFrames();
|
| +#endif
|
| }
|
| #endif // !DBC
|
|
|
|
|