Bug 1593922 - Add HuffmanDictionary.tableIndices_ to populate HuffmanDictionary.tables_ from the beginning. r=Yoric
authorTooru Fujisawa <arai_a@mac.com>
Fri, 22 Nov 2019 14:38:51 +0000
changeset 503364 ba7c82709e9f28a58a21cbc699cd89beeb804d28
parent 503363 fd82074eab1d8d4642d816436c166267350ecf6f
child 503365 bfb371be51b33a6dd6aea0bc4b7ef8ac6b090937
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
bugs1593922, 1555387
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 1593922 - Add HuffmanDictionary.tableIndices_ to populate HuffmanDictionary.tables_ from the beginning. r=Yoric This is preparation for bug 1555387, to store initialized GenericHuffmanTable instances in contiguous space. Differential Revision: https://phabricator.services.mozilla.com/D52952
js/src/frontend/BinASTTokenReaderContext.cpp
js/src/frontend/BinASTTokenReaderContext.h
--- a/js/src/frontend/BinASTTokenReaderContext.cpp
+++ b/js/src/frontend/BinASTTokenReaderContext.cpp
@@ -2784,20 +2784,18 @@ HuffmanPreludeReader::readSingleValueTab
     GenericHuffmanTable& table, const UnsignedLong& entry) {
   BINJS_MOZ_TRY_DECL(index, reader_.readUnpackedLong());
   MOZ_TRY(
       table.initWithSingleValue(cx_, BinASTSymbol::fromUnsignedLong(index)));
   return Ok();
 }
 
 HuffmanDictionary::~HuffmanDictionary() {
-  for (size_t i = 0; i < TableIdentity::Limit; i++) {
-    if (status_[i] == TableStatus::Ready) {
-      table(i).~GenericHuffmanTable();
-    }
+  for (size_t i = 0; i < nextIndex_; i++) {
+    tableAtIndex(i).~GenericHuffmanTable();
   }
 }
 
 uint32_t HuffmanLookup::leadingBits(const uint8_t aBitLength) const {
   MOZ_ASSERT(aBitLength <= bitLength_);
   const uint32_t result = (aBitLength == 0)
                               ? 0  // Shifting a uint32_t by 32 bits is UB.
                               : bits_ >> uint32_t(bitLength_ - aBitLength);
--- a/js/src/frontend/BinASTTokenReaderContext.h
+++ b/js/src/frontend/BinASTTokenReaderContext.h
@@ -935,61 +935,78 @@ class HuffmanDictionary {
   void setReady(TableIdentity i) { status_[i.toIndex()] = TableStatus::Ready; }
 
  public:
   GenericHuffmanTable& createTable(TableIdentity i) {
     MOZ_ASSERT(isUnreachable(i) || isInitializing(i));
 
     setReady(i);
 
-    auto& t = table(i.toIndex());
+    tableIndices_[i.toIndex()] = nextIndex_++;
+
+    auto& t = table(i);
     new (mozilla::KnownNotNull, &t) GenericHuffmanTable();
 
     return t;
   }
 
   const GenericHuffmanTable& getTable(TableIdentity i) const {
     MOZ_ASSERT(isReady(i));
-    return table(i.toIndex());
+    return table(i);
   }
 
  private:
   // For the following purpose, tables are stored as an array of status
   // and a uninitialized buffer to store an array of tables.
   //
   //   * In most case a single BinAST file doesn't use all tables
   //   * GenericHuffmanTable constructor/destructor costs are not negligible,
   //     and we don't want to call them for unused tables
   //   * Initializing status for whether the table is used or not takes
   //     less time if they're stored in contiguous memory, instead of
   //     placed before each table (using `Variant` or `Maybe`)
   //
-  // Tables with `Ready` status are destructed in HuffmanDictionary destructor.
+  // 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`.
   //   * list lengths
-  // Some entries may be uninitialized if they represent `(Interface, Field)`
-  // pairs or lists that actually do not show up in the file.
   //
-  // The mapping from `(Interface, Field) -> index` and `List -> index` is
-  // extracted statically from the webidl specs.
+  // Tables in [0..nextIndex_] range are initialized.
   //
   // Semantically this is `GenericHuffmanTable tables_[TableIdentity::Limit]`,
   // but items are constructed lazily.
   alignas(GenericHuffmanTable) char tables_[sizeof(GenericHuffmanTable) *
                                             TableIdentity::Limit];
 
-  GenericHuffmanTable& table(size_t i) {
+  GenericHuffmanTable& table(TableIdentity i) {
+    return tableAtIndex(tableIndices_[i.toIndex()]);
+  }
+
+  const GenericHuffmanTable& table(TableIdentity i) const {
+    return tableAtIndex(tableIndices_[i.toIndex()]);
+  }
+
+  GenericHuffmanTable& tableAtIndex(size_t i) {
     return (reinterpret_cast<GenericHuffmanTable*>(tables_))[i];
   }
 
-  const GenericHuffmanTable& table(size_t i) const {
+  const GenericHuffmanTable& tableAtIndex(size_t i) const {
     return (reinterpret_cast<const GenericHuffmanTable*>(tables_))[i];
   }
 };
 
 /**
  * A token reader implementing the "context" serialization format for BinAST.
  *
  * This serialization format, which is also supported by the reference