From 6cea01f81194b8823c285418997f31bde897b700 Mon Sep 17 00:00:00 2001 From: Martok Date: Mon, 27 Mar 2023 08:38:11 +0200 Subject: Issue #2173 - Add accessors to UnaryNode and subclasses Based-on: m-c 1479659/4 --- js/src/builtin/ModuleObject.cpp | 11 +- js/src/builtin/ReflectParse.cpp | 99 +++++++----- js/src/frontend/BytecodeEmitter.cpp | 298 +++++++++++++++++------------------ js/src/frontend/BytecodeEmitter.h | 44 +++--- js/src/frontend/FoldConstants.cpp | 147 +++++++++-------- js/src/frontend/FullParseHandler.h | 53 ++++--- js/src/frontend/NameFunctions.cpp | 24 ++- js/src/frontend/ParseNode.cpp | 38 +++-- js/src/frontend/ParseNode.h | 162 +++++++++++-------- js/src/frontend/Parser.cpp | 42 ++--- js/src/frontend/Parser.h | 22 +-- js/src/frontend/SyntaxParseHandler.h | 32 ++-- js/src/wasm/AsmJS.cpp | 3 +- 13 files changed, 502 insertions(+), 473 deletions(-) (limited to 'js') diff --git a/js/src/builtin/ModuleObject.cpp b/js/src/builtin/ModuleObject.cpp index d97304cf1a..08c9608f62 100644 --- a/js/src/builtin/ModuleObject.cpp +++ b/js/src/builtin/ModuleObject.cpp @@ -1210,10 +1210,11 @@ ModuleBuilder::processExport(frontend::ParseNode* exportNode) { MOZ_ASSERT(exportNode->isKind(PNK_EXPORT) || exportNode->isKind(PNK_EXPORT_DEFAULT)); - MOZ_ASSERT_IF(exportNode->isKind(PNK_EXPORT), exportNode->is()); bool isDefault = exportNode->isKind(PNK_EXPORT_DEFAULT); - ParseNode* kid = isDefault ? exportNode->as().left() : exportNode->pn_kid; + ParseNode* kid = isDefault + ? exportNode->as().left() + : exportNode->as().kid(); if (isDefault && exportNode->as().right()) { // This is an export default containing an expression. @@ -1321,7 +1322,7 @@ ModuleBuilder::processExportArrayBinding(frontend::ListNode* array) continue; if (node->isKind(PNK_SPREAD)) - node = node->pn_kid; + node = node->as().kid(); else if (node->isKind(PNK_ASSIGN)) node = node->as().left(); @@ -1345,10 +1346,10 @@ ModuleBuilder::processExportObjectBinding(frontend::ListNode* obj) ParseNode* target; if (node->isKind(PNK_SPREAD)) { - target = node->pn_kid; + target = node->as().kid(); } else { if (node->isKind(PNK_MUTATEPROTO)) - target = node->pn_kid; + target = node->as().kid(); else target = node->as().right(); diff --git a/js/src/builtin/ReflectParse.cpp b/js/src/builtin/ReflectParse.cpp index 2cee92eabe..1c584132c1 100644 --- a/js/src/builtin/ReflectParse.cpp +++ b/js/src/builtin/ReflectParse.cpp @@ -2214,7 +2214,7 @@ ASTSerializer::exportDeclaration(ParseNode* exportNode, MutableHandleValue dst) NodeVector elts(cx); ParseNode* kid = exportNode->isKind(PNK_EXPORT) - ? exportNode->pn_kid + ? exportNode->as().kid() : exportNode->as().left(); switch (ParseNodeKind kind = kid->getKind()) { case PNK_EXPORT_SPEC_LIST: { @@ -2468,9 +2468,9 @@ ASTSerializer::statement(ParseNode* pn, MutableHandleValue dst) return exportDeclaration(pn, dst); case PNK_SEMI: - if (pn->pn_kid) { + if (pn->as().kid()) { RootedValue expr(cx); - return expression(pn->pn_kid, &expr) && + return expression(pn->as().kid(), &expr) && builder.expressionStatement(expr, &pn->pn_pos, dst); } return builder.emptyStatement(&pn->pn_pos, dst); @@ -2629,22 +2629,26 @@ ASTSerializer::statement(ParseNode* pn, MutableHandleValue dst) case PNK_THROW: { - MOZ_ASSERT_IF(pn->pn_kid, pn->pn_pos.encloses(pn->pn_kid->pn_pos)); + UnaryNode* throwNode = &pn->as(); + ParseNode* operand = throwNode->kid(); + MOZ_ASSERT(throwNode->pn_pos.encloses(operand->pn_pos)); RootedValue arg(cx); - return optExpression(pn->pn_kid, &arg) && - builder.throwStatement(arg, &pn->pn_pos, dst); + return expression(operand, &arg) && + builder.throwStatement(arg, &throwNode->pn_pos, dst); } case PNK_RETURN: { - MOZ_ASSERT_IF(pn->pn_kid, pn->pn_pos.encloses(pn->pn_kid->pn_pos)); + UnaryNode* returnNode = &pn->as(); + ParseNode* operand = returnNode->kid(); + MOZ_ASSERT_IF(operand, returnNode->pn_pos.encloses(operand->pn_pos)); RootedValue arg(cx); - return optExpression(pn->pn_kid, &arg) && - builder.returnStatement(arg, &pn->pn_pos, dst); + return optExpression(operand, &arg) && + builder.returnStatement(arg, &returnNode->pn_pos, dst); } case PNK_DEBUGGER: @@ -2865,7 +2869,7 @@ ASTSerializer::comprehension(ParseNode* pn, MutableHandleValue dst) RootedValue body(cx); - return expression(next->pn_kid, &body) && + return expression(next->as().kid(), &body) && builder.comprehensionExpression(body, blocks, filter, isLegacy, &pn->pn_pos, dst); } @@ -2907,13 +2911,14 @@ ASTSerializer::generatorExpression(ParseNode* pn, MutableHandleValue dst) } } - LOCAL_ASSERT(next->isKind(PNK_SEMI) && - next->pn_kid->isKind(PNK_YIELD) && - next->pn_kid->pn_kid); + LOCAL_ASSERT(next->isKind(PNK_SEMI)); + ParseNode* yieldNode = next->as().kid(); + LOCAL_ASSERT(yieldNode->isKind(PNK_YIELD) && + yieldNode->as().kid()); RootedValue body(cx); - return expression(next->pn_kid->pn_kid, &body) && + return expression(yieldNode->as().kid(), &body) && builder.generatorExpression(body, blocks, filter, isLegacy, &pn->pn_pos, dst); } @@ -2961,23 +2966,27 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst) case PNK_PREINCREMENT: case PNK_PREDECREMENT: { - MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_kid->pn_pos)); + UnaryNode* incDec = &pn->as(); + ParseNode* operand = incDec->kid(); + MOZ_ASSERT(incDec->pn_pos.encloses(operand->pn_pos)); - bool inc = pn->isKind(PNK_PREINCREMENT); + bool inc = incDec->isKind(PNK_PREINCREMENT); RootedValue expr(cx); - return expression(pn->pn_kid, &expr) && - builder.updateExpression(expr, inc, true, &pn->pn_pos, dst); + return expression(operand, &expr) && + builder.updateExpression(expr, inc, true, &incDec->pn_pos, dst); } case PNK_POSTINCREMENT: case PNK_POSTDECREMENT: { - MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_kid->pn_pos)); + UnaryNode* incDec = &pn->as(); + ParseNode* operand = incDec->kid(); + MOZ_ASSERT(incDec->pn_pos.encloses(operand->pn_pos)); - bool inc = pn->isKind(PNK_POSTINCREMENT); + bool inc = incDec->isKind(PNK_POSTINCREMENT); RootedValue expr(cx); - return expression(pn->pn_kid, &expr) && - builder.updateExpression(expr, inc, false, &pn->pn_pos, dst); + return expression(operand, &expr) && + builder.updateExpression(expr, inc, false, &incDec->pn_pos, dst); } case PNK_ASSIGN: @@ -3047,14 +3056,16 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst) case PNK_POS: case PNK_AWAIT: case PNK_NEG: { - MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_kid->pn_pos)); + UnaryNode* unaryNode = &pn->as(); + ParseNode* operand = unaryNode->kid(); + MOZ_ASSERT(unaryNode->pn_pos.encloses(operand->pn_pos)); - UnaryOperator op = unop(pn->getKind(), pn->getOp()); + UnaryOperator op = unop(unaryNode->getKind(), unaryNode->getOp()); LOCAL_ASSERT(op > UNOP_ERR && op < UNOP_LIMIT); RootedValue expr(cx); - return expression(pn->pn_kid, &expr) && - builder.unaryExpression(op, expr, &pn->pn_pos, dst); + return expression(operand, &expr) && + builder.unaryExpression(op, expr, &unaryNode->pn_pos, dst); } case PNK_GENEXP: { @@ -3073,13 +3084,13 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst) case PNK_DELETEOPTCHAIN: { RootedValue expr(cx); - return expression(pn->pn_kid, &expr) && + return expression(pn->as().kid(), &expr) && builder.deleteOptionalExpression(expr, &pn->pn_pos, dst); } case PNK_OPTCHAIN: { RootedValue expr(cx); - return expression(pn->pn_kid, &expr) && + return expression(pn->as().kid(), &expr) && builder.optionalExpression(expr, &pn->pn_pos, dst); } @@ -3240,14 +3251,14 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst) case PNK_SPREAD: { RootedValue expr(cx); - return expression(pn->pn_kid, &expr) && + return expression(pn->as().kid(), &expr) && builder.spreadExpression(expr, &pn->pn_pos, dst); } case PNK_COMPUTED_NAME: { RootedValue name(cx); - return expression(pn->pn_kid, &name) && + return expression(pn->as().kid(), &name) && builder.computedName(name, &pn->pn_pos, dst); } @@ -3307,20 +3318,24 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst) case PNK_YIELD_STAR: { - MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_kid->pn_pos)); + UnaryNode* yieldNode = &pn->as(); + ParseNode* operand = yieldNode->kid(); + MOZ_ASSERT(yieldNode->pn_pos.encloses(operand->pn_pos)); RootedValue arg(cx); - return expression(pn->pn_kid, &arg) && - builder.yieldExpression(arg, Delegating, &pn->pn_pos, dst); + return expression(operand, &arg) && + builder.yieldExpression(arg, Delegating, &yieldNode->pn_pos, dst); } case PNK_YIELD: { - MOZ_ASSERT_IF(pn->pn_kid, pn->pn_pos.encloses(pn->pn_kid->pn_pos)); + UnaryNode* yieldNode = &pn->as(); + ParseNode* operand = yieldNode->kid(); + MOZ_ASSERT_IF(operand, yieldNode->pn_pos.encloses(operand->pn_pos)); RootedValue arg(cx); - return optExpression(pn->pn_kid, &arg) && - builder.yieldExpression(arg, NotDelegating, &pn->pn_pos, dst); + return optExpression(operand, &arg) && + builder.yieldExpression(arg, NotDelegating, &yieldNode->pn_pos, dst); } case PNK_ARRAYCOMP: @@ -3389,7 +3404,7 @@ ASTSerializer::property(ParseNode* pn, MutableHandleValue dst) { if (pn->isKind(PNK_MUTATEPROTO)) { RootedValue val(cx); - return expression(pn->pn_kid, &val) && + return expression(pn->as().kid(), &val) && builder.prototypeMutation(val, &pn->pn_pos, dst); } if (pn->isKind(PNK_SPREAD)) @@ -3492,7 +3507,7 @@ ASTSerializer::arrayPattern(ListNode* array, MutableHandleValue dst) } else if (item->isKind(PNK_SPREAD)) { RootedValue target(cx); RootedValue spread(cx); - if (!pattern(item->pn_kid, &target)) + if (!pattern(item->as().kid(), &target)) return false; if(!builder.spreadExpression(target, &item->pn_pos, &spread)) return false; @@ -3521,7 +3536,7 @@ ASTSerializer::objectPattern(ListNode* obj, MutableHandleValue dst) if (propdef->isKind(PNK_SPREAD)) { RootedValue target(cx); RootedValue spread(cx); - if (!pattern(propdef->pn_kid, &target)) + if (!pattern(propdef->as().kid(), &target)) return false; if(!builder.spreadExpression(target, &propdef->pn_pos, &spread)) return false; @@ -3536,7 +3551,7 @@ ASTSerializer::objectPattern(ListNode* obj, MutableHandleValue dst) RootedValue pname(cx, StringValue(cx->names().proto)); if (!builder.literal(pname, &propdef->pn_pos, &key)) return false; - target = propdef->pn_kid; + target = propdef->as().kid(); } else { BinaryNode* prop = &propdef->as(); if (!propertyName(prop->left(), &key)) @@ -3648,7 +3663,7 @@ ASTSerializer::functionArgsAndBody(ParseNode* pn, NodeVector& args, NodeVector& switch (pnbody->getKind()) { case PNK_RETURN: /* expression closure, no destructured args */ return functionArgs(pn, argsList, args, defaults, rest) && - expression(pnbody->pn_kid, body); + expression(pnbody->as().kid(), body); case PNK_STATEMENTLIST: /* statement closure */ { @@ -3665,7 +3680,7 @@ ASTSerializer::functionArgsAndBody(ParseNode* pn, NodeVector& args, NodeVector& if (isAsync && isExpression) { MOZ_ASSERT(firstNode->getKind() == PNK_RETURN); return functionArgs(pn, argsList, args, defaults, rest) && - expression(firstNode->pn_kid, body); + expression(firstNode->as().kid(), body); } return functionArgs(pn, argsList, args, defaults, rest) && diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index a628ac88ed..fa3f2ddded 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -1072,7 +1072,7 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer) // |this| can throw in derived class constructors, including nested arrow // functions or eval. case PNK_THIS: - MOZ_ASSERT(pn->isArity(PN_UNARY)); + MOZ_ASSERT(pn->is()); *answer = sc->needsThisTDZChecks(); return true; @@ -1101,8 +1101,7 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer) case PNK_TYPEOFEXPR: case PNK_VOID: case PNK_NOT: - MOZ_ASSERT(pn->isArity(PN_UNARY)); - return checkSideEffects(pn->pn_kid, answer); + return checkSideEffects(pn->as().kid(), answer); // Even if the name expression is effect-free, performing ToPropertyKey on // it might not be effect-free: @@ -1116,13 +1115,13 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer) // Q.toString = () => { throw 17; }; // new Q; // new.target will be Q, ToPropertyKey(Q) throws 17 case PNK_COMPUTED_NAME: - MOZ_ASSERT(pn->isArity(PN_UNARY)); + MOZ_ASSERT(pn->is()); *answer = true; return true; // Looking up or evaluating the associated name could throw. case PNK_TYPEOFNAME: - MOZ_ASSERT(pn->isArity(PN_UNARY)); + MOZ_ASSERT(pn->is()); *answer = true; return true; @@ -1135,8 +1134,7 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer) // only produce a value, without affecting anything else. case PNK_MUTATEPROTO: case PNK_ARRAYPUSH: - MOZ_ASSERT(pn->isArity(PN_UNARY)); - return checkSideEffects(pn->pn_kid, answer); + return checkSideEffects(pn->as().kid(), answer); // Unary cases with obvious side effects. case PNK_PREINCREMENT: @@ -1144,7 +1142,7 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer) case PNK_PREDECREMENT: case PNK_POSTDECREMENT: case PNK_THROW: - MOZ_ASSERT(pn->isArity(PN_UNARY)); + MOZ_ASSERT(pn->is()); *answer = true; return true; @@ -1153,13 +1151,13 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer) case PNK_BITNOT: case PNK_POS: case PNK_NEG: - MOZ_ASSERT(pn->isArity(PN_UNARY)); + MOZ_ASSERT(pn->is()); *answer = true; return true; // This invokes the (user-controllable) iterator protocol. case PNK_SPREAD: - MOZ_ASSERT(pn->isArity(PN_UNARY)); + MOZ_ASSERT(pn->is()); *answer = true; return true; @@ -1167,7 +1165,7 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer) case PNK_YIELD_STAR: case PNK_YIELD: case PNK_AWAIT: - MOZ_ASSERT(pn->isArity(PN_UNARY)); + MOZ_ASSERT(pn->is()); *answer = true; return true; @@ -1176,21 +1174,19 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer) case PNK_DELETEPROP: case PNK_DELETEELEM: case PNK_DELETEOPTCHAIN: - MOZ_ASSERT(pn->isArity(PN_UNARY)); + MOZ_ASSERT(pn->is()); *answer = true; return true; // Deletion of a non-Reference expression has side effects only through // evaluating the expression. case PNK_DELETEEXPR: { - MOZ_ASSERT(pn->isArity(PN_UNARY)); - ParseNode* expr = pn->pn_kid; + ParseNode* expr = pn->as().kid(); return checkSideEffects(expr, answer); } case PNK_SEMI: - MOZ_ASSERT(pn->isArity(PN_UNARY)); - if (ParseNode* expr = pn->pn_kid) + if (ParseNode* expr = pn->as().kid()) return checkSideEffects(expr, answer); *answer = false; return true; @@ -1299,7 +1295,7 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer) // Likewise. case PNK_EXPORT: - MOZ_ASSERT(pn->isArity(PN_UNARY)); + MOZ_ASSERT(pn->is()); *answer = true; return true; @@ -1360,7 +1356,7 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer) return true; case PNK_OPTCHAIN: - MOZ_ASSERT(pn->isArity(PN_UNARY)); + MOZ_ASSERT(pn->is()); *answer = true; return true; @@ -1875,13 +1871,12 @@ BytecodeEmitter::emitPropLHS(PropertyAccess* prop) } bool -BytecodeEmitter::emitPropIncDec(ParseNode* pn) +BytecodeEmitter::emitPropIncDec(UnaryNode* incDec) { - MOZ_ASSERT(pn->pn_kid->isKind(PNK_DOT)); - PropertyAccess* prop = &pn->pn_kid->as(); + PropertyAccess* prop = &incDec->kid()->as(); bool isSuper = prop->isSuper(); - ParseNodeKind kind = pn->getKind(); + ParseNodeKind kind = incDec->getKind(); PropOpEmitter poe(this, kind == PNK_POSTINCREMENT ? PropOpEmitter::Kind::PostIncrement : kind == PNK_PREINCREMENT ? PropOpEmitter::Kind::PreIncrement @@ -1894,7 +1889,7 @@ BytecodeEmitter::emitPropIncDec(ParseNode* pn) return false; } if (isSuper) { - ParseNode* base = &prop->expression(); + UnaryNode* base = &prop->expression().as(); if (!emitGetThisForSuperBase(base)) { // THIS return false; } @@ -1910,12 +1905,12 @@ BytecodeEmitter::emitPropIncDec(ParseNode* pn) } bool -BytecodeEmitter::emitNameIncDec(ParseNode* incDec) +BytecodeEmitter::emitNameIncDec(UnaryNode* incDec) { - MOZ_ASSERT(incDec->pn_kid->isKind(PNK_NAME)); + MOZ_ASSERT(incDec->kid()->isKind(PNK_NAME)); ParseNodeKind kind = incDec->getKind(); - NameNode* name = &incDec->pn_kid->as(); + NameNode* name = &incDec->kid()->as(); NameOpEmitter noe(this, name->pn_atom, kind == PNK_POSTINCREMENT ? NameOpEmitter::Kind::PostIncrement : kind == PNK_PREINCREMENT ? NameOpEmitter::Kind::PreIncrement @@ -1945,7 +1940,7 @@ BytecodeEmitter::emitElemObjAndKey(PropertyByValue* elem, bool isSuper, ElemOpEm if (!eoe.prepareForObj()) { // return false; } - ParseNode* base = &elem->expression(); + UnaryNode* base = &elem->expression().as(); if (!emitGetThisForSuperBase(base)) { // THIS return false; } @@ -1976,11 +1971,11 @@ BytecodeEmitter::emitElemObjAndKey(PropertyByValue* elem, bool isSuper, ElemOpEm } bool -BytecodeEmitter::emitElemIncDec(ParseNode* pn) +BytecodeEmitter::emitElemIncDec(UnaryNode* incDec) { - PropertyByValue* elemExpr = &pn->pn_kid->as(); - bool isSuper = elemExpr->isSuper(); - ParseNodeKind kind = pn->getKind(); + PropertyByValue* elem = &incDec->kid()->as(); + bool isSuper = elem->isSuper(); + ParseNodeKind kind = incDec->getKind(); ElemOpEmitter eoe(this, kind == PNK_POSTINCREMENT ? ElemOpEmitter::Kind::PostIncrement : kind == PNK_PREINCREMENT ? ElemOpEmitter::Kind::PreIncrement @@ -1989,7 +1984,7 @@ BytecodeEmitter::emitElemIncDec(ParseNode* pn) isSuper ? ElemOpEmitter::ObjKind::Super : ElemOpEmitter::ObjKind::Other); - if (!emitElemObjAndKey(elemExpr, isSuper, eoe)) { // [Super] + if (!emitElemObjAndKey(elem, isSuper, eoe)) { // [Super] // // THIS KEY // // [Other] // // OBJ KEY @@ -2003,16 +1998,15 @@ BytecodeEmitter::emitElemIncDec(ParseNode* pn) } bool -BytecodeEmitter::emitCallIncDec(ParseNode* incDec) +BytecodeEmitter::emitCallIncDec(UnaryNode* incDec) { MOZ_ASSERT(incDec->isKind(PNK_PREINCREMENT) || incDec->isKind(PNK_POSTINCREMENT) || incDec->isKind(PNK_PREDECREMENT) || incDec->isKind(PNK_POSTDECREMENT)); - MOZ_ASSERT(incDec->pn_kid->isKind(PNK_CALL)); - - ParseNode* call = incDec->pn_kid; + ParseNode* call = incDec->kid(); + MOZ_ASSERT(call->isKind(PNK_CALL)); if (!emitTree(call)) // CALLRESULT return false; if (!emit1(JSOP_POS)) // N @@ -2440,7 +2434,7 @@ BytecodeEmitter::emitDestructuringLHSRef(ParseNode* target, size_t* emitted) *emitted = 0; if (target->isKind(PNK_SPREAD)) - target = target->pn_kid; + target = target->as().kid(); else if (target->isKind(PNK_ASSIGN)) target = target->as().left(); @@ -2467,7 +2461,7 @@ BytecodeEmitter::emitDestructuringLHSRef(ParseNode* target, size_t* emitted) return false; } if (isSuper) { - ParseNode* base = &prop->expression(); + UnaryNode* base = &prop->expression().as(); if (!emitGetThisForSuperBase(base)) { // THIS SUPERBASE return false; } @@ -2539,7 +2533,7 @@ BytecodeEmitter::emitSetOrInitializeDestructuring(ParseNode* target, Destructuri // the matched value. Otherwise emit an lvalue bytecode sequence followed // by an assignment op. if (target->isKind(PNK_SPREAD)) - target = target->pn_kid; + target = target->as().kid(); else if (target->isKind(PNK_ASSIGN)) target = target->as().left(); if (target->isKind(PNK_ARRAY) || target->isKind(PNK_OBJECT)) { @@ -3317,10 +3311,10 @@ BytecodeEmitter::emitDestructuringOpsArray(ListNode* pattern, DestructuringFlavo } bool -BytecodeEmitter::emitComputedPropertyName(ParseNode* computedPropName) +BytecodeEmitter::emitComputedPropertyName(UnaryNode* computedPropName) { MOZ_ASSERT(computedPropName->isKind(PNK_COMPUTED_NAME)); - return emitTree(computedPropName->pn_kid) && emit1(JSOP_TOID); + return emitTree(computedPropName->kid()) && emit1(JSOP_TOID); } bool @@ -3346,7 +3340,7 @@ BytecodeEmitter::emitDestructuringOpsObject(ListNode* pattern, DestructuringFlav for (ParseNode* member : pattern->contents()) { ParseNode* subpattern; if (member->isKind(PNK_MUTATEPROTO) || member->isKind(PNK_SPREAD)) - subpattern = member->pn_kid; + subpattern = member->as().kid(); else { MOZ_ASSERT(member->isKind(PNK_COLON) || member->isKind(PNK_SHORTHAND)); @@ -3422,7 +3416,7 @@ BytecodeEmitter::emitDestructuringOpsObject(ListNode* pattern, DestructuringFlav return false; needsGetElem = false; } else { - if (!emitComputedPropertyName(key)) // ... *SET RHS *LREF RHS KEY + if (!emitComputedPropertyName(&key->as())) // ... *SET RHS *LREF RHS KEY return false; // Add the computed property key to the exclusion set. @@ -3753,7 +3747,7 @@ BytecodeEmitter::emitAssignment(ParseNode* lhs, JSOp compoundOp, ParseNode* rhs) return false; } if (isSuper) { - ParseNode* base = &prop->expression(); + UnaryNode* base = &prop->expression().as(); if (!emitGetThisForSuperBase(base)) { // THIS SUPERBASE return false; } @@ -6088,7 +6082,7 @@ BytecodeEmitter::emitGetFunctionThis(const mozilla::Maybe& offset) return false; } if (sc->needsThisTDZChecks()) { - if (!emit1(JSOP_CHECKTHIS)) { // THIS + if (!emit1(JSOP_CHECKTHIS)) { // THIS return false; } } @@ -6097,18 +6091,16 @@ BytecodeEmitter::emitGetFunctionThis(const mozilla::Maybe& offset) } bool -BytecodeEmitter::emitGetThisForSuperBase(ParseNode* pn) +BytecodeEmitter::emitGetThisForSuperBase(UnaryNode* superBase) { - MOZ_ASSERT(pn->isKind(PNK_SUPERBASE)); - return emitGetFunctionThis(pn->pn_kid); // THIS + MOZ_ASSERT(superBase->isKind(PNK_SUPERBASE)); + return emitGetFunctionThis(superBase->kid()); // THIS } bool -BytecodeEmitter::emitThisLiteral(ParseNode* pn) +BytecodeEmitter::emitThisLiteral(ThisLiteral* pn) { - MOZ_ASSERT(pn->isKind(PNK_THIS)); - - if (ParseNode* thisName = pn->pn_kid) + if (ParseNode* thisName = pn->kid()) return emitGetFunctionThis(thisName); // THIS if (sc->thisBinding() == ThisBinding::Module) @@ -6130,9 +6122,9 @@ BytecodeEmitter::emitCheckDerivedClassConstructorReturn() } bool -BytecodeEmitter::emitReturn(ParseNode* pn) +BytecodeEmitter::emitReturn(UnaryNode* returnNode) { - if (!updateSourceCoordNotes(pn->pn_pos.begin)) + if (!updateSourceCoordNotes(returnNode->pn_pos.begin)) return false; bool needsIteratorResult = sc->isFunctionBox() && sc->asFunctionBox()->needsIteratorResult(); @@ -6142,8 +6134,8 @@ BytecodeEmitter::emitReturn(ParseNode* pn) } /* Push a return value */ - if (ParseNode* pn2 = pn->pn_kid) { - if (!emitTree(pn2)) + if (ParseNode* expr = returnNode->kid()) { + if (!emitTree(expr)) return false; bool isAsyncGenerator = sc->asFunctionBox()->isAsync() && @@ -6232,9 +6224,9 @@ BytecodeEmitter::emitGetDotGeneratorInScope(EmitterScope& currentScope) } bool -BytecodeEmitter::emitInitialYield(ParseNode* pn) +BytecodeEmitter::emitInitialYield(UnaryNode* yieldNode) { - if (!emitTree(pn->pn_kid)) + if (!emitTree(yieldNode->kid())) return false; if (!emitYieldOp(JSOP_INITIALYIELD)) @@ -6247,18 +6239,19 @@ BytecodeEmitter::emitInitialYield(ParseNode* pn) } bool -BytecodeEmitter::emitYield(ParseNode* pn) +BytecodeEmitter::emitYield(UnaryNode* yieldNode) { MOZ_ASSERT(sc->isFunctionBox()); - MOZ_ASSERT(pn->getOp() == JSOP_YIELD); + MOZ_ASSERT(yieldNode->getOp() == JSOP_YIELD); bool needsIteratorResult = sc->asFunctionBox()->needsIteratorResult(); if (needsIteratorResult) { if (!emitPrepareIteratorResult()) return false; } - if (pn->pn_kid) { - if (!emitTree(pn->pn_kid)) + + if (ParseNode* expr = yieldNode->kid()) { + if (!emitTree(expr)) return false; } else { if (!emit1(JSOP_UNDEFINED)) @@ -6287,12 +6280,12 @@ BytecodeEmitter::emitYield(ParseNode* pn) } bool -BytecodeEmitter::emitAwaitInInnermostScope(ParseNode* pn) +BytecodeEmitter::emitAwaitInInnermostScope(UnaryNode* awaitNode) { MOZ_ASSERT(sc->isFunctionBox()); - MOZ_ASSERT(pn->getOp() == JSOP_AWAIT); + MOZ_ASSERT(awaitNode->getOp() == JSOP_AWAIT); - if (!emitTree(pn->pn_kid)) + if (!emitTree(awaitNode->kid())) return false; return emitAwaitInInnermostScope(); } @@ -6606,15 +6599,15 @@ BytecodeEmitter::emitStatementList(ListNode* stmtList) } bool -BytecodeEmitter::emitStatement(ParseNode* pn) +BytecodeEmitter::emitStatement(UnaryNode* exprStmt) { - MOZ_ASSERT(pn->isKind(PNK_SEMI)); + MOZ_ASSERT(exprStmt->isKind(PNK_SEMI)); - ParseNode* pn2 = pn->pn_kid; - if (!pn2) + ParseNode* expr = exprStmt->kid(); + if (!expr) return true; - if (!updateSourceCoordNotes(pn->pn_pos.begin)) + if (!updateSourceCoordNotes(exprStmt->pn_pos.begin)) return false; /* @@ -6635,7 +6628,7 @@ BytecodeEmitter::emitStatement(ParseNode* pn) /* Don't eliminate expressions with side effects. */ if (!useful) { - if (!checkSideEffects(pn2, &useful)) + if (!checkSideEffects(expr, &useful)) return false; /* @@ -6654,16 +6647,16 @@ BytecodeEmitter::emitStatement(ParseNode* pn) if (useful) { JSOp op = wantval ? JSOP_SETRVAL : JSOP_POP; ValueUsage valueUsage = wantval ? ValueUsage::WantValue : ValueUsage::IgnoreValue; - MOZ_ASSERT_IF(pn2->isKind(PNK_ASSIGN), pn2->isOp(JSOP_NOP)); - if (!emitTree(pn2, valueUsage)) + MOZ_ASSERT_IF(expr->isKind(PNK_ASSIGN), expr->isOp(JSOP_NOP)); + if (!emitTree(expr, valueUsage)) return false; if (!emit1(op)) return false; - } else if (pn->isDirectivePrologueMember()) { + } else if (exprStmt->isDirectivePrologueMember()) { // Don't complain about directive prologue members; just don't emit // their code. } else { - if (JSAtom* atom = pn->isStringExprStatement()) { + if (JSAtom* atom = exprStmt->isStringExprStatement()) { // Warn if encountering a non-directive prologue member string // expression statement, that is inconsistent with the current // directive prologue. That is, a script *not* starting with @@ -6681,13 +6674,13 @@ BytecodeEmitter::emitStatement(ParseNode* pn) } if (directive) { - if (!reportExtraWarning(pn2, JSMSG_CONTRARY_NONDIRECTIVE, directive)) + if (!reportExtraWarning(expr, JSMSG_CONTRARY_NONDIRECTIVE, directive)) return false; } } else { - current->currentLine = parser->tokenStream.srcCoords.lineNum(pn2->pn_pos.begin); + current->currentLine = parser->tokenStream.srcCoords.lineNum(expr->pn_pos.begin); current->lastColumn = 0; - if (!reportExtraWarning(pn2, JSMSG_USELESS_EXPR)) + if (!reportExtraWarning(expr, JSMSG_USELESS_EXPR)) return false; } } @@ -6696,24 +6689,22 @@ BytecodeEmitter::emitStatement(ParseNode* pn) } bool -BytecodeEmitter::emitDeleteName(ParseNode* node) +BytecodeEmitter::emitDeleteName(UnaryNode* deleteNode) { - MOZ_ASSERT(node->isKind(PNK_DELETENAME)); - MOZ_ASSERT(node->isArity(PN_UNARY)); + MOZ_ASSERT(deleteNode->isKind(PNK_DELETENAME)); - ParseNode* nameExpr = node->pn_kid; + ParseNode* nameExpr = deleteNode->kid(); MOZ_ASSERT(nameExpr->isKind(PNK_NAME)); return emitAtomOp(nameExpr->pn_atom, JSOP_DELNAME); } bool -BytecodeEmitter::emitDeleteProperty(ParseNode* node) +BytecodeEmitter::emitDeleteProperty(UnaryNode* deleteNode) { - MOZ_ASSERT(node->isKind(PNK_DELETEPROP)); - MOZ_ASSERT(node->isArity(PN_UNARY)); + MOZ_ASSERT(deleteNode->isKind(PNK_DELETEPROP)); - PropertyAccess* propExpr = &node->pn_kid->as(); + PropertyAccess* propExpr = &deleteNode->kid()->as(); MOZ_ASSERT(propExpr->isKind(PNK_DOT)); PropOpEmitter poe(this, @@ -6727,7 +6718,7 @@ BytecodeEmitter::emitDeleteProperty(ParseNode* node) // which could throw if |this| hasn't yet been set by a |super(...)| // call or the super-base is not an object, before throwing a // ReferenceError for attempting to delete a super-reference. - ParseNode* base = &propExpr->expression(); + UnaryNode* base = &propExpr->expression().as(); if (!emitGetThisForSuperBase(base)) { // THIS return false; } @@ -6751,12 +6742,11 @@ BytecodeEmitter::emitDeleteProperty(ParseNode* node) } bool -BytecodeEmitter::emitDeleteElement(ParseNode* node) +BytecodeEmitter::emitDeleteElement(UnaryNode* deleteNode) { - MOZ_ASSERT(node->isKind(PNK_DELETEELEM)); - MOZ_ASSERT(node->isArity(PN_UNARY)); + MOZ_ASSERT(deleteNode->isKind(PNK_DELETEELEM)); - PropertyByValue* elemExpr = &node->pn_kid->as(); + PropertyByValue* elemExpr = &deleteNode->kid()->as(); MOZ_ASSERT(elemExpr->isKind(PNK_ELEM)); bool isSuper = elemExpr->isSuper(); @@ -6775,7 +6765,7 @@ BytecodeEmitter::emitDeleteElement(ParseNode* node) return false; } - ParseNode* base = &elemExpr->expression(); + UnaryNode* base = &elemExpr->expression().as(); if (!emitGetThisForSuperBase(base)) { // THIS return false; } @@ -6801,12 +6791,11 @@ BytecodeEmitter::emitDeleteElement(ParseNode* node) } bool -BytecodeEmitter::emitDeleteExpression(ParseNode* node) +BytecodeEmitter::emitDeleteExpression(UnaryNode* deleteNode) { - MOZ_ASSERT(node->isKind(PNK_DELETEEXPR)); - MOZ_ASSERT(node->isArity(PN_UNARY)); + MOZ_ASSERT(deleteNode->isKind(PNK_DELETEEXPR)); - ParseNode* expression = node->pn_kid; + ParseNode* expression = deleteNode->kid(); // If useless, just emit JSOP_TRUE; otherwise convert |delete | to // effectively |, true|. @@ -6825,13 +6814,13 @@ BytecodeEmitter::emitDeleteExpression(ParseNode* node) } bool -BytecodeEmitter::emitDeleteOptionalChain(ParseNode* deleteNode) +BytecodeEmitter::emitDeleteOptionalChain(UnaryNode* deleteNode) { MOZ_ASSERT(deleteNode->isKind(PNK_DELETEOPTCHAIN)); OptionalEmitter oe(this, stackDepth); - ParseNode* kid = deleteNode->pn_kid; + ParseNode* kid = deleteNode->kid(); switch (kid->getKind()) { case PNK_ELEM: case PNK_OPTELEM: { @@ -7226,7 +7215,7 @@ BytecodeEmitter::emitOptionalCalleeAndThis( break; } case PNK_OPTCHAIN: { - return emitCalleeAndThisForOptionalChain(calleeNode, callNode, cone); + return emitCalleeAndThisForOptionalChain(&calleeNode->as(), callNode, cone); } default: { MOZ_RELEASE_ASSERT(calleeNode->getKind() != PNK_SUPERBASE); @@ -7274,7 +7263,7 @@ BytecodeEmitter::emitOptionalCall( CallOrNewEmitter cone(this, op, isSpread && (argc == 1) && - isRestParameter(argsList->head()->pn_kid) + isRestParameter(argsList->head()->as().kid()) ? CallOrNewEmitter::ArgumentsKind::SingleSpreadRest : CallOrNewEmitter::ArgumentsKind::Other, valueUsage); @@ -7365,7 +7354,7 @@ BytecodeEmitter::emitArguments(ListNode* argsList, bool isCall, bool isSpread, } else { if (cone.wantSpreadOperand()) { ParseNode* spreadNode = argsList->head(); - if (!emitTree(spreadNode->pn_kid)) { // CALLEE THIS ARG0 + if (!emitTree(spreadNode->as().kid())) { // CALLEE THIS ARG0 return false; } } @@ -7432,7 +7421,7 @@ BytecodeEmitter::emitCallOrNew( JSOp op = callNode->getOp(); CallOrNewEmitter cone(this, op, isSpread && (argc == 1) && - isRestParameter(argsList->head()->pn_kid) + isRestParameter(argsList->head()->as().kid()) ? CallOrNewEmitter::ArgumentsKind::SingleSpreadRest : CallOrNewEmitter::ArgumentsKind::Other, valueUsage); @@ -7474,7 +7463,7 @@ BytecodeEmitter::emitCalleeAndThis( return false; } if (isSuper) { - ParseNode* base = &prop->expression(); + UnaryNode* base = &prop->expression().as(); if (!emitGetThisForSuperBase(base)) { // THIS return false; } @@ -7520,7 +7509,7 @@ BytecodeEmitter::emitCalleeAndThis( } break; case PNK_OPTCHAIN: - return emitCalleeAndThisForOptionalChain(calleeNode, callNode, cone); + return emitCalleeAndThisForOptionalChain(&calleeNode->as(), callNode, cone); default: if (!cone.prepareForOtherCallee()) { return false; @@ -7638,17 +7627,17 @@ BytecodeEmitter::emitSequenceExpr(ListNode* node, // Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See // the comment on emitSwitch. MOZ_NEVER_INLINE bool -BytecodeEmitter::emitIncOrDec(ParseNode* pn) +BytecodeEmitter::emitIncOrDec(UnaryNode* incDec) { - switch (pn->pn_kid->getKind()) { + switch (incDec->kid()->getKind()) { case PNK_DOT: - return emitPropIncDec(pn); + return emitPropIncDec(incDec); case PNK_ELEM: - return emitElemIncDec(pn); + return emitElemIncDec(incDec); case PNK_CALL: - return emitCallIncDec(pn); + return emitCallIncDec(incDec); default: - return emitNameIncDec(pn); + return emitNameIncDec(incDec); } return true; @@ -7726,7 +7715,7 @@ BytecodeEmitter::emitPropertyList(ListNode* obj, MutableHandlePlainObject objp, // involving "__proto__", performs [[Prototype]] mutation. if (propdef->isKind(PNK_MUTATEPROTO)) { MOZ_ASSERT(type == ObjectLiteral); - if (!emitTree(propdef->pn_kid)) + if (!emitTree(propdef->as().kid())) return false; objp.set(nullptr); if (!emit1(JSOP_MUTATEPROTO)) @@ -7740,7 +7729,7 @@ BytecodeEmitter::emitPropertyList(ListNode* obj, MutableHandlePlainObject objp, if (!emit1(JSOP_DUP)) return false; - if (!emitTree(propdef->pn_kid)) + if (!emitTree(propdef->as().kid())) return false; if (!emitCopyDataProperties(CopyOption::Unfiltered)) @@ -7774,7 +7763,8 @@ BytecodeEmitter::emitPropertyList(ListNode* obj, MutableHandlePlainObject objp, continue; } } else { - if (!emitComputedPropertyName(key)) + MOZ_ASSERT(key->isKind(PNK_COMPUTED_NAME)); + if (!emitComputedPropertyName(&key->as())) return false; isIndex = true; } @@ -8065,7 +8055,7 @@ BytecodeEmitter::emitArray(ParseNode* arrayHead, uint32_t count, JSOp op) } else { ParseNode* expr; if (elem->isKind(PNK_SPREAD)) { - expr = elem->pn_kid; + expr = elem->as().kid(); if (emitterMode == BytecodeEmitter::SelfHosting && expr->isKind(PNK_CALL) && @@ -8105,30 +8095,29 @@ BytecodeEmitter::emitArray(ParseNode* arrayHead, uint32_t count, JSOp op) } bool -BytecodeEmitter::emitUnary(ParseNode* pn) +BytecodeEmitter::emitUnary(UnaryNode* unaryNode) { - if (!updateSourceCoordNotes(pn->pn_pos.begin)) + if (!updateSourceCoordNotes(unaryNode->pn_pos.begin)) return false; /* Unary op, including unary +/-. */ - JSOp op = pn->getOp(); - ParseNode* pn2 = pn->pn_kid; + JSOp op = unaryNode->getOp(); - if (!emitTree(pn2)) + if (!emitTree(unaryNode->kid())) return false; return emit1(op); } bool -BytecodeEmitter::emitTypeof(ParseNode* node, JSOp op) +BytecodeEmitter::emitTypeof(UnaryNode* typeofNode, JSOp op) { MOZ_ASSERT(op == JSOP_TYPEOF || op == JSOP_TYPEOFEXPR); - if (!updateSourceCoordNotes(node->pn_pos.begin)) + if (!updateSourceCoordNotes(typeofNode->pn_pos.begin)) return false; - if (!emitTree(node->pn_kid)) + if (!emitTree(typeofNode->kid())) return false; return emit1(op); @@ -8699,12 +8688,12 @@ BytecodeEmitter::emitTree(ParseNode* pn, ValueUsage valueUsage /* = ValueUsage:: break; case PNK_RETURN: - if (!emitReturn(pn)) + if (!emitReturn(&pn->as())) return false; break; case PNK_YIELD_STAR: - if (!emitYieldStar(pn->pn_kid)) + if (!emitYieldStar(pn->as().kid())) return false; break; @@ -8714,17 +8703,17 @@ BytecodeEmitter::emitTree(ParseNode* pn, ValueUsage valueUsage /* = ValueUsage:: break; case PNK_INITIALYIELD: - if (!emitInitialYield(pn)) + if (!emitInitialYield(&pn->as())) return false; break; case PNK_YIELD: - if (!emitYield(pn)) + if (!emitYield(&pn->as())) return false; break; case PNK_AWAIT: - if (!emitAwaitInInnermostScope(pn)) + if (!emitAwaitInInnermostScope(&pn->as())) return false; break; @@ -8734,7 +8723,7 @@ BytecodeEmitter::emitTree(ParseNode* pn, ValueUsage valueUsage /* = ValueUsage:: break; case PNK_SEMI: - if (!emitStatement(pn)) + if (!emitStatement(&pn->as())) return false; break; @@ -8810,12 +8799,12 @@ BytecodeEmitter::emitTree(ParseNode* pn, ValueUsage valueUsage /* = ValueUsage:: break; case PNK_TYPEOFNAME: - if (!emitTypeof(pn, JSOP_TYPEOF)) + if (!emitTypeof(&pn->as(), JSOP_TYPEOF)) return false; break; case PNK_TYPEOFEXPR: - if (!emitTypeof(pn, JSOP_TYPEOFEXPR)) + if (!emitTypeof(&pn->as(), JSOP_TYPEOFEXPR)) return false; break; @@ -8825,7 +8814,7 @@ BytecodeEmitter::emitTree(ParseNode* pn, ValueUsage valueUsage /* = ValueUsage:: case PNK_BITNOT: case PNK_POS: case PNK_NEG: - if (!emitUnary(pn)) + if (!emitUnary(&pn->as())) return false; break; @@ -8833,38 +8822,38 @@ BytecodeEmitter::emitTree(ParseNode* pn, ValueUsage valueUsage /* = ValueUsage:: case PNK_PREDECREMENT: case PNK_POSTINCREMENT: case PNK_POSTDECREMENT: - if (!emitIncOrDec(pn)) + if (!emitIncOrDec(&pn->as())) return false; break; case PNK_DELETENAME: - if (!emitDeleteName(pn)) + if (!emitDeleteName(&pn->as())) return false; break; case PNK_DELETEPROP: - if (!emitDeleteProperty(pn)) + if (!emitDeleteProperty(&pn->as())) return false; break; case PNK_DELETEELEM: - if (!emitDeleteElement(pn)) + if (!emitDeleteElement(&pn->as())) return false; break; case PNK_DELETEEXPR: - if (!emitDeleteExpression(pn)) + if (!emitDeleteExpression(&pn->as())) return false; break; case PNK_DELETEOPTCHAIN: - if (!emitDeleteOptionalChain(pn)) { + if (!emitDeleteOptionalChain(&pn->as())) { return false; } break; case PNK_OPTCHAIN: - if (!emitOptionalChain(pn, valueUsage)) { + if (!emitOptionalChain(&pn->as(), valueUsage)) { return false; } break; @@ -8881,7 +8870,7 @@ BytecodeEmitter::emitTree(ParseNode* pn, ValueUsage valueUsage /* = ValueUsage:: return false; } if (isSuper) { - ParseNode* base = &prop->expression(); + UnaryNode* base = &prop->expression().as(); if (!emitGetThisForSuperBase(base)) { // THIS return false; } @@ -8940,13 +8929,16 @@ BytecodeEmitter::emitTree(ParseNode* pn, ValueUsage valueUsage /* = ValueUsage:: MOZ_ASSERT(sc->isModuleContext()); break; - case PNK_EXPORT: + case PNK_EXPORT: { MOZ_ASSERT(sc->isModuleContext()); - if (pn->pn_kid->getKind() != PNK_EXPORT_SPEC_LIST) { - if (!emitTree(pn->pn_kid)) + UnaryNode* node = &pn->as(); + ParseNode* decl = node->kid(); + if (decl->getKind() != PNK_EXPORT_SPEC_LIST) { + if (!emitTree(decl)) return false; } break; + } case PNK_EXPORT_DEFAULT: { MOZ_ASSERT(sc->isModuleContext()); @@ -8972,7 +8964,7 @@ BytecodeEmitter::emitTree(ParseNode* pn, ValueUsage valueUsage /* = ValueUsage:: * under the array initialiser code generator for array comprehension * special casing. */ - if (!emitTree(pn->pn_kid)) + if (!emitTree(pn->as().kid())) return false; if (!emitDupAt(this->stackDepth - 1 - arrayCompDepth)) return false; @@ -9035,7 +9027,7 @@ BytecodeEmitter::emitTree(ParseNode* pn, ValueUsage valueUsage /* = ValueUsage:: break; case PNK_THIS: - if (!emitThisLiteral(pn)) + if (!emitThisLiteral(&pn->as())) return false; break; @@ -9198,11 +9190,11 @@ BytecodeEmitter::emitOptionalTree( // For example `(a?.b)()` and `(a?.b)?.()`. bool BytecodeEmitter::emitCalleeAndThisForOptionalChain( - ParseNode* optionalChain, + UnaryNode* optionalChain, ParseNode* callNode, CallOrNewEmitter& cone) { - ParseNode* calleeNode = optionalChain->pn_kid; + ParseNode* calleeNode = optionalChain->kid(); // Create a new OptionalEmitter, in order to emit the right bytecode // in isolation. @@ -9231,10 +9223,10 @@ BytecodeEmitter::emitCalleeAndThisForOptionalChain( bool BytecodeEmitter::emitOptionalChain( - ParseNode* optionalChain, + UnaryNode* optionalChain, ValueUsage valueUsage) { - ParseNode* expression = optionalChain->pn_kid; + ParseNode* expression = optionalChain->kid(); OptionalEmitter oe(this, stackDepth); @@ -9266,14 +9258,13 @@ BytecodeEmitter::emitOptionalDotExpression( return false; } - ParseNode* base = &prop->expression(); if (isSuper) { - if (!emitGetThisForSuperBase(base)) { + if (!emitGetThisForSuperBase(&prop->expression().as())) { // [stack] OBJ return false; } } else { - if (!emitOptionalTree(base, oe)) { + if (!emitOptionalTree(&prop->expression(), oe)) { // [stack] OBJ return false; } @@ -9310,14 +9301,13 @@ BytecodeEmitter::emitOptionalElemExpression( return false; } - ParseNode* base = &elem->expression(); if (isSuper) { - if (!emitGetThisForSuperBase(base)) { + if (!emitGetThisForSuperBase(&elem->expression().as())) { // [stack] OBJ return false; } } else { - if (!emitOptionalTree(base, oe)) { + if (!emitOptionalTree(&elem->expression(), oe)) { // [stack] OBJ return false; } diff --git a/js/src/frontend/BytecodeEmitter.h b/js/src/frontend/BytecodeEmitter.h index 46b2d0b4f4..3fd95b60bd 100644 --- a/js/src/frontend/BytecodeEmitter.h +++ b/js/src/frontend/BytecodeEmitter.h @@ -465,10 +465,10 @@ struct MOZ_STACK_CLASS BytecodeEmitter MOZ_MUST_USE bool emitNumberOp(double dval); - MOZ_MUST_USE bool emitThisLiteral(ParseNode* pn); + MOZ_MUST_USE bool emitThisLiteral(ThisLiteral* pn); MOZ_MUST_USE bool emitGetFunctionThis(ParseNode* pn); MOZ_MUST_USE bool emitGetFunctionThis(const mozilla::Maybe& offset); - MOZ_MUST_USE bool emitGetThisForSuperBase(ParseNode* pn); + MOZ_MUST_USE bool emitGetThisForSuperBase(UnaryNode* superBase); MOZ_MUST_USE bool emitSetThis(BinaryNode* setThisNode); MOZ_MUST_USE bool emitCheckDerivedClassConstructorReturn(); @@ -484,7 +484,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter MOZ_MUST_USE bool emitCall(JSOp op, uint16_t argc, const mozilla::Maybe& sourceCoordOffset); MOZ_MUST_USE bool emitCall(JSOp op, uint16_t argc, ParseNode* pn = nullptr); - MOZ_MUST_USE bool emitCallIncDec(ParseNode* incDec); + MOZ_MUST_USE bool emitCallIncDec(UnaryNode* incDec); MOZ_MUST_USE bool emitLoopHead(ParseNode* nextpn, JumpTarget* top); MOZ_MUST_USE bool emitLoopEntry(ParseNode* nextpn, JumpList entryJump); @@ -536,7 +536,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter MOZ_MUST_USE bool emitTDZCheckIfNeeded(JSAtom* name, const NameLocation& loc); - MOZ_MUST_USE bool emitNameIncDec(ParseNode* incDec); + MOZ_MUST_USE bool emitNameIncDec(UnaryNode* incDec); MOZ_MUST_USE bool emitDeclarationList(ListNode* declList); MOZ_MUST_USE bool emitSingleDeclaration(ParseNode* declList, ParseNode* decl, @@ -555,23 +555,23 @@ struct MOZ_STACK_CLASS BytecodeEmitter } MOZ_MUST_USE bool emitGetDotGeneratorInScope(EmitterScope& currentScope); - MOZ_MUST_USE bool emitInitialYield(ParseNode* pn); - MOZ_MUST_USE bool emitYield(ParseNode* pn); + MOZ_MUST_USE bool emitInitialYield(UnaryNode* yieldNode); + MOZ_MUST_USE bool emitYield(UnaryNode* yieldNode); MOZ_MUST_USE bool emitYieldOp(JSOp op); MOZ_MUST_USE bool emitYieldStar(ParseNode* iter); MOZ_MUST_USE bool emitAwaitInInnermostScope() { return emitAwaitInScope(*innermostEmitterScope()); } - MOZ_MUST_USE bool emitAwaitInInnermostScope(ParseNode* pn); + MOZ_MUST_USE bool emitAwaitInInnermostScope(UnaryNode* awaitNode); MOZ_MUST_USE bool emitAwaitInScope(EmitterScope& currentScope); MOZ_MUST_USE bool emitPropLHS(PropertyAccess* prop); - MOZ_MUST_USE bool emitPropIncDec(ParseNode* pn); + MOZ_MUST_USE bool emitPropIncDec(UnaryNode* incDec); MOZ_MUST_USE bool emitAsyncWrapperLambda(unsigned index, bool isArrow); MOZ_MUST_USE bool emitAsyncWrapper(unsigned index, bool needsHomeObject, bool isArrow, bool isStarGenerator); - MOZ_MUST_USE bool emitComputedPropertyName(ParseNode* computedPropName); + MOZ_MUST_USE bool emitComputedPropertyName(UnaryNode* computedPropName); // Emit bytecode to put operands for a JSOP_GETELEM/CALLELEM/SETELEM/DELELEM // opcode onto the stack in the right order. In the case of SETELEM, the @@ -581,7 +581,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter MOZ_MUST_USE bool emitElemObjAndKey(PropertyByValue* elem, bool isSuper, ElemOpEmitter& eoe); MOZ_MUST_USE bool emitElemOpBase(JSOp op); - MOZ_MUST_USE bool emitElemIncDec(ParseNode* pn); + MOZ_MUST_USE bool emitElemIncDec(UnaryNode* incDec); MOZ_MUST_USE bool emitCatch(TernaryNode* catchNode); MOZ_MUST_USE bool emitIf(TernaryNode* ifNode); @@ -695,22 +695,22 @@ struct MOZ_STACK_CLASS BytecodeEmitter MOZ_MUST_USE bool emitTemplateString(ListNode* templateString); MOZ_MUST_USE bool emitAssignment(ParseNode* lhs, JSOp compoundOp, ParseNode* rhs); - MOZ_MUST_USE bool emitReturn(ParseNode* pn); - MOZ_MUST_USE bool emitStatement(ParseNode* pn); + MOZ_MUST_USE bool emitReturn(UnaryNode* returnNode); + MOZ_MUST_USE bool emitStatement(UnaryNode* exprStmt); MOZ_MUST_USE bool emitStatementList(ListNode* stmtList); - MOZ_MUST_USE bool emitDeleteName(ParseNode* pn); - MOZ_MUST_USE bool emitDeleteProperty(ParseNode* pn); - MOZ_MUST_USE bool emitDeleteElement(ParseNode* pn); - MOZ_MUST_USE bool emitDeleteExpression(ParseNode* pn); + MOZ_MUST_USE bool emitDeleteName(UnaryNode* deleteNode); + MOZ_MUST_USE bool emitDeleteProperty(UnaryNode* deleteNode); + MOZ_MUST_USE bool emitDeleteElement(UnaryNode* deleteNode); + MOZ_MUST_USE bool emitDeleteExpression(UnaryNode* deleteNode); // Optional methods which emit Optional Jump Target - MOZ_MUST_USE bool emitOptionalChain(ParseNode* optionalChain, + MOZ_MUST_USE bool emitOptionalChain(UnaryNode* optionalChain, ValueUsage valueUsage); - MOZ_MUST_USE bool emitCalleeAndThisForOptionalChain(ParseNode* optionalChain, + MOZ_MUST_USE bool emitCalleeAndThisForOptionalChain(UnaryNode* optionalChain, ParseNode* callNode, CallOrNewEmitter& cone); - MOZ_MUST_USE bool emitDeleteOptionalChain(ParseNode* deleteNode); + MOZ_MUST_USE bool emitDeleteOptionalChain(UnaryNode* deleteNode); // Optional methods which emit a shortCircuit jump. They need to be called by // a method which emits an Optional Jump Target, see below. @@ -729,16 +729,16 @@ struct MOZ_STACK_CLASS BytecodeEmitter OptionalEmitter& oe); // |op| must be JSOP_TYPEOF or JSOP_TYPEOFEXPR. - MOZ_MUST_USE bool emitTypeof(ParseNode* node, JSOp op); + MOZ_MUST_USE bool emitTypeof(UnaryNode* typeofNode, JSOp op); - MOZ_MUST_USE bool emitUnary(ParseNode* pn); + MOZ_MUST_USE bool emitUnary(UnaryNode* unaryNode); MOZ_MUST_USE bool emitRightAssociative(ListNode* node); MOZ_MUST_USE bool emitLeftAssociative(ListNode* node); MOZ_MUST_USE bool emitLogical(ListNode* node); MOZ_MUST_USE bool emitSequenceExpr(ListNode* node, ValueUsage valueUsage = ValueUsage::WantValue); - MOZ_NEVER_INLINE MOZ_MUST_USE bool emitIncOrDec(ParseNode* pn); + MOZ_NEVER_INLINE MOZ_MUST_USE bool emitIncOrDec(UnaryNode* incDec); MOZ_MUST_USE bool emitConditionalExpression(ConditionalExpression& conditional, ValueUsage valueUsage = ValueUsage::WantValue); diff --git a/js/src/frontend/FoldConstants.cpp b/js/src/frontend/FoldConstants.cpp index dfe6f75fdd..fedec39598 100644 --- a/js/src/frontend/FoldConstants.cpp +++ b/js/src/frontend/FoldConstants.cpp @@ -110,7 +110,7 @@ ContainsHoistedDeclaration(ExclusiveContext* cx, ParseNode* node, bool* result) case PNK_SEMI: case PNK_THROW: case PNK_RETURN: - MOZ_ASSERT(node->isArity(PN_UNARY)); + MOZ_ASSERT(node->is()); *result = false; return true; @@ -119,7 +119,7 @@ ContainsHoistedDeclaration(ExclusiveContext* cx, ParseNode* node, bool* result) case PNK_INITIALYIELD: case PNK_YIELD_STAR: case PNK_YIELD: - MOZ_ASSERT(node->isArity(PN_UNARY)); + MOZ_ASSERT(node->is()); *result = false; return true; @@ -515,7 +515,7 @@ Boolish(ParseNode* pn, bool isNullish = false) // |void| expressions, for good measure) and check that the nested // expression doesn't break this requirement before indicating falsity. do { - pn = pn->pn_kid; + pn = pn->as().kid(); } while (pn->isKind(PNK_VOID)); return IsEffectless(pn) ? Falsy : Unknown; @@ -561,16 +561,16 @@ FoldCondition(ExclusiveContext* cx, ParseNode** nodePtr, Parser& parser, +FoldTypeOfExpr(ExclusiveContext* cx, UnaryNode* node, Parser& parser, bool inGenexpLambda) { MOZ_ASSERT(node->isKind(PNK_TYPEOFEXPR)); - MOZ_ASSERT(node->isArity(PN_UNARY)); - ParseNode*& expr = node->pn_kid; - if (!Fold(cx, &expr, parser, inGenexpLambda)) + if (!Fold(cx, node->unsafeKidReference(), parser, inGenexpLambda)) return false; + ParseNode* expr = node->kid(); + // Constant-fold the entire |typeof| if given a constant with known type. RootedPropertyName result(cx); if (expr->isKind(PNK_STRING) || expr->isKind(PNK_TEMPLATE_STRING)) @@ -597,16 +597,16 @@ FoldTypeOfExpr(ExclusiveContext* cx, ParseNode* node, Parser& } static bool -FoldDeleteExpr(ExclusiveContext* cx, ParseNode* node, Parser& parser, +FoldDeleteExpr(ExclusiveContext* cx, UnaryNode* node, Parser& parser, bool inGenexpLambda) { MOZ_ASSERT(node->isKind(PNK_DELETEEXPR)); - MOZ_ASSERT(node->isArity(PN_UNARY)); - ParseNode*& expr = node->pn_kid; - if (!Fold(cx, &expr, parser, inGenexpLambda)) + if (!Fold(cx, node->unsafeKidReference(), parser, inGenexpLambda)) return false; + ParseNode* expr = node->kid(); + // Expression deletion evaluates the expression, then evaluates to true. // For effectless expressions, eliminate the expression evaluation. if (IsEffectless(expr)) { @@ -620,17 +620,17 @@ FoldDeleteExpr(ExclusiveContext* cx, ParseNode* node, Parser& } static bool -FoldDeleteElement(ExclusiveContext* cx, ParseNode* node, Parser& parser, +FoldDeleteElement(ExclusiveContext* cx, UnaryNode* node, Parser& parser, bool inGenexpLambda) { MOZ_ASSERT(node->isKind(PNK_DELETEELEM)); - MOZ_ASSERT(node->isArity(PN_UNARY)); - MOZ_ASSERT(node->pn_kid->isKind(PNK_ELEM)); + MOZ_ASSERT(node->kid()->isKind(PNK_ELEM)); - ParseNode*& expr = node->pn_kid; - if (!Fold(cx, &expr, parser, inGenexpLambda)) + if (!Fold(cx, node->unsafeKidReference(), parser, inGenexpLambda)) return false; + ParseNode* expr = node->kid(); + // If we're deleting an element, but constant-folding converted our // element reference into a dotted property access, we must *also* // morph the node's kind. @@ -645,38 +645,36 @@ FoldDeleteElement(ExclusiveContext* cx, ParseNode* node, Parser& parser, +FoldDeleteProperty(ExclusiveContext* cx, UnaryNode* node, Parser& parser, bool inGenexpLambda) { MOZ_ASSERT(node->isKind(PNK_DELETEPROP)); - MOZ_ASSERT(node->isArity(PN_UNARY)); - MOZ_ASSERT(node->pn_kid->isKind(PNK_DOT)); + MOZ_ASSERT(node->kid()->isKind(PNK_DOT)); - ParseNode*& expr = node->pn_kid; #ifdef DEBUG - ParseNodeKind oldKind = expr->getKind(); + ParseNodeKind oldKind = node->kid()->getKind(); #endif - if (!Fold(cx, &expr, parser, inGenexpLambda)) + if (!Fold(cx, node->unsafeKidReference(), parser, inGenexpLambda)) return false; - MOZ_ASSERT(expr->isKind(oldKind), + MOZ_ASSERT(node->kid()->isKind(oldKind), "kind should have remained invariant under folding"); return true; } static bool -FoldNot(ExclusiveContext* cx, ParseNode* node, Parser& parser, +FoldNot(ExclusiveContext* cx, UnaryNode* node, Parser& parser, bool inGenexpLambda) { MOZ_ASSERT(node->isKind(PNK_NOT)); - MOZ_ASSERT(node->isArity(PN_UNARY)); - ParseNode*& expr = node->pn_kid; - if (!FoldCondition(cx, &expr, parser, inGenexpLambda)) + if (!FoldCondition(cx, node->unsafeKidReference(), parser, inGenexpLambda)) return false; + ParseNode* expr = node->kid(); + if (expr->isKind(PNK_NUMBER)) { double d = expr->pn_dval; @@ -702,17 +700,17 @@ FoldNot(ExclusiveContext* cx, ParseNode* node, Parser& parser, } static bool -FoldUnaryArithmetic(ExclusiveContext* cx, ParseNode* node, Parser& parser, +FoldUnaryArithmetic(ExclusiveContext* cx, UnaryNode* node, Parser& parser, bool inGenexpLambda) { MOZ_ASSERT(node->isKind(PNK_BITNOT) || node->isKind(PNK_POS) || node->isKind(PNK_NEG), "need a different method for this node kind"); - MOZ_ASSERT(node->isArity(PN_UNARY)); - ParseNode*& expr = node->pn_kid; - if (!Fold(cx, &expr, parser, inGenexpLambda)) + if (!Fold(cx, node->unsafeKidReference(), parser, inGenexpLambda)) return false; + ParseNode* expr = node->kid(); + if (expr->isKind(PNK_NUMBER) || expr->isKind(PNK_TRUE) || expr->isKind(PNK_FALSE)) { double d = expr->isKind(PNK_NUMBER) ? expr->pn_dval @@ -736,22 +734,22 @@ FoldUnaryArithmetic(ExclusiveContext* cx, ParseNode* node, Parser& parser, +FoldIncrementDecrement(ExclusiveContext* cx, UnaryNode* incDec, Parser& parser, bool inGenexpLambda) { - MOZ_ASSERT(node->isKind(PNK_PREINCREMENT) || - node->isKind(PNK_POSTINCREMENT) || - node->isKind(PNK_PREDECREMENT) || - node->isKind(PNK_POSTDECREMENT)); - MOZ_ASSERT(node->isArity(PN_UNARY)); + MOZ_ASSERT(incDec->isKind(PNK_PREINCREMENT) || + incDec->isKind(PNK_POSTINCREMENT) || + incDec->isKind(PNK_PREDECREMENT) || + incDec->isKind(PNK_POSTDECREMENT)); - ParseNode*& target = node->pn_kid; - MOZ_ASSERT(parser.isValidSimpleAssignmentTarget(target, Parser::PermitAssignmentToFunctionCalls)); + MOZ_ASSERT(parser.isValidSimpleAssignmentTarget(incDec->kid(), + Parser::PermitAssignmentToFunctionCalls)); - if (!Fold(cx, &target, parser, inGenexpLambda)) + if (!Fold(cx, incDec->unsafeKidReference(), parser, inGenexpLambda)) return false; - MOZ_ASSERT(parser.isValidSimpleAssignmentTarget(target, Parser::PermitAssignmentToFunctionCalls)); + MOZ_ASSERT(parser.isValidSimpleAssignmentTarget(incDec->kid(), + Parser::PermitAssignmentToFunctionCalls)); return true; } @@ -1214,14 +1212,13 @@ FoldList(ExclusiveContext* cx, ListNode* list, Parser& parser, } static bool -FoldReturn(ExclusiveContext* cx, ParseNode* node, Parser& parser, +FoldReturn(ExclusiveContext* cx, UnaryNode* node, Parser& parser, bool inGenexpLambda) { MOZ_ASSERT(node->isKind(PNK_RETURN)); - MOZ_ASSERT(node->isArity(PN_UNARY)); - if (ParseNode*& expr = node->pn_kid) { - if (!Fold(cx, &expr, parser, inGenexpLambda)) + if (node->kid()) { + if (!Fold(cx, node->unsafeKidReference(), parser, inGenexpLambda)) return false; } @@ -1368,7 +1365,7 @@ FoldElement(ExclusiveContext* cx, ParseNode** nodePtr, Parser& // assertions during freeing, then free it. elem->setKind(PNK_TYPEOFEXPR); elem->setArity(PN_UNARY); - elem->pn_kid = key; + *(elem->as().unsafeKidReference()) = key; parser.freeTree(elem); return true; @@ -1671,29 +1668,31 @@ Fold(ExclusiveContext* cx, ParseNode** pnp, Parser& parser, bo return true; case PNK_SUPERBASE: - case PNK_TYPEOFNAME: - MOZ_ASSERT(pn->isArity(PN_UNARY)); - MOZ_ASSERT(pn->pn_kid->isKind(PNK_NAME)); - MOZ_ASSERT(!pn->pn_kid->expr()); + case PNK_TYPEOFNAME: { +#ifdef DEBUG + UnaryNode* node = &pn->as(); + MOZ_ASSERT(node->kid()->isKind(PNK_NAME)); + MOZ_ASSERT(!node->kid()->expr()); +#endif return true; + } case PNK_TYPEOFEXPR: - return FoldTypeOfExpr(cx, pn, parser, inGenexpLambda); + return FoldTypeOfExpr(cx, &pn->as(), parser, inGenexpLambda); case PNK_DELETENAME: { - MOZ_ASSERT(pn->isArity(PN_UNARY)); - MOZ_ASSERT(pn->pn_kid->isKind(PNK_NAME)); + MOZ_ASSERT(pn->as().kid()->isKind(PNK_NAME)); return true; } case PNK_DELETEEXPR: - return FoldDeleteExpr(cx, pn, parser, inGenexpLambda); + return FoldDeleteExpr(cx, &pn->as(), parser, inGenexpLambda); case PNK_DELETEELEM: - return FoldDeleteElement(cx, pn, parser, inGenexpLambda); + return FoldDeleteElement(cx, &pn->as(), parser, inGenexpLambda); case PNK_DELETEPROP: - return FoldDeleteProperty(cx, pn, parser, inGenexpLambda); + return FoldDeleteProperty(cx, &pn->as(), parser, inGenexpLambda); case PNK_CONDITIONAL: MOZ_ASSERT((*pnp)->is()); @@ -1704,18 +1703,18 @@ Fold(ExclusiveContext* cx, ParseNode** pnp, Parser& parser, bo return FoldIf(cx, pnp, parser, inGenexpLambda); case PNK_NOT: - return FoldNot(cx, pn, parser, inGenexpLambda); + return FoldNot(cx, &pn->as(), parser, inGenexpLambda); case PNK_BITNOT: case PNK_POS: case PNK_NEG: - return FoldUnaryArithmetic(cx, pn, parser, inGenexpLambda); + return FoldUnaryArithmetic(cx, &pn->as(), parser, inGenexpLambda); case PNK_PREINCREMENT: case PNK_POSTINCREMENT: case PNK_PREDECREMENT: case PNK_POSTDECREMENT: - return FoldIncrementDecrement(cx, pn, parser, inGenexpLambda); + return FoldIncrementDecrement(cx, &pn->as(), parser, inGenexpLambda); case PNK_THROW: case PNK_ARRAYPUSH: @@ -1724,8 +1723,7 @@ Fold(ExclusiveContext* cx, ParseNode** pnp, Parser& parser, bo case PNK_SPREAD: case PNK_EXPORT: case PNK_VOID: - MOZ_ASSERT(pn->isArity(PN_UNARY)); - return Fold(cx, &pn->pn_kid, parser, inGenexpLambda); + return Fold(cx, pn->as().unsafeKidReference(), parser, inGenexpLambda); case PNK_EXPORT_DEFAULT: case PNK_GENEXP: @@ -1734,11 +1732,13 @@ Fold(ExclusiveContext* cx, ParseNode** pnp, Parser& parser, bo case PNK_DELETEOPTCHAIN: case PNK_OPTCHAIN: case PNK_SEMI: - case PNK_THIS: - MOZ_ASSERT(pn->isArity(PN_UNARY)); - if (ParseNode*& expr = pn->pn_kid) - return Fold(cx, &expr, parser, inGenexpLambda); + case PNK_THIS: { + UnaryNode* node = &pn->as(); + ParseNode** expr = node->unsafeKidReference(); + if (*expr) + return Fold(cx, expr, parser, inGenexpLambda); return true; + } case PNK_COALESCE: case PNK_AND: @@ -1797,9 +1797,8 @@ Fold(ExclusiveContext* cx, ParseNode** pnp, Parser& parser, bo return FoldList(cx, &pn->as(), parser, inGenexpLambda); case PNK_INITIALYIELD: { - MOZ_ASSERT(pn->isArity(PN_UNARY)); #ifdef DEBUG - AssignmentNode* assignNode = &pn->pn_kid->as(); + AssignmentNode* assignNode = &pn->as().kid()->as(); MOZ_ASSERT(assignNode->left()->isKind(PNK_NAME)); MOZ_ASSERT(assignNode->right()->isKind(PNK_GENERATOR)); #endif @@ -1807,18 +1806,18 @@ Fold(ExclusiveContext* cx, ParseNode** pnp, Parser& parser, bo } case PNK_YIELD_STAR: - MOZ_ASSERT(pn->isArity(PN_UNARY)); - return Fold(cx, &pn->pn_kid, parser, inGenexpLambda); + return Fold(cx, pn->as().unsafeKidReference(), parser, inGenexpLambda); case PNK_YIELD: - case PNK_AWAIT: - MOZ_ASSERT(pn->isArity(PN_UNARY)); - if (!pn->pn_kid) + case PNK_AWAIT: { + UnaryNode* node = &pn->as(); + if (!node->kid()) return true; - return Fold(cx, &pn->pn_kid, parser, inGenexpLambda); + return Fold(cx, node->unsafeKidReference(), parser, inGenexpLambda); + } case PNK_RETURN: - return FoldReturn(cx, pn, parser, inGenexpLambda); + return FoldReturn(cx, &pn->as(), parser, inGenexpLambda); case PNK_TRY: return FoldTry(cx, &pn->as(), parser, inGenexpLambda); diff --git a/js/src/frontend/FullParseHandler.h b/js/src/frontend/FullParseHandler.h index 9baee6a747..af4900402a 100644 --- a/js/src/frontend/FullParseHandler.h +++ b/js/src/frontend/FullParseHandler.h @@ -138,7 +138,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) return new_(PNK_NAME, JSOP_GETNAME, name, pos); } - ParseNode* newComputedName(ParseNode* expr, uint32_t begin, uint32_t end) { + UnaryNodeType newComputedName(Node expr, uint32_t begin, uint32_t end) { TokenPos pos(begin, end); return new_(PNK_COMPUTED_NAME, JSOP_NOP, pos, expr); } @@ -195,7 +195,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) setEndPosition(callSiteObj, callSiteObj->rawNodes()); } - ParseNode* newThisLiteral(const TokenPos& pos, ParseNode* thisName) { + ThisLiteralType newThisLiteral(const TokenPos& pos, Node thisName) { return new_(pos, thisName); } @@ -222,7 +222,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) return new_(cond, thenExpr, elseExpr); } - ParseNode* newDelete(uint32_t begin, ParseNode* expr) { + UnaryNodeType newDelete(uint32_t begin, Node expr) { if (expr->isKind(PNK_NAME)) { expr->setOp(JSOP_DELNAME); return newUnary(PNK_DELETENAME, JSOP_NOP, begin, expr); @@ -235,7 +235,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) return newUnary(PNK_DELETEELEM, JSOP_NOP, begin, expr); if (expr->isKind(PNK_OPTCHAIN)) { - ParseNode* kid = expr->pn_kid; + ParseNode* kid = expr->as().kid(); // Handle property deletion explicitly. OptionalCall is handled // via DeleteExpr. if (kid->isKind(PNK_DOT) || @@ -249,7 +249,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) return newUnary(PNK_DELETEEXPR, JSOP_NOP, begin, expr); } - ParseNode* newTypeof(uint32_t begin, ParseNode* kid) { + UnaryNodeType newTypeof(uint32_t begin, Node kid) { TokenPos pos(begin, kid->pn_pos.end); ParseNodeKind kind = kid->isKind(PNK_NAME) ? PNK_TYPEOFNAME : PNK_TYPEOFEXPR; return new_(kind, JSOP_NOP, pos, kid); @@ -259,17 +259,17 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) return new_(kind, op, pos); } - ParseNode* newUnary(ParseNodeKind kind, JSOp op, uint32_t begin, ParseNode* kid) { + UnaryNodeType newUnary(ParseNodeKind kind, JSOp op, uint32_t begin, ParseNode* kid) { TokenPos pos(begin, kid ? kid->pn_pos.end : begin + 1); return new_(kind, op, pos, kid); } - ParseNode* newUpdate(ParseNodeKind kind, uint32_t begin, ParseNode* kid) { + UnaryNodeType newUpdate(ParseNodeKind kind, uint32_t begin, Node kid) { TokenPos pos(begin, kid->pn_pos.end); return new_(kind, JSOP_NOP, pos, kid); } - ParseNode* newSpread(uint32_t begin, ParseNode* kid) { + UnaryNodeType newSpread(uint32_t begin, Node kid) { TokenPos pos(begin, kid->pn_pos.end); return new_(PNK_SPREAD, JSOP_NOP, pos, kid); } @@ -387,7 +387,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) ParseNode* newPosHolder(const TokenPos& pos) { return new_(PNK_POSHOLDER, pos); } - ParseNode* newSuperBase(ParseNode* thisName, const TokenPos& pos) { + UnaryNodeType newSuperBase(Node thisName, const TokenPos& pos) { return new_(PNK_SUPERBASE, JSOP_NOP, pos, thisName); } @@ -396,7 +396,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) // singleton objects will have Object.prototype as their [[Prototype]]. literal->setHasNonConstInitializer(); - ParseNode* mutation = newUnary(PNK_MUTATEPROTO, JSOP_NOP, begin, expr); + UnaryNode* mutation = newUnary(PNK_MUTATEPROTO, JSOP_NOP, begin, expr); if (!mutation) return false; literal->append(mutation); @@ -478,22 +478,22 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) return true; } - ParseNode* newInitialYieldExpression(uint32_t begin, ParseNode* gen) { + UnaryNodeType newInitialYieldExpression(uint32_t begin, Node gen) { TokenPos pos(begin, begin + 1); return new_(PNK_INITIALYIELD, JSOP_INITIALYIELD, pos, gen); } - ParseNode* newYieldExpression(uint32_t begin, ParseNode* value) { + UnaryNodeType newYieldExpression(uint32_t begin, Node value) { TokenPos pos(begin, value ? value->pn_pos.end : begin + 1); return new_(PNK_YIELD, JSOP_YIELD, pos, value); } - ParseNode* newYieldStarExpression(uint32_t begin, ParseNode* value) { + UnaryNodeType newYieldStarExpression(uint32_t begin, Node value) { TokenPos pos(begin, value->pn_pos.end); return new_(PNK_YIELD_STAR, JSOP_NOP, pos, value); } - ParseNode* newAwaitExpression(uint32_t begin, ParseNode* value) { + UnaryNodeType newAwaitExpression(uint32_t begin, Node value) { TokenPos pos(begin, value ? value->pn_pos.end : begin + 1); return new_(PNK_AWAIT, JSOP_AWAIT, pos, value); } @@ -550,7 +550,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) if (!genInit) return false; - ParseNode* initialYield = newInitialYieldExpression(yieldPos.begin, genInit); + UnaryNode* initialYield = newInitialYieldExpression(yieldPos.begin, genInit); if (!initialYield) return false; @@ -575,7 +575,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) return pn; } - ParseNode* newExportDeclaration(ParseNode* kid, const TokenPos& pos) { + UnaryNodeType newExportDeclaration(Node kid, const TokenPos& pos) { return new_(PNK_EXPORT, JSOP_NOP, pos, kid); } @@ -597,7 +597,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) return new_(PNK_EXPORT_DEFAULT, JSOP_NOP, pos, kid, maybeBinding); } - ParseNode* newExprStatement(ParseNode* expr, uint32_t end) { + UnaryNodeType newExprStatement(Node expr, uint32_t end) { MOZ_ASSERT(expr->pn_pos.end <= end); return new_(PNK_SEMI, JSOP_NOP, TokenPos(expr->pn_pos.begin, end), expr); } @@ -669,7 +669,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) return new_(label, pos); } - ParseNode* newReturnStatement(ParseNode* expr, const TokenPos& pos) { + UnaryNodeType newReturnStatement(Node expr, const TokenPos& pos) { MOZ_ASSERT_IF(expr, pos.encloses(expr->pn_pos)); return new_(PNK_RETURN, JSOP_RETURN, pos, expr); } @@ -683,7 +683,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) return new_(label, stmt, begin); } - ParseNode* newThrowStatement(ParseNode* expr, const TokenPos& pos) { + UnaryNodeType newThrowStatement(Node expr, const TokenPos& pos) { MOZ_ASSERT(pos.encloses(expr->pn_pos)); return new_(PNK_THROW, JSOP_THROW, pos, expr); } @@ -820,7 +820,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) bool isStatementPermittedAfterReturnStatement(ParseNode *node) { ParseNodeKind kind = node->getKind(); return kind == PNK_FUNCTION || kind == PNK_VAR || kind == PNK_BREAK || kind == PNK_THROW || - (kind == PNK_SEMI && !node->pn_kid); + (kind == PNK_SEMI && !node->as().kid()); } bool isSuperBase(ParseNode* node) { @@ -916,8 +916,8 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) MOZ_MUST_USE ParseNode* setLikelyIIFE(ParseNode* pn) { return parenthesize(pn); } - void setInDirectivePrologue(ParseNode* pn) { - pn->pn_prologue = true; + void setInDirectivePrologue(UnaryNodeType exprStmt) { + exprStmt->setIsDirectivePrologueMember(); } bool isConstant(ParseNode* pn) { @@ -966,9 +966,12 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) nullptr; } JSAtom* isStringExprStatement(ParseNode* pn, TokenPos* pos) { - if (JSAtom* atom = pn->isStringExprStatement()) { - *pos = pn->pn_kid->pn_pos; - return atom; + if (pn->is()) { + UnaryNode* unary = &pn->as(); + if (JSAtom* atom = unary->isStringExprStatement()) { + *pos = unary->kid()->pn_pos; + return atom; + } } return nullptr; } diff --git a/js/src/frontend/NameFunctions.cpp b/js/src/frontend/NameFunctions.cpp index e527085f71..9dbfb441f0 100644 --- a/js/src/frontend/NameFunctions.cpp +++ b/js/src/frontend/NameFunctions.cpp @@ -404,9 +404,8 @@ class NameResolver case PNK_TYPEOFNAME: case PNK_SUPERBASE: - MOZ_ASSERT(cur->isArity(PN_UNARY)); - MOZ_ASSERT(cur->pn_kid->isKind(PNK_NAME)); - MOZ_ASSERT(!cur->pn_kid->expr()); + MOZ_ASSERT(cur->as().kid()->isKind(PNK_NAME)); + MOZ_ASSERT(!cur->as().kid()->expr()); break; case PNK_NEWTARGET: { @@ -436,16 +435,14 @@ class NameResolver case PNK_SPREAD: case PNK_MUTATEPROTO: case PNK_EXPORT: - MOZ_ASSERT(cur->isArity(PN_UNARY)); - if (!resolve(cur->pn_kid, prefix)) + if (!resolve(cur->as().kid(), prefix)) return false; break; // Nodes with a single nullable child. case PNK_SEMI: case PNK_THIS: - MOZ_ASSERT(cur->isArity(PN_UNARY)); - if (ParseNode* expr = cur->pn_kid) { + if (ParseNode* expr = cur->as().kid()) { if (!resolve(expr, prefix)) return false; } @@ -515,7 +512,7 @@ class NameResolver case PNK_INITIALYIELD: { #ifdef DEBUG - AssignmentNode* assignNode = &cur->pn_kid->as(); + AssignmentNode* assignNode = &cur->as().kid()->as(); MOZ_ASSERT(assignNode->left()->isKind(PNK_NAME)); MOZ_ASSERT(assignNode->right()->isKind(PNK_GENERATOR)); #endif @@ -523,23 +520,20 @@ class NameResolver } case PNK_YIELD_STAR: - MOZ_ASSERT(cur->isArity(PN_UNARY)); - if (!resolve(cur->pn_kid, prefix)) + if (!resolve(cur->as().kid(), prefix)) return false; break; case PNK_YIELD: case PNK_AWAIT: - MOZ_ASSERT(cur->isArity(PN_UNARY)); - if (cur->pn_kid) { - if (!resolve(cur->pn_kid, prefix)) + if (ParseNode* expr = cur->as().kid()) { + if (!resolve(expr, prefix)) return false; } break; case PNK_RETURN: - MOZ_ASSERT(cur->isArity(PN_UNARY)); - if (ParseNode* returnValue = cur->pn_kid) { + if (ParseNode* returnValue = cur->as().kid()) { if (!resolve(returnValue, prefix)) return false; } diff --git a/js/src/frontend/ParseNode.cpp b/js/src/frontend/ParseNode.cpp index db0fff1284..4cdf6bde05 100644 --- a/js/src/frontend/ParseNode.cpp +++ b/js/src/frontend/ParseNode.cpp @@ -157,11 +157,9 @@ PushListNodeChildren(ListNode* node, NodeStack* stack) } static PushResult -PushUnaryNodeChild(ParseNode* node, NodeStack* stack) +PushUnaryNodeChild(UnaryNode* node, NodeStack* stack) { - MOZ_ASSERT(node->isArity(PN_UNARY)); - - stack->push(node->pn_kid); + stack->push(node->kid()); return PushResult::Recyclable; } @@ -223,16 +221,16 @@ PushNodeChildren(ParseNode* pn, NodeStack* stack) case PNK_MUTATEPROTO: case PNK_EXPORT: case PNK_SUPERBASE: - return PushUnaryNodeChild(pn, stack); + return PushUnaryNodeChild(&pn->as(), stack); // Nodes with a single nullable child. case PNK_OPTCHAIN: case PNK_DELETEOPTCHAIN: case PNK_THIS: case PNK_SEMI: { - MOZ_ASSERT(pn->isArity(PN_UNARY)); - if (pn->pn_kid) - stack->push(pn->pn_kid); + UnaryNode* un = &pn->as(); + if (un->kid()) + stack->push(un->kid()); return PushResult::Recyclable; } @@ -297,14 +295,14 @@ PushNodeChildren(ParseNode* pn, NodeStack* stack) // 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)); + UnaryNode* un = &pn->as(); #ifdef DEBUG - MOZ_ASSERT(pn->pn_kid->isKind(PNK_ASSIGN)); - BinaryNode* bn = &pn->pn_kid->as(); + MOZ_ASSERT(un->kid()->isKind(PNK_ASSIGN)); + BinaryNode* bn = &un->kid()->as(); MOZ_ASSERT(bn->left()->isKind(PNK_NAME) && bn->right()->isKind(PNK_GENERATOR)); #endif - stack->push(pn->pn_kid); + stack->push(un->kid()); return PushResult::Recyclable; } @@ -312,18 +310,18 @@ PushNodeChildren(ParseNode* pn, NodeStack* stack) case PNK_YIELD_STAR: case PNK_YIELD: case PNK_AWAIT: { - MOZ_ASSERT(pn->isArity(PN_UNARY)); - if (pn->pn_kid) - stack->push(pn->pn_kid); + UnaryNode* un = &pn->as(); + if (un->kid()) + stack->push(un->kid()); return PushResult::Recyclable; } // A return node's child is what you'd expect: the return expression, // if any. case PNK_RETURN: { - MOZ_ASSERT(pn->isArity(PN_UNARY)); - if (pn->pn_kid) - stack->push(pn->pn_kid); + UnaryNode* un = &pn->as(); + if (un->kid()) + stack->push(un->kid()); return PushResult::Recyclable; } @@ -660,7 +658,7 @@ ParseNode::dump(int indent) ((NullaryNode*) this)->dump(); break; case PN_UNARY: - ((UnaryNode*) this)->dump(indent); + as().dump(indent); break; case PN_BINARY: as().dump(indent); @@ -723,7 +721,7 @@ UnaryNode::dump(int indent) const char* name = parseNodeNames[getKind()]; fprintf(stderr, "(%s ", name); indent += strlen(name) + 2; - DumpParseTree(pn_kid, indent); + DumpParseTree(kid(), indent); fprintf(stderr, ")"); } diff --git a/js/src/frontend/ParseNode.h b/js/src/frontend/ParseNode.h index 0b8a914e21..d21c4c6c20 100644 --- a/js/src/frontend/ParseNode.h +++ b/js/src/frontend/ParseNode.h @@ -240,7 +240,8 @@ IsTypeofKind(ParseNodeKind kind) * * StatementList node for function body statements * * Return for expression closure * count: number of formal parameters + 1 - * PNK_SPREAD unary pn_kid: expression being spread + * PNK_SPREAD (UnaryNode) + * 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 @@ -302,6 +303,8 @@ IsTypeofKind(ParseNodeKind kind) * kid1: init expr before first ';' or nullptr * kid2: cond expr before second ';' or nullptr * kid3: update expr after second ';' or nullptr + * PNK_THROW (UnaryNode) + * kid: thrown exception * PNK_TRY (TernaryNode) * kid1: try block * kid2: null or PNK_CATCHLIST list @@ -334,11 +337,12 @@ IsTypeofKind(ParseNodeKind kind) * pn_lexdef (NOT pn_expr) set * right: initializer * count: N > 0 - * PNK_RETURN unary pn_kid: return expr or null - * PNK_SEMI unary pn_kid: expr or null statement - * pn_prologue: true if Directive Prologue member - * in original source, not introduced via - * constant folding or other tree rewriting + * PNK_RETURN (UnaryNode) + * kid: returned expression, or null if none + * PNK_SEMI (UnaryNode) + * kid: expr + * prologue: true if Directive Prologue member in original source, not + * introduced via constant folding or other tree rewriting * PNK_LABEL name pn_atom: label, pn_expr: labeled statement * PNK_IMPORT (BinaryNode) * left: PNK_IMPORT_SPEC_LIST import specifiers @@ -349,7 +353,8 @@ IsTypeofKind(ParseNodeKind kind) * PNK_IMPORT_SPEC (BinaryNode) * left: import name * right: local binding name - * PNK_EXPORT unary pn_kid: declaration expression + * PNK_EXPORT (UnaryNode) + * kid: declaration expression * PNK_EXPORT_FROM (BinaryNode) * left: PNK_EXPORT_SPEC_LIST export specifiers * right: PNK_STRING module specifier @@ -397,29 +402,25 @@ IsTypeofKind(ParseNodeKind kind) * ParseNode::appendOrCreateList). * count: N >= 2 * - * PNK_POS, unary pn_kid: UNARY expr - * PNK_NEG - * PNK_VOID, unary pn_kid: UNARY expr - * PNK_NOT, - * PNK_BITNOT, - * PNK_AWAIT - * PNK_TYPEOFNAME, unary pn_kid: UNARY expr - * PNK_TYPEOFEXPR - * PNK_PREINCREMENT, unary pn_kid: MEMBER expr - * PNK_POSTINCREMENT, - * PNK_PREDECREMENT, - * PNK_POSTDECREMENT + * PNK_POS, PNK_NEG, PNK_VOID, PNK_NOT, PNK_BITNOT, + * PNK_TYPEOFNAME, PNK_TYPEOFEXPR (UnaryNode) + * kid: unary expr + * PNK_PREINCREMENT, PNK_POSTINCREMENT, + * PNK_PREDECREMENT, PNK_POSTDECREMENT (UnaryNode) + * kid: member expr * PNK_NEW (BinaryNode) * left: ctor expression on the left of the '(' * right: Arguments - * PNK_DELETENAME unary pn_kid: PNK_NAME expr - * PNK_DELETEPROP unary pn_kid: PNK_DOT expr - * PNK_DELETEELEM unary pn_kid: PNK_ELEM expr - * PNK_DELETEEXPR unary pn_kid: MEMBER expr that's evaluated, then the - * overall delete evaluates to true; can't be a kind - * for a more-specific PNK_DELETE* unless constant - * folding (or a similar parse tree manipulation) has - * occurred + * PNK_DELETENAME, PNK_DELETEPROP, PNK_DELETEELEM, + * PNK_DELETEEXPR (UnaryNode) + * kid: expression that's evaluated, then the overall delete evaluates to + * true; can't be a kind for a more-specific ParseNodeKind::Delete* + * unless constant folding (or a similar parse tree manipulation) has + * occurred + * * DeleteName: PNK_NAME expr + * * DeleteProp: PNK_DOT expr + * * DeleteElem: PNK_ELEM expr + * * DeleteExpr: MEMBER expr * PNK_DELETEOPTCHAIN unary pn_kid: MEMBER expr that's evaluated, then the * overall delete evaluates to true; If constant * folding occurs, PNK_ELEM may become PNK_DOT. @@ -467,7 +468,9 @@ IsTypeofKind(ParseNodeKind kind) * PNK_SHORTHAND (BinaryNode) * Same fields as Colon. This is used for object literal properties using * shorthand ({x}). - * PNK_COMPUTED_NAME unary ES6 ComputedPropertyName. + * PNK_COMPUTED_NAME (UnaryNode) + * ES6 ComputedPropertyName. + * kid: the AssignmentExpression inside the square brackets * pn_kid: the AssignmentExpression inside the square brackets * PNK_NAME, name pn_atom: name, string, or object atom * PNK_STRING pn_op: JSOP_GETNAME, JSOP_STRING, or JSOP_OBJECT @@ -497,8 +500,10 @@ IsTypeofKind(ParseNodeKind kind) * PNK_NULL, * PNK_RAW_UNDEFINED * - * PNK_THIS, unary pn_kid: '.this' Name if function `this`, else nullptr - * PNK_SUPERBASE unary pn_kid: '.this' Name + * PNK_THIS (UnaryNode) + * kid: '.this' Name if function `this`, else nullptr + * PNK_SUPERBASE (UnaryNode) + * kid: '.this' Name * * PNK_SUPERCALL (BinaryNode) * left: SuperBase @@ -509,9 +514,10 @@ IsTypeofKind(ParseNodeKind kind) * PNK_LEXICALSCOPE scope pn_u.scope.bindings: scope bindings * pn_u.scope.body: scope body * PNK_GENERATOR nullary - * PNK_INITIALYIELD unary pn_kid: generator object - * PNK_YIELD, unary pn_kid: expr or null - * PNK_YIELD_STAR + * PNK_INITIALYIELD (UnaryNode) + * kid: generator object + * PNK_YIELD, PNK_YIELD_STAR, PNK_AWAIT (UnaryNode) + * kid: expr or null * PNK_ARRAYCOMP list pn_count: 1 * pn_head: list of 1 element, which is block * enclosing for loop(s) and optionally @@ -548,7 +554,9 @@ enum ParseNodeArity \ macro(TernaryNode, TernaryNodeType, asTernary) \ macro(ClassNode, ClassNodeType, asClass) \ - macro(ConditionalExpression, ConditionalExpressionType, asConditionalExpression) + macro(ConditionalExpression, ConditionalExpressionType, asConditionalExpression) \ + macro(UnaryNode, UnaryNodeType, asUnary) \ + macro(ThisLiteral, ThisLiteralType, asThisLiteral) class LoopControlStatement; class BreakStatement; @@ -669,9 +677,10 @@ class ParseNode }; } binary; struct { /* one kid if unary */ + private: + friend class UnaryNode; ParseNode* kid; - bool prologue; /* directive prologue member (as - pn_prologue) */ + bool prologue; /* directive prologue member */ } unary; struct { /* name, labeled statement, etc. */ union { @@ -699,8 +708,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_kid pn_u.unary.kid -#define pn_prologue pn_u.unary.prologue #define pn_atom pn_u.name.atom #define pn_objbox pn_u.name.objbox #define pn_expr pn_u.name.expr @@ -758,29 +765,6 @@ class ParseNode return !isOp(JSOP_LAMBDA) && !isOp(JSOP_LAMBDA_ARROW) && !isOp(JSOP_DEFFUN); } - /* - * True if this statement node could be a member of a Directive Prologue: an - * expression statement consisting of a single string literal. - * - * This considers only the node and its children, not its context. After - * parsing, check the node's pn_prologue flag to see if it is indeed part of - * a directive prologue. - * - * Note that a Directive Prologue can contain statements that cannot - * themselves be directives (string literals that include escape sequences - * or escaped newlines, say). This member function returns true for such - * nodes; we use it to determine the extent of the prologue. - */ - JSAtom* isStringExprStatement() const { - if (getKind() == PNK_SEMI) { - MOZ_ASSERT(pn_arity == PN_UNARY); - ParseNode* kid = pn_kid; - if (kid && kid->getKind() == PNK_STRING && !kid->pn_parens) - return kid->pn_atom; - } - return nullptr; - } - /* True if pn is a parsenode representing a literal constant. */ bool isLiteral() const { return isKind(PNK_NUMBER) || @@ -791,9 +775,6 @@ class ParseNode isKind(PNK_RAW_UNDEFINED); } - /* Return true if this node appears in a Directive Prologue. */ - bool isDirectivePrologueMember() const { return pn_prologue; } - // True iff this is a for-in/of loop variable declaration (var/let/const). bool isForLoopDeclaration() const; @@ -860,12 +841,13 @@ struct NullaryNode : public ParseNode #endif }; -struct UnaryNode : public ParseNode +class UnaryNode : public ParseNode { + public: UnaryNode(ParseNodeKind kind, JSOp op, const TokenPos& pos, ParseNode* kid) : ParseNode(kind, op, PN_UNARY, pos) { - pn_kid = kid; + pn_u.unary.kid = kid; } static bool test(const ParseNode& node) { @@ -875,6 +857,48 @@ struct UnaryNode : public ParseNode #ifdef DEBUG void dump(int indent); #endif + + ParseNode* kid() const { + return pn_u.unary.kid; + } + + /* Return true if this node appears in a Directive Prologue. */ + bool isDirectivePrologueMember() const { + return pn_u.unary.prologue; + } + + void setIsDirectivePrologueMember() { + pn_u.unary.prologue = true; + } + + /* + * Non-null if this is a statement node which could be a member of a + * Directive Prologue: an expression statement consisting of a single + * string literal. + * + * This considers only the node and its children, not its context. After + * parsing, check the node's prologue flag to see if it is indeed part of + * a directive prologue. + * + * Note that a Directive Prologue can contain statements that cannot + * themselves be directives (string literals that include escape sequences + * or escaped newlines, say). This member function returns true for such + * nodes; we use it to determine the extent of the prologue. + */ + JSAtom* isStringExprStatement() const { + if (isKind(PNK_SEMI)) { + ParseNode* expr = kid(); + if (expr && expr->isKind(PNK_STRING) && !expr->isInParens()) { + return expr->pn_atom; + } + } + return nullptr; + } + + // Methods used by FoldConstants.cpp. + ParseNode** unsafeKidReference() { + return &pn_u.unary.kid; + } }; class BinaryNode : public ParseNode @@ -1565,6 +1589,12 @@ class ThisLiteral : public UnaryNode ThisLiteral(const TokenPos& pos, ParseNode* thisName) : UnaryNode(PNK_THIS, JSOP_NOP, pos, thisName) { } + + static bool test(const ParseNode& node) { + bool match = node.isKind(PNK_THIS); + MOZ_ASSERT_IF(match, node.is()); + return match; + } }; class NullLiteral : public ParseNode diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index d3849d10d6..86a9fcc7a0 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -3977,7 +3977,7 @@ Parser::asmJS(ListNodeType list) * Recognize Directive Prologue members and directives. Assuming |pn| is a * candidate for membership in a directive prologue, recognize directives and * set |pc|'s flags accordingly. If |pn| is indeed part of a prologue, set its - * |pn_prologue| flag. + * |prologue| flag. * * Note that the following is a strict mode function: * @@ -4014,7 +4014,7 @@ Parser::maybeParseDirective(ListNodeType list, Node possibleDirect // directive in the future. We don't want to interfere with people // taking advantage of directive-prologue-enabled features that appear // in other browsers first. - handler.setInDirectivePrologue(possibleDirective); + handler.setInDirectivePrologue(handler.asUnary(possibleDirective)); if (directive == context->names().useStrict) { // Functions with non-simple parameter lists (destructuring, @@ -5229,7 +5229,7 @@ Parser::checkExportedNamesForArrayBinding(ListNode* array) ParseNode* binding; if (node->isKind(PNK_SPREAD)) - binding = node->pn_kid; + binding = node->as().kid(); else if (node->isKind(PNK_ASSIGN)) binding = node->as().left(); else @@ -5264,10 +5264,10 @@ Parser::checkExportedNamesForObjectBinding(ListNode* obj) ParseNode* target; if (node->isKind(PNK_SPREAD)) { - target = node->pn_kid; + target = node->as().kid(); } else { if (node->isKind(PNK_MUTATEPROTO)) - target = node->pn_kid; + target = node->as().kid(); else target = node->as().right(); @@ -5590,7 +5590,7 @@ Parser::exportClause(uint32_t begin) if (!checkLocalExportNames(kid)) return null(); - Node node = handler.newExportDeclaration(kid, TokenPos(begin, pos().end)); + UnaryNodeType node = handler.newExportDeclaration(kid, TokenPos(begin, pos().end)); if (!node) return null(); @@ -5601,7 +5601,7 @@ Parser::exportClause(uint32_t begin) } template -typename ParseHandler::Node +typename ParseHandler::UnaryNodeType Parser::exportVariableStatement(uint32_t begin) { if (!abortIfSyntaxParser()) @@ -5617,7 +5617,7 @@ Parser::exportVariableStatement(uint32_t begin) if (!checkExportedNamesForDeclarationList(kid)) return null(); - Node node = handler.newExportDeclaration(kid, TokenPos(begin, pos().end)); + UnaryNodeType node = handler.newExportDeclaration(kid, TokenPos(begin, pos().end)); if (!node) return null(); @@ -5628,7 +5628,7 @@ Parser::exportVariableStatement(uint32_t begin) } template -typename ParseHandler::Node +typename ParseHandler::UnaryNodeType Parser::exportFunctionDeclaration(uint32_t begin) { if (!abortIfSyntaxParser()) @@ -5643,7 +5643,7 @@ Parser::exportFunctionDeclaration(uint32_t begin) if (!checkExportedNameForFunction(kid)) return null(); - Node node = handler.newExportDeclaration(kid, TokenPos(begin, pos().end)); + UnaryNodeType node = handler.newExportDeclaration(kid, TokenPos(begin, pos().end)); if (!node) return null(); @@ -5654,7 +5654,7 @@ Parser::exportFunctionDeclaration(uint32_t begin) } template -typename ParseHandler::Node +typename ParseHandler::UnaryNodeType Parser::exportClassDeclaration(uint32_t begin) { if (!abortIfSyntaxParser()) @@ -5669,7 +5669,7 @@ Parser::exportClassDeclaration(uint32_t begin) if (!checkExportedNameForClass(kid)) return null(); - Node node = handler.newExportDeclaration(kid, TokenPos(begin, pos().end)); + UnaryNodeType node = handler.newExportDeclaration(kid, TokenPos(begin, pos().end)); if (!node) return null(); @@ -5680,7 +5680,7 @@ Parser::exportClassDeclaration(uint32_t begin) } template -typename ParseHandler::Node +typename ParseHandler::UnaryNodeType Parser::exportLexicalDeclaration(uint32_t begin, DeclarationKind kind) { if (!abortIfSyntaxParser()) @@ -5696,7 +5696,7 @@ Parser::exportLexicalDeclaration(uint32_t begin, DeclarationKind k if (!checkExportedNamesForDeclarationList(kid)) return null(); - Node node = handler.newExportDeclaration(kid, TokenPos(begin, pos().end)); + UnaryNodeType node = handler.newExportDeclaration(kid, TokenPos(begin, pos().end)); if (!node) return null(); @@ -5878,7 +5878,7 @@ Parser::exportDeclaration() } template -typename ParseHandler::Node +typename ParseHandler::UnaryNodeType Parser::expressionStatement(YieldHandling yieldHandling, InvokedPrediction invoked) { tokenStream.ungetToken(); @@ -6635,7 +6635,7 @@ Parser::breakStatement(YieldHandling yieldHandling) } template -typename ParseHandler::Node +typename ParseHandler::UnaryNodeType Parser::returnStatement(YieldHandling yieldHandling) { MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_RETURN)); @@ -6675,7 +6675,7 @@ Parser::returnStatement(YieldHandling yieldHandling) return null(); } - Node pn = handler.newReturnStatement(exprNode, TokenPos(begin, pos().end)); + UnaryNodeType pn = handler.newReturnStatement(exprNode, TokenPos(begin, pos().end)); if (!pn) return null(); @@ -6689,7 +6689,7 @@ Parser::returnStatement(YieldHandling yieldHandling) } template -typename ParseHandler::Node +typename ParseHandler::UnaryNodeType Parser::yieldExpression(InHandling inHandling) { MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_YIELD)); @@ -6924,7 +6924,7 @@ Parser::labeledStatement(YieldHandling yieldHandling) } template -typename ParseHandler::Node +typename ParseHandler::UnaryNodeType Parser::throwStatement(YieldHandling yieldHandling) { MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_THROW)); @@ -8540,7 +8540,7 @@ Parser::checkIncDecOperand(Node operand, uint32_t operandOffset) } template -typename ParseHandler::Node +typename ParseHandler::UnaryNodeType Parser::unaryOpExpr(YieldHandling yieldHandling, ParseNodeKind kind, JSOp op, uint32_t begin) { @@ -10065,7 +10065,7 @@ Parser::propertyName(YieldHandling yieldHandling, } template -typename ParseHandler::Node +typename ParseHandler::UnaryNodeType Parser::computedPropertyName(YieldHandling yieldHandling, const Maybe& maybeDecl, ListNodeType literal) diff --git a/js/src/frontend/Parser.h b/js/src/frontend/Parser.h index b4a4540f5a..332956716c 100644 --- a/js/src/frontend/Parser.h +++ b/js/src/frontend/Parser.h @@ -1213,9 +1213,9 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE) SwitchStatementType switchStatement(YieldHandling yieldHandling); Node continueStatement(YieldHandling yieldHandling); Node breakStatement(YieldHandling yieldHandling); - Node returnStatement(YieldHandling yieldHandling); + UnaryNodeType returnStatement(YieldHandling yieldHandling); BinaryNodeType withStatement(YieldHandling yieldHandling); - Node throwStatement(YieldHandling yieldHandling); + UnaryNodeType throwStatement(YieldHandling yieldHandling); TernaryNodeType tryStatement(YieldHandling yieldHandling); Node catchBlockStatement(YieldHandling yieldHandling, ParseContext::Scope& catchParamScope); Node debuggerStatement(); @@ -1244,10 +1244,10 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE) BinaryNodeType exportBatch(uint32_t begin); bool checkLocalExportNames(ListNodeType node); Node exportClause(uint32_t begin); - Node exportFunctionDeclaration(uint32_t begin); - Node exportVariableStatement(uint32_t begin); - Node exportClassDeclaration(uint32_t begin); - Node exportLexicalDeclaration(uint32_t begin, DeclarationKind kind); + UnaryNodeType exportFunctionDeclaration(uint32_t begin); + UnaryNodeType exportVariableStatement(uint32_t begin); + UnaryNodeType exportClassDeclaration(uint32_t begin); + UnaryNodeType exportLexicalDeclaration(uint32_t begin, DeclarationKind kind); BinaryNodeType exportDefaultFunctionDeclaration(uint32_t begin, FunctionAsyncKind asyncKind = SyncFunction); BinaryNodeType exportDefaultClassDeclaration(uint32_t begin); @@ -1255,7 +1255,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE) BinaryNodeType exportDefault(uint32_t begin); Node exportDeclaration(); - Node expressionStatement(YieldHandling yieldHandling, + UnaryNodeType expressionStatement(YieldHandling yieldHandling, InvokedPrediction invoked = PredictUninvoked); // Declaration parsing. The main entrypoint is Parser::declarationList, @@ -1316,7 +1316,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE) TripledotHandling tripledotHandling, PossibleError* possibleError = nullptr, InvokedPrediction invoked = PredictUninvoked); Node assignExprWithoutYieldOrAwait(YieldHandling yieldHandling); - Node yieldExpression(InHandling inHandling); + UnaryNodeType yieldExpression(InHandling inHandling); Node condExpr1(InHandling inHandling, YieldHandling yieldHandling, TripledotHandling tripledotHandling, PossibleError* possibleError, @@ -1366,7 +1366,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE) Node functionBody(InHandling inHandling, YieldHandling yieldHandling, FunctionSyntaxKind kind, FunctionBodyType type); - Node unaryOpExpr(YieldHandling yieldHandling, ParseNodeKind kind, JSOp op, uint32_t begin); + UnaryNodeType unaryOpExpr(YieldHandling yieldHandling, ParseNodeKind kind, JSOp op, uint32_t begin); Node condition(InHandling inHandling, YieldHandling yieldHandling); @@ -1519,8 +1519,8 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE) Node propertyName(YieldHandling yieldHandling, const mozilla::Maybe& maybeDecl, ListNodeType propList, PropertyType* propType, MutableHandleAtom propAtom); - Node computedPropertyName(YieldHandling yieldHandling, - const mozilla::Maybe& maybeDecl, ListNodeType literal); + UnaryNodeType computedPropertyName(YieldHandling yieldHandling, + const mozilla::Maybe& maybeDecl, ListNodeType literal); ListNodeType arrayInitializer(YieldHandling yieldHandling, PossibleError* possibleError); Node newRegExp(); diff --git a/js/src/frontend/SyntaxParseHandler.h b/js/src/frontend/SyntaxParseHandler.h index 9ca68cac5e..bb382447c6 100644 --- a/js/src/frontend/SyntaxParseHandler.h +++ b/js/src/frontend/SyntaxParseHandler.h @@ -215,7 +215,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) return NodeUnparenthesizedName; } - Node newComputedName(Node expr, uint32_t start, uint32_t end) { + UnaryNodeType newComputedName(Node expr, uint32_t start, uint32_t end) { return NodeGeneric; } @@ -242,7 +242,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) void addToCallSiteObject(CallSiteNodeType callSiteObj, Node rawNode, Node cookedNode) {} - Node newThisLiteral(const TokenPos& pos, Node thisName) { return NodeGeneric; } + UnaryNodeType newThisLiteral(const TokenPos& pos, Node thisName) { return NodeGeneric; } Node newNullLiteral(const TokenPos& pos) { return NodeGeneric; } Node newRawUndefinedLiteral(const TokenPos& pos) { return NodeGeneric; } @@ -255,11 +255,11 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) Node newElision() { return NodeGeneric; } - Node newDelete(uint32_t begin, Node expr) { + UnaryNodeType newDelete(uint32_t begin, Node expr) { return NodeUnparenthesizedUnary; } - Node newTypeof(uint32_t begin, Node kid) { + UnaryNodeType newTypeof(uint32_t begin, Node kid) { return NodeUnparenthesizedUnary; } @@ -267,15 +267,15 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) return NodeGeneric; } - Node newUnary(ParseNodeKind kind, JSOp op, uint32_t begin, Node kid) { + UnaryNodeType newUnary(ParseNodeKind kind, JSOp op, uint32_t begin, Node kid) { return NodeUnparenthesizedUnary; } - Node newUpdate(ParseNodeKind kind, uint32_t begin, Node kid) { + UnaryNodeType newUpdate(ParseNodeKind kind, uint32_t begin, Node kid) { return NodeGeneric; } - Node newSpread(uint32_t begin, Node kid) { + UnaryNodeType newSpread(uint32_t begin, Node kid) { return NodeGeneric; } @@ -318,7 +318,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) BinaryNodeType newNewTarget(Node newHolder, Node targetHolder) { return NodeGeneric; } Node newPosHolder(const TokenPos& pos) { return NodeGeneric; } - Node newSuperBase(Node thisName, const TokenPos& pos) { return NodeSuperBase; } + UnaryNodeType newSuperBase(Node thisName, const TokenPos& pos) { return NodeSuperBase; } MOZ_MUST_USE bool addPrototypeMutation(ListNodeType literal, uint32_t begin, Node expr) { return true; } MOZ_MUST_USE bool addPropertyDefinition(ListNodeType literal, Node name, Node expr) { return true; } @@ -326,9 +326,9 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) MOZ_MUST_USE bool addSpreadProperty(ListNodeType literal, uint32_t begin, Node inner) { return true; } MOZ_MUST_USE bool addObjectMethodDefinition(ListNodeType literal, Node name, Node fn, JSOp op) { return true; } MOZ_MUST_USE bool addClassMethodDefinition(ListNodeType literal, Node name, Node fn, JSOp op, bool isStatic) { return true; } - 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; } + UnaryNodeType newYieldExpression(uint32_t begin, Node value) { return NodeGeneric; } + UnaryNodeType newYieldStarExpression(uint32_t begin, Node value) { return NodeGeneric; } + UnaryNodeType newAwaitExpression(uint32_t begin, Node value) { return NodeGeneric; } Node newOptionalChain(uint32_t begin, Node value) { return NodeGeneric; } // Statements @@ -339,7 +339,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) MOZ_MUST_USE bool prependInitialYield(ListNodeType stmtList, Node genName) { return true; } Node newEmptyStatement(const TokenPos& pos) { return NodeEmptyStatement; } - Node newExportDeclaration(Node kid, const TokenPos& pos) { + UnaryNodeType newExportDeclaration(Node kid, const TokenPos& pos) { return NodeGeneric; } BinaryNodeType newExportFromDeclaration(uint32_t begin, Node exportSpecSet, Node moduleSpec) { @@ -351,7 +351,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) BinaryNodeType newSetThis(Node thisName, Node value) { return value; } - Node newExprStatement(Node expr, uint32_t end) { + UnaryNodeType newExprStatement(Node expr, uint32_t end) { return expr == NodeUnparenthesizedString ? NodeStringExprStatement : NodeGeneric; } @@ -367,14 +367,14 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) CaseClauseType newCaseOrDefault(uint32_t begin, Node expr, Node body) { return NodeGeneric; } Node newContinueStatement(PropertyName* label, const TokenPos& pos) { return NodeGeneric; } Node newBreakStatement(PropertyName* label, const TokenPos& pos) { return NodeBreak; } - Node newReturnStatement(Node expr, const TokenPos& pos) { return NodeReturn; } + UnaryNodeType newReturnStatement(Node expr, const TokenPos& pos) { return NodeReturn; } BinaryNodeType newWithStatement(uint32_t begin, Node expr, Node body) { return NodeGeneric; } Node newLabeledStatement(PropertyName* label, Node stmt, uint32_t begin) { return NodeGeneric; } - Node newThrowStatement(Node expr, const TokenPos& pos) { return NodeThrow; } + UnaryNodeType newThrowStatement(Node expr, const TokenPos& pos) { return NodeThrow; } Node newTryStatement(uint32_t begin, Node body, ListNodeType catchList, Node finallyBlock) { return NodeGeneric; } @@ -590,7 +590,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) MOZ_MUST_USE Node setLikelyIIFE(Node pn) { return pn; // Remain in syntax-parse mode. } - void setInDirectivePrologue(Node pn) {} + void setInDirectivePrologue(UnaryNodeType exprStmt) {} bool isConstant(Node pn) { return false; } diff --git a/js/src/wasm/AsmJS.cpp b/js/src/wasm/AsmJS.cpp index ce4d06ea81..ff3dc5d1e9 100644 --- a/js/src/wasm/AsmJS.cpp +++ b/js/src/wasm/AsmJS.cpp @@ -402,8 +402,7 @@ NextNode(ParseNode* pn) static inline ParseNode* UnaryKid(ParseNode* pn) { - MOZ_ASSERT(pn->isArity(PN_UNARY)); - return pn->pn_kid; + return pn->as().kid(); } static inline ParseNode* -- cgit v1.2.3