Skip to content

Commit 5a549e8

Browse files
authored
gh-152235: Defer GC tracking in set.union and set.difference (gh-152290)
1 parent a85e73b commit 5a549e8

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
@@ -1577,6 +1577,21 @@ _PySet_Freeze(PyObject *set)
15771577
return Py_NewRef(set);
15781578
}
15791579

1580+
static PyObject *
1581+
set_copy_untracked_lock_held(PySetObject *so)
1582+
{
1583+
_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
1584+
PyObject *copy = make_new_set_basetype_untracked(Py_TYPE(so), NULL);
1585+
if (copy == NULL) {
1586+
return NULL;
1587+
}
1588+
if (set_merge_lock_held((PySetObject *)copy, (PyObject *)so) < 0) {
1589+
Py_DECREF(copy);
1590+
return NULL;
1591+
}
1592+
return copy;
1593+
}
1594+
15801595
/*[clinic input]
15811596
@critical_section
15821597
set.copy
@@ -1589,14 +1604,9 @@ static PyObject *
15891604
set_copy_impl(PySetObject *so)
15901605
/*[clinic end generated code: output=c9223a1e1cc6b041 input=c169a4fbb8209257]*/
15911606
{
1592-
_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
1593-
PyObject *copy = make_new_set_basetype(Py_TYPE(so), NULL);
1594-
if (copy == NULL) {
1595-
return NULL;
1596-
}
1597-
if (set_merge_lock_held((PySetObject *)copy, (PyObject *)so) < 0) {
1598-
Py_DECREF(copy);
1599-
return NULL;
1607+
PyObject *copy = set_copy_untracked_lock_held(so);
1608+
if (copy != NULL) {
1609+
_PyObject_GC_TRACK(copy);
16001610
}
16011611
return copy;
16021612
}
@@ -1652,7 +1662,8 @@ set_union_impl(PySetObject *so, PyObject * const *others,
16521662
PyObject *other;
16531663
Py_ssize_t i;
16541664

1655-
result = (PySetObject *)set_copy((PyObject *)so, NULL);
1665+
result = (PySetObject *)make_new_set_basetype_untracked(Py_TYPE(so),
1666+
(PyObject *)so);
16561667
if (result == NULL)
16571668
return NULL;
16581669

@@ -1665,6 +1676,7 @@ set_union_impl(PySetObject *so, PyObject * const *others,
16651676
return NULL;
16661677
}
16671678
}
1679+
_PyObject_GC_TRACK(result);
16681680
return (PyObject *)result;
16691681
}
16701682

@@ -2055,11 +2067,11 @@ set_difference_update_impl(PySetObject *so, PyObject * const *others,
20552067
}
20562068

20572069
static PyObject *
2058-
set_copy_and_difference(PySetObject *so, PyObject *other)
2070+
set_copy_and_difference_untracked(PySetObject *so, PyObject *other)
20592071
{
20602072
PyObject *result;
20612073

2062-
result = set_copy_impl(so);
2074+
result = set_copy_untracked_lock_held(so);
20632075
if (result == NULL)
20642076
return NULL;
20652077
if (set_difference_update_internal((PySetObject *) result, other) == 0)
@@ -2069,7 +2081,7 @@ set_copy_and_difference(PySetObject *so, PyObject *other)
20692081
}
20702082

20712083
static PyObject *
2072-
set_difference(PySetObject *so, PyObject *other)
2084+
set_difference_untracked(PySetObject *so, PyObject *other)
20732085
{
20742086
PyObject *result;
20752087
PyObject *key;
@@ -2085,13 +2097,13 @@ set_difference(PySetObject *so, PyObject *other)
20852097
other_size = PyDict_GET_SIZE(other);
20862098
}
20872099
else {
2088-
return set_copy_and_difference(so, other);
2100+
return set_copy_and_difference_untracked(so, other);
20892101
}
20902102

20912103
/* If len(so) much more than len(other), it's more efficient to simply copy
20922104
* so and then iterate other looking for common elements. */
20932105
if ((PySet_GET_SIZE(so) >> 2) > other_size) {
2094-
return set_copy_and_difference(so, other);
2106+
return set_copy_and_difference_untracked(so, other);
20952107
}
20962108

20972109
result = make_new_set_basetype_untracked(Py_TYPE(so), NULL);
@@ -2118,7 +2130,6 @@ set_difference(PySetObject *so, PyObject *other)
21182130
}
21192131
Py_DECREF(key);
21202132
}
2121-
_PyObject_GC_TRACK(result);
21222133
return result;
21232134
}
21242135

@@ -2142,7 +2153,6 @@ set_difference(PySetObject *so, PyObject *other)
21422153
}
21432154
Py_DECREF(key);
21442155
}
2145-
_PyObject_GC_TRACK(result);
21462156
return result;
21472157
}
21482158

@@ -2169,7 +2179,7 @@ set_difference_multi_impl(PySetObject *so, PyObject * const *others,
21692179

21702180
other = others[0];
21712181
Py_BEGIN_CRITICAL_SECTION2(so, other);
2172-
result = set_difference(so, other);
2182+
result = set_difference_untracked(so, other);
21732183
Py_END_CRITICAL_SECTION2();
21742184
if (result == NULL)
21752185
return NULL;
@@ -2185,6 +2195,7 @@ set_difference_multi_impl(PySetObject *so, PyObject * const *others,
21852195
return NULL;
21862196
}
21872197
}
2198+
_PyObject_GC_TRACK(result);
21882199
return result;
21892200
}
21902201

@@ -2197,8 +2208,11 @@ set_sub(PyObject *self, PyObject *other)
21972208

21982209
PyObject *rv;
21992210
Py_BEGIN_CRITICAL_SECTION2(so, other);
2200-
rv = set_difference(so, other);
2211+
rv = set_difference_untracked(so, other);
22012212
Py_END_CRITICAL_SECTION2();
2213+
if (rv != NULL) {
2214+
_PyObject_GC_TRACK(rv);
2215+
}
22022216
return rv;
22032217
}
22042218

0 commit comments

Comments
 (0)