Skip to content

Commit bbebec7

Browse files
reuse the tuple xxhash algorithm for entries in frozendict_hash by unrolling it for tuples of len 2
1 parent 22f55bb commit bbebec7

1 file changed

Lines changed: 23 additions & 20 deletions

File tree

Objects/dictobject.c

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ As a consequence of this, split keys have a maximum size of 16.
129129
#include "pycore_pyerrors.h" // _PyErr_GetRaisedException()
130130
#include "pycore_pystate.h" // _PyThreadState_GET()
131131
#include "pycore_setobject.h" // _PySet_NextEntry()
132-
#include "pycore_tuple.h" // _PyTuple_Recycle()
132+
#include "pycore_tuple.h" // _PyTuple_Recycle(), _PyTuple_HASH_XXPRIME1, _PyTuple_HASH_XXPRIME2, _PyTuple_HASH_XXPRIME5, _PyTuple_HASH_XXROTATE
133133
#include "pycore_unicodeobject.h" // _PyUnicode_InternImmortal()
134134

135135
#include "stringlib/eq.h" // unicode_eq()
@@ -8222,24 +8222,27 @@ frozendict_repr(PyObject *self)
82228222
return res;
82238223
}
82248224

8225+
// Code unrolled from tuple_hash() for 2 values
82258226
static inline Py_uhash_t
8226-
_combine_hashes(Py_uhash_t h1, Py_uhash_t h2)
8227-
{
8228-
#if SIZEOF_PY_HASH_T == 8
8229-
// 2^sizeof(Py_hash_t) / phi
8230-
const Py_uhash_t GOLDEN_C = 0x9e3779b97f4a7c15ULL;
8231-
h1 += GOLDEN_C;
8232-
h1 ^= h2;
8233-
h1 ^= (h1 << 13) + (h1 >> 3);
8234-
h1 ^= h1 >> 33;
8235-
#else
8236-
const Py_uhash_t GOLDEN_C = 0x9e3779b9UL;
8237-
h1 += GOLDEN_C;
8238-
h1 ^= h2;
8239-
h1 ^= (h1 << 6) + (h1 >> 2);
8240-
h1 ^= h1 >> 16;
8241-
#endif
8242-
return h1;
8227+
_tuple2_xxhash(Py_uhash_t h1, Py_uhash_t h2)
8228+
{
8229+
Py_uhash_t acc = _PyTuple_HASH_XXPRIME_5;
8230+
8231+
acc += h1 * _PyTuple_HASH_XXPRIME_2;
8232+
acc = _PyTuple_HASH_XXROTATE(acc);
8233+
acc *= _PyTuple_HASH_XXPRIME_1;
8234+
8235+
acc += h2 * _PyTuple_HASH_XXPRIME_2;
8236+
acc = _PyTuple_HASH_XXROTATE(acc);
8237+
acc *= _PyTuple_HASH_XXPRIME_1;
8238+
8239+
acc += 2 ^ (_PyTuple_HASH_XXPRIME_5 ^ 3527539UL);
8240+
8241+
if (acc == (Py_uhash_t)-1) {
8242+
acc = 1546275796;
8243+
}
8244+
8245+
return acc;
82438246
}
82448247

82458248
// Code copied from frozenset_hash()
@@ -8253,7 +8256,7 @@ frozendict_hash(PyObject *op)
82538256
}
82548257

82558258
PyDictObject *mp = _PyAnyDict_CAST(op);
8256-
Py_uhash_t hash = 0xfd1c74; // start at a different value from frozenset to avoid collision with empty frozenset
8259+
Py_uhash_t hash = 0xfd1c74; // start at a different value from frozenset to avoid collision with frozenset(frozendict.items())
82578260

82588261
PyObject *key, *value; // borrowed refs
82598262
Py_ssize_t pos = 0;
@@ -8266,7 +8269,7 @@ frozendict_hash(PyObject *op)
82668269
if (value_hash == -1) {
82678270
return -1;
82688271
}
8269-
hash ^= _combine_hashes(key_hash, value_hash);
8272+
hash ^= _tuple2_xxhash(key_hash, value_hash);
82708273
}
82718274

82728275
/* Factor in the number of active entries */

0 commit comments

Comments
 (0)