From d0348b2d1ede6489755b55c3a082f02993263341 Mon Sep 17 00:00:00 2001 From: Cameron Kaiser Date: Sat, 15 Sep 2018 10:35:22 -0700 Subject: [PATCH] #521: async/await M1185106 parts 0, 1 --- js/src/asmjs/AsmJSValidate.cpp | 2 +- js/src/frontend/BytecodeCompiler.cpp | 1 + js/src/frontend/BytecodeEmitter.cpp | 11 +++++++++- js/src/frontend/ParseNode.cpp | 3 ++- js/src/frontend/Parser.cpp | 20 ++++++++++------- js/src/frontend/Parser.h | 14 +++++++++--- js/src/frontend/SharedContext.h | 6 ++++- js/src/jit/BaselineCompiler.cpp | 9 ++++---- js/src/jit/CodeGenerator.cpp | 3 ++- js/src/jit/IonBuilder.cpp | 6 +---- js/src/jit/Lowering.cpp | 6 ++++- js/src/jit/MIR.h | 20 ++++++++--------- js/src/jit/shared/LIR-shared.h | 12 ++++++---- js/src/jsfun.h | 19 ++++++++++++++++ js/src/jsscript.cpp | 7 ++++++ js/src/jsscript.h | 33 +++++++++++++++++++++++++++- js/src/vm/Interpreter.cpp | 24 +++----------------- js/src/vm/Opcodes.h | 6 ++--- 18 files changed, 135 insertions(+), 67 deletions(-) diff --git a/js/src/asmjs/AsmJSValidate.cpp b/js/src/asmjs/AsmJSValidate.cpp index 02371b0122..aabe277123 100644 --- a/js/src/asmjs/AsmJSValidate.cpp +++ b/js/src/asmjs/AsmJSValidate.cpp @@ -6429,7 +6429,7 @@ ParseFunction(ModuleValidator& m, ParseNode** fnOut, unsigned* line, unsigned* c AsmJSParseContext* outerpc = m.parser().pc; Directives directives(outerpc); - FunctionBox* funbox = m.parser().newFunctionBox(fn, fun, outerpc, directives, NotGenerator); + FunctionBox* funbox = m.parser().newFunctionBox(fn, fun, outerpc, directives, NotGenerator, SyncFunction); if (!funbox) return false; diff --git a/js/src/frontend/BytecodeCompiler.cpp b/js/src/frontend/BytecodeCompiler.cpp index 22519caa8a..7b6ccb38cb 100644 --- a/js/src/frontend/BytecodeCompiler.cpp +++ b/js/src/frontend/BytecodeCompiler.cpp @@ -312,6 +312,7 @@ BytecodeCompiler::saveCallerFun(HandleScript evalCaller) Directives directives(/* strict = */ options.strictOption); ObjectBox* funbox = parser->newFunctionBox(/* fn = */ nullptr, fun, directives, fun->generatorKind(), + fun->asyncKind(), enclosingStaticScope); if (!funbox) return false; diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index a3e19e19d2..df0d8a7b0a 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -6401,6 +6401,13 @@ BytecodeEmitter::emitFunction(ParseNode* pn, bool needsProto) MOZ_ASSERT(pn->getOp() == JSOP_LAMBDA); pn->setOp(JSOP_FUNWITHPROTO); } + + if (pn->getOp() == JSOP_DEFFUN) { + if (!emitIndex32(JSOP_LAMBDA, index)) + return false; + return emit1(JSOP_DEFFUN); + } + return emitIndex32(pn->getOp(), index); } @@ -6441,7 +6448,9 @@ BytecodeEmitter::emitFunction(ParseNode* pn, bool needsProto) MOZ_ASSERT(pn->pn_scopecoord.isFree()); MOZ_ASSERT(pn->getOp() == JSOP_NOP); switchToPrologue(); - if (!emitIndex32(JSOP_DEFFUN, index)) + if (!emitIndex32(JSOP_LAMBDA, index)) + return false; + if (!emit1(JSOP_DEFFUN)) return false; if (!updateSourceCoordNotes(pn->pn_pos.begin)) return false; diff --git a/js/src/frontend/ParseNode.cpp b/js/src/frontend/ParseNode.cpp index bd8b262aa8..f4fcb1ee3c 100644 --- a/js/src/frontend/ParseNode.cpp +++ b/js/src/frontend/ParseNode.cpp @@ -689,7 +689,8 @@ Parser::cloneParseTree(ParseNode* opn) RootedFunction fun(context, opn->pn_funbox->function()); NULLCHECK(pn->pn_funbox = newFunctionBox(pn, fun, pc, Directives(/* strict = */ opn->pn_funbox->strict()), - opn->pn_funbox->generatorKind())); + opn->pn_funbox->generatorKind(), + opn->pn_funbox->asyncKind())); NULLCHECK(pn->pn_body = cloneParseTree(opn->pn_body)); pn->pn_scopecoord = opn->pn_scopecoord; pn->pn_dflags = opn->pn_dflags; diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index 22ff1ae4d8..ad565285bf 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -760,7 +760,8 @@ Parser::newObjectBox(JSObject* obj) template FunctionBox::FunctionBox(ExclusiveContext* cx, ObjectBox* traceListHead, JSFunction* fun, JSObject* enclosingStaticScope, ParseContext* outerpc, - Directives directives, bool extraWarnings, GeneratorKind generatorKind) + Directives directives, bool extraWarnings, GeneratorKind generatorKind, + FunctionAsyncKind asyncKind) : ObjectBox(fun, traceListHead), SharedContext(cx, directives, extraWarnings), bindings(), @@ -771,6 +772,7 @@ FunctionBox::FunctionBox(ExclusiveContext* cx, ObjectBox* traceListHead, JSFunct startColumn(0), length(0), generatorKindBits_(GeneratorKindAsBits(generatorKind)), + asyncKindBits_(AsyncKindAsBits(asyncKind)), inGenexpLambda(false), hasDestructuringArgs(false), useAsm(false), @@ -794,6 +796,7 @@ Parser::newFunctionBox(Node fn, JSFunction* fun, ParseContext* outerpc, Directives inheritedDirectives, GeneratorKind generatorKind, + FunctionAsyncKind asyncKind, JSObject* enclosingStaticScope) { MOZ_ASSERT_IF(outerpc, enclosingStaticScope == outerpc->innermostStaticScope()); @@ -809,7 +812,7 @@ Parser::newFunctionBox(Node fn, JSFunction* fun, FunctionBox* funbox = alloc.new_(context, traceListHead, fun, enclosingStaticScope, outerpc, inheritedDirectives, options().extraWarningsOption, - generatorKind); + generatorKind, asyncKind); if (!funbox) { ReportOutOfMemory(context); return nullptr; @@ -1155,7 +1158,7 @@ Parser::standaloneFunctionBody(HandleFunction fun, return null(); fn->pn_body = argsbody; - FunctionBox* funbox = newFunctionBox(fn, fun, inheritedDirectives, generatorKind, + FunctionBox* funbox = newFunctionBox(fn, fun, inheritedDirectives, generatorKind, SyncFunction, enclosingStaticScope); if (!funbox) return null(); @@ -2507,7 +2510,7 @@ Parser::checkFunctionDefinition(HandlePropertyName funName, RootedFunction fun(context, handler.nextLazyInnerFunction()); MOZ_ASSERT(!fun->isLegacyGenerator()); FunctionBox* funbox = newFunctionBox(pn, fun, pc, Directives(/* strict = */ false), - fun->generatorKind()); + fun->generatorKind(), fun->asyncKind()); if (!funbox) return false; @@ -2836,6 +2839,7 @@ Parser::finishFunctionDefinition(Node pn, FunctionBox* funbo if (pc->sc->strict()) lazy->setStrict(); lazy->setGeneratorKind(funbox->generatorKind()); + lazy->setAsyncKind(funbox->asyncKind()); if (funbox->isLikelyConstructorWrapper()) lazy->setLikelyConstructorWrapper(); if (funbox->isDerivedClassConstructor()) @@ -2859,7 +2863,7 @@ Parser::functionArgsAndBody(InHandling inHandling, ParseNode* ParseContext* outerpc = pc; // Create box for fun->object early to protect against last-ditch GC. - FunctionBox* funbox = newFunctionBox(pn, fun, pc, inheritedDirectives, generatorKind); + FunctionBox* funbox = newFunctionBox(pn, fun, pc, inheritedDirectives, generatorKind, SyncFunction); if (!funbox) return false; @@ -2959,7 +2963,7 @@ Parser::functionArgsAndBody(InHandling inHandling, Node pn, ParseContext* outerpc = pc; // Create box for fun->object early to protect against last-ditch GC. - FunctionBox* funbox = newFunctionBox(pn, fun, pc, inheritedDirectives, generatorKind); + FunctionBox* funbox = newFunctionBox(pn, fun, pc, inheritedDirectives, generatorKind, SyncFunction); if (!funbox) return false; @@ -3018,7 +3022,7 @@ Parser::standaloneLazyFunction(HandleFunction fun, bool strict RootedObject enclosing(context, fun->lazyScript()->enclosingScope()); Directives directives(/* strict = */ strict); - FunctionBox* funbox = newFunctionBox(pn, fun, directives, generatorKind, enclosing); + FunctionBox* funbox = newFunctionBox(pn, fun, directives, generatorKind, SyncFunction, enclosing); if (!funbox) return null(); funbox->length = fun->nargs() - fun->hasRest(); @@ -8632,7 +8636,7 @@ Parser::generatorComprehensionLambda(GeneratorKind comprehensionKi // Create box for fun->object early to root it. Directives directives(/* strict = */ outerpc->sc->strict()); - FunctionBox* genFunbox = newFunctionBox(genfn, fun, outerpc, directives, comprehensionKind); + FunctionBox* genFunbox = newFunctionBox(genfn, fun, outerpc, directives, comprehensionKind, SyncFunction); if (!genFunbox) return null(); diff --git a/js/src/frontend/Parser.h b/js/src/frontend/Parser.h index d62b6365a1..921fe280a0 100644 --- a/js/src/frontend/Parser.h +++ b/js/src/frontend/Parser.h @@ -126,6 +126,10 @@ struct MOZ_STACK_CLASS ParseContext : public GenericParseContext bool isLegacyGenerator() const { return generatorKind() == LegacyGenerator; } bool isStarGenerator() const { return generatorKind() == StarGenerator; } + bool isAsync() const { + return sc->isFunctionBox() && sc->asFunctionBox()->isAsync(); + } + bool isArrowFunction() const { return sc->isFunctionBox() && sc->asFunctionBox()->function()->isArrow(); } @@ -579,22 +583,26 @@ class Parser : private JS::AutoGCRooter, public StrictModeGetter ObjectBox* newObjectBox(JSObject* obj); FunctionBox* newFunctionBox(Node fn, JSFunction* fun, ParseContext* outerpc, Directives directives, GeneratorKind generatorKind, + FunctionAsyncKind asyncKind, JSObject* enclosingStaticScope); // Use when the funbox is the outermost. FunctionBox* newFunctionBox(Node fn, HandleFunction fun, Directives directives, - GeneratorKind generatorKind, HandleObject enclosingStaticScope) + GeneratorKind generatorKind, FunctionAsyncKind asyncKind, + HandleObject enclosingStaticScope) { return newFunctionBox(fn, fun, nullptr, directives, generatorKind, + asyncKind, enclosingStaticScope); } // Use when the funbox should be linked to the outerpc's innermost scope. FunctionBox* newFunctionBox(Node fn, HandleFunction fun, ParseContext* outerpc, - Directives directives, GeneratorKind generatorKind) + Directives directives, GeneratorKind generatorKind, + FunctionAsyncKind asyncKind) { RootedObject enclosing(context, outerpc->innermostStaticScope()); - return newFunctionBox(fn, fun, outerpc, directives, generatorKind, enclosing); + return newFunctionBox(fn, fun, outerpc, directives, generatorKind, asyncKind, enclosing); } ModuleBox* newModuleBox(Node pn, HandleModuleObject module); diff --git a/js/src/frontend/SharedContext.h b/js/src/frontend/SharedContext.h index c075951126..263567f5b1 100644 --- a/js/src/frontend/SharedContext.h +++ b/js/src/frontend/SharedContext.h @@ -333,6 +333,7 @@ class FunctionBox : public ObjectBox, public SharedContext uint16_t length; uint8_t generatorKindBits_; /* The GeneratorKind of this function. */ + uint8_t asyncKindBits_; /* The FunctionAsyncKing of this function. */ bool inGenexpLambda:1; /* lambda from generator expression */ bool hasDestructuringArgs:1; /* arguments list contains destructuring expression */ bool useAsm:1; /* see useAsmOrInsideUseAsm */ @@ -350,7 +351,8 @@ class FunctionBox : public ObjectBox, public SharedContext template FunctionBox(ExclusiveContext* cx, ObjectBox* traceListHead, JSFunction* fun, JSObject* enclosingStaticScope, ParseContext* pc, - Directives directives, bool extraWarnings, GeneratorKind generatorKind); + Directives directives, bool extraWarnings, GeneratorKind generatorKind, + FunctionAsyncKind asyncKind); ObjectBox* toObjectBox() override { return this; } JSFunction* function() const { return &object->as(); } @@ -365,6 +367,8 @@ class FunctionBox : public ObjectBox, public SharedContext bool isGenerator() const { return generatorKind() != NotGenerator; } bool isLegacyGenerator() const { return generatorKind() == LegacyGenerator; } bool isStarGenerator() const { return generatorKind() == StarGenerator; } + FunctionAsyncKind asyncKind() const { return AsyncKindFromBits(asyncKindBits_); } + bool isAsync() const { return asyncKind() == AsyncFunction; } bool isArrow() const { return function()->isArrow(); } void setGeneratorKind(GeneratorKind kind) { diff --git a/js/src/jit/BaselineCompiler.cpp b/js/src/jit/BaselineCompiler.cpp index 1977638525..367cc4ce1e 100644 --- a/js/src/jit/BaselineCompiler.cpp +++ b/js/src/jit/BaselineCompiler.cpp @@ -2679,15 +2679,14 @@ static const VMFunction DefFunOperationInfo = FunctionInfo(De bool BaselineCompiler::emit_JSOP_DEFFUN() { - RootedFunction fun(cx, script->getFunction(GET_UINT32_INDEX(pc))); - - frame.syncStack(0); - masm.loadPtr(frame.addressOfScopeChain(), R0.scratchReg()); + frame.popRegsAndSync(1); + masm.unboxObject(R0, R0.scratchReg()); + masm.loadPtr(frame.addressOfScopeChain(), R1.scratchReg()); prepareVMCall(); - pushArg(ImmGCPtr(fun)); pushArg(R0.scratchReg()); + pushArg(R1.scratchReg()); pushArg(ImmGCPtr(script)); return callVM(DefFunOperationInfo); diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp index 16842ee012..a769bf1db3 100644 --- a/js/src/jit/CodeGenerator.cpp +++ b/js/src/jit/CodeGenerator.cpp @@ -4368,7 +4368,8 @@ CodeGenerator::visitDefFun(LDefFun* lir) { Register scopeChain = ToRegister(lir->scopeChain()); - pushArg(ImmGCPtr(lir->mir()->fun())); + Register fun = ToRegister(lir->fun()); + pushArg(fun); pushArg(scopeChain); pushArg(ImmGCPtr(current->mir()->info().script())); diff --git a/js/src/jit/IonBuilder.cpp b/js/src/jit/IonBuilder.cpp index 615766b0e5..31f199361f 100644 --- a/js/src/jit/IonBuilder.cpp +++ b/js/src/jit/IonBuilder.cpp @@ -12927,13 +12927,9 @@ IonBuilder::jsop_deflexical(uint32_t index) bool IonBuilder::jsop_deffun(uint32_t index) { - JSFunction* fun = script()->getFunction(index); - if (fun->isNative() && IsAsmJSModuleNative(fun->native())) - return abort("asm.js module function"); - MOZ_ASSERT(analysis().usesScopeChain()); - MDefFun* deffun = MDefFun::New(alloc(), fun, current->scopeChain()); + MDefFun* deffun = MDefFun::New(alloc(), current->pop(), current->scopeChain()); current->add(deffun); return resumeAfter(deffun); diff --git a/js/src/jit/Lowering.cpp b/js/src/jit/Lowering.cpp index aab664210d..cadb468035 100644 --- a/js/src/jit/Lowering.cpp +++ b/js/src/jit/Lowering.cpp @@ -164,7 +164,11 @@ LIRGenerator::visitDefLexical(MDefLexical* ins) void LIRGenerator::visitDefFun(MDefFun* ins) { - LDefFun* lir = new(alloc()) LDefFun(useRegisterAtStart(ins->scopeChain())); + MDefinition* fun = ins->fun(); + MOZ_ASSERT(fun->type() == MIRType_Object); + + LDefFun* lir = new(alloc()) LDefFun(useRegisterAtStart(fun), + useRegisterAtStart(ins->scopeChain())); add(lir, ins); assignSafepoint(lir, ins); } diff --git a/js/src/jit/MIR.h b/js/src/jit/MIR.h index b93b794135..d94ec4c9d5 100644 --- a/js/src/jit/MIR.h +++ b/js/src/jit/MIR.h @@ -7423,30 +7423,28 @@ class MDefLexical }; class MDefFun - : public MUnaryInstruction, - public NoTypePolicy::Data + : public MBinaryInstruction, + public SingleObjectPolicy::Data { - CompilerFunction fun_; - private: - MDefFun(JSFunction* fun, MDefinition* scopeChain) - : MUnaryInstruction(scopeChain), - fun_(fun) + MDefFun(MDefinition* fun, MDefinition* scopeChain) + : MBinaryInstruction(fun, scopeChain) {} public: INSTRUCTION_HEADER(DefFun) - static MDefFun* New(TempAllocator& alloc, JSFunction* fun, MDefinition* scopeChain) { + static MDefFun* New(TempAllocator& alloc, MDefinition* fun, MDefinition* scopeChain) { return new(alloc) MDefFun(fun, scopeChain); } - JSFunction* fun() const { - return fun_; + MDefinition* fun() const { + return getOperand(0); } MDefinition* scopeChain() const { - return getOperand(0); + return getOperand(1); } + bool possiblyCalls() const override { return true; } diff --git a/js/src/jit/shared/LIR-shared.h b/js/src/jit/shared/LIR-shared.h index d60892924d..3b2a3f1438 100644 --- a/js/src/jit/shared/LIR-shared.h +++ b/js/src/jit/shared/LIR-shared.h @@ -1238,19 +1238,23 @@ class LDefLexical : public LCallInstructionHelper<0, 0, 0> } }; -class LDefFun : public LCallInstructionHelper<0, 1, 0> +class LDefFun : public LCallInstructionHelper<0, 2, 0> { public: LIR_HEADER(DefFun) - explicit LDefFun(const LAllocation& scopeChain) + LDefFun(const LAllocation& fun, const LAllocation& scopeChain) { - setOperand(0, scopeChain); + setOperand(0, fun); + setOperand(1, scopeChain); } - const LAllocation* scopeChain() { + const LAllocation* fun() { return getOperand(0); } + const LAllocation* scopeChain() { + return getOperand(1); + } MDefFun* mir() const { return mir_->toDefFun(); } diff --git a/js/src/jsfun.h b/js/src/jsfun.h index 8b732150ca..0b87ec4114 100644 --- a/js/src/jsfun.h +++ b/js/src/jsfun.h @@ -291,6 +291,13 @@ class JSFunction : public js::NativeObject flags_ |= RESOLVED_NAME; } + void setAsyncKind(js::FunctionAsyncKind asyncKind) { + if (isInterpretedLazy()) + lazyScript()->setAsyncKind(asyncKind); + else + nonLazyScript()->setAsyncKind(asyncKind); + } + JSAtom* atom() const { return hasGuessedAtom() ? nullptr : atom_.get(); } js::PropertyName* name() const { @@ -471,6 +478,18 @@ class JSFunction : public js::NativeObject bool isStarGenerator() const { return generatorKind() == js::StarGenerator; } + js::FunctionAsyncKind asyncKind() const { + return isInterpretedLazy() ? lazyScript()->asyncKind() : nonLazyScript()->asyncKind(); + } + + bool isAsync() const { + if (isInterpretedLazy()) + return lazyScript()->asyncKind() == js::AsyncFunction; + if (hasScript()) + return nonLazyScript()->asyncKind() == js::AsyncFunction; + return false; + } + void setScript(JSScript* script_) { mutableScript() = script_; } diff --git a/js/src/jsscript.cpp b/js/src/jsscript.cpp index 854f47bcf9..92af3262ba 100644 --- a/js/src/jsscript.cpp +++ b/js/src/jsscript.cpp @@ -867,6 +867,7 @@ js::XDRScript(XDRState* xdr, HandleObject enclosingScopeArg, HandleScript return false; if (mode == XDR_DECODE) { + /* XXX: AsyncFunction and isAsync not implemented. */ if (!JSScript::partiallyInit(cx, script, nconsts, nobjects, nregexps, ntrynotes, nblockscopes, nyieldoffsets, nTypeSets)) { @@ -2751,6 +2752,7 @@ JSScript::Create(ExclusiveContext* cx, HandleObject enclosingScope, bool savedCa script->setSourceObject(sourceObject); script->sourceStart_ = bufStart; script->sourceEnd_ = bufEnd; + script->isAsync_ = false; return script; } @@ -2915,6 +2917,7 @@ JSScript::linkToFunctionFromEmitter(js::ExclusiveContext* cx, JS::HandleisGeneratorExp_ = funbox->inGenexpLambda; script->setGeneratorKind(funbox->generatorKind()); + script->setAsyncKind(funbox->asyncKind()); // Link the function and the script to each other, so that StaticScopeIter // may walk the scope chain of currently compiling scripts. @@ -2940,6 +2943,7 @@ JSScript::linkToModuleFromEmitter(js::ExclusiveContext* cx, JS::HandlefunLength_ = 0; script->isGeneratorExp_ = false; + script->isAsync_ = false; script->setGeneratorKind(NotGenerator); // Link the module and the script to each other, so that StaticScopeIter @@ -3575,6 +3579,7 @@ js::detail::CopyScript(JSContext* cx, HandleObject scriptStaticScope, HandleScri dst->hasInnerFunctions_ = src->hasInnerFunctions(); dst->isGeneratorExp_ = src->isGeneratorExp(); dst->setGeneratorKind(src->generatorKind()); + dst->isAsync_ = src->asyncKind() == AsyncFunction; if (nconsts != 0) { HeapValue* vector = Rebase(dst, src, src->consts()->vector); @@ -4275,6 +4280,7 @@ LazyScript::CreateRaw(ExclusiveContext* cx, HandleFunction fun, // Reset runtime flags to obtain a fresh LazyScript. p.hasBeenCloned = false; p.treatAsRunOnce = false; + p.isAsync = false; size_t bytes = (p.numFreeVariables * sizeof(FreeVariable)) + (p.numInnerFunctions * sizeof(HeapPtrFunction)); @@ -4306,6 +4312,7 @@ LazyScript::CreateRaw(ExclusiveContext* cx, HandleFunction fun, p.version = version; p.numFreeVariables = numFreeVariables; + p.isAsync = false; p.numInnerFunctions = numInnerFunctions; p.generatorKindBits = GeneratorKindAsBits(NotGenerator); p.strict = false; diff --git a/js/src/jsscript.h b/js/src/jsscript.h index 59b94dd34a..90eb07ed93 100644 --- a/js/src/jsscript.h +++ b/js/src/jsscript.h @@ -894,6 +894,7 @@ class ScriptSourceObject : public NativeObject }; enum GeneratorKind { NotGenerator, LegacyGenerator, StarGenerator }; +enum FunctionAsyncKind { SyncFunction, AsyncFunction }; static inline unsigned GeneratorKindAsBits(GeneratorKind generatorKind) { @@ -906,6 +907,17 @@ GeneratorKindFromBits(unsigned val) { return static_cast(val); } +static inline unsigned +AsyncKindAsBits(FunctionAsyncKind asyncKind) { + return static_cast(asyncKind); +} + +static inline FunctionAsyncKind +AsyncKindFromBits(unsigned val) { + MOZ_ASSERT(val <= AsyncFunction); + return static_cast(val); +} + /* * NB: after a successful XDR_DECODE, XDRScript callers must do any required * subsequent set-up of owning function or script object and then call @@ -1190,6 +1202,8 @@ class JSScript : public js::gc::TenuredCell bool isDerivedClassConstructor_:1; + bool isAsync_:1; + // Add padding so JSScript is gc::Cell aligned. Make padding protected // instead of private to suppress -Wunused-private-field compiler warnings. protected: @@ -1456,6 +1470,14 @@ class JSScript : public js::gc::TenuredCell generatorKindBits_ = GeneratorKindAsBits(kind); } + js::FunctionAsyncKind asyncKind() const { + return isAsync_ ? js::AsyncFunction : js::SyncFunction; + } + + void setAsyncKind(js::FunctionAsyncKind kind) { + isAsync_ = kind == js::AsyncFunction; + } + void setNeedsHomeObject() { needsHomeObject_ = true; } @@ -2136,7 +2158,8 @@ class LazyScript : public gc::TenuredCell // Assorted bits that should really be in ScriptSourceObject. uint32_t version : 8; - uint32_t numFreeVariables : 24; + uint32_t numFreeVariables : 23; + uint32_t isAsync: 1; uint32_t numInnerFunctions : 20; uint32_t generatorKindBits : 2; @@ -2274,6 +2297,14 @@ class LazyScript : public gc::TenuredCell p_.generatorKindBits = GeneratorKindAsBits(kind); } + FunctionAsyncKind asyncKind() const { + return p_.isAsync ? AsyncFunction : SyncFunction; + } + + void setAsyncKind(FunctionAsyncKind kind) { + p_.isAsync = kind == AsyncFunction; + } + bool strict() const { return p_.strict; } diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp index 66e3926687..6326a325eb 100644 --- a/js/src/vm/Interpreter.cpp +++ b/js/src/vm/Interpreter.cpp @@ -3277,9 +3277,10 @@ CASE(JSOP_DEFFUN) * a compound statement (not at the top statement level of global code, or * at the top level of a function body). */ - ReservedRooted fun(&rootFunction0, script->getFunction(GET_UINT32_INDEX(REGS.pc))); + ReservedRooted fun(&rootFunction0, ®S.sp[-1].toObject().as()); if (!DefFunOperation(cx, script, REGS.fp()->scopeChain(), fun)) goto error; + REGS.sp--; } END_CASE(JSOP_DEFFUN) @@ -4095,27 +4096,8 @@ js::LambdaArrow(JSContext* cx, HandleFunction fun, HandleObject parent, HandleVa bool js::DefFunOperation(JSContext* cx, HandleScript script, HandleObject scopeChain, - HandleFunction funArg) + HandleFunction fun) { - /* - * If static link is not current scope, clone fun's object to link to the - * current scope via parent. We do this to enable sharing of compiled - * functions among multiple equivalent scopes, amortizing the cost of - * compilation over a number of executions. Examples include XUL scripts - * and event handlers shared among Firefox or other Mozilla app chrome - * windows, and user-defined JS functions precompiled and then shared among - * requests in server-side JS. - */ - RootedFunction fun(cx, funArg); - if (fun->isNative() || fun->environment() != scopeChain) { - fun = CloneFunctionObjectIfNotSingleton(cx, fun, scopeChain, nullptr, TenuredObject); - if (!fun) - return false; - } else { - MOZ_ASSERT(script->treatAsRunOnce()); - MOZ_ASSERT(!script->functionNonDelazifying()); - } - /* * We define the function as a property of the variable object and not the * current scope chain even for the case of function expression statements diff --git a/js/src/vm/Opcodes.h b/js/src/vm/Opcodes.h index eae3e53337..7bcb3b6ed1 100644 --- a/js/src/vm/Opcodes.h +++ b/js/src/vm/Opcodes.h @@ -1286,10 +1286,10 @@ * scripts where use of dynamic scoping inhibits optimization. * Category: Variables and Scopes * Type: Variables - * Operands: uint32_t funcIndex - * Stack: => + * Operands: + * Stack: fun => */ \ - macro(JSOP_DEFFUN, 127,"deffun", NULL, 5, 0, 0, JOF_OBJECT) \ + macro(JSOP_DEFFUN, 127,"deffun", NULL, 1, 1, 0, JOF_BYTE) \ /* Defines the new constant binding on global lexical scope. * * Throws if a binding with the same name already exists on the scope, or