Bug 1462353 - Remove new.target slot from generators, clean up generator code a bit. r=arai

This commit is contained in:
Jan de Mooij 2018-05-21 09:13:05 +02:00
parent 3c8f09cb23
commit 77cdcf29a8
6 changed files with 37 additions and 52 deletions

View File

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

View File

@ -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, &notConstructing);
masm.pushValue(newTarget);
masm.move32(Imm32(CalleeToken_FunctionConstructing), constructing);
masm.bind(&notConstructing);
}
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();

View File

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

View File

@ -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<GeneratorObject*> obj,

View File

@ -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<InterpreterFrame*>(argv + nformal + constructing);
InterpreterFrame* fp = reinterpret_cast<InterpreterFrame*>(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_);

View File

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