diff options
Diffstat (limited to 'js')
-rw-r--r-- | js/src/builtin/ReflectParse.cpp | 201 | ||||
-rw-r--r-- | js/src/frontend/BytecodeEmitter.cpp | 149 | ||||
-rw-r--r-- | js/src/frontend/BytecodeEmitter.h | 10 | ||||
-rw-r--r-- | js/src/frontend/FoldConstants.cpp | 198 | ||||
-rw-r--r-- | js/src/frontend/FullParseHandler.h | 42 | ||||
-rw-r--r-- | js/src/frontend/NameFunctions.cpp | 107 | ||||
-rw-r--r-- | js/src/frontend/ParseNode.cpp | 86 | ||||
-rw-r--r-- | js/src/frontend/ParseNode.h | 173 | ||||
-rw-r--r-- | js/src/frontend/Parser.cpp | 32 | ||||
-rw-r--r-- | js/src/frontend/Parser.h | 10 | ||||
-rw-r--r-- | js/src/frontend/SyntaxParseHandler.h | 18 | ||||
-rw-r--r-- | js/src/wasm/AsmJS.cpp | 9 |
12 files changed, 560 insertions, 475 deletions
diff --git a/js/src/builtin/ReflectParse.cpp b/js/src/builtin/ReflectParse.cpp index 4c7d7cad8c..e1dad1f4b6 100644 --- a/js/src/builtin/ReflectParse.cpp +++ b/js/src/builtin/ReflectParse.cpp @@ -1806,7 +1806,7 @@ class ASTSerializer bool importSpecifier(ParseNode* pn, MutableHandleValue dst); bool exportDeclaration(ParseNode* pn, MutableHandleValue dst); bool exportSpecifier(ParseNode* pn, MutableHandleValue dst); - bool classDefinition(ParseNode* pn, bool expr, MutableHandleValue dst); + bool classDefinition(ClassNode* pn, bool expr, MutableHandleValue dst); bool optStatement(ParseNode* pn, MutableHandleValue dst) { if (!pn) { @@ -1817,16 +1817,16 @@ class ASTSerializer } bool forInit(ParseNode* pn, MutableHandleValue dst); - bool forIn(ParseNode* loop, ParseNode* head, HandleValue var, HandleValue stmt, + bool forIn(ParseNode* loop, ParseNode* iterExpr, HandleValue var, HandleValue stmt, MutableHandleValue dst); - bool forOf(ParseNode* loop, ParseNode* head, HandleValue var, HandleValue stmt, + bool forOf(ParseNode* loop, ParseNode* iterExpr, HandleValue var, HandleValue stmt, MutableHandleValue dst); bool statement(ParseNode* pn, MutableHandleValue dst); bool blockStatement(ListNode* node, MutableHandleValue dst); bool switchStatement(ParseNode* pn, MutableHandleValue dst); bool switchCase(ParseNode* pn, MutableHandleValue dst); - bool tryStatement(ParseNode* pn, MutableHandleValue dst); - bool catchClause(ParseNode* pn, bool* isGuarded, MutableHandleValue dst); + bool tryStatement(TernaryNode* tryNode, MutableHandleValue dst); + bool catchClause(TernaryNode* clauseNode, bool* isGuarded, MutableHandleValue dst); bool optExpression(ParseNode* pn, MutableHandleValue dst) { if (!pn) { @@ -1874,7 +1874,7 @@ class ASTSerializer bool functionBody(ParseNode* pn, TokenPos* pos, MutableHandleValue dst); bool comprehensionBlock(ParseNode* pn, MutableHandleValue dst); - bool comprehensionIf(ParseNode* pn, MutableHandleValue dst); + bool comprehensionIf(TernaryNode* ifNode, MutableHandleValue dst); bool comprehension(ParseNode* pn, MutableHandleValue dst); bool generatorExpression(ParseNode* pn, MutableHandleValue dst); @@ -2236,7 +2236,7 @@ ASTSerializer::exportDeclaration(ParseNode* pn, MutableHandleValue dst) break; case PNK_CLASS: - if (!classDefinition(kid, false, &decl)) + if (!classDefinition(&kid->as<ClassNode>(), false, &decl)) return false; break; @@ -2321,47 +2321,58 @@ ASTSerializer::switchStatement(ParseNode* pn, MutableHandleValue dst) } bool -ASTSerializer::catchClause(ParseNode* pn, bool* isGuarded, MutableHandleValue dst) +ASTSerializer::catchClause(TernaryNode* clauseNode, bool* isGuarded, MutableHandleValue dst) { - MOZ_ASSERT_IF(pn->pn_kid1, pn->pn_pos.encloses(pn->pn_kid1->pn_pos)); - MOZ_ASSERT_IF(pn->pn_kid2, pn->pn_pos.encloses(pn->pn_kid2->pn_pos)); - MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_kid3->pn_pos)); + ParseNode* patNode = clauseNode->kid1(); + MOZ_ASSERT_IF(patNode, clauseNode->pn_pos.encloses(patNode->pn_pos)); + + ParseNode* condNode = clauseNode->kid2(); + MOZ_ASSERT_IF(condNode, clauseNode->pn_pos.encloses(condNode->pn_pos)); + + ParseNode* bodyNode = clauseNode->kid3(); + MOZ_ASSERT(clauseNode->pn_pos.encloses(bodyNode->pn_pos)); RootedValue var(cx), guard(cx), body(cx); - if (!optPattern(pn->pn_kid1, &var) || - !optExpression(pn->pn_kid2, &guard)) { + if (!optPattern(patNode, &var) || + !optExpression(condNode, &guard)) { return false; } *isGuarded = !guard.isMagic(JS_SERIALIZE_NO_NODE); - return statement(pn->pn_kid3, &body) && - builder.catchClause(var, guard, body, &pn->pn_pos, dst); + return statement(bodyNode, &body) && + builder.catchClause(var, guard, body, &clauseNode->pn_pos, dst); } bool -ASTSerializer::tryStatement(ParseNode* pn, MutableHandleValue dst) +ASTSerializer::tryStatement(TernaryNode* tryNode, MutableHandleValue dst) { - MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_kid1->pn_pos)); - MOZ_ASSERT_IF(pn->pn_kid2, pn->pn_pos.encloses(pn->pn_kid2->pn_pos)); - MOZ_ASSERT_IF(pn->pn_kid3, pn->pn_pos.encloses(pn->pn_kid3->pn_pos)); + ParseNode* bodyNode = tryNode->kid1(); + MOZ_ASSERT(tryNode->pn_pos.encloses(bodyNode->pn_pos)); + + ParseNode* catchNode = tryNode->kid2(); + MOZ_ASSERT_IF(catchNode, tryNode->pn_pos.encloses(catchNode->pn_pos)); + + ParseNode* finallyNode = tryNode->kid3(); + MOZ_ASSERT_IF(finallyNode, tryNode->pn_pos.encloses(finallyNode->pn_pos)); RootedValue body(cx); - if (!statement(pn->pn_kid1, &body)) + if (!statement(bodyNode, &body)) return false; NodeVector guarded(cx); RootedValue unguarded(cx, NullValue()); - if (ListNode* catchList = &pn->pn_kid2->as<ListNode>()) { + if (ListNode* catchList = &catchNode->as<ListNode>()) { if (!guarded.reserve(catchList->count())) return false; - for (ParseNode* next : catchList->contents()) { + for (ParseNode* catchScope : catchList->contents()) { + MOZ_ASSERT(catchScope->isKind(PNK_LEXICALSCOPE)); RootedValue clause(cx); bool isGuarded; - if (!catchClause(next->pn_expr, &isGuarded, &clause)) + if (!catchClause(&catchScope->scopeBody()->as<TernaryNode>(), &isGuarded, &clause)) return false; if (isGuarded) guarded.infallibleAppend(clause); @@ -2371,8 +2382,8 @@ ASTSerializer::tryStatement(ParseNode* pn, MutableHandleValue dst) } RootedValue finally(cx); - return optStatement(pn->pn_kid3, &finally) && - builder.tryStatement(body, guarded, unguarded, finally, &pn->pn_pos, dst); + return optStatement(finallyNode, &finally) && + builder.tryStatement(body, guarded, unguarded, finally, &tryNode->pn_pos, dst); } bool @@ -2390,40 +2401,40 @@ ASTSerializer::forInit(ParseNode* pn, MutableHandleValue dst) } bool -ASTSerializer::forOf(ParseNode* loop, ParseNode* head, HandleValue var, HandleValue stmt, +ASTSerializer::forOf(ParseNode* loop, ParseNode* iterExpr, HandleValue var, HandleValue stmt, MutableHandleValue dst) { RootedValue expr(cx); - return expression(head->pn_kid3, &expr) && + return expression(iterExpr, &expr) && builder.forOfStatement(var, expr, stmt, &loop->pn_pos, dst); } bool -ASTSerializer::forIn(ParseNode* loop, ParseNode* head, HandleValue var, HandleValue stmt, +ASTSerializer::forIn(ParseNode* loop, ParseNode* iterExpr, HandleValue var, HandleValue stmt, MutableHandleValue dst) { RootedValue expr(cx); bool isForEach = loop->pn_iflags & JSITER_FOREACH; - return expression(head->pn_kid3, &expr) && + return expression(iterExpr, &expr) && builder.forInStatement(var, expr, stmt, isForEach, &loop->pn_pos, dst); } bool -ASTSerializer::classDefinition(ParseNode* pn, bool expr, MutableHandleValue dst) +ASTSerializer::classDefinition(ClassNode* pn, bool expr, MutableHandleValue dst) { RootedValue className(cx, MagicValue(JS_SERIALIZE_NO_NODE)); RootedValue heritage(cx); RootedValue classBody(cx); - if (pn->pn_kid1) { - if (!identifier(pn->pn_kid1->as<ClassNames>().innerBinding(), &className)) + if (ClassNames* names = pn->names()) { + if (!identifier(names->innerBinding(), &className)) return false; } - return optExpression(pn->pn_kid2, &heritage) && - statement(pn->pn_kid3, &classBody) && + return optExpression(pn->heritage(), &heritage) && + statement(pn->methodList(), &classBody) && builder.classDefinition(expr, className, heritage, classBody, &pn->pn_pos, dst); } @@ -2467,23 +2478,30 @@ ASTSerializer::statement(ParseNode* pn, MutableHandleValue dst) case PNK_IF: { - MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_kid1->pn_pos)); - MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_kid2->pn_pos)); - MOZ_ASSERT_IF(pn->pn_kid3, pn->pn_pos.encloses(pn->pn_kid3->pn_pos)); + TernaryNode* ifNode = &pn->as<TernaryNode>(); + + ParseNode* testNode = ifNode->kid1(); + MOZ_ASSERT(ifNode->pn_pos.encloses(testNode->pn_pos)); + + ParseNode* consNode = ifNode->kid2(); + MOZ_ASSERT(ifNode->pn_pos.encloses(consNode->pn_pos)); + + ParseNode* altNode = ifNode->kid3(); + MOZ_ASSERT_IF(altNode, ifNode->pn_pos.encloses(altNode->pn_pos)); RootedValue test(cx), cons(cx), alt(cx); - return expression(pn->pn_kid1, &test) && - statement(pn->pn_kid2, &cons) && - optStatement(pn->pn_kid3, &alt) && - builder.ifStatement(test, cons, alt, &pn->pn_pos, dst); + return expression(testNode, &test) && + statement(consNode, &cons) && + optStatement(altNode, &alt) && + builder.ifStatement(test, cons, alt, &ifNode->pn_pos, dst); } case PNK_SWITCH: return switchStatement(pn, dst); case PNK_TRY: - return tryStatement(pn, dst); + return tryStatement(&pn->as<TernaryNode>(), dst); case PNK_WITH: case PNK_WHILE: @@ -2518,11 +2536,16 @@ ASTSerializer::statement(ParseNode* pn, MutableHandleValue dst) MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_left->pn_pos)); MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_right->pn_pos)); - ParseNode* head = pn->pn_left; + TernaryNode* head = &pn->pn_left->as<TernaryNode>(); + + ParseNode* initNode = head->kid1(); + MOZ_ASSERT_IF(initNode, head->pn_pos.encloses(initNode->pn_pos)); + + ParseNode* maybeTest = head->kid2(); + MOZ_ASSERT_IF(maybeTest, head->pn_pos.encloses(maybeTest->pn_pos)); - MOZ_ASSERT_IF(head->pn_kid1, head->pn_pos.encloses(head->pn_kid1->pn_pos)); - MOZ_ASSERT_IF(head->pn_kid2, head->pn_pos.encloses(head->pn_kid2->pn_pos)); - MOZ_ASSERT_IF(head->pn_kid3, head->pn_pos.encloses(head->pn_kid3->pn_pos)); + ParseNode* updateOrIter = head->kid3(); + MOZ_ASSERT_IF(updateOrIter, head->pn_pos.encloses(updateOrIter->pn_pos)); RootedValue stmt(cx); if (!statement(pn->pn_right, &stmt)) @@ -2530,34 +2553,34 @@ ASTSerializer::statement(ParseNode* pn, MutableHandleValue dst) if (head->isKind(PNK_FORIN) || head->isKind(PNK_FOROF)) { RootedValue var(cx); - if (head->pn_kid1->isKind(PNK_LEXICALSCOPE)) { - if (!variableDeclaration(&head->pn_kid1->scopeBody()->as<ListNode>(), true, &var)) + if (initNode->isKind(PNK_LEXICALSCOPE)) { + if (!variableDeclaration(&initNode->scopeBody()->as<ListNode>(), true, &var)) return false; - } else if (!head->pn_kid1->isKind(PNK_VAR) && - !head->pn_kid1->isKind(PNK_LET) && - !head->pn_kid1->isKind(PNK_CONST)) + } else if (!initNode->isKind(PNK_VAR) && + !initNode->isKind(PNK_LET) && + !initNode->isKind(PNK_CONST)) { - if (!pattern(head->pn_kid1, &var)) + if (!pattern(initNode, &var)) return false; } else { - if (!variableDeclaration(&head->pn_kid1->as<ListNode>(), - head->pn_kid1->isKind(PNK_LET) || - head->pn_kid1->isKind(PNK_CONST), + if (!variableDeclaration(&initNode->as<ListNode>(), + initNode->isKind(PNK_LET) || + initNode->isKind(PNK_CONST), &var)) { return false; } } if (head->isKind(PNK_FORIN)) - return forIn(pn, head, var, stmt, dst); - return forOf(pn, head, var, stmt, dst); + return forIn(pn, updateOrIter, var, stmt, dst); + return forOf(pn, updateOrIter, var, stmt, dst); } RootedValue init(cx), test(cx), update(cx); - return forInit(head->pn_kid1, &init) && - optExpression(head->pn_kid2, &test) && - optExpression(head->pn_kid3, &update) && + return forInit(initNode, &init) && + optExpression(maybeTest, &test) && + optExpression(updateOrIter, &update) && builder.forStatement(init, test, update, stmt, &pn->pn_pos, dst); } @@ -2607,7 +2630,7 @@ ASTSerializer::statement(ParseNode* pn, MutableHandleValue dst) return builder.debuggerStatement(&pn->pn_pos, dst); case PNK_CLASS: - return classDefinition(pn, false, dst); + return classDefinition(&pn->as<ClassNode>(), false, dst); case PNK_CLASSMETHODLIST: { @@ -2748,7 +2771,7 @@ ASTSerializer::comprehensionBlock(ParseNode* pn, MutableHandleValue dst) { LOCAL_ASSERT(pn->isArity(PN_BINARY)); - ParseNode* in = pn->pn_left; + TernaryNode* in = &pn->pn_left->as<TernaryNode>(); LOCAL_ASSERT(in && (in->isKind(PNK_FORIN) || in->isKind(PNK_FOROF))); @@ -2756,27 +2779,27 @@ ASTSerializer::comprehensionBlock(ParseNode* pn, MutableHandleValue dst) bool isForOf = in->isKind(PNK_FOROF); ListNode* decl; - if (in->pn_kid1->isKind(PNK_LEXICALSCOPE)) - decl = &in->pn_kid1->pn_expr->as<ListNode>(); + if (in->kid1()->isKind(PNK_LEXICALSCOPE)) + decl = &in->kid1()->pn_expr->as<ListNode>(); else - decl = &in->pn_kid1->as<ListNode>(); + decl = &in->kid1()->as<ListNode>(); MOZ_ASSERT(decl->count() == 1); RootedValue patt(cx), src(cx); return pattern(decl->head(), &patt) && - expression(in->pn_kid3, &src) && + expression(in->kid3(), &src) && builder.comprehensionBlock(patt, src, isForEach, isForOf, &in->pn_pos, dst); } bool -ASTSerializer::comprehensionIf(ParseNode* pn, MutableHandleValue dst) +ASTSerializer::comprehensionIf(TernaryNode* ifNode, MutableHandleValue dst) { - LOCAL_ASSERT(pn->isKind(PNK_IF)); - LOCAL_ASSERT(!pn->pn_kid3); + LOCAL_ASSERT(ifNode->isKind(PNK_IF)); + LOCAL_ASSERT(!ifNode->kid3()); RootedValue patt(cx); - return pattern(pn->pn_kid1, &patt) && - builder.comprehensionIf(patt, &pn->pn_pos, dst); + return pattern(ifNode->kid1(), &patt) && + builder.comprehensionIf(patt, &ifNode->pn_pos, dst); } bool @@ -2799,17 +2822,19 @@ ASTSerializer::comprehension(ParseNode* pn, MutableHandleValue dst) return false; next = next->pn_right; } else if (next->isKind(PNK_IF)) { + TernaryNode* tn = &next->as<TernaryNode>(); if (isLegacy) { MOZ_ASSERT(filter.isMagic(JS_SERIALIZE_NO_NODE)); - if (!optExpression(next->pn_kid1, &filter)) + if (!optExpression(tn->kid1(), &filter)) return false; } else { // ES7 comprehension can contain multiple ComprehensionIfs. RootedValue compif(cx); - if (!comprehensionIf(next, &compif) || !blocks.append(compif)) + if (!comprehensionIf(tn, &compif) || + !blocks.append(compif)) return false; } - next = next->pn_kid2; + next = tn->kid2(); } else { break; } @@ -2842,17 +2867,19 @@ ASTSerializer::generatorExpression(ParseNode* pn, MutableHandleValue dst) return false; next = next->pn_right; } else if (next->isKind(PNK_IF)) { + TernaryNode* tn = &next->as<TernaryNode>(); if (isLegacy) { MOZ_ASSERT(filter.isMagic(JS_SERIALIZE_NO_NODE)); - if (!optExpression(next->pn_kid1, &filter)) + if (!optExpression(tn->kid1(), &filter)) return false; } else { // ES7 comprehension can contain multiple ComprehensionIfs. RootedValue compif(cx); - if (!comprehensionIf(next, &compif) || !blocks.append(compif)) + if (!comprehensionIf(tn, &compif) || + !blocks.append(compif)) return false; } - next = next->pn_kid2; + next = tn->kid2(); } else { break; } @@ -2888,16 +2915,20 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst) case PNK_CONDITIONAL: { - MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_kid1->pn_pos)); - MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_kid2->pn_pos)); - MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_kid3->pn_pos)); + ConditionalExpression* condNode = &pn->as<ConditionalExpression>(); + ParseNode* testNode = condNode->kid1(); + ParseNode* consNode = condNode->kid2(); + ParseNode* altNode = condNode->kid3(); + MOZ_ASSERT(condNode->pn_pos.encloses(testNode->pn_pos)); + MOZ_ASSERT(condNode->pn_pos.encloses(consNode->pn_pos)); + MOZ_ASSERT(condNode->pn_pos.encloses(altNode->pn_pos)); RootedValue test(cx), cons(cx), alt(cx); - return expression(pn->pn_kid1, &test) && - expression(pn->pn_kid2, &cons) && - expression(pn->pn_kid3, &alt) && - builder.conditionalExpression(test, cons, alt, &pn->pn_pos, dst); + return expression(testNode, &test) && + expression(consNode, &cons) && + expression(altNode, &alt) && + builder.conditionalExpression(test, cons, alt, &condNode->pn_pos, dst); } case PNK_COALESCE: @@ -3281,7 +3312,7 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst) } case PNK_CLASS: - return classDefinition(pn, true, dst); + return classDefinition(&pn->as<ClassNode>(), true, dst); case PNK_NEWTARGET: { diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index ffaf99a444..861d0c51d6 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -1322,18 +1322,20 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer) case PNK_IF: case PNK_CONDITIONAL: - MOZ_ASSERT(pn->isArity(PN_TERNARY)); - if (!checkSideEffects(pn->pn_kid1, answer)) + { + TernaryNode* node = &pn->as<TernaryNode>(); + if (!checkSideEffects(node->kid1(), answer)) return false; if (*answer) return true; - if (!checkSideEffects(pn->pn_kid2, answer)) + if (!checkSideEffects(node->kid2(), answer)) return false; if (*answer) return true; - if ((pn = pn->pn_kid3)) + if ((pn = node->kid3())) goto restart; return true; + } // Function calls can invoke non-local code. case PNK_NEW: @@ -1362,7 +1364,7 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer) // the heritage and/or class body (through computed property names) // usually have effects. case PNK_CLASS: - MOZ_ASSERT(pn->isArity(PN_TERNARY)); + MOZ_ASSERT(pn->is<ClassNode>()); *answer = true; return true; @@ -1415,39 +1417,43 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer) return true; case PNK_TRY: - MOZ_ASSERT(pn->isArity(PN_TERNARY)); - if (!checkSideEffects(pn->pn_kid1, answer)) + { + TernaryNode* tryNode = &pn->as<TernaryNode>(); + if (!checkSideEffects(tryNode->kid1(), answer)) return false; if (*answer) return true; - if (ParseNode* catchList = pn->pn_kid2) { + if (ParseNode* catchList = tryNode->kid2()) { MOZ_ASSERT(catchList->isKind(PNK_CATCHLIST)); if (!checkSideEffects(catchList, answer)) return false; if (*answer) return true; } - if (ParseNode* finallyBlock = pn->pn_kid3) { + if (ParseNode* finallyBlock = tryNode->kid3()) { if (!checkSideEffects(finallyBlock, answer)) return false; } return true; + } case PNK_CATCH: - MOZ_ASSERT(pn->isArity(PN_TERNARY)); - if (ParseNode* name = pn->pn_kid1) { - if (!checkSideEffects(name, answer)) + { + TernaryNode* catchNode = &pn->as<TernaryNode>(); + if (ParseNode* binding = catchNode->kid1()) { + if (!checkSideEffects(binding, answer)) return false; if (*answer) return true; } - if (ParseNode* cond = pn->pn_kid2) { + if (ParseNode* cond = catchNode->kid2()) { if (!checkSideEffects(cond, answer)) return false; if (*answer) return true; } - return checkSideEffects(pn->pn_kid3, answer); + return checkSideEffects(catchNode->kid3(), answer); + } case PNK_SWITCH: MOZ_ASSERT(pn->isArity(PN_BINARY)); @@ -4087,7 +4093,7 @@ class EmitLevelManager } /* anonymous namespace */ bool -BytecodeEmitter::emitCatch(ParseNode* pn) +BytecodeEmitter::emitCatch(TernaryNode* catchNode) { // We must be nested under a try-finally statement. TryFinallyControl& controlInfo = innermostNestableControl->as<TryFinallyControl>(); @@ -4100,10 +4106,10 @@ BytecodeEmitter::emitCatch(ParseNode* pn) * Dup the exception object if there is a guard for rethrowing to use * it later when rethrowing or in other catches. */ - if (pn->pn_kid2 && !emit1(JSOP_DUP)) + if (catchNode->kid2() && !emit1(JSOP_DUP)) return false; - ParseNode* pn2 = pn->pn_kid1; + ParseNode* pn2 = catchNode->kid1(); if (!pn2) { // See ES2019 13.15.7 Runtime Semantics: CatchClauseEvaluation // Catch variable was omitted: discard the exception. @@ -4133,8 +4139,8 @@ BytecodeEmitter::emitCatch(ParseNode* pn) // If there is a guard expression, emit it and arrange to jump to the next // catch block if the guard expression is false. - if (pn->pn_kid2) { - if (!emitTree(pn->pn_kid2)) + if (catchNode->kid2()) { + if (!emitTree(catchNode->kid2())) return false; // If the guard expression is false, fall through, pop the block scope, @@ -4171,16 +4177,16 @@ BytecodeEmitter::emitCatch(ParseNode* pn) } /* Emit the catch body. */ - return emitTree(pn->pn_kid3); + return emitTree(catchNode->kid3()); } // Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See the // comment on EmitSwitch. MOZ_NEVER_INLINE bool -BytecodeEmitter::emitTry(ParseNode* pn) +BytecodeEmitter::emitTry(TernaryNode* tryNode) { - ParseNode* catchList = pn->pn_kid2; - ParseNode* finallyNode = pn->pn_kid3; + ParseNode* catchList = tryNode->kid2(); + ParseNode* finallyNode = tryNode->kid3(); TryEmitter::Kind kind; if (catchList) { @@ -4197,7 +4203,7 @@ BytecodeEmitter::emitTry(ParseNode* pn) if (!tryCatch.emitTry()) return false; - if (!emitTree(pn->pn_kid1)) + if (!emitTree(tryNode->kid1())) return false; // If this try has a catch block, emit it. @@ -4256,16 +4262,16 @@ BytecodeEmitter::emitTry(ParseNode* pn) } bool -BytecodeEmitter::emitIf(ParseNode* pn) +BytecodeEmitter::emitIf(TernaryNode* ifNode) { IfEmitter ifThenElse(this); if_again: /* Emit code for the condition before pushing stmtInfo. */ - if (!emitTreeInBranch(pn->pn_kid1)) + if (!emitTreeInBranch(ifNode->kid1())) return false; - ParseNode* elseNode = pn->pn_kid3; + ParseNode* elseNode = ifNode->kid3(); if (elseNode) { if (!ifThenElse.emitThenElse()) return false; @@ -4275,12 +4281,12 @@ BytecodeEmitter::emitIf(ParseNode* pn) } /* Emit code for the then part. */ - if (!emitTreeInBranch(pn->pn_kid2)) + if (!emitTreeInBranch(ifNode->kid2())) return false; if (elseNode) { if (elseNode->isKind(PNK_IF)) { - pn = elseNode; + ifNode = &elseNode->as<TernaryNode>(); if (!ifThenElse.emitElseIf()) return false; @@ -4380,11 +4386,12 @@ BytecodeEmitter::emitLexicalScope(ParseNode* pn) EmitterScope emitterScope(this); ScopeKind kind; - if (body->isKind(PNK_CATCH)) - kind = (!body->pn_kid1 || body->pn_kid1->isKind(PNK_NAME)) ? + if (body->isKind(PNK_CATCH)) { + TernaryNode* catchNode = &body->as<TernaryNode>(); + kind = (!catchNode->kid1() || catchNode->kid1()->isKind(PNK_NAME)) ? ScopeKind::SimpleCatch : ScopeKind::Catch; - else + } else kind = ScopeKind::Lexical; if (!emitterScope.enterLexical(this, kind, pn->scopeBindings())) @@ -4664,16 +4671,15 @@ BytecodeEmitter::emitSpread(bool allowSelfHosted) } bool -BytecodeEmitter::emitInitializeForInOrOfTarget(ParseNode* forHead) +BytecodeEmitter::emitInitializeForInOrOfTarget(TernaryNode* forHead) { MOZ_ASSERT(forHead->isKind(PNK_FORIN) || forHead->isKind(PNK_FOROF)); - MOZ_ASSERT(forHead->isArity(PN_TERNARY)); MOZ_ASSERT(this->stackDepth >= 1, "must have a per-iteration value for initializing"); - ParseNode* target = forHead->pn_kid1; - MOZ_ASSERT(!forHead->pn_kid2); + ParseNode* target = forHead->kid1(); + MOZ_ASSERT(!forHead->kid2()); // If the for-in/of loop didn't have a variable declaration, per-loop // initialization is just assigning the iteration value to a target @@ -4733,9 +4739,8 @@ BytecodeEmitter::emitForOf(ParseNode* forOfLoop, EmitterScope* headLexicalEmitte MOZ_ASSERT(forOfLoop->isKind(PNK_FOR)); MOZ_ASSERT(forOfLoop->isArity(PN_BINARY)); - ParseNode* forOfHead = forOfLoop->pn_left; + TernaryNode* forOfHead = &forOfLoop->pn_left->as<TernaryNode>(); MOZ_ASSERT(forOfHead->isKind(PNK_FOROF)); - MOZ_ASSERT(forOfHead->isArity(PN_TERNARY)); unsigned iflags = forOfLoop->pn_iflags; IteratorKind iterKind = (iflags & JSITER_FORAWAITOF) @@ -4744,7 +4749,7 @@ BytecodeEmitter::emitForOf(ParseNode* forOfLoop, EmitterScope* headLexicalEmitte MOZ_ASSERT_IF(iterKind == IteratorKind::Async, sc->asFunctionBox()); MOZ_ASSERT_IF(iterKind == IteratorKind::Async, sc->asFunctionBox()->isAsync()); - ParseNode* forHeadExpr = forOfHead->pn_kid3; + ParseNode* forHeadExpr = forOfHead->kid3(); // Certain builtins (e.g. Array.from) are implemented in self-hosting // as for-of loops. @@ -4799,7 +4804,7 @@ BytecodeEmitter::emitForOf(ParseNode* forOfLoop, EmitterScope* headLexicalEmitte // recreation each iteration. If a lexical scope exists for the head, // it must be the innermost one. If that scope has closed-over // bindings inducing an environment, recreate the current environment. - DebugOnly<ParseNode*> forOfTarget = forOfHead->pn_kid1; + DebugOnly<ParseNode*> forOfTarget = forOfHead->kid1(); MOZ_ASSERT(forOfTarget->isKind(PNK_LET) || forOfTarget->isKind(PNK_CONST)); MOZ_ASSERT(headLexicalEmitterScope == innermostEmitterScope()); MOZ_ASSERT(headLexicalEmitterScope->scope(this)->kind() == ScopeKind::Lexical); @@ -4909,13 +4914,12 @@ BytecodeEmitter::emitForIn(ParseNode* forInLoop, EmitterScope* headLexicalEmitte MOZ_ASSERT(forInLoop->isArity(PN_BINARY)); MOZ_ASSERT(forInLoop->isOp(JSOP_ITER)); - ParseNode* forInHead = forInLoop->pn_left; + TernaryNode* forInHead = &forInLoop->pn_left->as<TernaryNode>(); MOZ_ASSERT(forInHead->isKind(PNK_FORIN)); - MOZ_ASSERT(forInHead->isArity(PN_TERNARY)); // Annex B: Evaluate the var-initializer expression if present. // |for (var i = initializer in expr) { ... }| - ParseNode* forInTarget = forInHead->pn_kid1; + ParseNode* forInTarget = forInHead->kid1(); if (parser->handler.isDeclarationList(forInTarget)) { ParseNode* decl = parser->handler.singleBindingFromDeclaration(&forInTarget->as<ListNode>()); if (decl->isKind(PNK_NAME)) { @@ -4945,7 +4949,7 @@ BytecodeEmitter::emitForIn(ParseNode* forInLoop, EmitterScope* headLexicalEmitte } // Evaluate the expression being iterated. - ParseNode* expr = forInHead->pn_kid3; + ParseNode* expr = forInHead->kid3(); if (!emitTree(expr)) // EXPR return false; @@ -5058,7 +5062,7 @@ BytecodeEmitter::emitCStyleFor(ParseNode* pn, EmitterScope* headLexicalEmitterSc { LoopControl loopInfo(this, StatementKind::ForLoop); - ParseNode* forHead = pn->pn_left; + TernaryNode* forHead = &pn->pn_left->as<TernaryNode>(); ParseNode* forBody = pn->pn_right; // If the head of this for-loop declared any lexical variables, the parser @@ -5085,7 +5089,7 @@ BytecodeEmitter::emitCStyleFor(ParseNode* pn, EmitterScope* headLexicalEmitterSc // can't reassign consts. This is observable through the Debugger API. (The // ES6 spec also skips cloning the environment in this case.) bool forLoopRequiresFreshening = false; - if (ParseNode* init = forHead->pn_kid1) { + if (ParseNode* init = forHead->kid1()) { // Emit the `init` clause, whether it's an expression or a variable // declaration. (The loop variables were hoisted into an enclosing // scope, but we still need to emit code for the initializers.) @@ -5140,7 +5144,7 @@ BytecodeEmitter::emitCStyleFor(ParseNode* pn, EmitterScope* headLexicalEmitterSc ptrdiff_t tmp = offset(); JumpList jmp; - if (forHead->pn_kid2) { + if (forHead->kid2()) { /* Goto the loop condition, which branches back to iterate. */ if (!emitJump(JSOP_GOTO, &jmp)) return false; @@ -5175,7 +5179,7 @@ BytecodeEmitter::emitCStyleFor(ParseNode* pn, EmitterScope* headLexicalEmitterSc // Check for update code to do before the condition (if any). // The update code may not be executed at all; it needs its own TDZ cache. - if (ParseNode* update = forHead->pn_kid3) { + if (ParseNode* update = forHead->kid3()) { TDZCheckCache tdzCache(this); if (!updateSourceCoordNotes(update->pn_pos.begin)) @@ -5197,15 +5201,15 @@ BytecodeEmitter::emitCStyleFor(ParseNode* pn, EmitterScope* headLexicalEmitterSc ptrdiff_t tmp3 = offset(); - if (forHead->pn_kid2) { + if (forHead->kid2()) { /* Fix up the goto from top to target the loop condition. */ MOZ_ASSERT(jmp.offset >= 0); - if (!emitLoopEntry(forHead->pn_kid2, jmp)) + if (!emitLoopEntry(forHead->kid2(), jmp)) return false; - if (!emitTree(forHead->pn_kid2)) + if (!emitTree(forHead->kid2())) return false; - } else if (!forHead->pn_kid3) { + } else if (!forHead->kid3()) { // If there is no condition clause and no update clause, mark // the loop-ending "goto" with the location of the "for". // This ensures that the debugger will stop on each loop @@ -5223,7 +5227,7 @@ BytecodeEmitter::emitCStyleFor(ParseNode* pn, EmitterScope* headLexicalEmitterSc /* If no loop condition, just emit a loop-closing jump. */ JumpList beq; JumpTarget breakTarget{ -1 }; - if (!emitBackwardJump(forHead->pn_kid2 ? JSOP_IFNE : JSOP_GOTO, top, &beq, &breakTarget)) + if (!emitBackwardJump(forHead->kid2() ? JSOP_IFNE : JSOP_GOTO, top, &beq, &breakTarget)) return false; /* The third note offset helps us find the loop-closing jump. */ @@ -5292,13 +5296,13 @@ BytecodeEmitter::emitComprehensionForOf(ParseNode* pn) { MOZ_ASSERT(pn->isKind(PNK_COMPREHENSIONFOR)); - ParseNode* forHead = pn->pn_left; + TernaryNode* forHead = &pn->pn_left->as<TernaryNode>(); MOZ_ASSERT(forHead->isKind(PNK_FOROF)); - ParseNode* forHeadExpr = forHead->pn_kid3; + ParseNode* forHeadExpr = forHead->kid3(); ParseNode* forBody = pn->pn_right; - ParseNode* loopDecl = forHead->pn_kid1; + ParseNode* loopDecl = forHead->kid1(); bool lexicalScope = false; if (!emitComprehensionForInOrOfVariables(loopDecl, &lexicalScope)) return false; @@ -5436,18 +5440,18 @@ BytecodeEmitter::emitComprehensionForIn(ParseNode* pn) { MOZ_ASSERT(pn->isKind(PNK_COMPREHENSIONFOR)); - ParseNode* forHead = pn->pn_left; + TernaryNode* forHead = &pn->pn_left->as<TernaryNode>(); MOZ_ASSERT(forHead->isKind(PNK_FORIN)); ParseNode* forBody = pn->pn_right; - ParseNode* loopDecl = forHead->pn_kid1; + ParseNode* loopDecl = forHead->kid1(); bool lexicalScope = false; if (loopDecl && !emitComprehensionForInOrOfVariables(loopDecl, &lexicalScope)) return false; // Evaluate the expression to the right of 'in'. - if (!emitTree(forHead->pn_kid3)) + if (!emitTree(forHead->kid3())) return false; /* @@ -5500,7 +5504,7 @@ BytecodeEmitter::emitComprehensionForIn(ParseNode* pn) // Emit code to assign the enumeration value to the left hand side, but // also leave it on the stack. - if (!emitAssignment(forHead->pn_kid2, JSOP_NOP, nullptr)) + if (!emitAssignment(forHead->kid2(), JSOP_NOP, nullptr)) return false; /* The stack should be balanced around the assignment opcode sequence. */ @@ -8458,15 +8462,12 @@ BytecodeEmitter::emitLexicalInitialization(ParseNode* pn) // This follows ES6 14.5.14 (ClassDefinitionEvaluation) and ES6 14.5.15 // (BindingClassDeclarationEvaluation). bool -BytecodeEmitter::emitClass(ParseNode* pn) +BytecodeEmitter::emitClass(ClassNode* classNode) { - ClassNode& classNode = pn->as<ClassNode>(); - - ClassNames* names = classNode.names(); - - ParseNode* heritageExpression = classNode.heritage(); + ClassNames* names = classNode->names(); + ParseNode* heritageExpression = classNode->heritage(); + ListNode* classMethods = classNode->methodList(); - ListNode* classMethods = classNode.methodList(); ParseNode* constructor = nullptr; for (ParseNode* mn : classMethods->contents()) { ClassMethod& method = mn->as<ClassMethod>(); @@ -8487,7 +8488,7 @@ BytecodeEmitter::emitClass(ParseNode* pn) if (names) { tdzCache.emplace(this); emitterScope.emplace(this); - if (!emitterScope->enterLexical(this, ScopeKind::Lexical, classNode.scopeBindings())) + if (!emitterScope->enterLexical(this, ScopeKind::Lexical, classNode->scopeBindings())) return false; } @@ -8525,7 +8526,9 @@ BytecodeEmitter::emitClass(ParseNode* pn) // offsets in the source buffer as source notes so that when we // actually make the constructor during execution, we can give it the // correct toString output. - if (!newSrcNote3(SRC_CLASS_SPAN, ptrdiff_t(pn->pn_pos.begin), ptrdiff_t(pn->pn_pos.end))) + ptrdiff_t classStart = ptrdiff_t(classNode->pn_pos.begin); + ptrdiff_t classEnd = ptrdiff_t(classNode->pn_pos.end); + if (!newSrcNote3(SRC_CLASS_SPAN, classStart, classEnd)) return false; JSAtom *name = names ? names->innerBinding()->pn_atom : cx->names().empty; @@ -8609,7 +8612,7 @@ BytecodeEmitter::emitTree(ParseNode* pn, ValueUsage valueUsage /* = ValueUsage:: break; case PNK_IF: - if (!emitIf(pn)) + if (!emitIf(&pn->as<TernaryNode>())) return false; break; @@ -8654,12 +8657,12 @@ BytecodeEmitter::emitTree(ParseNode* pn, ValueUsage valueUsage /* = ValueUsage:: break; case PNK_TRY: - if (!emitTry(pn)) + if (!emitTry(&pn->as<TernaryNode>())) return false; break; case PNK_CATCH: - if (!emitCatch(pn)) + if (!emitCatch(&pn->as<TernaryNode>())) return false; break; @@ -9017,7 +9020,7 @@ BytecodeEmitter::emitTree(ParseNode* pn, ValueUsage valueUsage /* = ValueUsage:: break; case PNK_CLASS: - if (!emitClass(pn)) + if (!emitClass(&pn->as<ClassNode>())) return false; break; diff --git a/js/src/frontend/BytecodeEmitter.h b/js/src/frontend/BytecodeEmitter.h index e2fb16e224..416c3cf4bc 100644 --- a/js/src/frontend/BytecodeEmitter.h +++ b/js/src/frontend/BytecodeEmitter.h @@ -583,8 +583,8 @@ struct MOZ_STACK_CLASS BytecodeEmitter MOZ_MUST_USE bool emitElemOpBase(JSOp op); MOZ_MUST_USE bool emitElemIncDec(ParseNode* pn); - MOZ_MUST_USE bool emitCatch(ParseNode* pn); - MOZ_MUST_USE bool emitIf(ParseNode* pn); + MOZ_MUST_USE bool emitCatch(TernaryNode* catchNode); + MOZ_MUST_USE bool emitIf(TernaryNode* ifNode); MOZ_MUST_USE bool emitWith(ParseNode* pn); MOZ_NEVER_INLINE MOZ_MUST_USE bool emitLabeledStatement(const LabeledStatement* pn); @@ -592,7 +592,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter MOZ_MUST_USE bool emitLexicalScopeBody(ParseNode* body, EmitLineNumberNote emitLineNote = EMIT_LINENOTE); MOZ_NEVER_INLINE MOZ_MUST_USE bool emitSwitch(SwitchStatement* pn); - MOZ_NEVER_INLINE MOZ_MUST_USE bool emitTry(ParseNode* pn); + MOZ_NEVER_INLINE MOZ_MUST_USE bool emitTry(TernaryNode* tryNode); enum DestructuringFlavor { // Destructuring into a declaration. @@ -778,7 +778,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter MOZ_MUST_USE bool emitForIn(ParseNode* pn, EmitterScope* headLexicalEmitterScope); MOZ_MUST_USE bool emitForOf(ParseNode* pn, EmitterScope* headLexicalEmitterScope); - MOZ_MUST_USE bool emitInitializeForInOrOfTarget(ParseNode* forHead); + MOZ_MUST_USE bool emitInitializeForInOrOfTarget(TernaryNode* forHead); MOZ_MUST_USE bool emitBreak(PropertyName* label); MOZ_MUST_USE bool emitContinue(PropertyName* label); @@ -799,7 +799,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter // iteration count). The stack after iteration will look like |ARRAY INDEX|. MOZ_MUST_USE bool emitSpread(bool allowSelfHosted = false); - MOZ_MUST_USE bool emitClass(ParseNode* pn); + MOZ_MUST_USE bool emitClass(ClassNode* classNode); }; class MOZ_RAII AutoCheckUnstableEmitterScope { diff --git a/js/src/frontend/FoldConstants.cpp b/js/src/frontend/FoldConstants.cpp index 4ad1b4d6fe..ee1d5983aa 100644 --- a/js/src/frontend/FoldConstants.cpp +++ b/js/src/frontend/FoldConstants.cpp @@ -81,7 +81,7 @@ ContainsHoistedDeclaration(ExclusiveContext* cx, ParseNode* node, bool* result) // Similarly to the lexical declarations above, classes cannot add hoisted // declarations case PNK_CLASS: - MOZ_ASSERT(node->isArity(PN_TERNARY)); + MOZ_ASSERT(node->is<ClassNode>()); *result = false; return true; @@ -158,15 +158,14 @@ ContainsHoistedDeclaration(ExclusiveContext* cx, ParseNode* node, bool* result) // if-statement nodes may have hoisted declarations in their consequent // and alternative components. case PNK_IF: { - MOZ_ASSERT(node->isArity(PN_TERNARY)); - - ParseNode* consequent = node->pn_kid2; + TernaryNode* ifNode = &node->as<TernaryNode>(); + ParseNode* consequent = ifNode->kid2(); if (!ContainsHoistedDeclaration(cx, consequent, result)) return false; if (*result) return true; - if ((node = node->pn_kid3)) + if ((node = ifNode->kid3())) goto restart; *result = false; @@ -192,25 +191,25 @@ ContainsHoistedDeclaration(ExclusiveContext* cx, ParseNode* node, bool* result) // try-statements have statements to execute, and one or both of a // catch-list and a finally-block. case PNK_TRY: { - MOZ_ASSERT(node->isArity(PN_TERNARY)); - MOZ_ASSERT(node->pn_kid2 || node->pn_kid3, + TernaryNode* tryNode = &node->as<TernaryNode>(); + MOZ_ASSERT(tryNode->kid2() || tryNode->kid3(), "must have either catch(es) or finally"); - ParseNode* tryBlock = node->pn_kid1; + ParseNode* tryBlock = tryNode->kid1(); if (!ContainsHoistedDeclaration(cx, tryBlock, result)) return false; if (*result) return true; - if (node->pn_kid2) { - if (ListNode* catchList = &node->pn_kid2->as<ListNode>()) { + if (tryNode->kid2()) { + if (ListNode* catchList = &tryNode->kid2()->as<ListNode>()) { for (ParseNode* lexicalScope : catchList->contents()) { MOZ_ASSERT(lexicalScope->isKind(PNK_LEXICALSCOPE)); - ParseNode* catchNode = lexicalScope->scopeBody(); + TernaryNode* catchNode = &lexicalScope->scopeBody()->as<TernaryNode>(); MOZ_ASSERT(catchNode->isKind(PNK_CATCH)); - ParseNode* catchStatements = catchNode->pn_kid3; + ParseNode* catchStatements = catchNode->kid3(); if (!ContainsHoistedDeclaration(cx, catchStatements, result)) return false; if (*result) @@ -219,7 +218,7 @@ ContainsHoistedDeclaration(ExclusiveContext* cx, ParseNode* node, bool* result) } } - if (ParseNode* finallyBlock = node->pn_kid3) + if (ParseNode* finallyBlock = tryNode->kid3()) return ContainsHoistedDeclaration(cx, finallyBlock, result); *result = false; @@ -240,7 +239,7 @@ ContainsHoistedDeclaration(ExclusiveContext* cx, ParseNode* node, bool* result) case PNK_COMPREHENSIONFOR: { MOZ_ASSERT(node->isArity(PN_BINARY)); - ParseNode* loopHead = node->pn_left; + TernaryNode* loopHead = &node->pn_left->as<TernaryNode>(); MOZ_ASSERT(loopHead->isKind(PNK_FORHEAD) || loopHead->isKind(PNK_FORIN) || loopHead->isKind(PNK_FOROF)); @@ -251,9 +250,7 @@ ContainsHoistedDeclaration(ExclusiveContext* cx, ParseNode* node, bool* result) // (at present) hoisted in SpiderMonkey parlance -- but such // hoisting doesn't extend outside of this statement, so it is not // hoisting in the sense meant by ContainsHoistedDeclaration.) - MOZ_ASSERT(loopHead->isArity(PN_TERNARY)); - - ParseNode* init = loopHead->pn_kid1; + ParseNode* init = loopHead->kid1(); if (init && init->isKind(PNK_VAR)) { *result = true; return true; @@ -271,9 +268,7 @@ ContainsHoistedDeclaration(ExclusiveContext* cx, ParseNode* node, bool* result) // // Either way, if |target| contains a declaration, it's |loopHead|'s // first kid. - MOZ_ASSERT(loopHead->isArity(PN_TERNARY)); - - ParseNode* decl = loopHead->pn_kid1; + ParseNode* decl = loopHead->kid1(); if (decl && decl->isKind(PNK_VAR)) { *result = true; return true; @@ -856,19 +851,17 @@ FoldConditional(ExclusiveContext* cx, ParseNode** nodePtr, Parser<FullParseHandl nodePtr = nextNode; nextNode = nullptr; - ParseNode* node = *nodePtr; + TernaryNode* node = &(*nodePtr)->as<TernaryNode>(); MOZ_ASSERT(node->isKind(PNK_CONDITIONAL)); - MOZ_ASSERT(node->isArity(PN_TERNARY)); - - ParseNode*& expr = node->pn_kid1; - if (!FoldCondition(cx, &expr, parser, inGenexpLambda)) + ParseNode** expr = node->unsafeKid1Reference(); + if (!FoldCondition(cx, expr, parser, inGenexpLambda)) return false; - ParseNode*& ifTruthy = node->pn_kid2; - if (!Fold(cx, &ifTruthy, parser, inGenexpLambda)) + ParseNode** ifTruthy = node->unsafeKid2Reference(); + if (!Fold(cx, ifTruthy, parser, inGenexpLambda)) return false; - ParseNode*& ifFalsy = node->pn_kid3; + ParseNode** ifFalsy = node->unsafeKid3Reference(); // If our C?T:F node has F as another ?: node, *iteratively* constant- // fold F *after* folding C and T (and possibly eliminating C and one @@ -877,15 +870,16 @@ FoldConditional(ExclusiveContext* cx, ParseNode** nodePtr, Parser<FullParseHandl // // Conceivably we could instead/also iteratively constant-fold T, if T // were more complex than F. Such an optimization is unimplemented. - if (ifFalsy->isKind(PNK_CONDITIONAL)) { - nextNode = &ifFalsy; + if ((*ifFalsy)->isKind(PNK_CONDITIONAL)) { + MOZ_ASSERT((*ifFalsy)->is<TernaryNode>()); + nextNode = ifFalsy; } else { - if (!Fold(cx, &ifFalsy, parser, inGenexpLambda)) + if (!Fold(cx, ifFalsy, parser, inGenexpLambda)) return false; } // Try to constant-fold based on the condition expression. - Truthiness t = Boolish(expr); + Truthiness t = Boolish(*expr); if (t == Unknown) continue; @@ -893,11 +887,11 @@ FoldConditional(ExclusiveContext* cx, ParseNode** nodePtr, Parser<FullParseHandl ParseNode* replacement; ParseNode* discarded; if (t == Truthy) { - replacement = ifTruthy; - discarded = ifFalsy; + replacement = *ifTruthy; + discarded = *ifFalsy; } else { - replacement = ifFalsy; - discarded = ifTruthy; + replacement = *ifFalsy; + discarded = *ifTruthy; } // Otherwise perform a replacement. This invalidates |nextNode|, so @@ -925,29 +919,28 @@ FoldIf(ExclusiveContext* cx, ParseNode** nodePtr, Parser<FullParseHandler>& pars nodePtr = nextNode; nextNode = nullptr; - ParseNode* node = *nodePtr; + TernaryNode* node = &(*nodePtr)->as<TernaryNode>(); MOZ_ASSERT(node->isKind(PNK_IF)); - MOZ_ASSERT(node->isArity(PN_TERNARY)); - - ParseNode*& expr = node->pn_kid1; - if (!FoldCondition(cx, &expr, parser, inGenexpLambda)) + ParseNode** expr = node->unsafeKid1Reference(); + if (!FoldCondition(cx, expr, parser, inGenexpLambda)) return false; - ParseNode*& consequent = node->pn_kid2; - if (!Fold(cx, &consequent, parser, inGenexpLambda)) + ParseNode** consequent = node->unsafeKid2Reference(); + if (!Fold(cx, consequent, parser, inGenexpLambda)) return false; - ParseNode*& alternative = node->pn_kid3; - if (alternative) { + ParseNode** alternative = node->unsafeKid3Reference(); + if (*alternative) { // If in |if (C) T; else F;| we have |F| as another |if|, // *iteratively* constant-fold |F| *after* folding |C| and |T| (and // possibly completely replacing the whole thing with |T| or |F|); // otherwise fold F normally. Making |nextNode| non-null causes // this loop to run again to fold F. - if (alternative->isKind(PNK_IF)) { - nextNode = &alternative; + if ((*alternative)->isKind(PNK_IF)) { + MOZ_ASSERT((*alternative)->is<TernaryNode>()); + nextNode = alternative; } else { - if (!Fold(cx, &alternative, parser, inGenexpLambda)) + if (!Fold(cx, alternative, parser, inGenexpLambda)) return false; } } @@ -956,7 +949,7 @@ FoldIf(ExclusiveContext* cx, ParseNode** nodePtr, Parser<FullParseHandler>& pars // constant truthiness. Don't eliminate if we have an |if (0)| in // trailing position in a generator expression, as this is a special // form we can't fold away. - Truthiness t = Boolish(expr); + Truthiness t = Boolish(*expr); if (t == Unknown || inGenexpLambda) continue; @@ -965,11 +958,11 @@ FoldIf(ExclusiveContext* cx, ParseNode** nodePtr, Parser<FullParseHandler>& pars ParseNode* replacement; ParseNode* discarded; if (t == Truthy) { - replacement = consequent; - discarded = alternative; + replacement = *consequent; + discarded = *alternative; } else { - replacement = alternative; - discarded = consequent; + replacement = *alternative; + discarded = *consequent; } bool performReplacement = true; @@ -1234,23 +1227,23 @@ FoldReturn(ExclusiveContext* cx, ParseNode* node, Parser<FullParseHandler>& pars } static bool -FoldTry(ExclusiveContext* cx, ParseNode* node, Parser<FullParseHandler>& parser, +FoldTry(ExclusiveContext* cx, TernaryNode* node, Parser<FullParseHandler>& parser, bool inGenexpLambda) { MOZ_ASSERT(node->isKind(PNK_TRY)); - MOZ_ASSERT(node->isArity(PN_TERNARY)); - - ParseNode*& statements = node->pn_kid1; - if (!Fold(cx, &statements, parser, inGenexpLambda)) + ParseNode** statements = node->unsafeKid1Reference(); + if (!Fold(cx, statements, parser, inGenexpLambda)) return false; - if (ParseNode*& catchList = node->pn_kid2) { - if (!Fold(cx, &catchList, parser, inGenexpLambda)) + ParseNode** catchList = node->unsafeKid2Reference(); + if (*catchList) { + if (!Fold(cx, catchList, parser, inGenexpLambda)) return false; } - if (ParseNode*& finally = node->pn_kid3) { - if (!Fold(cx, &finally, parser, inGenexpLambda)) + ParseNode** finally = node->unsafeKid3Reference(); + if (*finally) { + if (!Fold(cx, finally, parser, inGenexpLambda)) return false; } @@ -1258,24 +1251,25 @@ FoldTry(ExclusiveContext* cx, ParseNode* node, Parser<FullParseHandler>& parser, } static bool -FoldCatch(ExclusiveContext* cx, ParseNode* node, Parser<FullParseHandler>& parser, +FoldCatch(ExclusiveContext* cx, TernaryNode* node, Parser<FullParseHandler>& parser, bool inGenexpLambda) { MOZ_ASSERT(node->isKind(PNK_CATCH)); - MOZ_ASSERT(node->isArity(PN_TERNARY)); - if (ParseNode*& declPattern = node->pn_kid1) { - if (!Fold(cx, &declPattern, parser, inGenexpLambda)) + ParseNode** binding = node->unsafeKid1Reference(); + if (*binding) { + if (!Fold(cx, binding, parser, inGenexpLambda)) return false; } - if (ParseNode*& cond = node->pn_kid2) { - if (!FoldCondition(cx, &cond, parser, inGenexpLambda)) + ParseNode** cond = node->unsafeKid2Reference(); + if (*cond) { + if (!FoldCondition(cx, cond, parser, inGenexpLambda)) return false; } - if (ParseNode*& statements = node->pn_kid3) { - if (!Fold(cx, &statements, parser, inGenexpLambda)) + if (ParseNode** statements = node->unsafeKid3Reference()) { + if (!Fold(cx, statements, parser, inGenexpLambda)) return false; } @@ -1283,24 +1277,24 @@ FoldCatch(ExclusiveContext* cx, ParseNode* node, Parser<FullParseHandler>& parse } static bool -FoldClass(ExclusiveContext* cx, ParseNode* node, Parser<FullParseHandler>& parser, +FoldClass(ExclusiveContext* cx, ClassNode* node, Parser<FullParseHandler>& parser, bool inGenexpLambda) { MOZ_ASSERT(node->isKind(PNK_CLASS)); - MOZ_ASSERT(node->isArity(PN_TERNARY)); - - if (ParseNode*& classNames = node->pn_kid1) { - if (!Fold(cx, &classNames, parser, inGenexpLambda)) + ParseNode** classNames = node->unsafeKid1Reference(); + if (*classNames) { + if (!Fold(cx, classNames, parser, inGenexpLambda)) return false; } - if (ParseNode*& heritage = node->pn_kid2) { - if (!Fold(cx, &heritage, parser, inGenexpLambda)) + ParseNode** heritage = node->unsafeKid2Reference(); + if (*heritage) { + if (!Fold(cx, heritage, parser, inGenexpLambda)) return false; } - ParseNode*& body = node->pn_kid3; - return Fold(cx, &body, parser, inGenexpLambda); + ParseNode** body = node->unsafeKid3Reference(); + return Fold(cx, body, parser, inGenexpLambda); } static bool @@ -1580,41 +1574,41 @@ FoldArguments(ExclusiveContext* cx, ListNode* node, Parser<FullParseHandler>& pa } static bool -FoldForInOrOf(ExclusiveContext* cx, ParseNode* node, Parser<FullParseHandler>& parser, +FoldForInOrOf(ExclusiveContext* cx, TernaryNode* node, Parser<FullParseHandler>& parser, bool inGenexpLambda) { MOZ_ASSERT(node->isKind(PNK_FORIN) || node->isKind(PNK_FOROF)); - MOZ_ASSERT(node->isArity(PN_TERNARY)); - MOZ_ASSERT(!node->pn_kid2); + MOZ_ASSERT(!node->kid2()); - return Fold(cx, &node->pn_kid1, parser, inGenexpLambda) && - Fold(cx, &node->pn_kid3, parser, inGenexpLambda); + return Fold(cx, node->unsafeKid1Reference(), parser, inGenexpLambda) && + Fold(cx, node->unsafeKid3Reference(), parser, inGenexpLambda); } static bool -FoldForHead(ExclusiveContext* cx, ParseNode* node, Parser<FullParseHandler>& parser, +FoldForHead(ExclusiveContext* cx, TernaryNode* node, Parser<FullParseHandler>& parser, bool inGenexpLambda) { MOZ_ASSERT(node->isKind(PNK_FORHEAD)); - MOZ_ASSERT(node->isArity(PN_TERNARY)); - - if (ParseNode*& init = node->pn_kid1) { - if (!Fold(cx, &init, parser, inGenexpLambda)) + ParseNode** init = node->unsafeKid1Reference(); + if (*init) { + if (!Fold(cx, init, parser, inGenexpLambda)) return false; } - if (ParseNode*& test = node->pn_kid2) { - if (!FoldCondition(cx, &test, parser, inGenexpLambda)) + ParseNode** test = node->unsafeKid2Reference(); + if (*test) { + if (!FoldCondition(cx, test, parser, inGenexpLambda)) return false; - if (test->isKind(PNK_TRUE)) { - parser.freeTree(test); - test = nullptr; + if ((*test)->isKind(PNK_TRUE)) { + parser.freeTree(*test); + *test = nullptr; } } - if (ParseNode*& update = node->pn_kid3) { - if (!Fold(cx, &update, parser, inGenexpLambda)) + ParseNode** update = node->unsafeKid3Reference(); + if (*update) { + if (!Fold(cx, update, parser, inGenexpLambda)) return false; } @@ -1709,9 +1703,11 @@ Fold(ExclusiveContext* cx, ParseNode** pnp, Parser<FullParseHandler>& parser, bo return FoldDeleteProperty(cx, pn, parser, inGenexpLambda); case PNK_CONDITIONAL: + MOZ_ASSERT((*pnp)->is<TernaryNode>()); return FoldConditional(cx, pnp, parser, inGenexpLambda); case PNK_IF: + MOZ_ASSERT((*pnp)->is<TernaryNode>()); return FoldIf(cx, pnp, parser, inGenexpLambda); case PNK_NOT: @@ -1830,13 +1826,13 @@ Fold(ExclusiveContext* cx, ParseNode** pnp, Parser<FullParseHandler>& parser, bo return FoldReturn(cx, pn, parser, inGenexpLambda); case PNK_TRY: - return FoldTry(cx, pn, parser, inGenexpLambda); + return FoldTry(cx, &pn->as<TernaryNode>(), parser, inGenexpLambda); case PNK_CATCH: - return FoldCatch(cx, pn, parser, inGenexpLambda); + return FoldCatch(cx, &pn->as<TernaryNode>(), parser, inGenexpLambda); case PNK_CLASS: - return FoldClass(cx, pn, parser, inGenexpLambda); + return FoldClass(cx, &pn->as<ClassNode>(), parser, inGenexpLambda); case PNK_OPTELEM: case PNK_ELEM: @@ -1926,10 +1922,10 @@ Fold(ExclusiveContext* cx, ParseNode** pnp, Parser<FullParseHandler>& parser, bo case PNK_FORIN: case PNK_FOROF: - return FoldForInOrOf(cx, pn, parser, inGenexpLambda); + return FoldForInOrOf(cx, &pn->as<TernaryNode>(), parser, inGenexpLambda); case PNK_FORHEAD: - return FoldForHead(cx, pn, parser, inGenexpLambda); + return FoldForHead(cx, &pn->as<TernaryNode>(), parser, inGenexpLambda); case PNK_LABEL: MOZ_ASSERT(pn->isArity(PN_NAME)); diff --git a/js/src/frontend/FullParseHandler.h b/js/src/frontend/FullParseHandler.h index 249b0aa276..0ce3f86567 100644 --- a/js/src/frontend/FullParseHandler.h +++ b/js/src/frontend/FullParseHandler.h @@ -218,7 +218,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) return new_<RegExpLiteral>(objbox, pos); } - ParseNode* newConditional(ParseNode* cond, ParseNode* thenExpr, ParseNode* elseExpr) { + ConditionalExpressionType newConditional(Node cond, Node thenExpr, Node elseExpr) { return new_<ConditionalExpression>(cond, thenExpr, elseExpr); } @@ -372,9 +372,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) return literal; } - ParseNode* newClass(ParseNode* name, ParseNode* heritage, ParseNode* methodBlock, - const TokenPos& pos) - { + ClassNodeType newClass(Node name, Node heritage, Node methodBlock, const TokenPos& pos) { return new_<ClassNode>(name, heritage, methodBlock, pos); } ListNodeType newClassMethodList(uint32_t begin) { @@ -606,14 +604,12 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) return new_<UnaryNode>(PNK_SEMI, JSOP_NOP, TokenPos(expr->pn_pos.begin, end), expr); } - ParseNode* newIfStatement(uint32_t begin, ParseNode* cond, ParseNode* thenBranch, - ParseNode* elseBranch) - { - ParseNode* pn = new_<TernaryNode>(PNK_IF, JSOP_NOP, cond, thenBranch, elseBranch); - if (!pn) + TernaryNodeType newIfStatement(uint32_t begin, Node cond, Node thenBranch, Node elseBranch) { + TernaryNode* node = new_<TernaryNode>(PNK_IF, JSOP_NOP, cond, thenBranch, elseBranch); + if (!node) return null(); - pn->pn_pos.begin = begin; - return pn; + node->pn_pos.begin = begin; + return node; } ParseNode* newDoWhileStatement(ParseNode* body, ParseNode* cond, const TokenPos& pos) { @@ -625,9 +621,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) return new_<BinaryNode>(PNK_WHILE, JSOP_NOP, pos, cond, body); } - ParseNode* newForStatement(uint32_t begin, ParseNode* forHead, ParseNode* body, - unsigned iflags) - { + Node newForStatement(uint32_t begin, TernaryNodeType forHead, Node body, unsigned iflags) { /* A FOR node is binary, left is loop control and right is the body. */ JSOp op = forHead->isKind(PNK_FORIN) ? JSOP_ITER : JSOP_NOP; BinaryNode* pn = new_<BinaryNode>(PNK_FOR, op, TokenPos(begin, body->pn_pos.end), @@ -638,7 +632,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) return pn; } - ParseNode* newComprehensionFor(uint32_t begin, ParseNode* forHead, ParseNode* body) { + Node newComprehensionFor(uint32_t begin, TernaryNodeType forHead, Node body) { // A PNK_COMPREHENSIONFOR node is binary: left is loop control, right // is the body. MOZ_ASSERT(forHead->isKind(PNK_FORIN) || forHead->isKind(PNK_FOROF)); @@ -656,14 +650,12 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) return new_<ListNode>(PNK_LET, JSOP_NOP, kid); } - ParseNode* newForHead(ParseNode* init, ParseNode* test, ParseNode* update, - const TokenPos& pos) - { + TernaryNodeType newForHead(Node init, Node test, Node update, const TokenPos& pos) { return new_<TernaryNode>(PNK_FORHEAD, JSOP_NOP, init, test, update, pos); } - ParseNode* newForInOrOfHead(ParseNodeKind kind, ParseNode* target, ParseNode* iteratedExpr, - const TokenPos& pos) + TernaryNodeType newForInOrOfHead(ParseNodeKind kind, Node target, Node iteratedExpr, + const TokenPos& pos) { MOZ_ASSERT(kind == PNK_FORIN || kind == PNK_FOROF); return new_<TernaryNode>(kind, JSOP_NOP, target, nullptr, iteratedExpr, pos); @@ -707,8 +699,8 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) return new_<UnaryNode>(PNK_THROW, JSOP_THROW, pos, expr); } - ParseNode* newTryStatement(uint32_t begin, ParseNode* body, ListNodeType catchList, - ParseNode* finallyBlock) { + TernaryNodeType newTryStatement(uint32_t begin, Node body, ListNodeType catchList, + Node finallyBlock) { TokenPos pos(begin, (finallyBlock ? finallyBlock : catchList)->pn_pos.end); return new_<TernaryNode>(PNK_TRY, JSOP_NOP, body, catchList, finallyBlock, pos); } @@ -738,7 +730,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) } inline MOZ_MUST_USE bool addCatchBlock(ListNodeType catchList, ParseNode* lexicalScope, - ParseNode* catchName, ParseNode* catchGuard, + ParseNode* catchBinding, ParseNode* catchGuard, ParseNode* catchBody); inline MOZ_MUST_USE bool setLastFunctionFormalParameterDefault(ParseNode* funcpn, @@ -1023,9 +1015,9 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) inline bool FullParseHandler::addCatchBlock(ListNodeType catchList, ParseNode* lexicalScope, - ParseNode* catchName, ParseNode* catchGuard, ParseNode* catchBody) + ParseNode* catchBinding, ParseNode* catchGuard, ParseNode* catchBody) { - ParseNode* catchpn = newTernary(PNK_CATCH, catchName, catchGuard, catchBody); + ParseNode* catchpn = newTernary(PNK_CATCH, catchBinding, catchGuard, catchBody); if (!catchpn) return false; catchList->append(lexicalScope); diff --git a/js/src/frontend/NameFunctions.cpp b/js/src/frontend/NameFunctions.cpp index 1b981876c2..26ea434c89 100644 --- a/js/src/frontend/NameFunctions.cpp +++ b/js/src/frontend/NameFunctions.cpp @@ -545,15 +545,16 @@ class NameResolver break; // Ternary nodes with three expression children. - case PNK_CONDITIONAL: - MOZ_ASSERT(cur->isArity(PN_TERNARY)); - if (!resolve(cur->pn_kid1, prefix)) + case PNK_CONDITIONAL: { + TernaryNode* condNode = &cur->as<TernaryNode>(); + if (!resolve(condNode->kid1(), prefix)) return false; - if (!resolve(cur->pn_kid2, prefix)) + if (!resolve(condNode->kid2(), prefix)) return false; - if (!resolve(cur->pn_kid3, prefix)) + if (!resolve(condNode->kid3(), prefix)) return false; break; + } // The first part of a for-in/of is the declaration in the loop (or // null if no declaration). The latter two parts are the location @@ -562,107 +563,115 @@ class NameResolver // computed property names, and possibly through [deprecated!] // initializers) also contain functions to name. case PNK_FORIN: - case PNK_FOROF: - MOZ_ASSERT(cur->isArity(PN_TERNARY)); - if (ParseNode* decl = cur->pn_kid1) { + case PNK_FOROF: { + TernaryNode* forHead = &cur->as<TernaryNode>(); + if (ParseNode* decl = forHead->kid1()) { if (!resolve(decl, prefix)) return false; } - if (!resolve(cur->pn_kid2, prefix)) - return false; - if (!resolve(cur->pn_kid3, prefix)) + MOZ_ASSERT(!forHead->kid2()); + if (!resolve(forHead->kid3(), prefix)) return false; break; + } // Every part of a for(;;) head may contain a function needing name // resolution. - case PNK_FORHEAD: - MOZ_ASSERT(cur->isArity(PN_TERNARY)); - if (ParseNode* init = cur->pn_kid1) { + case PNK_FORHEAD: { + TernaryNode* forHead = &cur->as<TernaryNode>(); + if (ParseNode* init = forHead->kid1()) { if (!resolve(init, prefix)) return false; } - if (ParseNode* cond = cur->pn_kid2) { + if (ParseNode* cond = forHead->kid2()) { if (!resolve(cond, prefix)) return false; } - if (ParseNode* step = cur->pn_kid3) { - if (!resolve(step, prefix)) + if (ParseNode* update = forHead->kid3()) { + if (!resolve(update, prefix)) return false; } break; + } // The first child of a class is a pair of names referring to it, // inside and outside the class. The second is the class's heritage, // if any. The third is the class body. - case PNK_CLASS: - MOZ_ASSERT(cur->isArity(PN_TERNARY)); - MOZ_ASSERT_IF(cur->pn_kid1, cur->pn_kid1->isKind(PNK_CLASSNAMES)); - MOZ_ASSERT_IF(cur->pn_kid1, cur->pn_kid1->isArity(PN_BINARY)); - MOZ_ASSERT_IF(cur->pn_kid1 && cur->pn_kid1->pn_left, - cur->pn_kid1->pn_left->isKind(PNK_NAME)); - MOZ_ASSERT_IF(cur->pn_kid1 && cur->pn_kid1->pn_left, - !cur->pn_kid1->pn_left->expr()); - MOZ_ASSERT_IF(cur->pn_kid1, cur->pn_kid1->pn_right->isKind(PNK_NAME)); - MOZ_ASSERT_IF(cur->pn_kid1, !cur->pn_kid1->pn_right->expr()); - if (cur->pn_kid2) { - if (!resolve(cur->pn_kid2, prefix)) + case PNK_CLASS: { + ClassNode* classNode = &cur->as<ClassNode>(); +#ifdef DEBUG + if (classNode->names()) { + ParseNode* name = classNode->names(); + MOZ_ASSERT(name->isKind(PNK_CLASSNAMES)); + MOZ_ASSERT(name->isArity(PN_BINARY)); + MOZ_ASSERT_IF(name->pn_left, name->pn_left->isKind(PNK_NAME)); + MOZ_ASSERT_IF(name->pn_left, !name->pn_left->expr()); + MOZ_ASSERT(name->pn_right->isKind(PNK_NAME)); + MOZ_ASSERT(!name->pn_right->expr()); + } +#endif + if (ParseNode* heritage = classNode->heritage()) { + if (!resolve(heritage, prefix)) return false; } - if (!resolve(cur->pn_kid3, prefix)) + if (!resolve(classNode->methodList(), prefix)) return false; break; + } // The condition and consequent are non-optional, but the alternative // might be omitted. - case PNK_IF: - MOZ_ASSERT(cur->isArity(PN_TERNARY)); - if (!resolve(cur->pn_kid1, prefix)) + case PNK_IF: { + TernaryNode* ifNode = &cur->as<TernaryNode>(); + if (!resolve(ifNode->kid1(), prefix)) return false; - if (!resolve(cur->pn_kid2, prefix)) + if (!resolve(ifNode->kid2(), prefix)) return false; - if (cur->pn_kid3) { - if (!resolve(cur->pn_kid3, prefix)) + if (ParseNode* alternative = ifNode->kid3()) { + if (!resolve(alternative, prefix)) return false; } break; + } // The statements in the try-block are mandatory. The catch-blocks // and finally block are optional (but at least one or the other must // be present). - case PNK_TRY: - MOZ_ASSERT(cur->isArity(PN_TERNARY)); - if (!resolve(cur->pn_kid1, prefix)) + case PNK_TRY: { + TernaryNode* tryNode = &cur->as<TernaryNode>(); + if (!resolve(tryNode->kid1(), prefix)) return false; - MOZ_ASSERT(cur->pn_kid2 || cur->pn_kid3); - if (ParseNode* catchList = cur->pn_kid2) { + MOZ_ASSERT(tryNode->kid2() || tryNode->kid3()); + if (ParseNode* catchList = tryNode->kid2()) { MOZ_ASSERT(catchList->isKind(PNK_CATCHLIST)); if (!resolve(catchList, prefix)) return false; } - if (ParseNode* finallyBlock = cur->pn_kid3) { + if (ParseNode* finallyBlock = tryNode->kid3()) { if (!resolve(finallyBlock, prefix)) return false; } break; + } // The first child, the catch-pattern, may contain functions via // computed property names. The optional catch-conditions may // contain any expression. The catch statements, of course, may // contain arbitrary expressions. - case PNK_CATCH: - MOZ_ASSERT(cur->isArity(PN_TERNARY)); - if (cur->pn_kid1) { - if (!resolve(cur->pn_kid1, prefix)) + case PNK_CATCH: { + TernaryNode* catchNode = &cur->as<TernaryNode>(); + if (ParseNode* patNode = catchNode->kid1()) { + if (!resolve(patNode, prefix)) return false; } - if (cur->pn_kid2) { - if (!resolve(cur->pn_kid2, prefix)) + if (ParseNode* condNode = catchNode->kid2()) { + if (!resolve(condNode, prefix)) return false; } - if (!resolve(cur->pn_kid3, prefix)) + if (!resolve(catchNode->kid3(), prefix)) return false; break; + } // Nodes with arbitrary-expression children. case PNK_COALESCE: diff --git a/js/src/frontend/ParseNode.cpp b/js/src/frontend/ParseNode.cpp index 218b08ef48..97ddbc482b 100644 --- a/js/src/frontend/ParseNode.cpp +++ b/js/src/frontend/ParseNode.cpp @@ -349,10 +349,10 @@ PushNodeChildren(ParseNode* pn, NodeStack* stack) // Ternary nodes with all children non-null. case PNK_CONDITIONAL: { - MOZ_ASSERT(pn->isArity(PN_TERNARY)); - stack->push(pn->pn_kid1); - stack->push(pn->pn_kid2); - stack->push(pn->pn_kid3); + TernaryNode* tn = &pn->as<TernaryNode>(); + stack->push(tn->kid1()); + stack->push(tn->kid2()); + stack->push(tn->kid3()); return PushResult::Recyclable; } @@ -363,57 +363,57 @@ PushNodeChildren(ParseNode* pn, NodeStack* stack) // p|, the second child is null, and the third child is |obj|. case PNK_FORIN: case PNK_FOROF: { - MOZ_ASSERT(pn->isArity(PN_TERNARY)); - MOZ_ASSERT(!pn->pn_kid2); - stack->push(pn->pn_kid1); - stack->push(pn->pn_kid3); + TernaryNode* tn = &pn->as<TernaryNode>(); + MOZ_ASSERT(!tn->kid2()); + stack->push(tn->kid1()); + stack->push(tn->kid3()); return PushResult::Recyclable; } // for (;;) nodes have one child per optional component of the loop head. case PNK_FORHEAD: { - MOZ_ASSERT(pn->isArity(PN_TERNARY)); - if (pn->pn_kid1) - stack->push(pn->pn_kid1); - if (pn->pn_kid2) - stack->push(pn->pn_kid2); - if (pn->pn_kid3) - stack->push(pn->pn_kid3); + TernaryNode* tn = &pn->as<TernaryNode>(); + if (tn->kid1()) + stack->push(tn->kid1()); + if (tn->kid2()) + stack->push(tn->kid2()); + if (tn->kid3()) + stack->push(tn->kid3()); return PushResult::Recyclable; } // classes might have an optional node for the heritage, as well as the names case PNK_CLASS: { - MOZ_ASSERT(pn->isArity(PN_TERNARY)); - if (pn->pn_kid1) - stack->push(pn->pn_kid1); - if (pn->pn_kid2) - stack->push(pn->pn_kid2); - stack->push(pn->pn_kid3); + TernaryNode* tn = &pn->as<TernaryNode>(); + if (tn->kid1()) + stack->push(tn->kid1()); + if (tn->kid2()) + stack->push(tn->kid2()); + stack->push(tn->kid3()); return PushResult::Recyclable; } // if-statement nodes have condition and consequent children and a // possibly-null alternative. case PNK_IF: { - MOZ_ASSERT(pn->isArity(PN_TERNARY)); - stack->push(pn->pn_kid1); - stack->push(pn->pn_kid2); - if (pn->pn_kid3) - stack->push(pn->pn_kid3); + TernaryNode* tn = &pn->as<TernaryNode>(); + stack->push(tn->kid1()); + stack->push(tn->kid2()); + if (tn->kid3()) + stack->push(tn->kid3()); return PushResult::Recyclable; } // try-statements have statements to execute, and one or both of a // catch-list and a finally-block. case PNK_TRY: { - MOZ_ASSERT(pn->isArity(PN_TERNARY)); - MOZ_ASSERT(pn->pn_kid2 || pn->pn_kid3); - stack->push(pn->pn_kid1); - if (pn->pn_kid2) - stack->push(pn->pn_kid2); - if (pn->pn_kid3) - stack->push(pn->pn_kid3); + TernaryNode* tn = &pn->as<TernaryNode>(); + MOZ_ASSERT(tn->kid2() || tn->kid3()); + stack->push(tn->kid1()); + if (tn->kid2()) + stack->push(tn->kid2()); + if (tn->kid3()) + stack->push(tn->kid3()); return PushResult::Recyclable; } @@ -422,12 +422,12 @@ PushNodeChildren(ParseNode* pn, NodeStack* stack) // |<cond>| in SpiderMonkey's |catch (e if <cond>)| extension), and // third kid as the statements in the catch block. case PNK_CATCH: { - MOZ_ASSERT(pn->isArity(PN_TERNARY)); - if (pn->pn_kid1) - stack->push(pn->pn_kid1); - if (pn->pn_kid2) - stack->push(pn->pn_kid2); - stack->push(pn->pn_kid3); + TernaryNode* tn = &pn->as<TernaryNode>(); + if (tn->kid1()) + stack->push(tn->kid1()); + if (tn->kid2()) + stack->push(tn->kid2()); + stack->push(tn->kid3()); return PushResult::Recyclable; } @@ -663,7 +663,7 @@ ParseNode::dump(int indent) ((BinaryNode*) this)->dump(indent); break; case PN_TERNARY: - ((TernaryNode*) this)->dump(indent); + as<TernaryNode>().dump(indent); break; case PN_CODE: ((CodeNode*) this)->dump(indent); @@ -757,11 +757,11 @@ TernaryNode::dump(int indent) const char* name = parseNodeNames[getKind()]; fprintf(stderr, "(%s ", name); indent += strlen(name) + 2; - DumpParseTree(pn_kid1, indent); + DumpParseTree(kid1(), indent); IndentNewLine(indent); - DumpParseTree(pn_kid2, indent); + DumpParseTree(kid2(), indent); IndentNewLine(indent); - DumpParseTree(pn_kid3, indent); + DumpParseTree(kid3(), indent); fprintf(stderr, ")"); } diff --git a/js/src/frontend/ParseNode.h b/js/src/frontend/ParseNode.h index a19e4c3389..ebc29ef851 100644 --- a/js/src/frontend/ParseNode.h +++ b/js/src/frontend/ParseNode.h @@ -241,16 +241,31 @@ IsTypeofKind(ParseNodeKind kind) * * Return for expression closure * count: number of formal parameters + 1 * PNK_SPREAD unary pn_kid: expression being spread + * PNK_CLASS (ClassNode) + * kid1: PNK_CLASSNAMES for class name. can be null for anonymous class. + * kid2: expression after `extends`. null if no expression + * kid3: either of + * * PNK_CLASSMETHODLIST, if anonymous class + * * PNK_LEXICALSCOPE which contains PNK_CLASSMETHODLIST as scopeBody, + * if named class + * PNK_CLASSNAMES (ClassNames) + * pn_left: Name node for outer binding. can be null + * pn_right: Name node for inner binding + * PNK_CLASSMETHODLIST (ListNode) + * head: list of N PNK_CLASSMETHOD nodes + * count: N >= 0 + * PNK_CLASSMETHOD (ClassMethod) + * name: propertyName + * method: methodDefinition * * <Statements> * PNK_STATEMENTLIST (ListNode) * head: list of N statements * count: N >= 0 - * PNK_IF ternary pn_kid1: cond, pn_kid2: then, pn_kid3: else or null. - * In body of a comprehension or desugared generator - * expression, pn_kid2 is PNK_YIELD, PNK_ARRAYPUSH, - * or (if the push was optimized away) empty - * PNK_STATEMENTLIST. + * PNK_IF (TernaryNode) In body of a comprehension or desugared PNK_GENEXP: + * kid1: cond + * kid2: then = PNK_YIELD, PNK_ARRAYPUSH, (empty) PNK_STATEMENTLIST + * kid3: else or null * PNK_SWITCH binary pn_left: discriminant * pn_right: PNK_LEXICALSCOPE node that contains the list * of PNK_CASE nodes, with at most one default node. @@ -266,26 +281,30 @@ IsTypeofKind(ParseNodeKind kind) * pn_right: body * PNK_COMPREHENSIONFOR pn_left: either PNK_FORIN or PNK_FOROF * binary pn_right: body - * PNK_FORIN ternary pn_kid1: declaration or expression to left of 'in' - * pn_kid2: null - * pn_kid3: object expr to right of 'in' - * PNK_FOROF ternary pn_kid1: declaration or expression to left of 'of' - * pn_kid2: null - * pn_kid3: expr to right of 'of' - * PNK_FORHEAD ternary pn_kid1: init expr before first ';' or nullptr - * pn_kid2: cond expr before second ';' or nullptr - * pn_kid3: update expr after second ';' or nullptr - * PNK_THROW unary pn_op: JSOP_THROW, pn_kid: exception - * PNK_TRY ternary pn_kid1: try block - * pn_kid2: null or PNK_CATCHLIST list - * pn_kid3: null or finally block + * PNK_FORIN (TernaryNode) + * kid1: declaration or expression to left of 'in' + * kid2: null + * kid3: object expr to right of 'in' + * PNK_FOROF (TernaryNode) + * kid1: declaration or expression to left of 'of' + * kid2: null + * kid3: expr to right of 'of' + * PNK_FORHEAD (TernaryNode) + * kid1: init expr before first ';' or nullptr + * kid2: cond expr before second ';' or nullptr + * kid3: update expr after second ';' or nullptr + * PNK_TRY (TernaryNode) + * kid1: try block + * kid2: null or PNK_CATCHLIST list + * kid3: null or finally block * PNK_CATCHLIST list pn_head: list of PNK_LEXICALSCOPE nodes, one per * catch-block, each with pn_expr pointing * to a PNK_CATCH node - * PNK_CATCH ternary pn_kid1: PNK_NAME, PNK_ARRAY, or PNK_OBJECT catch var node - * (PNK_ARRAY or PNK_OBJECT if destructuring) - * pn_kid2: null or the catch guard expression - * pn_kid3: catch block statements + * PNK_CATCH (TernaryNode) + * kid1: PNK_NAME, PNK_ARRAY, or PNK_OBJECT catch binding node (PNK_ARRAY or PNK_OBJECT if destructuring) + or null if optional catch binding + * kid2: null or the catch guard expression + * kid3: catch block statements * PNK_BREAK name pn_atom: label or null * PNK_CONTINUE name pn_atom: label or null * PNK_WITH binary pn_left: head expr; pn_right: body; @@ -342,8 +361,11 @@ IsTypeofKind(ParseNodeKind kind) * PNK_DIVASSIGN, * PNK_MODASSIGN, * PNK_POWASSIGN - * PNK_CONDITIONAL ternary (cond ? trueExpr : falseExpr) - * pn_kid1: cond, pn_kid2: then, pn_kid3: else + * PNK_CONDITIONAL (ConditionalExpression) + * (cond ? thenExpr : elseExpr) + * kid1: cond + * kid2: thenExpr + * kid3: elseExpr * PNK_COALESCE, list pn_head; list of pn_count subexpressions * PNK_OR, PNK_AND, PNK_BITOR, * PNK_BITXOR, PNK_BITAND, PNK_EQ, @@ -498,12 +520,15 @@ enum ParseNodeArity #define FOR_EACH_PARSENODE_SUBCLASS(macro) \ macro(ListNode, ListNodeType, asList) \ - macro(CallSiteNode, CallSiteNodeType, asCallSite) + macro(CallSiteNode, CallSiteNodeType, asCallSite) \ + \ + macro(TernaryNode, TernaryNodeType, asTernary) \ + macro(ClassNode, ClassNodeType, asClass) \ + macro(ConditionalExpression, ConditionalExpressionType, asConditionalExpression) class LoopControlStatement; class BreakStatement; class ContinueStatement; -class ConditionalExpression; class PropertyAccess; #define DECLARE_CLASS(typeName, longTypeName, asMethodName) \ @@ -604,6 +629,8 @@ class ParseNode uint32_t xflags; /* see ListNode class */ } list; struct { /* ternary: if, for(;;), ?: */ + private: + friend class TernaryNode; ParseNode* kid1; /* condition, discriminant, etc. */ ParseNode* kid2; /* then-part, case list, etc. */ ParseNode* kid3; /* else-part, default case, etc. */ @@ -648,9 +675,6 @@ class ParseNode #define pn_objbox pn_u.name.objbox #define pn_funbox pn_u.name.funbox #define pn_body pn_u.name.expr -#define pn_kid1 pn_u.ternary.kid1 -#define pn_kid2 pn_u.ternary.kid2 -#define pn_kid3 pn_u.ternary.kid3 #define pn_left pn_u.binary.left #define pn_right pn_u.binary.right #define pn_pval pn_u.binary.pval @@ -854,30 +878,56 @@ struct BinaryNode : public ParseNode #endif }; -struct TernaryNode : public ParseNode +class TernaryNode : public ParseNode { + public: TernaryNode(ParseNodeKind kind, JSOp op, ParseNode* kid1, ParseNode* kid2, ParseNode* kid3) - : ParseNode(kind, op, PN_TERNARY, - TokenPos((kid1 ? kid1 : kid2 ? kid2 : kid3)->pn_pos.begin, - (kid3 ? kid3 : kid2 ? kid2 : kid1)->pn_pos.end)) - { - pn_kid1 = kid1; - pn_kid2 = kid2; - pn_kid3 = kid3; - } + : TernaryNode(kind, op, kid1, kid2, kid3, + TokenPos((kid1 ? kid1 : kid2 ? kid2 : kid3)->pn_pos.begin, + (kid3 ? kid3 : kid2 ? kid2 : kid1)->pn_pos.end)) + {} TernaryNode(ParseNodeKind kind, JSOp op, ParseNode* kid1, ParseNode* kid2, ParseNode* kid3, const TokenPos& pos) : ParseNode(kind, op, PN_TERNARY, pos) { - pn_kid1 = kid1; - pn_kid2 = kid2; - pn_kid3 = kid3; + pn_u.ternary.kid1 = kid1; + pn_u.ternary.kid2 = kid2; + pn_u.ternary.kid3 = kid3; + } + + static bool test(const ParseNode& node) { + return node.isArity(PN_TERNARY); } #ifdef DEBUG void dump(int indent); #endif + + ParseNode* kid1() const { + return pn_u.ternary.kid1; + } + + ParseNode* kid2() const { + return pn_u.ternary.kid2; + } + + ParseNode* kid3() const { + return pn_u.ternary.kid3; + } + + // Methods used by FoldConstants.cpp. + ParseNode** unsafeKid1Reference() { + return &pn_u.ternary.kid1; + } + + ParseNode** unsafeKid2Reference() { + return &pn_u.ternary.kid2; + } + + ParseNode** unsafeKid3Reference() { + return &pn_u.ternary.kid3; + } }; class ListNode : public ParseNode @@ -1377,36 +1427,33 @@ class DebuggerStatement : public ParseNode { } }; -class ConditionalExpression : public ParseNode +class ConditionalExpression : public TernaryNode { public: ConditionalExpression(ParseNode* condition, ParseNode* thenExpr, ParseNode* elseExpr) - : ParseNode(PNK_CONDITIONAL, JSOP_NOP, PN_TERNARY, - TokenPos(condition->pn_pos.begin, elseExpr->pn_pos.end)) + : TernaryNode(PNK_CONDITIONAL, JSOP_NOP, condition, thenExpr, elseExpr, + TokenPos(condition->pn_pos.begin, elseExpr->pn_pos.end)) { MOZ_ASSERT(condition); MOZ_ASSERT(thenExpr); MOZ_ASSERT(elseExpr); - pn_u.ternary.kid1 = condition; - pn_u.ternary.kid2 = thenExpr; - pn_u.ternary.kid3 = elseExpr; } ParseNode& condition() const { - return *pn_u.ternary.kid1; + return *kid1(); } ParseNode& thenExpression() const { - return *pn_u.ternary.kid2; + return *kid2(); } ParseNode& elseExpression() const { - return *pn_u.ternary.kid3; + return *kid3(); } static bool test(const ParseNode& node) { bool match = node.isKind(PNK_CONDITIONAL); - MOZ_ASSERT_IF(match, node.isArity(PN_TERNARY)); + MOZ_ASSERT_IF(match, node.is<TernaryNode>()); MOZ_ASSERT_IF(match, node.isOp(JSOP_NOP)); return match; } @@ -1721,7 +1768,9 @@ struct ClassNames : public BinaryNode { } }; -struct ClassNode : public TernaryNode { +class ClassNode : public TernaryNode +{ + public: ClassNode(ParseNode* names, ParseNode* heritage, ParseNode* methodsOrBlock, const TokenPos& pos) : TernaryNode(PNK_CLASS, JSOP_NOP, names, heritage, methodsOrBlock, pos) @@ -1733,28 +1782,30 @@ struct ClassNode : public TernaryNode { static bool test(const ParseNode& node) { bool match = node.isKind(PNK_CLASS); - MOZ_ASSERT_IF(match, node.isArity(PN_TERNARY)); + MOZ_ASSERT_IF(match, node.is<TernaryNode>()); return match; } ClassNames* names() const { - return pn_kid1 ? &pn_kid1->as<ClassNames>() : nullptr; + return kid1() ? &kid1()->as<ClassNames>() : nullptr; } ParseNode* heritage() const { - return pn_kid2; + return kid2(); } ListNode* methodList() const { - if (pn_kid3->isKind(PNK_CLASSMETHODLIST)) - return &pn_kid3->as<ListNode>(); + ParseNode* methodsOrBlock = kid3(); + if (methodsOrBlock->isKind(PNK_CLASSMETHODLIST)) + return &methodsOrBlock->as<ListNode>(); - MOZ_ASSERT(pn_kid3->is<LexicalScopeNode>()); - ListNode* list = &pn_kid3->scopeBody()->as<ListNode>(); + MOZ_ASSERT(methodsOrBlock->is<LexicalScopeNode>()); + ListNode* list = &methodsOrBlock->scopeBody()->as<ListNode>(); MOZ_ASSERT(list->isKind(PNK_CLASSMETHODLIST)); return list; } Handle<LexicalScope::Data*> scopeBindings() const { - MOZ_ASSERT(pn_kid3->is<LexicalScopeNode>()); - return pn_kid3->scopeBindings(); + ParseNode* scope = kid3(); + MOZ_ASSERT(scope->is<LexicalScopeNode>()); + return scope->scopeBindings(); } }; diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index b6f834c876..4a6a629d28 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -5369,16 +5369,15 @@ Parser<SyntaxParseHandler>::checkExportedNameForFunction(Node node) template<> bool -Parser<FullParseHandler>::checkExportedNameForClass(ParseNode* node) +Parser<FullParseHandler>::checkExportedNameForClass(ClassNode* classNode) { - const ClassNode& cls = node->as<ClassNode>(); - MOZ_ASSERT(cls.names()); - return checkExportedName(cls.names()->innerBinding()->pn_atom); + MOZ_ASSERT(classNode->names()); + return checkExportedName(classNode->names()->innerBinding()->pn_atom); } template<> bool -Parser<SyntaxParseHandler>::checkExportedNameForClass(Node node) +Parser<SyntaxParseHandler>::checkExportedNameForClass(ClassNodeType classNode) { MOZ_ALWAYS_FALSE(abortIfSyntaxParser()); return false; @@ -5658,7 +5657,7 @@ Parser<ParseHandler>::exportClassDeclaration(uint32_t begin) MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_CLASS)); - Node kid = classDefinition(YieldIsKeyword, ClassStatement, NameRequired); + ClassNodeType kid = classDefinition(YieldIsName, ClassStatement, NameRequired); if (!kid) return null(); @@ -5736,7 +5735,7 @@ Parser<ParseHandler>::exportDefaultClassDeclaration(uint32_t begin) MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_CLASS)); - Node kid = classDefinition(YieldIsKeyword, ClassStatement, AllowDefaultName); + ClassNodeType kid = classDefinition(YieldIsName, ClassStatement, AllowDefaultName); if (!kid) return null(); @@ -5966,7 +5965,7 @@ Parser<ParseHandler>::consequentOrAlternative(YieldHandling yieldHandling) } template <typename ParseHandler> -typename ParseHandler::Node +typename ParseHandler::TernaryNodeType Parser<ParseHandler>::ifStatement(YieldHandling yieldHandling) { Vector<Node, 4> condList(context), thenList(context); @@ -6015,13 +6014,16 @@ Parser<ParseHandler>::ifStatement(YieldHandling yieldHandling) break; } + TernaryNodeType ifNode; for (int i = condList.length() - 1; i >= 0; i--) { - elseBranch = handler.newIfStatement(posList[i], condList[i], thenList[i], elseBranch); - if (!elseBranch) + ifNode = handler.newIfStatement(posList[i], condList[i], thenList[i], elseBranch); + if (!ifNode) { return null(); + } + elseBranch = ifNode; } - return elseBranch; + return ifNode; } template <typename ParseHandler> @@ -6325,7 +6327,7 @@ Parser<ParseHandler>::forStatement(YieldHandling yieldHandling) MOZ_ASSERT(headKind == PNK_FORIN || headKind == PNK_FOROF || headKind == PNK_FORHEAD); - Node forHead; + TernaryNodeType forHead; if (headKind == PNK_FORHEAD) { Node init = startNode; @@ -6947,7 +6949,7 @@ Parser<ParseHandler>::throwStatement(YieldHandling yieldHandling) } template <typename ParseHandler> -typename ParseHandler::Node +typename ParseHandler::TernaryNodeType Parser<ParseHandler>::tryStatement(YieldHandling yieldHandling) { MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_TRY)); @@ -7219,7 +7221,7 @@ JSOpFromPropertyType(PropertyType propType) } template <typename ParseHandler> -typename ParseHandler::Node +typename ParseHandler::ClassNodeType Parser<ParseHandler>::classDefinition(YieldHandling yieldHandling, ClassContext classContext, DefaultHandling defaultHandling) @@ -8929,7 +8931,7 @@ Parser<ParseHandler>::comprehensionFor(GeneratorKind comprehensionKind) if (!lexicalScope) return null(); - Node head = handler.newForInOrOfHead(PNK_FOROF, lexicalScope, rhs, headPos); + TernaryNodeType head = handler.newForInOrOfHead(PNK_FOROF, lexicalScope, rhs, headPos); if (!head) return null(); diff --git a/js/src/frontend/Parser.h b/js/src/frontend/Parser.h index 59ce925464..89b89674a4 100644 --- a/js/src/frontend/Parser.h +++ b/js/src/frontend/Parser.h @@ -1216,7 +1216,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE) Node returnStatement(YieldHandling yieldHandling); Node withStatement(YieldHandling yieldHandling); Node throwStatement(YieldHandling yieldHandling); - Node tryStatement(YieldHandling yieldHandling); + TernaryNodeType tryStatement(YieldHandling yieldHandling); Node catchBlockStatement(YieldHandling yieldHandling, ParseContext::Scope& catchParamScope); Node debuggerStatement(); @@ -1225,7 +1225,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE) Node labeledStatement(YieldHandling yieldHandling); Node labeledItem(YieldHandling yieldHandling); - Node ifStatement(YieldHandling yieldHandling); + TernaryNodeType ifStatement(YieldHandling yieldHandling); Node consequentOrAlternative(YieldHandling yieldHandling); // While on a |let| TOK_NAME token, examine |next|. Indicate whether @@ -1395,11 +1395,11 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE) bool checkExportedNameForClause(Node node); bool checkExportedNameForFunction(Node node); - bool checkExportedNameForClass(Node node); + bool checkExportedNameForClass(ClassNodeType classNode); enum ClassContext { ClassStatement, ClassExpression }; - Node classDefinition(YieldHandling yieldHandling, ClassContext classContext, - DefaultHandling defaultHandling); + ClassNodeType classDefinition(YieldHandling yieldHandling, ClassContext classContext, + DefaultHandling defaultHandling); bool checkLabelOrIdentifierReference(HandlePropertyName ident, uint32_t offset, diff --git a/js/src/frontend/SyntaxParseHandler.h b/js/src/frontend/SyntaxParseHandler.h index 0f4c66e8e7..d37dd4e20b 100644 --- a/js/src/frontend/SyntaxParseHandler.h +++ b/js/src/frontend/SyntaxParseHandler.h @@ -249,7 +249,9 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) template <class Boxer> Node newRegExp(RegExpObject* reobj, const TokenPos& pos, Boxer& boxer) { return NodeGeneric; } - Node newConditional(Node cond, Node thenExpr, Node elseExpr) { return NodeGeneric; } + ConditionalExpressionType newConditional(Node cond, Node thenExpr, Node elseExpr) { + return NodeGeneric; + } Node newElision() { return NodeGeneric; } @@ -312,7 +314,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) ListNodeType newObjectLiteral(uint32_t begin) { return NodeUnparenthesizedObject; } ListNodeType newClassMethodList(uint32_t begin) { return NodeGeneric; } Node newClassNames(Node outer, Node inner, const TokenPos& pos) { return NodeGeneric; } - Node newClass(Node name, Node heritage, Node methodBlock, const TokenPos& pos) { return NodeGeneric; } + ClassNodeType newClass(Node name, Node heritage, Node methodBlock, const TokenPos& pos) { return NodeGeneric; } Node newNewTarget(Node newHolder, Node targetHolder) { return NodeGeneric; } Node newPosHolder(const TokenPos& pos) { return NodeGeneric; } @@ -353,7 +355,9 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) return expr == NodeUnparenthesizedString ? NodeStringExprStatement : NodeGeneric; } - Node newIfStatement(uint32_t begin, Node cond, Node then, Node else_) { return NodeGeneric; } + TernaryNodeType newIfStatement(uint32_t begin, Node cond, Node thenBranch, Node elseBranch) { + return NodeGeneric; + } Node newDoWhileStatement(Node body, Node cond, const TokenPos& pos) { return NodeGeneric; } Node newWhileStatement(uint32_t begin, Node cond, Node body) { return NodeGeneric; } Node newSwitchStatement(uint32_t begin, Node discriminant, Node lexicalForCaseList, bool hasDefault) @@ -393,7 +397,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) Node newOptionalPropertyByValue(Node pn, Node kid, uint32_t end) { return NodeOptionalElement; } - MOZ_MUST_USE bool addCatchBlock(ListNodeType catchList, Node letBlock, Node catchName, + MOZ_MUST_USE bool addCatchBlock(ListNodeType catchList, Node letBlock, Node catchBinding, Node catchGuard, Node catchBody) { return true; } MOZ_MUST_USE bool setLastFunctionFormalParameterDefault(Node funcpn, Node pn) { return true; } @@ -410,7 +414,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) void setFunctionBox(Node pn, FunctionBox* funbox) {} void addFunctionFormalParameter(Node pn, Node argpn) {} - Node newForStatement(uint32_t begin, Node forHead, Node body, unsigned iflags) { + Node newForStatement(uint32_t begin, TernaryNodeType forHead, Node body, unsigned iflags) { return NodeGeneric; } @@ -426,11 +430,11 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) return NodeGeneric; } - Node newForHead(Node init, Node test, Node update, const TokenPos& pos) { + TernaryNodeType newForHead(Node init, Node test, Node update, const TokenPos& pos) { return NodeGeneric; } - Node newForInOrOfHead(ParseNodeKind kind, Node target, Node iteratedExpr, const TokenPos& pos) { + TernaryNodeType newForInOrOfHead(ParseNodeKind kind, Node target, Node iteratedExpr, const TokenPos& pos) { return NodeGeneric; } diff --git a/js/src/wasm/AsmJS.cpp b/js/src/wasm/AsmJS.cpp index 4af6e51a5f..e6d6018fee 100644 --- a/js/src/wasm/AsmJS.cpp +++ b/js/src/wasm/AsmJS.cpp @@ -430,22 +430,19 @@ ReturnExpr(ParseNode* pn) static inline ParseNode* TernaryKid1(ParseNode* pn) { - MOZ_ASSERT(pn->isArity(PN_TERNARY)); - return pn->pn_kid1; + return pn->as<TernaryNode>().kid1(); } static inline ParseNode* TernaryKid2(ParseNode* pn) { - MOZ_ASSERT(pn->isArity(PN_TERNARY)); - return pn->pn_kid2; + return pn->as<TernaryNode>().kid2(); } static inline ParseNode* TernaryKid3(ParseNode* pn) { - MOZ_ASSERT(pn->isArity(PN_TERNARY)); - return pn->pn_kid3; + return pn->as<TernaryNode>().kid3(); } static inline ParseNode* |