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