Skip to content

Commit a39b8a5

Browse files
committed
Address review: skip the fast path for a comprehension that is not inlined
Instead of copying a shared set in make_frozenset(), don't use the frozenset() fast path for a set comprehension that is not inlined. Only such a comprehension returns its set from a call, where a trace function can keep it, so make_frozenset() keeps its assumption that the set is uniquely referenced and other uses pay for no extra check.
1 parent 65e3277 commit a39b8a5

2 files changed

Lines changed: 15 additions & 3 deletions

File tree

‎Python/codegen.c‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4029,6 +4029,20 @@ maybe_optimize_function_call(compiler *c, expr_ty e, jump_target_label end)
40294029

40304030
if (_PyUnicode_EqualToASCIIString(func->v.Name.id, "frozenset")
40314031
&& (arg_expr->kind == Set_kind || arg_expr->kind == SetComp_kind)) {
4032+
if (arg_expr->kind == SetComp_kind) {
4033+
/* A comprehension that is not inlined returns its set from a
4034+
call, so a trace function may still hold a reference to it. */
4035+
PySTEntryObject *entry = _PySymtable_Lookup(SYMTABLE(c),
4036+
(void *)arg_expr);
4037+
if (entry == NULL) {
4038+
return ERROR;
4039+
}
4040+
int is_inlined = (entry->ste_type == InlinedComprehensionBlock);
4041+
Py_DECREF(entry);
4042+
if (!is_inlined) {
4043+
return 0;
4044+
}
4045+
}
40324046
NEW_JUMP_TARGET_LABEL(c, skip_optimization);
40334047

40344048
ADDOP_I(c, loc, COPY, 1);

‎Python/intrinsics.c‎

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -212,9 +212,7 @@ static PyObject *
212212
make_frozenset(PyThreadState* Py_UNUSED(ignored), PyObject *set)
213213
{
214214
assert(PySet_CheckExact(set));
215-
if (!_PyObject_IsUniquelyReferenced(set)) {
216-
return PyFrozenSet_New(set);
217-
}
215+
assert(_PyObject_IsUniquelyReferenced(set));
218216
return _PySet_Freeze(set);
219217
}
220218

0 commit comments

Comments
 (0)