Skip to content

Commit 89dc467

Browse files
Mark unique tuple freeing as non-escaping
1 parent 6bce6b4 commit 89dc467

File tree

7 files changed

+109
-47
lines changed

7 files changed

+109
-47
lines changed

Include/internal/pycore_tuple.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ extern PyStatus _PyTuple_InitGlobalObjects(PyInterpreterState *);
2121

2222
/* other API */
2323

24-
PyAPI_FUNC(void) _PyTuple_Free(PyObject *self);
24+
PyAPI_FUNC(void) _PyStolenTuple_Free(PyObject *self);
2525

2626
#define _PyTuple_ITEMS(op) _Py_RVALUE(_PyTuple_CAST(op)->ob_item)
2727

Include/internal/pycore_uop_ids.h

Lines changed: 9 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Include/internal/pycore_uop_metadata.h

Lines changed: 14 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Objects/tupleobject.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -234,16 +234,20 @@ _PyTuple_FromPairSteal(PyObject *first, PyObject *second)
234234

235235
/* Methods */
236236

237+
/*
238+
Free of a tuple where all contents have been stolen and
239+
is now untracked by GC. This operation is thus non-escaping.
240+
*/
237241
void
238-
_PyTuple_Free(PyObject *obj)
242+
_PyStolenTuple_Free(PyObject *obj)
239243
{
240244
assert(PyTuple_CheckExact(obj));
241245
PyTupleObject *op = _PyTuple_CAST(obj);
242246
assert(Py_SIZE(op) != 0);
243-
247+
assert(!_PyObject_GC_IS_TRACKED(obj));
244248
// This will abort on the empty singleton (if there is one).
245249
if (!maybe_freelist_push(op)) {
246-
Py_TYPE(op)->tp_free((PyObject *)op);
250+
PyTuple_Type.tp_free((PyObject *)op);
247251
}
248252
}
249253

Python/bytecodes.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
#include "pycore_sliceobject.h" // _PyBuildSlice_ConsumeRefs
3434
#include "pycore_stackref.h"
3535
#include "pycore_template.h" // _PyTemplate_Build()
36-
#include "pycore_tuple.h" // _PyTuple_Free(), _PyTuple_ITEMS()
36+
#include "pycore_tuple.h" // _PyStolenTuple_Free(), _PyTuple_ITEMS()
3737
#include "pycore_typeobject.h" // _PySuper_Lookup()
3838

3939
#include "pycore_dict.h"
@@ -1745,7 +1745,7 @@ dummy_func(
17451745
val0 = PyStackRef_FromPyObjectSteal(PyTuple_GET_ITEM(seq_o, 0));
17461746
val1 = PyStackRef_FromPyObjectSteal(PyTuple_GET_ITEM(seq_o, 1));
17471747
PyObject_GC_UnTrack(seq_o);
1748-
_PyTuple_Free(seq_o);
1748+
_PyStolenTuple_Free(seq_o);
17491749
}
17501750

17511751
op(_UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE, (seq -- val2, val1, val0)) {
@@ -1755,7 +1755,7 @@ dummy_func(
17551755
val1 = PyStackRef_FromPyObjectSteal(PyTuple_GET_ITEM(seq_o, 1));
17561756
val2 = PyStackRef_FromPyObjectSteal(PyTuple_GET_ITEM(seq_o, 2));
17571757
PyObject_GC_UnTrack(seq_o);
1758-
_PyTuple_Free(seq_o);
1758+
_PyStolenTuple_Free(seq_o);
17591759
}
17601760

17611761
macro(UNPACK_SEQUENCE_TUPLE) =
@@ -1784,7 +1784,7 @@ dummy_func(
17841784
*values++ = PyStackRef_FromPyObjectSteal(items[i]);
17851785
}
17861786
PyObject_GC_UnTrack(seq_o);
1787-
_PyTuple_Free(seq_o);
1787+
_PyStolenTuple_Free(seq_o);
17881788
}
17891789

17901790
macro(UNPACK_SEQUENCE_LIST) =

Python/executor_cases.c.h

Lines changed: 72 additions & 25 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Tools/cases_generator/analyzer.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -715,6 +715,8 @@ def has_error_without_pop(op: parser.CodeDef) -> bool:
715715
"_PyThreadState_PopCStackRefSteal",
716716
"doesnt_escape",
717717
"_Py_GatherStats_GetIter",
718+
"_PyStolenTuple_Free",
719+
"PyObject_GC_UnTrack",
718720
)
719721

720722

0 commit comments

Comments
 (0)