diff options
author | Raymond Hettinger <python@rcn.com> | 2015-11-17 16:28:07 (GMT) |
---|---|---|
committer | Raymond Hettinger <python@rcn.com> | 2015-11-17 16:28:07 (GMT) |
commit | 6019c8ced03fcb7acde715bf39aea18d1e44cba8 (patch) | |
tree | 508679ad457a0e88d970e64b20cc562e5e57e5fb /Objects/setobject.c | |
parent | 9ba97df69c9b056d8531bb8ed54378ca81d761de (diff) | |
download | cpython-6019c8ced03fcb7acde715bf39aea18d1e44cba8.zip cpython-6019c8ced03fcb7acde715bf39aea18d1e44cba8.tar.gz cpython-6019c8ced03fcb7acde715bf39aea18d1e44cba8.tar.bz2 |
Issue #25629: Move set fill/used updates out of inner loop
Diffstat (limited to 'Objects/setobject.c')
-rw-r--r-- | Objects/setobject.c | 15 |
1 files changed, 8 insertions, 7 deletions
diff --git a/Objects/setobject.c b/Objects/setobject.c index 03bb230..083cbea 100644 --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -254,9 +254,10 @@ set_add_entry(PySetObject *so, PyObject *key, Py_hash_t hash) Internal routine used by set_table_resize() to insert an item which is known to be absent from the set. This routine also assumes that the set contains no deleted entries. Besides the performance benefit, -using set_insert_clean() in set_table_resize() is dangerous (SF bug #1456209). -Note that no refcounts are changed by this routine; if needed, the caller -is responsible for incref'ing `key`. +there is also safety benefit since using set_add_entry() risks making +a callback in the middle of a set_table_resize(), see issue 1456209. +The caller is responsible for updating the key's reference count and +the setobject's fill and used fields. */ static void 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) found_null: entry->key = key; entry->hash = hash; - so->fill++; - so->used++; } /* ======== End logic for probing the hash table ========================== */ @@ -356,8 +355,8 @@ set_table_resize(PySetObject *so, Py_ssize_t minused) /* Make the set empty, using the new table. */ assert(newtable != oldtable); memset(newtable, 0, sizeof(setentry) * newsize); - so->fill = 0; - so->used = 0; + so->fill = oldused; + so->used = oldused; so->mask = newsize - 1; so->table = newtable; @@ -676,6 +675,8 @@ set_merge(PySetObject *so, PyObject *otherset) /* If our table is empty, we can use set_insert_clean() */ if (so->fill == 0) { + so->fill = other->used; + so->used = other->used; for (i = 0; i <= other->mask; i++, other_entry++) { key = other_entry->key; if (key != NULL && key != dummy) { |