Skip to content

Commit a3292c2

Browse files
committed
Do not track frozenset objects with immutables
1 parent 2ebd0cd commit a3292c2

File tree

1 file changed

+25
-2
lines changed

1 file changed

+25
-2
lines changed

Objects/setobject.c

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1174,6 +1174,23 @@ make_new_set_basetype(PyTypeObject *type, PyObject *iterable)
11741174
return make_new_set(type, iterable);
11751175
}
11761176

1177+
void
1178+
_PyFrozenSet_MaybeUntrack(PyObject *op)
1179+
{
1180+
if ((op ==NULL) || !(PyFrozenSet_CheckExact(op))) {
1181+
return;
1182+
}
1183+
// the frozenset is tracked by the GC. if all elements are immutable we can untrack
1184+
Py_ssize_t pos = 0;
1185+
setentry *entry;
1186+
while (set_next((PySetObject *)op, &pos, &entry)) {
1187+
if (_PyObject_GC_MAY_BE_TRACKED(entry->key)) {
1188+
return;
1189+
}
1190+
}
1191+
_PyObject_GC_UNTRACK(op);
1192+
}
1193+
11771194
static PyObject *
11781195
make_new_frozenset(PyTypeObject *type, PyObject *iterable)
11791196
{
@@ -1185,7 +1202,9 @@ make_new_frozenset(PyTypeObject *type, PyObject *iterable)
11851202
/* frozenset(f) is idempotent */
11861203
return Py_NewRef(iterable);
11871204
}
1188-
return make_new_set(type, iterable);
1205+
PyObject *obj = make_new_set(type, iterable);
1206+
_PyFrozenSet_MaybeUntrack(obj);
1207+
return obj;
11891208
}
11901209

11911210
static PyObject *
@@ -2710,7 +2729,11 @@ PySet_New(PyObject *iterable)
27102729
PyObject *
27112730
PyFrozenSet_New(PyObject *iterable)
27122731
{
2713-
return make_new_set(&PyFrozenSet_Type, iterable);
2732+
PyObject *result = make_new_set(&PyFrozenSet_Type, iterable);
2733+
if (result != NULL) {
2734+
_PyFrozenSet_MaybeUntrack(result);
2735+
}
2736+
return result;
27142737
}
27152738

27162739
Py_ssize_t

0 commit comments

Comments
 (0)