From f07d5707c77e73031b6921faac165ca7f8d577c6 Mon Sep 17 00:00:00 2001 From: Gaming4JC Date: Sun, 1 Dec 2019 18:44:06 -0500 Subject: Bug 1343481 - Part 2: Stop using StarGegerator for async function. Tag #1287 --- js/src/frontend/BytecodeCompiler.cpp | 2 +- js/src/frontend/BytecodeEmitter.cpp | 23 +++++++++------ js/src/frontend/Parser.cpp | 54 ++++++++++++++++-------------------- js/src/frontend/SharedContext.h | 4 +++ js/src/jsfun.cpp | 16 +++++------ js/src/jsfun.h | 6 ++-- js/src/jsscript.cpp | 2 +- js/src/vm/AsyncFunction.cpp | 2 +- js/src/vm/Debugger.cpp | 2 +- js/src/vm/GeneratorObject.cpp | 2 +- 10 files changed, 58 insertions(+), 55 deletions(-) (limited to 'js') diff --git a/js/src/frontend/BytecodeCompiler.cpp b/js/src/frontend/BytecodeCompiler.cpp index a1abbfeda..7760c4b2e 100644 --- a/js/src/frontend/BytecodeCompiler.cpp +++ b/js/src/frontend/BytecodeCompiler.cpp @@ -727,5 +727,5 @@ frontend::CompileStandaloneAsyncFunction(JSContext* cx, MutableHandleFunction fu BytecodeCompiler compiler(cx, cx->tempLifoAlloc(), options, srcBuf, emptyGlobalScope, TraceLogger_ParserCompileFunction); - return compiler.compileStandaloneFunction(fun, StarGenerator, AsyncFunction, parameterListEnd); + return compiler.compileStandaloneFunction(fun, NotGenerator, AsyncFunction, parameterListEnd); } diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index 4dc4914dc..b8a9bdf7e 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -8443,7 +8443,8 @@ BytecodeEmitter::emitReturn(ParseNode* pn) if (!updateSourceCoordNotes(pn->pn_pos.begin)) return false; - if (sc->isFunctionBox() && sc->asFunctionBox()->isStarGenerator()) { + bool needsIteratorResult = sc->isFunctionBox() && sc->asFunctionBox()->needsIteratorResult(); + if (needsIteratorResult) { if (!emitPrepareIteratorResult()) return false; } @@ -8458,7 +8459,7 @@ BytecodeEmitter::emitReturn(ParseNode* pn) return false; } - if (sc->isFunctionBox() && sc->asFunctionBox()->isStarGenerator()) { + if (needsIteratorResult) { if (!emitFinishIteratorResult(true)) return false; } @@ -8530,7 +8531,8 @@ BytecodeEmitter::emitYield(ParseNode* pn) MOZ_ASSERT(sc->isFunctionBox()); if (pn->getOp() == JSOP_YIELD) { - if (sc->asFunctionBox()->isStarGenerator()) { + bool needsIteratorResult = sc->asFunctionBox()->needsIteratorResult(); + if (needsIteratorResult) { if (!emitPrepareIteratorResult()) return false; } @@ -8541,7 +8543,7 @@ BytecodeEmitter::emitYield(ParseNode* pn) if (!emit1(JSOP_UNDEFINED)) return false; } - if (sc->asFunctionBox()->isStarGenerator()) { + if (needsIteratorResult) { if (!emitFinishIteratorResult(false)) return false; } @@ -10319,14 +10321,19 @@ BytecodeEmitter::emitFunctionBody(ParseNode* funBody) if (funbox->needsFinalYield()) { // If we fall off the end of a generator, do a final yield. - if (funbox->isStarGenerator() && !emitPrepareIteratorResult()) - return false; + bool needsIteratorResult = funbox->needsIteratorResult(); + if (needsIteratorResult) { + if (!emitPrepareIteratorResult()) + return false; + } if (!emit1(JSOP_UNDEFINED)) return false; - if (funbox->isStarGenerator() && !emitFinishIteratorResult(true)) - return false; + if (needsIteratorResult) { + if (!emitFinishIteratorResult(true)) + return false; + } if (!emit1(JSOP_SETRVAL)) return false; diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index 64b1f22c2..406d37725 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -2474,10 +2474,8 @@ Parser::finishFunction(bool isStandaloneFunction /* = false } static YieldHandling -GetYieldHandling(GeneratorKind generatorKind, FunctionAsyncKind asyncKind) +GetYieldHandling(GeneratorKind generatorKind) { - if (asyncKind == AsyncFunction) - return YieldIsName; if (generatorKind == NotGenerator) return YieldIsName; return YieldIsKeyword; @@ -2541,7 +2539,7 @@ Parser::standaloneFunction(HandleFunction fun, return null(); funpc.setIsStandaloneFunctionBody(); - YieldHandling yieldHandling = GetYieldHandling(generatorKind, asyncKind); + YieldHandling yieldHandling = GetYieldHandling(generatorKind); AutoAwaitIsKeyword awaitIsKeyword(this, asyncKind == AsyncFunction); if (!functionFormalParametersAndBody(InAllowed, yieldHandling, fn, Statement, parameterListEnd, /* isStandaloneFunction = */ true)) @@ -2699,7 +2697,7 @@ Parser::functionBody(InHandling inHandling, YieldHandling yieldHan switch (pc->generatorKind()) { case NotGenerator: - MOZ_ASSERT(pc->lastYieldOffset == startYieldOffset); + MOZ_ASSERT_IF(!pc->isAsync(), pc->lastYieldOffset == startYieldOffset); break; case LegacyGenerator: @@ -2715,8 +2713,8 @@ Parser::functionBody(InHandling inHandling, YieldHandling yieldHan break; case StarGenerator: - MOZ_ASSERT_IF(!pc->isAsync(), kind != Arrow); - MOZ_ASSERT_IF(!pc->isAsync(), type == StatementListBody); + MOZ_ASSERT(kind != Arrow); + MOZ_ASSERT(type == StatementListBody); break; } @@ -2761,9 +2759,9 @@ Parser::newFunction(HandleAtom atom, FunctionSyntaxKind kind, #endif switch (kind) { case Expression: - flags = (generatorKind == NotGenerator + flags = (generatorKind == NotGenerator && asyncKind == SyncFunction ? JSFunction::INTERPRETED_LAMBDA - : JSFunction::INTERPRETED_LAMBDA_GENERATOR); + : JSFunction::INTERPRETED_LAMBDA_GENERATOR_OR_ASYNC); break; case Arrow: flags = JSFunction::INTERPRETED_LAMBDA_ARROW; @@ -2771,9 +2769,9 @@ Parser::newFunction(HandleAtom atom, FunctionSyntaxKind kind, break; case Method: MOZ_ASSERT(generatorKind == NotGenerator || generatorKind == StarGenerator); - flags = (generatorKind == NotGenerator + flags = (generatorKind == NotGenerator && asyncKind == SyncFunction ? JSFunction::INTERPRETED_METHOD - : JSFunction::INTERPRETED_METHOD_GENERATOR); + : JSFunction::INTERPRETED_METHOD_GENERATOR_OR_ASYNC); allocKind = gc::AllocKind::FUNCTION_EXTENDED; break; case ClassConstructor: @@ -2799,9 +2797,9 @@ Parser::newFunction(HandleAtom atom, FunctionSyntaxKind kind, allocKind = gc::AllocKind::FUNCTION_EXTENDED; } #endif - flags = (generatorKind == NotGenerator + flags = (generatorKind == NotGenerator && asyncKind == SyncFunction ? JSFunction::INTERPRETED_NORMAL - : JSFunction::INTERPRETED_GENERATOR); + : JSFunction::INTERPRETED_GENERATOR_OR_ASYNC); } // We store the async wrapper in a slot for later access. @@ -3324,7 +3322,6 @@ Parser::functionDefinition(uint32_t toStringStart, Node pn, InHand bool tryAnnexB /* = false */) { MOZ_ASSERT_IF(kind == Statement, funName); - MOZ_ASSERT_IF(asyncKind == AsyncFunction, generatorKind == StarGenerator); // When fully parsing a LazyScript, we do not fully reparse its inner // functions, which are also lazy. Instead, their free variables and @@ -3336,7 +3333,7 @@ Parser::functionDefinition(uint32_t toStringStart, Node pn, InHand } RootedObject proto(context); - if (generatorKind == StarGenerator) { + if (generatorKind == StarGenerator || asyncKind == AsyncFunction) { // If we are off the main thread, the generator meta-objects have // already been created by js::StartOffThreadParseScript, so cx will not // be necessary. @@ -3408,7 +3405,7 @@ Parser::trySyntaxParseInnerFunction(ParseNode* pn, HandleFunct // parse to avoid the overhead of a lazy syntax-only parse. Although // the prediction may be incorrect, IIFEs are common enough that it // pays off for lots of code. - if (pn->isLikelyIIFE() && generatorKind == NotGenerator) + if (pn->isLikelyIIFE() && generatorKind == NotGenerator && asyncKind == SyncFunction) break; Parser* parser = handler.syntaxParser; @@ -3584,7 +3581,7 @@ Parser::standaloneLazyFunction(HandleFunction fun, bool strict if (!tokenStream.peekTokenPos(&pn->pn_pos, modifier)) return null(); - YieldHandling yieldHandling = GetYieldHandling(generatorKind, asyncKind); + YieldHandling yieldHandling = GetYieldHandling(generatorKind); FunctionSyntaxKind syntaxKind = Statement; if (fun->isClassConstructor()) syntaxKind = ClassConstructor; @@ -3665,7 +3662,7 @@ Parser::functionFormalParametersAndBody(InHandling inHandling, return false; uint32_t openedPos = 0; if (tt != TOK_LC) { - if ((funbox->isStarGenerator() && !funbox->isAsync()) || kind == Method || + if (funbox->isStarGenerator() || kind == Method || kind == GetterNoExpressionClosure || kind == SetterNoExpressionClosure || IsConstructorKind(kind)) { error(JSMSG_CURLY_BEFORE_BODY); @@ -3695,7 +3692,7 @@ Parser::functionFormalParametersAndBody(InHandling inHandling, // whether the arrow function is enclosed in a generator function or not. // Whereas the |yield| in the function body is always parsed as a name. // The same goes when parsing |await| in arrow functions. - YieldHandling bodyYieldHandling = GetYieldHandling(pc->generatorKind(), pc->asyncKind()); + YieldHandling bodyYieldHandling = GetYieldHandling(pc->generatorKind()); Node body; { AutoAwaitIsKeyword awaitIsKeyword(this, funbox->isAsync()); @@ -3786,7 +3783,7 @@ Parser::functionStmt(uint32_t toStringStart, YieldHandling yieldHa if (!tokenStream.getToken(&tt)) return null(); - GeneratorKind generatorKind = asyncKind == AsyncFunction ? StarGenerator : NotGenerator; + GeneratorKind generatorKind = NotGenerator; if (tt == TOK_MUL) { if (asyncKind != SyncFunction) { error(JSMSG_ASYNC_GENERATOR); @@ -3817,7 +3814,7 @@ Parser::functionStmt(uint32_t toStringStart, YieldHandling yieldHa MOZ_ASSERT(declaredInStmt->kind() != StatementKind::Label); MOZ_ASSERT(StatementKindIsBraced(declaredInStmt->kind())); - if (!pc->sc()->strict() && generatorKind == NotGenerator) { + if (!pc->sc()->strict() && generatorKind == NotGenerator && asyncKind == SyncFunction) { // In sloppy mode, try Annex B.3.3 semantics. If making an // additional 'var' binding of the same name does not throw an // early error, do so. This 'var' binding would be assigned @@ -3841,7 +3838,7 @@ Parser::functionStmt(uint32_t toStringStart, YieldHandling yieldHa if (!pn) return null(); - YieldHandling newYieldHandling = GetYieldHandling(generatorKind, asyncKind); + YieldHandling newYieldHandling = GetYieldHandling(generatorKind); return functionDefinition(toStringStart, pn, InAllowed, newYieldHandling, name, Statement, generatorKind, asyncKind, tryAnnexB); } @@ -3854,7 +3851,7 @@ Parser::functionExpr(uint32_t toStringStart, InvokedPrediction inv MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_FUNCTION)); AutoAwaitIsKeyword awaitIsKeyword(this, asyncKind == AsyncFunction); - GeneratorKind generatorKind = asyncKind == AsyncFunction ? StarGenerator : NotGenerator; + GeneratorKind generatorKind = NotGenerator; TokenKind tt; if (!tokenStream.getToken(&tt)) return null(); @@ -3869,7 +3866,7 @@ Parser::functionExpr(uint32_t toStringStart, InvokedPrediction inv return null(); } - YieldHandling yieldHandling = GetYieldHandling(generatorKind, asyncKind); + YieldHandling yieldHandling = GetYieldHandling(generatorKind); RootedPropertyName name(context); if (TokenKindIsPossibleIdentifier(tt)) { @@ -8187,7 +8184,6 @@ Parser::assignExpr(InHandling inHandling, YieldHandling yieldHandl uint32_t toStringStart = pos().begin; tokenStream.ungetToken(); - GeneratorKind generatorKind = NotGenerator; FunctionAsyncKind asyncKind = SyncFunction; if (next == TOK_ASYNC) { @@ -8200,7 +8196,6 @@ Parser::assignExpr(InHandling inHandling, YieldHandling yieldHandl if (nextSameLine == TOK_ARROW) { tokenStream.ungetToken(); } else { - generatorKind = StarGenerator; asyncKind = AsyncFunction; } } @@ -8210,7 +8205,7 @@ Parser::assignExpr(InHandling inHandling, YieldHandling yieldHandl return null(); Node arrowFunc = functionDefinition(toStringStart, pn, inHandling, yieldHandling, nullptr, - Arrow, generatorKind, asyncKind); + Arrow, NotGenerator, asyncKind); if (!arrowFunc) return null(); @@ -9950,8 +9945,7 @@ Parser::methodDefinition(uint32_t toStringStart, PropertyType prop MOZ_CRASH("Parser: methodDefinition: unexpected property type"); } - GeneratorKind generatorKind = (propType == PropertyType::GeneratorMethod || - propType == PropertyType::AsyncMethod) + GeneratorKind generatorKind = propType == PropertyType::GeneratorMethod ? StarGenerator : NotGenerator; @@ -9959,7 +9953,7 @@ Parser::methodDefinition(uint32_t toStringStart, PropertyType prop ? AsyncFunction : SyncFunction; - YieldHandling yieldHandling = GetYieldHandling(generatorKind, asyncKind); + YieldHandling yieldHandling = GetYieldHandling(generatorKind); Node pn = handler.newFunctionExpression(); if (!pn) diff --git a/js/src/frontend/SharedContext.h b/js/src/frontend/SharedContext.h index 5766c135a..2d478308e 100644 --- a/js/src/frontend/SharedContext.h +++ b/js/src/frontend/SharedContext.h @@ -552,6 +552,10 @@ class FunctionBox : public ObjectBox, public SharedContext return isStarGenerator() || isLegacyGenerator() || isAsync(); } + bool needsIteratorResult() const { + return isStarGenerator() || isAsync(); + } + bool isAsync() const { return asyncKind() == AsyncFunction; } bool isArrow() const { return function()->isArrow(); } diff --git a/js/src/jsfun.cpp b/js/src/jsfun.cpp index 9d54fef78..65d44cba7 100644 --- a/js/src/jsfun.cpp +++ b/js/src/jsfun.cpp @@ -523,7 +523,7 @@ js::XDRInterpretedFunction(XDRState* xdr, HandleScope enclosingScope, { enum FirstWordFlag { HasAtom = 0x1, - IsStarGenerator = 0x2, + HasStarGeneratorProto = 0x2, IsLazy = 0x4, HasSingletonType = 0x8 }; @@ -552,8 +552,8 @@ js::XDRInterpretedFunction(XDRState* xdr, HandleScope enclosingScope, if (fun->explicitName() || fun->hasCompileTimeName() || fun->hasGuessedAtom()) firstword |= HasAtom; - if (fun->isStarGenerator()) - firstword |= IsStarGenerator; + if (fun->isStarGenerator() || fun->isAsync()) + firstword |= HasStarGeneratorProto; if (fun->isInterpretedLazy()) { // Encode a lazy script. @@ -589,7 +589,7 @@ js::XDRInterpretedFunction(XDRState* xdr, HandleScope enclosingScope, if (mode == XDR_DECODE) { RootedObject proto(cx); - if (firstword & IsStarGenerator) { + if (firstword & HasStarGeneratorProto) { proto = GlobalObject::getOrCreateStarGeneratorFunctionPrototype(cx, cx->global()); if (!proto) return false; @@ -1596,8 +1596,6 @@ FunctionConstructor(JSContext* cx, const CallArgs& args, GeneratorKind generator bool isStarGenerator = generatorKind == StarGenerator; bool isAsync = asyncKind == AsyncFunction; MOZ_ASSERT(generatorKind != LegacyGenerator); - MOZ_ASSERT_IF(isAsync, isStarGenerator); - MOZ_ASSERT_IF(!isStarGenerator, !isAsync); RootedScript maybeScript(cx); const char* filename; @@ -1709,7 +1707,7 @@ FunctionConstructor(JSContext* cx, const CallArgs& args, GeneratorKind generator // Step 4.d, use %Generator% as the fallback prototype. // Also use %Generator% for the unwrapped function of async functions. - if (!proto && isStarGenerator) { + if (!proto && (isStarGenerator || isAsync)) { proto = GlobalObject::getOrCreateStarGeneratorFunctionPrototype(cx, global); if (!proto) return false; @@ -1777,7 +1775,7 @@ js::AsyncFunctionConstructor(JSContext* cx, unsigned argc, Value* vp) else newTarget = &args.callee(); - if (!FunctionConstructor(cx, args, StarGenerator, AsyncFunction)) + if (!FunctionConstructor(cx, args, NotGenerator, AsyncFunction)) return false; // ES2017, draft rev 0f10dba4ad18de92d47d421f378233a2eae8f077 @@ -1973,7 +1971,7 @@ NewFunctionClone(JSContext* cx, HandleFunction fun, NewObjectKind newKind, gc::AllocKind allocKind, HandleObject proto) { RootedObject cloneProto(cx, proto); - if (!proto && fun->isStarGenerator()) { + if (!proto && (fun->isStarGenerator() || fun->isAsync())) { cloneProto = GlobalObject::getOrCreateStarGeneratorFunctionPrototype(cx, cx->global()); if (!cloneProto) return nullptr; diff --git a/js/src/jsfun.h b/js/src/jsfun.h index 9aee719e4..9e50387d6 100644 --- a/js/src/jsfun.h +++ b/js/src/jsfun.h @@ -89,15 +89,15 @@ class JSFunction : public js::NativeObject ASMJS_CTOR = ASMJS_KIND | NATIVE_CTOR, ASMJS_LAMBDA_CTOR = ASMJS_KIND | NATIVE_CTOR | LAMBDA, INTERPRETED_METHOD = INTERPRETED | METHOD_KIND, - INTERPRETED_METHOD_GENERATOR = INTERPRETED | METHOD_KIND, + INTERPRETED_METHOD_GENERATOR_OR_ASYNC = INTERPRETED | METHOD_KIND, INTERPRETED_CLASS_CONSTRUCTOR = INTERPRETED | CLASSCONSTRUCTOR_KIND | CONSTRUCTOR, INTERPRETED_GETTER = INTERPRETED | GETTER_KIND, INTERPRETED_SETTER = INTERPRETED | SETTER_KIND, INTERPRETED_LAMBDA = INTERPRETED | LAMBDA | CONSTRUCTOR, INTERPRETED_LAMBDA_ARROW = INTERPRETED | LAMBDA | ARROW_KIND, - INTERPRETED_LAMBDA_GENERATOR = INTERPRETED | LAMBDA, + INTERPRETED_LAMBDA_GENERATOR_OR_ASYNC = INTERPRETED | LAMBDA, INTERPRETED_NORMAL = INTERPRETED | CONSTRUCTOR, - INTERPRETED_GENERATOR = INTERPRETED, + INTERPRETED_GENERATOR_OR_ASYNC = INTERPRETED, NO_XDR_FLAGS = RESOLVED_LENGTH | RESOLVED_NAME, STABLE_ACROSS_CLONES = CONSTRUCTOR | HAS_GUESSED_ATOM | LAMBDA | diff --git a/js/src/jsscript.cpp b/js/src/jsscript.cpp index 6f5284a3b..eb74a1ec6 100644 --- a/js/src/jsscript.cpp +++ b/js/src/jsscript.cpp @@ -3188,7 +3188,7 @@ CloneInnerInterpretedFunction(JSContext* cx, HandleScope enclosingScope, HandleF { /* NB: Keep this in sync with XDRInterpretedFunction. */ RootedObject cloneProto(cx); - if (srcFun->isStarGenerator()) { + if (srcFun->isStarGenerator() || srcFun->isAsync()) { cloneProto = GlobalObject::getOrCreateStarGeneratorFunctionPrototype(cx, cx->global()); if (!cloneProto) return nullptr; diff --git a/js/src/vm/AsyncFunction.cpp b/js/src/vm/AsyncFunction.cpp index e14b77424..be7a36ecc 100644 --- a/js/src/vm/AsyncFunction.cpp +++ b/js/src/vm/AsyncFunction.cpp @@ -109,7 +109,7 @@ WrappedAsyncFunction(JSContext* cx, unsigned argc, Value* vp) JSObject* js::WrapAsyncFunctionWithProto(JSContext* cx, HandleFunction unwrapped, HandleObject proto) { - MOZ_ASSERT(unwrapped->isStarGenerator()); + MOZ_ASSERT(unwrapped->isAsync()); MOZ_ASSERT(proto, "We need an explicit prototype to avoid the default" "%FunctionPrototype% fallback in NewFunctionWithProto()."); diff --git a/js/src/vm/Debugger.cpp b/js/src/vm/Debugger.cpp index b3efeb175..7c09c50b0 100644 --- a/js/src/vm/Debugger.cpp +++ b/js/src/vm/Debugger.cpp @@ -1569,7 +1569,7 @@ CheckResumptionValue(JSContext* cx, AbstractFramePtr frame, const MaybeisStarGenerator()) { + } else if (callee->isStarGenerator() || callee->isAsync()) { if (!CheckStarGeneratorResumptionValue(cx, vp)) { JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_DEBUG_BAD_YIELD); return false; diff --git a/js/src/vm/GeneratorObject.cpp b/js/src/vm/GeneratorObject.cpp index 448bc543d..c0dff8faa 100644 --- a/js/src/vm/GeneratorObject.cpp +++ b/js/src/vm/GeneratorObject.cpp @@ -25,7 +25,7 @@ GeneratorObject::create(JSContext* cx, AbstractFramePtr frame) Rooted global(cx, cx->global()); RootedNativeObject obj(cx); - if (frame.script()->isStarGenerator()) { + if (frame.script()->isStarGenerator() || frame.script()->isAsync()) { RootedValue pval(cx); RootedObject fun(cx, frame.callee()); // FIXME: This would be faster if we could avoid doing a lookup to get -- cgit v1.2.3