Skip to content

Commit 4c3596c

Browse files
committed
Add and use set_compare_frozenset().
1 parent 157cd60 commit 4c3596c

File tree

1 file changed

+56
-9
lines changed

1 file changed

+56
-9
lines changed

Objects/setobject.c

Lines changed: 56 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,9 @@ static PyObject _dummy_struct;
6868
#define SET_LOOKKEY_CHANGED (-2)
6969
#define SET_LOOKKEY_EMPTY (-3)
7070

71+
typedef int (*compare_func)(PySetObject *so, setentry *table, setentry *ep,
72+
PyObject *key, Py_hash_t hash);
73+
7174
#ifdef Py_GIL_DISABLED
7275

7376
#define SET_IS_SHARED(so) _PyObject_GC_IS_SHARED(so)
@@ -159,6 +162,36 @@ set_compare_entry(PySetObject *so, setentry *table, setentry *entry,
159162
return SET_LOOKKEY_NO_MATCH;
160163
}
161164

165+
// This is similar to set_compare_entry() but we don't need to incref startkey
166+
// before comparing and we don't need to check if the set has changed.
167+
static inline Py_ALWAYS_INLINE int
168+
set_compare_frozenset(PySetObject *so, setentry *table, setentry *ep,
169+
PyObject *key, Py_hash_t hash)
170+
{
171+
assert(PyFrozenSet_CheckExact(so));
172+
PyObject *startkey = ep->key;
173+
if (startkey == NULL) {
174+
return SET_LOOKKEY_EMPTY;
175+
}
176+
if (startkey == key) {
177+
return SET_LOOKKEY_FOUND;
178+
}
179+
Py_ssize_t ep_hash = ep->hash;
180+
if (ep_hash == hash) {
181+
if (PyUnicode_CheckExact(startkey)
182+
&& PyUnicode_CheckExact(key)
183+
&& unicode_eq(startkey, key))
184+
return SET_LOOKKEY_FOUND;
185+
int cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
186+
if (cmp < 0) {
187+
return SET_LOOKKEY_ERROR;
188+
}
189+
assert(cmp == SET_LOOKKEY_FOUND || cmp == SET_LOOKKEY_NO_MATCH);
190+
return cmp;
191+
}
192+
return SET_LOOKKEY_NO_MATCH;
193+
}
194+
162195
static void
163196
set_zero_table(setentry *table, size_t size)
164197
{
@@ -186,9 +219,7 @@ set_zero_table(setentry *table, size_t size)
186219

187220
static int
188221
set_do_lookup(PySetObject *so, setentry *table, size_t mask, PyObject *key,
189-
Py_hash_t hash, setentry **epp,
190-
int (*compare_entry)(PySetObject *so, setentry *table, setentry *ep,
191-
PyObject *key, Py_hash_t hash))
222+
Py_hash_t hash, setentry **epp, compare_func compare_entry)
192223
{
193224
setentry *entry;
194225
size_t perturb = hash;
@@ -363,11 +394,18 @@ static int
363394
set_lookkey(PySetObject *so, PyObject *key, Py_hash_t hash, setentry **epp)
364395
{
365396
int status;
366-
Py_BEGIN_CRITICAL_SECTION(so);
367-
do {
368-
status = set_do_lookup(so, so->table, so->mask, key, hash, epp, set_compare_entry);
369-
} while (status == SET_LOOKKEY_CHANGED);
370-
Py_END_CRITICAL_SECTION();
397+
if (PyFrozenSet_CheckExact(so)) {
398+
status = set_do_lookup(so, so->table, so->mask, key, hash, epp,
399+
set_compare_frozenset);
400+
}
401+
else {
402+
Py_BEGIN_CRITICAL_SECTION(so);
403+
do {
404+
status = set_do_lookup(so, so->table, so->mask, key, hash, epp,
405+
set_compare_entry);
406+
} while (status == SET_LOOKKEY_CHANGED);
407+
Py_END_CRITICAL_SECTION();
408+
}
371409
assert(status == SET_LOOKKEY_FOUND ||
372410
status == SET_LOOKKEY_NO_MATCH ||
373411
status == SET_LOOKKEY_ERROR);
@@ -380,13 +418,22 @@ set_lookkey_threadsafe(PySetObject *so, PyObject *key, Py_hash_t hash)
380418
{
381419
int status;
382420
setentry *entry;
421+
if (PyFrozenSet_CheckExact(so)) {
422+
status = set_do_lookup(so, so->table, so->mask, key, hash, &entry,
423+
set_compare_frozenset);
424+
assert(status == SET_LOOKKEY_FOUND ||
425+
status == SET_LOOKKEY_NO_MATCH ||
426+
status == SET_LOOKKEY_ERROR);
427+
return status;
428+
}
383429
ensure_shared_on_read(so);
384430
setentry *table = FT_ATOMIC_LOAD_PTR_ACQUIRE(so->table);
385431
size_t mask = FT_ATOMIC_LOAD_SSIZE_RELAXED(so->mask);
386432
if (table == NULL || table != FT_ATOMIC_LOAD_PTR_ACQUIRE(so->table)) {
387433
return set_lookkey(so, key, hash, &entry);
388434
}
389-
status = set_do_lookup(so, table, mask, key, hash, &entry, set_compare_threadsafe);
435+
status = set_do_lookup(so, table, mask, key, hash, &entry,
436+
set_compare_threadsafe);
390437
if (status == SET_LOOKKEY_CHANGED) {
391438
return set_lookkey(so, key, hash, &entry);
392439
}

0 commit comments

Comments
 (0)