bool DebugEpilogue(JSContext* cx, BaselineFrame* frame, jsbytecode* pc, bool ok) { // If Debugger::onLeaveFrame returns |true| we have to return the frame's // return value. If it returns |false|, the debugger threw an exception. // In both cases we have to pop debug scopes. ok = Debugger::onLeaveFrame(cx, frame, ok); // Unwind to the outermost scope and set pc to the end of the script, // regardless of error. ScopeIter si(cx, frame, pc); UnwindAllScopesInFrame(cx, si); JSScript* script = frame->script(); frame->setOverridePc(script->lastPC()); if (frame->isNonEvalFunctionFrame()) { MOZ_ASSERT_IF(ok, frame->hasReturnValue()); DebugScopes::onPopCall(frame, cx); } else if (frame->isStrictEvalFrame()) { MOZ_ASSERT_IF(frame->hasCallObj(), frame->scopeChain()->as<CallObject>().isForEval()); DebugScopes::onPopStrictEvalScope(frame); } if (!ok) { // Pop this frame by updating jitTop, so that the exception handling // code will start at the previous frame. JitFrameLayout* prefix = frame->framePrefix(); EnsureExitFrame(prefix); cx->runtime()->jitTop = (uint8_t*)prefix; return false; } // Clear the override pc. This is not necessary for correctness: the frame // will return immediately, but this simplifies the check we emit in debug // builds after each callVM, to ensure this flag is not set. frame->clearOverridePc(); return true; }