diff options
-rw-r--r-- | js/src/builtin/ReflectParse.cpp | 12 | ||||
-rw-r--r-- | js/src/frontend/BytecodeEmitter.cpp | 77 | ||||
-rw-r--r-- | js/src/frontend/BytecodeEmitter.h | 5 | ||||
-rw-r--r-- | js/src/frontend/FoldConstants.cpp | 25 | ||||
-rw-r--r-- | js/src/frontend/FullParseHandler.h | 21 | ||||
-rw-r--r-- | js/src/frontend/NameFunctions.cpp | 21 | ||||
-rw-r--r-- | js/src/frontend/ParseNode.cpp | 28 | ||||
-rw-r--r-- | js/src/frontend/ParseNode.h | 6 | ||||
-rw-r--r-- | js/src/frontend/Parser.cpp | 33 | ||||
-rw-r--r-- | js/src/frontend/Parser.h | 2 | ||||
-rw-r--r-- | js/src/frontend/SyntaxParseHandler.h | 6 |
11 files changed, 124 insertions, 112 deletions
diff --git a/js/src/builtin/ReflectParse.cpp b/js/src/builtin/ReflectParse.cpp index 120970196..22c958d4c 100644 --- a/js/src/builtin/ReflectParse.cpp +++ b/js/src/builtin/ReflectParse.cpp @@ -2800,11 +2800,11 @@ ASTSerializer::generatorExpression(ParseNode* pn, MutableHandleValue dst) LOCAL_ASSERT(next->isKind(PNK_SEMI) && next->pn_kid->isKind(PNK_YIELD) && - next->pn_kid->pn_left); + next->pn_kid->pn_kid); RootedValue body(cx); - return expression(next->pn_kid->pn_left, &body) && + return expression(next->pn_kid->pn_kid, &body) && builder.generatorExpression(body, blocks, filter, isLegacy, &pn->pn_pos, dst); } @@ -3146,7 +3146,7 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst) case PNK_YIELD_STAR: { - MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_left->pn_pos)); + MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_kid->pn_pos)); RootedValue arg(cx); return expression(pn->pn_left, &arg) && @@ -3155,10 +3155,10 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst) case PNK_YIELD: { - MOZ_ASSERT_IF(pn->pn_left, pn->pn_pos.encloses(pn->pn_left->pn_pos)); + MOZ_ASSERT_IF(pn->pn_kid, pn->pn_pos.encloses(pn->pn_kid->pn_pos)); RootedValue arg(cx); - return optExpression(pn->pn_left, &arg) && + return optExpression(pn->pn_kid, &arg) && builder.yieldExpression(arg, NotDelegating, &pn->pn_pos, dst); } @@ -3480,7 +3480,7 @@ ASTSerializer::functionArgsAndBody(ParseNode* pn, NodeVector& args, NodeVector& ParseNode* pnstart = pnbody->pn_head; // Skip over initial yield in generator. - if (pnstart && pnstart->isKind(PNK_YIELD)) { + if (pnstart && pnstart->isKind(PNK_INITIALYIELD)) { MOZ_ASSERT(pnstart->getOp() == JSOP_INITIALYIELD); pnstart = pnstart->pn_next; } diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index 6a6deed12..77a480bff 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -3175,10 +3175,11 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer) *answer = true; return true; + case PNK_INITIALYIELD: case PNK_YIELD_STAR: case PNK_YIELD: case PNK_AWAIT: - MOZ_ASSERT(pn->isArity(PN_BINARY)); + MOZ_ASSERT(pn->isArity(PN_UNARY)); *answer = true; return true; @@ -8526,45 +8527,61 @@ BytecodeEmitter::emitReturn(ParseNode* pn) } bool +BytecodeEmitter::emitGetDotGenerator() +{ + NameLocation loc = *locationOfNameBoundInFunctionScope(cx->names().dotGenerator); + return emitGetNameAtLocation(cx->names().dotGenerator, loc); +} + +bool +BytecodeEmitter::emitInitialYield(ParseNode* pn) +{ + if (!emitTree(pn->pn_kid)) + return false; + + if (!emitYieldOp(JSOP_INITIALYIELD)) + return false; + + if (!emit1(JSOP_POP)) + return false; + + return true; +} + +bool BytecodeEmitter::emitYield(ParseNode* pn) { MOZ_ASSERT(sc->isFunctionBox()); + MOZ_ASSERT(pn->getOp() == JSOP_YIELD || pn->getOp() == JSOP_AWAIT); - if (pn->getOp() == JSOP_YIELD || pn->getOp() == JSOP_AWAIT) { - bool needsIteratorResult = sc->asFunctionBox()->needsIteratorResult(); - if (needsIteratorResult) { - if (!emitPrepareIteratorResult()) - return false; - } - if (pn->pn_left) { - if (!emitTree(pn->pn_left)) - return false; - } else { - if (!emit1(JSOP_UNDEFINED)) - return false; - } - if (needsIteratorResult) { - if (!emitFinishIteratorResult(false)) - return false; - } + bool needsIteratorResult = sc->asFunctionBox()->needsIteratorResult(); + if (needsIteratorResult) { + if (!emitPrepareIteratorResult()) + return false; + } + if (pn->pn_kid) { + if (!emitTree(pn->pn_kid)) + return false; } else { - MOZ_ASSERT(pn->getOp() == JSOP_INITIALYIELD); + if (!emit1(JSOP_UNDEFINED)) + return false; + } + if (needsIteratorResult) { + if (!emitFinishIteratorResult(false)) + return false; } - if (!emitTree(pn->pn_right)) + if (!emitGetDotGenerator()) return false; if (!emitYieldOp(pn->getOp())) return false; - if (pn->getOp() == JSOP_INITIALYIELD && !emit1(JSOP_POP)) - return false; - return true; } bool -BytecodeEmitter::emitYieldStar(ParseNode* iter, ParseNode* gen) +BytecodeEmitter::emitYieldStar(ParseNode* iter) { MOZ_ASSERT(sc->isFunctionBox()); MOZ_ASSERT(sc->asFunctionBox()->isStarGenerator()); @@ -8594,7 +8611,7 @@ BytecodeEmitter::emitYieldStar(ParseNode* iter, ParseNode* gen) MOZ_ASSERT(this->stackDepth == startDepth); // Load the generator object. - if (!emitTree(gen)) // ITER RESULT GENOBJ + if (!emitGetDotGenerator()) // ITER RESULT GENOBJ return false; // Yield RESULT as-is, without re-boxing. @@ -10338,8 +10355,7 @@ BytecodeEmitter::emitFunctionBody(ParseNode* funBody) if (!emit1(JSOP_SETRVAL)) return false; - NameLocation loc = *locationOfNameBoundInFunctionScope(cx->names().dotGenerator); - if (!emitGetNameAtLocation(cx->names().dotGenerator, loc)) + if (!emitGetDotGenerator()) return false; // No need to check for finally blocks, etc as in EmitReturn. @@ -10599,7 +10615,7 @@ BytecodeEmitter::emitTree(ParseNode* pn, ValueUsage valueUsage /* = ValueUsage:: break; case PNK_YIELD_STAR: - if (!emitYieldStar(pn->pn_left, pn->pn_right)) + if (!emitYieldStar(pn->pn_kid)) return false; break; @@ -10608,6 +10624,11 @@ BytecodeEmitter::emitTree(ParseNode* pn, ValueUsage valueUsage /* = ValueUsage:: return false; break; + case PNK_INITIALYIELD: + if (!emitInitialYield(pn)) + return false; + break; + case PNK_YIELD: case PNK_AWAIT: if (!emitYield(pn)) diff --git a/js/src/frontend/BytecodeEmitter.h b/js/src/frontend/BytecodeEmitter.h index 7f2dddfed..08638f48a 100644 --- a/js/src/frontend/BytecodeEmitter.h +++ b/js/src/frontend/BytecodeEmitter.h @@ -607,9 +607,12 @@ struct MOZ_STACK_CLASS BytecodeEmitter MOZ_MUST_USE bool emitFinishIteratorResult(bool done); MOZ_MUST_USE bool iteratorResultShape(unsigned* shape); + MOZ_MUST_USE bool emitGetDotGenerator(); + + MOZ_MUST_USE bool emitInitialYield(ParseNode* pn); MOZ_MUST_USE bool emitYield(ParseNode* pn); MOZ_MUST_USE bool emitYieldOp(JSOp op); - MOZ_MUST_USE bool emitYieldStar(ParseNode* iter, ParseNode* gen); + MOZ_MUST_USE bool emitYieldStar(ParseNode* iter); MOZ_MUST_USE bool emitPropLHS(ParseNode* pn); MOZ_MUST_USE bool emitPropOp(ParseNode* pn, JSOp op); diff --git a/js/src/frontend/FoldConstants.cpp b/js/src/frontend/FoldConstants.cpp index 689fa02b4..16294c4a8 100644 --- a/js/src/frontend/FoldConstants.cpp +++ b/js/src/frontend/FoldConstants.cpp @@ -117,9 +117,10 @@ ContainsHoistedDeclaration(ExclusiveContext* cx, ParseNode* node, bool* result) // These two aren't statements in the spec, but we sometimes insert them // in statement lists anyway. + case PNK_INITIALYIELD: case PNK_YIELD_STAR: case PNK_YIELD: - MOZ_ASSERT(node->isArity(PN_BINARY)); + MOZ_ASSERT(node->isArity(PN_UNARY)); *result = false; return true; @@ -1775,21 +1776,23 @@ Fold(ExclusiveContext* cx, ParseNode** pnp, Parser<FullParseHandler>& parser, bo case PNK_GENEXP: return FoldList(cx, pn, parser, inGenexpLambda); + case PNK_INITIALYIELD: + MOZ_ASSERT(pn->isArity(PN_UNARY)); + MOZ_ASSERT(pn->pn_kid->isKind(PNK_ASSIGN) && + pn->pn_kid->pn_left->isKind(PNK_NAME) && + pn->pn_kid->pn_right->isKind(PNK_GENERATOR)); + return true; + case PNK_YIELD_STAR: - MOZ_ASSERT(pn->isArity(PN_BINARY)); - MOZ_ASSERT(pn->pn_right->isKind(PNK_NAME)); - return Fold(cx, &pn->pn_left, parser, inGenexpLambda); + MOZ_ASSERT(pn->isArity(PN_UNARY)); + return Fold(cx, &pn->pn_kid, parser, inGenexpLambda); case PNK_YIELD: case PNK_AWAIT: - MOZ_ASSERT(pn->isArity(PN_BINARY)); - MOZ_ASSERT(pn->pn_right->isKind(PNK_NAME) || - (pn->pn_right->isKind(PNK_ASSIGN) && - pn->pn_right->pn_left->isKind(PNK_NAME) && - pn->pn_right->pn_right->isKind(PNK_GENERATOR))); - if (!pn->pn_left) + MOZ_ASSERT(pn->isArity(PN_UNARY)); + if (!pn->pn_kid) return true; - return Fold(cx, &pn->pn_left, parser, inGenexpLambda); + return Fold(cx, &pn->pn_kid, parser, inGenexpLambda); case PNK_RETURN: return FoldReturn(cx, pn, parser, inGenexpLambda); diff --git a/js/src/frontend/FullParseHandler.h b/js/src/frontend/FullParseHandler.h index 6ab93f3f9..44694298b 100644 --- a/js/src/frontend/FullParseHandler.h +++ b/js/src/frontend/FullParseHandler.h @@ -440,20 +440,24 @@ class FullParseHandler return true; } - ParseNode* newYieldExpression(uint32_t begin, ParseNode* value, ParseNode* gen, - JSOp op = JSOP_YIELD) { + ParseNode* newInitialYieldExpression(uint32_t begin, ParseNode* gen) { + TokenPos pos(begin, begin + 1); + return new_<UnaryNode>(PNK_INITIALYIELD, JSOP_INITIALYIELD, pos, gen); + } + + ParseNode* newYieldExpression(uint32_t begin, ParseNode* value) { TokenPos pos(begin, value ? value->pn_pos.end : begin + 1); - return new_<BinaryNode>(PNK_YIELD, op, pos, value, gen); + return new_<UnaryNode>(PNK_YIELD, JSOP_YIELD, pos, value); } - ParseNode* newYieldStarExpression(uint32_t begin, ParseNode* value, ParseNode* gen) { + ParseNode* newYieldStarExpression(uint32_t begin, ParseNode* value) { TokenPos pos(begin, value->pn_pos.end); - return new_<BinaryNode>(PNK_YIELD_STAR, JSOP_NOP, pos, value, gen); + return new_<UnaryNode>(PNK_YIELD_STAR, JSOP_NOP, pos, value); } - ParseNode* newAwaitExpression(uint32_t begin, ParseNode* value, ParseNode* gen) { + ParseNode* newAwaitExpression(uint32_t begin, ParseNode* value) { TokenPos pos(begin, value ? value->pn_pos.end : begin + 1); - return new_<BinaryNode>(PNK_AWAIT, JSOP_AWAIT, pos, value, gen); + return new_<UnaryNode>(PNK_AWAIT, JSOP_AWAIT, pos, value); } // Statements @@ -506,8 +510,7 @@ class FullParseHandler if (!genInit) return false; - ParseNode* initialYield = newYieldExpression(yieldPos.begin, nullptr, genInit, - JSOP_INITIALYIELD); + ParseNode* initialYield = newInitialYieldExpression(yieldPos.begin, genInit); if (!initialYield) return false; diff --git a/js/src/frontend/NameFunctions.cpp b/js/src/frontend/NameFunctions.cpp index dc54d0a88..376be7624 100644 --- a/js/src/frontend/NameFunctions.cpp +++ b/js/src/frontend/NameFunctions.cpp @@ -501,24 +501,25 @@ class NameResolver return false; break; + case PNK_INITIALYIELD: + MOZ_ASSERT(cur->pn_kid->isKind(PNK_ASSIGN) && + cur->pn_kid->pn_left->isKind(PNK_NAME) && + cur->pn_kid->pn_right->isKind(PNK_GENERATOR)); + break; + case PNK_YIELD_STAR: - MOZ_ASSERT(cur->isArity(PN_BINARY)); - MOZ_ASSERT(cur->pn_right->isKind(PNK_NAME)); - if (!resolve(cur->pn_left, prefix)) + MOZ_ASSERT(cur->isArity(PN_UNARY)); + if (!resolve(cur->pn_kid, prefix)) return false; break; case PNK_YIELD: case PNK_AWAIT: - MOZ_ASSERT(cur->isArity(PN_BINARY)); - if (cur->pn_left) { - if (!resolve(cur->pn_left, prefix)) + MOZ_ASSERT(cur->isArity(PN_UNARY)); + if (cur->pn_kid) { + if (!resolve(cur->pn_kid, prefix)) return false; } - MOZ_ASSERT(cur->pn_right->isKind(PNK_NAME) || - (cur->pn_right->isKind(PNK_ASSIGN) && - cur->pn_right->pn_left->isKind(PNK_NAME) && - cur->pn_right->pn_right->isKind(PNK_GENERATOR))); break; case PNK_RETURN: diff --git a/js/src/frontend/ParseNode.cpp b/js/src/frontend/ParseNode.cpp index 5fe64e3d3..42ae9451a 100644 --- a/js/src/frontend/ParseNode.cpp +++ b/js/src/frontend/ParseNode.cpp @@ -286,22 +286,24 @@ PushNodeChildren(ParseNode* pn, NodeStack* stack) return PushResult::Recyclable; } - // The left half is the expression being yielded. The right half is - // internal goop: a name reference to the invisible '.generator' local - // variable, or an assignment of a PNK_GENERATOR node to the '.generator' - // local, for a synthesized, prepended initial yield. Yum! + // The child is an assignment of a PNK_GENERATOR node to the + // '.generator' local, for a synthesized, prepended initial yield. + case PNK_INITIALYIELD: { + MOZ_ASSERT(pn->isArity(PN_UNARY)); + MOZ_ASSERT(pn->pn_kid->isKind(PNK_ASSIGN) && + pn->pn_kid->pn_left->isKind(PNK_NAME) && + pn->pn_kid->pn_right->isKind(PNK_GENERATOR)); + stack->push(pn->pn_kid); + return PushResult::Recyclable; + } + + // The child is the expression being yielded. case PNK_YIELD_STAR: case PNK_YIELD: case PNK_AWAIT: { - MOZ_ASSERT(pn->isArity(PN_BINARY)); - MOZ_ASSERT(pn->pn_right); - MOZ_ASSERT(pn->pn_right->isKind(PNK_NAME) || - (pn->pn_right->isKind(PNK_ASSIGN) && - pn->pn_right->pn_left->isKind(PNK_NAME) && - pn->pn_right->pn_right->isKind(PNK_GENERATOR))); - if (pn->pn_left) - stack->push(pn->pn_left); - stack->push(pn->pn_right); + MOZ_ASSERT(pn->isArity(PN_UNARY)); + if (pn->pn_kid) + stack->push(pn->pn_kid); return PushResult::Recyclable; } diff --git a/js/src/frontend/ParseNode.h b/js/src/frontend/ParseNode.h index 1f20f3988..9a435e270 100644 --- a/js/src/frontend/ParseNode.h +++ b/js/src/frontend/ParseNode.h @@ -83,6 +83,7 @@ class ObjectBox; F(THROW) \ F(DEBUGGER) \ F(GENERATOR) \ + F(INITIALYIELD) \ F(YIELD) \ F(YIELD_STAR) \ F(GENEXP) \ @@ -418,8 +419,9 @@ IsTypeofKind(ParseNodeKind kind) * PNK_LEXICALSCOPE scope pn_u.scope.bindings: scope bindings * pn_u.scope.body: scope body * PNK_GENERATOR nullary - * PNK_YIELD, binary pn_left: expr or null; pn_right: generator object - * PNK_YIELD_STAR + * PNK_INITIALYIELD unary pn_kid: generator object + * PNK_YIELD, unary pn_kid: expr or null + * PNK_YIELD_STAR, * PNK_ARRAYCOMP list pn_count: 1 * pn_head: list of 1 element, which is block * enclosing for loop(s) and optionally diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index 406d37725..3ae5890ac 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -6548,29 +6548,6 @@ Parser<ParseHandler>::returnStatement(YieldHandling yieldHandling) template <typename ParseHandler> typename ParseHandler::Node -Parser<ParseHandler>::newYieldExpression(uint32_t begin, typename ParseHandler::Node expr, - bool isYieldStar) -{ - Node generator = newDotGeneratorName(); - if (!generator) - return null(); - if (isYieldStar) - return handler.newYieldStarExpression(begin, expr, generator); - return handler.newYieldExpression(begin, expr, generator); -} - -template <typename ParseHandler> -typename ParseHandler::Node -Parser<ParseHandler>::newAwaitExpression(uint32_t begin, typename ParseHandler::Node expr) -{ - Node generator = newDotGeneratorName(); - if (!generator) - return null(); - return handler.newAwaitExpression(begin, expr, generator); -} - -template <typename ParseHandler> -typename ParseHandler::Node Parser<ParseHandler>::yieldExpression(InHandling inHandling) { MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_YIELD)); @@ -6617,7 +6594,9 @@ Parser<ParseHandler>::yieldExpression(InHandling inHandling) if (!exprNode) return null(); } - return newYieldExpression(begin, exprNode, kind == PNK_YIELD_STAR); + if (kind == PNK_YIELD_STAR) + return handler.newYieldStarExpression(begin, exprNode); + return handler.newYieldExpression(begin, exprNode); } case NotGenerator: @@ -6694,7 +6673,7 @@ Parser<ParseHandler>::yieldExpression(InHandling inHandling) return null(); } - return newYieldExpression(begin, exprNode); + return handler.newYieldExpression(begin, exprNode); } } @@ -8449,7 +8428,7 @@ Parser<ParseHandler>::unaryExpr(YieldHandling yieldHandling, TripledotHandling t if (!kid) return null(); pc->lastAwaitOffset = begin; - return newAwaitExpression(begin, kid); + return handler.newAwaitExpression(begin, kid); } } @@ -8707,7 +8686,7 @@ Parser<ParseHandler>::comprehensionTail(GeneratorKind comprehensionKind) return handler.newArrayPush(begin, bodyExpr); MOZ_ASSERT(comprehensionKind == StarGenerator); - Node yieldExpr = newYieldExpression(begin, bodyExpr); + Node yieldExpr = handler.newYieldExpression(begin, bodyExpr); if (!yieldExpr) return null(); yieldExpr = handler.parenthesize(yieldExpr); diff --git a/js/src/frontend/Parser.h b/js/src/frontend/Parser.h index 33fe345d6..73c2817f4 100644 --- a/js/src/frontend/Parser.h +++ b/js/src/frontend/Parser.h @@ -1110,8 +1110,6 @@ class Parser final : public ParserBase, private JS::AutoGCRooter inline Node newName(PropertyName* name); inline Node newName(PropertyName* name, TokenPos pos); - inline Node newYieldExpression(uint32_t begin, Node expr, bool isYieldStar = false); - inline Node newAwaitExpression(uint32_t begin, Node expr); inline bool abortIfSyntaxParser(); diff --git a/js/src/frontend/SyntaxParseHandler.h b/js/src/frontend/SyntaxParseHandler.h index a604b599f..d919f1354 100644 --- a/js/src/frontend/SyntaxParseHandler.h +++ b/js/src/frontend/SyntaxParseHandler.h @@ -301,9 +301,9 @@ class SyntaxParseHandler MOZ_MUST_USE bool addSpreadProperty(Node literal, uint32_t begin, Node inner) { return true; } MOZ_MUST_USE bool addObjectMethodDefinition(Node literal, Node name, Node fn, JSOp op) { return true; } MOZ_MUST_USE bool addClassMethodDefinition(Node literal, Node name, Node fn, JSOp op, bool isStatic) { return true; } - Node newYieldExpression(uint32_t begin, Node value, Node gen) { return NodeGeneric; } - Node newYieldStarExpression(uint32_t begin, Node value, Node gen) { return NodeGeneric; } - Node newAwaitExpression(uint32_t begin, Node value, Node gen) { return NodeGeneric; } + Node newYieldExpression(uint32_t begin, Node value) { return NodeGeneric; } + Node newYieldStarExpression(uint32_t begin, Node value) { return NodeGeneric; } + Node newAwaitExpression(uint32_t begin, Node value) { return NodeGeneric; } // Statements |