Home | History | Annotate | Line # | Download | only in internal
      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