diff --git a/js/src/jit-test/tests/basic/bug657975.js b/js/src/jit-test/tests/basic/bug657975.js new file mode 100644 index 00000000000..91cf383c223 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug657975.js @@ -0,0 +1,8 @@ +// |jit-test| debug + +// bug 658491 +function f7() { + try { y = w; } catch(y) {} +} +trap(f7, 14, '') +f7() diff --git a/js/src/jsapi-tests/testDebugger.cpp b/js/src/jsapi-tests/testDebugger.cpp index 91c88849185..75f0e2c398e 100644 --- a/js/src/jsapi-tests/testDebugger.cpp +++ b/js/src/jsapi-tests/testDebugger.cpp @@ -4,6 +4,7 @@ #include "tests.h" #include "jsdbgapi.h" +#include "jscntxt.h" static int callCount[2] = {0, 0}; @@ -252,3 +253,42 @@ bool testIndirectEval(JSObject *scope, JSObject *g, const char *code, int expect return true; } END_TEST(testDebugger_newScriptHook) + +BEGIN_TEST(testDebugger_singleStepThrow) + { + CHECK(JS_SetDebugModeForCompartment(cx, cx->compartment, true)); + CHECK(JS_SetInterrupt(rt, onStep, NULL)); + + uint32 opts = JS_GetOptions(cx); + opts |= JSOPTION_METHODJIT | JSOPTION_METHODJIT_ALWAYS; + opts &= ~JSOPTION_JIT; + JS_SetOptions(cx, opts); + + CHECK(JS_DefineFunction(cx, global, "setStepMode", setStepMode, 0, 0)); + EXEC("var e;\n" + "setStepMode();\n" + "function f() { throw 0; }\n" + "try { f(); }\n" + "catch (x) { e = x; }\n"); + return true; + } + + static JSBool + setStepMode(JSContext *cx, uintN argc, jsval *vp) + { + JSStackFrame *fp = JS_GetScriptedCaller(cx, NULL); + JS_ASSERT(fp); + JSScript *script = JS_GetFrameScript(cx, fp); + JS_ASSERT(script); + if (!JS_SetSingleStepMode(cx, script, true)) + return false; + JS_SET_RVAL(cx, vp, JSVAL_VOID); + return true; + } + + static JSTrapStatus + onStep(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval, void *closure) + { + return JSTRAP_CONTINUE; + } +END_TEST(testDebugger_singleStepThrow) diff --git a/js/src/methodjit/Compiler.cpp b/js/src/methodjit/Compiler.cpp index 7f57a072e44..c7a1572a696 100644 --- a/js/src/methodjit/Compiler.cpp +++ b/js/src/methodjit/Compiler.cpp @@ -942,6 +942,17 @@ mjit::Compiler::generateMethod() SPEW_OPCODE(); JS_ASSERT(frame.stackDepth() == opinfo->stackDepth); + // If this is an exception entry point, then jsl_InternalThrow has set + // VMFrame::fp to the correct fp for the entry point. We need to copy + // that value here to FpReg so that FpReg also has the correct sp. + // Otherwise, we would simply be using a stale FpReg value. + // Additionally, we check the interrupt flag to allow interrupting + // deeply nested exception handling. + if (op == JSOP_ENTERBLOCK && analysis->getCode(PC).exceptionEntry) { + restoreFrameRegs(masm); + interruptCheckHelper(); + } + if (trap) { prepareStubCall(Uses(0)); masm.move(Imm32(trap), Registers::ArgReg1); @@ -4831,17 +4842,6 @@ mjit::Compiler::jumpAndTrace(Jump j, jsbytecode *target, Jump *slow) void mjit::Compiler::enterBlock(JSObject *obj) { - // If this is an exception entry point, then jsl_InternalThrow has set - // VMFrame::fp to the correct fp for the entry point. We need to copy - // that value here to FpReg so that FpReg also has the correct sp. - // Otherwise, we would simply be using a stale FpReg value. - // Additionally, we check the interrupt flag to allow interrupting - // deeply nested exception handling. - if (analysis->getCode(PC).exceptionEntry) { - restoreFrameRegs(masm); - interruptCheckHelper(); - } - uint32 oldFrameDepth = frame.localSlots(); /* For now, don't bother doing anything for this opcode. */