Skip to content

Commit 80dddd2

Browse files
[3.13] gh-152235: Defer GC tracking in more set operations (gh-152273) (gh-152280)
gh-152235: Defer GC tracking in more set operations (gh-152273) (cherry picked from commit a87d24a) Co-authored-by: Donghee Na <donghee.na@python.org>
1 parent 8c6f547 commit 80dddd2

2 files changed

Lines changed: 36 additions & 10 deletions

File tree

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Defer GC tracking of :meth:`set.intersection`, :meth:`set.difference` and
2+
:meth:`set.symmetric_difference`. Patch by Donghee Na.

Objects/setobject.c

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1080,14 +1080,14 @@ set_update_impl(PySetObject *so, PyObject *args)
10801080
can be retrieved or updated in a single cache line.
10811081
*/
10821082

1083+
// Build a set/frozenset left GC-untracked; the caller must _PyObject_GC_TRACK()
1084+
// it once fully built, so a half-built set is never exposed during filling.
10831085
static PyObject *
1084-
make_new_set(PyTypeObject *type, PyObject *iterable)
1086+
make_new_set_untracked(PyTypeObject *type, PyObject *iterable)
10851087
{
10861088
assert(PyType_Check(type));
10871089
PySetObject *so;
10881090

1089-
// Allocate untracked: the fill below runs user code, and a half-built
1090-
// set must not be reachable from another thread via gc.get_objects().
10911091
so = (PySetObject *)_PyType_AllocNoTrack(type, 0);
10921092
if (so == NULL)
10931093
return NULL;
@@ -1107,21 +1107,39 @@ make_new_set(PyTypeObject *type, PyObject *iterable)
11071107
}
11081108
}
11091109

1110-
// Track only once fully built.
1111-
_PyObject_GC_TRACK(so);
11121110
return (PyObject *)so;
11131111
}
11141112

11151113
static PyObject *
1116-
make_new_set_basetype(PyTypeObject *type, PyObject *iterable)
1114+
make_new_set(PyTypeObject *type, PyObject *iterable)
1115+
{
1116+
PyObject *so = make_new_set_untracked(type, iterable);
1117+
if (so != NULL) {
1118+
_PyObject_GC_TRACK(so);
1119+
}
1120+
return so;
1121+
}
1122+
1123+
static PyObject *
1124+
make_new_set_basetype_untracked(PyTypeObject *type, PyObject *iterable)
11171125
{
11181126
if (type != &PySet_Type && type != &PyFrozenSet_Type) {
11191127
if (PyType_IsSubtype(type, &PySet_Type))
11201128
type = &PySet_Type;
11211129
else
11221130
type = &PyFrozenSet_Type;
11231131
}
1124-
return make_new_set(type, iterable);
1132+
return make_new_set_untracked(type, iterable);
1133+
}
1134+
1135+
static PyObject *
1136+
make_new_set_basetype(PyTypeObject *type, PyObject *iterable)
1137+
{
1138+
PyObject *so = make_new_set_basetype_untracked(type, iterable);
1139+
if (so != NULL) {
1140+
_PyObject_GC_TRACK(so);
1141+
}
1142+
return so;
11251143
}
11261144

11271145
static PyObject *
@@ -1364,7 +1382,7 @@ set_intersection(PySetObject *so, PyObject *other)
13641382
if ((PyObject *)so == other)
13651383
return set_copy_impl(so);
13661384

1367-
result = (PySetObject *)make_new_set_basetype(Py_TYPE(so), NULL);
1385+
result = (PySetObject *)make_new_set_basetype_untracked(Py_TYPE(so), NULL);
13681386
if (result == NULL)
13691387
return NULL;
13701388

@@ -1397,6 +1415,7 @@ set_intersection(PySetObject *so, PyObject *other)
13971415
}
13981416
Py_DECREF(key);
13991417
}
1418+
_PyObject_GC_TRACK(result);
14001419
return (PyObject *)result;
14011420
}
14021421

@@ -1428,6 +1447,7 @@ set_intersection(PySetObject *so, PyObject *other)
14281447
Py_DECREF(result);
14291448
return NULL;
14301449
}
1450+
_PyObject_GC_TRACK(result);
14311451
return (PyObject *)result;
14321452
error:
14331453
Py_DECREF(it);
@@ -1737,7 +1757,7 @@ set_difference(PySetObject *so, PyObject *other)
17371757
return set_copy_and_difference(so, other);
17381758
}
17391759

1740-
result = make_new_set_basetype(Py_TYPE(so), NULL);
1760+
result = make_new_set_basetype_untracked(Py_TYPE(so), NULL);
17411761
if (result == NULL)
17421762
return NULL;
17431763

@@ -1761,6 +1781,7 @@ set_difference(PySetObject *so, PyObject *other)
17611781
}
17621782
Py_DECREF(key);
17631783
}
1784+
_PyObject_GC_TRACK(result);
17641785
return result;
17651786
}
17661787

@@ -1784,6 +1805,7 @@ set_difference(PySetObject *so, PyObject *other)
17841805
}
17851806
Py_DECREF(key);
17861807
}
1808+
_PyObject_GC_TRACK(result);
17871809
return result;
17881810
}
17891811

@@ -1970,7 +1992,8 @@ static PyObject *
19701992
set_symmetric_difference_impl(PySetObject *so, PyObject *other)
19711993
/*[clinic end generated code: output=270ee0b5d42b0797 input=624f6e7bbdf70db1]*/
19721994
{
1973-
PySetObject *result = (PySetObject *)make_new_set_basetype(Py_TYPE(so), NULL);
1995+
PySetObject *result =
1996+
(PySetObject *)make_new_set_basetype_untracked(Py_TYPE(so), NULL);
19741997
if (result == NULL) {
19751998
return NULL;
19761999
}
@@ -1982,6 +2005,7 @@ set_symmetric_difference_impl(PySetObject *so, PyObject *other)
19822005
Py_DECREF(result);
19832006
return NULL;
19842007
}
2008+
_PyObject_GC_TRACK(result);
19852009
return (PyObject *)result;
19862010
}
19872011

0 commit comments

Comments
 (0)