1*8e33eff8Schristos #ifndef JEMALLOC_INTERNAL_HASH_H 2*8e33eff8Schristos #define JEMALLOC_INTERNAL_HASH_H 3*8e33eff8Schristos 4*8e33eff8Schristos #include "jemalloc/internal/assert.h" 5*8e33eff8Schristos 6*8e33eff8Schristos /* 7*8e33eff8Schristos * The following hash function is based on MurmurHash3, placed into the public 8*8e33eff8Schristos * domain by Austin Appleby. See https://github.com/aappleby/smhasher for 9*8e33eff8Schristos * details. 10*8e33eff8Schristos */ 11*8e33eff8Schristos 12*8e33eff8Schristos /******************************************************************************/ 13*8e33eff8Schristos /* Internal implementation. */ 14*8e33eff8Schristos static inline uint32_t 15*8e33eff8Schristos hash_rotl_32(uint32_t x, int8_t r) { 16*8e33eff8Schristos return ((x << r) | (x >> (32 - r))); 17*8e33eff8Schristos } 18*8e33eff8Schristos 19*8e33eff8Schristos static inline uint64_t 20*8e33eff8Schristos hash_rotl_64(uint64_t x, int8_t r) { 21*8e33eff8Schristos return ((x << r) | (x >> (64 - r))); 22*8e33eff8Schristos } 23*8e33eff8Schristos 24*8e33eff8Schristos static inline uint32_t 25*8e33eff8Schristos hash_get_block_32(const uint32_t *p, int i) { 26*8e33eff8Schristos /* Handle unaligned read. */ 27*8e33eff8Schristos if (unlikely((uintptr_t)p & (sizeof(uint32_t)-1)) != 0) { 28*8e33eff8Schristos uint32_t ret; 29*8e33eff8Schristos 30*8e33eff8Schristos memcpy(&ret, (const uint8_t *)(p + i), sizeof(uint32_t)); 31*8e33eff8Schristos return ret; 32*8e33eff8Schristos } 33*8e33eff8Schristos 34*8e33eff8Schristos return p[i]; 35*8e33eff8Schristos } 36*8e33eff8Schristos 37*8e33eff8Schristos static inline uint64_t 38*8e33eff8Schristos hash_get_block_64(const uint64_t *p, int i) { 39*8e33eff8Schristos /* Handle unaligned read. */ 40*8e33eff8Schristos if (unlikely((uintptr_t)p & (sizeof(uint64_t)-1)) != 0) { 41*8e33eff8Schristos uint64_t ret; 42*8e33eff8Schristos 43*8e33eff8Schristos memcpy(&ret, (const uint8_t *)(p + i), sizeof(uint64_t)); 44*8e33eff8Schristos return ret; 45*8e33eff8Schristos } 46*8e33eff8Schristos 47*8e33eff8Schristos return p[i]; 48*8e33eff8Schristos } 49*8e33eff8Schristos 50*8e33eff8Schristos static inline uint32_t 51*8e33eff8Schristos hash_fmix_32(uint32_t h) { 52*8e33eff8Schristos h ^= h >> 16; 53*8e33eff8Schristos h *= 0x85ebca6b; 54*8e33eff8Schristos h ^= h >> 13; 55*8e33eff8Schristos h *= 0xc2b2ae35; 56*8e33eff8Schristos h ^= h >> 16; 57*8e33eff8Schristos 58*8e33eff8Schristos return h; 59*8e33eff8Schristos } 60*8e33eff8Schristos 61*8e33eff8Schristos static inline uint64_t 62*8e33eff8Schristos hash_fmix_64(uint64_t k) { 63*8e33eff8Schristos k ^= k >> 33; 64*8e33eff8Schristos k *= KQU(0xff51afd7ed558ccd); 65*8e33eff8Schristos k ^= k >> 33; 66*8e33eff8Schristos k *= KQU(0xc4ceb9fe1a85ec53); 67*8e33eff8Schristos k ^= k >> 33; 68*8e33eff8Schristos 69*8e33eff8Schristos return k; 70*8e33eff8Schristos } 71*8e33eff8Schristos 72*8e33eff8Schristos static inline uint32_t 73*8e33eff8Schristos hash_x86_32(const void *key, int len, uint32_t seed) { 74*8e33eff8Schristos const uint8_t *data = (const uint8_t *) key; 75*8e33eff8Schristos const int nblocks = len / 4; 76*8e33eff8Schristos 77*8e33eff8Schristos uint32_t h1 = seed; 78*8e33eff8Schristos 79*8e33eff8Schristos const uint32_t c1 = 0xcc9e2d51; 80*8e33eff8Schristos const uint32_t c2 = 0x1b873593; 81*8e33eff8Schristos 82*8e33eff8Schristos /* body */ 83*8e33eff8Schristos { 84*8e33eff8Schristos const uint32_t *blocks = (const uint32_t *) (data + nblocks*4); 85*8e33eff8Schristos int i; 86*8e33eff8Schristos 87*8e33eff8Schristos for (i = -nblocks; i; i++) { 88*8e33eff8Schristos uint32_t k1 = hash_get_block_32(blocks, i); 89*8e33eff8Schristos 90*8e33eff8Schristos k1 *= c1; 91*8e33eff8Schristos k1 = hash_rotl_32(k1, 15); 92*8e33eff8Schristos k1 *= c2; 93*8e33eff8Schristos 94*8e33eff8Schristos h1 ^= k1; 95*8e33eff8Schristos h1 = hash_rotl_32(h1, 13); 96*8e33eff8Schristos h1 = h1*5 + 0xe6546b64; 97*8e33eff8Schristos } 98*8e33eff8Schristos } 99*8e33eff8Schristos 100*8e33eff8Schristos /* tail */ 101*8e33eff8Schristos { 102*8e33eff8Schristos const uint8_t *tail = (const uint8_t *) (data + nblocks*4); 103*8e33eff8Schristos 104*8e33eff8Schristos uint32_t k1 = 0; 105*8e33eff8Schristos 106*8e33eff8Schristos switch (len & 3) { 107*8e33eff8Schristos case 3: k1 ^= tail[2] << 16; 108*8e33eff8Schristos case 2: k1 ^= tail[1] << 8; 109*8e33eff8Schristos case 1: k1 ^= tail[0]; k1 *= c1; k1 = hash_rotl_32(k1, 15); 110*8e33eff8Schristos k1 *= c2; h1 ^= k1; 111*8e33eff8Schristos } 112*8e33eff8Schristos } 113*8e33eff8Schristos 114*8e33eff8Schristos /* finalization */ 115*8e33eff8Schristos h1 ^= len; 116*8e33eff8Schristos 117*8e33eff8Schristos h1 = hash_fmix_32(h1); 118*8e33eff8Schristos 119*8e33eff8Schristos return h1; 120*8e33eff8Schristos } 121*8e33eff8Schristos 122*8e33eff8Schristos UNUSED static inline void 123*8e33eff8Schristos hash_x86_128(const void *key, const int len, uint32_t seed, 124*8e33eff8Schristos uint64_t r_out[2]) { 125*8e33eff8Schristos const uint8_t * data = (const uint8_t *) key; 126*8e33eff8Schristos const int nblocks = len / 16; 127*8e33eff8Schristos 128*8e33eff8Schristos uint32_t h1 = seed; 129*8e33eff8Schristos uint32_t h2 = seed; 130*8e33eff8Schristos uint32_t h3 = seed; 131*8e33eff8Schristos uint32_t h4 = seed; 132*8e33eff8Schristos 133*8e33eff8Schristos const uint32_t c1 = 0x239b961b; 134*8e33eff8Schristos const uint32_t c2 = 0xab0e9789; 135*8e33eff8Schristos const uint32_t c3 = 0x38b34ae5; 136*8e33eff8Schristos const uint32_t c4 = 0xa1e38b93; 137*8e33eff8Schristos 138*8e33eff8Schristos /* body */ 139*8e33eff8Schristos { 140*8e33eff8Schristos const uint32_t *blocks = (const uint32_t *) (data + nblocks*16); 141*8e33eff8Schristos int i; 142*8e33eff8Schristos 143*8e33eff8Schristos for (i = -nblocks; i; i++) { 144*8e33eff8Schristos uint32_t k1 = hash_get_block_32(blocks, i*4 + 0); 145*8e33eff8Schristos uint32_t k2 = hash_get_block_32(blocks, i*4 + 1); 146*8e33eff8Schristos uint32_t k3 = hash_get_block_32(blocks, i*4 + 2); 147*8e33eff8Schristos uint32_t k4 = hash_get_block_32(blocks, i*4 + 3); 148*8e33eff8Schristos 149*8e33eff8Schristos k1 *= c1; k1 = hash_rotl_32(k1, 15); k1 *= c2; h1 ^= k1; 150*8e33eff8Schristos 151*8e33eff8Schristos h1 = hash_rotl_32(h1, 19); h1 += h2; 152*8e33eff8Schristos h1 = h1*5 + 0x561ccd1b; 153*8e33eff8Schristos 154*8e33eff8Schristos k2 *= c2; k2 = hash_rotl_32(k2, 16); k2 *= c3; h2 ^= k2; 155*8e33eff8Schristos 156*8e33eff8Schristos h2 = hash_rotl_32(h2, 17); h2 += h3; 157*8e33eff8Schristos h2 = h2*5 + 0x0bcaa747; 158*8e33eff8Schristos 159*8e33eff8Schristos k3 *= c3; k3 = hash_rotl_32(k3, 17); k3 *= c4; h3 ^= k3; 160*8e33eff8Schristos 161*8e33eff8Schristos h3 = hash_rotl_32(h3, 15); h3 += h4; 162*8e33eff8Schristos h3 = h3*5 + 0x96cd1c35; 163*8e33eff8Schristos 164*8e33eff8Schristos k4 *= c4; k4 = hash_rotl_32(k4, 18); k4 *= c1; h4 ^= k4; 165*8e33eff8Schristos 166*8e33eff8Schristos h4 = hash_rotl_32(h4, 13); h4 += h1; 167*8e33eff8Schristos h4 = h4*5 + 0x32ac3b17; 168*8e33eff8Schristos } 169*8e33eff8Schristos } 170*8e33eff8Schristos 171*8e33eff8Schristos /* tail */ 172*8e33eff8Schristos { 173*8e33eff8Schristos const uint8_t *tail = (const uint8_t *) (data + nblocks*16); 174*8e33eff8Schristos uint32_t k1 = 0; 175*8e33eff8Schristos uint32_t k2 = 0; 176*8e33eff8Schristos uint32_t k3 = 0; 177*8e33eff8Schristos uint32_t k4 = 0; 178*8e33eff8Schristos 179*8e33eff8Schristos switch (len & 15) { 180*8e33eff8Schristos case 15: k4 ^= tail[14] << 16; /*FALLTHROUGH*/ 181*8e33eff8Schristos case 14: k4 ^= tail[13] << 8; /*FALLTHROUGH*/ 182*8e33eff8Schristos case 13: k4 ^= tail[12] << 0; 183*8e33eff8Schristos k4 *= c4; k4 = hash_rotl_32(k4, 18); k4 *= c1; h4 ^= k4; 184*8e33eff8Schristos /*FALLTHROUGH*/ 185*8e33eff8Schristos 186*8e33eff8Schristos case 12: k3 ^= (uint32_t)tail[11] << 24; /*FALLTHROUGH*/ 187*8e33eff8Schristos case 11: k3 ^= tail[10] << 16; /*FALLTHROUGH*/ 188*8e33eff8Schristos case 10: k3 ^= tail[ 9] << 8; /*FALLTHROUGH*/ 189*8e33eff8Schristos case 9: k3 ^= tail[ 8] << 0; 190*8e33eff8Schristos k3 *= c3; k3 = hash_rotl_32(k3, 17); k3 *= c4; h3 ^= k3; 191*8e33eff8Schristos /*FALLTHROUGH*/ 192*8e33eff8Schristos 193*8e33eff8Schristos case 8: k2 ^= (uint32_t)tail[ 7] << 24; /*FALLTHROUGH*/ 194*8e33eff8Schristos case 7: k2 ^= tail[ 6] << 16; /*FALLTHROUGH*/ 195*8e33eff8Schristos case 6: k2 ^= tail[ 5] << 8; /*FALLTHROUGH*/ 196*8e33eff8Schristos case 5: k2 ^= tail[ 4] << 0; 197*8e33eff8Schristos k2 *= c2; k2 = hash_rotl_32(k2, 16); k2 *= c3; h2 ^= k2; 198*8e33eff8Schristos /*FALLTHROUGH*/ 199*8e33eff8Schristos 200*8e33eff8Schristos case 4: k1 ^= (uint32_t)tail[ 3] << 24; /*FALLTHROUGH*/ 201*8e33eff8Schristos case 3: k1 ^= tail[ 2] << 16; /*FALLTHROUGH*/ 202*8e33eff8Schristos case 2: k1 ^= tail[ 1] << 8; /*FALLTHROUGH*/ 203*8e33eff8Schristos case 1: k1 ^= tail[ 0] << 0; 204*8e33eff8Schristos k1 *= c1; k1 = hash_rotl_32(k1, 15); k1 *= c2; h1 ^= k1; 205*8e33eff8Schristos } 206*8e33eff8Schristos } 207*8e33eff8Schristos 208*8e33eff8Schristos /* finalization */ 209*8e33eff8Schristos h1 ^= len; h2 ^= len; h3 ^= len; h4 ^= len; 210*8e33eff8Schristos 211*8e33eff8Schristos h1 += h2; h1 += h3; h1 += h4; 212*8e33eff8Schristos h2 += h1; h3 += h1; h4 += h1; 213*8e33eff8Schristos 214*8e33eff8Schristos h1 = hash_fmix_32(h1); 215*8e33eff8Schristos h2 = hash_fmix_32(h2); 216*8e33eff8Schristos h3 = hash_fmix_32(h3); 217*8e33eff8Schristos h4 = hash_fmix_32(h4); 218*8e33eff8Schristos 219*8e33eff8Schristos h1 += h2; h1 += h3; h1 += h4; 220*8e33eff8Schristos h2 += h1; h3 += h1; h4 += h1; 221*8e33eff8Schristos 222*8e33eff8Schristos r_out[0] = (((uint64_t) h2) << 32) | h1; 223*8e33eff8Schristos r_out[1] = (((uint64_t) h4) << 32) | h3; 224*8e33eff8Schristos } 225*8e33eff8Schristos 226*8e33eff8Schristos UNUSED static inline void 227*8e33eff8Schristos hash_x64_128(const void *key, const int len, const uint32_t seed, 228*8e33eff8Schristos uint64_t r_out[2]) { 229*8e33eff8Schristos const uint8_t *data = (const uint8_t *) key; 230*8e33eff8Schristos const int nblocks = len / 16; 231*8e33eff8Schristos 232*8e33eff8Schristos uint64_t h1 = seed; 233*8e33eff8Schristos uint64_t h2 = seed; 234*8e33eff8Schristos 235*8e33eff8Schristos const uint64_t c1 = KQU(0x87c37b91114253d5); 236*8e33eff8Schristos const uint64_t c2 = KQU(0x4cf5ad432745937f); 237*8e33eff8Schristos 238*8e33eff8Schristos /* body */ 239*8e33eff8Schristos { 240*8e33eff8Schristos const uint64_t *blocks = (const uint64_t *) (data); 241*8e33eff8Schristos int i; 242*8e33eff8Schristos 243*8e33eff8Schristos for (i = 0; i < nblocks; i++) { 244*8e33eff8Schristos uint64_t k1 = hash_get_block_64(blocks, i*2 + 0); 245*8e33eff8Schristos uint64_t k2 = hash_get_block_64(blocks, i*2 + 1); 246*8e33eff8Schristos 247*8e33eff8Schristos k1 *= c1; k1 = hash_rotl_64(k1, 31); k1 *= c2; h1 ^= k1; 248*8e33eff8Schristos 249*8e33eff8Schristos h1 = hash_rotl_64(h1, 27); h1 += h2; 250*8e33eff8Schristos h1 = h1*5 + 0x52dce729; 251*8e33eff8Schristos 252*8e33eff8Schristos k2 *= c2; k2 = hash_rotl_64(k2, 33); k2 *= c1; h2 ^= k2; 253*8e33eff8Schristos 254*8e33eff8Schristos h2 = hash_rotl_64(h2, 31); h2 += h1; 255*8e33eff8Schristos h2 = h2*5 + 0x38495ab5; 256*8e33eff8Schristos } 257*8e33eff8Schristos } 258*8e33eff8Schristos 259*8e33eff8Schristos /* tail */ 260*8e33eff8Schristos { 261*8e33eff8Schristos const uint8_t *tail = (const uint8_t*)(data + nblocks*16); 262*8e33eff8Schristos uint64_t k1 = 0; 263*8e33eff8Schristos uint64_t k2 = 0; 264*8e33eff8Schristos 265*8e33eff8Schristos switch (len & 15) { 266*8e33eff8Schristos case 15: k2 ^= ((uint64_t)(tail[14])) << 48; /* falls through */ 267*8e33eff8Schristos case 14: k2 ^= ((uint64_t)(tail[13])) << 40; /* falls through */ 268*8e33eff8Schristos case 13: k2 ^= ((uint64_t)(tail[12])) << 32; /* falls through */ 269*8e33eff8Schristos case 12: k2 ^= ((uint64_t)(tail[11])) << 24; /* falls through */ 270*8e33eff8Schristos case 11: k2 ^= ((uint64_t)(tail[10])) << 16; /* falls through */ 271*8e33eff8Schristos case 10: k2 ^= ((uint64_t)(tail[ 9])) << 8; /* falls through */ 272*8e33eff8Schristos case 9: k2 ^= ((uint64_t)(tail[ 8])) << 0; 273*8e33eff8Schristos k2 *= c2; k2 = hash_rotl_64(k2, 33); k2 *= c1; h2 ^= k2; 274*8e33eff8Schristos /* falls through */ 275*8e33eff8Schristos case 8: k1 ^= ((uint64_t)(tail[ 7])) << 56; /* falls through */ 276*8e33eff8Schristos case 7: k1 ^= ((uint64_t)(tail[ 6])) << 48; /* falls through */ 277*8e33eff8Schristos case 6: k1 ^= ((uint64_t)(tail[ 5])) << 40; /* falls through */ 278*8e33eff8Schristos case 5: k1 ^= ((uint64_t)(tail[ 4])) << 32; /* falls through */ 279*8e33eff8Schristos case 4: k1 ^= ((uint64_t)(tail[ 3])) << 24; /* falls through */ 280*8e33eff8Schristos case 3: k1 ^= ((uint64_t)(tail[ 2])) << 16; /* falls through */ 281*8e33eff8Schristos case 2: k1 ^= ((uint64_t)(tail[ 1])) << 8; /* falls through */ 282*8e33eff8Schristos case 1: k1 ^= ((uint64_t)(tail[ 0])) << 0; 283*8e33eff8Schristos k1 *= c1; k1 = hash_rotl_64(k1, 31); k1 *= c2; h1 ^= k1; 284*8e33eff8Schristos } 285*8e33eff8Schristos } 286*8e33eff8Schristos 287*8e33eff8Schristos /* finalization */ 288*8e33eff8Schristos h1 ^= len; h2 ^= len; 289*8e33eff8Schristos 290*8e33eff8Schristos h1 += h2; 291*8e33eff8Schristos h2 += h1; 292*8e33eff8Schristos 293*8e33eff8Schristos h1 = hash_fmix_64(h1); 294*8e33eff8Schristos h2 = hash_fmix_64(h2); 295*8e33eff8Schristos 296*8e33eff8Schristos h1 += h2; 297*8e33eff8Schristos h2 += h1; 298*8e33eff8Schristos 299*8e33eff8Schristos r_out[0] = h1; 300*8e33eff8Schristos r_out[1] = h2; 301*8e33eff8Schristos } 302*8e33eff8Schristos 303*8e33eff8Schristos /******************************************************************************/ 304*8e33eff8Schristos /* API. */ 305*8e33eff8Schristos static inline void 306*8e33eff8Schristos hash(const void *key, size_t len, const uint32_t seed, size_t r_hash[2]) { 307*8e33eff8Schristos assert(len <= INT_MAX); /* Unfortunate implementation limitation. */ 308*8e33eff8Schristos 309*8e33eff8Schristos #if (LG_SIZEOF_PTR == 3 && !defined(JEMALLOC_BIG_ENDIAN)) 310*8e33eff8Schristos hash_x64_128(key, (int)len, seed, (uint64_t *)r_hash); 311*8e33eff8Schristos #else 312*8e33eff8Schristos { 313*8e33eff8Schristos uint64_t hashes[2]; 314*8e33eff8Schristos hash_x86_128(key, (int)len, seed, hashes); 315*8e33eff8Schristos r_hash[0] = (size_t)hashes[0]; 316*8e33eff8Schristos r_hash[1] = (size_t)hashes[1]; 317*8e33eff8Schristos } 318*8e33eff8Schristos #endif 319*8e33eff8Schristos } 320*8e33eff8Schristos 321*8e33eff8Schristos #endif /* JEMALLOC_INTERNAL_HASH_H */ 322