https://github.com/python/cpython/commit/e1dc5f5e63c0fa28149d9fe04057e7008c1960f6
commit: e1dc5f5e63c0fa28149d9fe04057e7008c1960f6
branch: 3.14
author: Miss Islington (bot) <[email protected]>
committer: corona10 <[email protected]>
date: 2026-06-26T14:04:16Z
summary:

[3.14] gh-152235: Defer GC tracking in more set operations (gh-152273) 
(gh-152279)

gh-152235: Defer GC tracking in more set operations (gh-152273)
(cherry picked from commit a87d24a69d1e97a1e9643c8951d180918ef36e4c)

Co-authored-by: Donghee Na <[email protected]>

files:
A 
Misc/NEWS.d/next/Core_and_Builtins/2026-06-26-22-03-16.gh-issue-152235.ZKWiWk.rst
M Objects/setobject.c

diff --git 
a/Misc/NEWS.d/next/Core_and_Builtins/2026-06-26-22-03-16.gh-issue-152235.ZKWiWk.rst
 
b/Misc/NEWS.d/next/Core_and_Builtins/2026-06-26-22-03-16.gh-issue-152235.ZKWiWk.rst
new file mode 100644
index 00000000000000..bcc128404897da
--- /dev/null
+++ 
b/Misc/NEWS.d/next/Core_and_Builtins/2026-06-26-22-03-16.gh-issue-152235.ZKWiWk.rst
@@ -0,0 +1,2 @@
+Defer GC tracking of :meth:`set.intersection`, :meth:`set.difference` and
+:meth:`set.symmetric_difference`. Patch by Donghee Na.
diff --git a/Objects/setobject.c b/Objects/setobject.c
index 332552aa0822e1..272ca4568119e3 100644
--- a/Objects/setobject.c
+++ b/Objects/setobject.c
@@ -1137,14 +1137,14 @@ set_update_impl(PySetObject *so, PyObject * const 
*others,
    can be retrieved or updated in a single cache line.
 */
 
+// Build a set/frozenset left GC-untracked; the caller must 
_PyObject_GC_TRACK()
+// it once fully built, so a half-built set is never exposed during filling.
 static PyObject *
-make_new_set(PyTypeObject *type, PyObject *iterable)
+make_new_set_untracked(PyTypeObject *type, PyObject *iterable)
 {
     assert(PyType_Check(type));
     PySetObject *so;
 
-    // Allocate untracked: the fill below runs user code, and a half-built
-    // set must not be reachable from another thread via gc.get_objects().
     so = (PySetObject *)_PyType_AllocNoTrack(type, 0);
     if (so == NULL)
         return NULL;
@@ -1164,13 +1164,21 @@ make_new_set(PyTypeObject *type, PyObject *iterable)
         }
     }
 
-    // Track only once fully built.
-    _PyObject_GC_TRACK(so);
     return (PyObject *)so;
 }
 
 static PyObject *
-make_new_set_basetype(PyTypeObject *type, PyObject *iterable)
+make_new_set(PyTypeObject *type, PyObject *iterable)
+{
+    PyObject *so = make_new_set_untracked(type, iterable);
+    if (so != NULL) {
+        _PyObject_GC_TRACK(so);
+    }
+    return so;
+}
+
+static PyObject *
+make_new_set_basetype_untracked(PyTypeObject *type, PyObject *iterable)
 {
     if (type != &PySet_Type && type != &PyFrozenSet_Type) {
         if (PyType_IsSubtype(type, &PySet_Type))
@@ -1178,7 +1186,17 @@ make_new_set_basetype(PyTypeObject *type, PyObject 
*iterable)
         else
             type = &PyFrozenSet_Type;
     }
-    return make_new_set(type, iterable);
+    return make_new_set_untracked(type, iterable);
+}
+
+static PyObject *
+make_new_set_basetype(PyTypeObject *type, PyObject *iterable)
+{
+    PyObject *so = make_new_set_basetype_untracked(type, iterable);
+    if (so != NULL) {
+        _PyObject_GC_TRACK(so);
+    }
+    return so;
 }
 
 static PyObject *
@@ -1423,7 +1441,7 @@ set_intersection(PySetObject *so, PyObject *other)
     if ((PyObject *)so == other)
         return set_copy_impl(so);
 
-    result = (PySetObject *)make_new_set_basetype(Py_TYPE(so), NULL);
+    result = (PySetObject *)make_new_set_basetype_untracked(Py_TYPE(so), NULL);
     if (result == NULL)
         return NULL;
 
@@ -1456,6 +1474,7 @@ set_intersection(PySetObject *so, PyObject *other)
             }
             Py_DECREF(key);
         }
+        _PyObject_GC_TRACK(result);
         return (PyObject *)result;
     }
 
@@ -1487,6 +1506,7 @@ set_intersection(PySetObject *so, PyObject *other)
         Py_DECREF(result);
         return NULL;
     }
+    _PyObject_GC_TRACK(result);
     return (PyObject *)result;
   error:
     Py_DECREF(it);
@@ -1801,7 +1821,7 @@ set_difference(PySetObject *so, PyObject *other)
         return set_copy_and_difference(so, other);
     }
 
-    result = make_new_set_basetype(Py_TYPE(so), NULL);
+    result = make_new_set_basetype_untracked(Py_TYPE(so), NULL);
     if (result == NULL)
         return NULL;
 
@@ -1825,6 +1845,7 @@ set_difference(PySetObject *so, PyObject *other)
             }
             Py_DECREF(key);
         }
+        _PyObject_GC_TRACK(result);
         return result;
     }
 
@@ -1848,6 +1869,7 @@ set_difference(PySetObject *so, PyObject *other)
         }
         Py_DECREF(key);
     }
+    _PyObject_GC_TRACK(result);
     return result;
 }
 
@@ -2037,7 +2059,8 @@ static PyObject *
 set_symmetric_difference_impl(PySetObject *so, PyObject *other)
 /*[clinic end generated code: output=270ee0b5d42b0797 input=624f6e7bbdf70db1]*/
 {
-    PySetObject *result = (PySetObject *)make_new_set_basetype(Py_TYPE(so), 
NULL);
+    PySetObject *result =
+        (PySetObject *)make_new_set_basetype_untracked(Py_TYPE(so), NULL);
     if (result == NULL) {
         return NULL;
     }
@@ -2049,6 +2072,7 @@ set_symmetric_difference_impl(PySetObject *so, PyObject 
*other)
         Py_DECREF(result);
         return NULL;
     }
+    _PyObject_GC_TRACK(result);
     return (PyObject *)result;
 }
 

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to