@@ -254,9 +254,10 @@ set_add_entry(PySetObject *so, PyObject *key, Py_hash_t hash)
254254Internal routine used by set_table_resize() to insert an item which is
255255known to be absent from the set. This routine also assumes that
256256the 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*/
261262static void
262263set_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