hash.h revision 1.1 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