https://github.com/python/cpython/commit/a87d24a69d1e97a1e9643c8951d180918ef36e4c
commit: a87d24a69d1e97a1e9643c8951d180918ef36e4c
branch: main
author: Donghee Na <[email protected]>
committer: corona10 <[email protected]>
date: 2026-06-26T22:35:17+09:00
summary:
gh-152235: Defer GC tracking in more set operations (gh-152273)
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 883658b8bfd340..d8c38ff1c1d899 100644
--- a/Objects/setobject.c
+++ b/Objects/setobject.c
@@ -1345,14 +1345,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;
@@ -1372,13 +1372,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))
@@ -1386,7 +1394,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;
}
// gh-140232: check whether a frozenset can be untracked from the GC
@@ -1696,7 +1714,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;
@@ -1729,6 +1747,7 @@ set_intersection(PySetObject *so, PyObject *other)
}
Py_DECREF(key);
}
+ _PyObject_GC_TRACK(result);
return (PyObject *)result;
}
@@ -1760,6 +1779,7 @@ set_intersection(PySetObject *so, PyObject *other)
Py_DECREF(result);
return NULL;
}
+ _PyObject_GC_TRACK(result);
return (PyObject *)result;
error:
Py_DECREF(it);
@@ -2074,7 +2094,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;
@@ -2098,6 +2118,7 @@ set_difference(PySetObject *so, PyObject *other)
}
Py_DECREF(key);
}
+ _PyObject_GC_TRACK(result);
return result;
}
@@ -2121,6 +2142,7 @@ set_difference(PySetObject *so, PyObject *other)
}
Py_DECREF(key);
}
+ _PyObject_GC_TRACK(result);
return result;
}
@@ -2322,7 +2344,8 @@ static PyObject *
set_symmetric_difference_impl(PySetObject *so, PyObject *other)
/*[clinic end generated code: output=270ee0b5d42b0797 input=8c29b0be90d47feb]*/
{
- 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;
}
@@ -2334,6 +2357,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]