commit 76504589695a5c6d65d581795076a0cd4977e34c
parent 25de8c18648c6d6536b9b9379337560c78dffd30
Author: Iain Ireland <iireland@mozilla.com>
Date: Thu, 27 Nov 2025 21:39:55 +0000
Bug 2000328: Add MacroAssembler implementations of hash1/hash2/applyDoubleHash r=jandem
Differential Revision: https://phabricator.services.mozilla.com/D273670
Diffstat:
4 files changed, 83 insertions(+), 0 deletions(-)
diff --git a/js/src/gc/WeakMap.h b/js/src/gc/WeakMap.h
@@ -432,6 +432,10 @@ class WeakMap : public WeakMapBase {
size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf);
+ static size_t offsetOfHashShift() {
+ return offsetof(WeakMap, map_) + UnbarrieredMap::offsetOfHashShift();
+ }
+
protected:
inline void assertMapIsSameZoneWithValue(const BarrieredValue& v);
diff --git a/js/src/jit/MacroAssembler.cpp b/js/src/jit/MacroAssembler.cpp
@@ -10510,6 +10510,57 @@ void MacroAssembler::prepareHashMFBT(Register hashCode, bool alreadyScrambled) {
and32(Imm32(~CollisionBit), hashCode);
}
+template <typename Table>
+void MacroAssembler::computeHash1MFBT(Register hashTable, Register hashCode,
+ Register hash1, Register scratch) {
+ // Inline implementation of |mozilla::HashTable::hash1|
+ // return aHash0 >> hashShift();
+ move32(hashCode, hash1);
+ load8ZeroExtend(Address(hashTable, Table::offsetOfHashShift()), scratch);
+ flexibleRshift32(scratch, hash1);
+}
+
+template void MacroAssembler::computeHash1MFBT<WeakMapObject::Map>(
+ Register hashTable, Register hashCode, Register hash1, Register scratch);
+
+template <typename Table>
+void MacroAssembler::computeHash2MFBT(Register hashTable, Register hashCode,
+ Register hash2, Register sizeMask,
+ Register scratch) {
+ // Inline implementation of |mozilla::detail::HashTable::hash2|
+
+ // Load hashShift into sizeMask
+ load8ZeroExtend(Address(hashTable, Table::offsetOfHashShift()), sizeMask);
+
+ // uint32_t sizeLog2 = kHashNumberBits - hashShift();
+ move32(Imm32(kHashNumberBits), scratch);
+ sub32(sizeMask, scratch);
+
+ // DoubleHash dh = {((aCurKeyHash << sizeLog2) >> hashShift()) | 1,
+ move32(hashCode, hash2);
+ flexibleLshift32(scratch, hash2);
+ flexibleRshift32(sizeMask, hash2);
+ or32(Imm32(1), hash2);
+
+ // sizeMask = (HashNumber(1) << sizeLog2) - 1};
+ move32(Imm32(1), sizeMask);
+ flexibleLshift32(scratch, sizeMask);
+ sub32(Imm32(1), sizeMask);
+}
+
+template void MacroAssembler::computeHash2MFBT<WeakMapObject::Map>(
+ Register hashTable, Register hashCode, Register hash2, Register sizeMask,
+ Register scratch);
+
+void MacroAssembler::applyDoubleHashMFBT(Register hash1, Register hash2,
+ Register sizeMask) {
+ // Inline implementation of |mozilla::detail::HashTable::applyDoubleHash|
+
+ // return WrappingSubtract(aHash1, aDoubleHash.mHash2) & aDoubleHash.mSizeMask
+ sub32(hash2, hash1);
+ and32(sizeMask, hash1);
+}
+
// Can't push large frames blindly on windows, so we must touch frame memory
// incrementally, with no more than 4096 - 1 bytes between touches.
//
diff --git a/js/src/jit/MacroAssembler.h b/js/src/jit/MacroAssembler.h
@@ -5447,6 +5447,13 @@ class MacroAssembler : public MacroAssemblerSpecific {
// Helper functions used to implement mozilla::HashTable lookup inline
// in jitcode.
void prepareHashMFBT(Register hashCode, bool alreadyScrambled);
+ template <typename Table>
+ void computeHash1MFBT(Register hashTable, Register hashCode, Register hash1,
+ Register scratch);
+ template <typename Table>
+ void computeHash2MFBT(Register hashTable, Register hashCode, Register hash2,
+ Register sizeMask, Register scratch);
+ void applyDoubleHashMFBT(Register hash1, Register hash2, Register sizeMask);
private:
enum class IsBigInt { No, Yes, Maybe };
diff --git a/mfbt/HashTable.h b/mfbt/HashTable.h
@@ -81,6 +81,7 @@
#include "mozilla/Assertions.h"
#include "mozilla/Attributes.h"
#include "mozilla/Casting.h"
+#include "mozilla/EndianUtils.h"
#include "mozilla/HashFunctions.h"
#include "mozilla/MathAlgorithms.h"
#include "mozilla/Maybe.h"
@@ -424,6 +425,10 @@ class MOZ_STANDALONE_DEBUG HashMap {
using Range = typename Impl::Range;
using Enum = typename Impl::Enum;
Range all() const { return mImpl.all(); }
+
+ static size_t offsetOfHashShift() {
+ return offsetof(HashMap, mImpl) + Impl::offsetOfHashShift();
+ }
};
//---------------------------------------------------------------------------
@@ -2331,6 +2336,22 @@ class MOZ_STANDALONE_DEBUG HashTable : private AllocPolicy {
rekeyWithoutRehash(aPtr, aLookup, aKey);
infallibleRehashIfOverloaded();
}
+
+ static size_t offsetOfHashShift() {
+ static_assert(sHashShiftBits == 8,
+ "callers assume hash shift is stored in a byte");
+ // The hash shift is stored in the least significant bits of
+ // mGenAndHashShift. On little-endian platforms, this is the
+ // same offset as mGenAndHashShift itself. On big-endian platforms,
+ // we have to add an additional offset to point to the last byte.
+ // (Or we would if we had JIT support for any big-endian platforms.)
+#if MOZ_BIG_ENDIAN()
+ return offsetof(HashTable, mGenAndHashShift) + sizeof(mGenAndHashShift) -
+ sizeof(uint8_t);
+#else
+ return offsetof(HashTable, mGenAndHashShift);
+#endif
+ }
};
} // namespace detail