diff --git a/js/src/jit-test/tests/generators/bug1462353.js b/js/src/jit-test/tests/generators/bug1462353.js new file mode 100644 index 000000000000..9140a38339f3 --- /dev/null +++ b/js/src/jit-test/tests/generators/bug1462353.js @@ -0,0 +1,11 @@ +class Base {} +class Derived extends Base { + constructor() { + var fun = async() => { + for (var i = 0; i < 20; i++) {} // Trigger OSR. + super(); + }; + fun(); + } +} +d = new Derived(); diff --git a/js/src/jit/BaselineCompiler.cpp b/js/src/jit/BaselineCompiler.cpp index 7c2cbf77e104..aca940e578a8 100644 --- a/js/src/jit/BaselineCompiler.cpp +++ b/js/src/jit/BaselineCompiler.cpp @@ -4698,19 +4698,6 @@ BaselineCompiler::emit_JSOP_RESUME() return false; #endif - Register constructing = regs.takeAny(); - ValueOperand newTarget = regs.takeAnyValue(); - masm.loadValue(Address(genObj, GeneratorObject::offsetOfNewTargetSlot()), newTarget); - masm.move32(Imm32(0), constructing); - { - Label notConstructing; - masm.branchTestObject(Assembler::NotEqual, newTarget, ¬Constructing); - masm.pushValue(newTarget); - masm.move32(Imm32(CalleeToken_FunctionConstructing), constructing); - masm.bind(¬Constructing); - } - regs.add(newTarget); - // Push |undefined| for all formals. Register scratch2 = regs.takeAny(); Label loop, loopDone; @@ -4735,14 +4722,10 @@ BaselineCompiler::emit_JSOP_RESUME() masm.makeFrameDescriptor(scratch2, JitFrame_BaselineJS, JitFrameLayout::Size()); masm.Push(Imm32(0)); // actual argc - - // Duplicate PushCalleeToken with a variable instead. - masm.orPtr(constructing, callee); - masm.Push(callee); + masm.PushCalleeToken(callee, /* constructing = */ false); masm.Push(scratch2); // frame descriptor regs.add(callee); - regs.add(constructing); // Load the return value. ValueOperand retVal = regs.takeAnyValue(); diff --git a/js/src/vm/GeneratorObject.cpp b/js/src/vm/GeneratorObject.cpp index df14f163142c..6f41259004fb 100644 --- a/js/src/vm/GeneratorObject.cpp +++ b/js/src/vm/GeneratorObject.cpp @@ -21,6 +21,7 @@ GeneratorObject::create(JSContext* cx, AbstractFramePtr frame) { MOZ_ASSERT(frame.script()->isGenerator() || frame.script()->isAsync()); MOZ_ASSERT(frame.script()->nfixed() == 0); + MOZ_ASSERT(!frame.isConstructing()); Rooted global(cx, cx->global()); @@ -41,7 +42,6 @@ GeneratorObject::create(JSContext* cx, AbstractFramePtr frame) return nullptr; genObj->setCallee(*frame.callee()); - genObj->setNewTarget(frame.newTarget()); genObj->setEnvironmentChain(*frame.environmentChain()); if (frame.script()->needsArgsObj()) genObj->setArgsObj(frame.argsObj()); @@ -137,9 +137,8 @@ GeneratorObject::resume(JSContext* cx, InterpreterActivation& activation, MOZ_ASSERT(genObj->isSuspended()); RootedFunction callee(cx, &genObj->callee()); - RootedValue newTarget(cx, genObj->newTarget()); RootedObject envChain(cx, &genObj->environmentChain()); - if (!activation.resumeGeneratorFrame(callee, newTarget, envChain)) + if (!activation.resumeGeneratorFrame(callee, envChain)) return false; activation.regs().fp()->setResumedGenerator(); diff --git a/js/src/vm/GeneratorObject.h b/js/src/vm/GeneratorObject.h index e10c1ee7b343..41f092c87cb1 100644 --- a/js/src/vm/GeneratorObject.h +++ b/js/src/vm/GeneratorObject.h @@ -29,7 +29,6 @@ class GeneratorObject : public NativeObject ARGS_OBJ_SLOT, EXPRESSION_STACK_SLOT, YIELD_AND_AWAIT_INDEX_SLOT, - NEWTARGET_SLOT, RESERVED_SLOTS }; @@ -114,17 +113,6 @@ class GeneratorObject : public NativeObject setFixedSlot(EXPRESSION_STACK_SLOT, NullValue()); } - bool isConstructing() const { - return getFixedSlot(NEWTARGET_SLOT).isObject(); - } - const Value& newTarget() const { - return getFixedSlot(NEWTARGET_SLOT); - } - void setNewTarget(const Value& newTarget) { - setFixedSlot(NEWTARGET_SLOT, newTarget); - } - - // The yield index slot is abused for a few purposes. It's undefined if // it hasn't been set yet (before the initial yield), and null if the // generator is closed. If the generator is running, the yield index is @@ -180,7 +168,6 @@ class GeneratorObject : public NativeObject setFixedSlot(ARGS_OBJ_SLOT, NullValue()); setFixedSlot(EXPRESSION_STACK_SLOT, NullValue()); setFixedSlot(YIELD_AND_AWAIT_INDEX_SLOT, NullValue()); - setFixedSlot(NEWTARGET_SLOT, NullValue()); } bool isAfterYield(); @@ -205,9 +192,6 @@ class GeneratorObject : public NativeObject static size_t offsetOfExpressionStackSlot() { return getFixedSlotOffset(EXPRESSION_STACK_SLOT); } - static size_t offsetOfNewTargetSlot() { - return getFixedSlotOffset(NEWTARGET_SLOT); - } }; bool GeneratorThrowOrReturn(JSContext* cx, AbstractFramePtr frame, Handle obj, diff --git a/js/src/vm/Stack-inl.h b/js/src/vm/Stack-inl.h index bf2056e458c2..5647c477761a 100644 --- a/js/src/vm/Stack-inl.h +++ b/js/src/vm/Stack-inl.h @@ -318,8 +318,7 @@ InterpreterStack::pushInlineFrame(JSContext* cx, InterpreterRegs& regs, const Ca MOZ_ALWAYS_INLINE bool InterpreterStack::resumeGeneratorCallFrame(JSContext* cx, InterpreterRegs& regs, - HandleFunction callee, HandleValue newTarget, - HandleObject envChain) + HandleFunction callee, HandleObject envChain) { MOZ_ASSERT(callee->isGenerator() || callee->isAsync()); RootedScript script(cx, JSFunction::getOrCreateScript(cx, callee)); @@ -332,11 +331,12 @@ InterpreterStack::resumeGeneratorCallFrame(JSContext* cx, InterpreterRegs& regs, LifoAlloc::Mark mark = allocator_.mark(); - MaybeConstruct constructing = MaybeConstruct(newTarget.isObject()); + // (Async) generators and async functions are not constructors. + MOZ_ASSERT(!callee->isConstructor()); // Include callee, |this|, and maybe |new.target| unsigned nformal = callee->nargs(); - unsigned nvals = 2 + constructing + nformal + script->nslots(); + unsigned nvals = 2 + nformal + script->nslots(); uint8_t* buffer = allocateFrame(cx, sizeof(InterpreterFrame) + nvals * sizeof(Value)); if (!buffer) @@ -346,12 +346,10 @@ InterpreterStack::resumeGeneratorCallFrame(JSContext* cx, InterpreterRegs& regs, argv[-2] = ObjectValue(*callee); argv[-1] = UndefinedValue(); SetValueRangeToUndefined(argv, nformal); - if (constructing) - argv[nformal] = newTarget; - InterpreterFrame* fp = reinterpret_cast(argv + nformal + constructing); + InterpreterFrame* fp = reinterpret_cast(argv + nformal); fp->mark_ = mark; - fp->initCallFrame(prev, prevpc, prevsp, *callee, script, argv, 0, constructing); + fp->initCallFrame(prev, prevpc, prevsp, *callee, script, argv, 0, NO_CONSTRUCT); fp->resumeGeneratorFrame(envChain); regs.prepareToRun(*fp, script); @@ -647,6 +645,18 @@ AbstractFramePtr::unsetIsDebuggee() asRematerializedFrame()->unsetIsDebuggee(); } +inline bool +AbstractFramePtr::isConstructing() const +{ + if (isInterpreterFrame()) + return asInterpreterFrame()->isConstructing(); + if (isBaselineFrame()) + return asBaselineFrame()->isConstructing(); + if (isRematerializedFrame()) + return asRematerializedFrame()->isConstructing(); + MOZ_CRASH("Unexpected frame"); +} + inline bool AbstractFramePtr::hasArgs() const { @@ -963,11 +973,10 @@ InterpreterActivation::popInlineFrame(InterpreterFrame* frame) } inline bool -InterpreterActivation::resumeGeneratorFrame(HandleFunction callee, HandleValue newTarget, - HandleObject envChain) +InterpreterActivation::resumeGeneratorFrame(HandleFunction callee, HandleObject envChain) { InterpreterStack& stack = cx_->interpreterStack(); - if (!stack.resumeGeneratorCallFrame(cx_, regs_, callee, newTarget, envChain)) + if (!stack.resumeGeneratorCallFrame(cx_, regs_, callee, envChain)) return false; MOZ_ASSERT(regs_.fp()->script()->compartment() == compartment_); diff --git a/js/src/vm/Stack.h b/js/src/vm/Stack.h index a4c3955da1f3..e391da8ec6fd 100644 --- a/js/src/vm/Stack.h +++ b/js/src/vm/Stack.h @@ -231,6 +231,7 @@ class AbstractFramePtr inline Value calleev() const; inline Value& thisArgument() const; + inline bool isConstructing() const; inline Value newTarget() const; inline bool debuggerNeedsCheckPrimitiveReturn() const; @@ -906,8 +907,7 @@ class InterpreterStack void popInlineFrame(InterpreterRegs& regs); bool resumeGeneratorCallFrame(JSContext* cx, InterpreterRegs& regs, - HandleFunction callee, HandleValue newTarget, - HandleObject envChain); + HandleFunction callee, HandleObject envChain); inline void purge(JSRuntime* rt); @@ -1552,8 +1552,7 @@ class InterpreterActivation : public Activation MaybeConstruct constructing); inline void popInlineFrame(InterpreterFrame* frame); - inline bool resumeGeneratorFrame(HandleFunction callee, HandleValue newTarget, - HandleObject envChain); + inline bool resumeGeneratorFrame(HandleFunction callee, HandleObject envChain); InterpreterFrame* current() const { return regs_.fp();