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
staticPyObject*
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
returnNULL;
@@ -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
staticPyObject*
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+
returnso;
1121+
}
1122+
1123+
staticPyObject*
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-
returnmake_new_set(type, iterable);
1132+
returnmake_new_set_untracked(type, iterable);
1133+
}
1134+
1135+
staticPyObject*
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+
returnso;
11251143
}
11261144

11271145
staticPyObject*
@@ -1364,7 +1382,7 @@ set_intersection(PySetObject *so, PyObject *other)
13641382
if ((PyObject*)so==other)
13651383
returnset_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
returnNULL;
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
returnNULL;
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
returnset_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
returnNULL;
17431763

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

@@ -1784,6 +1805,7 @@ set_difference(PySetObject *so, PyObject *other)
17841805
}
17851806
Py_DECREF(key);
17861807
}
1808+
_PyObject_GC_TRACK(result);
17871809
returnresult;
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
returnNULL;
19761999
}
@@ -1982,6 +2005,7 @@ set_symmetric_difference_impl(PySetObject *so, PyObject *other)
19822005
Py_DECREF(result);
19832006
returnNULL;
19842007
}
2008+
_PyObject_GC_TRACK(result);
19852009
return (PyObject*)result;
19862010
}
19872011

0 commit comments

Comments
 (0)