Bug 1674351 - Part 3: Use CompilationState.parserAtoms in parser and emitter. r=tcampbell
authorTooru Fujisawa <arai_a@mac.com>
Thu, 05 Nov 2020 15:35:24 +0000
changeset 556081 7a4ce0db75ba7d9d36d61479ae71b42b7440f217
parent 556080 6af11f8f19839a8bf57bbb47f964b51608c1da9f
child 556082 6f1bf8c8117fa09123eaf86c59fba05fcc600f54
push id130313
push userarai_a@mac.com
push dateThu, 05 Nov 2020 20:22:51 +0000
treeherderautoland@f0df0bb8123d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstcampbell
bugs1674351
milestone84.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 1674351 - Part 3: Use CompilationState.parserAtoms in parser and emitter. r=tcampbell Differential Revision: https://phabricator.services.mozilla.com/D95841
js/src/frontend/BytecodeEmitter.cpp
js/src/frontend/CompilationInfo.h
js/src/frontend/EitherParser.h
js/src/frontend/ModuleSharedContext.h
js/src/frontend/Parser.cpp
js/src/frontend/Parser.h
js/src/frontend/SharedContext-inl.h
js/src/frontend/SharedContext.cpp
js/src/frontend/SharedContext.h
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -2480,17 +2480,17 @@ bool BytecodeEmitter::emitScript(ParseNo
   if (!emitReturnRval()) {
     return false;
   }
 
   if (!emitterScope.leave(this)) {
     return false;
   }
 
-  if (!NameFunctions(cx, compilationInfo.stencil.parserAtoms, body)) {
+  if (!NameFunctions(cx, compilationState.parserAtoms, body)) {
     return false;
   }
 
   // Create a Stencil and convert it into a JSScript.
   return intoScriptStencil(
       &compilationInfo.stencil.scriptData[CompilationInfo::TopLevelIndex]);
 }
 
@@ -2560,17 +2560,17 @@ bool BytecodeEmitter::emitFunctionScript
   }
 
   if (!fse.emitEndBody()) {
     //              [stack]
     return false;
   }
 
   if (isTopLevel == TopLevelFunction::Yes) {
-    if (!NameFunctions(cx, compilationInfo.stencil.parserAtoms, funNode)) {
+    if (!NameFunctions(cx, compilationState.parserAtoms, funNode)) {
       return false;
     }
   }
 
   return fse.intoStencil();
 }
 
 bool BytecodeEmitter::emitDestructuringLHSRef(ParseNode* target,
@@ -8653,17 +8653,17 @@ bool BytecodeEmitter::emitPropertyList(L
     auto emitValue = [this, &key, &propVal, accessorType, &pe]() {
       //            [stack] CTOR? OBJ CTOR? KEY?
 
       if (propVal->isDirectRHSAnonFunction()) {
         if (key->isKind(ParseNodeKind::NumberExpr)) {
           MOZ_ASSERT(accessorType == AccessorType::None);
 
           const ParserAtom* keyAtom = key->as<NumericLiteral>().toAtom(
-              cx, compilationInfo.stencil.parserAtoms);
+              cx, compilationState.parserAtoms);
           if (!keyAtom) {
             return false;
           }
           if (!emitAnonymousFunctionWithName(propVal, keyAtom)) {
             //      [stack] CTOR? OBJ CTOR? KEY VAL
             return false;
           }
         } else if (key->isKind(ParseNodeKind::ObjectPropertyName) ||
@@ -9263,17 +9263,17 @@ bool BytecodeEmitter::emitPrivateMethodI
         if (!storedMethodName.append(".setter")) {
           return false;
         }
         break;
       default:
         MOZ_CRASH("Invalid private method accessor type");
     }
     const ParserAtom* storedMethodAtom =
-        storedMethodName.finishParserAtom(compilationInfo.stencil.parserAtoms);
+        storedMethodName.finishParserAtom(compilationState.parserAtoms);
 
     // Emit the private method body and store it as a lexical var.
     if (!emitFunction(&propdef->as<ClassMethod>().method())) {
       //              [stack] HOMEOBJ HERITAGE? ARRAY METHOD
       // or:
       //              [stack] CTOR HOMEOBJ ARRAY METHOD
       return false;
     }
@@ -10482,17 +10482,17 @@ MOZ_NEVER_INLINE bool BytecodeEmitter::e
 
   // Push undefined for the call's |this| value.
   if (!emit1(JSOp::Undefined)) {
     return false;
   }
   //            [stack] CALLBACK UNDEFINED
 
   const ParserAtom* atom = RealmInstrumentation::getInstrumentationKindName(
-      cx, compilationInfo.stencil.parserAtoms, kind);
+      cx, compilationState.parserAtoms, kind);
   if (!atom) {
     return false;
   }
 
   if (!emitAtomOp(JSOp::String, atom)) {
     return false;
   }
   //            [stack] CALLBACK UNDEFINED KIND
--- a/js/src/frontend/CompilationInfo.h
+++ b/js/src/frontend/CompilationInfo.h
@@ -433,21 +433,16 @@ struct CompilationInfo {
   MOZ_MUST_USE bool instantiateStencils(JSContext* cx,
                                         CompilationGCOutput& gcOutput);
   MOZ_MUST_USE bool instantiateStencilsAfterPreparation(
       JSContext* cx, CompilationGCOutput& gcOutput);
 
   MOZ_MUST_USE bool serializeStencils(JSContext* cx, JS::TranscodeBuffer& buf,
                                       bool* succeededOut = nullptr);
 
-  const ParserAtom* lowerJSAtomToParserAtom(JSContext* cx, JSAtom* atom) {
-    auto result = stencil.parserAtoms.internJSAtom(cx, *this, atom);
-    return result.unwrapOr(nullptr);
-  }
-
   // Move constructor is necessary to use Rooted.
   CompilationInfo(CompilationInfo&&) = default;
 
   // To avoid any misuses, make sure this is neither copyable or assignable.
   CompilationInfo(const CompilationInfo&) = delete;
   CompilationInfo& operator=(const CompilationInfo&) = delete;
   CompilationInfo& operator=(CompilationInfo&&) = delete;
 
--- a/js/src/frontend/EitherParser.h
+++ b/js/src/frontend/EitherParser.h
@@ -149,18 +149,14 @@ class EitherParser : public BCEParserHan
         matcher{offset, line, column};
     return parser.match(std::move(matcher));
   }
 
   JSAtom* liftParserAtomToJSAtom(const ParserAtom* parserAtom) {
     ParserSharedBase& base = parser.match(detail::ParserSharedBaseMatcher());
     return base.liftParserAtomToJSAtom(parserAtom);
   }
-  const ParserAtom* lowerJSAtomToParserAtom(JSAtom* atom) {
-    ParserSharedBase& base = parser.match(detail::ParserSharedBaseMatcher());
-    return base.lowerJSAtomToParserAtom(atom);
-  }
 };
 
 } /* namespace frontend */
 } /* namespace js */
 
 #endif /* frontend_EitherParser_h */
--- a/js/src/frontend/ModuleSharedContext.h
+++ b/js/src/frontend/ModuleSharedContext.h
@@ -16,16 +16,18 @@
 #include "vm/Scope.h"                // js::{Module,}Scope
 
 namespace js {
 
 class ModuleBuilder;
 
 namespace frontend {
 
+struct CompilationInfo;
+
 class MOZ_STACK_CLASS ModuleSharedContext : public SharedContext {
  public:
   ParserModuleScopeData* bindings;
   ModuleBuilder& builder;
 
   ModuleSharedContext(JSContext* cx, CompilationInfo& compilationInfo,
                       ModuleBuilder& builder, SourceExtent extent);
 };
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -201,18 +201,17 @@ PerHandlerParser<ParseHandler>::PerHandl
 template <class ParseHandler, typename Unit>
 GeneralParser<ParseHandler, Unit>::GeneralParser(
     JSContext* cx, const ReadOnlyCompileOptions& options, const Unit* units,
     size_t length, bool foldConstants, CompilationInfo& compilationInfo,
     CompilationState& compilationState, SyntaxParser* syntaxParser,
     BaseScript* lazyOuterFunction)
     : Base(cx, options, foldConstants, compilationInfo, compilationState,
            syntaxParser, lazyOuterFunction),
-      tokenStream(cx, &compilationInfo.stencil.parserAtoms, options, units,
-                  length) {}
+      tokenStream(cx, &compilationState.parserAtoms, options, units, length) {}
 
 template <typename Unit>
 void Parser<SyntaxParseHandler, Unit>::setAwaitHandling(
     AwaitHandling awaitHandling) {
   this->awaitHandling_ = awaitHandling;
 }
 
 template <typename Unit>
@@ -276,18 +275,18 @@ FunctionBox* PerHandlerParser<ParseHandl
   /*
    * We use JSContext.tempLifoAlloc to allocate parsed objects and place them
    * on a list in this Parser to ensure GC safety. Thus the tempLifoAlloc
    * arenas containing the entries must be alive until we are done with
    * scanning, parsing and code generation for the whole script or top-level
    * function.
    */
   FunctionBox* funbox = alloc_.new_<FunctionBox>(
-      cx_, extent, compilationInfo_, compilationState_, inheritedDirectives,
-      generatorKind, asyncKind, explicitName, flags, index, isTopLevel);
+      cx_, extent, compilationInfo_, inheritedDirectives, generatorKind,
+      asyncKind, explicitName, flags, index, isTopLevel);
   if (!funbox) {
     ReportOutOfMemory(cx_);
     return nullptr;
   }
 
   handler_.setFunctionBox(funNode, funbox);
 
   return funbox;
@@ -380,18 +379,18 @@ typename ParseHandler::ListNodeType Gene
     return null();
   }
 
   if (foldConstants_) {
     Node node = stmtList;
     // Don't constant-fold inside "use asm" code, as this could create a parse
     // tree that doesn't type-check as asm.js.
     if (!pc_->useAsmOrInsideUseAsm()) {
-      if (!FoldConstants(cx_, this->getCompilationInfo().stencil.parserAtoms,
-                         &node, &handler_)) {
+      if (!FoldConstants(cx_, this->compilationState_.parserAtoms, &node,
+                         &handler_)) {
         return null();
       }
     }
     stmtList = handler_.asList(node);
   }
 
   return stmtList;
 }
@@ -838,17 +837,17 @@ bool PerHandlerParser<ParseHandler>::
   if (handler_.canSkipLazyClosedOverBindings()) {
     // Scopes are nullptr-delimited in the BaseScript closed over bindings
     // array.
     uint32_t slotCount = scope.declaredCount();
     while (JSAtom* name = handler_.nextLazyClosedOverBinding()) {
       // TODO-Stencil
       //   After closed-over-bindings are snapshotted in the handler,
       //   remove this.
-      auto mbNameId = compilationInfo_.stencil.parserAtoms.internJSAtom(
+      auto mbNameId = this->compilationState_.parserAtoms.internJSAtom(
           cx_, this->getCompilationInfo(), name);
       if (mbNameId.isErr()) {
         return false;
       }
       const ParserName* nameId = mbNameId.unwrap()->asName();
 
       scope.lookupDeclaredName(nameId)->value()->setClosedOver();
       MOZ_ASSERT(slotCount > 0);
@@ -1611,18 +1610,18 @@ LexicalScopeNode* Parser<FullParseHandle
   if (!CheckParseTree(cx_, alloc_, body)) {
     return null();
   }
 
   ParseNode* node = body;
   // Don't constant-fold inside "use asm" code, as this could create a parse
   // tree that doesn't type-check as asm.js.
   if (!pc_->useAsmOrInsideUseAsm()) {
-    if (!FoldConstants(cx_, this->getCompilationInfo().stencil.parserAtoms,
-                       &node, &handler_)) {
+    if (!FoldConstants(cx_, this->compilationState_.parserAtoms, &node,
+                       &handler_)) {
       return null();
     }
   }
   body = handler_.asLexicalScope(node);
 
   if (!this->setSourceMapInfo()) {
     return nullptr;
   }
@@ -1672,18 +1671,18 @@ ListNode* Parser<FullParseHandler, Unit>
   if (!checkForUndefinedPrivateFields()) {
     return null();
   }
 
   ParseNode* node = body;
   // Don't constant-fold inside "use asm" code, as this could create a parse
   // tree that doesn't type-check as asm.js.
   if (!pc_->useAsmOrInsideUseAsm()) {
-    if (!FoldConstants(cx_, this->getCompilationInfo().stencil.parserAtoms,
-                       &node, &handler_)) {
+    if (!FoldConstants(cx_, this->compilationState_.parserAtoms, &node,
+                       &handler_)) {
       return null();
     }
   }
   body = &node->as<ListNode>();
 
   if (!this->setSourceMapInfo()) {
     return nullptr;
   }
@@ -1784,18 +1783,18 @@ ModuleNode* Parser<FullParseHandler, Uni
   if (!CheckParseTree(cx_, alloc_, stmtList)) {
     return null();
   }
 
   ParseNode* node = stmtList;
   // Don't constant-fold inside "use asm" code, as this could create a parse
   // tree that doesn't type-check as asm.js.
   if (!pc_->useAsmOrInsideUseAsm()) {
-    if (!FoldConstants(cx_, this->getCompilationInfo().stencil.parserAtoms,
-                       &node, &handler_)) {
+    if (!FoldConstants(cx_, this->compilationState_.parserAtoms, &node,
+                       &handler_)) {
       return null();
     }
   }
   stmtList = &node->as<ListNode>();
 
   if (!this->setSourceMapInfo()) {
     return null();
   }
@@ -2189,18 +2188,18 @@ FunctionNode* Parser<FullParseHandler, U
   if (!CheckParseTree(cx_, alloc_, funNode)) {
     return null();
   }
 
   ParseNode* node = funNode;
   // Don't constant-fold inside "use asm" code, as this could create a parse
   // tree that doesn't type-check as asm.js.
   if (!pc_->useAsmOrInsideUseAsm()) {
-    if (!FoldConstants(cx_, this->getCompilationInfo().stencil.parserAtoms,
-                       &node, &handler_)) {
+    if (!FoldConstants(cx_, this->compilationState_.parserAtoms, &node,
+                       &handler_)) {
       return null();
     }
   }
   funNode = &node->as<FunctionNode>();
 
   if (!checkForUndefinedPrivateFields(nullptr)) {
     return null();
   }
@@ -2394,17 +2393,17 @@ const ParserAtom* ParserBase::prefixAcce
     prefix = cx_->parserNames().setPrefix;
   } else {
     MOZ_ASSERT(propType == PropertyType::Getter);
     prefix = cx_->parserNames().getPrefix;
   }
 
   const ParserAtom* atoms[2] = {prefix, propAtom};
   auto atomsRange = mozilla::Range(atoms, 2);
-  return compilationInfo_.stencil.parserAtoms.concatAtoms(cx_, atomsRange)
+  return this->compilationState_.parserAtoms.concatAtoms(cx_, atomsRange)
       .unwrapOr(nullptr);
 }
 
 template <class ParseHandler, typename Unit>
 void GeneralParser<ParseHandler, Unit>::setFunctionStartAtPosition(
     FunctionBox* funbox, TokenPos pos) const {
   uint32_t startLine, startColumn;
   tokenStream.computeLineAndColumn(pos.begin, &startLine, &startColumn);
@@ -2740,17 +2739,19 @@ bool Parser<FullParseHandler, Unit>::ski
   // so we can skip over them after accounting for their free variables.
 
   RootedFunction fun(cx_, handler_.nextLazyInnerFunction());
 
   // TODO-Stencil: Consider for snapshotting.
   const ParserAtom* displayAtom = nullptr;
   if (fun->displayAtom()) {
     displayAtom =
-        this->compilationInfo_.lowerJSAtomToParserAtom(cx_, fun->displayAtom());
+        this->compilationState_.parserAtoms
+            .internJSAtom(cx_, this->compilationInfo_, fun->displayAtom())
+            .unwrapOr(nullptr);
     if (!displayAtom) {
       return false;
     }
   }
 
   FunctionBox* funbox =
       newFunctionBox(funNode, displayAtom, fun->flags(), toStringStart,
                      Directives(/* strict = */ false), fun->generatorKind(),
@@ -3231,17 +3232,19 @@ FunctionNode* Parser<FullParseHandler, U
   if (!funNode) {
     return null();
   }
 
   // TODO-Stencil: Consider for snapshotting.
   const ParserAtom* displayAtom = nullptr;
   if (fun->displayAtom()) {
     displayAtom =
-        this->compilationInfo_.lowerJSAtomToParserAtom(cx_, fun->displayAtom());
+        this->compilationState_.parserAtoms
+            .internJSAtom(cx_, this->compilationInfo_, fun->displayAtom())
+            .unwrapOr(nullptr);
     if (!displayAtom) {
       return null();
     }
   }
 
   Directives directives(strict);
   FunctionBox* funbox = newFunctionBox(funNode, displayAtom, fun->flags(),
                                        toStringStart, directives, generatorKind,
@@ -3290,18 +3293,18 @@ FunctionNode* Parser<FullParseHandler, U
   if (!CheckParseTree(cx_, alloc_, funNode)) {
     return null();
   }
 
   ParseNode* node = funNode;
   // Don't constant-fold inside "use asm" code, as this could create a parse
   // tree that doesn't type-check as asm.js.
   if (!pc_->useAsmOrInsideUseAsm()) {
-    if (!FoldConstants(cx_, this->getCompilationInfo().stencil.parserAtoms,
-                       &node, &handler_)) {
+    if (!FoldConstants(cx_, this->compilationState_.parserAtoms, &node,
+                       &handler_)) {
       return null();
     }
   }
   funNode = &node->as<FunctionNode>();
 
   return funNode;
 }
 
@@ -3691,18 +3694,18 @@ bool Parser<FullParseHandler, Unit>::asm
   pc_->functionBox()->useAsm = true;
 
   // Attempt to validate and compile this asm.js module. On success, the
   // tokenStream has been advanced to the closing }. On failure, the
   // tokenStream is in an indeterminate state and we must reparse the
   // function from the beginning. Reparsing is triggered by marking that a
   // new directive has been encountered and returning 'false'.
   bool validated;
-  if (!CompileAsmJS(cx_, this->compilationInfo_.stencil.parserAtoms, *this,
-                    list, &validated)) {
+  if (!CompileAsmJS(cx_, this->compilationState_.parserAtoms, *this, list,
+                    &validated)) {
     return false;
   }
   if (!validated) {
     pc_->newDirectives->setAsmJS();
     return false;
   }
 
   return true;
@@ -7379,17 +7382,17 @@ bool GeneralParser<ParseHandler, Unit>::
           if (!storedMethodName.append(".setter")) {
             return false;
           }
           break;
         default:
           MOZ_CRASH("Invalid private method accessor type");
       }
       const ParserAtom* storedMethodAtom = storedMethodName.finishParserAtom(
-          this->compilationInfo_.stencil.parserAtoms);
+          this->compilationState_.parserAtoms);
       if (!storedMethodAtom) {
         return false;
       }
       const ParserName* storedMethodProp = storedMethodAtom->asName();
       if (!noteDeclaredName(storedMethodProp, DeclarationKind::Const, pos())) {
         return false;
       }
 
@@ -10639,17 +10642,17 @@ typename ParseHandler::Node GeneralParse
   //   StringLiteral
   //   NumericLiteral
   TokenKind ltok = anyChars.currentToken().type;
 
   *propAtomOut = nullptr;
   switch (ltok) {
     case TokenKind::Number: {
       const ParserAtom* numAtom =
-          NumberToParserAtom(cx_, this->compilationInfo_.stencil.parserAtoms,
+          NumberToParserAtom(cx_, this->compilationState_.parserAtoms,
                              anyChars.currentToken().number());
       if (!numAtom) {
         return null();
       }
       *propAtomOut = numAtom;
       return newNumber(anyChars.currentToken());
     }
 
--- a/js/src/frontend/Parser.h
+++ b/js/src/frontend/Parser.h
@@ -267,19 +267,16 @@ class MOZ_STACK_CLASS ParserSharedBase {
  public:
   CompilationInfo& getCompilationInfo() { return compilationInfo_; }
 
   LifoAlloc& stencilAlloc() { return compilationInfo_.stencil.alloc; }
 
   JSAtom* liftParserAtomToJSAtom(const ParserAtom* parserAtom) {
     return parserAtom->toJSAtom(cx_, compilationInfo_.input.atomCache);
   }
-  const ParserAtom* lowerJSAtomToParserAtom(JSAtom* atom) {
-    return compilationInfo_.lowerJSAtomToParserAtom(cx_, atom);
-  }
 };
 
 class MOZ_STACK_CLASS ParserBase : public ParserSharedBase,
                                    public ErrorReportMixin {
   using Base = ErrorReportMixin;
 
  public:
   TokenStreamAnyChars anyChars;
--- a/js/src/frontend/SharedContext-inl.h
+++ b/js/src/frontend/SharedContext-inl.h
@@ -15,18 +15,14 @@ namespace frontend {
 
 inline Directives::Directives(ParseContext* parent)
     : strict_(parent->sc()->strict()), asmJS_(parent->useAsmOrInsideUseAsm()) {}
 
 inline JSAtom* SharedContext::liftParserAtomToJSAtom(JSContext* cx,
                                                      const ParserAtom* atomId) {
   return atomId->toJSAtom(cx, compilationInfo_.input.atomCache);
 }
-inline const ParserAtom* SharedContext::lowerJSAtomToParserAtom(JSContext* cx,
-                                                                JSAtom* atom) {
-  return compilationInfo_.lowerJSAtomToParserAtom(cx, atom);
-}
 
 }  // namespace frontend
 
 }  // namespace js
 
 #endif  // frontend_SharedContext_inl_h
--- a/js/src/frontend/SharedContext.cpp
+++ b/js/src/frontend/SharedContext.cpp
@@ -221,17 +221,16 @@ EvalSharedContext::EvalSharedContext(JSC
   allowSuperCall_ = compilationState.scopeContext.allowSuperCall;
   allowArguments_ = compilationState.scopeContext.allowArguments;
   thisBinding_ = compilationState.scopeContext.thisBinding;
   inWith_ = compilationState.scopeContext.inWith;
 }
 
 FunctionBox::FunctionBox(JSContext* cx, SourceExtent extent,
                          CompilationInfo& compilationInfo,
-                         CompilationState& compilationState,
                          Directives directives, GeneratorKind generatorKind,
                          FunctionAsyncKind asyncKind, const ParserAtom* atom,
                          FunctionFlags flags, FunctionIndex index,
                          TopLevelFunction isTopLevel)
     : SharedContext(cx, Kind::FunctionBox, compilationInfo, directives, extent),
       atom_(atom),
       funcDataIndex_(index),
       flags_(FunctionFlags::clearMutableflags(flags)),
--- a/js/src/frontend/SharedContext.h
+++ b/js/src/frontend/SharedContext.h
@@ -274,17 +274,16 @@ class SharedContext {
   bool setLocalStrictMode(bool strict) {
     bool retVal = localStrict;
     localStrict = strict;
     return retVal;
   }
 
   inline JSAtom* liftParserAtomToJSAtom(JSContext* cx,
                                         const ParserAtom* atomId);
-  inline const ParserAtom* lowerJSAtomToParserAtom(JSContext* cx, JSAtom* atom);
 
   void copyScriptFields(ScriptStencil& script);
 };
 
 class MOZ_STACK_CLASS GlobalSharedContext : public SharedContext {
   ScopeKind scopeKind_;
 
  public:
@@ -419,18 +418,17 @@ class FunctionBox : public SharedContext
   // Tracks if function-related fields are already copied to ScriptStencil.
   // If this field is true, modification to those fields should be synced with
   // ScriptStencil by copyUpdated* methods.
   bool isFunctionFieldCopiedToStencil : 1;
 
   // End of fields.
 
   FunctionBox(JSContext* cx, SourceExtent extent,
-              CompilationInfo& compilationInfo,
-              CompilationState& compilationState, Directives directives,
+              CompilationInfo& compilationInfo, Directives directives,
               GeneratorKind generatorKind, FunctionAsyncKind asyncKind,
               const ParserAtom* atom, FunctionFlags flags, FunctionIndex index,
               TopLevelFunction isTopLevel);
 
   ScriptStencil& functionStencil() const;
 
   ParserLexicalScopeData* namedLambdaBindings() { return namedLambdaBindings_; }
   void setNamedLambdaBindings(ParserLexicalScopeData* bindings) {