summaryrefslogtreecommitdiff
path: root/src/support/hash.h
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2024-11-04 12:56:46 -0800
committerGitHub <noreply@github.com>2024-11-04 12:56:46 -0800
commitc35e9871697b0b103228a96e9e79066e762d5e22 (patch)
treebcd8ae8f24e0b7e62ca309f35513553b727ee112 /src/support/hash.h
parent9f496abc5cf1ddbca8c8a4f4e740c412588708ef (diff)
downloadbinaryen-c35e9871697b0b103228a96e9e79066e762d5e22.tar.gz
binaryen-c35e9871697b0b103228a96e9e79066e762d5e22.tar.bz2
binaryen-c35e9871697b0b103228a96e9e79066e762d5e22.zip
Make 32-bit hashing identical to 64-bit in TypeSSA (#7048)
This is NFC on 64-bit systems but noticeable on 32. Also remove the 32-bit path in hash_combine. That isn't necessary for this fix, but it makes the code simpler and also makes debugging between systems simpler. It might also avoid problems in future cases, if we are lucky. The only cost is perhaps a slight slowdown on 32-bit systems, which seems worth it. Fixes #7046
Diffstat (limited to 'src/support/hash.h')
-rw-r--r--src/support/hash.h22
1 files changed, 12 insertions, 10 deletions
diff --git a/src/support/hash.h b/src/support/hash.h
index b99902616..ba1001d66 100644
--- a/src/support/hash.h
+++ b/src/support/hash.h
@@ -28,29 +28,31 @@ template<typename T> inline std::size_t hash(const T& value) {
}
// Combines two digests into the first digest. Use instead of `rehash` if
-// `otherDigest` is another digest and not a `size_t` value. This is also useful
-// when you want deterministic behavior across systems, as this method does not
-// call std::hash, so it does not depend on the behavior of the local machine's
-// C++ standard library implementation.
+// `otherDigest` is another digest. This is also deterministic, aside from
+// possible differences in size_t (see deterministic_hash_combine, below).
inline void hash_combine(std::size_t& digest, const std::size_t otherDigest) {
// see: boost/container_hash/hash.hpp
// The constant is the N-bits reciprocal of the golden ratio:
// phi = (1 + sqrt(5)) / 2
-#if SIZE_MAX == UINT64_MAX
// trunc(2^64 / phi) = 0x9e3779b97f4a7c15
digest ^= otherDigest + 0x9e3779b97f4a7c15 + (digest << 12) + (digest >> 4);
-#else
- // trunc(2^32 / phi) = 0x9e3779b9
- digest ^= otherDigest + 0x9e3779b9 + (digest << 6) + (digest >> 2);
-#endif
}
// Hashes `value` and combines the resulting digest into the existing digest.
-// Use instead of `hash_combine` if `value` is not another digest.
+// Use instead of `hash_combine` if `value` is not another digest (i.e., it
+// needs to be hashed first).
template<typename T> inline void rehash(std::size_t& digest, const T& value) {
hash_combine(digest, hash(value));
}
+// Similar to hash_combine, but guaranteed to produce the exact same results on
+// all machines, even ones where size_t differs. This is essentially identical
+// to hash_combine, but the types are all uint64_t.
+inline void deterministic_hash_combine(uint64_t& digest,
+ const uint64_t otherDigest) {
+ digest ^= otherDigest + 0x9e3779b97f4a7c15 + (digest << 12) + (digest >> 4);
+}
+
} // namespace wasm
namespace std {