Bug 1660798 - Part 1 - Adaptor glue to allow for parser to transition to internal atoms representation. r=mgaudet,tcampbell
authorKannan Vijayan <kvijayan@mozilla.com>
Wed, 26 Aug 2020 00:15:23 +0000
changeset 546226 2258849b0ee1e5037093ade2d648b0c8a2d04286
parent 546225 f0ec22dea9acbd01f0a20a31805ad27952b3f538
child 546227 e87bcd8a1f949b155dff0cc0c7cbad7f4fe03f77
push id124986
push usertcampbell@mozilla.com
push dateWed, 26 Aug 2020 01:06:30 +0000
treeherderautoland@e87bcd8a1f94 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmgaudet, tcampbell
bugs1660798
milestone82.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 1660798 - Part 1 - Adaptor glue to allow for parser to transition to internal atoms representation. r=mgaudet,tcampbell Differential Revision: https://phabricator.services.mozilla.com/D84865
js/src/frontend/BCEParserHandle.h
js/src/frontend/CompilationInfo.h
js/src/frontend/EitherParser.h
js/src/frontend/Parser.h
js/src/frontend/ParserAtom.cpp
js/src/frontend/ParserAtom.h
js/src/frontend/TokenStream.cpp
js/src/jsapi.cpp
--- a/js/src/frontend/BCEParserHandle.h
+++ b/js/src/frontend/BCEParserHandle.h
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef frontend_BCEParserHandle_h
 #define frontend_BCEParserHandle_h
 
 #include "frontend/ErrorReporter.h"
 #include "frontend/FullParseHandler.h"
 #include "frontend/Parser.h"
+#include "frontend/ParserAtom.h"
 
 namespace js {
 namespace frontend {
 
 struct BCEParserHandle {
   virtual ErrorReporter& errorReporter() = 0;
   virtual const ErrorReporter& errorReporter() const = 0;
 
--- a/js/src/frontend/CompilationInfo.h
+++ b/js/src/frontend/CompilationInfo.h
@@ -285,16 +285,24 @@ struct MOZ_RAII CompilationInfo : public
   MOZ_MUST_USE bool assignSource(JS::SourceText<Unit>& sourceBuffer) {
     return source()->assignSource(cx, options, sourceBuffer);
   }
 
   MOZ_MUST_USE bool instantiateStencils();
 
   void trace(JSTracer* trc) final;
 
+  JSAtom* liftParserAtomToJSAtom(const ParserAtom* parserAtom) {
+    return parserAtom->toJSAtom(cx).unwrapOr(nullptr);
+  }
+  const ParserAtom* lowerJSAtomToParserAtom(JSAtom* atom) {
+    auto result = parserAtoms.internJSAtom(cx, atom);
+    return result.unwrapOr(nullptr);
+  }
+
   // To avoid any misuses, make sure this is neither copyable,
   // movable or assignable.
   CompilationInfo(const CompilationInfo&) = delete;
   CompilationInfo(CompilationInfo&&) = delete;
   CompilationInfo& operator=(const CompilationInfo&) = delete;
   CompilationInfo& operator=(CompilationInfo&&) = delete;
 
   ScriptStencilIterable functionScriptStencils() {
--- a/js/src/frontend/EitherParser.h
+++ b/js/src/frontend/EitherParser.h
@@ -144,14 +144,23 @@ class EitherParser : public BCEParserHan
   void computeLineAndColumn(uint32_t offset, uint32_t* line,
                             uint32_t* column) const {
     InvokeMemberFunction<detail::GetTokenStream,
                          detail::TokenStreamComputeLineAndColumn, uint32_t,
                          uint32_t*, uint32_t*>
         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/Parser.h
+++ b/js/src/frontend/Parser.h
@@ -261,16 +261,23 @@ class MOZ_STACK_CLASS ParserSharedBase :
   // innermost parse context (stack-allocated)
   ParseContext* pc_;
 
   // For tracking used names in this parsing session.
   UsedNameTracker& usedNames_;
 
  public:
   CompilationInfo& getCompilationInfo() { return compilationInfo_; }
+
+  JSAtom* liftParserAtomToJSAtom(const ParserAtom* parserAtom) {
+    return compilationInfo_.liftParserAtomToJSAtom(parserAtom);
+  }
+  const ParserAtom* lowerJSAtomToParserAtom(JSAtom* atom) {
+    return compilationInfo_.lowerJSAtomToParserAtom(atom);
+  }
 };
 
 class MOZ_STACK_CLASS ParserBase : public ParserSharedBase,
                                    public ErrorReportMixin {
   using Base = ErrorReportMixin;
 
  public:
   TokenStreamAnyChars anyChars;
--- a/js/src/frontend/ParserAtom.cpp
+++ b/js/src/frontend/ParserAtom.cpp
@@ -424,17 +424,17 @@ const ParserAtom* WellKnownParserAtoms::
   EntrySet::Ptr get = entrySet_.readonlyThreadsafeLookup(lookup);
   if (get) {
     return get->get()->asAtom();
   }
   return nullptr;
 }
 
 bool WellKnownParserAtoms::initSingle(JSContext* cx, const ParserName** name,
-                                      const char* str) {
+                                      const char* str, JSAtom* jsatom) {
   MOZ_ASSERT(name != nullptr);
 
   unsigned int len = strlen(str);
 
   MOZ_ASSERT(FindSmallestEncoding(UTF8Chars(str, len)) ==
              JS::SmallestEncoding::ASCII);
 
   InflatedChar16Sequence<Latin1Char> seq(
@@ -461,38 +461,39 @@ bool WellKnownParserAtoms::initSingle(JS
     }
     mozilla::PodCopy(copy.get(), reinterpret_cast<const Latin1Char*>(str), len);
     auto maybeEntry = ParserAtomEntry::allocate(cx, std::move(copy), len, hash);
     if (maybeEntry.isErr()) {
       return false;
     }
     entry = maybeEntry.unwrap();
   }
+  entry->jsatom_ = jsatom;
 
   // Save name for returning after moving entry into set.
   const ParserName* nm = entry.get()->asName();
   if (!entrySet_.putNew(lookup, std::move(entry))) {
     return false;
   }
 
   *name = nm;
   return true;
 }
 
 bool WellKnownParserAtoms::init(JSContext* cx) {
-#define COMMON_NAME_INIT_(idpart, id, text) \
-  if (!initSingle(cx, &(id), text)) {       \
-    return false;                           \
+#define COMMON_NAME_INIT_(idpart, id, text)           \
+  if (!initSingle(cx, &(id), text, cx->names().id)) { \
+    return false;                                     \
   }
   FOR_EACH_COMMON_PROPERTYNAME(COMMON_NAME_INIT_)
 #undef COMMON_NAME_INIT_
 
-#define COMMON_NAME_INIT_(name, clasp)   \
-  if (!initSingle(cx, &(name), #name)) { \
-    return false;                        \
+#define COMMON_NAME_INIT_(name, clasp)                     \
+  if (!initSingle(cx, &(name), #name, cx->names().name)) { \
+    return false;                                          \
   }
   JS_FOR_EACH_PROTOTYPE(COMMON_NAME_INIT_)
 #undef COMMON_NAME_INIT_
 
   return true;
 }
 
 } /* namespace frontend */
--- a/js/src/frontend/ParserAtom.h
+++ b/js/src/frontend/ParserAtom.h
@@ -4,16 +4,17 @@
  * 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_ParserAtom_h
 #define frontend_ParserAtom_h
 
 #include "mozilla/DebugOnly.h"      // mozilla::DebugOnly
 #include "mozilla/HashFunctions.h"  // HashString
+#include "mozilla/Range.h"          // mozilla::Range
 #include "mozilla/Variant.h"        // mozilla::Variant
 
 #include "ds/LifoAlloc.h"  // LifoAlloc
 #include "js/HashTable.h"  // HashSet
 #include "js/UniquePtr.h"  // js::UniquePtr
 #include "js/Vector.h"     // Vector
 #include "vm/CommonPropertyNames.h"
 #include "vm/StringType.h"  // CompareChars, StringEqualsAscii
@@ -187,16 +188,20 @@ class alignas(alignof(void*)) ParserAtom
   uint32_t length_;
 
   // The JSAtom-compatible hash of the string.
   HashNumber hash_;
 
   // Used to dynamically optimize the mapping of ParserAtoms to JSAtom*s.
   // If the entry comes from an atom or has been mapped to an
   // atom previously, the atom reference is kept here.
+  //
+  // Note: if/when this field is removed, remove the comment
+  // in front of the call to `rt->initializeParserAtoms()` in
+  // `JS::InitSelfHostedCode`.
   mutable JSAtom* jsatom_ = nullptr;
 
  public:
   template <typename CharT>
   ParserAtomEntry(mozilla::UniquePtr<CharT[], JS::FreePolicy> chars,
                   uint32_t length, HashNumber hash)
       : variant_(std::move(chars)), length_(length), hash_(hash) {}
 
@@ -244,16 +249,22 @@ class alignas(alignof(void*)) ParserAtom
   const Latin1Char* latin1Chars() const {
     MOZ_ASSERT(hasLatin1Chars());
     return variant_.getUnchecked<Latin1Char>();
   }
   const char16_t* twoByteChars() const {
     MOZ_ASSERT(hasTwoByteChars());
     return variant_.getUnchecked<char16_t>();
   }
+  mozilla::Range<const Latin1Char> latin1Range() const {
+    return mozilla::Range(latin1Chars(), length_);
+  }
+  mozilla::Range<const char16_t> twoByteRange() const {
+    return mozilla::Range(twoByteChars(), length_);
+  }
 
   bool isIndex(uint32_t* indexp) const;
   bool isIndex() const {
     uint32_t index;
     return isIndex(&index);
   }
 
   HashNumber hash() const { return hash_; }
@@ -350,17 +361,18 @@ class WellKnownParserAtoms {
   JS_FOR_EACH_PROTOTYPE(PROPERTYNAME_FIELD_)
 #undef PROPERTYNAME_FIELD_
 
  private:
   using EntrySet = HashSet<UniquePtr<ParserAtomEntry>, ParserAtomLookupHasher,
                            TempAllocPolicy>;
   EntrySet entrySet_;
 
-  bool initSingle(JSContext* cx, const ParserName** name, const char* str);
+  bool initSingle(JSContext* cx, const ParserName** name, const char* str,
+                  JSAtom* jsatom);
 
  public:
   explicit WellKnownParserAtoms(JSContext* cx) : entrySet_(cx) {}
 
   bool init(JSContext* cx);
 
   template <typename CharT>
   const ParserAtom* lookupChar16Seq(InflatedChar16Sequence<CharT> seq) const;
--- a/js/src/frontend/TokenStream.cpp
+++ b/js/src/frontend/TokenStream.cpp
@@ -28,16 +28,17 @@
 #include <type_traits>
 #include <utility>
 
 #include "jsexn.h"
 #include "jsnum.h"
 
 #include "frontend/BytecodeCompiler.h"
 #include "frontend/Parser.h"
+#include "frontend/ParserAtom.h"
 #include "frontend/ReservedWords.h"
 #include "js/CharacterEncoding.h"
 #include "js/RegExpFlags.h"  // JS::RegExpFlags
 #include "js/UniquePtr.h"
 #include "util/StringBuffer.h"
 #include "util/Unicode.h"
 #include "vm/FrameIter.h"  // js::{,NonBuiltin}FrameIter
 #include "vm/HelperThreads.h"
@@ -120,40 +121,37 @@ no_match:
 }
 
 template <>
 MOZ_ALWAYS_INLINE const ReservedWordInfo* FindReservedWord<Utf8Unit>(
     const Utf8Unit* units, size_t length) {
   return FindReservedWord(Utf8AsUnsignedChars(units), length);
 }
 
+template <typename CharT>
 static const ReservedWordInfo* FindReservedWord(
-    JSLinearString* str, js::frontend::NameVisibility* visibility) {
-  JS::AutoCheckCannotGC nogc;
-  if (str->hasLatin1Chars()) {
-    const JS::Latin1Char* chars = str->latin1Chars(nogc);
-    size_t length = str->length();
-    if (length > 0 && chars[0] == '#') {
-      *visibility = js::frontend::NameVisibility::Private;
-      return nullptr;
-    }
-    *visibility = js::frontend::NameVisibility::Public;
-    return FindReservedWord(chars, length);
-  }
-
-  const char16_t* chars = str->twoByteChars(nogc);
-  size_t length = str->length();
+    const CharT* chars, size_t length,
+    js::frontend::NameVisibility* visibility) {
   if (length > 0 && chars[0] == '#') {
     *visibility = js::frontend::NameVisibility::Private;
     return nullptr;
   }
   *visibility = js::frontend::NameVisibility::Public;
   return FindReservedWord(chars, length);
 }
 
+static const ReservedWordInfo* FindReservedWord(
+    JSLinearString* str, js::frontend::NameVisibility* visibility) {
+  JS::AutoCheckCannotGC nogc;
+  if (str->hasLatin1Chars()) {
+    return FindReservedWord(str->latin1Chars(nogc), str->length(), visibility);
+  }
+  return FindReservedWord(str->twoByteChars(nogc), str->length(), visibility);
+}
+
 static uint32_t GetSingleCodePoint(const char16_t** p, const char16_t* end) {
   using namespace js;
 
   uint32_t codePoint;
   if (MOZ_UNLIKELY(unicode::IsLeadSurrogate(**p)) && *p + 1 < end) {
     char16_t lead = **p;
     char16_t maybeTrail = *(*p + 1);
     if (unicode::IsTrailSurrogate(maybeTrail)) {
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -460,16 +460,18 @@ JS_PUBLIC_API bool JS::InitSelfHostedCod
   AutoNoteSingleThreadedRegion anstr;
 
   JSRuntime* rt = cx->runtime();
 
   if (!rt->initializeAtoms(cx)) {
     return false;
   }
 
+  // Initialization of well-known ParserAtoms must happen AFTER
+  // initialization of the coresponding JSAtoms.
   if (!rt->initializeParserAtoms(cx)) {
     return false;
   }
 
 #ifndef JS_CODEGEN_NONE
   if (!rt->createJitRuntime(cx)) {
     return false;
   }