[3.14] gh-132657: avoid locks and refcounting in frozenset lookups (GH-136107) (gh-141772)

gh-132657: avoid locks and refcounting in `frozenset` lookups (GH-136107)
(cherry picked from commit f58a7c7175)

Co-authored-by: Pieter Eendebak <pieter.eendebak@gmail.com>
This commit is contained in:
Miss Islington (bot) 2025-11-20 02:00:42 +01:00 committed by GitHub
parent f6552d2c58
commit c05e71f61e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 26 additions and 10 deletions

View file

@ -86,6 +86,8 @@ set_lookkey(PySetObject *so, PyObject *key, Py_hash_t hash)
int probes;
int cmp;
int frozenset = PyFrozenSet_CheckExact(so);
while (1) {
entry = &so->table[i];
probes = (i + LINEAR_PROBES <= mask) ? LINEAR_PROBES: 0;
@ -102,13 +104,20 @@ set_lookkey(PySetObject *so, PyObject *key, Py_hash_t hash)
&& unicode_eq(startkey, key))
return entry;
table = so->table;
Py_INCREF(startkey);
cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
Py_DECREF(startkey);
if (cmp < 0)
return NULL;
if (table != so->table || entry->key != startkey)
return set_lookkey(so, key, hash);
if (frozenset) {
cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
if (cmp < 0)
return NULL;
} else {
// incref startkey because it can be removed from the set by the compare
Py_INCREF(startkey);
cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
Py_DECREF(startkey);
if (cmp < 0)
return NULL;
if (table != so->table || entry->key != startkey)
return set_lookkey(so, key, hash);
}
if (cmp > 0)
return entry;
mask = so->mask;
@ -2234,10 +2243,16 @@ set_contains_lock_held(PySetObject *so, PyObject *key)
int
_PySet_Contains(PySetObject *so, PyObject *key)
{
assert(so);
int rv;
Py_BEGIN_CRITICAL_SECTION(so);
rv = set_contains_lock_held(so, key);
Py_END_CRITICAL_SECTION();
if (PyFrozenSet_CheckExact(so)) {
rv = set_contains_lock_held(so, key);
} else {
Py_BEGIN_CRITICAL_SECTION(so);
rv = set_contains_lock_held(so, key);
Py_END_CRITICAL_SECTION();
}
return rv;
}