Bug 1227263 part 2 - Remove this-slot from generators. r=efaust

This commit is contained in:
Jan de Mooij 2015-11-26 12:00:04 +01:00
parent 8987cbf642
commit 78e54d2bfb
7 changed files with 37 additions and 31 deletions

View File

@ -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),

View File

@ -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];
}

View File

@ -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);

View File

@ -48,7 +48,6 @@ GeneratorObject::create(JSContext* cx, AbstractFramePtr frame)
GeneratorObject* genObj = &obj->as<GeneratorObject>();
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();

View File

@ -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);
}

View File

@ -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<Value*>(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_);

View File

@ -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();