diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index a51dd50e6dc1..45151c1d75c2 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -3017,7 +3017,10 @@ EmitYieldOp(ExclusiveContext *cx, BytecodeEmitter *bce, JSOp op) SET_UINT24(bce->code(off), yieldIndex); - return bce->yieldOffsetList.append(bce->offset()); + if (!bce->yieldOffsetList.append(bce->offset())) + return false; + + return Emit1(cx, bce, JSOP_DEBUGAFTERYIELD) >= 0; } bool diff --git a/js/src/jit/BaselineCompiler.cpp b/js/src/jit/BaselineCompiler.cpp index a15353d11feb..61d8bda57091 100644 --- a/js/src/jit/BaselineCompiler.cpp +++ b/js/src/jit/BaselineCompiler.cpp @@ -3405,6 +3405,22 @@ BaselineCompiler::emit_JSOP_YIELD() return emitReturn(); } +typedef bool (*DebugAfterYieldFn)(JSContext *, BaselineFrame *); +static const VMFunction DebugAfterYieldInfo = FunctionInfo(jit::DebugAfterYield); + +bool +BaselineCompiler::emit_JSOP_DEBUGAFTERYIELD() +{ + if (!compileDebugInstrumentation_) + return true; + + frame.assertSyncedStack(); + masm.loadBaselineFramePtr(BaselineFrameReg, R0.scratchReg()); + prepareVMCall(); + pushArg(R0.scratchReg()); + return callVM(DebugAfterYieldInfo); +} + typedef bool (*FinalSuspendFn)(JSContext *, HandleObject, BaselineFrame *, jsbytecode *); static const VMFunction FinalSuspendInfo = FunctionInfo(jit::FinalSuspend); diff --git a/js/src/jit/BaselineCompiler.h b/js/src/jit/BaselineCompiler.h index 47b481f63ac2..d1c85bdecb85 100644 --- a/js/src/jit/BaselineCompiler.h +++ b/js/src/jit/BaselineCompiler.h @@ -176,6 +176,7 @@ namespace jit { _(JSOP_GENERATOR) \ _(JSOP_INITIALYIELD) \ _(JSOP_YIELD) \ + _(JSOP_DEBUGAFTERYIELD) \ _(JSOP_FINALYIELDRVAL) \ _(JSOP_RESUME) \ _(JSOP_CALLEE) \ diff --git a/js/src/jit/VMFunctions.cpp b/js/src/jit/VMFunctions.cpp index 949fca0653c4..1d8764fd55e5 100644 --- a/js/src/jit/VMFunctions.cpp +++ b/js/src/jit/VMFunctions.cpp @@ -907,6 +907,16 @@ InterpretResume(JSContext *cx, HandleObject obj, HandleValue val, HandleProperty return true; } +bool +DebugAfterYield(JSContext *cx, BaselineFrame *frame) +{ + // The BaselineFrame has just been constructed by JSOP_RESUME in the + // caller. We need to set its debuggee flag as necessary. + if (frame->script()->isDebuggee()) + frame->setIsDebuggee(); + return true; +} + bool StrictEvalPrologue(JSContext *cx, BaselineFrame *frame) { diff --git a/js/src/jit/VMFunctions.h b/js/src/jit/VMFunctions.h index 47ee0ec31efc..84854bb699aa 100644 --- a/js/src/jit/VMFunctions.h +++ b/js/src/jit/VMFunctions.h @@ -712,6 +712,7 @@ bool NormalSuspend(JSContext *cx, HandleObject obj, BaselineFrame *frame, jsbyte bool FinalSuspend(JSContext *cx, HandleObject obj, BaselineFrame *frame, jsbytecode *pc); bool InterpretResume(JSContext *cx, HandleObject obj, HandleValue val, HandlePropertyName kind, MutableHandleValue rval); +bool DebugAfterYield(JSContext *cx, BaselineFrame *frame); bool StrictEvalPrologue(JSContext *cx, BaselineFrame *frame); bool HeavyweightFunPrologue(JSContext *cx, BaselineFrame *frame); diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp index 134c65e2ee59..1d6e2e93ded0 100644 --- a/js/src/vm/Interpreter.cpp +++ b/js/src/vm/Interpreter.cpp @@ -1645,7 +1645,6 @@ CASE(JSOP_UNUSED190) CASE(JSOP_UNUSED191) CASE(JSOP_UNUSED192) CASE(JSOP_UNUSED196) -CASE(JSOP_UNUSED208) CASE(JSOP_UNUSED209) CASE(JSOP_UNUSED210) CASE(JSOP_UNUSED211) @@ -3413,6 +3412,14 @@ CASE(JSOP_RESUME) ADVANCE_AND_DISPATCH(0); } +CASE(JSOP_DEBUGAFTERYIELD) +{ + // No-op in the interpreter, as GeneratorObject::resume takes care of + // fixing up InterpreterFrames. + MOZ_ASSERT_IF(REGS.fp()->script()->isDebuggee(), REGS.fp()->isDebuggee()); +} +END_CASE(JSOP_DEBUGAFTERYIELD) + CASE(JSOP_FINALYIELDRVAL) { RootedObject &gen = rootObject0; diff --git a/js/src/vm/Opcodes.h b/js/src/vm/Opcodes.h index 8b15d6f35ef2..152ef56e829d 100644 --- a/js/src/vm/Opcodes.h +++ b/js/src/vm/Opcodes.h @@ -1619,7 +1619,15 @@ */ \ macro(JSOP_FORCEINTERPRETER, 207, "forceinterpreter", NULL, 1, 0, 0, JOF_BYTE) \ \ - macro(JSOP_UNUSED208, 208, "unused208", NULL, 1, 0, 0, JOF_BYTE) \ + /* + * Bytecode emitted after 'yield' statements to help the Debugger + * fix up the frame in the JITs. No-op in the interpreter. + * + * Category: Debugger + * Operands: + * Stack: => + */ \ + macro(JSOP_DEBUGAFTERYIELD, 208, "debugafteryield", NULL, 1, 0, 0, JOF_BYTE) \ macro(JSOP_UNUSED209, 209, "unused209", NULL, 1, 0, 0, JOF_BYTE) \ macro(JSOP_UNUSED210, 210, "unused210", NULL, 1, 0, 0, JOF_BYTE) \ macro(JSOP_UNUSED211, 211, "unused211", NULL, 1, 0, 0, JOF_BYTE) \ diff --git a/js/src/vm/Xdr.h b/js/src/vm/Xdr.h index 4dd275fda860..c78a8e8dbeca 100644 --- a/js/src/vm/Xdr.h +++ b/js/src/vm/Xdr.h @@ -34,7 +34,7 @@ namespace js { * Nightly) and without (all others). FIXME: Bug 1066322 - Enable ES6 symbols * in all builds. */ -static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 202; +static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 204; static_assert(XDR_BYTECODE_VERSION_SUBTRAHEND % 2 == 0, "see the comment above"); static const uint32_t XDR_BYTECODE_VERSION = uint32_t(0xb973c0de - (XDR_BYTECODE_VERSION_SUBTRAHEND