Bug 1493870 - Remove ParseNode::name. r=jorendorff
authorTooru Fujisawa <arai_a@mac.com>
Tue, 16 Oct 2018 15:01:15 +0900
changeset 497173 847c7c6af1db86f0edcae2986a9a9582160f4f4b
parent 497172 4700f0a79ebd4ec48932225cc7c124c999656938
child 497174 0ece655d6f5b5ff673e1d12b7b8979b5ff0089da
push id9996
push userarchaeopteryx@coole-files.de
push dateThu, 18 Oct 2018 18:37:15 +0000
treeherdermozilla-beta@8efe26839243 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjorendorff
bugs1493870
milestone64.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1493870 - Remove ParseNode::name. r=jorendorff
js/src/builtin/ReflectParse.cpp
js/src/frontend/BinSource-auto.cpp
js/src/frontend/BinSource.cpp
js/src/frontend/BinSource.yaml
js/src/frontend/BytecodeEmitter.cpp
js/src/frontend/BytecodeEmitter.h
js/src/frontend/ParseNode-inl.h
js/src/frontend/ParseNode.cpp
js/src/frontend/ParseNode.h
js/src/frontend/Parser.cpp
js/src/wasm/AsmJS.cpp
--- a/js/src/builtin/ReflectParse.cpp
+++ b/js/src/builtin/ReflectParse.cpp
@@ -11,25 +11,25 @@
 #include "mozilla/Move.h"
 
 #include <stdlib.h>
 
 #include "jspubtd.h"
 
 #include "builtin/Array.h"
 #include "builtin/Reflect.h"
+#include "frontend/ParseNode.h"
 #include "frontend/Parser.h"
 #include "frontend/TokenStream.h"
 #include "js/CharacterEncoding.h"
 #include "js/StableStringChars.h"
 #include "vm/JSAtom.h"
 #include "vm/JSObject.h"
 #include "vm/RegExpObject.h"
 
-#include "frontend/ParseNode-inl.h"
 #include "vm/JSObject-inl.h"
 
 using namespace js;
 using namespace js::frontend;
 
 using JS::AutoStableStringChars;
 using JS::AutoValueArray;
 using JS::CompileOptions;
--- a/js/src/frontend/BinSource-auto.cpp
+++ b/js/src/frontend/BinSource-auto.cpp
@@ -15,23 +15,23 @@
 #include "mozilla/Move.h"
 #include "mozilla/PodOperations.h"
 #include "mozilla/Vector.h"
 
 #include "frontend/BinSource-macros.h"
 #include "frontend/BinSource.h"
 #include "frontend/BinTokenReaderTester.h"
 #include "frontend/FullParseHandler.h"
+#include "frontend/ParseNode.h"
 #include "frontend/Parser.h"
 #include "frontend/SharedContext.h"
 
 #include "vm/RegExpObject.h"
 
 #include "frontend/ParseContext-inl.h"
-#include "frontend/ParseNode-inl.h"
 
 namespace js {
 namespace frontend {
 
 // Compare a bunch of `uint8_t` values (as returned by the tokenizer_) with
 // a string literal (and ONLY a string literal).
 template<typename Tok, size_t N>
 bool operator==(const typename Tok::Chars& left, const char (&right)[N]) {
@@ -2838,18 +2838,19 @@ BinASTParser<Tok>::parseInterfaceCallExp
                 parseContext_->functionBox()->usesApply = true;
         } else if (prop == cx_->names().call) {
             op = JSOP_FUNCALL;
         }
     }
 
     // Check for direct calls to `eval`.
     if (factory_.isEvalName(callee, cx_)) {
-        if (!parseContext_->varScope().lookupDeclaredNameForAdd(callee->name())
-         && !parseContext_->innermostScope()->lookupDeclaredNameForAdd(callee->name())) {
+        if (!parseContext_->varScope().lookupDeclaredNameForAdd(cx_->names().eval)
+         && !parseContext_->innermostScope()->lookupDeclaredNameForAdd(cx_->names().eval))
+        {
             // This is a direct call to `eval`.
             if (!parseContext_->sc()->hasDirectEval()) {
                 return raiseMissingDirectEvalInAssertedScope();
             }
 
             op = parseContext_->sc()->strict() ? JSOP_STRICTEVAL : JSOP_EVAL;
         }
     }
@@ -4540,17 +4541,17 @@ BinASTParser<Tok>::parseInterfaceShortha
     const BinField expected_fields[1] = { BinField::Name };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
 
     BINJS_MOZ_TRY_DECL(name, parseIdentifierExpression());
 
     MOZ_ASSERT(name->isKind(ParseNodeKind::Name));
     MOZ_ASSERT(!factory_.isUsableAsObjectPropertyName(name));
-    BINJS_TRY_DECL(propName, factory_.newObjectLiteralPropertyName(name->name(), tokenizer_->pos(start)));
+    BINJS_TRY_DECL(propName, factory_.newObjectLiteralPropertyName(name->template as<NameNode>().name(), tokenizer_->pos(start)));
 
     BINJS_TRY_DECL(result, factory_.newObjectMethodOrPropertyDefinition(propName, name, AccessorType::None));
     result->setKind(ParseNodeKind::Shorthand);
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceSpreadElement(const size_t start, const BinKind kind, const BinFields& fields)
--- a/js/src/frontend/BinSource.cpp
+++ b/js/src/frontend/BinSource.cpp
@@ -12,24 +12,24 @@
 #include "mozilla/Move.h"
 #include "mozilla/PodOperations.h"
 #include "mozilla/ScopeExit.h"
 #include "mozilla/Vector.h"
 
 #include "frontend/BinSource-macros.h"
 #include "frontend/BinTokenReaderTester.h"
 #include "frontend/FullParseHandler.h"
+#include "frontend/ParseNode.h"
 #include "frontend/Parser.h"
 #include "frontend/SharedContext.h"
 
 #include "js/Result.h"
 #include "vm/RegExpObject.h"
 
 #include "frontend/ParseContext-inl.h"
-#include "frontend/ParseNode-inl.h"
 #include "vm/JSContext-inl.h"
 
 // # About compliance with EcmaScript
 //
 // For the moment, this parser implements ES5. Future versions will be extended
 // to ES6 and further on.
 //
 // By design, it does NOT implement Annex B.3.3. If possible, we would like
@@ -553,17 +553,17 @@ BinASTParser<Tok>::checkPositionalParame
 
             JSAtom* name = positionalParams.get()[i];
             if (!name) {
                 // Step 2.a.ii.1.
                 return raiseError("Expected destructuring/rest parameter per AssertedParameterScope.paramNames, got positional parameter");
             }
 
             // Step 2.a.i.
-            if (param->name() != name) {
+            if (param->as<NameNode>().name() != name) {
                 // Step 2.a.ii.1.
                 return raiseError("Name mismatch between AssertedPositionalParameterName in AssertedParameterScope.paramNames and actual parameter");
             }
 
             // Step 2.a.i.1.
             // Implicitly done.
         } else {
             // Destructuring parameter.
--- a/js/src/frontend/BinSource.yaml
+++ b/js/src/frontend/BinSource.yaml
@@ -33,23 +33,23 @@ cpp:
         #include "mozilla/Move.h"
         #include "mozilla/PodOperations.h"
         #include "mozilla/Vector.h"
 
         #include "frontend/BinSource-macros.h"
         #include "frontend/BinSource.h"
         #include "frontend/BinTokenReaderTester.h"
         #include "frontend/FullParseHandler.h"
+        #include "frontend/ParseNode.h"
         #include "frontend/Parser.h"
         #include "frontend/SharedContext.h"
 
         #include "vm/RegExpObject.h"
 
         #include "frontend/ParseContext-inl.h"
-        #include "frontend/ParseNode-inl.h"
 
         namespace js {
         namespace frontend {
 
         // Compare a bunch of `uint8_t` values (as returned by the tokenizer_) with
         // a string literal (and ONLY a string literal).
         template<typename Tok, size_t N>
         bool operator==(const typename Tok::Chars& left, const char (&right)[N]) {
@@ -501,18 +501,19 @@ CallExpression:
                     parseContext_->functionBox()->usesApply = true;
             } else if (prop == cx_->names().call) {
                 op = JSOP_FUNCALL;
             }
         }
 
         // Check for direct calls to `eval`.
         if (factory_.isEvalName(callee, cx_)) {
-            if (!parseContext_->varScope().lookupDeclaredNameForAdd(callee->name())
-             && !parseContext_->innermostScope()->lookupDeclaredNameForAdd(callee->name())) {
+            if (!parseContext_->varScope().lookupDeclaredNameForAdd(cx_->names().eval)
+             && !parseContext_->innermostScope()->lookupDeclaredNameForAdd(cx_->names().eval))
+            {
                 // This is a direct call to `eval`.
                 if (!parseContext_->sc()->hasDirectEval()) {
                     return raiseMissingDirectEvalInAssertedScope();
                 }
 
                 op = parseContext_->sc()->strict() ? JSOP_STRICTEVAL : JSOP_EVAL;
             }
         }
@@ -1108,17 +1109,17 @@ Script:
     build:
         MOZ_TRY(checkClosedVars(parseContext_->varScope()));
         BINJS_MOZ_TRY_DECL(result, appendDirectivesToBody(/* body = */ statements, /* directives = */ directives));
 
 ShorthandProperty:
     build: |
         MOZ_ASSERT(name->isKind(ParseNodeKind::Name));
         MOZ_ASSERT(!factory_.isUsableAsObjectPropertyName(name));
-        BINJS_TRY_DECL(propName, factory_.newObjectLiteralPropertyName(name->name(), tokenizer_->pos(start)));
+        BINJS_TRY_DECL(propName, factory_.newObjectLiteralPropertyName(name->template as<NameNode>().name(), tokenizer_->pos(start)));
 
         BINJS_TRY_DECL(result, factory_.newObjectMethodOrPropertyDefinition(propName, name, AccessorType::None));
         result->setKind(ParseNodeKind::Shorthand);
 
 SwitchCase:
     type-ok:
         CaseClause*
     build: |
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -31,16 +31,17 @@
 #include "frontend/ElemOpEmitter.h"
 #include "frontend/EmitterScope.h"
 #include "frontend/ExpressionStatementEmitter.h"
 #include "frontend/ForInEmitter.h"
 #include "frontend/ForOfEmitter.h"
 #include "frontend/ForOfLoopControl.h"
 #include "frontend/IfEmitter.h"
 #include "frontend/NameOpEmitter.h"
+#include "frontend/ParseNode.h"
 #include "frontend/Parser.h"
 #include "frontend/PropOpEmitter.h"
 #include "frontend/SwitchEmitter.h"
 #include "frontend/TDZCheckCache.h"
 #include "frontend/TryEmitter.h"
 #include "frontend/WhileEmitter.h"
 #include "js/CompileOptions.h"
 #include "vm/BytecodeUtil.h"
@@ -48,17 +49,16 @@
 #include "vm/GeneratorObject.h"
 #include "vm/JSAtom.h"
 #include "vm/JSContext.h"
 #include "vm/JSFunction.h"
 #include "vm/JSScript.h"
 #include "vm/Stack.h"
 #include "wasm/AsmJS.h"
 
-#include "frontend/ParseNode-inl.h"
 #include "vm/JSObject-inl.h"
 
 using namespace js;
 using namespace js::frontend;
 
 using mozilla::AssertedCast;
 using mozilla::DebugOnly;
 using mozilla::Maybe;
@@ -1711,19 +1711,19 @@ BytecodeEmitter::emitGetNameAtLocation(J
     if (!noe.emitGet()) {
         return false;
     }
 
     return true;
 }
 
 bool
-BytecodeEmitter::emitGetName(ParseNode* pn)
-{
-    return emitGetName(pn->name());
+BytecodeEmitter::emitGetName(NameNode* name)
+{
+    return emitGetName(name->name());
 }
 
 bool
 BytecodeEmitter::emitTDZCheckIfNeeded(JSAtom* name, const NameLocation& loc)
 {
     // Dynamic accesses have TDZ checks built into their VM code and should
     // never emit explicit TDZ checks.
     MOZ_ASSERT(loc.hasKnownSlot());
@@ -2216,17 +2216,17 @@ bool
 BytecodeEmitter::emitSetThis(BinaryNode* setThisNode)
 {
     // ParseNodeKind::SetThis is used to update |this| after a super() call
     // in a derived class constructor.
 
     MOZ_ASSERT(setThisNode->isKind(ParseNodeKind::SetThis));
     MOZ_ASSERT(setThisNode->left()->isKind(ParseNodeKind::Name));
 
-    RootedAtom name(cx, setThisNode->left()->name());
+    RootedAtom name(cx, setThisNode->left()->as<NameNode>().name());
 
     // The 'this' binding is not lexical, but due to super() semantics this
     // initialization needs to be treated as a lexical one.
     NameLocation loc = lookupName(name);
     NameLocation lexicalLoc;
     if (loc.kind() == NameLocation::Kind::FrameSlot) {
         lexicalLoc = NameLocation::FrameSlot(BindingKind::Let, loc.frameSlot());
     } else if (loc.kind() == NameLocation::Kind::EnvironmentCoordinate) {
@@ -2553,17 +2553,17 @@ BytecodeEmitter::emitSetOrInitializeDest
         // Per its post-condition, emitDestructuringOps has left the
         // to-be-destructured value on top of the stack.
         if (!emit1(JSOP_POP)) {
             return false;
         }
     } else {
         switch (target->getKind()) {
           case ParseNodeKind::Name: {
-            RootedAtom name(cx, target->name());
+            RootedAtom name(cx, target->as<NameNode>().name());
             NameLocation loc;
             NameOpEmitter::Kind kind;
             switch (flav) {
               case DestructuringDeclaration:
                 loc = lookupName(name);
                 kind = NameOpEmitter::Kind::Initialize;
                 break;
               case DestructuringFormalParameterInVarScope: {
@@ -3022,17 +3022,17 @@ bool
 BytecodeEmitter::emitInitializer(ParseNode* initializer, ParseNode* pattern)
 {
     if (!emitTree(initializer)) {
         return false;
     }
 
     if (initializer->isDirectRHSAnonFunction()) {
         MOZ_ASSERT(!pattern->isInParens());
-        RootedAtom name(cx, pattern->name());
+        RootedAtom name(cx, pattern->as<NameNode>().name());
         if (!setOrEmitSetFunName(initializer, name)) {
             return false;
         }
     }
 
     return true;
 }
 
@@ -3764,26 +3764,27 @@ BytecodeEmitter::emitDeclarationList(Lis
             if (!emitDestructuringOps(pattern, DestructuringDeclaration)) {
                 return false;
             }
 
             if (!emit1(JSOP_POP)) {
                 return false;
             }
         } else {
-            if (!emitSingleDeclaration(declList, decl, decl->as<NameNode>().initializer())) {
-                return false;
-            }
-        }
-    }
-    return true;
-}
-
-bool
-BytecodeEmitter::emitSingleDeclaration(ParseNode* declList, ParseNode* decl,
+            NameNode* name = &decl->as<NameNode>();
+            if (!emitSingleDeclaration(declList, name, name->initializer())) {
+                return false;
+            }
+        }
+    }
+    return true;
+}
+
+bool
+BytecodeEmitter::emitSingleDeclaration(ListNode* declList, NameNode* decl,
                                        ParseNode* initializer)
 {
     MOZ_ASSERT(decl->isKind(ParseNodeKind::Name));
 
     // Nothing to do for initializer-less 'var' declarations, as there's no TDZ.
     if (!initializer && declList->isKind(ParseNodeKind::Var)) {
         return true;
     }
@@ -3860,35 +3861,36 @@ CompoundAssignmentParseNodeKindToJSOp(Pa
 bool
 BytecodeEmitter::emitAssignment(ParseNode* lhs, JSOp compoundOp, ParseNode* rhs)
 {
     bool isCompound = compoundOp != JSOP_NOP;
 
     // Name assignments are handled separately because choosing ops and when
     // to emit BINDNAME is involved and should avoid duplication.
     if (lhs->isKind(ParseNodeKind::Name)) {
+        NameNode* nameNode = &lhs->as<NameNode>();
+        RootedAtom name(cx, nameNode->name());
         NameOpEmitter noe(this,
-                          lhs->name(),
+                          name,
                           isCompound
                           ? NameOpEmitter::Kind::CompoundAssignment
                           : NameOpEmitter::Kind::SimpleAssignment);
         if (!noe.prepareForRhs()) {                       // ENV? VAL?
             return false;
         }
 
         // Emit the RHS. If we emitted a BIND[G]NAME, then the scope is on
         // the top of the stack and we need to pick the right RHS value.
         uint8_t offset = noe.emittedBindOp() ? 2 : 1;
         if (!EmitAssignmentRhs(this, rhs, offset)) {      // ENV? VAL? RHS
             return false;
         }
         if (rhs && rhs->isDirectRHSAnonFunction()) {
-            MOZ_ASSERT(!lhs->isInParens());
+            MOZ_ASSERT(!nameNode->isInParens());
             MOZ_ASSERT(!isCompound);
-            RootedAtom name(cx, lhs->name());
             if (!setOrEmitSetFunName(rhs, name)) {         // ENV? VAL? RHS
                 return false;
             }
         }
 
         // Emit the compound assignment op if there is one.
         if (isCompound) {
             if (!emit1(compoundOp)) {                     // ENV? VAL
@@ -4322,17 +4324,17 @@ BytecodeEmitter::emitCatch(BinaryNode* c
                 return false;
             }
             if (!emit1(JSOP_POP)) {
                 return false;
             }
             break;
 
           case ParseNodeKind::Name:
-            if (!emitLexicalInitialization(param)) {
+            if (!emitLexicalInitialization(&param->as<NameNode>())) {
                 return false;
             }
             if (!emit1(JSOP_POP)) {
                 return false;
             }
             break;
 
           default:
@@ -4904,17 +4906,18 @@ BytecodeEmitter::emitInitializeForInOrOf
     if (!updateSourceCoordNotes(target->pn_pos.begin)) {
         return false;
     }
 
     MOZ_ASSERT(target->isForLoopDeclaration());
     target = parser->astGenerator().singleBindingFromDeclaration(&target->as<ListNode>());
 
     if (target->isKind(ParseNodeKind::Name)) {
-        NameOpEmitter noe(this, target->name(), NameOpEmitter::Kind::Initialize);
+        NameNode* nameNode = &target->as<NameNode>();
+        NameOpEmitter noe(this, nameNode->name(), NameOpEmitter::Kind::Initialize);
         if (!noe.prepareForRhs()) {
             return false;
         }
         if (noe.emittedBindOp()) {
             // Per-iteration initialization in for-in/of loops computes the
             // iteration value *before* initializing.  Thus the initializing
             // value may be buried under a bind-specific value on the stack.
             // Swap it to the top of the stack.
@@ -4960,18 +4963,17 @@ BytecodeEmitter::emitForOf(ForNode* forO
 
     ParseNode* forHeadExpr = forOfHead->kid3();
 
     // Certain builtins (e.g. Array.from) are implemented in self-hosting
     // as for-of loops.
     bool allowSelfHostedIter = false;
     if (emitterMode == BytecodeEmitter::SelfHosting &&
         forHeadExpr->isKind(ParseNodeKind::Call) &&
-        forHeadExpr->as<BinaryNode>().left()->name() == cx->names().allowContentIter)
-    {
+        forHeadExpr->as<BinaryNode>().left()->isName(cx->names().allowContentIter)) {
         allowSelfHostedIter = true;
     }
 
     ForOfEmitter forOf(this, headLexicalEmitterScope, allowSelfHostedIter, iterKind);
 
     if (!forOf.emitIterated()) {                          //
         return false;
     }
@@ -5031,17 +5033,18 @@ BytecodeEmitter::emitForIn(ForNode* forI
             if (ParseNode* initializer = decl->as<NameNode>().initializer()) {
                 MOZ_ASSERT(forInTarget->isKind(ParseNodeKind::Var),
                            "for-in initializers are only permitted for |var| declarations");
 
                 if (!updateSourceCoordNotes(decl->pn_pos.begin)) {
                     return false;
                 }
 
-                NameOpEmitter noe(this, decl->name(), NameOpEmitter::Kind::Initialize);
+                NameNode* nameNode = &decl->as<NameNode>();
+                NameOpEmitter noe(this, nameNode->name(), NameOpEmitter::Kind::Initialize);
                 if (!noe.prepareForRhs()) {
                     return false;
                 }
                 if (!emitInitializer(initializer, decl)) {
                     return false;
                 }
                 if (!noe.emitAssignment()) {
                     return false;
@@ -5612,23 +5615,22 @@ BytecodeEmitter::emitContinue(PropertyNa
         }
     } else {
         target = findInnermostNestableControl<LoopControl>();
     }
     return emitGoto(target, &target->continues, SRC_CONTINUE);
 }
 
 bool
-BytecodeEmitter::emitGetFunctionThis(ParseNode* pn)
+BytecodeEmitter::emitGetFunctionThis(NameNode* thisName)
 {
     MOZ_ASSERT(sc->thisBinding() == ThisBinding::Function);
-    MOZ_ASSERT(pn->isKind(ParseNodeKind::Name));
-    MOZ_ASSERT(pn->name() == cx->names().dotThis);
-
-    return emitGetFunctionThis(Some(pn->pn_pos.begin));
+    MOZ_ASSERT(thisName->isName(cx->names().dotThis));
+
+    return emitGetFunctionThis(Some(thisName->pn_pos.begin));
 }
 
 bool
 BytecodeEmitter::emitGetFunctionThis(const mozilla::Maybe<uint32_t>& offset)
 {
     if (offset) {
         if (!updateLineNumberNotes(*offset)) {
             return false;
@@ -5646,23 +5648,25 @@ BytecodeEmitter::emitGetFunctionThis(con
 
     return true;
 }
 
 bool
 BytecodeEmitter::emitGetThisForSuperBase(UnaryNode* superBase)
 {
     MOZ_ASSERT(superBase->isKind(ParseNodeKind::SuperBase));
-    return emitGetFunctionThis(superBase->kid());         // THIS
+    NameNode* nameNode = &superBase->kid()->as<NameNode>();
+    return emitGetFunctionThis(nameNode);                 // THIS
 }
 
 bool
 BytecodeEmitter::emitThisLiteral(ThisLiteral* pn)
 {
-    if (ParseNode* thisName = pn->kid()) {
+    if (ParseNode* kid = pn->kid()) {
+        NameNode* thisName = &kid->as<NameNode>();
         return emitGetFunctionThis(thisName);             // THIS
     }
 
     if (sc->thisBinding() == ThisBinding::Module) {
         return emit1(JSOP_UNDEFINED);                     // UNDEF
     }
 
     MOZ_ASSERT(sc->thisBinding() == ThisBinding::Global);
@@ -6515,17 +6519,17 @@ BytecodeEmitter::emitSelfHostedCallFunct
     // invokes the callee with the correct |this| object and arguments.
     // callFunction(fun, thisArg, arg0, arg1) thus becomes:
     // - emit lookup for fun
     // - emit lookup for thisArg
     // - emit lookups for arg0, arg1
     //
     // argc is set to the amount of actually emitted args and the
     // emitting of args below is disabled by setting emitArgs to false.
-    ParseNode* calleeNode = callNode->left();
+    NameNode* calleeNode = &callNode->left()->as<NameNode>();
     ListNode* argsList = &callNode->right()->as<ListNode>();
 
     const char* errorName = SelfHostedCallFunctionName(calleeNode->name(), cx);
 
     if (argsList->count() < 2) {
         reportError(callNode, JSMSG_MORE_ARGS_NEEDED, errorName, "2", "s");
         return false;
     }
@@ -6535,18 +6539,17 @@ BytecodeEmitter::emitSelfHostedCallFunct
         reportError(callNode, JSMSG_NOT_CONSTRUCTOR, errorName);
         return false;
     }
 
     bool constructing = calleeNode->name() == cx->names().constructContentFunction;
     ParseNode* funNode = argsList->head();
     if (constructing) {
         callOp = JSOP_NEW;
-    } else if (funNode->getKind() == ParseNodeKind::Name &&
-               funNode->name() == cx->names().std_Function_apply) {
+    } else if (funNode->isName(cx->names().std_Function_apply)) {
         callOp = JSOP_FUNAPPLY;
     }
 
     if (!emitTree(funNode)) {
         return false;
     }
 
 #ifdef DEBUG
@@ -6730,42 +6733,42 @@ BytecodeEmitter::emitSelfHostedGetProper
     if (!emitTree(objNode)) {
         return false;
     }
 
     return emitElemOpBase(JSOP_GETELEM_SUPER);
 }
 
 bool
-BytecodeEmitter::isRestParameter(ParseNode* pn)
+BytecodeEmitter::isRestParameter(ParseNode* expr)
 {
     if (!sc->isFunctionBox()) {
         return false;
     }
 
     FunctionBox* funbox = sc->asFunctionBox();
     RootedFunction fun(cx, funbox->function());
     if (!funbox->hasRest()) {
         return false;
     }
 
-    if (!pn->isKind(ParseNodeKind::Name)) {
-        if (emitterMode == BytecodeEmitter::SelfHosting && pn->isKind(ParseNodeKind::Call)) {
-            BinaryNode* callNode = &pn->as<BinaryNode>();
+    if (!expr->isKind(ParseNodeKind::Name)) {
+        if (emitterMode == BytecodeEmitter::SelfHosting &&
+            expr->isKind(ParseNodeKind::Call))
+        {
+            BinaryNode* callNode = &expr->as<BinaryNode>();
             ParseNode* calleeNode = callNode->left();
-            if (calleeNode->getKind() == ParseNodeKind::Name &&
-                calleeNode->name() == cx->names().allowContentIter)
-            {
+            if (calleeNode->isName(cx->names().allowContentIter)) {
                 return isRestParameter(callNode->right()->as<ListNode>().head());
             }
         }
         return false;
     }
 
-    JSAtom* name = pn->name();
+    JSAtom* name = expr->as<NameNode>().name();
     Maybe<NameLocation> paramLoc = locationOfNameBoundInFunctionScope(name);
     if (paramLoc && lookupName(name) == *paramLoc) {
         FunctionScope::Data* bindings = funbox->functionScopeBindings();
         if (bindings->nonPositionalFormalStart > 0) {
             // |paramName| can be nullptr when the rest destructuring syntax is
             // used: `function f(...[]) {}`.
             JSAtom* paramName =
                 bindings->trailingNames[bindings->nonPositionalFormalStart - 1].name();
@@ -6776,18 +6779,18 @@ BytecodeEmitter::isRestParameter(ParseNo
     return false;
 }
 
 bool
 BytecodeEmitter::emitCalleeAndThis(ParseNode* callee, ParseNode* call, CallOrNewEmitter& cone)
 {
     switch (callee->getKind()) {
       case ParseNodeKind::Name:
-        if (!cone.emitNameCallee(callee->name())) {       // CALLEE THIS
-            return false;
+        if (!cone.emitNameCallee(callee->as<NameNode>().name())) {
+            return false;                                 // CALLEE THIS
         }
         break;
       case ParseNodeKind::Dot: {
         MOZ_ASSERT(emitterMode != BytecodeEmitter::SelfHosting);
         PropertyAccess* prop = &callee->as<PropertyAccess>();
         bool isSuper = prop->isSuper();
 
         PropOpEmitter& poe = cone.prepareForPropCallee(isSuper);
@@ -6953,17 +6956,17 @@ BytecodeEmitter::emitCallOrNew(BinaryNod
     ListNode* argsList = &callNode->right()->as<ListNode>();
     bool isSpread = JOF_OPTYPE(callNode->getOp()) == JOF_BYTE;
     if (calleeNode->isKind(ParseNodeKind::Name) && emitterMode == BytecodeEmitter::SelfHosting &&
         !isSpread)
     {
         // Calls to "forceInterpreter", "callFunction",
         // "callContentFunction", or "resumeGenerator" in self-hosted
         // code generate inline bytecode.
-        PropertyName* calleeName = calleeNode->name();
+        PropertyName* calleeName = calleeNode->as<NameNode>().name();
         if (calleeName == cx->names().callFunction ||
             calleeName == cx->names().callContentFunction ||
             calleeName == cx->names().constructContentFunction)
         {
             return emitSelfHostedCallFunction(callNode);
         }
         if (calleeName == cx->names().resumeGenerator) {
             return emitSelfHostedResumeGenerator(callNode);
@@ -7660,18 +7663,17 @@ BytecodeEmitter::emitArray(ParseNode* ar
             }
         } else {
             ParseNode* expr;
             if (elem->isKind(ParseNodeKind::Spread)) {
                 expr = elem->as<UnaryNode>().kid();
 
                 if (emitterMode == BytecodeEmitter::SelfHosting &&
                     expr->isKind(ParseNodeKind::Call) &&
-                    expr->as<BinaryNode>().left()->name() == cx->names().allowContentIter)
-                {
+                    expr->as<BinaryNode>().left()->isName(cx->names().allowContentIter)) {
                     allowSelfHostedIter = true;
                 }
             } else {
                 expr = elem;
             }
             if (!emitTree(expr)) {                                       // ARRAY INDEX? VALUE
                 return false;
             }
@@ -7950,17 +7952,17 @@ BytecodeEmitter::emitFunctionFormalParam
             {
                 return false;
             }
 
             if (!emit1(JSOP_POP)) {
                 return false;
             }
         } else if (hasParameterExprs || isRest) {
-            RootedAtom paramName(cx, bindingElement->name());
+            RootedAtom paramName(cx, bindingElement->as<NameNode>().name());
             NameLocation paramLoc = *locationOfNameBoundInScope(paramName, funScope);
             NameOpEmitter noe(this, paramName, paramLoc, NameOpEmitter::Kind::Initialize);
             if (!noe.prepareForRhs()) {
                 return false;
             }
             if (hasParameterExprs) {
                 // If we had an initializer or a rest parameter, the value is
                 // already on the stack.
@@ -8097,19 +8099,19 @@ BytecodeEmitter::emitFunctionBody(ParseN
             return false;
         }
     }
 
     return true;
 }
 
 bool
-BytecodeEmitter::emitLexicalInitialization(ParseNode* pn)
-{
-    NameOpEmitter noe(this, pn->name(), NameOpEmitter::Kind::Initialize);
+BytecodeEmitter::emitLexicalInitialization(NameNode* name)
+{
+    NameOpEmitter noe(this, name->name(), NameOpEmitter::Kind::Initialize);
     if (!noe.prepareForRhs()) {
         return false;
     }
 
     // The caller has pushed the RHS to the top of the stack. Assert that the
     // name is lexical and no BIND[G]NAME ops were emitted.
     MOZ_ASSERT(noe.loc().isLexical());
     MOZ_ASSERT(!noe.emittedBindOp());
@@ -8321,29 +8323,28 @@ BytecodeEmitter::emitClass(ClassNode* cl
         return false;
     }
 
     if (!emit1(JSOP_POP)) {                                     // ... CONSTRUCTOR
         return false;
     }
 
     if (names) {
-        ParseNode* innerName = names->innerBinding();
+        NameNode* innerName = names->innerBinding();
         if (!emitLexicalInitialization(innerName)) {            // ... CONSTRUCTOR
             return false;
         }
 
         // Pop the inner scope.
         if (!emitterScope->leave(this)) {
             return false;
         }
         emitterScope.reset();
 
-        ParseNode* outerName = names->outerBinding();
-        if (outerName) {
+        if (NameNode* outerName = names->outerBinding()) {
             if (!emitLexicalInitialization(outerName)) {        // ... CONSTRUCTOR
                 return false;
             }
             // Only class statements make outer bindings, and they do not leave
             // themselves on the stack.
             if (!emit1(JSOP_POP)) {                             // ...
                 return false;
             }
@@ -8363,17 +8364,17 @@ BytecodeEmitter::emitExportDefault(Binar
     MOZ_ASSERT(exportNode->isKind(ParseNodeKind::ExportDefault));
 
     ParseNode* nameNode = exportNode->left();
     if (!emitTree(nameNode)) {
         return false;
     }
 
     if (ParseNode* binding = exportNode->right()) {
-        if (!emitLexicalInitialization(binding)) {
+        if (!emitLexicalInitialization(&binding->as<NameNode>())) {
             return false;
         }
 
         if (nameNode->isDirectRHSAnonFunction()) {
             HandlePropertyName name = cx->names().default_;
             if (!setOrEmitSetFunName(nameNode, name)) {
                 return false;
             }
@@ -8799,17 +8800,17 @@ BytecodeEmitter::emitTree(ParseNode* pn,
 
       case ParseNodeKind::Object:
         if (!emitObject(&pn->as<ListNode>())) {
             return false;
         }
         break;
 
       case ParseNodeKind::Name:
-        if (!emitGetName(pn)) {
+        if (!emitGetName(&pn->as<NameNode>())) {
             return false;
         }
         break;
 
       case ParseNodeKind::TemplateStringList:
         if (!emitTemplateString(&pn->as<ListNode>())) {
             return false;
         }
--- a/js/src/frontend/BytecodeEmitter.h
+++ b/js/src/frontend/BytecodeEmitter.h
@@ -12,16 +12,17 @@
 #include "mozilla/Attributes.h"
 #include "mozilla/Span.h"
 
 #include "ds/InlineTable.h"
 #include "frontend/BCEParserHandle.h"
 #include "frontend/EitherParser.h"
 #include "frontend/JumpList.h"
 #include "frontend/NameFunctions.h"
+#include "frontend/ParseNode.h"
 #include "frontend/SharedContext.h"
 #include "frontend/SourceNotes.h"
 #include "frontend/ValueUsage.h"
 #include "vm/BytecodeUtil.h"
 #include "vm/Interpreter.h"
 #include "vm/Iteration.h"
 
 namespace js {
@@ -516,17 +517,17 @@ struct MOZ_STACK_CLASS BytecodeEmitter
     MOZ_MUST_USE bool emitUint32Operand(JSOp op, uint32_t operand);
 
     // Emit (1 + extra) bytecodes, for N bytes of op and its immediate operand.
     MOZ_MUST_USE bool emitN(JSOp op, size_t extra, ptrdiff_t* offset = nullptr);
 
     MOZ_MUST_USE bool emitNumberOp(double dval);
 
     MOZ_MUST_USE bool emitThisLiteral(ThisLiteral* pn);
-    MOZ_MUST_USE bool emitGetFunctionThis(ParseNode* pn);
+    MOZ_MUST_USE bool emitGetFunctionThis(NameNode* thisName);
     MOZ_MUST_USE bool emitGetFunctionThis(const mozilla::Maybe<uint32_t>& offset);
     MOZ_MUST_USE bool emitGetThisForSuperBase(UnaryNode* superBase);
     MOZ_MUST_USE bool emitSetThis(BinaryNode* setThisNode);
     MOZ_MUST_USE bool emitCheckDerivedClassConstructorReturn();
 
     // Handle jump opcodes and jump targets.
     MOZ_MUST_USE bool emitJumpTarget(JumpTarget* target);
     MOZ_MUST_USE bool emitJumpNoFallthrough(JSOp op, JumpList* jump);
@@ -580,24 +581,24 @@ struct MOZ_STACK_CLASS BytecodeEmitter
 
     MOZ_MUST_USE bool emitArgOp(JSOp op, uint16_t slot);
     MOZ_MUST_USE bool emitEnvCoordOp(JSOp op, EnvironmentCoordinate ec);
 
     MOZ_MUST_USE bool emitGetNameAtLocation(JSAtom* name, const NameLocation& loc);
     MOZ_MUST_USE bool emitGetName(JSAtom* name) {
         return emitGetNameAtLocation(name, lookupName(name));
     }
-    MOZ_MUST_USE bool emitGetName(ParseNode* pn);
+    MOZ_MUST_USE bool emitGetName(NameNode* name);
 
     MOZ_MUST_USE bool emitTDZCheckIfNeeded(JSAtom* name, const NameLocation& loc);
 
     MOZ_MUST_USE bool emitNameIncDec(UnaryNode* incDec);
 
     MOZ_MUST_USE bool emitDeclarationList(ListNode* declList);
-    MOZ_MUST_USE bool emitSingleDeclaration(ParseNode* declList, ParseNode* decl,
+    MOZ_MUST_USE bool emitSingleDeclaration(ListNode* declList, NameNode* decl,
                                             ParseNode* initializer);
 
     MOZ_MUST_USE bool emitNewInit();
     MOZ_MUST_USE bool emitSingletonInitialiser(ParseNode* pn);
 
     MOZ_MUST_USE bool emitPrepareIteratorResult();
     MOZ_MUST_USE bool emitFinishIteratorResult(bool done);
     MOZ_MUST_USE bool iteratorResultShape(unsigned* shape);
@@ -756,17 +757,17 @@ struct MOZ_STACK_CLASS BytecodeEmitter
     MOZ_MUST_USE bool emitSequenceExpr(ListNode* node,
                                        ValueUsage valueUsage = ValueUsage::WantValue);
 
     MOZ_NEVER_INLINE MOZ_MUST_USE bool emitIncOrDec(UnaryNode* incDec);
 
     MOZ_MUST_USE bool emitConditionalExpression(ConditionalExpression& conditional,
                                                 ValueUsage valueUsage = ValueUsage::WantValue);
 
-    bool isRestParameter(ParseNode* pn);
+    bool isRestParameter(ParseNode* expr);
 
     MOZ_MUST_USE bool emitArguments(ListNode* argsList, bool isCall, bool isSpread,
                                     CallOrNewEmitter& cone);
     MOZ_MUST_USE bool emitCallOrNew(BinaryNode* callNode,
                                     ValueUsage valueUsage = ValueUsage::WantValue);
     MOZ_MUST_USE bool emitSelfHostedCallFunction(BinaryNode* callNode);
     MOZ_MUST_USE bool emitSelfHostedResumeGenerator(BinaryNode* callNode);
     MOZ_MUST_USE bool emitSelfHostedForceInterpreter();
@@ -788,17 +789,17 @@ struct MOZ_STACK_CLASS BytecodeEmitter
 
     MOZ_MUST_USE bool emitBreak(PropertyName* label);
     MOZ_MUST_USE bool emitContinue(PropertyName* label);
 
     MOZ_MUST_USE bool emitFunctionFormalParametersAndBody(ListNode* paramsBody);
     MOZ_MUST_USE bool emitFunctionFormalParameters(ListNode* paramsBody);
     MOZ_MUST_USE bool emitInitializeFunctionSpecialNames();
     MOZ_MUST_USE bool emitFunctionBody(ParseNode* pn);
-    MOZ_MUST_USE bool emitLexicalInitialization(ParseNode* pn);
+    MOZ_MUST_USE bool emitLexicalInitialization(NameNode* name);
 
     // Emit bytecode for the spread operator.
     //
     // emitSpread expects the current index (I) of the array, the array itself
     // and the iterator to be on the stack in that order (iterator on the bottom).
     // It will pop the iterator and I, then iterate over the iterator by calling
     // |.next()| and put the results into the I-th element of array with
     // incrementing I, then push the result I (it will be original I +
deleted file mode 100644
--- a/js/src/frontend/ParseNode-inl.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * vim: set ts=8 sts=4 et sw=4 tw=99:
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef frontend_ParseNode_inl_h
-#define frontend_ParseNode_inl_h
-
-#include "frontend/ParseNode.h"
-
-#include "frontend/SharedContext.h"
-
-namespace js {
-namespace frontend {
-
-inline PropertyName*
-ParseNode::name() const
-{
-    MOZ_ASSERT(isKind(ParseNodeKind::Function) || isKind(ParseNodeKind::Name));
-    JSAtom* atom = isKind(ParseNodeKind::Function)
-                   ? as<CodeNode>().funbox()->function()->explicitName()
-                   : as<NameNode>().atom();
-    return atom->asPropertyName();
-}
-
-} /* namespace frontend */
-} /* namespace js */
-
-#endif /* frontend_ParseNode_inl_h */
--- a/js/src/frontend/ParseNode.cpp
+++ b/js/src/frontend/ParseNode.cpp
@@ -1,15 +1,15 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * vim: set ts=8 sts=4 et sw=4 tw=99:
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "frontend/ParseNode-inl.h"
+#include "frontend/ParseNode.h"
 
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/FloatingPoint.h"
 
 #include "jsnum.h"
 
 #include "frontend/Parser.h"
 
--- a/js/src/frontend/ParseNode.h
+++ b/js/src/frontend/ParseNode.h
@@ -636,16 +636,17 @@ class ParseNode
     ParseNodeArity getArity() const        { return ParseNodeArity(pn_arity); }
     bool isArity(ParseNodeArity a) const   { return getArity() == a; }
     void setArity(ParseNodeArity a)        { pn_arity = a; }
 
     bool isBinaryOperation() const {
         ParseNodeKind kind = getKind();
         return ParseNodeKind::BinOpFirst <= kind && kind <= ParseNodeKind::BinOpLast;
     }
+    inline bool isName(PropertyName* name) const;
 
     /* Boolean attributes. */
     bool isInParens() const                { return pn_parens; }
     bool isLikelyIIFE() const              { return isInParens(); }
     void setInParens(bool enabled)         { pn_parens = enabled; }
 
     bool isDirectRHSAnonFunction() const {
         return pn_rhs_anon_fun;
@@ -735,19 +736,16 @@ class ParseNode
     /*
      * If |left| is a list of the given kind/left-associative op, append
      * |right| to it and return |left|.  Otherwise return a [left, right] list.
      */
     static ParseNode*
     appendOrCreateList(ParseNodeKind kind, ParseNode* left, ParseNode* right,
                        FullParseHandler* handler, ParseContext* pc);
 
-    // include "ParseNode-inl.h" for these methods.
-    inline PropertyName* name() const;
-
     /* True if pn is a parsenode representing a literal constant. */
     bool isLiteral() const {
         return isKind(ParseNodeKind::Number) ||
                isKind(ParseNodeKind::String) ||
                isKind(ParseNodeKind::True) ||
                isKind(ParseNodeKind::False) ||
                isKind(ParseNodeKind::Null) ||
                isKind(ParseNodeKind::RawUndefined);
@@ -836,16 +834,21 @@ class NameNode : public ParseNode
 #ifdef DEBUG
     void dump(GenericPrinter& out, int indent);
 #endif
 
     JSAtom* atom() const {
         return pn_u.name.atom;
     }
 
+    PropertyName* name() const {
+        MOZ_ASSERT(isKind(ParseNodeKind::Name));
+        return atom()->asPropertyName();
+    }
+
     ParseNode* initializer() const {
         return pn_u.name.initOrStmt;
     }
 
     void setAtom(JSAtom* atom) {
         pn_u.name.atom = atom;
     }
 
@@ -854,16 +857,22 @@ class NameNode : public ParseNode
     }
 
     // Methods used by FoldConstants.cpp.
     ParseNode** unsafeInitializerReference() {
         return &pn_u.name.initOrStmt;
     }
 };
 
+inline bool
+ParseNode::isName(PropertyName* name) const
+{
+    return getKind() == ParseNodeKind::Name && as<NameNode>().name() == name;
+}
+
 class UnaryNode : public ParseNode
 {
   public:
     UnaryNode(ParseNodeKind kind, const TokenPos& pos, ParseNode* kid)
       : ParseNode(kind, JSOP_NOP, PN_UNARY, pos)
     {
         pn_u.unary.kid = kid;
     }
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -30,29 +30,29 @@
 
 #include "jsnum.h"
 #include "jstypes.h"
 
 #include "builtin/ModuleObject.h"
 #include "builtin/SelfHostingDefines.h"
 #include "frontend/BytecodeCompiler.h"
 #include "frontend/FoldConstants.h"
+#include "frontend/ParseNode.h"
 #include "frontend/TokenStream.h"
 #include "irregexp/RegExpParser.h"
 #include "vm/BytecodeUtil.h"
 #include "vm/JSAtom.h"
 #include "vm/JSContext.h"
 #include "vm/JSFunction.h"
 #include "vm/JSScript.h"
 #include "vm/RegExpObject.h"
 #include "vm/StringType.h"
 #include "wasm/AsmJS.h"
 
 #include "frontend/ParseContext-inl.h"
-#include "frontend/ParseNode-inl.h"
 #include "vm/EnvironmentObject-inl.h"
 
 using namespace js;
 
 using mozilla::Maybe;
 using mozilla::Nothing;
 using mozilla::PodCopy;
 using mozilla::PodZero;
--- a/js/src/wasm/AsmJS.cpp
+++ b/js/src/wasm/AsmJS.cpp
@@ -26,16 +26,17 @@
 #include "mozilla/Unused.h"
 
 #include <new>
 
 #include "jsmath.h"
 #include "jsutil.h"
 
 #include "builtin/String.h"
+#include "frontend/ParseNode.h"
 #include "frontend/Parser.h"
 #include "gc/Policy.h"
 #include "js/MemoryMetrics.h"
 #include "js/Printf.h"
 #include "js/SourceBufferHolder.h"
 #include "js/StableStringChars.h"
 #include "js/Wrapper.h"
 #include "util/StringBuffer.h"
@@ -47,17 +48,16 @@
 #include "wasm/WasmCompile.h"
 #include "wasm/WasmGenerator.h"
 #include "wasm/WasmInstance.h"
 #include "wasm/WasmIonCompile.h"
 #include "wasm/WasmJS.h"
 #include "wasm/WasmSerialize.h"
 #include "wasm/WasmValidate.h"
 
-#include "frontend/ParseNode-inl.h"
 #include "vm/ArrayBufferObject-inl.h"
 #include "vm/JSObject-inl.h"
 
 using namespace js;
 using namespace js::frontend;
 using namespace js::jit;
 using namespace js::wasm;
 
@@ -698,17 +698,17 @@ static inline ParseNode*
 MaybeInitializer(ParseNode* pn)
 {
     return pn->as<NameNode>().initializer();
 }
 
 static inline bool
 IsUseOfName(ParseNode* pn, PropertyName* name)
 {
-    return pn->isKind(ParseNodeKind::Name) && pn->name() == name;
+    return pn->isName(name);
 }
 
 static inline bool
 IsIgnoredDirectiveName(JSContext* cx, JSAtom* atom)
 {
     return atom != cx->names().useStrict;
 }
 
@@ -2245,17 +2245,17 @@ IsCallToGlobal(ModuleValidator& m, Parse
         return false;
     }
 
     ParseNode* callee = CallCallee(pn);
     if (!callee->isKind(ParseNodeKind::Name)) {
         return false;
     }
 
-    *global = m.lookupGlobal(callee->name());
+    *global = m.lookupGlobal(callee->as<NameNode>().name());
     return !!*global;
 }
 
 static bool
 IsCoercionCall(ModuleValidator& m, ParseNode* pn, Type* coerceTo, ParseNode** coercedExpr)
 {
     const ModuleValidator::Global* global;
     if (!IsCallToGlobal(m, pn, &global)) {
@@ -2766,21 +2766,22 @@ static bool
 CheckArgument(ModuleValidator& m, ParseNode* arg, PropertyName** name)
 {
     *name = nullptr;
 
     if (!arg->isKind(ParseNodeKind::Name)) {
         return m.fail(arg, "argument is not a plain name");
     }
 
-    if (!CheckIdentifier(m, arg, arg->name())) {
-        return false;
-    }
-
-    *name = arg->name();
+    PropertyName* argName = arg->as<NameNode>().name();;
+    if (!CheckIdentifier(m, arg, argName)) {
+        return false;
+    }
+
+    *name = argName;
     return true;
 }
 
 static bool
 CheckModuleArgument(ModuleValidator& m, ParseNode* arg, PropertyName** name)
 {
     if (!CheckArgument(m, arg, name)) {
         return false;
@@ -3003,17 +3004,17 @@ CheckNewArrayView(ModuleValidator& m, Pr
         if (!IsArrayViewCtorName(m, field, &type)) {
             return m.fail(ctorExpr, "could not match typed array name");
         }
     } else {
         if (!ctorExpr->isKind(ParseNodeKind::Name)) {
             return m.fail(ctorExpr, "expecting name of imported array view constructor");
         }
 
-        PropertyName* globalName = ctorExpr->name();
+        PropertyName* globalName = ctorExpr->as<NameNode>().name();
         const ModuleValidator::Global* global = m.lookupGlobal(globalName);
         if (!global) {
             return m.failName(ctorExpr, "%s not found in module global scope", globalName);
         }
 
         if (global->which() != ModuleValidator::Global::ArrayViewCtor) {
             return m.failName(ctorExpr, "%s must be an imported array view constructor", globalName);
         }
@@ -3078,72 +3079,74 @@ CheckGlobalDotImport(ModuleValidator& m,
         }
         return m.failName(base, "expecting %s.Math", globalName);
     }
 
     if (!base->isKind(ParseNodeKind::Name)) {
         return m.fail(base, "expected name of variable or parameter");
     }
 
-    if (base->name() == m.globalArgumentName()) {
+    auto baseName = base->as<NameNode>().name();
+    if (baseName == m.globalArgumentName()) {
         if (field == m.cx()->names().NaN) {
             return m.addGlobalConstant(varName, GenericNaN(), field);
         }
         if (field == m.cx()->names().Infinity) {
             return m.addGlobalConstant(varName, PositiveInfinity<double>(), field);
         }
 
         Scalar::Type type;
         if (IsArrayViewCtorName(m, field, &type)) {
             return m.addArrayViewCtor(varName, type, field);
         }
 
         return m.failName(initNode, "'%s' is not a standard constant or typed array name", field);
     }
 
-    if (base->name() != m.importArgumentName()) {
+    if (baseName != m.importArgumentName()) {
         return m.fail(base, "expected global or import name");
     }
 
     return m.addFFI(varName, field);
 }
 
 static bool
 CheckModuleGlobal(ModuleValidator& m, ParseNode* var, bool isConst)
 {
     if (!var->isKind(ParseNodeKind::Name)) {
         return m.fail(var, "import variable is not a plain name");
     }
 
-    if (!CheckModuleLevelName(m, var, var->name())) {
+    PropertyName* varName = var->as<NameNode>().name();
+    if (!CheckModuleLevelName(m, var, varName)) {
         return false;
     }
 
     ParseNode* initNode = MaybeInitializer(var);
     if (!initNode) {
         return m.fail(var, "module import needs initializer");
     }
 
     if (IsNumericLiteral(m, initNode)) {
-        return CheckGlobalVariableInitConstant(m, var->name(), initNode, isConst);
+        return CheckGlobalVariableInitConstant(m, varName, initNode, isConst);
     }
 
     if (initNode->isKind(ParseNodeKind::BitOr) ||
         initNode->isKind(ParseNodeKind::Pos) ||
         initNode->isKind(ParseNodeKind::Call))
     {
-        return CheckGlobalVariableInitImport(m, var->name(), initNode, isConst);
+        return CheckGlobalVariableInitImport(m, varName, initNode, isConst);
     }
 
     if (initNode->isKind(ParseNodeKind::New)) {
-        return CheckNewArrayView(m, var->name(), initNode);
+        return CheckNewArrayView(m, varName, initNode);
     }
 
     if (initNode->isKind(ParseNodeKind::Dot)) {
-        return CheckGlobalDotImport(m, var->name(), initNode);
+        return CheckGlobalDotImport(m, varName, initNode);
     }
 
     return m.fail(initNode, "unsupported import expression");
 }
 
 static bool
 CheckModuleProcessingDirectives(ModuleValidator& m)
 {
@@ -3278,17 +3281,17 @@ CheckArguments(FunctionValidator& f, Par
     *stmtIter = stmt;
     return true;
 }
 
 static bool
 IsLiteralOrConst(FunctionValidator& f, ParseNode* pn, NumLit* lit)
 {
     if (pn->isKind(ParseNodeKind::Name)) {
-        const ModuleValidator::Global* global = f.lookupGlobal(pn->name());
+        const ModuleValidator::Global* global = f.lookupGlobal(pn->as<NameNode>().name());
         if (!global || global->which() != ModuleValidator::Global::ConstantLiteral) {
             return false;
         }
 
         *lit = global->constLiteralValue();
         return true;
     }
 
@@ -3321,17 +3324,17 @@ CheckFinalReturn(FunctionValidator& f, P
 
 static bool
 CheckVariable(FunctionValidator& f, ParseNode* var, ValTypeVector* types, Vector<NumLit>* inits)
 {
     if (!var->isKind(ParseNodeKind::Name)) {
         return f.fail(var, "local variable is not a plain name");
     }
 
-    PropertyName* name = var->name();
+    PropertyName* name = var->as<NameNode>().name();
 
     if (!CheckIdentifier(f.m(), var, name)) {
         return false;
     }
 
     ParseNode* initNode = MaybeInitializer(var);
     if (!initNode) {
         return f.failName(var, "var '%s' needs explicit type declaration via an initial value", name);
@@ -3409,17 +3412,17 @@ CheckNumericLiteral(FunctionValidator& f
     }
     *type = Type::lit(lit);
     return f.writeConstExpr(lit);
 }
 
 static bool
 CheckVarRef(FunctionValidator& f, ParseNode* varRef, Type* type)
 {
-    PropertyName* name = varRef->name();
+    PropertyName* name = varRef->as<NameNode>().name();
 
     if (const FunctionValidator::Local* local = f.lookupLocal(name)) {
         if (!f.encoder().writeOp(Op::GetLocal)) {
             return false;
         }
         if (!f.encoder().writeVarU32(local->slot)) {
             return false;
         }
@@ -3468,17 +3471,17 @@ static const int32_t NoMask = -1;
 static bool
 CheckArrayAccess(FunctionValidator& f, ParseNode* viewName, ParseNode* indexExpr,
                  Scalar::Type* viewType)
 {
     if (!viewName->isKind(ParseNodeKind::Name)) {
         return f.fail(viewName, "base of array access must be a typed array view name");
     }
 
-    const ModuleValidator::Global* global = f.lookupGlobal(viewName->name());
+    const ModuleValidator::Global* global = f.lookupGlobal(viewName->as<NameNode>().name());
     if (!global || !global->isAnyArrayView()) {
         return f.fail(viewName, "base of array access must be a typed array view name");
     }
 
     *viewType = global->viewType();
 
     uint32_t index;
     if (IsLiteralOrConstInt(f, indexExpr, &index)) {
@@ -3701,17 +3704,17 @@ CheckStoreArray(FunctionValidator& f, Pa
 
     *type = rhsType;
     return true;
 }
 
 static bool
 CheckAssignName(FunctionValidator& f, ParseNode* lhs, ParseNode* rhs, Type* type)
 {
-    RootedPropertyName name(f.cx(), lhs->name());
+    RootedPropertyName name(f.cx(), lhs->as<NameNode>().name());
 
     if (const FunctionValidator::Local* lhsVar = f.lookupLocal(name)) {
         Type rhsType;
         if (!CheckExpr(f, rhs, &rhsType)) {
             return false;
         }
 
         if (!f.encoder().writeOp(Op::TeeLocal)) {
@@ -4101,17 +4104,17 @@ CheckFuncPtrCall(FunctionValidator& f, P
     ParseNode* callee = CallCallee(callNode);
     ParseNode* tableNode = ElemBase(callee);
     ParseNode* indexExpr = ElemIndex(callee);
 
     if (!tableNode->isKind(ParseNodeKind::Name)) {
         return f.fail(tableNode, "expecting name of function-pointer array");
     }
 
-    PropertyName* name = tableNode->name();
+    PropertyName* name = tableNode->as<NameNode>().name();
     if (const ModuleValidator::Global* existing = f.lookupGlobal(name)) {
         if (existing->which() != ModuleValidator::Global::Table) {
             return f.failName(tableNode, "'%s' is not the name of a function-pointer array", name);
         }
     }
 
     if (!indexExpr->isKind(ParseNodeKind::BitAnd)) {
         return f.fail(indexExpr, "function-pointer table index expression needs & mask");
@@ -4168,17 +4171,17 @@ CheckIsExternType(FunctionValidator& f, 
     return true;
 }
 
 static bool
 CheckFFICall(FunctionValidator& f, ParseNode* callNode, unsigned ffiIndex, Type ret, Type* type)
 {
     MOZ_ASSERT(ret.isCanonical());
 
-    PropertyName* calleeName = CallCallee(callNode)->name();
+    PropertyName* calleeName = CallCallee(callNode)->as<NameNode>().name();
 
     if (ret.isFloat()) {
         return f.fail(callNode, "FFI calls can't return float");
     }
 
     ValTypeVector args;
     if (!CheckCallArgs<CheckIsExternType>(f, callNode, &args)) {
         return false;
@@ -4461,31 +4464,31 @@ CheckCoercedCall(FunctionValidator& f, P
     if (callee->isKind(ParseNodeKind::Elem)) {
         return CheckFuncPtrCall(f, call, ret, type);
     }
 
     if (!callee->isKind(ParseNodeKind::Name)) {
         return f.fail(callee, "unexpected callee expression type");
     }
 
-    PropertyName* calleeName = callee->name();
+    PropertyName* calleeName = callee->as<NameNode>().name();
 
     if (const ModuleValidator::Global* global = f.lookupGlobal(calleeName)) {
         switch (global->which()) {
           case ModuleValidator::Global::FFI:
             return CheckFFICall(f, call, global->ffiIndex(), ret, type);
           case ModuleValidator::Global::MathBuiltinFunction:
             return CheckCoercedMathBuiltinCall(f, call, global->mathBuiltinFunction(), ret, type);
           case ModuleValidator::Global::ConstantLiteral:
           case ModuleValidator::Global::ConstantImport:
           case ModuleValidator::Global::Variable:
           case ModuleValidator::Global::Table:
           case ModuleValidator::Global::ArrayView:
           case ModuleValidator::Global::ArrayViewCtor:
-            return f.failName(callee, "'%s' is not callable function", callee->name());
+            return f.failName(callee, "'%s' is not callable function", calleeName);
           case ModuleValidator::Global::Function:
             break;
         }
     }
 
     return CheckInternalCall(f, call, calleeName, ret, type);
 }
 
@@ -6009,17 +6012,17 @@ CheckFuncPtrTable(ModuleValidator& m, Pa
 
     Uint32Vector elemFuncDefIndices;
     const FuncType* sig = nullptr;
     for (ParseNode* elem = ListHead(arrayLiteral); elem; elem = NextNode(elem)) {
         if (!elem->isKind(ParseNodeKind::Name)) {
             return m.fail(elem, "function-pointer table's elements must be names of functions");
         }
 
-        PropertyName* funcName = elem->name();
+        PropertyName* funcName = elem->as<NameNode>().name();
         const ModuleValidator::Func* func = m.lookupFuncDef(funcName);
         if (!func) {
             return m.fail(elem, "function-pointer table's elements must be names of functions");
         }
 
         const FuncType& funcSig = m.env().types[func->sigIndex()].funcType();
         if (sig) {
             if (*sig != funcSig) {
@@ -6035,17 +6038,17 @@ CheckFuncPtrTable(ModuleValidator& m, Pa
     }
 
     FuncType copy;
     if (!copy.clone(*sig)) {
         return false;
     }
 
     uint32_t tableIndex;
-    if (!CheckFuncPtrTableAgainstExisting(m, var, var->name(), std::move(copy), mask, &tableIndex)) {
+    if (!CheckFuncPtrTableAgainstExisting(m, var, var->as<NameNode>().name(), std::move(copy), mask, &tableIndex)) {
         return false;
     }
 
     if (!m.defineFuncPtrTable(tableIndex, std::move(elemFuncDefIndices))) {
         return m.fail(var, "duplicate function-pointer definition");
     }
 
     return true;
@@ -6083,17 +6086,17 @@ CheckFuncPtrTables(ModuleValidator& m)
 
 static bool
 CheckModuleExportFunction(ModuleValidator& m, ParseNode* pn, PropertyName* maybeFieldName = nullptr)
 {
     if (!pn->isKind(ParseNodeKind::Name)) {
         return m.fail(pn, "expected name of exported function");
     }
 
-    PropertyName* funcName = pn->name();
+    PropertyName* funcName = pn->as<NameNode>().name();
     const ModuleValidator::Func* func = m.lookupFuncDef(funcName);
     if (!func) {
         return m.failName(pn, "function '%s' not found", funcName);
     }
 
     return m.addExportField(*func, maybeFieldName);
 }
 
@@ -6997,17 +7000,17 @@ class ModuleCharsForStore : ModuleChars
         // not present in the source so we must manually explicitly serialize
         // and match the formals as a Vector of PropertyName.
         isFunCtor_ = parser.pc->isStandaloneFunctionBody();
         if (isFunCtor_) {
             unsigned numArgs;
             CodeNode* functionNode = parser.pc->functionBox()->functionNode;
             ParseNode* arg = FunctionFormalParametersList(functionNode, &numArgs);
             for (unsigned i = 0; i < numArgs; i++, arg = arg->pn_next) {
-                UniqueChars name = StringToNewUTF8CharsZ(nullptr, *arg->name());
+                UniqueChars name = StringToNewUTF8CharsZ(nullptr, *arg->as<NameNode>().name());
                 if (!name || !funCtorArgs_.append(std::move(name))) {
                     return false;
                 }
             }
         }
 
         return true;
     }
@@ -7090,17 +7093,17 @@ class ModuleCharsForLookup : ModuleChars
             }
             unsigned numArgs;
             CodeNode* functionNode = parser.pc->functionBox()->functionNode;
             ParseNode* arg = FunctionFormalParametersList(functionNode, &numArgs);
             if (funCtorArgs_.length() != numArgs) {
                 return false;
             }
             for (unsigned i = 0; i < funCtorArgs_.length(); i++, arg = arg->pn_next) {
-                UniqueChars name = StringToNewUTF8CharsZ(nullptr, *arg->name());
+                UniqueChars name = StringToNewUTF8CharsZ(nullptr, *arg->as<NameNode>().name());
                 if (!name || strcmp(funCtorArgs_[i].get(), name.get())) {
                     return false;
                 }
             }
         }
         return true;
     }
 };