Bug 1555387 - Part 1: Move TableIdentity out of HuffmanDictionary. r=Yoric
authorTooru Fujisawa <arai_a@mac.com>
Fri, 22 Nov 2019 14:40:02 +0000
changeset 503367 0983a81c46c52a2681112fedb286b739c92f482b
parent 503366 05b9bea262ae7af3789859785b362f5f7e9facbf
child 503368 32906323feef46004cbe87c420a56578e5190798
push id36833
push userbtara@mozilla.com
push dateFri, 22 Nov 2019 21:40:53 +0000
treeherdermozilla-central@2c912e46295e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersYoric
bugs1555387
milestone72.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 1555387 - Part 1: Move TableIdentity out of HuffmanDictionary. r=Yoric TableIdentity is going to be used from multiple classes. Differential Revision: https://phabricator.services.mozilla.com/D52955
js/src/frontend/BinASTTokenReaderContext.cpp
js/src/frontend/BinASTTokenReaderContext.h
--- a/js/src/frontend/BinASTTokenReaderContext.cpp
+++ b/js/src/frontend/BinASTTokenReaderContext.cpp
@@ -469,17 +469,17 @@ class HuffmanPreludeReader {
   4. If the effective type is a monomorphic interface, push all of the
   interface’s fields
   5. Otherwise, push the field onto the stack
   */
 
   // Enqueue an entry to the stack.
   MOZ_MUST_USE JS::Result<Ok> pushValue(NormalizedInterfaceAndField identity,
                                         const List& list) {
-    const auto tableId = HuffmanDictionary::TableIdentity(list.contents_);
+    const auto tableId = TableIdentity(list.contents_);
     if (dictionary_.isUnreachable(tableId)) {
       // Spec:
       // 2. Add the field to the set of visited fields
       dictionary_.setInitializing(tableId);
 
       // Read the lengths immediately.
       MOZ_TRY((readTable<List>(tableId, list)));
     }
@@ -520,17 +520,17 @@ class HuffmanPreludeReader {
 #undef EMIT_CASE
 #undef WRAP_LIST_2
     }
     return Ok();
   }
 
   MOZ_MUST_USE JS::Result<Ok> pushValue(NormalizedInterfaceAndField identity,
                                         const Interface& interface) {
-    const auto tableId = HuffmanDictionary::TableIdentity(identity);
+    const auto tableId = TableIdentity(identity);
     if (dictionary_.isUnreachable(tableId)) {
       // Effectively, an `Interface` is a sum with a single entry.
       auto& table = dictionary_.createTable(tableId);
 
       MOZ_TRY(table.initWithSingleValue(
           cx_, BinASTSymbol::fromKind(BinASTKind(interface.kind_))));
     }
 
@@ -541,17 +541,17 @@ class HuffmanPreludeReader {
   }
 
   // Generic implementation for other cases.
   template <class Entry>
   MOZ_MUST_USE JS::Result<Ok> pushValue(NormalizedInterfaceAndField identity,
                                         const Entry& entry) {
     // Spec:
     // 1. If the field is in the set of visited contexts, stop.
-    const auto tableId = HuffmanDictionary::TableIdentity(identity);
+    const auto tableId = TableIdentity(identity);
     if (!dictionary_.isUnreachable(tableId)) {
       // Entry already initialized/initializing.
       return Ok();
     }
 
     // Spec:
     // 2. Add the field to the set of visited fields
     dictionary_.setInitializing(tableId);
@@ -818,32 +818,31 @@ class HuffmanPreludeReader {
     auxStorageLength_.clear();
     return Ok();
   }
 
   // Single-argument version: lookup the table using `dictionary_.table`
   // then proceed as three-arguments version.
   template <typename Entry>
   MOZ_MUST_USE JS::Result<Ok> readTable(Entry entry) {
-    const auto tableId = HuffmanDictionary::TableIdentity(entry.identity_);
+    const auto tableId = TableIdentity(entry.identity_);
     if (MOZ_UNLIKELY(!dictionary_.isInitializing(tableId))) {
       // We're attempting to re-read a table that has already been read.
       // FIXME: Shouldn't this be a MOZ_CRASH?
       return raiseDuplicateTableError(entry.identity_);
     }
 
     return readTable<Entry>(tableId, entry);
   }
 
   // Two-arguments version: pass table identity explicitly. Generally called
   // from single-argument version, but may be called manually, e.g. for list
   // lengths.
   template <typename Entry>
-  MOZ_MUST_USE JS::Result<Ok> readTable(
-      HuffmanDictionary::TableIdentity tableId, Entry entry) {
+  MOZ_MUST_USE JS::Result<Ok> readTable(TableIdentity tableId, Entry entry) {
     uint8_t headerByte;
     MOZ_TRY_VAR(headerByte, reader_.readByte<Compression::No>());
     switch (headerByte) {
       case TableHeader::SingleValue: {
         auto& table = dictionary_.createTable(tableId);
 
         // The table contains a single value.
         MOZ_TRY((readSingleValueTable<Entry>(table, entry)));
@@ -913,17 +912,17 @@ class HuffmanPreludeReader {
     MOZ_MUST_USE JS::Result<Ok> operator()(const MaybeInterface& entry) {
       // First, we need a table to determine whether the value is `null`.
       MOZ_TRY((owner.readTable<MaybeInterface>(entry)));
 
       // Then, if the table contains `true`, we need the fields of the
       // interface.
       // FIXME: readTable could return a reference to the table, eliminating an
       // array lookup.
-      const auto tableId = HuffmanDictionary::TableIdentity(entry.identity_);
+      const auto tableId = TableIdentity(entry.identity_);
       if (owner.dictionary_.isUnreachable(tableId)) {
         return Ok();
       }
 
       const auto& table = owner.dictionary_.getTable(tableId);
       if (!table.isMaybeInterfaceAlwaysNull()) {
         MOZ_TRY(owner.pushFields(entry.kind_));
       }
@@ -935,17 +934,17 @@ class HuffmanPreludeReader {
     MOZ_MUST_USE JS::Result<Ok> operator()(const Sum& entry) {
       // First, we need a table to determine which values are present.
       MOZ_TRY((owner.readTable<Sum>(entry)));
 
       // Now, walk the table to enqueue each value if necessary.
       // FIXME: readTable could return a reference to the table, eliminating an
       // array lookup.
 
-      const auto tableId = HuffmanDictionary::TableIdentity(entry.identity_);
+      const auto tableId = TableIdentity(entry.identity_);
       if (owner.dictionary_.isInitializing(tableId)) {
         return Ok();
       }
 
       auto index = entry.identity_;
       const auto& table = owner.dictionary_.getTable(tableId);
       for (auto iter : table) {
         MOZ_TRY(owner.pushValue(index, Interface(index, iter->toKind())));
@@ -958,17 +957,17 @@ class HuffmanPreludeReader {
     // `FOR_EACH_BIN_INTERFACE_IN_SUM_*`.
     MOZ_MUST_USE JS::Result<Ok> operator()(const MaybeSum& entry) {
       // First, we need a table to determine which values are present.
       MOZ_TRY((owner.readTable<MaybeSum>(entry)));
 
       // Now, walk the table to enqueue each value if necessary.
       // FIXME: readTable could return a reference to the table, eliminating an
       // array lookup.
-      const auto tableId = HuffmanDictionary::TableIdentity(entry.identity_);
+      const auto tableId = TableIdentity(entry.identity_);
       if (owner.dictionary_.isUnreachable(tableId)) {
         return Ok();
       }
 
       auto index = entry.identity_;
       const auto& table = owner.dictionary_.getTable(tableId);
       for (auto iter : table) {
         MOZ_TRY(owner.pushValue(index, Interface(index, iter->toKind())));
@@ -1323,35 +1322,33 @@ struct ExtractBinASTInterfaceAndFieldMat
       const BinASTTokenReaderBase::RootContext&) {
     MOZ_CRASH("The root context has no interface/field");
   }
 };
 
 JS::Result<BinASTKind> BinASTTokenReaderContext::readTagFromTable(
     const BinASTInterfaceAndField& identity) {
   // Extract the table.
-  const auto tableId =
-      HuffmanDictionary::TableIdentity(NormalizedInterfaceAndField(identity));
+  const auto tableId = TableIdentity(NormalizedInterfaceAndField(identity));
   const auto& table = dictionary_.getTable(tableId);
   BINJS_MOZ_TRY_DECL(bits_,
                      (bitBuffer.getHuffmanLookup<Compression::No>(*this)));
 
   // We're entering either a single interface or a sum.
   const auto result = table.lookup(bits_);
   if (MOZ_UNLIKELY(!result.isFound())) {
     return raiseInvalidValue();
   }
   bitBuffer.advanceBitBuffer<Compression::No>(result.bitLength());
   return result.value().toKind();
 }
 
 JS::Result<BinASTSymbol> BinASTTokenReaderContext::readFieldFromTable(
     const BinASTInterfaceAndField& identity) {
-  const auto tableId =
-      HuffmanDictionary::TableIdentity(NormalizedInterfaceAndField(identity));
+  const auto tableId = TableIdentity(NormalizedInterfaceAndField(identity));
   if (!dictionary_.isReady(tableId)) {
     return raiseNotInPrelude();
   }
 
   const auto& table = dictionary_.getTable(tableId);
   BINJS_MOZ_TRY_DECL(bits_, bitBuffer.getHuffmanLookup<Compression::No>(*this));
 
   const auto result = table.lookup(bits_);
@@ -1485,17 +1482,17 @@ JS::Result<Ok> BinASTTokenReaderContext:
                                                   const FieldContext& context) {
   // This tuple is the value of the field we're currently reading.
   MOZ_TRY_VAR(tag, readTagFromTable(context.position_));
   return Ok();
 }
 
 JS::Result<Ok> BinASTTokenReaderContext::enterList(uint32_t& items,
                                                    const ListContext& context) {
-  const auto tableId = HuffmanDictionary::TableIdentity(context.content_);
+  const auto tableId = TableIdentity(context.content_);
   const auto& table = dictionary_.getTable(tableId);
   BINJS_MOZ_TRY_DECL(bits_, bitBuffer.getHuffmanLookup<Compression::No>(*this));
   const auto result = table.lookup(bits_);
   if (MOZ_UNLIKELY(!result.isFound())) {
     return raiseInvalidValue();
   }
   bitBuffer.advanceBitBuffer<Compression::No>(result.bitLength());
   items = result.value().toListLength();
--- a/js/src/frontend/BinASTTokenReaderContext.h
+++ b/js/src/frontend/BinASTTokenReaderContext.h
@@ -950,16 +950,38 @@ class TemporaryStorage {
   TemporaryStorage() {}
 
   // Allocate `count` number of `T` items and returns the span to point the
   // allocated items.
   template <typename T>
   JS::Result<mozilla::Span<T>> alloc(JSContext* cx, size_t count);
 };
 
+// Handles the mapping from NormalizedInterfaceAndField and BinASTList to
+// the index inside the list of huffman tables.
+//
+// The mapping from `(Interface, Field) -> index` and `List -> index` is
+// extracted statically from the webidl specs.
+class TableIdentity {
+  size_t index_;
+
+  static const size_t ListIdentityBase = BINAST_INTERFACE_AND_FIELD_LIMIT;
+
+ public:
+  // The maximum number of tables.
+  static const size_t Limit = ListIdentityBase + BINAST_NUMBER_OF_LIST_TYPES;
+
+  explicit TableIdentity(NormalizedInterfaceAndField index)
+      : index_(static_cast<size_t>(index.identity_)) {}
+  explicit TableIdentity(BinASTList list)
+      : index_(static_cast<size_t>(list) + ListIdentityBase) {}
+
+  size_t toIndex() const { return index_; }
+};
+
 // A Huffman dictionary for the current file.
 //
 // A Huffman dictionary consists in a (contiguous) set of Huffman tables
 // to predict field values and a second (contiguous) set of Huffman tables
 // to predict list lengths.
 class HuffmanDictionary {
   // While reading the Huffman prelude, whenever we first encounter a
   // table with `Unreachable` status, we set its status with a `Initializing`
@@ -970,35 +992,16 @@ class HuffmanDictionary {
     Initializing,
     Ready,
   };
 
  public:
   HuffmanDictionary() {}
   ~HuffmanDictionary();
 
-  // Handles the mapping from NormalizedInterfaceAndField and BinASTList to
-  // the index inside the list of huffman tables.
-  class TableIdentity {
-    size_t index_;
-
-    static const size_t ListIdentityBase = BINAST_INTERFACE_AND_FIELD_LIMIT;
-
-   public:
-    // The maximum number of tables.
-    static const size_t Limit = ListIdentityBase + BINAST_NUMBER_OF_LIST_TYPES;
-
-    explicit TableIdentity(NormalizedInterfaceAndField index)
-        : index_(static_cast<size_t>(index.identity_)) {}
-    explicit TableIdentity(BinASTList list)
-        : index_(static_cast<size_t>(list) + ListIdentityBase) {}
-
-    size_t toIndex() const { return index_; }
-  };
-
   bool isUnreachable(TableIdentity i) const {
     return status_[i.toIndex()] == TableStatus::Unreachable;
   }
 
   bool isInitializing(TableIdentity i) const {
     return status_[i.toIndex()] == TableStatus::Initializing;
   }
 
@@ -1043,19 +1046,16 @@ class HuffmanDictionary {
   //     less time if they're stored in contiguous memory, instead of
   //     placed before each table (using `Variant` or `Maybe`)
   //
   // Some tables may be left Unreachable if they represent `(Interface, Field)`
   // pairs or lists that actually do not show up in the file.
   TableStatus status_[TableIdentity::Limit] = {TableStatus::Unreachable};
 
   // Mapping from TableIdentity to the index into tables_.
-  //
-  // The mapping from `(Interface, Field) -> index` and `List -> index` is
-  // extracted statically from the webidl specs.
   uint16_t tableIndices_[TableIdentity::Limit] = {0};
 
   // The next uninitialized table's index in tables_.
   uint16_t nextIndex_ = 0;
 
   // Huffman tables for either:
   //   * `(Interface, Field)` pairs, used to decode the value of
   //     `Interface::Field`.