Bug 1718516 - Fix AddToHash of 64-bits numbers on 32-bits platforms. r=nika,anba

Differential Revision: https://phabricator.services.mozilla.com/D197302
This commit is contained in:
Mike Hommey 2024-01-09 01:48:31 +00:00
parent 4bb1a054be
commit 6e1293b5f7
2 changed files with 15 additions and 25 deletions

View File

@ -7639,18 +7639,7 @@ void MacroAssembler::prepareHashNonGCThing(ValueOperand value, Register result,
move64(value.toRegister64(), r64); move64(value.toRegister64(), r64);
rshift64Arithmetic(Imm32(32), r64); rshift64Arithmetic(Imm32(32), r64);
#else #else
// TODO: This seems like a bug in mozilla::detail::AddUintptrToHash(). move32(value.typeReg(), temp);
// The uint64_t input is first converted to uintptr_t and then back to
// uint64_t. But |uint64_t(uintptr_t(bits))| actually only clears the high
// bits, so this computation:
//
// aValue = uintptr_t(bits)
// v2 = static_cast<uint32_t>(static_cast<uint64_t>(aValue) >> 32)
//
// really just sets |v2 = 0|. And that means the xor-operation in AddU32ToHash
// can be optimized away, because |x ^ 0 = x|.
//
// Filed as bug 1718516.
#endif #endif
// mozilla::WrappingMultiply(kGoldenRatioU32, RotateLeft5(aHash) ^ aValue); // mozilla::WrappingMultiply(kGoldenRatioU32, RotateLeft5(aHash) ^ aValue);
@ -7660,9 +7649,7 @@ void MacroAssembler::prepareHashNonGCThing(ValueOperand value, Register result,
// mozilla::WrappingMultiply(kGoldenRatioU32, RotateLeft5(aHash) ^ aValue); // mozilla::WrappingMultiply(kGoldenRatioU32, RotateLeft5(aHash) ^ aValue);
// with |aHash = <above hash>| and |aValue = v2|. // with |aHash = <above hash>| and |aValue = v2|.
rotateLeft(Imm32(5), result, result); rotateLeft(Imm32(5), result, result);
#ifdef JS_PUNBOX64
xor32(temp, result); xor32(temp, result);
#endif
// Combine |mul32| and |scrambleHashCode| by directly multiplying with // Combine |mul32| and |scrambleHashCode| by directly multiplying with
// |kGoldenRatioU32 * kGoldenRatioU32|. // |kGoldenRatioU32 * kGoldenRatioU32|.

View File

@ -153,17 +153,20 @@ constexpr HashNumber AddU32ToHash(HashNumber aHash, uint32_t aValue) {
} }
/** /**
* AddUintptrToHash takes sizeof(uintptr_t) as a template parameter. * AddUintNToHash takes sizeof(int_type) as a template parameter.
* Changes to these functions need to be propagated to
* MacroAssembler::prepareHashNonGCThing, which inlines them manually for
* the JIT.
*/ */
template <size_t PtrSize> template <size_t Size>
constexpr HashNumber AddUintptrToHash(HashNumber aHash, uintptr_t aValue) { constexpr HashNumber AddUintNToHash(HashNumber aHash, uint64_t aValue) {
return AddU32ToHash(aHash, static_cast<uint32_t>(aValue)); return AddU32ToHash(aHash, static_cast<uint32_t>(aValue));
} }
template <> template <>
inline HashNumber AddUintptrToHash<8>(HashNumber aHash, uintptr_t aValue) { inline HashNumber AddUintNToHash<8>(HashNumber aHash, uint64_t aValue) {
uint32_t v1 = static_cast<uint32_t>(aValue); uint32_t v1 = static_cast<uint32_t>(aValue);
uint32_t v2 = static_cast<uint32_t>(static_cast<uint64_t>(aValue) >> 32); uint32_t v2 = static_cast<uint32_t>(aValue >> 32);
return AddU32ToHash(AddU32ToHash(aHash, v1), v2); return AddU32ToHash(AddU32ToHash(aHash, v1), v2);
} }
@ -196,23 +199,23 @@ template <typename A>
static_assert(sizeof(aA) == sizeof(uintptr_t), "Strange pointer!"); static_assert(sizeof(aA) == sizeof(uintptr_t), "Strange pointer!");
return detail::AddUintptrToHash<sizeof(uintptr_t)>(aHash, uintptr_t(aA)); return detail::AddUintNToHash<sizeof(uintptr_t)>(aHash, uintptr_t(aA));
} }
// We use AddUintptrToHash() for hashing all integral types. 8-byte integral // We use AddUintNToHash() for hashing all integral types. 8-byte integral
// types are treated the same as 64-bit pointers, and smaller integral types are // types are treated the same as 64-bit pointers, and smaller integral types are
// first implicitly converted to 32 bits and then passed to AddUintptrToHash() // first implicitly converted to 32 bits and then passed to AddUintNToHash()
// to be hashed. // to be hashed.
template <typename T, std::enable_if_t<std::is_integral_v<T>, int> = 0> template <typename T, std::enable_if_t<std::is_integral_v<T>, int> = 0>
[[nodiscard]] constexpr HashNumber AddToHash(HashNumber aHash, T aA) { [[nodiscard]] constexpr HashNumber AddToHash(HashNumber aHash, T aA) {
return detail::AddUintptrToHash<sizeof(T)>(aHash, aA); return detail::AddUintNToHash<sizeof(T)>(aHash, aA);
} }
template <typename T, std::enable_if_t<std::is_enum_v<T>, int> = 0> template <typename T, std::enable_if_t<std::is_enum_v<T>, int> = 0>
[[nodiscard]] constexpr HashNumber AddToHash(HashNumber aHash, T aA) { [[nodiscard]] constexpr HashNumber AddToHash(HashNumber aHash, T aA) {
// Hash using AddUintptrToHash with the underlying type of the enum type // Hash using AddUintNToHash with the underlying type of the enum type
using UnderlyingType = typename std::underlying_type<T>::type; using UnderlyingType = typename std::underlying_type<T>::type;
return detail::AddUintptrToHash<sizeof(UnderlyingType)>( return detail::AddUintNToHash<sizeof(UnderlyingType)>(
aHash, static_cast<UnderlyingType>(aA)); aHash, static_cast<UnderlyingType>(aA));
} }