mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-23 04:41:11 +00:00
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:
parent
4bb1a054be
commit
6e1293b5f7
@ -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|.
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user