Skip to content
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion Lib/test/test_sys.py
Original file line number Diff line number Diff line change
Expand Up @@ -1876,7 +1876,10 @@ class S(set):
check(S(), set(), '3P')
class FS(frozenset):
__slots__ = 'a', 'b', 'c'
check(FS(), frozenset(), '3P')

class mytuple(tuple):
pass
check(FS([mytuple()]), frozenset([mytuple()]), '3P')
from collections import OrderedDict
class OD(OrderedDict):
__slots__ = 'a', 'b', 'c'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Frozenset objects with immutable elements are no longer tracked by the garbage collector.
25 changes: 23 additions & 2 deletions Objects/setobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -1174,6 +1174,23 @@ make_new_set_basetype(PyTypeObject *type, PyObject *iterable)
return make_new_set(type, iterable);
}

void
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a comment to explain the purpose of this function with a link to the GitHub issue.

_PyFrozenSet_MaybeUntrack(PyObject *op)
{
if ((op ==NULL) || !(PyFrozenSet_CheckExact(op))) {
return;
}
// if all elements of a frozenset are not tracked, we untrack the object
Py_ssize_t pos = 0;
setentry *entry;
while (set_next((PySetObject *)op, &pos, &entry)) {
if (_PyObject_GC_MAY_BE_TRACKED(entry->key)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should use faster _PyType_IS_GC(Py_TYPE(entry->key)) as in maybe_tracked from Objects/tupleobject.c?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure performance matters a lot, but I would prefer to have it consistent with what is used in tupleobject.c. Unless there are objections, I will change the implementation to use the maybe_tracked.

return;
}
}
_PyObject_GC_UNTRACK(op);
}

static PyObject *
make_new_frozenset(PyTypeObject *type, PyObject *iterable)
{
Expand All @@ -1185,7 +1202,9 @@ make_new_frozenset(PyTypeObject *type, PyObject *iterable)
/* frozenset(f) is idempotent */
return Py_NewRef(iterable);
}
return make_new_set(type, iterable);
PyObject *obj = make_new_set(type, iterable);
_PyFrozenSet_MaybeUntrack(obj);
return obj;
}

static PyObject *
Expand Down Expand Up @@ -2710,7 +2729,9 @@ PySet_New(PyObject *iterable)
PyObject *
PyFrozenSet_New(PyObject *iterable)
{
return make_new_set(&PyFrozenSet_Type, iterable);
PyObject *result = make_new_set(&PyFrozenSet_Type, iterable);
_PyFrozenSet_MaybeUntrack(result);
return result;
}

Py_ssize_t
Expand Down
Loading