tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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:
Mjs/src/jit/MacroAssembler.cpp | 60+++++++++++++++++++++++++++++++++++++++++++++++++-----------
Mjs/src/jit/MacroAssembler.h | 5+++++
Mmfbt/HashTable.h | 10+++++++---
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)];