commit 8c89daa76c67f0ecb039202c77b3e619052d660a
parent 095424a9b5152a1b1e327ca3ca7d33ad1be26cea
Author: Iain Ireland <iireland@mozilla.com>
Date: Thu, 27 Nov 2025 21:39:54 +0000
Bug 2000328: Implement prepareHashMFBT r=jandem
Differential Revision: https://phabricator.services.mozilla.com/D273668
Diffstat:
3 files changed, 61 insertions(+), 14 deletions(-)
diff --git a/js/src/jit/MacroAssembler.cpp b/js/src/jit/MacroAssembler.cpp
@@ -9936,17 +9936,13 @@ void MacroAssembler::scrambleHashCode(Register result) {
mul32(Imm32(mozilla::kGoldenRatioU32), result);
}
-void MacroAssembler::prepareHashNonGCThing(ValueOperand value, Register result,
- Register temp) {
- // Inline implementation of |OrderedHashTableImpl::prepareHash()| and
- // |mozilla::HashGeneric(v.asRawBits())|.
-
-#ifdef DEBUG
- Label ok;
- branchTestGCThing(Assembler::NotEqual, value, &ok);
- assumeUnreachable("Unexpected GC thing");
- bind(&ok);
-#endif
+void MacroAssembler::hashAndScrambleValue(ValueOperand value, Register result,
+ Register temp) {
+ // Inline implementation of:
+ // mozilla::ScrambleHashCode(mozilla::HashGeneric(v.asRawBits()))
+ // Note that this uses the raw bits, which will change if a GC thing moves.
+ // This function should only be used for non-GC things, or in cases where
+ // moving GC things are handled specially (eg WeakMapObject).
// uint32_t v1 = static_cast<uint32_t>(aValue);
#ifdef JS_PUNBOX64
@@ -9982,6 +9978,21 @@ void MacroAssembler::prepareHashNonGCThing(ValueOperand value, Register result,
mul32(Imm32(mozilla::kGoldenRatioU32 * mozilla::kGoldenRatioU32), result);
}
+void MacroAssembler::prepareHashNonGCThing(ValueOperand value, Register result,
+ Register temp) {
+ // Inline implementation of |OrderedHashTableImpl::prepareHash()| and
+ // |mozilla::HashGeneric(v.asRawBits())|.
+
+#ifdef DEBUG
+ Label ok;
+ branchTestGCThing(Assembler::NotEqual, value, &ok);
+ assumeUnreachable("Unexpected GC thing");
+ bind(&ok);
+#endif
+
+ hashAndScrambleValue(value, result, temp);
+}
+
void MacroAssembler::prepareHashString(Register str, Register result,
Register temp) {
// Inline implementation of |OrderedHashTableImpl::prepareHash()| and
@@ -10472,6 +10483,33 @@ void MacroAssembler::loadMapObjectSize(Register mapObj, Register result) {
loadOrderedHashTableCount<MapObject>(mapObj, result);
}
+void MacroAssembler::prepareHashMFBT(Register hashCode, bool alreadyScrambled) {
+ // Inline implementation of |mozilla::HashTable::prepareHash()|.
+ static_assert(sizeof(HashNumber) == sizeof(uint32_t));
+
+ // In some cases scrambling can be more efficiently folded into the
+ // computation of the hash itself.
+ if (!alreadyScrambled) {
+ // HashNumber keyHash = ScrambleHashCode(aInputHash);
+ scrambleHashCode(hashCode);
+ }
+
+ const mozilla::HashNumber RemovedKey = mozilla::detail::kHashTableRemovedKey;
+ const mozilla::HashNumber CollisionBit =
+ mozilla::detail::kHashTableCollisionBit;
+
+ // Avoid reserved hash codes:
+ // if (!isLiveHash(keyHash)) {
+ Label isLive;
+ branch32(Assembler::Above, hashCode, Imm32(RemovedKey), &isLive);
+ // keyHash -= (sRemovedKey + 1);
+ sub32(Imm32(RemovedKey + 1), hashCode);
+ bind(&isLive);
+
+ // return keyHash & ~sCollisionBit;
+ and32(Imm32(~CollisionBit), hashCode);
+}
+
// 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
@@ -5430,6 +5430,7 @@ class MacroAssembler : public MacroAssemblerSpecific {
void scrambleHashCode(Register result);
public:
+ void hashAndScrambleValue(ValueOperand value, Register result, Register temp);
void prepareHashNonGCThing(ValueOperand value, Register result,
Register temp);
void prepareHashString(Register str, Register result, Register temp);
@@ -5443,6 +5444,10 @@ class MacroAssembler : public MacroAssemblerSpecific {
Register temp1, Register temp2, Register temp3,
Register temp4);
+ // Helper functions used to implement mozilla::HashTable lookup inline
+ // in jitcode.
+ void prepareHashMFBT(Register hashCode, bool alreadyScrambled);
+
private:
enum class IsBigInt { No, Yes, Maybe };
diff --git a/mfbt/HashTable.h b/mfbt/HashTable.h
@@ -982,6 +982,10 @@ class HashMapEntry {
namespace detail {
+static const HashNumber kHashTableFreeKey = 0;
+static const HashNumber kHashTableRemovedKey = 1;
+static const HashNumber kHashTableCollisionBit = 1;
+
template <class T, class HashPolicy, class AllocPolicy>
class HashTable;
@@ -1057,9 +1061,9 @@ class HashTableEntry {
"subsequent N*2 T values must not require more than an even "
"number of HashNumbers provides");
- static const HashNumber sFreeKey = 0;
- static const HashNumber sRemovedKey = 1;
- static const HashNumber sCollisionBit = 1;
+ static const HashNumber sFreeKey = kHashTableFreeKey;
+ static const HashNumber sRemovedKey = kHashTableRemovedKey;
+ static const HashNumber sCollisionBit = kHashTableCollisionBit;
alignas(NonConstT) unsigned char mValueData[sizeof(NonConstT)];