Skip to content

Commit 6019c8c

Browse files
committed
Issue python#25629: Move set fill/used updates out of inner loop
1 parent 9ba97df commit 6019c8c

1 file changed

Lines changed: 8 additions & 7 deletions

File tree

Objects/setobject.c

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -254,9 +254,10 @@ set_add_entry(PySetObject *so, PyObject *key, Py_hash_t hash)
254254
Internal routine used by set_table_resize() to insert an item which is
255255
known to be absent from the set. This routine also assumes that
256256
the set contains no deleted entries. Besides the performance benefit,
257-
using set_insert_clean() in set_table_resize() is dangerous (SF bug #1456209).
258-
Note that no refcounts are changed by this routine; if needed, the caller
259-
is responsible for incref'ing `key`.
257+
there is also safety benefit since using set_add_entry() risks making
258+
a callback in the middle of a set_table_resize(), see issue 1456209.
259+
The caller is responsible for updating the key's reference count and
260+
the setobject's fill and used fields.
260261
*/
261262
static void
262263
set_insert_clean(PySetObject *so, PyObject *key, Py_hash_t hash)
@@ -285,8 +286,6 @@ set_insert_clean(PySetObject *so, PyObject *key, Py_hash_t hash)
285286
found_null:
286287
entry->key = key;
287288
entry->hash = hash;
288-
so->fill++;
289-
so->used++;
290289
}
291290

292291
/* ======== End logic for probing the hash table ========================== */
@@ -356,8 +355,8 @@ set_table_resize(PySetObject *so, Py_ssize_t minused)
356355
/* Make the set empty, using the new table. */
357356
assert(newtable != oldtable);
358357
memset(newtable, 0, sizeof(setentry) * newsize);
359-
so->fill = 0;
360-
so->used = 0;
358+
so->fill = oldused;
359+
so->used = oldused;
361360
so->mask = newsize - 1;
362361
so->table = newtable;
363362

@@ -676,6 +675,8 @@ set_merge(PySetObject *so, PyObject *otherset)
676675

677676
/* If our table is empty, we can use set_insert_clean() */
678677
if (so->fill == 0) {
678+
so->fill = other->used;
679+
so->used = other->used;
679680
for (i = 0; i <= other->mask; i++, other_entry++) {
680681
key = other_entry->key;
681682
if (key != NULL && key != dummy) {

0 commit comments

Comments
 (0)