Skip to content

Commit 668860b

Browse files
authored
[3.13] gh-152235: Defer GC tracking in set.union and set.difference (gh-152290) (gh-152319)
(cherry picked from commit 5a549e8)
1 parent 80dddd2 commit 668860b

2 files changed

Lines changed: 35 additions & 20 deletions

File tree

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

Objects/setobject.c

Lines changed: 32 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1247,6 +1247,21 @@ set_swap_bodies(PySetObject *a, PySetObject *b)
12471247
}
12481248
}
12491249

1250+
static PyObject *
1251+
set_copy_untracked_lock_held(PySetObject *so)
1252+
{
1253+
_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
1254+
PyObject *copy = make_new_set_basetype_untracked(Py_TYPE(so), NULL);
1255+
if (copy == NULL) {
1256+
return NULL;
1257+
}
1258+
if (set_merge_lock_held((PySetObject *)copy, (PyObject *)so) < 0) {
1259+
Py_DECREF(copy);
1260+
return NULL;
1261+
}
1262+
return copy;
1263+
}
1264+
12501265
/*[clinic input]
12511266
@critical_section
12521267
set.copy
@@ -1259,14 +1274,9 @@ static PyObject *
12591274
set_copy_impl(PySetObject *so)
12601275
/*[clinic end generated code: output=c9223a1e1cc6b041 input=c169a4fbb8209257]*/
12611276
{
1262-
_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
1263-
PyObject *copy = make_new_set_basetype(Py_TYPE(so), NULL);
1264-
if (copy == NULL) {
1265-
return NULL;
1266-
}
1267-
if (set_merge_lock_held((PySetObject *)copy, (PyObject *)so) < 0) {
1268-
Py_DECREF(copy);
1269-
return NULL;
1277+
PyObject *copy = set_copy_untracked_lock_held(so);
1278+
if (copy != NULL) {
1279+
_PyObject_GC_TRACK(copy);
12701280
}
12711281
return copy;
12721282
}
@@ -1321,7 +1331,8 @@ set_union_impl(PySetObject *so, PyObject *args)
13211331
PyObject *other;
13221332
Py_ssize_t i;
13231333

1324-
result = (PySetObject *)set_copy(so, NULL);
1334+
result = (PySetObject *)make_new_set_basetype_untracked(Py_TYPE(so),
1335+
(PyObject *)so);
13251336
if (result == NULL)
13261337
return NULL;
13271338

@@ -1334,6 +1345,7 @@ set_union_impl(PySetObject *so, PyObject *args)
13341345
return NULL;
13351346
}
13361347
}
1348+
_PyObject_GC_TRACK(result);
13371349
return (PyObject *)result;
13381350
}
13391351

@@ -1718,11 +1730,11 @@ set_difference_update_impl(PySetObject *so, PyObject *args)
17181730
}
17191731

17201732
static PyObject *
1721-
set_copy_and_difference(PySetObject *so, PyObject *other)
1733+
set_copy_and_difference_untracked(PySetObject *so, PyObject *other)
17221734
{
17231735
PyObject *result;
17241736

1725-
result = set_copy_impl(so);
1737+
result = set_copy_untracked_lock_held(so);
17261738
if (result == NULL)
17271739
return NULL;
17281740
if (set_difference_update_internal((PySetObject *) result, other) == 0)
@@ -1732,7 +1744,7 @@ set_copy_and_difference(PySetObject *so, PyObject *other)
17321744
}
17331745

17341746
static PyObject *
1735-
set_difference(PySetObject *so, PyObject *other)
1747+
set_difference_untracked(PySetObject *so, PyObject *other)
17361748
{
17371749
PyObject *result;
17381750
PyObject *key;
@@ -1748,13 +1760,13 @@ set_difference(PySetObject *so, PyObject *other)
17481760
other_size = PyDict_GET_SIZE(other);
17491761
}
17501762
else {
1751-
return set_copy_and_difference(so, other);
1763+
return set_copy_and_difference_untracked(so, other);
17521764
}
17531765

17541766
/* If len(so) much more than len(other), it's more efficient to simply copy
17551767
* so and then iterate other looking for common elements. */
17561768
if ((PySet_GET_SIZE(so) >> 2) > other_size) {
1757-
return set_copy_and_difference(so, other);
1769+
return set_copy_and_difference_untracked(so, other);
17581770
}
17591771

17601772
result = make_new_set_basetype_untracked(Py_TYPE(so), NULL);
@@ -1781,7 +1793,6 @@ set_difference(PySetObject *so, PyObject *other)
17811793
}
17821794
Py_DECREF(key);
17831795
}
1784-
_PyObject_GC_TRACK(result);
17851796
return result;
17861797
}
17871798

@@ -1805,7 +1816,6 @@ set_difference(PySetObject *so, PyObject *other)
18051816
}
18061817
Py_DECREF(key);
18071818
}
1808-
_PyObject_GC_TRACK(result);
18091819
return result;
18101820
}
18111821

@@ -1830,7 +1840,7 @@ set_difference_multi_impl(PySetObject *so, PyObject *args)
18301840

18311841
other = PyTuple_GET_ITEM(args, 0);
18321842
Py_BEGIN_CRITICAL_SECTION2(so, other);
1833-
result = set_difference(so, other);
1843+
result = set_difference_untracked(so, other);
18341844
Py_END_CRITICAL_SECTION2();
18351845
if (result == NULL)
18361846
return NULL;
@@ -1846,6 +1856,7 @@ set_difference_multi_impl(PySetObject *so, PyObject *args)
18461856
return NULL;
18471857
}
18481858
}
1859+
_PyObject_GC_TRACK(result);
18491860
return result;
18501861
}
18511862

@@ -1857,8 +1868,11 @@ set_sub(PySetObject *so, PyObject *other)
18571868

18581869
PyObject *rv;
18591870
Py_BEGIN_CRITICAL_SECTION2(so, other);
1860-
rv = set_difference(so, other);
1871+
rv = set_difference_untracked(so, other);
18611872
Py_END_CRITICAL_SECTION2();
1873+
if (rv != NULL) {
1874+
_PyObject_GC_TRACK(rv);
1875+
}
18621876
return rv;
18631877
}
18641878

0 commit comments

Comments
 (0)