@@ -122,7 +122,7 @@ set_lookkey(PySetObject *so, PyObject *key, Py_hash_t hash)
122122static int set_table_resize (PySetObject * , Py_ssize_t );
123123
124124static int
125- set_add_entry (PySetObject * so , PyObject * key , Py_hash_t hash )
125+ set_add_entry_takeref (PySetObject * so , PyObject * key , Py_hash_t hash )
126126{
127127 setentry * table ;
128128 setentry * freeslot ;
@@ -133,12 +133,6 @@ set_add_entry(PySetObject *so, PyObject *key, Py_hash_t hash)
133133 int probes ;
134134 int cmp ;
135135
136- _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED (so );
137-
138- /* Pre-increment is necessary to prevent arbitrary code in the rich
139- comparison from deallocating the key just before the insertion. */
140- Py_INCREF (key );
141-
142136 restart :
143137
144138 mask = so -> mask ;
@@ -209,6 +203,57 @@ set_add_entry(PySetObject *so, PyObject *key, Py_hash_t hash)
209203 return -1 ;
210204}
211205
206+ static int
207+ set_add_entry (PySetObject * so , PyObject * key , Py_hash_t hash )
208+ {
209+ _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED (so );
210+
211+ /* Pre-increment is necessary to prevent arbitrary code in the rich
212+ comparison from deallocating the key just before the insertion. */
213+ Py_INCREF (key );
214+
215+ return set_add_entry_takeref (so , key , hash );
216+ }
217+
218+ int
219+ _PySet_AddTakeRef (PySetObject * so , PyObject * key )
220+ {
221+ Py_hash_t hash = _PyObject_HashFast (key );
222+ if (hash == -1 ) {
223+ return -1 ;
224+ }
225+ // We don't pre-increment here, the caller holds a strong
226+ // reference to the object which we are stealing.
227+ return set_add_entry_takeref (so , key , hash );
228+ }
229+
230+ PyObject *
231+ _PySet_FromStackRefSteal (const _PyStackRef * src , Py_ssize_t n )
232+ {
233+ PySetObject * set = (PySetObject * )PySet_New (NULL );
234+ if (n == 0 ) {
235+ return (PyObject * )set ;
236+ }
237+
238+ if (set_table_resize (set , n * 2 ) != 0 ) {
239+ return NULL ;
240+ }
241+
242+ int err = 0 ;
243+ for (Py_ssize_t i = 0 ; i < n ; i ++ ) {
244+ if (err == 0 ) {
245+ err = _PySet_AddTakeRef (set , PyStackRef_AsPyObjectSteal (src [i ]));
246+ } else {
247+ PyStackRef_CLOSE (src [i ]);
248+ }
249+ }
250+ if (err ) {
251+ Py_CLEAR (set );
252+ }
253+
254+ return (PyObject * )set ;
255+ }
256+
212257/*
213258Internal routine used by set_table_resize() to insert an item which is
214259known to be absent from the set. Besides the performance benefit,
0 commit comments