Skip to content

Commit 4fa86ca

Browse files
[3.14] gh-152235: Defer GC tracking in set.union and set.difference (gh-152290) (gh-152312)
gh-152235: Defer GC tracking in set.union and set.difference (gh-152290) (cherry picked from commit 5a549e8) Co-authored-by: Donghee Na <donghee.na@python.org>
1 parent dbcc053 commit 4fa86ca

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
@@ -1304,6 +1304,21 @@ set_swap_bodies(PySetObject *a, PySetObject *b)
13041304
}
13051305
}
13061306

1307+
static PyObject *
1308+
set_copy_untracked_lock_held(PySetObject *so)
1309+
{
1310+
_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
1311+
PyObject *copy = make_new_set_basetype_untracked(Py_TYPE(so), NULL);
1312+
if (copy == NULL) {
1313+
return NULL;
1314+
}
1315+
if (set_merge_lock_held((PySetObject *)copy, (PyObject *)so) < 0) {
1316+
Py_DECREF(copy);
1317+
return NULL;
1318+
}
1319+
return copy;
1320+
}
1321+
13071322
/*[clinic input]
13081323
@critical_section
13091324
set.copy
@@ -1316,14 +1331,9 @@ static PyObject *
13161331
set_copy_impl(PySetObject *so)
13171332
/*[clinic end generated code: output=c9223a1e1cc6b041 input=c169a4fbb8209257]*/
13181333
{
1319-
_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
1320-
PyObject *copy = make_new_set_basetype(Py_TYPE(so), NULL);
1321-
if (copy == NULL) {
1322-
return NULL;
1323-
}
1324-
if (set_merge_lock_held((PySetObject *)copy, (PyObject *)so) < 0) {
1325-
Py_DECREF(copy);
1326-
return NULL;
1334+
PyObject *copy = set_copy_untracked_lock_held(so);
1335+
if (copy != NULL) {
1336+
_PyObject_GC_TRACK(copy);
13271337
}
13281338
return copy;
13291339
}
@@ -1379,7 +1389,8 @@ set_union_impl(PySetObject *so, PyObject * const *others,
13791389
PyObject *other;
13801390
Py_ssize_t i;
13811391

1382-
result = (PySetObject *)set_copy((PyObject *)so, NULL);
1392+
result = (PySetObject *)make_new_set_basetype_untracked(Py_TYPE(so),
1393+
(PyObject *)so);
13831394
if (result == NULL)
13841395
return NULL;
13851396

@@ -1392,6 +1403,7 @@ set_union_impl(PySetObject *so, PyObject * const *others,
13921403
return NULL;
13931404
}
13941405
}
1406+
_PyObject_GC_TRACK(result);
13951407
return (PyObject *)result;
13961408
}
13971409

@@ -1782,11 +1794,11 @@ set_difference_update_impl(PySetObject *so, PyObject * const *others,
17821794
}
17831795

17841796
static PyObject *
1785-
set_copy_and_difference(PySetObject *so, PyObject *other)
1797+
set_copy_and_difference_untracked(PySetObject *so, PyObject *other)
17861798
{
17871799
PyObject *result;
17881800

1789-
result = set_copy_impl(so);
1801+
result = set_copy_untracked_lock_held(so);
17901802
if (result == NULL)
17911803
return NULL;
17921804
if (set_difference_update_internal((PySetObject *) result, other) == 0)
@@ -1796,7 +1808,7 @@ set_copy_and_difference(PySetObject *so, PyObject *other)
17961808
}
17971809

17981810
static PyObject *
1799-
set_difference(PySetObject *so, PyObject *other)
1811+
set_difference_untracked(PySetObject *so, PyObject *other)
18001812
{
18011813
PyObject *result;
18021814
PyObject *key;
@@ -1812,13 +1824,13 @@ set_difference(PySetObject *so, PyObject *other)
18121824
other_size = PyDict_GET_SIZE(other);
18131825
}
18141826
else {
1815-
return set_copy_and_difference(so, other);
1827+
return set_copy_and_difference_untracked(so, other);
18161828
}
18171829

18181830
/* If len(so) much more than len(other), it's more efficient to simply copy
18191831
* so and then iterate other looking for common elements. */
18201832
if ((PySet_GET_SIZE(so) >> 2) > other_size) {
1821-
return set_copy_and_difference(so, other);
1833+
return set_copy_and_difference_untracked(so, other);
18221834
}
18231835

18241836
result = make_new_set_basetype_untracked(Py_TYPE(so), NULL);
@@ -1845,7 +1857,6 @@ set_difference(PySetObject *so, PyObject *other)
18451857
}
18461858
Py_DECREF(key);
18471859
}
1848-
_PyObject_GC_TRACK(result);
18491860
return result;
18501861
}
18511862

@@ -1869,7 +1880,6 @@ set_difference(PySetObject *so, PyObject *other)
18691880
}
18701881
Py_DECREF(key);
18711882
}
1872-
_PyObject_GC_TRACK(result);
18731883
return result;
18741884
}
18751885

@@ -1895,7 +1905,7 @@ set_difference_multi_impl(PySetObject *so, PyObject * const *others,
18951905

18961906
other = others[0];
18971907
Py_BEGIN_CRITICAL_SECTION2(so, other);
1898-
result = set_difference(so, other);
1908+
result = set_difference_untracked(so, other);
18991909
Py_END_CRITICAL_SECTION2();
19001910
if (result == NULL)
19011911
return NULL;
@@ -1911,6 +1921,7 @@ set_difference_multi_impl(PySetObject *so, PyObject * const *others,
19111921
return NULL;
19121922
}
19131923
}
1924+
_PyObject_GC_TRACK(result);
19141925
return result;
19151926
}
19161927

@@ -1923,8 +1934,11 @@ set_sub(PyObject *self, PyObject *other)
19231934

19241935
PyObject *rv;
19251936
Py_BEGIN_CRITICAL_SECTION2(so, other);
1926-
rv = set_difference(so, other);
1937+
rv = set_difference_untracked(so, other);
19271938
Py_END_CRITICAL_SECTION2();
1939+
if (rv != NULL) {
1940+
_PyObject_GC_TRACK(rv);
1941+
}
19281942
return rv;
19291943
}
19301944

0 commit comments

Comments
 (0)