diff --git a/js/src/jit/BaselineCompiler.cpp b/js/src/jit/BaselineCompiler.cpp index f13be1a762f..816e7aab1b2 100644 --- a/js/src/jit/BaselineCompiler.cpp +++ b/js/src/jit/BaselineCompiler.cpp @@ -4028,8 +4028,8 @@ BaselineCompiler::emit_JSOP_RESUME() } masm.bind(&loopDone); - // Push |this|. - masm.pushValue(Address(genObj, GeneratorObject::offsetOfThisSlot())); + // Push |undefined| for |this|. + masm.pushValue(UndefinedValue()); // Update BaselineFrame frameSize field and create the frame descriptor. masm.computeEffectiveAddress(Address(BaselineFrameReg, BaselineFrame::FramePointerOffset), diff --git a/js/src/jit/BaselineJIT.cpp b/js/src/jit/BaselineJIT.cpp index fb8660b9cb6..695f717aa56 100644 --- a/js/src/jit/BaselineJIT.cpp +++ b/js/src/jit/BaselineJIT.cpp @@ -110,9 +110,15 @@ EnterBaseline(JSContext* cx, EnterJitData& data) EnterJitCode enter = cx->runtime()->jitRuntime()->enterBaseline(); - // Caller must construct |this| before invoking the Ion function. - MOZ_ASSERT_IF(data.constructing, data.maxArgv[0].isObject() || - data.maxArgv[0].isMagic(JS_UNINITIALIZED_LEXICAL)); + bool constructingLegacyGen = + data.constructing && CalleeTokenToFunction(data.calleeToken)->isLegacyGenerator(); + + // Caller must construct |this| before invoking the Ion function. Legacy + // generators can be called with 'new' but when we resume them, the + // this-slot and arguments are |undefined| (they are stored in the + // CallObject). + MOZ_ASSERT_IF(data.constructing && !constructingLegacyGen, + data.maxArgv[0].isObject() || data.maxArgv[0].isMagic(JS_UNINITIALIZED_LEXICAL)); data.result.setInt32(data.numActualArgs); { @@ -135,7 +141,11 @@ EnterBaseline(JSContext* cx, EnterJitData& data) // Jit callers wrap primitive constructor return, except for derived // class constructors, which are forced to do it themselves. - if (!data.result.isMagic() && data.constructing && data.result.isPrimitive()) { + if (!data.result.isMagic() && + data.constructing && + data.result.isPrimitive() && + !constructingLegacyGen) + { MOZ_ASSERT(data.maxArgv[0].isObject()); data.result = data.maxArgv[0]; } diff --git a/js/src/tests/js1_7/geniter/yield-new.js b/js/src/tests/js1_7/geniter/yield-new.js index 779a5a2167e..726da3944c9 100644 --- a/js/src/tests/js1_7/geniter/yield-new.js +++ b/js/src/tests/js1_7/geniter/yield-new.js @@ -15,4 +15,14 @@ for (var i in g) assertEq((ct < K && ct++ == i) || i == obj, true); assertEq(i.x, "puppies"); +function g2() { + for (var i=0; i<20; i++) + yield i; +} +var i = 0; +for (var x of new g2()) { + assertEq(i, x); + i++; +} + reportCompare(true,true); diff --git a/js/src/vm/GeneratorObject.cpp b/js/src/vm/GeneratorObject.cpp index ad4d547d547..a65b67b1321 100644 --- a/js/src/vm/GeneratorObject.cpp +++ b/js/src/vm/GeneratorObject.cpp @@ -48,7 +48,6 @@ GeneratorObject::create(JSContext* cx, AbstractFramePtr frame) GeneratorObject* genObj = &obj->as(); genObj->setCallee(*frame.callee()); - genObj->setThisValue(frame.thisArgument()); genObj->setNewTarget(frame.newTarget()); genObj->setScopeChain(*frame.scopeChain()); if (frame.script()->needsArgsObj()) @@ -152,10 +151,9 @@ GeneratorObject::resume(JSContext* cx, InterpreterActivation& activation, MOZ_ASSERT(genObj->isSuspended()); RootedFunction callee(cx, &genObj->callee()); - RootedValue thisv(cx, genObj->thisValue()); RootedValue newTarget(cx, genObj->newTarget()); RootedObject scopeChain(cx, &genObj->scopeChain()); - if (!activation.resumeGeneratorFrame(callee, thisv, newTarget, scopeChain)) + if (!activation.resumeGeneratorFrame(callee, newTarget, scopeChain)) return false; activation.regs().fp()->setResumedGenerator(); diff --git a/js/src/vm/GeneratorObject.h b/js/src/vm/GeneratorObject.h index 4d8e4ddbdae..e2fa13c2966 100644 --- a/js/src/vm/GeneratorObject.h +++ b/js/src/vm/GeneratorObject.h @@ -26,7 +26,6 @@ class GeneratorObject : public NativeObject enum { CALLEE_SLOT = 0, - THIS_SLOT, SCOPE_CHAIN_SLOT, ARGS_OBJ_SLOT, EXPRESSION_STACK_SLOT, @@ -81,13 +80,6 @@ class GeneratorObject : public NativeObject setFixedSlot(CALLEE_SLOT, ObjectValue(callee)); } - const Value& thisValue() const { - return getFixedSlot(THIS_SLOT); - } - void setThisValue(Value& thisv) { - setFixedSlot(THIS_SLOT, thisv); - } - JSObject& scopeChain() const { return getFixedSlot(SCOPE_CHAIN_SLOT).toObject(); } @@ -179,7 +171,6 @@ class GeneratorObject : public NativeObject } void setClosed() { setFixedSlot(CALLEE_SLOT, NullValue()); - setFixedSlot(THIS_SLOT, NullValue()); setFixedSlot(SCOPE_CHAIN_SLOT, NullValue()); setFixedSlot(ARGS_OBJ_SLOT, NullValue()); setFixedSlot(EXPRESSION_STACK_SLOT, NullValue()); @@ -190,9 +181,6 @@ class GeneratorObject : public NativeObject static size_t offsetOfCalleeSlot() { return getFixedSlotOffset(CALLEE_SLOT); } - static size_t offsetOfThisSlot() { - return getFixedSlotOffset(THIS_SLOT); - } static size_t offsetOfScopeChainSlot() { return getFixedSlotOffset(SCOPE_CHAIN_SLOT); } diff --git a/js/src/vm/Stack-inl.h b/js/src/vm/Stack-inl.h index ce9bc612308..55d94bc4cef 100644 --- a/js/src/vm/Stack-inl.h +++ b/js/src/vm/Stack-inl.h @@ -353,8 +353,8 @@ InterpreterStack::pushInlineFrame(JSContext* cx, InterpreterRegs& regs, const Ca MOZ_ALWAYS_INLINE bool InterpreterStack::resumeGeneratorCallFrame(JSContext* cx, InterpreterRegs& regs, - HandleFunction callee, HandleValue thisv, - HandleValue newTarget, HandleObject scopeChain) + HandleFunction callee, HandleValue newTarget, + HandleObject scopeChain) { MOZ_ASSERT(callee->isGenerator()); RootedScript script(cx, callee->getOrCreateScript(cx)); @@ -379,7 +379,7 @@ InterpreterStack::resumeGeneratorCallFrame(JSContext* cx, InterpreterRegs& regs, Value* argv = reinterpret_cast(buffer) + 2; argv[-2] = ObjectValue(*callee); - argv[-1] = thisv; + argv[-1] = UndefinedValue(); SetValueRangeToUndefined(argv, nformal); if (constructing) argv[nformal] = newTarget; @@ -1012,11 +1012,11 @@ InterpreterActivation::popInlineFrame(InterpreterFrame* frame) } inline bool -InterpreterActivation::resumeGeneratorFrame(HandleFunction callee, HandleValue thisv, - HandleValue newTarget, HandleObject scopeChain) +InterpreterActivation::resumeGeneratorFrame(HandleFunction callee, HandleValue newTarget, + HandleObject scopeChain) { InterpreterStack& stack = cx_->asJSContext()->runtime()->interpreterStack(); - if (!stack.resumeGeneratorCallFrame(cx_->asJSContext(), regs_, callee, thisv, newTarget, scopeChain)) + if (!stack.resumeGeneratorCallFrame(cx_->asJSContext(), regs_, callee, newTarget, scopeChain)) return false; MOZ_ASSERT(regs_.fp()->script()->compartment() == compartment_); diff --git a/js/src/vm/Stack.h b/js/src/vm/Stack.h index 28b9d6f6ad9..df8a7fe803b 100644 --- a/js/src/vm/Stack.h +++ b/js/src/vm/Stack.h @@ -1071,8 +1071,8 @@ class InterpreterStack void popInlineFrame(InterpreterRegs& regs); bool resumeGeneratorCallFrame(JSContext* cx, InterpreterRegs& regs, - HandleFunction callee, HandleValue thisv, - HandleValue newTarget, HandleObject scopeChain); + HandleFunction callee, HandleValue newTarget, + HandleObject scopeChain); inline void purge(JSRuntime* rt); @@ -1473,8 +1473,8 @@ class InterpreterActivation : public Activation InitialFrameFlags initial); inline void popInlineFrame(InterpreterFrame* frame); - inline bool resumeGeneratorFrame(HandleFunction callee, HandleValue thisv, - HandleValue newTarget, HandleObject scopeChain); + inline bool resumeGeneratorFrame(HandleFunction callee, HandleValue newTarget, + HandleObject scopeChain); InterpreterFrame* current() const { return regs_.fp();