https://github.com/python/cpython/commit/67b1c765ef4aca61355747f7c7037e75b0c6b87b
commit: 67b1c765ef4aca61355747f7c7037e75b0c6b87b
branch: 3.13
author: Kumar Aditya <[email protected]>
committer: kumaraditya303 <[email protected]>
date: 2025-04-12T18:20:24Z
summary:
[3.13] gh-132213: use relaxed atomics for set hash (#132447)
files:
M Objects/setobject.c
diff --git a/Objects/setobject.c b/Objects/setobject.c
index 81a34ad5ab12c5..7c5d6eb34cae08 100644
--- a/Objects/setobject.c
+++ b/Objects/setobject.c
@@ -400,7 +400,7 @@ set_empty_to_minsize(PySetObject *so)
FT_ATOMIC_STORE_SSIZE_RELAXED(so->used, 0);
so->mask = PySet_MINSIZE - 1;
so->table = so->smalltable;
- so->hash = -1;
+ FT_ATOMIC_STORE_SSIZE_RELAXED(so->hash, -1);
}
static int
@@ -718,18 +718,15 @@ _shuffle_bits(Py_uhash_t h)
large primes with "interesting bit patterns" and that passed tests
for good collision statistics on a variety of problematic datasets
including powersets and graph structures (such as David Eppstein's
- graph recipes in Lib/test/test_set.py) */
+ graph recipes in Lib/test/test_set.py). */
static Py_hash_t
-frozenset_hash(PyObject *self)
+frozenset_hash_impl(PyObject *self)
{
- PySetObject *so = (PySetObject *)self;
+ PySetObject *so = _PySet_CAST(self);
Py_uhash_t hash = 0;
setentry *entry;
- if (so->hash != -1)
- return so->hash;
-
/* Xor-in shuffled bits from every entry's hash field because xor is
commutative and a frozenset hash should be independent of order.
@@ -762,7 +759,21 @@ frozenset_hash(PyObject *self)
if (hash == (Py_uhash_t)-1)
hash = 590923713UL;
- so->hash = hash;
+ return (Py_hash_t)hash;
+}
+
+static Py_hash_t
+frozenset_hash(PyObject *self)
+{
+ PySetObject *so = _PySet_CAST(self);
+ Py_uhash_t hash;
+
+ if (FT_ATOMIC_LOAD_SSIZE_RELAXED(so->hash) != -1) {
+ return FT_ATOMIC_LOAD_SSIZE_RELAXED(so->hash);
+ }
+
+ hash = frozenset_hash_impl(self);
+ FT_ATOMIC_STORE_SSIZE_RELAXED(so->hash, hash);
return hash;
}
@@ -1202,10 +1213,12 @@ set_swap_bodies(PySetObject *a, PySetObject *b)
if (PyType_IsSubtype(Py_TYPE(a), &PyFrozenSet_Type) &&
PyType_IsSubtype(Py_TYPE(b), &PyFrozenSet_Type)) {
- h = a->hash; a->hash = b->hash; b->hash = h;
+ h = FT_ATOMIC_LOAD_SSIZE_RELAXED(a->hash);
+ FT_ATOMIC_STORE_SSIZE_RELAXED(a->hash,
FT_ATOMIC_LOAD_SSIZE_RELAXED(b->hash));
+ FT_ATOMIC_STORE_SSIZE_RELAXED(b->hash, h);
} else {
- a->hash = -1;
- b->hash = -1;
+ FT_ATOMIC_STORE_SSIZE_RELAXED(a->hash, -1);
+ FT_ATOMIC_STORE_SSIZE_RELAXED(b->hash, -1);
}
}
@@ -2086,9 +2099,9 @@ set_richcompare(PySetObject *v, PyObject *w, int op)
case Py_EQ:
if (PySet_GET_SIZE(v) != PySet_GET_SIZE(w))
Py_RETURN_FALSE;
- if (v->hash != -1 &&
- ((PySetObject *)w)->hash != -1 &&
- v->hash != ((PySetObject *)w)->hash)
+ Py_hash_t v_hash = FT_ATOMIC_LOAD_SSIZE_RELAXED(v->hash);
+ Py_hash_t w_hash = FT_ATOMIC_LOAD_SSIZE_RELAXED(((PySetObject
*)w)->hash);
+ if (v_hash != -1 && w_hash != -1 && v_hash != w_hash)
Py_RETURN_FALSE;
return set_issubset(v, w);
case Py_NE:
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]