@@ -746,7 +746,6 @@ PLDHashTable::ShallowSizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
746746
747747PLDHashTable::Iterator::Iterator (Iterator&& aOther)
748748 : mTable(aOther.mTable )
749- , mLimit(aOther.mLimit )
750749 , mCurrent(aOther.mCurrent )
751750 , mNexts(aOther.mNexts )
752751 , mNextsLimit(aOther.mNextsLimit )
@@ -755,7 +754,7 @@ PLDHashTable::Iterator::Iterator(Iterator&& aOther)
755754{
756755 // No need to change |mChecker| here.
757756 aOther.mTable = nullptr ;
758- // We don't really have the concept of a null slot, so leave mLimit/ mCurrent.
757+ // We don't really have the concept of a null slot, so leave mCurrent.
759758 aOther.mNexts = 0 ;
760759 aOther.mNextsLimit = 0 ;
761760 aOther.mHaveRemoved = false ;
@@ -764,8 +763,6 @@ PLDHashTable::Iterator::Iterator(Iterator&& aOther)
764763
765764PLDHashTable::Iterator::Iterator (PLDHashTable* aTable)
766765 : mTable(aTable)
767- , mLimit(mTable ->mEntryStore .SlotForIndex(mTable ->Capacity (), mTable->mEntrySize,
768- mTable->Capacity()))
769766 , mCurrent(mTable ->mEntryStore .SlotForIndex(0 , mTable ->mEntrySize ,
770767 mTable ->Capacity ()))
771768 , mNexts(0 )
@@ -787,10 +784,8 @@ PLDHashTable::Iterator::Iterator(PLDHashTable* aTable)
787784 }
788785
789786 // Advance to the first live entry, if there is one.
790- if (!Done ()) {
791- while (IsOnNonLiveEntry ()) {
792- MoveToNextEntry ();
793- }
787+ if (!Done () && IsOnNonLiveEntry ()) {
788+ MoveToNextLiveEntry ();
794789 }
795790}
796791
@@ -813,17 +808,6 @@ PLDHashTable::Iterator::IsOnNonLiveEntry() const
813808 return !mCurrent .IsLive ();
814809}
815810
816- MOZ_ALWAYS_INLINE void
817- PLDHashTable::Iterator::MoveToNextEntry ()
818- {
819- mCurrent .Next (mEntrySize );
820- if (mCurrent == mLimit ) {
821- // We wrapped around. Possible due to chaos mode.
822- mCurrent = mTable ->mEntryStore .SlotForIndex (0 , mEntrySize ,
823- mTable ->CapacityFromHashShift ());
824- }
825- }
826-
827811void
828812PLDHashTable::Iterator::Next ()
829813{
@@ -833,12 +817,46 @@ PLDHashTable::Iterator::Next()
833817
834818 // Advance to the next live entry, if there is one.
835819 if (!Done ()) {
836- do {
837- MoveToNextEntry ();
838- } while (IsOnNonLiveEntry ());
820+ MoveToNextLiveEntry ();
839821 }
840822}
841823
824+ MOZ_ALWAYS_INLINE void
825+ PLDHashTable::Iterator::MoveToNextLiveEntry ()
826+ {
827+ // Chaos mode requires wraparound to cover all possible entries, so we can't
828+ // simply move to the next live entry and stop when we hit the end of the
829+ // entry store. But we don't want to introduce extra branches into our inner
830+ // loop. So we are going to exploit the structure of the entry store in this
831+ // method to implement an efficient inner loop.
832+ //
833+ // The idea is that since we are really only iterating through the stored
834+ // hashes and because we know that there are a power-of-two number of
835+ // hashes, we can use masking to implement the wraparound for us. This
836+ // method does have the downside of needing to recalculate where the
837+ // associated entry is once we've found it, but that seems OK.
838+
839+ // Our current slot and its associated hash.
840+ Slot slot = mCurrent ;
841+ PLDHashNumber* p = slot.HashPtr ();
842+ const uint32_t capacity = mTable ->CapacityFromHashShift ();
843+ const uint32_t mask = capacity - 1 ;
844+ auto hashes = reinterpret_cast <PLDHashNumber*>(mTable ->mEntryStore .Get ());
845+ uint32_t slotIndex = p - hashes;
846+
847+ do {
848+ slotIndex = (slotIndex + 1 ) & mask;
849+ } while (!Slot::IsLiveHash (hashes[slotIndex]));
850+
851+ // slotIndex now indicates where a live slot is. Rematerialize the entry
852+ // and the slot.
853+ auto entries = reinterpret_cast <char *>(&hashes[capacity]);
854+ char * entryPtr = entries + slotIndex * mEntrySize ;
855+ auto entry = reinterpret_cast <PLDHashEntryHdr*>(entryPtr);
856+
857+ mCurrent = Slot (entry, &hashes[slotIndex]);
858+ }
859+
842860void
843861PLDHashTable::Iterator::Remove ()
844862{
0 commit comments