From 3d77e7effda9360315ab4af330839eb82ed97925 Mon Sep 17 00:00:00 2001 From: John Naylor Date: Thu, 14 Dec 2023 19:41:17 +0700 Subject: [PATCH v9 6/6] Add optional tweak to finalizer For hashing strings, we need to incorporate the length of the input into the final hash when we call the finalizer. This is necessary to pass SMHasher. To reduce the number of places that need to know about this, it seemed best to make the finalizer a void function, and to make the 32-bit reducer able to accept any uint64 input. --- src/backend/catalog/namespace.c | 11 +++++++++-- src/include/common/hashfn_unstable.h | 21 ++++++++++----------- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c index 6bb28aecfc..3a3cb8ef70 100644 --- a/src/backend/catalog/namespace.c +++ b/src/backend/catalog/namespace.c @@ -247,6 +247,7 @@ static bool MatchNamedCall(HeapTuple proctup, int nargs, List *argnames, static inline uint32 spcachekey_hash(SearchPathCacheKey key) { + const char * const start = key.searchPath; const char *buf = key.searchPath; fasthash_state hs; @@ -274,7 +275,10 @@ spcachekey_hash(SearchPathCacheKey key) fasthash_accum(&hs, (const unsigned char *) buf, chunk_len); buf += chunk_len; } - Assert(fasthash_final64(&hs) == h_orig); + + // We passed the length to fasthash_init, so no tweak for assert testing + fasthash_final64(&hs, 0); + Assert(hs.hash == h_orig); buf = key.searchPath; /* reset */ #endif @@ -291,7 +295,10 @@ spcachekey_hash(SearchPathCacheKey key) fasthash_accum(&hs, (const unsigned char *) buf, chunk_len); buf += chunk_len; } - return fasthash_final32(&hs); + + /* pass the length to tweak the final mix */ + fasthash_final64(&hs, buf - start); + return fasthash_reduce32(hs.hash); } static inline bool diff --git a/src/include/common/hashfn_unstable.h b/src/include/common/hashfn_unstable.h index e8ca39fed2..578a4d0a83 100644 --- a/src/include/common/hashfn_unstable.h +++ b/src/include/common/hashfn_unstable.h @@ -53,9 +53,9 @@ typedef struct fasthash_state } fasthash_state; static inline uint64 -fasthash_mix(uint64 h) +fasthash_mix(uint64 h, uint64 tweak) { - h ^= h >> 23; + h ^= (h >> 23) + tweak; h *= 0x2127599bf4325c37; h ^= h >> 47; return h; @@ -64,7 +64,7 @@ fasthash_mix(uint64 h) static inline void fasthash_combine(fasthash_state* hs) { - hs->hash ^= fasthash_mix(hs->accum); + hs->hash ^= fasthash_mix(hs->accum, 0); hs->hash *= 0x880355f21e6d1965; /* reset hash state for next input */ @@ -114,19 +114,18 @@ fasthash_accum(fasthash_state *hs, const unsigned char *k, int len) } -static inline uint64 -fasthash_final64(fasthash_state *hs) +static inline void +fasthash_final64(fasthash_state *hs, uint64 tweak) { - return fasthash_mix(hs->hash); + hs->hash = fasthash_mix(hs->hash, tweak); } static inline uint32 -fasthash_final32(fasthash_state *hs) +fasthash_reduce32(uint64 h) { // the following trick converts the 64-bit hashcode to Fermat // residue, which shall retain information from both the higher // and lower parts of hashcode. - uint64 h = fasthash_final64(hs); return h - (h >> 32); } @@ -145,14 +144,14 @@ fasthash64(const unsigned char * k, int len, uint64 seed) } fasthash_accum(&hs, k, len); - return fasthash_final64(&hs); + fasthash_final64(&hs, 0); + return hs.hash; } static inline uint64 fasthash32(const unsigned char * k, int len, uint64 seed) { - uint64 h = fasthash64(k, len, seed); - return h - (h >> 32); + return fasthash_reduce32(fasthash64(k, len, seed)); } -- 2.43.0