From 662419c507d7ce0e1cf75fa2efa29f40af79c018 Mon Sep 17 00:00:00 2001 From: Martok Date: Sun, 26 Mar 2023 06:08:53 +0200 Subject: [PATCH] Issue #2173 - Add accessors to BinaryNode and subclasses Based-on: m-c 1479659/3 --- js/src/builtin/ModuleObject.cpp | 100 +++--- js/src/builtin/ModuleObject.h | 7 +- js/src/builtin/ReflectParse.cpp | 397 +++++++++++----------- js/src/frontend/BytecodeEmitter.cpp | 473 ++++++++++++++------------- js/src/frontend/BytecodeEmitter.h | 38 +-- js/src/frontend/FoldConstants.cpp | 183 ++++++----- js/src/frontend/FullParseHandler.h | 109 +++--- js/src/frontend/NameFunctions.cpp | 162 +++++---- js/src/frontend/ParseNode.cpp | 57 ++-- js/src/frontend/ParseNode.h | 380 +++++++++++++-------- js/src/frontend/Parser.cpp | 93 +++--- js/src/frontend/Parser.h | 30 +- js/src/frontend/SyntaxParseHandler.h | 40 +-- js/src/wasm/AsmJS.cpp | 20 +- 14 files changed, 1152 insertions(+), 937 deletions(-) diff --git a/js/src/builtin/ModuleObject.cpp b/js/src/builtin/ModuleObject.cpp index ede904f279..d97304cf1a 100644 --- a/js/src/builtin/ModuleObject.cpp +++ b/js/src/builtin/ModuleObject.cpp @@ -1161,31 +1161,40 @@ ModuleBuilder::initModule() } bool -ModuleBuilder::processImport(frontend::ParseNode* pn) +ModuleBuilder::processImport(frontend::BinaryNode* importNode) { - MOZ_ASSERT(pn->isKind(PNK_IMPORT)); - MOZ_ASSERT(pn->isArity(PN_BINARY)); - MOZ_ASSERT(pn->pn_left->isKind(PNK_IMPORT_SPEC_LIST)); - MOZ_ASSERT(pn->pn_right->isKind(PNK_STRING)); + MOZ_ASSERT(importNode->isKind(PNK_IMPORT)); + + ListNode* specList = &importNode->left()->as(); + MOZ_ASSERT(specList->isKind(PNK_IMPORT_SPEC_LIST)); + + ParseNode* moduleSpec = importNode->right(); + MOZ_ASSERT(moduleSpec->isKind(PNK_STRING)); - RootedAtom module(cx_, pn->pn_right->pn_atom); + RootedAtom module(cx_, moduleSpec->pn_atom); if (!maybeAppendRequestedModule(module)) return false; - for (ParseNode* spec : pn->pn_left->as().contents()) { + RootedAtom importName(cx_); + RootedAtom localName(cx_); + for (ParseNode* item : specList->contents()) { + BinaryNode* spec = &item->as(); MOZ_ASSERT(spec->isKind(PNK_IMPORT_SPEC)); - MOZ_ASSERT(spec->pn_left->isArity(PN_NAME)); - MOZ_ASSERT(spec->pn_right->isArity(PN_NAME)); + + ParseNode* importNameNode = spec->left(); + MOZ_ASSERT(importNameNode->isArity(PN_NAME)); + ParseNode* localNameNode = spec->right(); + MOZ_ASSERT(localNameNode->isArity(PN_NAME)); - RootedAtom importName(cx_, spec->pn_left->pn_atom); - RootedAtom localName(cx_, spec->pn_right->pn_atom); + RootedAtom importName(cx_, importNameNode->pn_atom); + RootedAtom localName(cx_, localNameNode->pn_atom); if (!importedBoundNames_.append(localName)) return false; uint32_t line; uint32_t column; - tokenStream_.srcCoords.lineNumAndColumnIndex(spec->pn_left->pn_pos.begin, &line, &column); + tokenStream_.srcCoords.lineNumAndColumnIndex(importNameNode->pn_pos.begin, &line, &column); RootedImportEntryObject importEntry(cx_); importEntry = ImportEntryObject::create(cx_, module, importName, localName, line, column); @@ -1197,15 +1206,16 @@ ModuleBuilder::processImport(frontend::ParseNode* pn) } bool -ModuleBuilder::processExport(frontend::ParseNode* pn) +ModuleBuilder::processExport(frontend::ParseNode* exportNode) { - MOZ_ASSERT(pn->isKind(PNK_EXPORT) || pn->isKind(PNK_EXPORT_DEFAULT)); - MOZ_ASSERT(pn->getArity() == (pn->isKind(PNK_EXPORT) ? PN_UNARY : PN_BINARY)); + MOZ_ASSERT(exportNode->isKind(PNK_EXPORT) || + exportNode->isKind(PNK_EXPORT_DEFAULT)); + MOZ_ASSERT_IF(exportNode->isKind(PNK_EXPORT), exportNode->is()); - bool isDefault = pn->getKind() == PNK_EXPORT_DEFAULT; - ParseNode* kid = isDefault ? pn->pn_left : pn->pn_kid; + bool isDefault = exportNode->isKind(PNK_EXPORT_DEFAULT); + ParseNode* kid = isDefault ? exportNode->as().left() : exportNode->pn_kid; - if (isDefault && pn->pn_right) { + if (isDefault && exportNode->as().right()) { // This is an export default containing an expression. RootedAtom localName(cx_, cx_->names().starDefaultStar); RootedAtom exportName(cx_, cx_->names().default_); @@ -1213,16 +1223,23 @@ ModuleBuilder::processExport(frontend::ParseNode* pn) } switch (kid->getKind()) { - case PNK_EXPORT_SPEC_LIST: + case PNK_EXPORT_SPEC_LIST: { MOZ_ASSERT(!isDefault); - for (ParseNode* spec : kid->as().contents()) { + RootedAtom localName(cx_); + RootedAtom exportName(cx_); + for (ParseNode* item : kid->as().contents()) { + BinaryNode* spec = &item->as(); MOZ_ASSERT(spec->isKind(PNK_EXPORT_SPEC)); - RootedAtom localName(cx_, spec->pn_left->pn_atom); - RootedAtom exportName(cx_, spec->pn_right->pn_atom); + + ParseNode* localNameNode = spec->left(); + ParseNode* exportNameNode = spec->right(); + localName = localNameNode->pn_atom; + exportName = exportNameNode->pn_atom; if (!appendExportEntry(exportName, localName, spec)) return false; } break; + } case PNK_CLASS: { const ClassNode& cls = kid->as(); @@ -1240,7 +1257,7 @@ ModuleBuilder::processExport(frontend::ParseNode* pn) MOZ_ASSERT(kid->isArity(PN_LIST)); for (ParseNode* binding : kid->as().contents()) { if (binding->isKind(PNK_ASSIGN)) - binding = binding->pn_left; + binding = binding->as().left(); else MOZ_ASSERT(binding->isKind(PNK_NAME)); @@ -1306,7 +1323,7 @@ ModuleBuilder::processExportArrayBinding(frontend::ListNode* array) if (node->isKind(PNK_SPREAD)) node = node->pn_kid; else if (node->isKind(PNK_ASSIGN)) - node = node->pn_left; + node = node->as().left(); if (!processExportBinding(node)) return false; @@ -1333,10 +1350,10 @@ ModuleBuilder::processExportObjectBinding(frontend::ListNode* obj) if (node->isKind(PNK_MUTATEPROTO)) target = node->pn_kid; else - target = node->pn_right; + target = node->as().right(); if (target->isKind(PNK_ASSIGN)) - target = target->pn_left; + target = target->as().left(); } if (!processExportBinding(target)) @@ -1347,27 +1364,34 @@ ModuleBuilder::processExportObjectBinding(frontend::ListNode* obj) } bool -ModuleBuilder::processExportFrom(frontend::ParseNode* pn) +ModuleBuilder::processExportFrom(frontend::BinaryNode* exportNode) { - MOZ_ASSERT(pn->isKind(PNK_EXPORT_FROM)); - MOZ_ASSERT(pn->isArity(PN_BINARY)); - MOZ_ASSERT(pn->pn_left->isKind(PNK_EXPORT_SPEC_LIST)); - MOZ_ASSERT(pn->pn_right->isKind(PNK_STRING)); + MOZ_ASSERT(exportNode->isKind(PNK_EXPORT_FROM)); - RootedAtom module(cx_, pn->pn_right->pn_atom); + ListNode* specList = &exportNode->left()->as(); + MOZ_ASSERT(specList->isKind(PNK_EXPORT_SPEC_LIST)); + + ParseNode* moduleSpec = exportNode->right(); + MOZ_ASSERT(moduleSpec->isKind(PNK_STRING)); + + RootedAtom module(cx_, moduleSpec->pn_atom); if (!maybeAppendRequestedModule(module)) return false; - for (ParseNode* spec : pn->pn_left->as().contents()) { + RootedAtom bindingName(cx_); + RootedAtom exportName(cx_); + for (ParseNode* spec : specList->contents()) { if (spec->isKind(PNK_EXPORT_SPEC)) { - RootedAtom bindingName(cx_, spec->pn_left->pn_atom); - RootedAtom exportName(cx_, spec->pn_right->pn_atom); - if (!appendExportFromEntry(exportName, module, bindingName, spec->pn_left)) + ParseNode* localNameNode = spec->as().left(); + ParseNode* exportNameNode = spec->as().right(); + bindingName = localNameNode->pn_atom; + exportName = exportNameNode->pn_atom; + if (!appendExportFromEntry(exportName, module, bindingName, localNameNode)) return false; } else { MOZ_ASSERT(spec->isKind(PNK_EXPORT_BATCH_SPEC)); - RootedAtom importName(cx_, cx_->names().star); - if (!appendExportFromEntry(nullptr, module, importName, spec)) + exportName = cx_->names().star; + if (!appendExportFromEntry(nullptr, module, exportName, spec)) return false; } } diff --git a/js/src/builtin/ModuleObject.h b/js/src/builtin/ModuleObject.h index 9c10f8465e..a2512db091 100644 --- a/js/src/builtin/ModuleObject.h +++ b/js/src/builtin/ModuleObject.h @@ -24,6 +24,7 @@ class ModuleEnvironmentObject; class ModuleObject; namespace frontend { +class BinaryNode; class ListNode; class ParseNode; class TokenStream; @@ -319,9 +320,9 @@ class MOZ_STACK_CLASS ModuleBuilder explicit ModuleBuilder(ExclusiveContext* cx, HandleModuleObject module, const frontend::TokenStream& tokenStream); - bool processImport(frontend::ParseNode* pn); - bool processExport(frontend::ParseNode* pn); - bool processExportFrom(frontend::ParseNode* pn); + bool processImport(frontend::BinaryNode* importNode); + bool processExport(frontend::ParseNode* exportNode); + bool processExportFrom(frontend::BinaryNode* exportNode); bool hasExportedName(JSAtom* name) const; diff --git a/js/src/builtin/ReflectParse.cpp b/js/src/builtin/ReflectParse.cpp index e1dad1f4b6..2cee92eabe 100644 --- a/js/src/builtin/ReflectParse.cpp +++ b/js/src/builtin/ReflectParse.cpp @@ -1802,10 +1802,10 @@ class ASTSerializer bool declaration(ParseNode* pn, MutableHandleValue dst); bool variableDeclaration(ListNode* declList, bool lexical, MutableHandleValue dst); bool variableDeclarator(ParseNode* pn, MutableHandleValue dst); - bool importDeclaration(ParseNode* pn, MutableHandleValue dst); - bool importSpecifier(ParseNode* pn, MutableHandleValue dst); - bool exportDeclaration(ParseNode* pn, MutableHandleValue dst); - bool exportSpecifier(ParseNode* pn, MutableHandleValue dst); + bool importDeclaration(BinaryNode* importNode, MutableHandleValue dst); + bool importSpecifier(BinaryNode* importSpec, MutableHandleValue dst); + bool exportDeclaration(ParseNode* exportNode, MutableHandleValue dst); + bool exportSpecifier(BinaryNode* exportSpec, MutableHandleValue dst); bool classDefinition(ClassNode* pn, bool expr, MutableHandleValue dst); bool optStatement(ParseNode* pn, MutableHandleValue dst) { @@ -1817,14 +1817,14 @@ class ASTSerializer } bool forInit(ParseNode* pn, MutableHandleValue dst); - bool forIn(ParseNode* loop, ParseNode* iterExpr, HandleValue var, HandleValue stmt, + bool forIn(ForNode* loop, ParseNode* iterExpr, HandleValue var, HandleValue stmt, MutableHandleValue dst); - bool forOf(ParseNode* loop, ParseNode* iterExpr, HandleValue var, HandleValue stmt, + bool forOf(ForNode* loop, ParseNode* iterExpr, HandleValue var, HandleValue stmt, MutableHandleValue dst); bool statement(ParseNode* pn, MutableHandleValue dst); bool blockStatement(ListNode* node, MutableHandleValue dst); - bool switchStatement(ParseNode* pn, MutableHandleValue dst); - bool switchCase(ParseNode* pn, MutableHandleValue dst); + bool switchStatement(SwitchStatement* switchStmt, MutableHandleValue dst); + bool switchCase(CaseClause* caseClause, MutableHandleValue dst); bool tryStatement(TernaryNode* tryNode, MutableHandleValue dst); bool catchClause(TernaryNode* clauseNode, bool* isGuarded, MutableHandleValue dst); @@ -1841,7 +1841,7 @@ class ASTSerializer bool propertyName(ParseNode* pn, MutableHandleValue dst); bool property(ParseNode* pn, MutableHandleValue dst); - bool classMethod(ParseNode* pn, MutableHandleValue dst); + bool classMethod(ClassMethod* classMethod, MutableHandleValue dst); bool optIdentifier(HandleAtom atom, TokenPos* pos, MutableHandleValue dst) { if (!atom) { @@ -1873,7 +1873,7 @@ class ASTSerializer MutableHandleValue body, MutableHandleValue rest); bool functionBody(ParseNode* pn, TokenPos* pos, MutableHandleValue dst); - bool comprehensionBlock(ParseNode* pn, MutableHandleValue dst); + bool comprehensionBlock(ForNode* forNode, MutableHandleValue dst); bool comprehensionIf(TernaryNode* ifNode, MutableHandleValue dst); bool comprehension(ParseNode* pn, MutableHandleValue dst); bool generatorExpression(ParseNode* pn, MutableHandleValue dst); @@ -2135,45 +2135,48 @@ ASTSerializer::variableDeclaration(ListNode* declList, bool lexical, MutableHand bool ASTSerializer::variableDeclarator(ParseNode* pn, MutableHandleValue dst) { - ParseNode* pnleft; - ParseNode* pnright; + ParseNode* patternNode; + ParseNode* initNode; if (pn->isKind(PNK_NAME)) { - pnleft = pn; - pnright = pn->pn_expr; - MOZ_ASSERT_IF(pnright, pn->pn_pos.encloses(pnright->pn_pos)); + patternNode = pn; + initNode = pn->pn_expr; + MOZ_ASSERT_IF(initNode, pn->pn_pos.encloses(initNode->pn_pos)); } else if (pn->isKind(PNK_ASSIGN)) { - pnleft = pn->pn_left; - pnright = pn->pn_right; - MOZ_ASSERT(pn->pn_pos.encloses(pnleft->pn_pos)); - MOZ_ASSERT(pn->pn_pos.encloses(pnright->pn_pos)); + AssignmentNode* assignNode = &pn->as(); + patternNode = assignNode->left(); + initNode = assignNode->right(); + MOZ_ASSERT(pn->pn_pos.encloses(patternNode->pn_pos)); + MOZ_ASSERT(pn->pn_pos.encloses(initNode->pn_pos)); } else { /* This happens for a destructuring declarator in a for-in/of loop. */ - pnleft = pn; - pnright = nullptr; + patternNode = pn; + initNode = nullptr; } - RootedValue left(cx), right(cx); - return pattern(pnleft, &left) && - optExpression(pnright, &right) && - builder.variableDeclarator(left, right, &pn->pn_pos, dst); + RootedValue patternVal(cx), init(cx); + return pattern(patternNode, &patternVal) && + optExpression(initNode, &init) && + builder.variableDeclarator(patternVal, init, &pn->pn_pos, dst); } bool -ASTSerializer::importDeclaration(ParseNode* pn, MutableHandleValue dst) +ASTSerializer::importDeclaration(BinaryNode* importNode, MutableHandleValue dst) { - MOZ_ASSERT(pn->isKind(PNK_IMPORT)); - MOZ_ASSERT(pn->isArity(PN_BINARY)); - MOZ_ASSERT(pn->pn_left->isKind(PNK_IMPORT_SPEC_LIST)); - MOZ_ASSERT(pn->pn_right->isKind(PNK_STRING)); + MOZ_ASSERT(importNode->isKind(PNK_IMPORT)); - ListNode* specList = &pn->pn_left->as(); + ListNode* specList = &importNode->left()->as(); + MOZ_ASSERT(specList->isKind(PNK_IMPORT_SPEC_LIST)); + + ParseNode* moduleSpecNode = importNode->right(); + MOZ_ASSERT(moduleSpecNode->isKind(PNK_STRING)); NodeVector elts(cx); if (!elts.reserve(specList->count())) return false; - for (ParseNode* spec : specList->contents()) { + for (ParseNode* item : specList->contents()) { + BinaryNode* spec = &item->as(); RootedValue elt(cx); if (!importSpecifier(spec, &elt)) return false; @@ -2181,48 +2184,51 @@ ASTSerializer::importDeclaration(ParseNode* pn, MutableHandleValue dst) } RootedValue moduleSpec(cx); - return literal(pn->pn_right, &moduleSpec) && - builder.importDeclaration(elts, moduleSpec, &pn->pn_pos, dst); + return literal(moduleSpecNode, &moduleSpec) && + builder.importDeclaration(elts, moduleSpec, &importNode->pn_pos, dst); } bool -ASTSerializer::importSpecifier(ParseNode* pn, MutableHandleValue dst) +ASTSerializer::importSpecifier(BinaryNode* importSpec, MutableHandleValue dst) { - MOZ_ASSERT(pn->isKind(PNK_IMPORT_SPEC)); + MOZ_ASSERT(importSpec->isKind(PNK_IMPORT_SPEC)); RootedValue importName(cx); RootedValue bindingName(cx); - return identifier(pn->pn_left, &importName) && - identifier(pn->pn_right, &bindingName) && - builder.importSpecifier(importName, bindingName, &pn->pn_pos, dst); + return identifier(importSpec->left(), &importName) && + identifier(importSpec->right(), &bindingName) && + builder.importSpecifier(importName, bindingName, &importSpec->pn_pos, dst); } bool -ASTSerializer::exportDeclaration(ParseNode* pn, MutableHandleValue dst) +ASTSerializer::exportDeclaration(ParseNode* exportNode, MutableHandleValue dst) { - MOZ_ASSERT(pn->isKind(PNK_EXPORT) || - pn->isKind(PNK_EXPORT_FROM) || - pn->isKind(PNK_EXPORT_DEFAULT)); - MOZ_ASSERT(pn->getArity() == (pn->isKind(PNK_EXPORT) ? PN_UNARY : PN_BINARY)); - MOZ_ASSERT_IF(pn->isKind(PNK_EXPORT_FROM), pn->pn_right->isKind(PNK_STRING)); + MOZ_ASSERT(exportNode->isKind(PNK_EXPORT) || + exportNode->isKind(PNK_EXPORT_FROM) || + exportNode->isKind(PNK_EXPORT_DEFAULT)); + MOZ_ASSERT_IF(exportNode->isKind(PNK_EXPORT), exportNode->is()); + MOZ_ASSERT_IF(exportNode->isKind(PNK_EXPORT_FROM), + exportNode->as().right()->isKind(PNK_STRING)); RootedValue decl(cx, NullValue()); NodeVector elts(cx); - ParseNode* kid = pn->isKind(PNK_EXPORT) ? pn->pn_kid : pn->pn_left; + ParseNode* kid = exportNode->isKind(PNK_EXPORT) + ? exportNode->pn_kid + : exportNode->as().left(); switch (ParseNodeKind kind = kid->getKind()) { case PNK_EXPORT_SPEC_LIST: { - ListNode* specList = &pn->pn_left->as(); + ListNode* specList = &kid->as(); if (!elts.reserve(specList->count())) return false; for (ParseNode* spec : specList->contents()) { RootedValue elt(cx); if (spec->isKind(PNK_EXPORT_SPEC)) { - if (!exportSpecifier(spec, &elt)) + if (!exportSpecifier(&spec->as(), &elt)) return false; } else { - if (!builder.exportBatchSpecifier(&pn->pn_pos, &elt)) + if (!builder.exportBatchSpecifier(&exportNode->pn_pos, &elt)) return false; } elts.infallibleAppend(elt); @@ -2254,70 +2260,72 @@ ASTSerializer::exportDeclaration(ParseNode* pn, MutableHandleValue dst) } RootedValue moduleSpec(cx, NullValue()); - if (pn->isKind(PNK_EXPORT_FROM) && !literal(pn->pn_right, &moduleSpec)) - return false; + if (exportNode->isKind(PNK_EXPORT_FROM)) { + if (!literal(exportNode->as().right(), &moduleSpec)) { + return false; + } + } RootedValue isDefault(cx, BooleanValue(false)); - if (pn->isKind(PNK_EXPORT_DEFAULT)) + if (exportNode->isKind(PNK_EXPORT_DEFAULT)) isDefault.setBoolean(true); - return builder.exportDeclaration(decl, elts, moduleSpec, isDefault, &pn->pn_pos, dst); + return builder.exportDeclaration(decl, elts, moduleSpec, isDefault, &exportNode->pn_pos, dst); } bool -ASTSerializer::exportSpecifier(ParseNode* pn, MutableHandleValue dst) +ASTSerializer::exportSpecifier(BinaryNode* exportSpec, MutableHandleValue dst) { - MOZ_ASSERT(pn->isKind(PNK_EXPORT_SPEC)); + MOZ_ASSERT(exportSpec->isKind(PNK_EXPORT_SPEC)); RootedValue bindingName(cx); RootedValue exportName(cx); - return identifier(pn->pn_left, &bindingName) && - identifier(pn->pn_right, &exportName) && - builder.exportSpecifier(bindingName, exportName, &pn->pn_pos, dst); + return identifier(exportSpec->left(), &bindingName) && + identifier(exportSpec->right(), &exportName) && + builder.exportSpecifier(bindingName, exportName, &exportSpec->pn_pos, dst); } bool -ASTSerializer::switchCase(ParseNode* pn, MutableHandleValue dst) +ASTSerializer::switchCase(CaseClause* caseClause, MutableHandleValue dst) { - MOZ_ASSERT_IF(pn->pn_left, pn->pn_pos.encloses(pn->pn_left->pn_pos)); - MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_right->pn_pos)); + MOZ_ASSERT_IF(caseClause->caseExpression(), + caseClause->pn_pos.encloses(caseClause->caseExpression()->pn_pos)); + MOZ_ASSERT(caseClause->pn_pos.encloses(caseClause->statementList()->pn_pos)); NodeVector stmts(cx); - RootedValue expr(cx); - - return optExpression(pn->as().caseExpression(), &expr) && - statements(pn->as().statementList(), stmts) && - builder.switchCase(expr, stmts, &pn->pn_pos, dst); + return optExpression(caseClause->caseExpression(), &expr) && + statements(caseClause->statementList(), stmts) && + builder.switchCase(expr, stmts, &caseClause->pn_pos, dst); } bool -ASTSerializer::switchStatement(ParseNode* pn, MutableHandleValue dst) +ASTSerializer::switchStatement(SwitchStatement* switchStmt, MutableHandleValue dst) { - MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_left->pn_pos)); - MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_right->pn_pos)); + MOZ_ASSERT(switchStmt->pn_pos.encloses(switchStmt->discriminant().pn_pos)); + MOZ_ASSERT(switchStmt->pn_pos.encloses(switchStmt->lexicalForCaseList().pn_pos)); RootedValue disc(cx); - if (!expression(pn->pn_left, &disc)) + if (!expression(&switchStmt->discriminant(), &disc)) return false; - MOZ_ASSERT(pn->pn_right->isKind(PNK_LEXICALSCOPE)); - ListNode* caseList = &pn->pn_right->scopeBody()->as(); + ListNode* caseList = &switchStmt->lexicalForCaseList().scopeBody()->as(); NodeVector cases(cx); if (!cases.reserve(caseList->count())) return false; - for (ParseNode* caseNode : caseList->contents()) { + for (ParseNode* item : caseList->contents()) { + CaseClause* caseClause = &item->as(); RootedValue child(cx); - if (!switchCase(caseNode, &child)) + if (!switchCase(caseClause, &child)) return false; cases.infallibleAppend(child); } - return builder.switchStatement(disc, cases, /* lexical = */ true, &pn->pn_pos, dst); + return builder.switchStatement(disc, cases, /* lexical = */ true, &switchStmt->pn_pos, dst); } bool @@ -2401,8 +2409,8 @@ ASTSerializer::forInit(ParseNode* pn, MutableHandleValue dst) } bool -ASTSerializer::forOf(ParseNode* loop, ParseNode* iterExpr, HandleValue var, HandleValue stmt, - MutableHandleValue dst) +ASTSerializer::forOf(ForNode* loop, ParseNode* iterExpr, HandleValue var, HandleValue stmt, + MutableHandleValue dst) { RootedValue expr(cx); @@ -2411,11 +2419,11 @@ ASTSerializer::forOf(ParseNode* loop, ParseNode* iterExpr, HandleValue var, Hand } bool -ASTSerializer::forIn(ParseNode* loop, ParseNode* iterExpr, HandleValue var, HandleValue stmt, - MutableHandleValue dst) +ASTSerializer::forIn(ForNode* loop, ParseNode* iterExpr, HandleValue var, HandleValue stmt, + MutableHandleValue dst) { RootedValue expr(cx); - bool isForEach = loop->pn_iflags & JSITER_FOREACH; + bool isForEach = loop->iflags() & JSITER_FOREACH; return expression(iterExpr, &expr) && builder.forInStatement(var, expr, stmt, isForEach, &loop->pn_pos, dst); @@ -2452,7 +2460,7 @@ ASTSerializer::statement(ParseNode* pn, MutableHandleValue dst) return declaration(pn, dst); case PNK_IMPORT: - return importDeclaration(pn, dst); + return importDeclaration(&pn->as(), dst); case PNK_EXPORT: case PNK_EXPORT_DEFAULT: @@ -2498,7 +2506,7 @@ ASTSerializer::statement(ParseNode* pn, MutableHandleValue dst) } case PNK_SWITCH: - return switchStatement(pn, dst); + return switchStatement(&pn->as(), dst); case PNK_TRY: return tryStatement(&pn->as(), dst); @@ -2506,37 +2514,50 @@ ASTSerializer::statement(ParseNode* pn, MutableHandleValue dst) case PNK_WITH: case PNK_WHILE: { - MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_left->pn_pos)); - MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_right->pn_pos)); + BinaryNode* node = &pn->as(); + + ParseNode* exprNode = node->left(); + MOZ_ASSERT(node->pn_pos.encloses(exprNode->pn_pos)); + + ParseNode* stmtNode = node->right(); + MOZ_ASSERT(node->pn_pos.encloses(stmtNode->pn_pos)); RootedValue expr(cx), stmt(cx); - return expression(pn->pn_left, &expr) && - statement(pn->pn_right, &stmt) && - (pn->isKind(PNK_WITH) - ? builder.withStatement(expr, stmt, &pn->pn_pos, dst) - : builder.whileStatement(expr, stmt, &pn->pn_pos, dst)); + return expression(exprNode, &expr) && + statement(stmtNode, &stmt) && + (node->isKind(PNK_WITH) + ? builder.withStatement(expr, stmt, &node->pn_pos, dst) + : builder.whileStatement(expr, stmt, &node->pn_pos, dst)); } case PNK_DOWHILE: { - MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_left->pn_pos)); - MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_right->pn_pos)); + BinaryNode* node = &pn->as(); + + ParseNode* stmtNode = node->left(); + MOZ_ASSERT(node->pn_pos.encloses(stmtNode->pn_pos)); + + ParseNode* testNode = node->right(); + MOZ_ASSERT(node->pn_pos.encloses(testNode->pn_pos)); RootedValue stmt(cx), test(cx); - return statement(pn->pn_left, &stmt) && - expression(pn->pn_right, &test) && - builder.doWhileStatement(stmt, test, &pn->pn_pos, dst); + return statement(stmtNode, &stmt) && + expression(testNode, &test) && + builder.doWhileStatement(stmt, test, &node->pn_pos, dst); } case PNK_FOR: case PNK_COMPREHENSIONFOR: { - MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_left->pn_pos)); - MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_right->pn_pos)); + ForNode* forNode = &pn->as(); - TernaryNode* head = &pn->pn_left->as(); + TernaryNode* head = forNode->head(); + MOZ_ASSERT(forNode->pn_pos.encloses(head->pn_pos)); + + ParseNode* stmtNode = forNode->right(); + MOZ_ASSERT(forNode->pn_pos.encloses(stmtNode->pn_pos)); ParseNode* initNode = head->kid1(); MOZ_ASSERT_IF(initNode, head->pn_pos.encloses(initNode->pn_pos)); @@ -2548,7 +2569,7 @@ ASTSerializer::statement(ParseNode* pn, MutableHandleValue dst) MOZ_ASSERT_IF(updateOrIter, head->pn_pos.encloses(updateOrIter->pn_pos)); RootedValue stmt(cx); - if (!statement(pn->pn_right, &stmt)) + if (!statement(stmtNode, &stmt)) return false; if (head->isKind(PNK_FORIN) || head->isKind(PNK_FOROF)) { @@ -2572,8 +2593,8 @@ ASTSerializer::statement(ParseNode* pn, MutableHandleValue dst) } } if (head->isKind(PNK_FORIN)) - return forIn(pn, updateOrIter, var, stmt, dst); - return forOf(pn, updateOrIter, var, stmt, dst); + return forIn(forNode, updateOrIter, var, stmt, dst); + return forOf(forNode, updateOrIter, var, stmt, dst); } RootedValue init(cx), test(cx), update(cx); @@ -2581,7 +2602,7 @@ ASTSerializer::statement(ParseNode* pn, MutableHandleValue dst) return forInit(initNode, &init) && optExpression(maybeTest, &test) && optExpression(updateOrIter, &update) && - builder.forStatement(init, test, update, stmt, &pn->pn_pos, dst); + builder.forStatement(init, test, update, stmt, &forNode->pn_pos, dst); } case PNK_BREAK: @@ -2639,7 +2660,8 @@ ASTSerializer::statement(ParseNode* pn, MutableHandleValue dst) if (!methods.reserve(methodList->count())) return false; - for (ParseNode* method : methodList->contents()) { + for (ParseNode* item : methodList->contents()) { + ClassMethod* method = &item->as(); MOZ_ASSERT(methodList->pn_pos.encloses(method->pn_pos)); RootedValue prop(cx); @@ -2660,10 +2682,10 @@ ASTSerializer::statement(ParseNode* pn, MutableHandleValue dst) } bool -ASTSerializer::classMethod(ParseNode* pn, MutableHandleValue dst) +ASTSerializer::classMethod(ClassMethod* classMethod, MutableHandleValue dst) { PropKind kind; - switch (pn->getOp()) { + switch (classMethod->getOp()) { case JSOP_INITPROP: kind = PROP_INIT; break; @@ -2681,10 +2703,10 @@ ASTSerializer::classMethod(ParseNode* pn, MutableHandleValue dst) } RootedValue key(cx), val(cx); - bool isStatic = pn->as().isStatic(); - return propertyName(pn->pn_left, &key) && - expression(pn->pn_right, &val) && - builder.classMethod(key, val, kind, isStatic, &pn->pn_pos, dst); + bool isStatic = classMethod->isStatic(); + return propertyName(&classMethod->name(), &key) && + expression(&classMethod->method(), &val) && + builder.classMethod(key, val, kind, isStatic, &classMethod->pn_pos, dst); } bool @@ -2767,15 +2789,13 @@ ASTSerializer::rightAssociate(ListNode* node, MutableHandleValue dst) } bool -ASTSerializer::comprehensionBlock(ParseNode* pn, MutableHandleValue dst) +ASTSerializer::comprehensionBlock(ForNode* forNode, MutableHandleValue dst) { - LOCAL_ASSERT(pn->isArity(PN_BINARY)); - - TernaryNode* in = &pn->pn_left->as(); + TernaryNode* in = forNode->head(); LOCAL_ASSERT(in && (in->isKind(PNK_FORIN) || in->isKind(PNK_FOROF))); - bool isForEach = in->isKind(PNK_FORIN) && (pn->pn_iflags & JSITER_FOREACH); + bool isForEach = in->isKind(PNK_FORIN) && (forNode->iflags() & JSITER_FOREACH); bool isForOf = in->isKind(PNK_FOROF); ListNode* decl; @@ -2817,10 +2837,11 @@ ASTSerializer::comprehension(ParseNode* pn, MutableHandleValue dst) RootedValue filter(cx, MagicValue(JS_SERIALIZE_NO_NODE)); while (true) { if (next->isKind(PNK_COMPREHENSIONFOR)) { + ForNode* forNode = &next->as(); RootedValue block(cx); - if (!comprehensionBlock(next, &block) || !blocks.append(block)) + if (!comprehensionBlock(forNode, &block) || !blocks.append(block)) return false; - next = next->pn_right; + next = forNode->body(); } else if (next->isKind(PNK_IF)) { TernaryNode* tn = &next->as(); if (isLegacy) { @@ -2862,10 +2883,11 @@ ASTSerializer::generatorExpression(ParseNode* pn, MutableHandleValue dst) RootedValue filter(cx, MagicValue(JS_SERIALIZE_NO_NODE)); while (true) { if (next->isKind(PNK_COMPREHENSIONFOR)) { + ForNode* forNode = &next->as(); RootedValue block(cx); - if (!comprehensionBlock(next, &block) || !blocks.append(block)) + if (!comprehensionBlock(forNode, &block) || !blocks.append(block)) return false; - next = next->pn_right; + next = forNode->body(); } else if (next->isKind(PNK_IF)) { TernaryNode* tn = &next->as(); if (isLegacy) { @@ -2972,16 +2994,19 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst) case PNK_MODASSIGN: case PNK_POWASSIGN: { - MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_left->pn_pos)); - MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_right->pn_pos)); + AssignmentNode* assignNode = &pn->as(); + ParseNode* lhsNode = assignNode->left(); + ParseNode* rhsNode = assignNode->right(); + MOZ_ASSERT(assignNode->pn_pos.encloses(lhsNode->pn_pos)); + MOZ_ASSERT(assignNode->pn_pos.encloses(rhsNode->pn_pos)); - AssignmentOperator op = aop(pn->getOp()); + AssignmentOperator op = aop(assignNode->getOp()); LOCAL_ASSERT(op > AOP_ERR && op < AOP_LIMIT); RootedValue lhs(cx), rhs(cx); - return pattern(pn->pn_left, &lhs) && - expression(pn->pn_right, &rhs) && - builder.assignmentExpression(op, lhs, rhs, &pn->pn_pos, dst); + return pattern(lhsNode, &lhs) && + expression(rhsNode, &rhs) && + builder.assignmentExpression(op, lhs, rhs, &assignNode->pn_pos, dst); } case PNK_ADD: @@ -3033,7 +3058,7 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst) } case PNK_GENEXP: { - ParseNode* callee = pn->pn_left; + ParseNode* callee = pn->as().left(); MOZ_ASSERT(callee->isKind(PNK_FUNCTION)); ListNode* paramsBody = &callee->pn_body->as(); @@ -3064,17 +3089,18 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst) case PNK_OPTCALL: case PNK_SUPERCALL: { - ParseNode* pn_callee = pn->pn_left; - ListNode* argsList = &pn->pn_right->as(); - MOZ_ASSERT(pn->pn_pos.encloses(pn_callee->pn_pos)); + BinaryNode* node = &pn->as(); + ParseNode* calleeNode = node->left(); + ListNode* argsList = &node->right()->as(); + MOZ_ASSERT(node->pn_pos.encloses(calleeNode->pn_pos)); RootedValue callee(cx); - if (pn->isKind(PNK_SUPERCALL)) { - MOZ_ASSERT(pn_callee->isKind(PNK_SUPERBASE)); - if (!builder.super(&pn_callee->pn_pos, &callee)) + if (node->isKind(PNK_SUPERCALL)) { + MOZ_ASSERT(calleeNode->isKind(PNK_SUPERBASE)); + if (!builder.super(&calleeNode->pn_pos, &callee)) return false; } else { - if (!expression(pn_callee, &callee)) + if (!expression(calleeNode, &callee)) return false; } @@ -3083,7 +3109,7 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst) return false; for (ParseNode* argNode : argsList->contents()) { - MOZ_ASSERT(pn->pn_pos.encloses(argNode->pn_pos)); + MOZ_ASSERT(node->pn_pos.encloses(argNode->pn_pos)); RootedValue arg(cx); if (!expression(argNode, &arg)) @@ -3091,67 +3117,63 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst) args.infallibleAppend(arg); } - if (pn->getKind() == PNK_TAGGED_TEMPLATE) - return builder.taggedTemplate(callee, args, &pn->pn_pos, dst); + if (node->getKind() == PNK_TAGGED_TEMPLATE) + return builder.taggedTemplate(callee, args, &node->pn_pos, dst); - bool isOptional = pn->isKind(PNK_OPTCALL); + bool isOptional = node->isKind(PNK_OPTCALL); // SUPERCALL is Call(super, args) - return pn->isKind(PNK_NEW) - ? builder.newExpression(callee, args, &pn->pn_pos, dst) - : builder.callExpression(callee, args, &pn->pn_pos, dst, isOptional); + return node->isKind(PNK_NEW) + ? builder.newExpression(callee, args, &node->pn_pos, dst) + : builder.callExpression(callee, args, &node->pn_pos, dst, isOptional); } case PNK_OPTDOT: case PNK_DOT: { - MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_left->pn_pos)); + PropertyAccess* prop = &pn->as(); + MOZ_ASSERT(prop->pn_pos.encloses(prop->expression().pn_pos)); RootedValue expr(cx); RootedValue propname(cx); - RootedAtom pnAtom(cx, pn->pn_right->pn_atom); + RootedAtom pnAtom(cx, prop->key().pn_atom); - bool isSuper = pn->is() && - pn->as().isSuper(); - - if (isSuper) { - if (!builder.super(&pn->pn_left->pn_pos, &expr)) + if (prop->isSuper()) { + if (!builder.super(&prop->expression().pn_pos, &expr)) return false; } else { - if (!expression(pn->pn_left, &expr)) + if (!expression(&prop->expression(), &expr)) return false; } - bool isOptional = pn->isKind(PNK_OPTDOT); + bool isOptional = prop->isKind(PNK_OPTDOT); return identifier(pnAtom, nullptr, &propname) && - builder.memberExpression(false, expr, propname, &pn->pn_pos, + builder.memberExpression(false, expr, propname, &prop->pn_pos, dst, isOptional); } case PNK_OPTELEM: case PNK_ELEM: { - MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_left->pn_pos)); - MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_right->pn_pos)); + PropertyByValueBase* elem = &pn->as(); + MOZ_ASSERT(elem->pn_pos.encloses(elem->expression().pn_pos)); + MOZ_ASSERT(elem->pn_pos.encloses(elem->key().pn_pos)); - RootedValue left(cx), right(cx); + RootedValue expr(cx), key(cx); - bool isSuper = pn->is() && - pn->as().isSuper(); - - if (isSuper) { - if (!builder.super(&pn->pn_left->pn_pos, &left)) + if (elem->isSuper()) { + if (!builder.super(&elem->expression().pn_pos, &expr)) return false; } else { - if (!expression(pn->pn_left, &left)) + if (!expression(&elem->expression(), &expr)) return false; } - bool isOptional = pn->isKind(PNK_OPTELEM); + bool isOptional = elem->isKind(PNK_OPTELEM); - return expression(pn->pn_right, &right) && - builder.memberExpression(true, left, right, &pn->pn_pos, dst, + return expression(&elem->key(), &key) && + builder.memberExpression(true, expr, key, &elem->pn_pos, dst, isOptional); } @@ -3288,7 +3310,7 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst) MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_kid->pn_pos)); RootedValue arg(cx); - return expression(pn->pn_left, &arg) && + return expression(pn->pn_kid, &arg) && builder.yieldExpression(arg, Delegating, &pn->pn_pos, dst); } @@ -3316,10 +3338,14 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst) case PNK_NEWTARGET: { - MOZ_ASSERT(pn->pn_left->isKind(PNK_POSHOLDER)); - MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_left->pn_pos)); - MOZ_ASSERT(pn->pn_right->isKind(PNK_POSHOLDER)); - MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_right->pn_pos)); + BinaryNode* node = &pn->as(); + ParseNode* firstNode = node->left(); + MOZ_ASSERT(firstNode->isKind(PNK_POSHOLDER)); + MOZ_ASSERT(node->pn_pos.encloses(firstNode->pn_pos)); + + ParseNode* secondNode = node->right(); + MOZ_ASSERT(secondNode->isKind(PNK_POSHOLDER)); + MOZ_ASSERT(node->pn_pos.encloses(secondNode->pn_pos)); RootedValue newIdent(cx); RootedValue targetIdent(cx); @@ -3327,16 +3353,18 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst) RootedAtom newStr(cx, cx->names().new_); RootedAtom targetStr(cx, cx->names().target); - return identifier(newStr, &pn->pn_left->pn_pos, &newIdent) && - identifier(targetStr, &pn->pn_right->pn_pos, &targetIdent) && - builder.metaProperty(newIdent, targetIdent, &pn->pn_pos, dst); + return identifier(newStr, &firstNode->pn_pos, &newIdent) && + identifier(targetStr, &secondNode->pn_pos, &targetIdent) && + builder.metaProperty(newIdent, targetIdent, &node->pn_pos, dst); } - case PNK_SETTHIS: + case PNK_SETTHIS: { // SETTHIS is used to assign the result of a super() call to |this|. // It's not part of the original AST, so just forward to the call. - MOZ_ASSERT(pn->pn_left->isKind(PNK_NAME)); - return expression(pn->pn_right, dst); + BinaryNode* node = &pn->as(); + MOZ_ASSERT(node->left()->isKind(PNK_NAME)); + return expression(node->right(), dst); + } default: LOCAL_NOT_REACHED("unexpected expression type"); @@ -3385,14 +3413,18 @@ ASTSerializer::property(ParseNode* pn, MutableHandleValue dst) LOCAL_NOT_REACHED("unexpected object-literal property"); } - bool isShorthand = pn->isKind(PNK_SHORTHAND); + BinaryNode* node = &pn->as(); + ParseNode* keyNode = node->left(); + ParseNode* valNode = node->right(); + + bool isShorthand = node->isKind(PNK_SHORTHAND); bool isMethod = - pn->pn_right->isKind(PNK_FUNCTION) && - pn->pn_right->pn_funbox->function()->kind() == JSFunction::Method; + valNode->isKind(PNK_FUNCTION) && + valNode->pn_funbox->function()->kind() == JSFunction::Method; RootedValue key(cx), val(cx); - return propertyName(pn->pn_left, &key) && - expression(pn->pn_right, &val) && - builder.propertyInitializer(key, val, kind, isShorthand, isMethod, &pn->pn_pos, dst); + return propertyName(keyNode, &key) && + expression(valNode, &val) && + builder.propertyInitializer(key, val, kind, isShorthand, isMethod, &node->pn_pos, dst); } bool @@ -3506,9 +3538,10 @@ ASTSerializer::objectPattern(ListNode* obj, MutableHandleValue dst) return false; target = propdef->pn_kid; } else { - if (!propertyName(propdef->pn_left, &key)) + BinaryNode* prop = &propdef->as(); + if (!propertyName(prop->left(), &key)) return false; - target = propdef->pn_right; + target = prop->right(); } RootedValue patt(cx), prop(cx); @@ -3665,9 +3698,9 @@ ASTSerializer::functionArgs(ParseNode* pn, ListNode* argsList, pat = arg; defNode = nullptr; } else { - MOZ_ASSERT(arg->isKind(PNK_ASSIGN)); - pat = arg->pn_left; - defNode = arg->pn_right; + AssignmentNode* assignNode = &arg->as(); + pat = assignNode->left(); + defNode = assignNode->right(); } // Process the name or pattern. diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index 861d0c51d6..a628ac88ed 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -1078,9 +1078,8 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer) // Trivial binary nodes with more token pos holders. case PNK_NEWTARGET: - MOZ_ASSERT(pn->isArity(PN_BINARY)); - MOZ_ASSERT(pn->pn_left->isKind(PNK_POSHOLDER)); - MOZ_ASSERT(pn->pn_right->isKind(PNK_POSHOLDER)); + MOZ_ASSERT(pn->as().left()->isKind(PNK_POSHOLDER)); + MOZ_ASSERT(pn->as().right()->isKind(PNK_POSHOLDER)); *answer = false; return true; @@ -1094,7 +1093,7 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer) // Watch out for getters! case PNK_DOT: case PNK_OPTDOT: - MOZ_ASSERT(pn->isArity(PN_BINARY)); + MOZ_ASSERT(pn->is()); *answer = true; return true; @@ -1210,8 +1209,12 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer) case PNK_DIVASSIGN: case PNK_MODASSIGN: case PNK_POWASSIGN: + MOZ_ASSERT(pn->is()); + *answer = true; + return true; + case PNK_SETTHIS: - MOZ_ASSERT(pn->isArity(PN_BINARY)); + MOZ_ASSERT(pn->is()); *answer = true; return true; @@ -1270,18 +1273,19 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer) return true; case PNK_COLON: - case PNK_CASE: - MOZ_ASSERT(pn->isArity(PN_BINARY)); - if (!checkSideEffects(pn->pn_left, answer)) + case PNK_CASE: { + BinaryNode* node = &pn->as(); + if (!checkSideEffects(node->left(), answer)) return false; if (*answer) return true; - return checkSideEffects(pn->pn_right, answer); + return checkSideEffects(node->right(), answer); + } // More getters. case PNK_ELEM: case PNK_OPTELEM: - MOZ_ASSERT(pn->isArity(PN_BINARY)); + MOZ_ASSERT(pn->is()); *answer = true; return true; @@ -1289,7 +1293,7 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer) case PNK_IMPORT: case PNK_EXPORT_FROM: case PNK_EXPORT_DEFAULT: - MOZ_ASSERT(pn->isArity(PN_BINARY)); + MOZ_ASSERT(pn->is()); *answer = true; return true; @@ -1308,7 +1312,7 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer) case PNK_WHILE: case PNK_FOR: case PNK_COMPREHENSIONFOR: - MOZ_ASSERT(pn->isArity(PN_BINARY)); + MOZ_ASSERT(pn->is()); *answer = true; return true; @@ -1343,7 +1347,7 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer) case PNK_OPTCALL: case PNK_TAGGED_TEMPLATE: case PNK_SUPERCALL: - MOZ_ASSERT(pn->isArity(PN_BINARY)); + MOZ_ASSERT(pn->is()); *answer = true; return true; @@ -1371,12 +1375,12 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer) // |with| calls |ToObject| on its expression and so throws if that value // is null/undefined. case PNK_WITH: - MOZ_ASSERT(pn->isArity(PN_BINARY)); + MOZ_ASSERT(pn->is()); *answer = true; return true; case PNK_RETURN: - MOZ_ASSERT(pn->isArity(PN_BINARY)); + MOZ_ASSERT(pn->is()); *answer = true; return true; @@ -1390,7 +1394,7 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer) // one. (Of course, it isn't necessary to use |with| for a shorthand to // trigger a getter.) case PNK_SHORTHAND: - MOZ_ASSERT(pn->isArity(PN_BINARY)); + MOZ_ASSERT(pn->is()); *answer = true; return true; @@ -1412,7 +1416,7 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer) // Generator expressions have no side effects on their own. case PNK_GENEXP: - MOZ_ASSERT(pn->isArity(PN_BINARY)); + MOZ_ASSERT(pn->is()); *answer = false; return true; @@ -1455,11 +1459,12 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer) return checkSideEffects(catchNode->kid3(), answer); } - case PNK_SWITCH: - MOZ_ASSERT(pn->isArity(PN_BINARY)); - if (!checkSideEffects(pn->pn_left, answer)) + case PNK_SWITCH: { + SwitchStatement* switchStmt = &pn->as(); + if (!checkSideEffects(&switchStmt->discriminant(), answer)) return false; - return *answer || checkSideEffects(pn->pn_right, answer); + return *answer || checkSideEffects(&switchStmt->lexicalForCaseList(), answer); + } case PNK_LABEL: MOZ_ASSERT(pn->isArity(PN_NAME)); @@ -1819,51 +1824,54 @@ BytecodeEmitter::emitTDZCheckIfNeeded(JSAtom* name, const NameLocation& loc) } bool -BytecodeEmitter::emitPropLHS(ParseNode* pn) +BytecodeEmitter::emitPropLHS(PropertyAccess* prop) { - MOZ_ASSERT(pn->isKind(PNK_DOT)); - MOZ_ASSERT(!pn->as().isSuper()); + MOZ_ASSERT(!prop->isSuper()); - ParseNode* pn2 = pn->pn_left; + ParseNode* expr = &prop->expression(); + + if (!expr->is() || expr->as().isSuper()) { + // The non-optimized case. + return emitTree(expr); + } /* * If the object operand is also a dotted property reference, reverse the * list linked via pn_left temporarily so we can iterate over it from the * bottom up (reversing again as we go), to avoid excessive recursion. */ - if (pn2->isKind(PNK_DOT) && !pn2->as().isSuper()) { - ParseNode* pndot = pn2; - ParseNode* pnup = nullptr; - ParseNode* pndown; - for (;;) { - /* Reverse pndot->pn_left to point up, not down. */ - pndown = pndot->pn_left; - pndot->pn_left = pnup; - if (!pndown->isKind(PNK_DOT) || pndown->as().isSuper()) - break; - pnup = pndot; - pndot = pndown; - } - - /* pndown is a primary expression, not a dotted property reference. */ - if (!emitTree(pndown)) - return false; - - do { - /* Walk back up the list, emitting annotated name ops. */ - if (!emitAtomOp(pndot->pn_right->pn_atom, JSOP_GETPROP)) - return false; - - /* Reverse the pn_left link again. */ - pnup = pndot->pn_left; - pndot->pn_left = pndown; - pndown = pndot; - } while ((pndot = pnup) != nullptr); - return true; + PropertyAccess* pndot = &expr->as(); + ParseNode* pnup = nullptr; + ParseNode* pndown; + for (;;) { + /* Reverse pndot->pn_left to point up, not down. */ + pndown = &pndot->expression(); + pndot->setExpression(pnup); + if (!pndown->is() || pndown->as().isSuper()) + break; + pnup = pndot; + pndot = &pndown->as(); } - // The non-optimized case. - return emitTree(pn2); + /* pndown is a primary expression, not a dotted property reference. */ + if (!emitTree(pndown)) + return false; + + while (true) { + /* Walk back up the list, emitting annotated name ops. */ + if (!emitAtomOp(pndot->key().pn_atom, JSOP_GETPROP)) + return false; + + /* Reverse the pn_left link again. */ + pnup = pndot->maybeExpression(); + pndot->setExpression(pndown); + pndown = pndot; + if (!pnup) { + break; + } + pndot = &pnup->as(); + } + return true; } bool @@ -1886,15 +1894,15 @@ BytecodeEmitter::emitPropIncDec(ParseNode* pn) return false; } if (isSuper) { - ParseNode* base = &pn->pn_kid->as().expression(); - if (!emitGetThisForSuperBase(base)) { // THIS + ParseNode* base = &prop->expression(); + if (!emitGetThisForSuperBase(base)) { // THIS return false; } } else { - if (!emitPropLHS(pn->pn_kid)) // OBJ + if (!emitPropLHS(prop)) // OBJ return false; } - if (!poe.emitIncDec(prop->nameAtom())) { // RESULT + if (!poe.emitIncDec(prop->key().pn_atom)) { // RESULT return false; } @@ -2057,17 +2065,17 @@ BytecodeEmitter::emitNumberOp(double dval) * into emitTree which is recursive and uses relatively little stack space. */ MOZ_NEVER_INLINE bool -BytecodeEmitter::emitSwitch(SwitchStatement* pn) +BytecodeEmitter::emitSwitch(SwitchStatement* switchStmt) { - ParseNode& lexical = pn->lexicalForCaseList(); + ParseNode& lexical = switchStmt->lexicalForCaseList(); MOZ_ASSERT(lexical.isKind(PNK_LEXICALSCOPE)); ListNode* cases = &lexical.scopeBody()->as(); MOZ_ASSERT(cases->isKind(PNK_STATEMENTLIST)); SwitchEmitter se(this); - if (!se.emitDiscriminant(Some(pn->pn_pos.begin))) + if (!se.emitDiscriminant(Some(switchStmt->pn_pos.begin))) return false; - if (!emitTree(&pn->discriminant())) + if (!emitTree(&switchStmt->discriminant())) return false; // Enter the scope before pushing the switch BreakableControl since all @@ -2080,8 +2088,9 @@ BytecodeEmitter::emitSwitch(SwitchStatement* pn) // cases. The PNX_FUNCDEFS flag is propagated from the STATEMENTLIST // bodies of the cases to the case list. if (cases->hasTopLevelFunctionDeclarations()) { - for (ParseNode* caseNode : cases->contents()) { - ListNode* statements = &caseNode->pn_right->as(); + for (ParseNode* item : cases->contents()) { + CaseClause* caseClause = &item->as(); + ListNode* statements = caseClause->statementList(); if (statements->hasTopLevelFunctionDeclarations()) { if (!emitHoistedFunctionsInList(statements)) return false; @@ -2093,16 +2102,16 @@ BytecodeEmitter::emitSwitch(SwitchStatement* pn) } SwitchEmitter::TableGenerator tableGen(this); - uint32_t caseCount = cases->count() - (pn->hasDefault() ? 1 : 0); + uint32_t caseCount = cases->count() - (switchStmt->hasDefault() ? 1 : 0); if (caseCount == 0) { tableGen.finish(0); } else { for (ParseNode* item : cases->contents()) { - CaseClause* caseNode = &item->as(); - if (caseNode->isDefault()) + CaseClause* caseClause = &item->as(); + if (caseClause->isDefault()) continue; - ParseNode* caseValue = caseNode->caseExpression(); + ParseNode* caseValue = caseClause->caseExpression(); if (caseValue->getKind() != PNK_NUMBER) { tableGen.setInvalid(); @@ -2134,11 +2143,11 @@ BytecodeEmitter::emitSwitch(SwitchStatement* pn) // Emit code for evaluating cases and jumping to case statements. for (ParseNode* item : cases->contents()) { - CaseClause* caseNode = &item->as(); - if (caseNode->isDefault()) + CaseClause* caseClause = &item->as(); + if (caseClause->isDefault()) continue; - ParseNode* caseValue = caseNode->caseExpression(); + ParseNode* caseValue = caseClause->caseExpression(); // If the expression is a literal, suppress line number emission so // that debugging works more naturally. @@ -2154,13 +2163,13 @@ BytecodeEmitter::emitSwitch(SwitchStatement* pn) // Emit code for each case's statements. for (ParseNode* item : cases->contents()) { - CaseClause* caseNode = &item->as(); - if (caseNode->isDefault()) { + CaseClause* caseClause = &item->as(); + if (caseClause->isDefault()) { if (!se.emitDefaultBody()) return false; } else { if (isTableSwitch) { - ParseNode* caseValue = caseNode->caseExpression(); + ParseNode* caseValue = caseClause->caseExpression(); MOZ_ASSERT(caseValue->isKind(PNK_NUMBER)); int32_t i = int32_t(caseValue->pn_dval); @@ -2174,7 +2183,7 @@ BytecodeEmitter::emitSwitch(SwitchStatement* pn) } } - if (!emitTree(caseNode->statementList())) + if (!emitTree(caseClause->statementList())) return false; } @@ -2237,15 +2246,15 @@ BytecodeEmitter::emitYieldOp(JSOp op) } bool -BytecodeEmitter::emitSetThis(ParseNode* pn) +BytecodeEmitter::emitSetThis(BinaryNode* setThisNode) { // PNK_SETTHIS is used to update |this| after a super() call in a derived // class constructor. - MOZ_ASSERT(pn->isKind(PNK_SETTHIS)); - MOZ_ASSERT(pn->pn_left->isKind(PNK_NAME)); + MOZ_ASSERT(setThisNode->isKind(PNK_SETTHIS)); + MOZ_ASSERT(setThisNode->left()->isKind(PNK_NAME)); - RootedAtom name(cx, pn->pn_left->name()); + RootedAtom name(cx, setThisNode->left()->name()); // The 'this' binding is not lexical, but due to super() semantics this // initialization needs to be treated as a lexical one. @@ -2268,7 +2277,7 @@ BytecodeEmitter::emitSetThis(ParseNode* pn) } // Emit the new |this| value. - if (!emitTree(pn->pn_right)) // NEWTHIS + if (!emitTree(setThisNode->right())) // NEWTHIS return false; // Get the original |this| and throw if we already initialized @@ -2433,7 +2442,7 @@ BytecodeEmitter::emitDestructuringLHSRef(ParseNode* target, size_t* emitted) if (target->isKind(PNK_SPREAD)) target = target->pn_kid; else if (target->isKind(PNK_ASSIGN)) - target = target->pn_left; + target = target->as().left(); // No need to recur into PNK_ARRAY and PNK_OBJECT subpatterns here, since // emitSetOrInitializeDestructuring does the recursion when setting or @@ -2465,7 +2474,7 @@ BytecodeEmitter::emitDestructuringLHSRef(ParseNode* target, size_t* emitted) // SUPERBASE is pushed onto THIS in poe.prepareForRhs below. *emitted = 2; } else { - if (!emitTree(target->pn_left)) // OBJ + if (!emitTree(&prop->expression())) // OBJ return false; *emitted = 1; } @@ -2532,7 +2541,7 @@ BytecodeEmitter::emitSetOrInitializeDestructuring(ParseNode* target, Destructuri if (target->isKind(PNK_SPREAD)) target = target->pn_kid; else if (target->isKind(PNK_ASSIGN)) - target = target->pn_left; + target = target->as().left(); if (target->isKind(PNK_ARRAY) || target->isKind(PNK_OBJECT)) { if (!emitDestructuringOps(&target->as(), flav)) return false; @@ -2616,7 +2625,7 @@ BytecodeEmitter::emitSetOrInitializeDestructuring(ParseNode* target, Destructuri if (!poe.skipObjAndRhs()) { return false; } - if (!poe.emitAssignment(prop->nameAtom())) { + if (!poe.emitAssignment(prop->key().pn_atom)) { return false; // VAL } break; @@ -3118,7 +3127,7 @@ BytecodeEmitter::emitDestructuringOpsArray(ListNode* pattern, DestructuringFlavo // Spec requires LHS reference to be evaluated first. ParseNode* lhsPattern = member; if (lhsPattern->isKind(PNK_ASSIGN)) - lhsPattern = lhsPattern->pn_left; + lhsPattern = lhsPattern->as().left(); bool isElision = lhsPattern->isKind(PNK_ELISION); if (!isElision) { @@ -3196,7 +3205,7 @@ BytecodeEmitter::emitDestructuringOpsArray(ListNode* pattern, DestructuringFlavo ParseNode* pndefault = nullptr; if (member->isKind(PNK_ASSIGN)) - pndefault = member->pn_right; + pndefault = member->as().right(); MOZ_ASSERT(!member->isKind(PNK_SPREAD)); @@ -3338,13 +3347,16 @@ BytecodeEmitter::emitDestructuringOpsObject(ListNode* pattern, DestructuringFlav ParseNode* subpattern; if (member->isKind(PNK_MUTATEPROTO) || member->isKind(PNK_SPREAD)) subpattern = member->pn_kid; - else - subpattern = member->pn_right; + else { + MOZ_ASSERT(member->isKind(PNK_COLON) || + member->isKind(PNK_SHORTHAND)); + subpattern = member->as().right(); + } ParseNode* lhs = subpattern; MOZ_ASSERT_IF(member->isKind(PNK_SPREAD), !lhs->isKind(PNK_ASSIGN)); if (lhs->isKind(PNK_ASSIGN)) - lhs = lhs->pn_left; + lhs = lhs->as().left(); size_t emitted; if (!emitDestructuringLHSRef(lhs, &emitted)) // ... *SET RHS *LREF @@ -3401,7 +3413,7 @@ BytecodeEmitter::emitDestructuringOpsObject(ListNode* pattern, DestructuringFlav } else { MOZ_ASSERT(member->isKind(PNK_COLON) || member->isKind(PNK_SHORTHAND)); - ParseNode* key = member->pn_left; + ParseNode* key = member->as().left(); if (key->isKind(PNK_NUMBER)) { if (!emitNumberOp(key->pn_dval)) // ... *SET RHS *LREF RHS KEY return false; @@ -3434,8 +3446,8 @@ BytecodeEmitter::emitDestructuringOpsObject(ListNode* pattern, DestructuringFlav return false; if (subpattern->isKind(PNK_ASSIGN)) { - if (!emitDefault(subpattern->pn_right, lhs)) // ... *SET RHS *LREF VALUE - return false; + if (!emitDefault(subpattern->as().right(), lhs)) + return false; // ... *SET RHS *LREF VALUE } // Destructure PROP per this member's lhs. @@ -3478,7 +3490,7 @@ BytecodeEmitter::emitDestructuringObjRestExclusionSet(ListNode* pattern) if (member->isKind(PNK_MUTATEPROTO)) { pnatom.set(cx->names().proto); } else { - ParseNode* key = member->pn_left; + ParseNode* key = member->as().left(); if (key->isKind(PNK_NUMBER)) { if (!emitNumberOp(key->pn_dval)) return false; @@ -3599,10 +3611,11 @@ BytecodeEmitter::emitDeclarationList(ListNode* declList) if (decl->isKind(PNK_ASSIGN)) { MOZ_ASSERT(decl->isOp(JSOP_NOP)); - ListNode* pattern = &decl->pn_left->as(); + AssignmentNode* assignNode = &decl->as(); + ListNode* pattern = &assignNode->left()->as(); MOZ_ASSERT(pattern->isKind(PNK_ARRAY) || pattern->isKind(PNK_OBJECT)); - if (!emitTree(decl->pn_right)) + if (!emitTree(assignNode->right())) return false; if (!emitDestructuringOps(pattern, DestructuringDeclaration)) @@ -3802,7 +3815,7 @@ BytecodeEmitter::emitAssignment(ParseNode* lhs, JSOp compoundOp, ParseNode* rhs) switch (lhs->getKind()) { case PNK_DOT: { PropertyAccess* prop = &lhs->as(); - if (!poe->emitGet(prop->nameAtom())) { // [Super] + if (!poe->emitGet(prop->key().pn_atom)) { // [Super] // // THIS SUPERBASE PROP // // [Other] // // OBJ PROP @@ -3871,7 +3884,7 @@ BytecodeEmitter::emitAssignment(ParseNode* lhs, JSOp compoundOp, ParseNode* rhs) switch (lhs->getKind()) { case PNK_DOT: { PropertyAccess* prop = &lhs->as(); - if (!poe->emitAssignment(prop->nameAtom())) { // VAL + if (!poe->emitAssignment(prop->key().pn_atom)) { // VAL return false; } @@ -3990,15 +4003,17 @@ ParseNode::getConstantValue(ExclusiveContext* cx, AllowConstantObjects allowObje Rooted properties(cx, IdValueVector(cx)); RootedValue value(cx), idvalue(cx); - for (ParseNode* prop : as().contents()) { - if (!prop->pn_right->getConstantValue(cx, allowObjects, &value)) + for (ParseNode* item : as().contents()) { + // MutateProto and Spread, both are unary, cannot appear here. + BinaryNode* prop = &item->as(); + if (!prop->right()->getConstantValue(cx, allowObjects, &value)) return false; if (value.isMagic(JS_GENERIC_MAGIC)) { vp.setMagic(JS_GENERIC_MAGIC); return true; } - ParseNode* key = prop->pn_left; + ParseNode* key = prop->left(); if (key->isKind(PNK_NUMBER)) { idvalue = NumberValue(key->pn_dval); } else { @@ -4401,7 +4416,7 @@ BytecodeEmitter::emitLexicalScope(ParseNode* pn) // for loops need to emit {FRESHEN,RECREATE}LEXICALENV if there are // lexical declarations in the head. Signal this by passing a // non-nullptr lexical scope. - if (!emitFor(body, &emitterScope)) + if (!emitFor(&body->as(), &emitterScope)) return false; } else { if (!emitLexicalScopeBody(body, SUPPRESS_LINENOTE)) @@ -4412,16 +4427,21 @@ BytecodeEmitter::emitLexicalScope(ParseNode* pn) } bool -BytecodeEmitter::emitWith(ParseNode* pn) +BytecodeEmitter::emitWith(BinaryNode* withNode) { - if (!emitTree(pn->pn_left)) + // Ensure that the column of the 'with' is set properly. + if (!updateSourceCoordNotes(withNode->pn_pos.begin)) { + return false; + } + + if (!emitTree(withNode->left())) return false; EmitterScope emitterScope(this); if (!emitterScope.enterWith(this)) return false; - if (!emitTree(pn->pn_right)) + if (!emitTree(withNode->right())) return false; return emitterScope.leave(this); @@ -4734,15 +4754,14 @@ BytecodeEmitter::emitInitializeForInOrOfTarget(TernaryNode* forHead) } bool -BytecodeEmitter::emitForOf(ParseNode* forOfLoop, EmitterScope* headLexicalEmitterScope) +BytecodeEmitter::emitForOf(ForNode* forNode, EmitterScope* headLexicalEmitterScope) { - MOZ_ASSERT(forOfLoop->isKind(PNK_FOR)); - MOZ_ASSERT(forOfLoop->isArity(PN_BINARY)); + MOZ_ASSERT(forNode->isKind(PNK_FOR)); - TernaryNode* forOfHead = &forOfLoop->pn_left->as(); + TernaryNode* forOfHead = forNode->head(); MOZ_ASSERT(forOfHead->isKind(PNK_FOROF)); - unsigned iflags = forOfLoop->pn_iflags; + unsigned iflags = forNode->iflags(); IteratorKind iterKind = (iflags & JSITER_FORAWAITOF) ? IteratorKind::Async : IteratorKind::Sync; @@ -4756,7 +4775,7 @@ BytecodeEmitter::emitForOf(ParseNode* forOfLoop, EmitterScope* headLexicalEmitte bool allowSelfHostedIter = false; if (emitterMode == BytecodeEmitter::SelfHosting && forHeadExpr->isKind(PNK_CALL) && - forHeadExpr->pn_left->name() == cx->names().allowContentIter) + forHeadExpr->as().left()->name() == cx->names().allowContentIter) { allowSelfHostedIter = true; } @@ -4854,7 +4873,7 @@ BytecodeEmitter::emitForOf(ParseNode* forOfLoop, EmitterScope* headLexicalEmitte return false; // Perform the loop body. - ParseNode* forBody = forOfLoop->pn_right; + ParseNode* forBody = forNode->body(); if (!emitTree(forBody)) // ITER RESULT UNDEF return false; @@ -4908,13 +4927,12 @@ BytecodeEmitter::emitForOf(ParseNode* forOfLoop, EmitterScope* headLexicalEmitte } bool -BytecodeEmitter::emitForIn(ParseNode* forInLoop, EmitterScope* headLexicalEmitterScope) +BytecodeEmitter::emitForIn(ForNode* forNode, EmitterScope* headLexicalEmitterScope) { - MOZ_ASSERT(forInLoop->isKind(PNK_FOR)); - MOZ_ASSERT(forInLoop->isArity(PN_BINARY)); - MOZ_ASSERT(forInLoop->isOp(JSOP_ITER)); + MOZ_ASSERT(forNode->isKind(PNK_FOR)); + MOZ_ASSERT(forNode->isOp(JSOP_ITER)); - TernaryNode* forInHead = &forInLoop->pn_left->as(); + TernaryNode* forInHead = forNode->head(); MOZ_ASSERT(forInHead->isKind(PNK_FORIN)); // Annex B: Evaluate the var-initializer expression if present. @@ -4955,7 +4973,7 @@ BytecodeEmitter::emitForIn(ParseNode* forInLoop, EmitterScope* headLexicalEmitte // Convert the value to the appropriate sort of iterator object for the // loop variant (for-in, for-each-in, or destructuring for-in). - unsigned iflags = forInLoop->pn_iflags; + unsigned iflags = forNode->iflags(); MOZ_ASSERT(0 == (iflags & ~(JSITER_FOREACH | JSITER_ENUMERATE))); if (!emit2(JSOP_ITER, AssertedCast(iflags))) // ITER return false; @@ -5018,7 +5036,7 @@ BytecodeEmitter::emitForIn(ParseNode* forInLoop, EmitterScope* headLexicalEmitte } // Perform the loop body. - ParseNode* forBody = forInLoop->pn_right; + ParseNode* forBody = forNode->body(); if (!emitTree(forBody)) // ITER ITERVAL return false; @@ -5058,12 +5076,12 @@ BytecodeEmitter::emitForIn(ParseNode* forInLoop, EmitterScope* headLexicalEmitte /* C-style `for (init; cond; update) ...` loop. */ bool -BytecodeEmitter::emitCStyleFor(ParseNode* pn, EmitterScope* headLexicalEmitterScope) +BytecodeEmitter::emitCStyleFor(ForNode* forNode, EmitterScope* headLexicalEmitterScope) { LoopControl loopInfo(this, StatementKind::ForLoop); - TernaryNode* forHead = &pn->pn_left->as(); - ParseNode* forBody = pn->pn_right; + TernaryNode* forHead = forNode->head(); + ParseNode* forBody = forNode->body(); // If the head of this for-loop declared any lexical variables, the parser // wrapped this PNK_FOR node in a PNK_LEXICALSCOPE representing the @@ -5190,7 +5208,7 @@ BytecodeEmitter::emitCStyleFor(ParseNode* pn, EmitterScope* headLexicalEmitterSc return false; /* Restore the absolute line number for source note readers. */ - uint32_t lineNum = parser->tokenStream.srcCoords.lineNum(pn->pn_pos.end); + uint32_t lineNum = parser->tokenStream.srcCoords.lineNum(forNode->pn_pos.end); if (currentLine() != lineNum) { if (!newSrcNote2(SRC_SETLINE, ptrdiff_t(lineNum))) return false; @@ -5214,7 +5232,7 @@ BytecodeEmitter::emitCStyleFor(ParseNode* pn, EmitterScope* headLexicalEmitterSc // the loop-ending "goto" with the location of the "for". // This ensures that the debugger will stop on each loop // iteration. - if (!updateSourceCoordNotes(pn->pn_pos.begin)) + if (!updateSourceCoordNotes(forNode->pn_pos.begin)) return false; } @@ -5244,21 +5262,21 @@ BytecodeEmitter::emitCStyleFor(ParseNode* pn, EmitterScope* headLexicalEmitterSc } bool -BytecodeEmitter::emitFor(ParseNode* pn, EmitterScope* headLexicalEmitterScope) +BytecodeEmitter::emitFor(ForNode* forNode, EmitterScope* headLexicalEmitterScope) { - MOZ_ASSERT(pn->isKind(PNK_FOR)); + MOZ_ASSERT(forNode->isKind(PNK_FOR)); - if (pn->pn_left->isKind(PNK_FORHEAD)) - return emitCStyleFor(pn, headLexicalEmitterScope); + if (forNode->head()->isKind(PNK_FORHEAD)) + return emitCStyleFor(forNode, headLexicalEmitterScope); - if (!updateLineNumberNotes(pn->pn_pos.begin)) + if (!updateLineNumberNotes(forNode->pn_pos.begin)) return false; - if (pn->pn_left->isKind(PNK_FORIN)) - return emitForIn(pn, headLexicalEmitterScope); + if (forNode->head()->isKind(PNK_FORIN)) + return emitForIn(forNode, headLexicalEmitterScope); - MOZ_ASSERT(pn->pn_left->isKind(PNK_FOROF)); - return emitForOf(pn, headLexicalEmitterScope); + MOZ_ASSERT(forNode->head()->isKind(PNK_FOROF)); + return emitForOf(forNode, headLexicalEmitterScope); } bool @@ -5292,15 +5310,15 @@ BytecodeEmitter::emitComprehensionForInOrOfVariables(ParseNode* pn, bool* lexica } bool -BytecodeEmitter::emitComprehensionForOf(ParseNode* pn) +BytecodeEmitter::emitComprehensionForOf(ForNode* forNode) { - MOZ_ASSERT(pn->isKind(PNK_COMPREHENSIONFOR)); + MOZ_ASSERT(forNode->isKind(PNK_COMPREHENSIONFOR)); - TernaryNode* forHead = &pn->pn_left->as(); + TernaryNode* forHead = forNode->head(); MOZ_ASSERT(forHead->isKind(PNK_FOROF)); ParseNode* forHeadExpr = forHead->kid3(); - ParseNode* forBody = pn->pn_right; + ParseNode* forBody = forNode->body(); ParseNode* loopDecl = forHead->kid1(); bool lexicalScope = false; @@ -5436,14 +5454,14 @@ BytecodeEmitter::emitComprehensionForOf(ParseNode* pn) } bool -BytecodeEmitter::emitComprehensionForIn(ParseNode* pn) +BytecodeEmitter::emitComprehensionForIn(ForNode* forNode) { - MOZ_ASSERT(pn->isKind(PNK_COMPREHENSIONFOR)); + MOZ_ASSERT(forNode->isKind(PNK_COMPREHENSIONFOR)); - TernaryNode* forHead = &pn->pn_left->as(); + TernaryNode* forHead = forNode->head(); MOZ_ASSERT(forHead->isKind(PNK_FORIN)); - ParseNode* forBody = pn->pn_right; + ParseNode* forBody = forNode->right(); ParseNode* loopDecl = forHead->kid1(); bool lexicalScope = false; @@ -5459,8 +5477,8 @@ BytecodeEmitter::emitComprehensionForIn(ParseNode* pn) * object depending on the loop variant (for-in, for-each-in, or * destructuring for-in). */ - MOZ_ASSERT(pn->isOp(JSOP_ITER)); - if (!emit2(JSOP_ITER, (uint8_t) pn->pn_iflags)) + MOZ_ASSERT(forNode->isOp(JSOP_ITER)); + if (!emit2(JSOP_ITER, (uint8_t) forNode->iflags())) return false; // For-in loops have both the iterator and the value on the stack. Push @@ -5557,17 +5575,18 @@ BytecodeEmitter::emitComprehensionForIn(ParseNode* pn) } bool -BytecodeEmitter::emitComprehensionFor(ParseNode* compFor) +BytecodeEmitter::emitComprehensionFor(ForNode* forNode) { - MOZ_ASSERT(compFor->pn_left->isKind(PNK_FORIN) || - compFor->pn_left->isKind(PNK_FOROF)); + TernaryNode* head = forNode->head(); + MOZ_ASSERT(head->isKind(PNK_FORIN) || + head->isKind(PNK_FOROF)); - if (!updateLineNumberNotes(compFor->pn_pos.begin)) + if (!updateLineNumberNotes(forNode->pn_pos.begin)) return false; - return compFor->pn_left->isKind(PNK_FORIN) - ? emitComprehensionForIn(compFor) - : emitComprehensionForOf(compFor); + return head->isKind(PNK_FORIN) + ? emitComprehensionForIn(forNode) + : emitComprehensionForOf(forNode); } MOZ_NEVER_INLINE bool @@ -5865,8 +5884,11 @@ BytecodeEmitter::emitAsyncWrapper(unsigned index, bool needsHomeObject, bool isA } bool -BytecodeEmitter::emitDo(ParseNode* pn) +BytecodeEmitter::emitDo(BinaryNode* doNode) { + ParseNode* bodyNode = doNode->left(); + ParseNode* condNode = doNode->right(); + /* Emit an annotated nop so IonBuilder can recognize the 'do' loop. */ unsigned noteIndex; if (!newSrcNote(SRC_WHILE, ¬eIndex)) @@ -5880,7 +5902,7 @@ BytecodeEmitter::emitDo(ParseNode* pn) /* Compile the loop body. */ JumpTarget top; - if (!emitLoopHead(pn->pn_left, &top)) + if (!emitLoopHead(bodyNode, &top)) return false; LoopControl loopInfo(this, StatementKind::DoLoop); @@ -5889,7 +5911,7 @@ BytecodeEmitter::emitDo(ParseNode* pn) if (!emitLoopEntry(nullptr, empty)) return false; - if (!emitTree(pn->pn_left)) + if (!emitTree(bodyNode)) return false; // Set the offset for continues. @@ -5897,7 +5919,7 @@ BytecodeEmitter::emitDo(ParseNode* pn) return false; /* Compile the loop condition, now that continues know where to go. */ - if (!emitTree(pn->pn_right)) + if (!emitTree(condNode)) return false; JumpList beq; @@ -5927,7 +5949,7 @@ BytecodeEmitter::emitDo(ParseNode* pn) } bool -BytecodeEmitter::emitWhile(ParseNode* pn) +BytecodeEmitter::emitWhile(BinaryNode* whileNode) { /* * Minimize bytecodes issued for one or more iterations by jumping to @@ -5951,11 +5973,14 @@ BytecodeEmitter::emitWhile(ParseNode* pn) // want to emit the line note after the initial goto, so that // "cont" stops on each iteration -- but without a stop before the // first iteration. - if (parser->tokenStream.srcCoords.lineNum(pn->pn_pos.begin) == - parser->tokenStream.srcCoords.lineNum(pn->pn_pos.end) && - !updateSourceCoordNotes(pn->pn_pos.begin)) + if (parser->tokenStream.srcCoords.lineNum(whileNode->pn_pos.begin) == + parser->tokenStream.srcCoords.lineNum(whileNode->pn_pos.end) && + !updateSourceCoordNotes(whileNode->pn_pos.begin)) return false; + ParseNode* bodyNode = whileNode->right(); + ParseNode* condNode = whileNode->left(); + JumpTarget top{ -1 }; if (!emitJumpTarget(&top)) return false; @@ -5971,15 +5996,15 @@ BytecodeEmitter::emitWhile(ParseNode* pn) if (!emitJump(JSOP_GOTO, &jmp)) return false; - if (!emitLoopHead(pn->pn_right, &top)) + if (!emitLoopHead(bodyNode, &top)) return false; - if (!emitTreeInBranch(pn->pn_right)) + if (!emitTreeInBranch(bodyNode)) return false; - if (!emitLoopEntry(pn->pn_left, jmp)) + if (!emitLoopEntry(condNode, jmp)) return false; - if (!emitTree(pn->pn_left)) + if (!emitTree(condNode)) return false; JumpList beq; @@ -6715,7 +6740,7 @@ BytecodeEmitter::emitDeleteProperty(ParseNode* node) } } - if (!poe.emitDelete(propExpr->nameAtom())) { // [Super] + if (!poe.emitDelete(propExpr->key().pn_atom)) { // [Super] // // THIS // // [Other] // // SUCCEEDED @@ -6885,7 +6910,7 @@ BytecodeEmitter::emitDeleteElementInOptChain( MOZ_ASSERT_IF(elemExpr->is(), !elemExpr->as().isSuper()); - if (!emitOptionalTree(elemExpr->pn_left, oe)) { + if (!emitOptionalTree(&elemExpr->expression(), oe)) { // [stack] OBJ return false; } @@ -6900,7 +6925,7 @@ BytecodeEmitter::emitDeleteElementInOptChain( } } - if (!emitTree(elemExpr->pn_right)) { + if (!emitTree(&elemExpr->key())) { // [stack] OBJ KEY return false; } @@ -6923,7 +6948,7 @@ SelfHostedCallFunctionName(JSAtom* name, ExclusiveContext* cx) } bool -BytecodeEmitter::emitSelfHostedCallFunction(ParseNode* pn) +BytecodeEmitter::emitSelfHostedCallFunction(BinaryNode* callNode) { // Special-casing of callFunction to emit bytecode that directly // invokes the callee with the correct |this| object and arguments. @@ -6934,23 +6959,23 @@ BytecodeEmitter::emitSelfHostedCallFunction(ParseNode* pn) // // argc is set to the amount of actually emitted args and the // emitting of args below is disabled by setting emitArgs to false. - ParseNode* pn_callee = pn->pn_left; - ListNode* argsList = &pn->pn_right->as(); + ParseNode* calleeNode = callNode->left(); + ListNode* argsList = &callNode->right()->as(); - const char* errorName = SelfHostedCallFunctionName(pn_callee->name(), cx); + const char* errorName = SelfHostedCallFunctionName(calleeNode->name(), cx); if (argsList->count() < 2) { - reportError(pn, JSMSG_MORE_ARGS_NEEDED, errorName, "2", "s"); + reportError(callNode, JSMSG_MORE_ARGS_NEEDED, errorName, "2", "s"); return false; } - JSOp callOp = pn->getOp(); + JSOp callOp = callNode->getOp(); if (callOp != JSOP_CALL) { - reportError(pn, JSMSG_NOT_CONSTRUCTOR, errorName); + reportError(callNode, JSMSG_NOT_CONSTRUCTOR, errorName); return false; } - bool constructing = pn_callee->name() == cx->names().constructContentFunction; + bool constructing = calleeNode->name() == cx->names().constructContentFunction; ParseNode* funNode = argsList->head(); if (constructing) callOp = JSOP_NEW; @@ -6962,7 +6987,7 @@ BytecodeEmitter::emitSelfHostedCallFunction(ParseNode* pn) #ifdef DEBUG if (emitterMode == BytecodeEmitter::SelfHosting && - pn_callee->name() == cx->names().callFunction) + calleeNode->name() == cx->names().callFunction) { if (!emit1(JSOP_DEBUGCHECKSELFHOSTED)) return false; @@ -7000,13 +7025,13 @@ BytecodeEmitter::emitSelfHostedCallFunction(ParseNode* pn) } bool -BytecodeEmitter::emitSelfHostedResumeGenerator(ParseNode* pn) +BytecodeEmitter::emitSelfHostedResumeGenerator(BinaryNode* callNode) { - ListNode* argsList = &pn->pn_right->as(); + ListNode* argsList = &callNode->right()->as(); // Syntax: resumeGenerator(gen, value, 'next'|'throw'|'close') if (argsList->count() != 3) { - reportError(pn, JSMSG_MORE_ARGS_NEEDED, "resumeGenerator", "1", "s"); + reportError(callNode, JSMSG_MORE_ARGS_NEEDED, "resumeGenerator", "1", "s"); return false; } @@ -7040,12 +7065,12 @@ BytecodeEmitter::emitSelfHostedForceInterpreter(ParseNode* pn) } bool -BytecodeEmitter::emitSelfHostedAllowContentIter(ParseNode* pn) +BytecodeEmitter::emitSelfHostedAllowContentIter(BinaryNode* callNode) { - ListNode* argsList = &pn->pn_right->as(); + ListNode* argsList = &callNode->right()->as(); if (argsList->count() != 1) { - reportError(pn, JSMSG_MORE_ARGS_NEEDED, "allowContentIter", "1", ""); + reportError(callNode, JSMSG_MORE_ARGS_NEEDED, "allowContentIter", "1", ""); return false; } @@ -7066,10 +7091,11 @@ BytecodeEmitter::isRestParameter(ParseNode* pn) if (!pn->isKind(PNK_NAME)) { if (emitterMode == BytecodeEmitter::SelfHosting && pn->isKind(PNK_CALL)) { - ParseNode* pn_callee = pn->pn_left; - if (pn_callee->getKind() == PNK_NAME && - pn_callee->name() == cx->names().allowContentIter) - return isRestParameter(pn->pn_right->as().head()); + BinaryNode* callNode = &pn->as(); + ParseNode* calleeNode = callNode->left(); + if (calleeNode->getKind() == PNK_NAME && + calleeNode->name() == cx->names().allowContentIter) + return isRestParameter(callNode->right()->as().head()); } return false; } @@ -7235,12 +7261,12 @@ BytecodeEmitter::emitOptionalCalleeAndThis( */ bool BytecodeEmitter::emitOptionalCall( - ParseNode* callNode, + BinaryNode* callNode, OptionalEmitter& oe, ValueUsage valueUsage) { - ParseNode* calleeNode = callNode->pn_left; - ListNode* argsList = &callNode->pn_right->as(); + ParseNode* calleeNode = callNode->left(); + ListNode* argsList = &callNode->right()->as(); bool isCall = true; bool isSpread = IsSpreadOp(callNode->getOp()); uint32_t argc = argsList->count(); @@ -7302,7 +7328,7 @@ ParseNode* BytecodeEmitter::getCoordNode(ParseNode* pn, // // obj()['aprop']() // expression // ^ // column coord - coordNode = calleeNode->pn_right; + coordNode = &calleeNode->as().key(); break; case PNK_NAME: // Use the start of callee names. @@ -7356,7 +7382,7 @@ BytecodeEmitter::emitArguments(ListNode* argsList, bool isCall, bool isSpread, bool BytecodeEmitter::emitCallOrNew( - ParseNode* callNode, + BinaryNode* callNode, ValueUsage valueUsage /* = ValueUsage::WantValue */) { /* @@ -7375,8 +7401,8 @@ BytecodeEmitter::emitCallOrNew( * will box into the global object). */ bool isCall = callNode->isKind(PNK_CALL) || callNode->isKind(PNK_TAGGED_TEMPLATE); - ParseNode* calleeNode = callNode->pn_left; - ListNode* argsList = &callNode->pn_right->as(); + ParseNode* calleeNode = callNode->left(); + ListNode* argsList = &callNode->right()->as(); bool isSpread = IsSpreadOp(callNode->getOp()); @@ -7457,7 +7483,7 @@ BytecodeEmitter::emitCalleeAndThis( return false; } } - if (!poe.emitGet(prop->nameAtom())) { // CALLEE THIS? + if (!poe.emitGet(prop->key().pn_atom)) { // CALLEE THIS? return false; } break; @@ -7734,7 +7760,7 @@ BytecodeEmitter::emitPropertyList(ListNode* obj, MutableHandlePlainObject objp, } /* Emit an index for t[2] for later consumption by JSOP_INITELEM. */ - ParseNode* key = propdef->pn_left; + ParseNode* key = propdef->as().left(); bool isIndex = false; if (key->isKind(PNK_NUMBER)) { if (!emitNumberOp(key->pn_dval)) @@ -7754,7 +7780,8 @@ BytecodeEmitter::emitPropertyList(ListNode* obj, MutableHandlePlainObject objp, } /* Emit code for the property initializer. */ - if (!emitTree(propdef->pn_right)) + ParseNode* propVal = propdef->as().right(); + if (!emitTree(propVal)) return false; JSOp op = propdef->getOp(); @@ -7769,11 +7796,11 @@ BytecodeEmitter::emitPropertyList(ListNode* obj, MutableHandlePlainObject objp, if (op == JSOP_INITPROP_GETTER || op == JSOP_INITPROP_SETTER) objp.set(nullptr); - if (propdef->pn_right->isKind(PNK_FUNCTION) && - propdef->pn_right->pn_funbox->needsHomeObject()) + if (propVal->isKind(PNK_FUNCTION) && + propVal->pn_funbox->needsHomeObject()) { - MOZ_ASSERT(propdef->pn_right->pn_funbox->function()->allowSuperProperty()); - bool isAsync = propdef->pn_right->pn_funbox->isAsync(); + MOZ_ASSERT(propVal->pn_funbox->function()->allowSuperProperty()); + bool isAsync = propVal->pn_funbox->isAsync(); if (isAsync) { if (!emit1(JSOP_SWAP)) return false; @@ -7807,7 +7834,7 @@ BytecodeEmitter::emitPropertyList(ListNode* obj, MutableHandlePlainObject objp, case JSOP_INITHIDDENPROP_SETTER: op = JSOP_INITHIDDENELEM_SETTER; break; default: MOZ_CRASH("Invalid op"); } - if (propdef->pn_right->isDirectRHSAnonFunction()) { + if (propVal->isDirectRHSAnonFunction()) { if (!emitDupAt(1)) return false; if (!emit2(JSOP_SETFUNNAME, uint8_t(prefixKind))) @@ -7836,9 +7863,9 @@ BytecodeEmitter::emitPropertyList(ListNode* obj, MutableHandlePlainObject objp, objp.set(nullptr); } - if (propdef->pn_right->isDirectRHSAnonFunction()) { + if (propVal->isDirectRHSAnonFunction()) { RootedAtom keyName(cx, key->pn_atom); - if (!setOrEmitSetFunName(propdef->pn_right, keyName, prefixKind)) + if (!setOrEmitSetFunName(propVal, keyName, prefixKind)) return false; } if (!emitIndex32(op, index)) @@ -8042,7 +8069,7 @@ BytecodeEmitter::emitArray(ParseNode* arrayHead, uint32_t count, JSOp op) if (emitterMode == BytecodeEmitter::SelfHosting && expr->isKind(PNK_CALL) && - expr->pn_left->name() == cx->names().allowContentIter) + expr->as().left()->name() == cx->names().allowContentIter) { allowSelfHostedIter = true; } @@ -8226,8 +8253,8 @@ BytecodeEmitter::emitFunctionFormalParameters(ListNode* paramsBody) ParseNode* bindingElement = arg; ParseNode* initializer = nullptr; if (arg->isKind(PNK_ASSIGN)) { - bindingElement = arg->pn_left; - initializer = arg->pn_right; + bindingElement = arg->as().left(); + initializer = arg->as().right(); } // Left-hand sides are either simple names or destructuring patterns. @@ -8622,22 +8649,22 @@ BytecodeEmitter::emitTree(ParseNode* pn, ValueUsage valueUsage /* = ValueUsage:: break; case PNK_WHILE: - if (!emitWhile(pn)) + if (!emitWhile(&pn->as())) return false; break; case PNK_DOWHILE: - if (!emitDo(pn)) + if (!emitDo(&pn->as())) return false; break; case PNK_FOR: - if (!emitFor(pn)) + if (!emitFor(&pn->as())) return false; break; case PNK_COMPREHENSIONFOR: - if (!emitComprehensionFor(pn)) + if (!emitComprehensionFor(&pn->as())) return false; break; @@ -8652,7 +8679,7 @@ BytecodeEmitter::emitTree(ParseNode* pn, ValueUsage valueUsage /* = ValueUsage:: break; case PNK_WITH: - if (!emitWith(pn)) + if (!emitWith(&pn->as())) return false; break; @@ -8733,10 +8760,12 @@ BytecodeEmitter::emitTree(ParseNode* pn, ValueUsage valueUsage /* = ValueUsage:: case PNK_MULASSIGN: case PNK_DIVASSIGN: case PNK_MODASSIGN: - case PNK_POWASSIGN: - if (!emitAssignment(pn->pn_left, pn->getOp(), pn->pn_right)) + case PNK_POWASSIGN: { + AssignmentNode* assignNode = &pn->as(); + if (!emitAssignment(assignNode->left(), assignNode->getOp(), assignNode->right())) return false; break; + } case PNK_CONDITIONAL: if (!emitConditionalExpression(pn->as(), valueUsage)) @@ -8861,7 +8890,7 @@ BytecodeEmitter::emitTree(ParseNode* pn, ValueUsage valueUsage /* = ValueUsage:: return false; } } - if (!poe.emitGet(prop->nameAtom())) { // PROP + if (!poe.emitGet(prop->key().pn_atom)) { // PROP return false; } break; @@ -8892,7 +8921,7 @@ BytecodeEmitter::emitTree(ParseNode* pn, ValueUsage valueUsage /* = ValueUsage:: case PNK_CALL: case PNK_GENEXP: case PNK_SUPERCALL: - if (!emitCallOrNew(pn, valueUsage)) + if (!emitCallOrNew(&pn->as(), valueUsage)) return false; break; @@ -8919,17 +8948,19 @@ BytecodeEmitter::emitTree(ParseNode* pn, ValueUsage valueUsage /* = ValueUsage:: } break; - case PNK_EXPORT_DEFAULT: + case PNK_EXPORT_DEFAULT: { MOZ_ASSERT(sc->isModuleContext()); - if (!emitTree(pn->pn_kid)) + BinaryNode* ed = &pn->as(); + if (!emitTree(ed->left())) return false; - if (pn->pn_right) { - if (!emitLexicalInitialization(pn->pn_right)) + if (ed->right()) { + if (!emitLexicalInitialization(ed->right())) return false; if (!emit1(JSOP_POP)) return false; } break; + } case PNK_EXPORT_FROM: MOZ_ASSERT(sc->isModuleContext()); @@ -9030,7 +9061,7 @@ BytecodeEmitter::emitTree(ParseNode* pn, ValueUsage valueUsage /* = ValueUsage:: break; case PNK_SETTHIS: - if (!emitSetThis(pn)) + if (!emitSetThis(&pn->as())) return false; break; @@ -9114,7 +9145,7 @@ BytecodeEmitter::emitOptionalTree( } case PNK_CALL: case PNK_OPTCALL: { - if (!emitOptionalCall(pn, oe, valueUsage)) { + if (!emitOptionalCall(&pn->as(), oe, valueUsage)) { return false; } break; @@ -9259,7 +9290,7 @@ BytecodeEmitter::emitOptionalDotExpression( } } - if (!poe.emitGet(prop->nameAtom())) { + if (!poe.emitGet(prop->key().pn_atom)) { // [stack] PROP return false; } diff --git a/js/src/frontend/BytecodeEmitter.h b/js/src/frontend/BytecodeEmitter.h index 416c3cf4bc..46b2d0b4f4 100644 --- a/js/src/frontend/BytecodeEmitter.h +++ b/js/src/frontend/BytecodeEmitter.h @@ -469,7 +469,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter 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 emitSetThis(ParseNode* pn); + MOZ_MUST_USE bool emitSetThis(BinaryNode* setThisNode); MOZ_MUST_USE bool emitCheckDerivedClassConstructorReturn(); // Handle jump opcodes and jump targets. @@ -564,7 +564,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter } MOZ_MUST_USE bool emitAwaitInInnermostScope(ParseNode* pn); MOZ_MUST_USE bool emitAwaitInScope(EmitterScope& currentScope); - MOZ_MUST_USE bool emitPropLHS(ParseNode* pn); + MOZ_MUST_USE bool emitPropLHS(PropertyAccess* prop); MOZ_MUST_USE bool emitPropIncDec(ParseNode* pn); MOZ_MUST_USE bool emitAsyncWrapperLambda(unsigned index, bool isArrow); @@ -577,7 +577,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter // opcode onto the stack in the right order. In the case of SETELEM, the // value to be assigned must already be pushed. enum class EmitElemOption { Get, Set, Call, IncDec, CompoundAssign, Ref }; - MOZ_MUST_USE bool emitElemOperands(ParseNode* pn, EmitElemOption opts); + MOZ_MUST_USE bool emitElemOperands(PropertyByValue* elem, EmitElemOption opts); MOZ_MUST_USE bool emitElemObjAndKey(PropertyByValue* elem, bool isSuper, ElemOpEmitter& eoe); MOZ_MUST_USE bool emitElemOpBase(JSOp op); @@ -585,13 +585,13 @@ struct MOZ_STACK_CLASS BytecodeEmitter MOZ_MUST_USE bool emitCatch(TernaryNode* catchNode); MOZ_MUST_USE bool emitIf(TernaryNode* ifNode); - MOZ_MUST_USE bool emitWith(ParseNode* pn); + MOZ_MUST_USE bool emitWith(BinaryNode* withNode); MOZ_NEVER_INLINE MOZ_MUST_USE bool emitLabeledStatement(const LabeledStatement* pn); MOZ_NEVER_INLINE MOZ_MUST_USE bool emitLexicalScope(ParseNode* pn); MOZ_MUST_USE bool emitLexicalScopeBody(ParseNode* body, EmitLineNumberNote emitLineNote = EMIT_LINENOTE); - MOZ_NEVER_INLINE MOZ_MUST_USE bool emitSwitch(SwitchStatement* pn); + MOZ_NEVER_INLINE MOZ_MUST_USE bool emitSwitch(SwitchStatement* switchStmt); MOZ_NEVER_INLINE MOZ_MUST_USE bool emitTry(TernaryNode* tryNode); enum DestructuringFlavor { @@ -720,7 +720,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter MOZ_MUST_USE bool emitOptionalElemExpression(PropertyByValueBase* elem, ElemOpEmitter& eoe, bool isSuper, OptionalEmitter& oe); - MOZ_MUST_USE bool emitOptionalCall(ParseNode* callNode, + MOZ_MUST_USE bool emitOptionalCall(BinaryNode* callNode, OptionalEmitter& oe, ValueUsage valueUsage); MOZ_MUST_USE bool emitDeletePropertyInOptChain(PropertyAccessBase* propExpr, @@ -750,7 +750,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter ListNode* argsList); MOZ_MUST_USE bool emitArguments(ListNode* argsList, bool isCall, bool isSpread, CallOrNewEmitter& cone); - MOZ_MUST_USE bool emitCallOrNew(ParseNode* pn, + MOZ_MUST_USE bool emitCallOrNew(BinaryNode* pn, ValueUsage valueUsage = ValueUsage::WantValue); MOZ_MUST_USE bool emitCalleeAndThis(ParseNode* callNode, ParseNode* calleeNode, @@ -760,23 +760,23 @@ struct MOZ_STACK_CLASS BytecodeEmitter CallOrNewEmitter& cone, OptionalEmitter& oe); - MOZ_MUST_USE bool emitSelfHostedCallFunction(ParseNode* pn); - MOZ_MUST_USE bool emitSelfHostedResumeGenerator(ParseNode* pn); + MOZ_MUST_USE bool emitSelfHostedCallFunction(BinaryNode* callNode); + MOZ_MUST_USE bool emitSelfHostedResumeGenerator(BinaryNode* callNode); MOZ_MUST_USE bool emitSelfHostedForceInterpreter(ParseNode* pn); - MOZ_MUST_USE bool emitSelfHostedAllowContentIter(ParseNode* pn); + MOZ_MUST_USE bool emitSelfHostedAllowContentIter(BinaryNode* callNode); - MOZ_MUST_USE bool emitComprehensionFor(ParseNode* compFor); - MOZ_MUST_USE bool emitComprehensionForIn(ParseNode* pn); + MOZ_MUST_USE bool emitComprehensionFor(ForNode* forNode); + MOZ_MUST_USE bool emitComprehensionForIn(ForNode* forNode); MOZ_MUST_USE bool emitComprehensionForInOrOfVariables(ParseNode* pn, bool* lexicalScope); - MOZ_MUST_USE bool emitComprehensionForOf(ParseNode* pn); + MOZ_MUST_USE bool emitComprehensionForOf(ForNode* forNode); - MOZ_MUST_USE bool emitDo(ParseNode* pn); - MOZ_MUST_USE bool emitWhile(ParseNode* pn); + MOZ_MUST_USE bool emitDo(BinaryNode* doNode); + MOZ_MUST_USE bool emitWhile(BinaryNode* whileNode); - MOZ_MUST_USE bool emitFor(ParseNode* pn, EmitterScope* headLexicalEmitterScope = nullptr); - MOZ_MUST_USE bool emitCStyleFor(ParseNode* pn, EmitterScope* headLexicalEmitterScope); - MOZ_MUST_USE bool emitForIn(ParseNode* pn, EmitterScope* headLexicalEmitterScope); - MOZ_MUST_USE bool emitForOf(ParseNode* pn, EmitterScope* headLexicalEmitterScope); + MOZ_MUST_USE bool emitFor(ForNode* forNode, EmitterScope* headLexicalEmitterScope = nullptr); + MOZ_MUST_USE bool emitCStyleFor(ForNode* forNode, EmitterScope* headLexicalEmitterScope); + MOZ_MUST_USE bool emitForIn(ForNode* forNode, EmitterScope* headLexicalEmitterScope); + MOZ_MUST_USE bool emitForOf(ForNode* forNode, EmitterScope* headLexicalEmitterScope); MOZ_MUST_USE bool emitInitializeForInOrOfTarget(TernaryNode* forHead); diff --git a/js/src/frontend/FoldConstants.cpp b/js/src/frontend/FoldConstants.cpp index ee1d5983aa..dfe6f75fdd 100644 --- a/js/src/frontend/FoldConstants.cpp +++ b/js/src/frontend/FoldConstants.cpp @@ -141,14 +141,14 @@ ContainsHoistedDeclaration(ExclusiveContext* cx, ParseNode* node, bool* result) // Statements possibly containing hoistable declarations only in the left // half, in ParseNode terms -- the loop body in AST terms. case PNK_DOWHILE: - return ContainsHoistedDeclaration(cx, node->pn_left, result); + return ContainsHoistedDeclaration(cx, node->as().left(), result); // Statements possibly containing hoistable declarations only in the // right half, in ParseNode terms -- the loop body or nested statement // (usually a block statement), in AST terms. case PNK_WHILE: case PNK_WITH: - return ContainsHoistedDeclaration(cx, node->pn_right, result); + return ContainsHoistedDeclaration(cx, node->as().right(), result); case PNK_LABEL: return ContainsHoistedDeclaration(cx, node->pn_expr, result); @@ -228,18 +228,20 @@ ContainsHoistedDeclaration(ExclusiveContext* cx, ParseNode* node, bool* result) // A switch node's left half is an expression; only its right half (a // list of cases/defaults, or a block node) could contain hoisted // declarations. - case PNK_SWITCH: - MOZ_ASSERT(node->isArity(PN_BINARY)); - return ContainsHoistedDeclaration(cx, node->pn_right, result); + case PNK_SWITCH: { + SwitchStatement* switchNode = &node->as(); + return ContainsHoistedDeclaration(cx, &switchNode->lexicalForCaseList(), result); + } - case PNK_CASE: - return ContainsHoistedDeclaration(cx, node->as().statementList(), result); + case PNK_CASE: { + CaseClause* caseClause = &node->as(); + return ContainsHoistedDeclaration(cx, caseClause->statementList(), result); + } case PNK_FOR: case PNK_COMPREHENSIONFOR: { - MOZ_ASSERT(node->isArity(PN_BINARY)); - - TernaryNode* loopHead = &node->pn_left->as(); + ForNode* forNode = &node->as(); + TernaryNode* loopHead = forNode->head(); MOZ_ASSERT(loopHead->isKind(PNK_FORHEAD) || loopHead->isKind(PNK_FORIN) || loopHead->isKind(PNK_FOROF)); @@ -275,7 +277,7 @@ ContainsHoistedDeclaration(ExclusiveContext* cx, ParseNode* node, bool* result) } } - ParseNode* loopBody = node->pn_right; + ParseNode* loopBody = forNode->body(); return ContainsHoistedDeclaration(cx, loopBody, result); } @@ -1301,19 +1303,16 @@ static bool FoldElement(ExclusiveContext* cx, ParseNode** nodePtr, Parser& parser, bool inGenexpLambda) { - ParseNode* node = *nodePtr; + PropertyByValueBase* elem = &(*nodePtr)->as(); - MOZ_ASSERT(node->isKind(PNK_ELEM) || node->isKind(PNK_OPTELEM)); - MOZ_ASSERT(node->isArity(PN_BINARY)); - - ParseNode*& expr = node->pn_left; - if (!Fold(cx, &expr, parser, inGenexpLambda)) + if (!Fold(cx, elem->unsafeLeftReference(), parser, inGenexpLambda)) return false; - ParseNode*& key = node->pn_right; - if (!Fold(cx, &key, parser, inGenexpLambda)) + if (!Fold(cx, elem->unsafeRightReference(), parser, inGenexpLambda)) return false; + ParseNode* expr = &elem->expression(); + ParseNode* key = &elem->key(); PropertyName* name = nullptr; if (key->isKind(PNK_STRING)) { JSAtom* atom = key->pn_atom; @@ -1351,7 +1350,7 @@ FoldElement(ExclusiveContext* cx, ParseNode** nodePtr, Parser& if (!nameNode) return false; ParseNode* dottedAccess; - if (node->isKind(PNK_OPTELEM)) { + if (elem->isKind(PNK_OPTELEM)) { dottedAccess = parser.handler.newOptionalPropertyAccess(expr, nameNode); } else { dottedAccess = parser.handler.newPropertyAccess(expr, nameNode); @@ -1359,7 +1358,7 @@ FoldElement(ExclusiveContext* cx, ParseNode** nodePtr, Parser& if (!dottedAccess) { return false; } - dottedAccess->setInParens(node->isInParens()); + dottedAccess->setInParens(elem->isInParens()); ReplaceNode(nodePtr, dottedAccess); // If we've replaced |expr["prop"]| with |expr.prop|, we can now free the @@ -1367,10 +1366,10 @@ FoldElement(ExclusiveContext* cx, ParseNode** nodePtr, Parser& // now using as a sub-node of |dottedAccess|. Munge |expr["prop"]| into a // node with |"prop"| as its only child, that'll pass AST sanity-checking // assertions during freeing, then free it. - node->setKind(PNK_TYPEOFEXPR); - node->setArity(PN_UNARY); - node->pn_kid = key; - parser.freeTree(node); + elem->setKind(PNK_TYPEOFEXPR); + elem->setArity(PN_UNARY); + elem->pn_kid = key; + parser.freeTree(elem); return true; } @@ -1523,7 +1522,7 @@ FoldAdd(ExclusiveContext* cx, ParseNode** nodePtr, Parser& par } static bool -FoldCall(ExclusiveContext* cx, ParseNode* node, Parser& parser, +FoldCall(ExclusiveContext* cx, BinaryNode* node, Parser& parser, bool inGenexpLambda) { MOZ_ASSERT(node->isKind(PNK_CALL) || @@ -1531,7 +1530,6 @@ FoldCall(ExclusiveContext* cx, ParseNode* node, Parser& parser node->isKind(PNK_SUPERCALL) || node->isKind(PNK_NEW) || node->isKind(PNK_TAGGED_TEMPLATE)); - MOZ_ASSERT(node->isArity(PN_BINARY)); // Don't fold a parenthesized callable component in an invocation, as this // might cause a different |this| value to be used, changing semantics: @@ -1544,14 +1542,13 @@ FoldCall(ExclusiveContext* cx, ParseNode* node, Parser& parser // assertEq(obj.f``, "obj"); // // See bug 537673 and bug 1182373. - ParseNode** pn_callee = &node->pn_left; - if (node->isKind(PNK_NEW) || !(*pn_callee)->isInParens()) { - if (!Fold(cx, pn_callee, parser, inGenexpLambda)) + ParseNode* callee = node->left(); + if (node->isKind(PNK_NEW) || !callee->isInParens()) { + if (!Fold(cx, node->unsafeLeftReference(), parser, inGenexpLambda)) return false; } - ParseNode** pn_args = &node->pn_right; - if (!Fold(cx, pn_args, parser, inGenexpLambda)) + if (!Fold(cx, node->unsafeRightReference(), parser, inGenexpLambda)) return false; return true; @@ -1616,18 +1613,14 @@ FoldForHead(ExclusiveContext* cx, TernaryNode* node, Parser& p } static bool -FoldDottedProperty(ExclusiveContext* cx, ParseNode* node, Parser& parser, +FoldDottedProperty(ExclusiveContext* cx, PropertyAccessBase* prop, Parser& parser, bool inGenexpLambda) { - MOZ_ASSERT(node->isKind(PNK_DOT) || node->isKind(PNK_OPTDOT)); - MOZ_ASSERT(node->isArity(PN_BINARY)); - // Iterate through a long chain of dotted property accesses to find the // most-nested non-dotted property node, then fold that. - ParseNode** nested = &node->pn_left; + ParseNode** nested = prop->unsafeLeftReference(); while ((*nested)->isKind(PNK_DOT) || (*nested)->isKind(PNK_OPTDOT)) { - MOZ_ASSERT((*nested)->isArity(PN_BINARY)); - nested = &(*nested)->pn_left; + nested = (*nested)->as().unsafeLeftReference(); } return Fold(cx, nested, parser, inGenexpLambda); @@ -1736,8 +1729,7 @@ Fold(ExclusiveContext* cx, ParseNode** pnp, Parser& parser, bo case PNK_EXPORT_DEFAULT: case PNK_GENEXP: - MOZ_ASSERT(pn->isArity(PN_BINARY)); - return Fold(cx, &pn->pn_left, parser, inGenexpLambda); + return Fold(cx, pn->as().unsafeLeftReference(), parser, inGenexpLambda); case PNK_DELETEOPTCHAIN: case PNK_OPTCHAIN: @@ -1804,12 +1796,15 @@ Fold(ExclusiveContext* cx, ParseNode** pnp, Parser& parser, bo case PNK_IMPORT_SPEC_LIST: return FoldList(cx, &pn->as(), parser, inGenexpLambda); - case PNK_INITIALYIELD: + case PNK_INITIALYIELD: { MOZ_ASSERT(pn->isArity(PN_UNARY)); - MOZ_ASSERT(pn->pn_kid->isKind(PNK_ASSIGN) && - pn->pn_kid->pn_left->isKind(PNK_NAME) && - pn->pn_kid->pn_right->isKind(PNK_GENERATOR)); +#ifdef DEBUG + AssignmentNode* assignNode = &pn->pn_kid->as(); + MOZ_ASSERT(assignNode->left()->isKind(PNK_NAME)); + MOZ_ASSERT(assignNode->right()->isKind(PNK_GENERATOR)); +#endif return true; + } case PNK_YIELD_STAR: MOZ_ASSERT(pn->isArity(PN_UNARY)); @@ -1836,6 +1831,7 @@ Fold(ExclusiveContext* cx, ParseNode** pnp, Parser& parser, bo case PNK_OPTELEM: case PNK_ELEM: + MOZ_ASSERT((*pnp)->is()); return FoldElement(cx, pnp, parser, inGenexpLambda); case PNK_ADD: @@ -1847,7 +1843,7 @@ Fold(ExclusiveContext* cx, ParseNode** pnp, Parser& parser, bo case PNK_NEW: case PNK_SUPERCALL: case PNK_TAGGED_TEMPLATE: - return FoldCall(cx, pn, parser, inGenexpLambda); + return FoldCall(cx, &pn->as(), parser, inGenexpLambda); case PNK_ARGUMENTS: return FoldArguments(cx, &pn->as(), parser, inGenexpLambda); @@ -1875,50 +1871,59 @@ Fold(ExclusiveContext* cx, ParseNode** pnp, Parser& parser, bo case PNK_CLASSMETHOD: case PNK_IMPORT_SPEC: case PNK_EXPORT_SPEC: - case PNK_SETTHIS: - MOZ_ASSERT(pn->isArity(PN_BINARY)); - return Fold(cx, &pn->pn_left, parser, inGenexpLambda) && - Fold(cx, &pn->pn_right, parser, inGenexpLambda); - - case PNK_NEWTARGET: - MOZ_ASSERT(pn->isArity(PN_BINARY)); - MOZ_ASSERT(pn->pn_left->isKind(PNK_POSHOLDER)); - MOZ_ASSERT(pn->pn_right->isKind(PNK_POSHOLDER)); - return true; - - case PNK_CLASSNAMES: - MOZ_ASSERT(pn->isArity(PN_BINARY)); - if (ParseNode*& outerBinding = pn->pn_left) { - if (!Fold(cx, &outerBinding, parser, inGenexpLambda)) - return false; - } - return Fold(cx, &pn->pn_right, parser, inGenexpLambda); - - case PNK_DOWHILE: - MOZ_ASSERT(pn->isArity(PN_BINARY)); - return Fold(cx, &pn->pn_left, parser, inGenexpLambda) && - FoldCondition(cx, &pn->pn_right, parser, inGenexpLambda); - - case PNK_WHILE: - MOZ_ASSERT(pn->isArity(PN_BINARY)); - return FoldCondition(cx, &pn->pn_left, parser, inGenexpLambda) && - Fold(cx, &pn->pn_right, parser, inGenexpLambda); - - case PNK_CASE: { - MOZ_ASSERT(pn->isArity(PN_BINARY)); - - // pn_left is null for DefaultClauses. - if (pn->pn_left) { - if (!Fold(cx, &pn->pn_left, parser, inGenexpLambda)) - return false; - } - return Fold(cx, &pn->pn_right, parser, inGenexpLambda); + case PNK_SETTHIS: { + BinaryNode* node = &pn->as(); + return Fold(cx, node->unsafeLeftReference(), parser, inGenexpLambda) && + Fold(cx, node->unsafeRightReference(), parser, inGenexpLambda); } - case PNK_WITH: - MOZ_ASSERT(pn->isArity(PN_BINARY)); - return Fold(cx, &pn->pn_left, parser, inGenexpLambda) && - Fold(cx, &pn->pn_right, parser, inGenexpLambda); + case PNK_NEWTARGET:{ +#ifdef DEBUG + BinaryNode* node = &pn->as(); + MOZ_ASSERT(node->left()->isKind(PNK_POSHOLDER)); + MOZ_ASSERT(node->right()->isKind(PNK_POSHOLDER)); +#endif + return true; + } + + case PNK_CLASSNAMES: { + ClassNames* names = &pn->as(); + if (names->outerBinding()) { + if (!Fold(cx, names->unsafeLeftReference(), parser, inGenexpLambda)) { + return false; + } + } + return Fold(cx, names->unsafeRightReference(), parser, inGenexpLambda); + } + + case PNK_DOWHILE: { + BinaryNode* node = &pn->as(); + return Fold(cx, node->unsafeLeftReference(), parser, inGenexpLambda) && + FoldCondition(cx, node->unsafeRightReference(), parser, inGenexpLambda); + } + + case PNK_WHILE: { + BinaryNode* node = &pn->as(); + return FoldCondition(cx, node->unsafeLeftReference(), parser, inGenexpLambda) && + Fold(cx, node->unsafeRightReference(), parser, inGenexpLambda); + } + + case PNK_CASE: { + CaseClause* caseClause = &pn->as(); + + // left (caseExpression) is null for DefaultClauses. + if (caseClause->left()) { + if (!Fold(cx, caseClause->unsafeLeftReference(), parser, inGenexpLambda)) + return false; + } + return Fold(cx, caseClause->unsafeRightReference(), parser, inGenexpLambda); + } + + case PNK_WITH: { + BinaryNode* node = &pn->as(); + return Fold(cx, node->unsafeLeftReference(), parser, inGenexpLambda) && + Fold(cx, node->unsafeRightReference(), parser, inGenexpLambda); + } case PNK_FORIN: case PNK_FOROF: @@ -1936,7 +1941,7 @@ Fold(ExclusiveContext* cx, ParseNode** pnp, Parser& parser, bo case PNK_OPTDOT: case PNK_DOT: - return FoldDottedProperty(cx, pn, parser, inGenexpLambda); + return FoldDottedProperty(cx, &pn->as(), parser, inGenexpLambda); case PNK_LEXICALSCOPE: MOZ_ASSERT(pn->isArity(PN_SCOPE)); diff --git a/js/src/frontend/FullParseHandler.h b/js/src/frontend/FullParseHandler.h index 0ce3f86567..9baee6a747 100644 --- a/js/src/frontend/FullParseHandler.h +++ b/js/src/frontend/FullParseHandler.h @@ -279,14 +279,14 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) return new_(PNK_ARRAYPUSH, JSOP_ARRAYPUSH, pos, kid); } - ParseNode* newBinary(ParseNodeKind kind, JSOp op = JSOP_NOP) { + BinaryNodeType newBinary(ParseNodeKind kind, JSOp op = JSOP_NOP) { return new_(kind, op, pos(), (ParseNode*) nullptr, (ParseNode*) nullptr); } - ParseNode* newBinary(ParseNodeKind kind, ParseNode* left, + BinaryNodeType newBinary(ParseNodeKind kind, ParseNode* left, JSOp op = JSOP_NOP) { return new_(kind, op, left->pn_pos, left, (ParseNode*) nullptr); } - ParseNode* newBinary(ParseNodeKind kind, ParseNode* left, ParseNode* right, + BinaryNodeType newBinary(ParseNodeKind kind, ParseNode* left, ParseNode* right, JSOp op = JSOP_NOP) { TokenPos pos(left->pn_pos.begin, right->pn_pos.end); return new_(kind, op, pos, left, right); @@ -340,11 +340,11 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) literal->append(element); } - ParseNode* newCall(ParseNode* callee, ParseNode* args) { + BinaryNodeType newCall(ParseNode* callee, ParseNode* args) { return new_(PNK_CALL, JSOP_CALL, callee, args); } - ParseNode* newOptionalCall(ParseNode* callee, ParseNode* args) { + BinaryNodeType newOptionalCall(ParseNode* callee, ParseNode* args) { return new_(PNK_OPTCALL, JSOP_CALL, callee, args); } @@ -352,15 +352,15 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) return new_(PNK_ARGUMENTS, JSOP_NOP, pos); } - ParseNode* newSuperCall(ParseNode* callee, ParseNode* args) { + BinaryNodeType newSuperCall(ParseNode* callee, ParseNode* args) { return new_(PNK_SUPERCALL, JSOP_SUPERCALL, callee, args); } - ParseNode* newTaggedTemplate(ParseNode* tag, ParseNode* args) { + BinaryNodeType newTaggedTemplate(ParseNode* tag, ParseNode* args) { return new_(PNK_TAGGED_TEMPLATE, JSOP_CALL, tag, args); } - ParseNode* newGenExp(ParseNode* callee, ParseNode* args) { + BinaryNodeType newGenExp(ParseNode* callee, ParseNode* args) { return new_(PNK_GENEXP, JSOP_CALL, callee, args); } @@ -378,10 +378,10 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) ListNodeType newClassMethodList(uint32_t begin) { return new_(PNK_CLASSMETHODLIST, TokenPos(begin, begin + 1)); } - ParseNode* newClassNames(ParseNode* outer, ParseNode* inner, const TokenPos& pos) { + ClassNamesType newClassNames(ParseNode* outer, ParseNode* inner, const TokenPos& pos) { return new_(outer, inner, pos); } - ParseNode* newNewTarget(ParseNode* newHolder, ParseNode* targetHolder) { + BinaryNodeType newNewTarget(ParseNode* newHolder, ParseNode* targetHolder) { return new_(PNK_NEWTARGET, JSOP_NOP, newHolder, targetHolder); } ParseNode* newPosHolder(const TokenPos& pos) { @@ -410,7 +410,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) key->isKind(PNK_STRING) || key->isKind(PNK_COMPUTED_NAME)); - ParseNode* propdef = newBinary(PNK_COLON, key, val, JSOP_INITPROP); + BinaryNode* propdef = newBinary(PNK_COLON, key, val, JSOP_INITPROP); if (!propdef) return false; @@ -428,7 +428,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) MOZ_ASSERT(name->pn_atom == expr->pn_atom); literal->setHasNonConstInitializer(); - ParseNode* propdef = newBinary(PNK_SHORTHAND, name, expr, JSOP_INITPROP); + BinaryNode* propdef = newBinary(PNK_SHORTHAND, name, expr, JSOP_INITPROP); if (!propdef) return false; literal->append(propdef); @@ -471,7 +471,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) key->isKind(PNK_STRING) || key->isKind(PNK_COMPUTED_NAME)); - ParseNode* classMethod = new_(key, fn, op, isStatic); + ClassMethod* classMethod = new_(key, fn, op, isStatic); if (!classMethod) return false; methodList->append(classMethod); @@ -527,14 +527,12 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) } } - void addCaseStatementToList(ListNodeType list, ParseNode* caseClause) { + void addCaseStatementToList(ListNodeType list, CaseClauseType caseClause) { MOZ_ASSERT(list->isKind(PNK_STATEMENTLIST)); - MOZ_ASSERT(caseClause->isKind(PNK_CASE)); - MOZ_ASSERT(caseClause->pn_right->isKind(PNK_STATEMENTLIST)); list->append(caseClause); - if (caseClause->pn_right->as().hasTopLevelFunctionDeclarations()) + if (caseClause->statementList()->hasTopLevelFunctionDeclarations()) list->setHasTopLevelFunctionDeclarations(); } @@ -560,7 +558,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) return true; } - ParseNode* newSetThis(ParseNode* thisName, ParseNode* val) { + BinaryNodeType newSetThis(ParseNode* thisName, ParseNode* val) { MOZ_ASSERT(thisName->getOp() == JSOP_GETNAME); thisName->setOp(JSOP_SETNAME); return newBinary(PNK_SETTHIS, thisName, val); @@ -570,13 +568,10 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) return new_(PNK_SEMI, JSOP_NOP, pos, (ParseNode*) nullptr); } - ParseNode* newImportDeclaration(ParseNode* importSpecSet, - ParseNode* moduleSpec, const TokenPos& pos) + BinaryNodeType newImportDeclaration(Node importSpecSet, Node moduleSpec, const TokenPos& pos) { - ParseNode* pn = new_(PNK_IMPORT, JSOP_NOP, pos, - importSpecSet, moduleSpec); - if (!pn) - return null(); + BinaryNode* pn = new_(PNK_IMPORT, JSOP_NOP, pos, + importSpecSet, moduleSpec); return pn; } @@ -584,18 +579,21 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) return new_(PNK_EXPORT, JSOP_NOP, pos, kid); } - ParseNode* newExportFromDeclaration(uint32_t begin, ParseNode* exportSpecSet, - ParseNode* moduleSpec) - { - ParseNode* pn = new_(PNK_EXPORT_FROM, JSOP_NOP, exportSpecSet, moduleSpec); - if (!pn) + BinaryNodeType newExportFromDeclaration(uint32_t begin, Node exportSpecSet, Node moduleSpec) { + BinaryNode* decl = new_(PNK_EXPORT_FROM, JSOP_NOP, exportSpecSet, moduleSpec); + if (!decl) return null(); - pn->pn_pos.begin = begin; - return pn; + decl->pn_pos.begin = begin; + return decl; } - ParseNode* newExportDefaultDeclaration(ParseNode* kid, ParseNode* maybeBinding, - const TokenPos& pos) { + BinaryNodeType newExportDefaultDeclaration(Node kid, Node maybeBinding, const TokenPos& pos) { + if (maybeBinding) { + MOZ_ASSERT(maybeBinding->isKind(PNK_NAME)); + MOZ_ASSERT(!maybeBinding->isInParens()); + + checkAndSetIsDirectRHSAnonFunction(kid); + } return new_(PNK_EXPORT_DEFAULT, JSOP_NOP, pos, kid, maybeBinding); } @@ -612,36 +610,28 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) return node; } - ParseNode* newDoWhileStatement(ParseNode* body, ParseNode* cond, const TokenPos& pos) { + BinaryNodeType newDoWhileStatement(Node body, Node cond, const TokenPos& pos) { return new_(PNK_DOWHILE, JSOP_NOP, pos, body, cond); } - ParseNode* newWhileStatement(uint32_t begin, ParseNode* cond, ParseNode* body) { + BinaryNodeType newWhileStatement(uint32_t begin, Node cond, Node body) { TokenPos pos(begin, body->pn_pos.end); return new_(PNK_WHILE, JSOP_NOP, pos, cond, body); } - Node newForStatement(uint32_t begin, TernaryNodeType forHead, Node body, unsigned iflags) { - /* A FOR node is binary, left is loop control and right is the body. */ - JSOp op = forHead->isKind(PNK_FORIN) ? JSOP_ITER : JSOP_NOP; - BinaryNode* pn = new_(PNK_FOR, op, TokenPos(begin, body->pn_pos.end), - forHead, body); - if (!pn) - return null(); - pn->pn_iflags = iflags; - return pn; + ForNodeType newForStatement(uint32_t begin, TernaryNodeType forHead, Node body, unsigned iflags) + { + return new_(TokenPos(begin, body->pn_pos.end), forHead, body, iflags); } - Node newComprehensionFor(uint32_t begin, TernaryNodeType forHead, Node body) { + ForNodeType newComprehensionFor(uint32_t begin, TernaryNodeType forHead, Node body) { // A PNK_COMPREHENSIONFOR node is binary: left is loop control, right // is the body. MOZ_ASSERT(forHead->isKind(PNK_FORIN) || forHead->isKind(PNK_FOROF)); - JSOp op = forHead->isKind(PNK_FORIN) ? JSOP_ITER : JSOP_NOP; - BinaryNode* pn = new_(PNK_COMPREHENSIONFOR, op, - TokenPos(begin, body->pn_pos.end), forHead, body); + ForNode* pn = new_(TokenPos(begin, body->pn_pos.end), forHead, body, JSOP_ITER); if (!pn) return null(); - pn->pn_iflags = JSOP_ITER; + pn->setKind(PNK_COMPREHENSIONFOR); return pn; } @@ -661,14 +651,13 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) return new_(kind, JSOP_NOP, target, nullptr, iteratedExpr, pos); } - ParseNode* newSwitchStatement(uint32_t begin, ParseNode* discriminant, - ParseNode* lexicalForCaseList, bool hasDefault) + SwitchStatementType newSwitchStatement(uint32_t begin, Node discriminant, + Node lexicalForCaseList, bool hasDefault) { return new_(begin, discriminant, lexicalForCaseList, hasDefault); - } - ParseNode* newCaseOrDefault(uint32_t begin, ParseNode* expr, ParseNode* body) { + CaseClauseType newCaseOrDefault(uint32_t begin, Node expr, Node body) { return new_(expr, body, begin); } @@ -685,7 +674,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) return new_(PNK_RETURN, JSOP_RETURN, pos, expr); } - ParseNode* newWithStatement(uint32_t begin, ParseNode* expr, ParseNode* body) { + BinaryNodeType newWithStatement(uint32_t begin, Node expr, Node body) { return new_(PNK_WITH, JSOP_NOP, TokenPos(begin, body->pn_pos.end), expr, body); } @@ -713,11 +702,11 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) return new_(PNK_PROPERTYNAME, JSOP_NOP, name, pos); } - ParseNode* newPropertyAccess(ParseNode* expr, ParseNode* key) { + PropertyAccessType newPropertyAccess(Node expr, Node key) { return new_(expr, key, expr->pn_pos.begin, key->pn_pos.end); } - ParseNode* newPropertyByValue(ParseNode* lhs, ParseNode* index, uint32_t end) { + PropertyByValueType newPropertyByValue(Node lhs, Node index, uint32_t end) { return new_(lhs, index, lhs->pn_pos.begin, end); } @@ -783,7 +772,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) return new_(PNK_MODULE, JSOP_NOP, pos()); } - Node newNewExpression(uint32_t begin, ParseNode* ctor, ParseNode* args) { + BinaryNodeType newNewExpression(uint32_t begin, Node ctor, Node args) { return new_(PNK_NEW, JSOP_NEW, TokenPos(begin, args->pn_pos.end), ctor, args); } @@ -791,10 +780,8 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) return new_(bindings, body); } - ParseNode* newAssignment(ParseNodeKind kind, ParseNode* lhs, ParseNode* rhs, - JSOp op) - { - return newBinary(kind, lhs, rhs, op); + AssignmentNodeType newAssignment(ParseNodeKind kind, Node lhs, Node rhs, JSOp op) { + return new_(kind, op, lhs, rhs); } bool isUnparenthesizedYieldExpression(ParseNode* node) { diff --git a/js/src/frontend/NameFunctions.cpp b/js/src/frontend/NameFunctions.cpp index 26ea434c89..e527085f71 100644 --- a/js/src/frontend/NameFunctions.cpp +++ b/js/src/frontend/NameFunctions.cpp @@ -73,12 +73,14 @@ class NameResolver */ bool nameExpression(ParseNode* n, bool* foundName) { switch (n->getKind()) { - case PNK_DOT: - if (!nameExpression(n->pn_left, foundName)) + case PNK_DOT: { + PropertyAccess* prop = &n->as(); + if (!nameExpression(&prop->expression(), foundName)) return false; if (!*foundName) return true; - return appendPropertyReference(n->pn_right->pn_atom); + return appendPropertyReference(prop->right()->pn_atom); + } case PNK_NAME: *foundName = true; @@ -88,16 +90,18 @@ class NameResolver *foundName = true; return buf->append("this"); - case PNK_ELEM: - if (!nameExpression(n->pn_left, foundName)) + case PNK_ELEM: { + PropertyByValue* elem = &n->as(); + if (!nameExpression(&elem->expression(), foundName)) return false; if (!*foundName) return true; - if (!buf->append('[') || !nameExpression(n->pn_right, foundName)) + if (!buf->append('[') || !nameExpression(elem->right(), foundName)) return false; if (!*foundName) return true; return buf->append(']'); + } case PNK_NUMBER: *foundName = true; @@ -128,7 +132,7 @@ class NameResolver for (int pos = nparents - 1; pos >= 0; pos--) { ParseNode* cur = parents[pos]; - if (cur->isAssignment()) + if (cur->is()) return cur; switch (cur->getKind()) { @@ -222,8 +226,8 @@ class NameResolver /* If the function is assigned to something, then that is very relevant */ if (assignment) { - if (assignment->isAssignment()) - assignment = assignment->pn_left; + if (assignment->is()) + assignment = assignment->as().left(); bool foundName = false; if (!nameExpression(assignment, &foundName)) return false; @@ -240,7 +244,7 @@ class NameResolver ParseNode* node = toName[pos]; if (node->isKind(PNK_COLON) || node->isKind(PNK_SHORTHAND)) { - ParseNode* left = node->pn_left; + ParseNode* left = node->as().left(); if (left->isKind(PNK_OBJECT_PROPERTY_NAME) || left->isKind(PNK_STRING)) { if (!appendPropertyReference(left->pn_atom)) return false; @@ -284,7 +288,7 @@ class NameResolver * for new variables and then return an anonymous function using this scope. */ bool isDirectCall(int pos, ParseNode* cur) { - return pos >= 0 && call(parents[pos]) && parents[pos]->pn_left == cur; + return pos >= 0 && call(parents[pos]) && parents[pos]->as().left() == cur; } bool resolveTemplateLiteral(ListNode* node, HandleAtom prefix) { @@ -304,10 +308,10 @@ class NameResolver } } - bool resolveTaggedTemplate(ParseNode* node, HandleAtom prefix) { - MOZ_ASSERT(node->isKind(PNK_TAGGED_TEMPLATE)); + bool resolveTaggedTemplate(BinaryNode* taggedTemplate, HandleAtom prefix) { + MOZ_ASSERT(taggedTemplate->isKind(PNK_TAGGED_TEMPLATE)); - ParseNode* tag = node->pn_left; + ParseNode* tag = taggedTemplate->left(); // The leading expression, e.g. |tag| in |tag`foo`|, // that might contain functions. @@ -317,7 +321,8 @@ class NameResolver // The callsite object node is first. This node only contains // internal strings or undefined and an array -- no user-controlled // expressions. - CallSiteNode* element = &node->pn_right->as().head()->as(); + CallSiteNode* element = + &taggedTemplate->right()->as().head()->as(); #ifdef DEBUG { ListNode* rawNodes = &element->head()->as(); @@ -404,11 +409,11 @@ class NameResolver MOZ_ASSERT(!cur->pn_kid->expr()); break; - case PNK_NEWTARGET: - MOZ_ASSERT(cur->isArity(PN_BINARY)); - MOZ_ASSERT(cur->pn_left->isKind(PNK_POSHOLDER)); - MOZ_ASSERT(cur->pn_right->isKind(PNK_POSHOLDER)); + case PNK_NEWTARGET: { + MOZ_ASSERT(cur->as().left()->isKind(PNK_POSHOLDER)); + MOZ_ASSERT(cur->as().right()->isKind(PNK_POSHOLDER)); break; + } // Nodes with a single non-null child requiring name resolution. case PNK_TYPEOFEXPR: @@ -468,45 +473,54 @@ class NameResolver case PNK_FOR: case PNK_COMPREHENSIONFOR: case PNK_CLASSMETHOD: - case PNK_SETTHIS: - MOZ_ASSERT(cur->isArity(PN_BINARY)); - if (!resolve(cur->pn_left, prefix)) + case PNK_SETTHIS: { + BinaryNode* node = &cur->as(); + if (!resolve(node->left(), prefix)) { return false; - if (!resolve(cur->pn_right, prefix)) + } + if (!resolve(node->right(), prefix)) { + return false; + } + break; + } + + case PNK_ELEM: { + PropertyByValue* elem = &cur->as(); + if (!elem->isSuper() && !resolve(&elem->expression(), prefix)) + return false; + if (!resolve(&elem->key(), prefix)) return false; break; + } - case PNK_ELEM: - MOZ_ASSERT(cur->isArity(PN_BINARY)); - if (!cur->as().isSuper() && !resolve(cur->pn_left, prefix)) + case PNK_WITH: { + BinaryNode* node = &cur->as(); + if (!resolve(node->left(), prefix)) return false; - if (!resolve(cur->pn_right, prefix)) + if (!resolve(node->right(), prefix)) return false; break; + } - case PNK_WITH: - MOZ_ASSERT(cur->isArity(PN_BINARY)); - if (!resolve(cur->pn_left, prefix)) - return false; - if (!resolve(cur->pn_right, prefix)) - return false; - break; - - case PNK_CASE: - MOZ_ASSERT(cur->isArity(PN_BINARY)); - if (ParseNode* caseExpr = cur->pn_left) { + case PNK_CASE: { + CaseClause* caseClause = &cur->as(); + if (ParseNode* caseExpr = caseClause->caseExpression()) { if (!resolve(caseExpr, prefix)) return false; } - if (!resolve(cur->pn_right, prefix)) + if (!resolve(caseClause->statementList(), prefix)) return false; break; + } - case PNK_INITIALYIELD: - MOZ_ASSERT(cur->pn_kid->isKind(PNK_ASSIGN) && - cur->pn_kid->pn_left->isKind(PNK_NAME) && - cur->pn_kid->pn_right->isKind(PNK_GENERATOR)); + case PNK_INITIALYIELD: { +#ifdef DEBUG + AssignmentNode* assignNode = &cur->pn_kid->as(); + MOZ_ASSERT(assignNode->left()->isKind(PNK_NAME)); + MOZ_ASSERT(assignNode->right()->isKind(PNK_GENERATOR)); +#endif break; + } case PNK_YIELD_STAR: MOZ_ASSERT(cur->isArity(PN_UNARY)); @@ -533,16 +547,18 @@ class NameResolver case PNK_IMPORT: case PNK_EXPORT_FROM: - case PNK_EXPORT_DEFAULT: + case PNK_EXPORT_DEFAULT: { + BinaryNode* node = &cur->as(); MOZ_ASSERT(cur->isArity(PN_BINARY)); // The left halves of these nodes don't contain any unconstrained // expressions, but it's very hard to assert this to safely rely on // it. So recur anyway. - if (!resolve(cur->pn_left, prefix)) + if (!resolve(node->left(), prefix)) return false; - MOZ_ASSERT_IF(!cur->isKind(PNK_EXPORT_DEFAULT), - cur->pn_right->isKind(PNK_STRING)); + MOZ_ASSERT_IF(!node->isKind(PNK_EXPORT_DEFAULT), + node->right()->isKind(PNK_STRING)); break; + } // Ternary nodes with three expression children. case PNK_CONDITIONAL: { @@ -601,13 +617,15 @@ class NameResolver ClassNode* classNode = &cur->as(); #ifdef DEBUG if (classNode->names()) { - ParseNode* name = classNode->names(); - MOZ_ASSERT(name->isKind(PNK_CLASSNAMES)); - MOZ_ASSERT(name->isArity(PN_BINARY)); - MOZ_ASSERT_IF(name->pn_left, name->pn_left->isKind(PNK_NAME)); - MOZ_ASSERT_IF(name->pn_left, !name->pn_left->expr()); - MOZ_ASSERT(name->pn_right->isKind(PNK_NAME)); - MOZ_ASSERT(!name->pn_right->expr()); + ClassNames* names = classNode->names(); + if (ParseNode* outerBinding = names->outerBinding()) { + MOZ_ASSERT(outerBinding->isKind(PNK_NAME)); + MOZ_ASSERT(!outerBinding->expr()); + } + + ParseNode* innerBinding = names->innerBinding(); + MOZ_ASSERT(innerBinding->isKind(PNK_NAME)); + MOZ_ASSERT(!innerBinding->expr()); } #endif if (ParseNode* heritage = classNode->heritage()) { @@ -744,21 +762,21 @@ class NameResolver break; case PNK_TAGGED_TEMPLATE: - MOZ_ASSERT(cur->isArity(PN_BINARY)); - if (!resolveTaggedTemplate(cur, prefix)) + if (!resolveTaggedTemplate(&cur->as(), prefix)) return false; break; case PNK_NEW: case PNK_CALL: case PNK_GENEXP: - case PNK_SUPERCALL: - MOZ_ASSERT(cur->isArity(PN_BINARY)); - if (!resolve(cur->pn_left, prefix)) + case PNK_SUPERCALL: { + BinaryNode* callNode = &cur->as(); + if (!resolve(callNode->left(), prefix)) return false; - if (!resolve(cur->pn_right, prefix)) + if (!resolve(callNode->right(), prefix)) return false; break; + } // Handles the arguments for new/call/supercall, but does _not_ handle // the Arguments node used by tagged template literals, since that is @@ -784,12 +802,12 @@ class NameResolver break; } for (ParseNode* item : list->contents()) { - MOZ_ASSERT(item->isKind(isImport ? PNK_IMPORT_SPEC : PNK_EXPORT_SPEC)); - MOZ_ASSERT(item->isArity(PN_BINARY)); - MOZ_ASSERT(item->pn_left->isKind(PNK_NAME)); - MOZ_ASSERT(!item->pn_left->expr()); - MOZ_ASSERT(item->pn_right->isKind(PNK_NAME)); - MOZ_ASSERT(!item->pn_right->expr()); + BinaryNode* spec = &item->as(); + MOZ_ASSERT(spec->isKind(isImport ? PNK_IMPORT_SPEC : PNK_EXPORT_SPEC)); + MOZ_ASSERT(spec->left()->isKind(PNK_NAME)); + MOZ_ASSERT(!spec->left()->expr()); + MOZ_ASSERT(spec->right()->isKind(PNK_NAME)); + MOZ_ASSERT(!spec->right()->expr()); } #endif break; @@ -807,15 +825,17 @@ class NameResolver break; } - case PNK_DOT: - MOZ_ASSERT(cur->isArity(PN_BINARY)); - + case PNK_DOT: { // Super prop nodes do not have a meaningful LHS - if (cur->as().isSuper()) + PropertyAccess* prop = &cur->as(); + if (prop->isSuper()) { break; - if (!resolve(cur->pn_left, prefix)) + } + if (!resolve(&prop->expression(), prefix)) { return false; + } break; + } case PNK_LABEL: MOZ_ASSERT(cur->isArity(PN_NAME)); diff --git a/js/src/frontend/ParseNode.cpp b/js/src/frontend/ParseNode.cpp index 97ddbc482b..db0fff1284 100644 --- a/js/src/frontend/ParseNode.cpp +++ b/js/src/frontend/ParseNode.cpp @@ -276,9 +276,9 @@ PushNodeChildren(ParseNode* pn, NodeStack* stack) case PNK_FOR: case PNK_COMPREHENSIONFOR: case PNK_WITH: { - MOZ_ASSERT(pn->isArity(PN_BINARY)); - stack->push(pn->pn_left); - stack->push(pn->pn_right); + BinaryNode* bn = &pn->as(); + stack->push(bn->left()); + stack->push(bn->right()); return PushResult::Recyclable; } @@ -287,10 +287,10 @@ PushNodeChildren(ParseNode* pn, NodeStack* stack) // So both are binary nodes with a possibly-null pn_left. case PNK_CASE: case PNK_CLASSNAMES: { - MOZ_ASSERT(pn->isArity(PN_BINARY)); - if (pn->pn_left) - stack->push(pn->pn_left); - stack->push(pn->pn_right); + BinaryNode* bn = &pn->as(); + if (bn->left()) + stack->push(bn->left()); + stack->push(bn->right()); return PushResult::Recyclable; } @@ -298,9 +298,12 @@ PushNodeChildren(ParseNode* pn, NodeStack* stack) // '.generator' local, for a synthesized, prepended initial yield. case PNK_INITIALYIELD: { MOZ_ASSERT(pn->isArity(PN_UNARY)); - MOZ_ASSERT(pn->pn_kid->isKind(PNK_ASSIGN) && - pn->pn_kid->pn_left->isKind(PNK_NAME) && - pn->pn_kid->pn_right->isKind(PNK_GENERATOR)); +#ifdef DEBUG + MOZ_ASSERT(pn->pn_kid->isKind(PNK_ASSIGN)); + BinaryNode* bn = &pn->pn_kid->as(); + MOZ_ASSERT(bn->left()->isKind(PNK_NAME) && + bn->right()->isKind(PNK_GENERATOR)); +#endif stack->push(pn->pn_kid); return PushResult::Recyclable; } @@ -328,22 +331,22 @@ PushNodeChildren(ParseNode* pn, NodeStack* stack) // and a module string on the right. case PNK_IMPORT: case PNK_EXPORT_FROM: { - MOZ_ASSERT(pn->isArity(PN_BINARY)); - MOZ_ASSERT_IF(pn->isKind(PNK_IMPORT), pn->pn_left->isKind(PNK_IMPORT_SPEC_LIST)); - MOZ_ASSERT_IF(pn->isKind(PNK_EXPORT_FROM), pn->pn_left->isKind(PNK_EXPORT_SPEC_LIST)); - MOZ_ASSERT(pn->pn_left->isArity(PN_LIST)); - MOZ_ASSERT(pn->pn_right->isKind(PNK_STRING)); - stack->pushList(&pn->pn_left->as()); - stack->push(pn->pn_right); + BinaryNode* bn = &pn->as(); + MOZ_ASSERT_IF(pn->isKind(PNK_IMPORT), bn->left()->isKind(PNK_IMPORT_SPEC_LIST)); + MOZ_ASSERT_IF(pn->isKind(PNK_EXPORT_FROM), bn->left()->isKind(PNK_EXPORT_SPEC_LIST)); + MOZ_ASSERT(bn->left()->isArity(PN_LIST)); + MOZ_ASSERT(bn->right()->isKind(PNK_STRING)); + stack->pushList(&bn->left()->as()); + stack->push(bn->right()); return PushResult::Recyclable; } case PNK_EXPORT_DEFAULT: { - MOZ_ASSERT(pn->isArity(PN_BINARY)); - MOZ_ASSERT_IF(pn->pn_right, pn->pn_right->isKind(PNK_NAME)); - stack->push(pn->pn_left); - if (pn->pn_right) - stack->push(pn->pn_right); + BinaryNode* bn = &pn->as(); + MOZ_ASSERT_IF(bn->right(), bn->right()->isKind(PNK_NAME)); + stack->push(bn->left()); + if (bn->right()) + stack->push(bn->right()); return PushResult::Recyclable; } @@ -660,7 +663,7 @@ ParseNode::dump(int indent) ((UnaryNode*) this)->dump(indent); break; case PN_BINARY: - ((BinaryNode*) this)->dump(indent); + as().dump(indent); break; case PN_TERNARY: as().dump(indent); @@ -730,13 +733,13 @@ BinaryNode::dump(int indent) if (isKind(PNK_DOT)) { fprintf(stderr, "(."); - DumpParseTree(pn_right, indent + 2); + DumpParseTree(right(), indent + 2); fprintf(stderr, " "); if (as().isSuper()) fprintf(stderr, "super"); else - DumpParseTree(pn_left, indent + 2); + DumpParseTree(left(), indent + 2); fprintf(stderr, ")"); return; @@ -745,9 +748,9 @@ BinaryNode::dump(int indent) const char* name = parseNodeNames[getKind()]; fprintf(stderr, "(%s ", name); indent += strlen(name) + 2; - DumpParseTree(pn_left, indent); + DumpParseTree(left(), indent); IndentNewLine(indent); - DumpParseTree(pn_right, indent); + DumpParseTree(right(), indent); fprintf(stderr, ")"); } diff --git a/js/src/frontend/ParseNode.h b/js/src/frontend/ParseNode.h index ebc29ef851..0b8a914e21 100644 --- a/js/src/frontend/ParseNode.h +++ b/js/src/frontend/ParseNode.h @@ -249,8 +249,9 @@ IsTypeofKind(ParseNodeKind kind) * * PNK_LEXICALSCOPE which contains PNK_CLASSMETHODLIST as scopeBody, * if named class * PNK_CLASSNAMES (ClassNames) - * pn_left: Name node for outer binding. can be null - * pn_right: Name node for inner binding + * left: Name node for outer binding, or null if the class is an expression + * that doesn't create an outer binding + * right: Name node for inner binding * PNK_CLASSMETHODLIST (ListNode) * head: list of N PNK_CLASSMETHOD nodes * count: N >= 0 @@ -266,21 +267,29 @@ IsTypeofKind(ParseNodeKind kind) * kid1: cond * kid2: then = PNK_YIELD, PNK_ARRAYPUSH, (empty) PNK_STATEMENTLIST * kid3: else or null - * PNK_SWITCH binary pn_left: discriminant - * pn_right: PNK_LEXICALSCOPE node that contains the list - * of PNK_CASE nodes, with at most one default node. - * hasDefault: true if there's a default case - * PNK_CASE binary pn_left: case-expression if CaseClause, or - * null if DefaultClause - * pn_right: PNK_STATEMENTLIST node for this case's - * statements - * PNK_WHILE binary pn_left: cond, pn_right: body - * PNK_DOWHILE binary pn_left: body, pn_right: cond - * PNK_FOR binary pn_left: either PNK_FORIN (for-in statement), - * PNK_FOROF (for-of) or PNK_FORHEAD (for(;;)) - * pn_right: body - * PNK_COMPREHENSIONFOR pn_left: either PNK_FORIN or PNK_FOROF - * binary pn_right: body + * PNK_SWITCH (SwitchStatement) + * left: discriminant + * right: LexicalScope node that contains the list of Case nodes, with at + * most one default node. + * hasDefault: true if there's a default case + * PNK_CASE (CaseClause) + * left: case-expression if CaseClause, or null if DefaultClause + * right: StatementList node for this case's statements + * PNK_WHILE (BinaryNode) + * left: cond + * right: body + * PNK_DOWHILE (BinaryNode) + * left: body + * right: cond + * PNK_FOR (ForNode) + * left: one of + * * PNK_FORIN: for (x in y) ... + * * PNK_FOROF: for (x of x) ... + * * PNK_FORHEAD: for (;;) ... + * right: body + * PNK_COMPREHENSIONFOR (ForNode) + * left: either PNK_FORIN or PNK_FOROF + * right: body * PNK_FORIN (TernaryNode) * kid1: declaration or expression to left of 'in' * kid2: null @@ -307,7 +316,9 @@ IsTypeofKind(ParseNodeKind kind) * kid3: catch block statements * PNK_BREAK name pn_atom: label or null * PNK_CONTINUE name pn_atom: label or null - * PNK_WITH binary pn_left: head expr; pn_right: body; + * PNK_WITH (BinaryNode) + * left: head expr + * right: body * PNK_VAR, PNK_LET, PNK_CONST (ListNode) * head: list of N Name or Assign nodes * each name node has either @@ -319,9 +330,9 @@ IsTypeofKind(ParseNodeKind kind) * pn_atom: variable name * pn_lexdef: def node * each assignment node has - * pn_left: Name with pn_used true and + * left: Name with pn_used true and * pn_lexdef (NOT pn_expr) set - * pn_right: initializer + * right: initializer * count: N > 0 * PNK_RETURN unary pn_kid: return expr or null * PNK_SEMI unary pn_kid: expr or null statement @@ -329,18 +340,28 @@ IsTypeofKind(ParseNodeKind kind) * in original source, not introduced via * constant folding or other tree rewriting * PNK_LABEL name pn_atom: label, pn_expr: labeled statement - * PNK_IMPORT binary pn_left: PNK_IMPORT_SPEC_LIST import specifiers - * pn_right: PNK_STRING module specifier + * PNK_IMPORT (BinaryNode) + * left: PNK_IMPORT_SPEC_LIST import specifiers + * right: PNK_STRING module specifier * PNK_IMPORT_SPEC_LIST (ListNode) * head: list of N ImportSpec nodes * count: N >= 0 (N = 0 for `import {} from ...`) + * PNK_IMPORT_SPEC (BinaryNode) + * left: import name + * right: local binding name * PNK_EXPORT unary pn_kid: declaration expression - * PNK_EXPORT_FROM binary pn_left: PNK_EXPORT_SPEC_LIST export specifiers - * pn_right: PNK_STRING module specifier + * PNK_EXPORT_FROM (BinaryNode) + * left: PNK_EXPORT_SPEC_LIST export specifiers + * right: PNK_STRING module specifier * PNK_EXPORT_SPEC_LIST (ListNode) * head: list of N ExportSpec nodes * count: N >= 0 (N = 0 for `export {}`) - * PNK_EXPORT_DEFAULT unary pn_kid: export default declaration or expression + * PNK_EXPORT (BinaryNode) + * left: local binding name + * right: export name + * PNK_EXPORT_DEFAULT (BinaryNode) + * left: export default declaration or expression + * right: PNK_NAME node for assignment * * * All left-associated binary trees of the same type are optimized into lists @@ -348,19 +369,15 @@ IsTypeofKind(ParseNodeKind kind) * PNK_COMMA (ListNode) * head: list of N comma-separated exprs * count: N >= 2 - * PNK_ASSIGN binary pn_left: lvalue, pn_right: rvalue - * PNK_ADDASSIGN, binary pn_left: lvalue, pn_right: rvalue - * PNK_SUBASSIGN, pn_op: JSOP_ADD for +=, etc. - * PNK_BITORASSIGN, - * PNK_BITXORASSIGN, - * PNK_BITANDASSIGN, - * PNK_LSHASSIGN, - * PNK_RSHASSIGN, - * PNK_URSHASSIGN, - * PNK_MULASSIGN, - * PNK_DIVASSIGN, - * PNK_MODASSIGN, - * PNK_POWASSIGN + * PNK_ASSIGN (BinaryNode) + * left: target of assignment + * right: value to assign + * PNK_ADDASSIGN, PNK_SUBASSIGN, PNK_BITORASSIGN, PNK_BITXORASSIGN, + * PNK_BITANDASSIGN, PNK_LSHASSIGN, PNK_RSHASSIGN, PNK_URSHASSIGN, + * PNK_MULASSIGN, PNK_DIVASSIGN, PNK_MODASSIGN, PNK_POWASSIGN (AssignmentNode) + * left: target of assignment + * right: value to assign + * pn_op: JSOP_ADD for +=, etc * PNK_CONDITIONAL (ConditionalExpression) * (cond ? thenExpr : elseExpr) * kid1: cond @@ -392,8 +409,9 @@ IsTypeofKind(ParseNodeKind kind) * PNK_POSTINCREMENT, * PNK_PREDECREMENT, * PNK_POSTDECREMENT - * PNK_NEW binary pn_left: ctor expression on the left of the ( - * pn_right: Arguments + * 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 @@ -415,26 +433,16 @@ IsTypeofKind(ParseNodeKind kind) * contains are nullish. An optional chain can also * contain nodes such as PNK_DOT, PNK_ELEM, PNK_NAME, * PNK_CALL, etc. These are evaluated normally. - * PNK_OPTDOT binary pn_left: MEMBER expr to left of . - * short circuits back to PNK_OPTCHAIN if nullish. - * pn_right: PropertyName to right of . - * PNK_OPTELEM binary pn_left: MEMBER expr to left of [ - * short circuits back to PNK_OPTCHAIN if nullish. - * pn_right: expr between [ and ] - * PNK_OPTCALL list pn_head: list of call, arg1, arg2, ... argN - * pn_count: 1 + N (where N is number of args) - * call is a MEMBER expr naming a callable object, - * short circuits back to PNK_OPTCHAIN if nullish. - * PNK_PROPERTYNAME pn_atom: property being accessed - * name - * PNK_DOT binary pn_left: MEMBER expr to left of . - * pn_right: PropertyName to right of . - * PNK_ELEM binary pn_left: MEMBER expr to left of [ - * pn_right: expr between [ and ] - * PNK_CALL binary pn_left: callee expression on the left of the ( - * pn_right: Arguments - * PNK_ARGUMENTS list pn_head: list of arg1, arg2, ... argN - * pn_count: N (where N is number of args) + * PNK_PROPERTYNAME name pn_atom: property being accessed + * PNK_DOT, PNK_OPTDOT (PropertyAccess) short circuits back to PNK_OPTCHAIN if nullish. + * left: MEMBER expr to left of '.' + * right: PropertyName to right of '.' + * PNK_ELEM, PNK_OPTELEM (PropertyByValue) short circuits back to PNK_OPTCHAIN if nullish. + * left: MEMBER expr to left of '[' + * right: expr between '[' and ']' + * PNK_CALL, PNK_OPTCALL (BinaryNode) short circuits back to PNK_OPTCHAIN if nullish. + * left: callee expression on the left of the '(' + * right: Arguments * PNK_GENEXP binary Exactly like PNK_CALL, used for the implicit call * in the desugaring of a generator-expression. * PNK_ARGUMENTS (ListNode) @@ -452,11 +460,13 @@ IsTypeofKind(ParseNodeKind kind) * * Shorthand * * Spread * count: N >= 0 - * PNK_COLON binary key-value pair in object initializer or - * destructuring lhs - * pn_left: property id, pn_right: value - * PNK_SHORTHAND binary Same fields as PNK_COLON. This is used for object - * literal properties using shorthand ({x}). + * PNK_COLON (BinaryNode) + * key-value pair in object initializer or destructuring lhs + * left: property id + * right: value + * PNK_SHORTHAND (BinaryNode) + * Same fields as Colon. This is used for object literal properties using + * shorthand ({x}). * PNK_COMPUTED_NAME unary ES6 ComputedPropertyName. * pn_kid: the AssignmentExpression inside the square brackets * PNK_NAME, name pn_atom: name, string, or object atom @@ -470,8 +480,10 @@ IsTypeofKind(ParseNodeKind kind) * no ${}-delimited expression, it's parsed as a single TemplateString * PNK_TEMPLATE_STRING pn_atom: template string atom nullary pn_op: JSOP_NOP - * PNK_TAGGED_TEMPLATE pn_left: tag expression - * binary pn_right: Arguments, with the first being the call site object, then arg1, arg2, ... argN + * PNK_TAGGED_TEMPLATE (BinaryNode) + * left: tag expression + * right: Arguments, with the first being the call site object, then + * arg1, arg2, ... argN * PNK_CALLSITEOBJ (CallSiteNode) * head: an Array of raw TemplateString, then corresponding cooked * TemplateString nodes @@ -488,16 +500,18 @@ IsTypeofKind(ParseNodeKind kind) * PNK_THIS, unary pn_kid: '.this' Name if function `this`, else nullptr * PNK_SUPERBASE unary pn_kid: '.this' Name * - * PNK_SUPERCALL binary pn_left: SuperBase pn_right: Arguments - * - * PNK_SETTHIS binary pn_left: '.this' Name, pn_right: SuperCall - * + * PNK_SUPERCALL (BinaryNode) + * left: SuperBase + * right: Arguments + * PNK_SETTHIS (BinaryNode) + * left: '.this' Name + * right: SuperCall * 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_YIELD_STAR * PNK_ARRAYCOMP list pn_count: 1 * pn_head: list of 1 element, which is block * enclosing for loop(s) and optionally @@ -519,6 +533,16 @@ enum ParseNodeArity }; #define FOR_EACH_PARSENODE_SUBCLASS(macro) \ + macro(BinaryNode, BinaryNodeType, asBinary) \ + macro(AssignmentNode, AssignmentNodeType, asAssignment) \ + macro(CaseClause, CaseClauseType, asCaseClause) \ + macro(ClassMethod, ClassMethodType, asClassMethod) \ + macro(ClassNames, ClassNamesType, asClassNames) \ + macro(ForNode, ForNodeType, asFor) \ + macro(PropertyAccess, PropertyAccessType, asPropertyAccess) \ + macro(PropertyByValue, PropertyByValueType, asPropertyByValue) \ + macro(SwitchStatement, SwitchStatementType, asSwitchStatement) \ + \ macro(ListNode, ListNodeType, asList) \ macro(CallSiteNode, CallSiteNodeType, asCallSite) \ \ @@ -529,7 +553,6 @@ enum ParseNodeArity class LoopControlStatement; class BreakStatement; class ContinueStatement; -class PropertyAccess; #define DECLARE_CLASS(typeName, longTypeName, asMethodName) \ class typeName; @@ -594,11 +617,6 @@ class ParseNode bool isArity(ParseNodeArity a) const { return getArity() == a; } void setArity(ParseNodeArity a) { pn_arity = a; } - bool isAssignment() const { - ParseNodeKind kind = getKind(); - return PNK_ASSIGNMENT_START <= kind && kind <= PNK_ASSIGNMENT_LAST; - } - bool isBinaryOperation() const { ParseNodeKind kind = getKind(); return PNK_BINOP_FIRST <= kind && kind <= PNK_BINOP_LAST; @@ -636,6 +654,12 @@ class ParseNode ParseNode* kid3; /* else-part, default case, etc. */ } ternary; struct { /* two kids if binary */ + private: + friend class BinaryNode; + friend class ForNode; + friend class ClassMethod; + friend class PropertyAccessBase; + friend class SwitchStatement; ParseNode* left; ParseNode* right; union { @@ -675,10 +699,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_left pn_u.binary.left -#define pn_right pn_u.binary.right -#define pn_pval pn_u.binary.pval -#define pn_iflags pn_u.binary.iflags #define pn_kid pn_u.unary.kid #define pn_prologue pn_u.unary.prologue #define pn_atom pn_u.name.atom @@ -857,25 +877,97 @@ struct UnaryNode : public ParseNode #endif }; -struct BinaryNode : public ParseNode +class BinaryNode : public ParseNode { + public: BinaryNode(ParseNodeKind kind, JSOp op, const TokenPos& pos, ParseNode* left, ParseNode* right) : ParseNode(kind, op, PN_BINARY, pos) { - pn_left = left; - pn_right = right; + pn_u.binary.left = left; + pn_u.binary.right = right; } BinaryNode(ParseNodeKind kind, JSOp op, ParseNode* left, ParseNode* right) : ParseNode(kind, op, PN_BINARY, TokenPos::box(left->pn_pos, right->pn_pos)) { - pn_left = left; - pn_right = right; + pn_u.binary.left = left; + pn_u.binary.right = right; + } + + static bool test(const ParseNode& node) { + return node.isArity(PN_BINARY); } #ifdef DEBUG void dump(int indent); #endif + + ParseNode* left() const { + return pn_u.binary.left; + } + + ParseNode* right() const { + return pn_u.binary.right; + } + + // Methods used by FoldConstants.cpp. + // caller are responsible for keeping the list consistent. + ParseNode** unsafeLeftReference() { + return &pn_u.binary.left; + } + + ParseNode** unsafeRightReference() { + return &pn_u.binary.right; + } +}; + +class AssignmentNode : public BinaryNode +{ + public: + AssignmentNode(ParseNodeKind kind, JSOp op, ParseNode* left, ParseNode* right) + : BinaryNode(kind, op, TokenPos(left->pn_pos.begin, right->pn_pos.end), left, right) + {} + + static bool test(const ParseNode& node) { + ParseNodeKind kind = node.getKind(); + bool match = PNK_ASSIGNMENT_START <= kind && + kind <= PNK_ASSIGNMENT_LAST; + MOZ_ASSERT_IF(match, node.is()); + return match; + } +}; + +class ForNode : public BinaryNode +{ + public: + ForNode(const TokenPos& pos, ParseNode* forHead, ParseNode* body, unsigned iflags) + : BinaryNode(PNK_FOR, + forHead->isKind(PNK_FORIN) ? JSOP_ITER : JSOP_NOP, + pos, forHead, body) + { + MOZ_ASSERT(forHead->isKind(PNK_FORIN) || + forHead->isKind(PNK_FOROF) || + forHead->isKind(PNK_FORHEAD)); + pn_u.binary.iflags = iflags; + } + + static bool test(const ParseNode& node) { + bool match = node.isKind(PNK_FOR) || node.isKind(PNK_COMPREHENSIONFOR); + MOZ_ASSERT_IF(match, node.is()); + return match; + } + + TernaryNode* head() const { + return &left()->as(); + } + + ParseNode* body() const { + return right(); + } + + unsigned iflags() const { + return pn_u.binary.iflags; + } }; class TernaryNode : public ParseNode @@ -1353,13 +1445,21 @@ class CaseClause : public BinaryNode CaseClause(ParseNode* expr, ParseNode* stmts, uint32_t begin) : BinaryNode(PNK_CASE, JSOP_NOP, TokenPos(begin, stmts->pn_pos.end), expr, stmts) {} - ParseNode* caseExpression() const { return pn_left; } - bool isDefault() const { return !caseExpression(); } - ListNode* statementList() const { return &pn_right->as(); } + ParseNode* caseExpression() const { + return left(); + } + + bool isDefault() const { + return !caseExpression(); + } + + ListNode* statementList() const { + return &right()->as(); + } static bool test(const ParseNode& node) { bool match = node.isKind(PNK_CASE); - MOZ_ASSERT_IF(match, node.isArity(PN_BINARY)); + MOZ_ASSERT_IF(match, node.is()); MOZ_ASSERT_IF(match, node.isOp(JSOP_NOP)); return match; } @@ -1515,7 +1615,7 @@ class PropertyAccessBase : public BinaryNode public: /* * PropertyAccess nodes can have any expression/'super' as left-hand - * side, but the name must be a ParseNodeKind::PropertyName node. + * side, but the name must be a PNK_PROPERTYNAME node. */ PropertyAccessBase(ParseNodeKind kind, ParseNode* lhs, ParseNode* name, uint32_t begin, uint32_t end) : BinaryNode(kind, JSOP_NOP, TokenPos(begin, end), lhs, name) @@ -1527,21 +1627,37 @@ class PropertyAccessBase : public BinaryNode static bool test(const ParseNode& node) { bool match = node.isKind(PNK_DOT) || node.isKind(PNK_OPTDOT); - MOZ_ASSERT_IF(match, node.isArity(PN_BINARY)); - MOZ_ASSERT_IF(match, node.pn_right->isKind(PNK_PROPERTYNAME)); + MOZ_ASSERT_IF(match, node.is()); + MOZ_ASSERT_IF(match, node.as().right()->isKind(PNK_PROPERTYNAME)); return match; } ParseNode& expression() const { - return *pn_u.binary.left; + return *left(); + } + + ParseNode& key() const { + return *right(); + } + + // Method used by BytecodeEmitter::emitPropLHS for optimization. + // Those methods allow expression to temporarily be nullptr for + // optimization purpose. + ParseNode* maybeExpression() const { + return left(); + } + + void setExpression(ParseNode* pn) { + pn_u.binary.left = pn; } PropertyName& name() const { - return *pn_u.binary.right->pn_atom->asPropertyName(); + return *right()->pn_atom->asPropertyName(); } - JSAtom* nameAtom() const { - return pn_u.binary.right->pn_atom; + bool isSuper() const { + // PNK_SUPERBASE cannot result from any expression syntax. + return expression().isKind(PNK_SUPERBASE); } }; @@ -1557,15 +1673,10 @@ class PropertyAccess : public PropertyAccessBase static bool test(const ParseNode& node) { bool match = node.isKind(PNK_DOT); - MOZ_ASSERT_IF(match, node.isArity(PN_BINARY)); - MOZ_ASSERT_IF(match, node.pn_right->isKind(PNK_PROPERTYNAME)); + MOZ_ASSERT_IF(match, node.is()); + MOZ_ASSERT_IF(match, node.as().right()->isKind(PNK_PROPERTYNAME)); return match; } - - bool isSuper() const { - // PNK_SUPERBASE cannot result from any expression syntax. - return expression().isKind(PNK_SUPERBASE); - } }; class OptionalPropertyAccess : public PropertyAccessBase @@ -1580,35 +1691,36 @@ class OptionalPropertyAccess : public PropertyAccessBase static bool test(const ParseNode& node) { bool match = node.isKind(PNK_OPTDOT); - MOZ_ASSERT_IF(match, node.isArity(PN_BINARY)); - MOZ_ASSERT_IF(match, node.pn_right->isKind(PNK_PROPERTYNAME)); + MOZ_ASSERT_IF(match, node.is()); + MOZ_ASSERT_IF(match, node.as().right()->isKind(PNK_PROPERTYNAME)); return match; } }; -class PropertyByValueBase : public ParseNode +class PropertyByValueBase : public BinaryNode { public: PropertyByValueBase(ParseNodeKind kind, ParseNode* lhs, ParseNode* propExpr, uint32_t begin, uint32_t end) - : ParseNode(kind, JSOP_NOP, PN_BINARY, TokenPos(begin, end)) - { - pn_u.binary.left = lhs; - pn_u.binary.right = propExpr; - } + : BinaryNode(kind, JSOP_NOP, TokenPos(begin, end), lhs, propExpr) + {} ParseNode& expression() const { - return *pn_u.binary.left; + return *left(); } ParseNode& key() const { - return *pn_u.binary.right; + return *right(); + } + + bool isSuper() const { + return left()->isKind(PNK_SUPERBASE); } static bool test(const ParseNode& node) { bool match = node.isKind(PNK_ELEM) || node.isKind(PNK_OPTELEM); - MOZ_ASSERT_IF(match, node.isArity(PN_BINARY)); + MOZ_ASSERT_IF(match, node.is()); return match; } }; @@ -1624,10 +1736,6 @@ class PropertyByValue : public PropertyByValueBase { MOZ_ASSERT_IF(match, node.isArity(PN_BINARY)); return match; } - - bool isSuper() const { - return pn_left->isKind(PNK_SUPERBASE); - } }; class OptionalPropertyByValue : public PropertyByValueBase { @@ -1667,7 +1775,9 @@ class CallSiteNode : public ListNode } }; -struct ClassMethod : public BinaryNode { +class ClassMethod : public BinaryNode +{ + public: /* * Method definitions often keep a name and function body that overlap, * so explicitly define the beginning and end here. @@ -1680,22 +1790,24 @@ struct ClassMethod : public BinaryNode { static bool test(const ParseNode& node) { bool match = node.isKind(PNK_CLASSMETHOD); - MOZ_ASSERT_IF(match, node.isArity(PN_BINARY)); + MOZ_ASSERT_IF(match, node.is()); return match; } ParseNode& name() const { - return *pn_u.binary.left; + return *left(); } ParseNode& method() const { - return *pn_u.binary.right; + return *right(); } bool isStatic() const { return pn_u.binary.isStatic; } }; -struct SwitchStatement : public BinaryNode { +class SwitchStatement : public BinaryNode +{ + public: SwitchStatement(uint32_t begin, ParseNode* discriminant, ParseNode* lexicalForCaseList, bool hasDefault) : BinaryNode(PNK_SWITCH, JSOP_NOP, @@ -1722,22 +1834,24 @@ struct SwitchStatement : public BinaryNode { static bool test(const ParseNode& node) { bool match = node.isKind(PNK_SWITCH); - MOZ_ASSERT_IF(match, node.isArity(PN_BINARY)); + MOZ_ASSERT_IF(match, node.is()); return match; } ParseNode& discriminant() const { - return *pn_u.binary.left; + return *left(); } - ParseNode& lexicalForCaseList() const { - return *pn_u.binary.right; + ParseNode& lexicalForCaseList() const {; + return *right(); } bool hasDefault() const { return pn_u.binary.hasDefault; } }; -struct ClassNames : public BinaryNode { +class ClassNames : public BinaryNode +{ + public: ClassNames(ParseNode* outerBinding, ParseNode* innerBinding, const TokenPos& pos) : BinaryNode(PNK_CLASSNAMES, JSOP_NOP, pos, outerBinding, innerBinding) { @@ -1748,7 +1862,7 @@ struct ClassNames : public BinaryNode { static bool test(const ParseNode& node) { bool match = node.isKind(PNK_CLASSNAMES); - MOZ_ASSERT_IF(match, node.isArity(PN_BINARY)); + MOZ_ASSERT_IF(match, node.is()); return match; } @@ -1761,10 +1875,10 @@ struct ClassNames : public BinaryNode { * the outer binding has been overwritten. */ ParseNode* outerBinding() const { - return pn_u.binary.left; + return left(); } ParseNode* innerBinding() const { - return pn_u.binary.right; + return right(); } }; diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index 4a6a629d28..d3849d10d6 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -4307,7 +4307,7 @@ Parser::PossibleError::transferErrorsTo(PossibleError* other) } template -typename ParseHandler::Node +typename ParseHandler::BinaryNodeType Parser::bindingInitializer(Node lhs, DeclarationKind kind, YieldHandling yieldHandling) { @@ -4322,12 +4322,17 @@ Parser::bindingInitializer(Node lhs, DeclarationKind kind, handler.checkAndSetIsDirectRHSAnonFunction(rhs); - Node assign = handler.newAssignment(PNK_ASSIGN, lhs, rhs, JSOP_NOP); + BinaryNodeType assign = handler.newAssignment(PNK_ASSIGN, lhs, rhs, JSOP_NOP); if (!assign) return null(); - if (foldConstants && !FoldConstants(context, &assign, this)) - return null(); + if (foldConstants) { + Node node = assign; + if (!FoldConstants(context, &node, this)) { + return null(); + } + assign = handler.asBinary(node); + } return assign; } @@ -4454,7 +4459,7 @@ Parser::objectBindingPattern(DeclarationKind kind, YieldHandling y tokenStream.consumeKnownToken(TOK_ASSIGN); - Node bindingExpr = bindingInitializer(binding, kind, yieldHandling); + BinaryNodeType bindingExpr = bindingInitializer(binding, kind, yieldHandling); if (!bindingExpr) return null(); @@ -5030,7 +5035,7 @@ Parser::namedImportsOrNamespaceImport(TokenKind tt, ListNodeTy if (!importNameNode) return false; - Node importSpec = handler.newBinary(PNK_IMPORT_SPEC, importNameNode, bindingName); + BinaryNodeType importSpec = handler.newBinary(PNK_IMPORT_SPEC, importNameNode, bindingName); if (!importSpec) return false; @@ -5076,7 +5081,7 @@ Parser::namedImportsOrNamespaceImport(TokenKind tt, ListNodeTy // environment. pc->varScope().lookupDeclaredName(bindingName)->value()->setClosedOver(); - Node importSpec = handler.newBinary(PNK_IMPORT_SPEC, importName, bindingNameNode); + BinaryNodeType importSpec = handler.newBinary(PNK_IMPORT_SPEC, importName, bindingNameNode); if (!importSpec) return false; @@ -5087,7 +5092,7 @@ Parser::namedImportsOrNamespaceImport(TokenKind tt, ListNodeTy } template<> -ParseNode* +BinaryNode* Parser::importDeclaration() { MOZ_ASSERT(tokenStream.currentToken().type == TOK_IMPORT); @@ -5134,7 +5139,7 @@ Parser::importDeclaration() if (!noteDeclaredName(bindingAtom, DeclarationKind::Import, pos())) return null(); - Node importSpec = handler.newBinary(PNK_IMPORT_SPEC, importName, bindingName); + BinaryNodeType importSpec = handler.newBinary(PNK_IMPORT_SPEC, importName, bindingName); if (!importSpec) return null(); @@ -5173,7 +5178,7 @@ Parser::importDeclaration() if (!matchOrInsertSemicolonAfterNonExpression()) return null(); - ParseNode* node = + BinaryNode* node = handler.newImportDeclaration(importSpecSet, moduleSpec, TokenPos(begin, pos().end)); if (!node || !pc->sc()->asModuleContext()->builder.processImport(node)) return null(); @@ -5182,7 +5187,7 @@ Parser::importDeclaration() } template<> -SyntaxParseHandler::Node +SyntaxParseHandler::BinaryNodeType Parser::importDeclaration() { JS_ALWAYS_FALSE(abortIfSyntaxParser()); @@ -5226,7 +5231,7 @@ Parser::checkExportedNamesForArrayBinding(ListNode* array) if (node->isKind(PNK_SPREAD)) binding = node->pn_kid; else if (node->isKind(PNK_ASSIGN)) - binding = node->pn_left; + binding = node->as().left(); else binding = node; @@ -5264,10 +5269,10 @@ Parser::checkExportedNamesForObjectBinding(ListNode* obj) if (node->isKind(PNK_MUTATEPROTO)) target = node->pn_kid; else - target = node->pn_right; + target = node->as().right(); if (target->isKind(PNK_ASSIGN)) - target = target->pn_left; + target = target->as().left(); } if (!checkExportedNamesForDeclaration(target)) @@ -5318,7 +5323,7 @@ Parser::checkExportedNamesForDeclarationList(ListNode* node) { for (ParseNode* binding : node->contents()) { if (binding->isKind(PNK_ASSIGN)) - binding = binding->pn_left; + binding = binding->as().left(); else MOZ_ASSERT(binding->isKind(PNK_NAME)); @@ -5400,21 +5405,21 @@ Parser::processExport(Node node) template<> bool -Parser::processExportFrom(ParseNode* node) +Parser::processExportFrom(BinaryNodeType node) { return pc->sc()->asModuleContext()->builder.processExportFrom(node); } template<> bool -Parser::processExportFrom(Node node) +Parser::processExportFrom(BinaryNodeType node) { MOZ_ALWAYS_FALSE(abortIfSyntaxParser()); return false; } template -typename ParseHandler::Node +typename ParseHandler::BinaryNodeType Parser::exportFrom(uint32_t begin, Node specList) { if (!abortIfSyntaxParser()) @@ -5434,7 +5439,7 @@ Parser::exportFrom(uint32_t begin, Node specList) if (!matchOrInsertSemicolonAfterNonExpression()) return null(); - Node node = handler.newExportFromDeclaration(begin, specList, moduleSpec); + BinaryNodeType node = handler.newExportFromDeclaration(begin, specList, moduleSpec); if (!node) return null(); @@ -5445,7 +5450,7 @@ Parser::exportFrom(uint32_t begin, Node specList) } template -typename ParseHandler::Node +typename ParseHandler::BinaryNodeType Parser::exportBatch(uint32_t begin) { if (!abortIfSyntaxParser()) @@ -5476,7 +5481,7 @@ Parser::checkLocalExportNames(ListNode* node) { // ES 2017 draft 15.2.3.1. for (ParseNode* next : node->contents()) { - ParseNode* name = next->pn_left; + ParseNode* name = next->as().left(); MOZ_ASSERT(name->isKind(PNK_NAME)); RootedPropertyName ident(context, name->pn_atom->asPropertyName()); @@ -5540,7 +5545,7 @@ Parser::exportClause(uint32_t begin) if (!checkExportedNameForClause(exportName)) return null(); - Node exportSpec = handler.newBinary(PNK_EXPORT_SPEC, bindingName, exportName); + BinaryNodeType exportSpec = handler.newBinary(PNK_EXPORT_SPEC, bindingName, exportName); if (!exportSpec) return null(); @@ -5702,7 +5707,7 @@ Parser::exportLexicalDeclaration(uint32_t begin, DeclarationKind k } template -typename ParseHandler::Node +typename ParseHandler::BinaryNodeType Parser::exportDefaultFunctionDeclaration(uint32_t begin, FunctionAsyncKind asyncKind /* = SyncFunction */) @@ -5716,7 +5721,7 @@ Parser::exportDefaultFunctionDeclaration(uint32_t begin, if (!kid) return null(); - Node node = handler.newExportDefaultDeclaration(kid, null(), TokenPos(begin, pos().end)); + BinaryNodeType node = handler.newExportDefaultDeclaration(kid, null(), TokenPos(begin, pos().end)); if (!node) return null(); @@ -5727,7 +5732,7 @@ Parser::exportDefaultFunctionDeclaration(uint32_t begin, } template -typename ParseHandler::Node +typename ParseHandler::BinaryNodeType Parser::exportDefaultClassDeclaration(uint32_t begin) { if (!abortIfSyntaxParser()) @@ -5739,7 +5744,7 @@ Parser::exportDefaultClassDeclaration(uint32_t begin) if (!kid) return null(); - Node node = handler.newExportDefaultDeclaration(kid, null(), TokenPos(begin, pos().end)); + BinaryNodeType node = handler.newExportDefaultDeclaration(kid, null(), TokenPos(begin, pos().end)); if (!node) return null(); @@ -5750,7 +5755,7 @@ Parser::exportDefaultClassDeclaration(uint32_t begin) } template -typename ParseHandler::Node +typename ParseHandler::BinaryNodeType Parser::exportDefaultAssignExpr(uint32_t begin) { if (!abortIfSyntaxParser()) @@ -5769,7 +5774,7 @@ Parser::exportDefaultAssignExpr(uint32_t begin) if (!matchOrInsertSemicolonAfterExpression()) return null(); - Node node = handler.newExportDefaultDeclaration(kid, nameNode, TokenPos(begin, pos().end)); + BinaryNodeType node = handler.newExportDefaultDeclaration(kid, nameNode, TokenPos(begin, pos().end)); if (!node) return null(); @@ -5780,7 +5785,7 @@ Parser::exportDefaultAssignExpr(uint32_t begin) } template -typename ParseHandler::Node +typename ParseHandler::BinaryNodeType Parser::exportDefault(uint32_t begin) { if (!abortIfSyntaxParser()) @@ -6027,7 +6032,7 @@ Parser::ifStatement(YieldHandling yieldHandling) } template -typename ParseHandler::Node +typename ParseHandler::BinaryNodeType Parser::doWhileStatement(YieldHandling yieldHandling) { uint32_t begin = pos().begin; @@ -6053,7 +6058,7 @@ Parser::doWhileStatement(YieldHandling yieldHandling) } template -typename ParseHandler::Node +typename ParseHandler::BinaryNodeType Parser::whileStatement(YieldHandling yieldHandling) { uint32_t begin = pos().begin; @@ -6414,7 +6419,7 @@ Parser::forStatement(YieldHandling yieldHandling) if (!body) return null(); - Node forLoop = handler.newForStatement(begin, forHead, body, iflags); + BinaryNodeType forLoop = handler.newForStatement(begin, forHead, body, iflags); if (!forLoop) return null(); @@ -6425,7 +6430,7 @@ Parser::forStatement(YieldHandling yieldHandling) } template -typename ParseHandler::Node +typename ParseHandler::SwitchStatementType Parser::switchStatement(YieldHandling yieldHandling) { MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_SWITCH)); @@ -6516,10 +6521,10 @@ Parser::switchStatement(YieldHandling yieldHandling) handler.addStatementToList(body, stmt); } - Node casepn = handler.newCaseOrDefault(caseBegin, caseExpr, body); - if (!casepn) + CaseClauseType caseClause = handler.newCaseOrDefault(caseBegin, caseExpr, body); + if (!caseClause) return null(); - handler.addCaseStatementToList(caseList, casepn); + handler.addCaseStatementToList(caseList, caseClause); } Node lexicalForCaseList = finishLexicalScope(scope, caseList); @@ -6818,7 +6823,7 @@ Parser::yieldExpression(InHandling inHandling) } template -typename ParseHandler::Node +typename ParseHandler::BinaryNodeType Parser::withStatement(YieldHandling yieldHandling) { MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_WITH)); @@ -9181,8 +9186,8 @@ Parser::memberExpr(YieldHandling yieldHandling, TripledotHandling if (tt == TOK_NEW) { uint32_t newBegin = pos().begin; // Make sure this wasn't a |new.target| in disguise. - Node newTarget; - if (!tryNewTarget(newTarget)) + BinaryNodeType newTarget; + if (!tryNewTarget(&newTarget)) return null(); if (newTarget) { lhs = newTarget; @@ -10246,7 +10251,7 @@ Parser::objectLiteral(YieldHandling yieldHandling, PossibleError* handler.checkAndSetIsDirectRHSAnonFunction(rhs); - Node propExpr = handler.newAssignment(PNK_ASSIGN, lhs, rhs, JSOP_NOP); + BinaryNodeType propExpr = handler.newAssignment(PNK_ASSIGN, lhs, rhs, JSOP_NOP); if (!propExpr) return null(); @@ -10362,11 +10367,11 @@ Parser::methodDefinition(uint32_t toStringStart, PropertyType prop template bool -Parser::tryNewTarget(Node &newTarget) +Parser::tryNewTarget(BinaryNodeType* newTarget) { MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_NEW)); - newTarget = null(); + *newTarget = null(); Node newHolder = handler.newPosHolder(pos()); if (!newHolder) @@ -10400,8 +10405,8 @@ Parser::tryNewTarget(Node &newTarget) if (!targetHolder) return false; - newTarget = handler.newNewTarget(newHolder, targetHolder); - return !!newTarget; + *newTarget = handler.newNewTarget(newHolder, targetHolder); + return !!*newTarget; } template diff --git a/js/src/frontend/Parser.h b/js/src/frontend/Parser.h index 89b89674a4..b4a4540f5a 100644 --- a/js/src/frontend/Parser.h +++ b/js/src/frontend/Parser.h @@ -1198,8 +1198,8 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE) Node blockStatement(YieldHandling yieldHandling, unsigned errorNumber = JSMSG_CURLY_IN_COMPOUND); - Node doWhileStatement(YieldHandling yieldHandling); - Node whileStatement(YieldHandling yieldHandling); + BinaryNodeType doWhileStatement(YieldHandling yieldHandling); + BinaryNodeType whileStatement(YieldHandling yieldHandling); Node forStatement(YieldHandling yieldHandling); bool forHeadStart(YieldHandling yieldHandling, @@ -1210,11 +1210,11 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE) Node* forInOrOfExpression); Node expressionAfterForInOrOf(ParseNodeKind forHeadKind, YieldHandling yieldHandling); - Node switchStatement(YieldHandling yieldHandling); + SwitchStatementType switchStatement(YieldHandling yieldHandling); Node continueStatement(YieldHandling yieldHandling); Node breakStatement(YieldHandling yieldHandling); Node returnStatement(YieldHandling yieldHandling); - Node withStatement(YieldHandling yieldHandling); + BinaryNodeType withStatement(YieldHandling yieldHandling); Node throwStatement(YieldHandling yieldHandling); TernaryNodeType tryStatement(YieldHandling yieldHandling); Node catchBlockStatement(YieldHandling yieldHandling, ParseContext::Scope& catchParamScope); @@ -1235,24 +1235,24 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE) ListNodeType lexicalDeclaration(YieldHandling yieldHandling, DeclarationKind kind); - Node importDeclaration(); + inline BinaryNodeType importDeclaration(); bool processExport(Node node); - bool processExportFrom(Node node); + bool processExportFrom(BinaryNodeType node); - Node exportFrom(uint32_t begin, Node specList); - Node exportBatch(uint32_t begin); + BinaryNodeType exportFrom(uint32_t begin, Node specList); + 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); - Node exportDefaultFunctionDeclaration(uint32_t begin, - FunctionAsyncKind asyncKind = SyncFunction); - Node exportDefaultClassDeclaration(uint32_t begin); - Node exportDefaultAssignExpr(uint32_t begin); - Node exportDefault(uint32_t begin); + BinaryNodeType exportDefaultFunctionDeclaration(uint32_t begin, + FunctionAsyncKind asyncKind = SyncFunction); + BinaryNodeType exportDefaultClassDeclaration(uint32_t begin); + BinaryNodeType exportDefaultAssignExpr(uint32_t begin); + BinaryNodeType exportDefault(uint32_t begin); Node exportDeclaration(); Node expressionStatement(YieldHandling yieldHandling, @@ -1343,7 +1343,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE) Node exprInParens(InHandling inHandling, YieldHandling yieldHandling, TripledotHandling tripledotHandling, PossibleError* possibleError = nullptr); - bool tryNewTarget(Node& newTarget); + bool tryNewTarget(BinaryNodeType* newTarget); bool checkAndMarkSuperScope(); Node methodDefinition(uint32_t toStringStart, PropertyType propType, HandleAtom funName); @@ -1526,7 +1526,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE) ListNodeType objectLiteral(YieldHandling yieldHandling, PossibleError* possibleError); - Node bindingInitializer(Node lhs, DeclarationKind kind, YieldHandling yieldHandling); + BinaryNodeType bindingInitializer(Node lhs, DeclarationKind kind, YieldHandling yieldHandling); Node bindingIdentifier(DeclarationKind kind, YieldHandling yieldHandling); Node bindingIdentifierOrPattern(DeclarationKind kind, YieldHandling yieldHandling, TokenKind tt); diff --git a/js/src/frontend/SyntaxParseHandler.h b/js/src/frontend/SyntaxParseHandler.h index d37dd4e20b..9ca68cac5e 100644 --- a/js/src/frontend/SyntaxParseHandler.h +++ b/js/src/frontend/SyntaxParseHandler.h @@ -304,19 +304,19 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) MOZ_MUST_USE bool addSpreadElement(ListNodeType literal, uint32_t begin, Node inner) { return true; } void addArrayElement(ListNodeType literal, Node element) { } - Node newCall(Node callee, Node args) { return NodeFunctionCall; } - Node newOptionalCall(Node callee, Node args) { return NodeOptionalFunctionCall; } + BinaryNodeType newCall(Node callee, Node args) { return NodeFunctionCall; } + BinaryNodeType newOptionalCall(Node callee, Node args) { return NodeOptionalFunctionCall; } ListNodeType newArguments(const TokenPos& pos) { return NodeGeneric; } - Node newSuperCall(Node callee, Node args) { return NodeGeneric; } - Node newTaggedTemplate(Node callee, Node args) { return NodeGeneric; } + BinaryNodeType newSuperCall(Node callee, Node args) { return NodeGeneric; } + BinaryNodeType newTaggedTemplate(Node callee, Node args) { return NodeGeneric; } Node newGenExp(Node callee, Node args) { return NodeGeneric; } ListNodeType newObjectLiteral(uint32_t begin) { return NodeUnparenthesizedObject; } ListNodeType newClassMethodList(uint32_t begin) { return NodeGeneric; } - Node newClassNames(Node outer, Node inner, const TokenPos& pos) { return NodeGeneric; } + ClassNamesType newClassNames(Node outer, Node inner, const TokenPos& pos) { return NodeGeneric; } ClassNodeType newClass(Node name, Node heritage, Node methodBlock, const TokenPos& pos) { return NodeGeneric; } - Node newNewTarget(Node newHolder, Node targetHolder) { return NodeGeneric; } + BinaryNodeType newNewTarget(Node newHolder, Node targetHolder) { return NodeGeneric; } Node newPosHolder(const TokenPos& pos) { return NodeGeneric; } Node newSuperBase(Node thisName, const TokenPos& pos) { return NodeSuperBase; } @@ -335,21 +335,21 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) ListNodeType newStatementList(const TokenPos& pos) { return NodeGeneric; } void addStatementToList(ListNodeType list, Node stmt) {} - void addCaseStatementToList(ListNodeType list, Node caseClause) {} + void addCaseStatementToList(ListNodeType list, CaseClauseType caseClause) {} 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) { return NodeGeneric; } - Node newExportFromDeclaration(uint32_t begin, Node exportSpecSet, Node moduleSpec) { + BinaryNodeType newExportFromDeclaration(uint32_t begin, Node exportSpecSet, Node moduleSpec) { return NodeGeneric; } - Node newExportDefaultDeclaration(Node kid, Node maybeBinding, const TokenPos& pos) { + BinaryNodeType newExportDefaultDeclaration(Node kid, Node maybeBinding, const TokenPos& pos) { return NodeGeneric; } - Node newSetThis(Node thisName, Node value) { return value; } + BinaryNodeType newSetThis(Node thisName, Node value) { return value; } Node newExprStatement(Node expr, uint32_t end) { return expr == NodeUnparenthesizedString ? NodeStringExprStatement : NodeGeneric; @@ -358,17 +358,17 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) TernaryNodeType newIfStatement(uint32_t begin, Node cond, Node thenBranch, Node elseBranch) { return NodeGeneric; } - Node newDoWhileStatement(Node body, Node cond, const TokenPos& pos) { return NodeGeneric; } - Node newWhileStatement(uint32_t begin, Node cond, Node body) { return NodeGeneric; } - Node newSwitchStatement(uint32_t begin, Node discriminant, Node lexicalForCaseList, bool hasDefault) + BinaryNodeType newDoWhileStatement(Node body, Node cond, const TokenPos& pos) { return NodeGeneric; } + BinaryNodeType newWhileStatement(uint32_t begin, Node cond, Node body) { return NodeGeneric; } + SwitchStatementType newSwitchStatement(uint32_t begin, Node discriminant, Node lexicalForCaseList, bool hasDefault) { return NodeGeneric; } - Node newCaseOrDefault(uint32_t begin, Node expr, Node body) { return NodeGeneric; } + 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; } - Node newWithStatement(uint32_t begin, Node expr, Node body) { return NodeGeneric; } + BinaryNodeType newWithStatement(uint32_t begin, Node expr, Node body) { return NodeGeneric; } Node newLabeledStatement(PropertyName* label, Node stmt, uint32_t begin) { return NodeGeneric; @@ -385,7 +385,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) return NodeGeneric; } - Node newPropertyAccess(Node expr, Node key) { + PropertyAccessType newPropertyAccess(Node expr, Node key) { return NodeDottedProperty; } @@ -393,7 +393,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) return NodeOptionalDottedProperty; } - Node newPropertyByValue(Node pn, Node kid, uint32_t end) { return NodeElement; } + PropertyByValueType newPropertyByValue(Node lhs, Node index, uint32_t end) { return NodeElement; } Node newOptionalPropertyByValue(Node pn, Node kid, uint32_t end) { return NodeOptionalElement; } @@ -414,7 +414,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) void setFunctionBox(Node pn, FunctionBox* funbox) {} void addFunctionFormalParameter(Node pn, Node argpn) {} - Node newForStatement(uint32_t begin, TernaryNodeType forHead, Node body, unsigned iflags) { + ForNodeType newForStatement(uint32_t begin, TernaryNodeType forHead, Node body, unsigned iflags) { return NodeGeneric; } @@ -518,11 +518,11 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS) } - Node newNewExpression(uint32_t begin, Node ctor, Node args) { + BinaryNodeType newNewExpression(uint32_t begin, Node ctor, Node args) { return NodeGeneric; } - Node newAssignment(ParseNodeKind kind, Node lhs, Node rhs, JSOp op) { + AssignmentNodeType newAssignment(ParseNodeKind kind, Node lhs, Node rhs, JSOp op) { if (kind == PNK_ASSIGN) return NodeUnparenthesizedAssignment; return newBinary(kind, lhs, rhs, op); diff --git a/js/src/wasm/AsmJS.cpp b/js/src/wasm/AsmJS.cpp index b941c80515..5c851dae3e 100644 --- a/js/src/wasm/AsmJS.cpp +++ b/js/src/wasm/AsmJS.cpp @@ -408,15 +408,13 @@ UnaryKid(ParseNode* pn) static inline ParseNode* BinaryRight(ParseNode* pn) { - MOZ_ASSERT(pn->isArity(PN_BINARY)); - return pn->pn_right; + return pn->as().right(); } static inline ParseNode* BinaryLeft(ParseNode* pn) { - MOZ_ASSERT(pn->isArity(PN_BINARY)); - return pn->pn_left; + return pn->as().left(); } static inline ParseNode* @@ -634,31 +632,25 @@ NumberNodeHasFrac(ParseNode* pn) static ParseNode* DotBase(ParseNode* pn) { - MOZ_ASSERT(pn->isKind(PNK_DOT)); - MOZ_ASSERT(pn->isArity(PN_BINARY)); - return pn->pn_left; + return &pn->as().expression(); } static PropertyName* DotMember(ParseNode* pn) { - MOZ_ASSERT(pn->isKind(PNK_DOT)); - MOZ_ASSERT(pn->isArity(PN_BINARY)); - return pn->pn_right->pn_atom->asPropertyName(); + return &pn->as().name(); } static ParseNode* ElemBase(ParseNode* pn) { - MOZ_ASSERT(pn->isKind(PNK_ELEM)); - return BinaryLeft(pn); + return &pn->as().expression(); } static ParseNode* ElemIndex(ParseNode* pn) { - MOZ_ASSERT(pn->isKind(PNK_ELEM)); - return BinaryRight(pn); + return &pn->as().key(); } static inline JSFunction*