Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 23 additions & 8 deletions Objects/dictobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ As a consequence of this, split keys have a maximum size of 16.
#include "pycore_pyerrors.h" // _PyErr_GetRaisedException()
#include "pycore_pystate.h" // _PyThreadState_GET()
#include "pycore_setobject.h" // _PySet_NextEntry()
#include "pycore_tuple.h" // _PyTuple_Recycle()
#include "pycore_tuple.h" // _PyTuple_Recycle(), _PyTuple_HASH_XXPRIME1, _PyTuple_HASH_XXPRIME2, _PyTuple_HASH_XXPRIME5, _PyTuple_HASH_XXROTATE
#include "pycore_unicodeobject.h" // _PyUnicode_InternImmortal()

#include "stringlib/eq.h" // unicode_eq()
Expand Down Expand Up @@ -8222,10 +8222,27 @@ frozendict_repr(PyObject *self)
return res;
}

static Py_uhash_t
_shuffle_bits(Py_uhash_t h)
// Code unrolled from tuple_hash() for 2 values
static inline Py_uhash_t
_tuple2_xxhash(Py_uhash_t h1, Py_uhash_t h2)
{
return ((h ^ 89869747UL) ^ (h << 16)) * 3644798167UL;
Py_uhash_t acc = _PyTuple_HASH_XXPRIME_5;

acc += h1 * _PyTuple_HASH_XXPRIME_2;
acc = _PyTuple_HASH_XXROTATE(acc);
acc *= _PyTuple_HASH_XXPRIME_1;

acc += h2 * _PyTuple_HASH_XXPRIME_2;
acc = _PyTuple_HASH_XXROTATE(acc);
acc *= _PyTuple_HASH_XXPRIME_1;

acc += 2 ^ (_PyTuple_HASH_XXPRIME_5 ^ 3527539UL);

if (acc == (Py_uhash_t)-1) {
acc = 1546275796;
}

return acc;
}

// Code copied from frozenset_hash()
Expand All @@ -8239,7 +8256,7 @@ frozendict_hash(PyObject *op)
}

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

PyObject *key, *value; // borrowed refs
Py_ssize_t pos = 0;
Expand All @@ -8248,13 +8265,11 @@ frozendict_hash(PyObject *op)
if (key_hash == -1) {
return -1;
}
hash ^= _shuffle_bits(key_hash);

Py_hash_t value_hash = PyObject_Hash(value);
if (value_hash == -1) {
return -1;
}
hash ^= _shuffle_bits(value_hash);
hash ^= _tuple2_xxhash(key_hash, value_hash);
}

/* Factor in the number of active entries */
Expand Down
Loading