Bug 1248289 - Part 0: Change OrderedHashTable::Range::ht member from a reference to a pointer to use offsetof. r=sfink
authorTooru Fujisawa <arai_a@mac.com>
Sat, 19 Mar 2016 02:41:44 +0900
changeset 289376 4fb38ce47512c913ec5b15ed85a383a7caab65e9
parent 289375 ce85118f049d36cf875b3228495b993473717583
child 289377 a3d994656b2bf373d1deb2cc13f559a4dcf15747
push id30102
push userryanvm@gmail.com
push dateSat, 19 Mar 2016 15:23:17 +0000
treeherdermozilla-central@720fb3d55e28 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssfink
bugs1248289
milestone48.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 1248289 - Part 0: Change OrderedHashTable::Range::ht member from a reference to a pointer to use offsetof. r=sfink
js/src/ds/OrderedHashTable.h
--- a/js/src/ds/OrderedHashTable.h
+++ b/js/src/ds/OrderedHashTable.h
@@ -279,54 +279,56 @@ class OrderedHashTable
      *         r.popFront();
      *         // ...do things that might modify map...
      *     }
      */
     class Range
     {
         friend class OrderedHashTable;
 
-        OrderedHashTable& ht;
+        // Cannot be a reference since we need to be able to do
+        // |offsetof(Range, ht)|.
+        OrderedHashTable* ht;
 
-        /* The index of front() within ht.data. */
+        /* The index of front() within ht->data. */
         uint32_t i;
 
         /*
-         * The number of nonempty entries in ht.data to the left of front().
+         * The number of nonempty entries in ht->data to the left of front().
          * This is used when the table is resized or compacted.
          */
         uint32_t count;
 
         /*
          * Links in the doubly-linked list of active Ranges on ht.
          *
          * prevp points to the previous Range's .next field;
-         *   or to ht.ranges if this is the first Range in the list.
+         *   or to ht->ranges if this is the first Range in the list.
          * next points to the next Range;
          *   or nullptr if this is the last Range in the list.
          *
          * Invariant: *prevp == this.
          */
         Range** prevp;
         Range* next;
 
         /*
          * Create a Range over all the entries in ht.
-         * (This is private on purpose. End users must use ht.all().)
+         * (This is private on purpose. End users must use ht->all().)
          */
-        explicit Range(OrderedHashTable& ht) : ht(ht), i(0), count(0), prevp(&ht.ranges), next(ht.ranges) {
+        explicit Range(OrderedHashTable* ht) : ht(ht), i(0), count(0), prevp(&ht->ranges), next(ht->ranges) {
             *prevp = this;
             if (next)
                 next->prevp = &next;
             seek();
         }
 
       public:
         Range(const Range& other)
-            : ht(other.ht), i(other.i), count(other.count), prevp(&ht.ranges), next(ht.ranges)
+            : ht(other.ht), i(other.i), count(other.count), prevp(&ht->ranges), next(ht->ranges)
         {
             *prevp = this;
             if (next)
                 next->prevp = &next;
         }
 
         ~Range() {
             *prevp = next;
@@ -334,17 +336,17 @@ class OrderedHashTable
                 next->prevp = prevp;
         }
 
       private:
         // Prohibit copy assignment.
         Range& operator=(const Range& other) = delete;
 
         void seek() {
-            while (i < ht.dataLength && Ops::isEmpty(Ops::getKey(ht.data[i].element)))
+            while (i < ht->dataLength && Ops::isEmpty(Ops::getKey(ht->data[i].element)))
                 i++;
         }
 
         /*
          * The hash table calls this when an entry is removed.
          * j is the index of the removed entry.
          */
         void onRemove(uint32_t j) {
@@ -380,91 +382,91 @@ class OrderedHashTable
             MOZ_ASSERT(valid());
             prevp = &next;
             next = this;
         }
 
       public:
         bool empty() const {
             MOZ_ASSERT(valid());
-            return i >= ht.dataLength;
+            return i >= ht->dataLength;
         }
 
         /*
          * Return the first element in the range. This must not be called if
          * this->empty().
          *
          * Warning: Removing an entry from the table also removes it from any
          * live Ranges, and a Range can become empty that way, rendering
          * front() invalid. If in doubt, check empty() before calling front().
          */
         T& front() {
             MOZ_ASSERT(valid());
             MOZ_ASSERT(!empty());
-            return ht.data[i].element;
+            return ht->data[i].element;
         }
 
         /*
          * Remove the first element from this range.
          * This must not be called if this->empty().
          *
          * Warning: Removing an entry from the table also removes it from any
          * live Ranges, and a Range can become empty that way, rendering
          * popFront() invalid. If in doubt, check empty() before calling
          * popFront().
          */
         void popFront() {
             MOZ_ASSERT(valid());
             MOZ_ASSERT(!empty());
-            MOZ_ASSERT(!Ops::isEmpty(Ops::getKey(ht.data[i].element)));
+            MOZ_ASSERT(!Ops::isEmpty(Ops::getKey(ht->data[i].element)));
             count++;
             i++;
             seek();
         }
 
         /*
          * Change the key of the front entry.
          *
          * This calls Ops::hash on both the current key and the new key.
          * Ops::hash on the current key must return the same hash code as
          * when the entry was added to the table.
          */
         void rekeyFront(const Key& k) {
             MOZ_ASSERT(valid());
-            Data& entry = ht.data[i];
-            HashNumber oldHash = prepareHash(Ops::getKey(entry.element)) >> ht.hashShift;
-            HashNumber newHash = prepareHash(k) >> ht.hashShift;
+            Data& entry = ht->data[i];
+            HashNumber oldHash = prepareHash(Ops::getKey(entry.element)) >> ht->hashShift;
+            HashNumber newHash = prepareHash(k) >> ht->hashShift;
             Ops::setKey(entry.element, k);
             if (newHash != oldHash) {
                 // Remove this entry from its old hash chain. (If this crashes
                 // reading nullptr, it would mean we did not find this entry on
                 // the hash chain where we expected it. That probably means the
                 // key's hash code changed since it was inserted, breaking the
                 // hash code invariant.)
-                Data** ep = &ht.hashTable[oldHash];
+                Data** ep = &ht->hashTable[oldHash];
                 while (*ep != &entry)
                     ep = &(*ep)->chain;
                 *ep = entry.chain;
 
                 // Add it to the new hash chain. We could just insert it at the
                 // beginning of the chain. Instead, we do a bit of work to
                 // preserve the invariant that hash chains always go in reverse
                 // insertion order (descending memory order). No code currently
                 // depends on this invariant, so it's fine to kill it if
                 // needed.
-                ep = &ht.hashTable[newHash];
+                ep = &ht->hashTable[newHash];
                 while (*ep && *ep > &entry)
                     ep = &(*ep)->chain;
                 entry.chain = *ep;
                 *ep = &entry;
             }
         }
     };
 
-    Range all() { return Range(*this); }
+    Range all() { return Range(this); }
 
     /*
      * Change the value of the given key.
      *
      * This calls Ops::hash on both the current key and the new key.
      * Ops::hash on the current key must return the same hash code as
      * when the entry was added to the table.
      */