Skip to content

Commit 073b658

Browse files
authored
[3.15] gh-152235: Defer GC tracking in set.union and set.difference (gh-152290) (gh-152316)
(cherry picked from commit 5a549e8)
1 parent 52bdfcc commit 073b658

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
@@ -1567,6 +1567,21 @@ set_swap_bodies(PySetObject *a, PySetObject *b)
15671567
FT_ATOMIC_STORE_PTR_RELEASE(b->table, b_table);
15681568
}
15691569

1570+
static PyObject *
1571+
set_copy_untracked_lock_held(PySetObject *so)
1572+
{
1573+
_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
1574+
PyObject *copy = make_new_set_basetype_untracked(Py_TYPE(so), NULL);
1575+
if (copy == NULL) {
1576+
return NULL;
1577+
}
1578+
if (set_merge_lock_held((PySetObject *)copy, (PyObject *)so) < 0) {
1579+
Py_DECREF(copy);
1580+
return NULL;
1581+
}
1582+
return copy;
1583+
}
1584+
15701585
/*[clinic input]
15711586
@critical_section
15721587
set.copy
@@ -1579,14 +1594,9 @@ static PyObject *
15791594
set_copy_impl(PySetObject *so)
15801595
/*[clinic end generated code: output=c9223a1e1cc6b041 input=c169a4fbb8209257]*/
15811596
{
1582-
_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
1583-
PyObject *copy = make_new_set_basetype(Py_TYPE(so), NULL);
1584-
if (copy == NULL) {
1585-
return NULL;
1586-
}
1587-
if (set_merge_lock_held((PySetObject *)copy, (PyObject *)so) < 0) {
1588-
Py_DECREF(copy);
1589-
return NULL;
1597+
PyObject *copy = set_copy_untracked_lock_held(so);
1598+
if (copy != NULL) {
1599+
_PyObject_GC_TRACK(copy);
15901600
}
15911601
return copy;
15921602
}
@@ -1642,7 +1652,8 @@ set_union_impl(PySetObject *so, PyObject * const *others,
16421652
PyObject *other;
16431653
Py_ssize_t i;
16441654

1645-
result = (PySetObject *)set_copy((PyObject *)so, NULL);
1655+
result = (PySetObject *)make_new_set_basetype_untracked(Py_TYPE(so),
1656+
(PyObject *)so);
16461657
if (result == NULL)
16471658
return NULL;
16481659

@@ -1655,6 +1666,7 @@ set_union_impl(PySetObject *so, PyObject * const *others,
16551666
return NULL;
16561667
}
16571668
}
1669+
_PyObject_GC_TRACK(result);
16581670
return (PyObject *)result;
16591671
}
16601672

@@ -2045,11 +2057,11 @@ set_difference_update_impl(PySetObject *so, PyObject * const *others,
20452057
}
20462058

20472059
static PyObject *
2048-
set_copy_and_difference(PySetObject *so, PyObject *other)
2060+
set_copy_and_difference_untracked(PySetObject *so, PyObject *other)
20492061
{
20502062
PyObject *result;
20512063

2052-
result = set_copy_impl(so);
2064+
result = set_copy_untracked_lock_held(so);
20532065
if (result == NULL)
20542066
return NULL;
20552067
if (set_difference_update_internal((PySetObject *) result, other) == 0)
@@ -2059,7 +2071,7 @@ set_copy_and_difference(PySetObject *so, PyObject *other)
20592071
}
20602072

20612073
static PyObject *
2062-
set_difference(PySetObject *so, PyObject *other)
2074+
set_difference_untracked(PySetObject *so, PyObject *other)
20632075
{
20642076
PyObject *result;
20652077
PyObject *key;
@@ -2075,13 +2087,13 @@ set_difference(PySetObject *so, PyObject *other)
20752087
other_size = PyDict_GET_SIZE(other);
20762088
}
20772089
else {
2078-
return set_copy_and_difference(so, other);
2090+
return set_copy_and_difference_untracked(so, other);
20792091
}
20802092

20812093
/* If len(so) much more than len(other), it's more efficient to simply copy
20822094
* so and then iterate other looking for common elements. */
20832095
if ((PySet_GET_SIZE(so) >> 2) > other_size) {
2084-
return set_copy_and_difference(so, other);
2096+
return set_copy_and_difference_untracked(so, other);
20852097
}
20862098

20872099
result = make_new_set_basetype_untracked(Py_TYPE(so), NULL);
@@ -2108,7 +2120,6 @@ set_difference(PySetObject *so, PyObject *other)
21082120
}
21092121
Py_DECREF(key);
21102122
}
2111-
_PyObject_GC_TRACK(result);
21122123
return result;
21132124
}
21142125

@@ -2132,7 +2143,6 @@ set_difference(PySetObject *so, PyObject *other)
21322143
}
21332144
Py_DECREF(key);
21342145
}
2135-
_PyObject_GC_TRACK(result);
21362146
return result;
21372147
}
21382148

@@ -2159,7 +2169,7 @@ set_difference_multi_impl(PySetObject *so, PyObject * const *others,
21592169

21602170
other = others[0];
21612171
Py_BEGIN_CRITICAL_SECTION2(so, other);
2162-
result = set_difference(so, other);
2172+
result = set_difference_untracked(so, other);
21632173
Py_END_CRITICAL_SECTION2();
21642174
if (result == NULL)
21652175
return NULL;
@@ -2175,6 +2185,7 @@ set_difference_multi_impl(PySetObject *so, PyObject * const *others,
21752185
return NULL;
21762186
}
21772187
}
2188+
_PyObject_GC_TRACK(result);
21782189
return result;
21792190
}
21802191

@@ -2187,8 +2198,11 @@ set_sub(PyObject *self, PyObject *other)
21872198

21882199
PyObject *rv;
21892200
Py_BEGIN_CRITICAL_SECTION2(so, other);
2190-
rv = set_difference(so, other);
2201+
rv = set_difference_untracked(so, other);
21912202
Py_END_CRITICAL_SECTION2();
2203+
if (rv != NULL) {
2204+
_PyObject_GC_TRACK(rv);
2205+
}
21922206
return rv;
21932207
}
21942208

0 commit comments

Comments
 (0)