Bug 676023 - Increment pc on error path out of JSOP_RETURN (r=dvander)
authorLuke Wagner <luke@mozilla.com>
Thu, 04 Aug 2011 23:15:35 -0700
changeset 73899 6181622382cfe47637cac70bff1a09e80b6cc2cb
parent 73898 ba19e1cd3f918d684ad8d71551254631c8d23870
child 73900 fff506a4889bb5df486975758acc5373dc32b86c
push id2
push userbsmedberg@mozilla.com
push dateFri, 19 Aug 2011 14:38:13 +0000
reviewersdvander
bugs676023
milestone8.0a1
Bug 676023 - Increment pc on error path out of JSOP_RETURN (r=dvander)
js/src/jsapi-tests/testDebugger.cpp
js/src/jsinterp.cpp
--- a/js/src/jsapi-tests/testDebugger.cpp
+++ b/js/src/jsapi-tests/testDebugger.cpp
@@ -98,8 +98,47 @@ BEGIN_TEST(testDebugger_getThisStrict)
          "strict.call(42);\n"
          "(42).strict();\n"
          "strict.call(undefined);\n"
          "strict.call(null);\n");
     CHECK(!anyWrapped);
     return true;
 }
 END_TEST(testDebugger_getThisStrict)
+
+bool called = false;
+
+static JSTrapStatus
+ThrowHook(JSContext *cx, JSScript *, jsbytecode *, jsval *rval, void *closure)
+{
+    called = true;
+
+    JSObject *global = JS_GetGlobalForScopeChain(cx);
+
+    char text[] = "new Error()";
+    jsval _;
+    JS_EvaluateScript(cx, global, text, strlen(text), "", 0, &_);
+
+    return JSTRAP_CONTINUE;
+}
+
+BEGIN_TEST(testDebugger_throwHook)
+{
+    uint32 newopts = JS_GetOptions(cx) | JSOPTION_METHODJIT | JSOPTION_METHODJIT_ALWAYS;
+    uint32 oldopts = JS_SetOptions(cx, newopts);
+
+    JSDebugHooks hooks = { 0 };
+    hooks.throwHook = ThrowHook;
+    JSDebugHooks *old = JS_SetContextDebugHooks(cx, &hooks);
+    EXEC("function foo() { throw 3 };\n"
+         "for (var i = 0; i < 10; ++i) { \n"
+         "  var x = <tag></tag>;\n"
+         "  try {\n"
+         "    foo(); \n"
+         "  } catch(e) {}\n"
+         "}\n");
+    CHECK(called);
+
+    JS_SetContextDebugHooks(cx, old);
+    JS_SetOptions(cx, oldopts);
+    return true;
+}
+END_TEST(testDebugger_throwHook)
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -2358,25 +2358,29 @@ BEGIN_CASE(JSOP_STOP)
         cx->stack.popInlineFrame(regs);
 
         /* Sync interpreter locals. */
         script = regs.fp()->script();
         pcCounts = script->pcCounters.get(JSRUNMODE_INTERP);
         argv = regs.fp()->maybeFormalArgs();
         atoms = FrameAtomBase(cx, regs.fp());
 
+        JS_ASSERT(*regs.pc == JSOP_TRAP || *regs.pc == JSOP_NEW || *regs.pc == JSOP_CALL ||
+                  *regs.pc == JSOP_FUNCALL || *regs.pc == JSOP_FUNAPPLY);
+
         /* Resume execution in the calling frame. */
         RESET_USE_METHODJIT();
         if (JS_LIKELY(interpReturnOK)) {
-            JS_ASSERT(js_CodeSpec[js_GetOpcode(cx, script, regs.pc)].length
-                      == JSOP_CALL_LENGTH);
             TRACE_0(LeaveFrame);
             len = JSOP_CALL_LENGTH;
             DO_NEXT_OP(len);
         }
+
+        /* Increment pc so that |sp - fp->slots == ReconstructStackDepth(pc)|. */
+        regs.pc += JSOP_CALL_LENGTH;
         goto error;
     } else {
         JS_ASSERT(regs.sp == regs.fp()->base());
     }
     interpReturnOK = true;
     goto exit;
 }