From d8fe3007eafb522cda67cc59c6e7421910094b8a Mon Sep 17 00:00:00 2001 From: "Nicolas B. Pierron" Date: Tue, 11 Dec 2012 20:34:15 -0800 Subject: [PATCH] Bug 800862 - Unwind bailouts exception with the interpreter. r=dvander --- js/src/ion/Bailouts.cpp | 14 +++++++++----- js/src/jsinterp.cpp | 7 +++++++ js/src/jsinterp.h | 3 ++- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/js/src/ion/Bailouts.cpp b/js/src/ion/Bailouts.cpp index abf042261be..c289aa1305e 100644 --- a/js/src/ion/Bailouts.cpp +++ b/js/src/ion/Bailouts.cpp @@ -596,9 +596,10 @@ ion::ThunkToInterpreter(Value *vp) JSContext *cx = GetIonContext()->cx; IonActivation *activation = cx->runtime->ionActivation; BailoutClosure *br = activation->takeBailout(); + InterpMode resumeMode = JSINTERP_BAILOUT; if (!EnsureHasScopeObjects(cx, cx->fp())) - return Interpret_Error; + resumeMode = JSINTERP_RETHROW; // By default we set the forbidOsr flag on the ion script, but if a GC // happens just after we re-enter the interpreter, the ion script get @@ -631,8 +632,10 @@ ion::ThunkToInterpreter(Value *vp) // object yet. JS_ASSERT(!fp->hasArgsObj()); ArgumentsObject *argsobj = ArgumentsObject::createExpected(cx, fp); - if (!argsobj) - return Interpret_Error; + if (!argsobj) { + resumeMode = JSINTERP_RETHROW; + break; + } InternalBindingsHandle bindings(script, &script->bindings); const unsigned var = Bindings::argumentsVarIndex(cx, bindings); // The arguments is a local binding and needsArgsObj does not @@ -653,10 +656,11 @@ ion::ThunkToInterpreter(Value *vp) // original Interpret activation. vp->setMagic(JS_ION_BAILOUT); js_delete(br); - return Interpret_Ok; + return resumeMode == JSINTERP_RETHROW ? Interpret_Error : Interpret_Ok; } - InterpretStatus status = Interpret(cx, br->entryfp(), JSINTERP_BAILOUT); + InterpretStatus status = Interpret(cx, br->entryfp(), resumeMode); + JS_ASSERT_IF(resumeMode == JSINTERP_RETHROW, status == Interpret_Error); if (status == Interpret_OSR) { // The interpreter currently does not ask to perform inline OSR, so diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index 51f7c9177ac..636fc256e76 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -1228,6 +1228,13 @@ js::Interpret(JSContext *cx, StackFrame *entryFrame, InterpMode interpMode) if (interpMode == JSINTERP_REJOIN) interpMode = JSINTERP_NORMAL; + /* + * The RETHROW mode acts like a bailout mode, except that it resume an + * exception instead of resuming the script. + */ + if (interpMode == JSINTERP_RETHROW) + goto error; + /* * It is important that "op" be initialized before calling DO_OP because * it is possible for "op" to be specially assigned during the normal diff --git a/js/src/jsinterp.h b/js/src/jsinterp.h index d4f9af6ae1e..df42f6f7af3 100644 --- a/js/src/jsinterp.h +++ b/js/src/jsinterp.h @@ -172,7 +172,8 @@ enum InterpMode JSINTERP_NORMAL = 0, /* interpreter is running normally */ JSINTERP_REJOIN = 1, /* as normal, but the frame has already started */ JSINTERP_SKIP_TRAP = 2, /* as REJOIN, but skip trap at first opcode */ - JSINTERP_BAILOUT = 3 /* interpreter is running from an Ion bailout */ + JSINTERP_BAILOUT = 3, /* interpreter is running from an Ion bailout */ + JSINTERP_RETHROW = 4 /* as BAILOUT, but unwind all frames */ }; enum InterpretStatus