Skip to content

Commit

Permalink
GH-128682: Change a couple of functions to only steal references on s…
Browse files Browse the repository at this point in the history
…uccess. (GH-129132)

Change PyTuple_FromStackRefSteal and PyList_FromStackRefSteal to only steal on success to avoid escaping
  • Loading branch information
markshannon authored Jan 22, 2025
1 parent a65f802 commit 470a0a6
Show file tree
Hide file tree
Showing 11 changed files with 34 additions and 32 deletions.
2 changes: 1 addition & 1 deletion Include/internal/pycore_list.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ typedef struct {

union _PyStackRef;

PyAPI_FUNC(PyObject *)_PyList_FromStackRefSteal(const union _PyStackRef *src, Py_ssize_t n);
PyAPI_FUNC(PyObject *)_PyList_FromStackRefStealOnSuccess(const union _PyStackRef *src, Py_ssize_t n);
PyAPI_FUNC(PyObject *)_PyList_AsTupleAndClear(PyListObject *v);

#ifdef __cplusplus
Expand Down
4 changes: 2 additions & 2 deletions Include/internal/pycore_opcode_metadata.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Include/internal/pycore_tuple.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ extern PyStatus _PyTuple_InitGlobalObjects(PyInterpreterState *);
#define _PyTuple_ITEMS(op) _Py_RVALUE(_PyTuple_CAST(op)->ob_item)

PyAPI_FUNC(PyObject *)_PyTuple_FromArray(PyObject *const *, Py_ssize_t);
PyAPI_FUNC(PyObject *)_PyTuple_FromStackRefSteal(const union _PyStackRef *, Py_ssize_t);
PyAPI_FUNC(PyObject *)_PyTuple_FromStackRefStealOnSuccess(const union _PyStackRef *, Py_ssize_t);
PyAPI_FUNC(PyObject *)_PyTuple_FromArraySteal(PyObject *const *, Py_ssize_t);

typedef struct {
Expand Down
4 changes: 2 additions & 2 deletions Include/internal/pycore_uop_metadata.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 1 addition & 4 deletions Objects/listobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -3190,17 +3190,14 @@ _PyList_AsTupleAndClear(PyListObject *self)
}

PyObject *
_PyList_FromStackRefSteal(const _PyStackRef *src, Py_ssize_t n)
_PyList_FromStackRefStealOnSuccess(const _PyStackRef *src, Py_ssize_t n)
{
if (n == 0) {
return PyList_New(0);
}

PyListObject *list = (PyListObject *)PyList_New(n);
if (list == NULL) {
for (Py_ssize_t i = 0; i < n; i++) {
PyStackRef_CLOSE(src[i]);
}
return NULL;
}

Expand Down
5 changes: 1 addition & 4 deletions Objects/tupleobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -391,16 +391,13 @@ _PyTuple_FromArray(PyObject *const *src, Py_ssize_t n)
}

PyObject *
_PyTuple_FromStackRefSteal(const _PyStackRef *src, Py_ssize_t n)
_PyTuple_FromStackRefStealOnSuccess(const _PyStackRef *src, Py_ssize_t n)
{
if (n == 0) {
return tuple_get_empty();
}
PyTupleObject *tuple = tuple_alloc(n);
if (tuple == NULL) {
for (Py_ssize_t i = 0; i < n; i++) {
PyStackRef_CLOSE(src[i]);
}
return NULL;
}
PyObject **dst = tuple->ob_item;
Expand Down
12 changes: 8 additions & 4 deletions Python/bytecodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -1852,16 +1852,20 @@ dummy_func(
}

inst(BUILD_TUPLE, (values[oparg] -- tup)) {
PyObject *tup_o = _PyTuple_FromStackRefSteal(values, oparg);
PyObject *tup_o = _PyTuple_FromStackRefStealOnSuccess(values, oparg);
if (tup_o == NULL) {
ERROR_NO_POP();
}
INPUTS_DEAD();
ERROR_IF(tup_o == NULL, error);
tup = PyStackRef_FromPyObjectSteal(tup_o);
}

inst(BUILD_LIST, (values[oparg] -- list)) {
PyObject *list_o = _PyList_FromStackRefSteal(values, oparg);
PyObject *list_o = _PyList_FromStackRefStealOnSuccess(values, oparg);
if (list_o == NULL) {
ERROR_NO_POP();
}
INPUTS_DEAD();
ERROR_IF(list_o == NULL, error);
list = PyStackRef_FromPyObjectSteal(list_o);
}

Expand Down
7 changes: 6 additions & 1 deletion Python/ceval.c
Original file line number Diff line number Diff line change
Expand Up @@ -1527,7 +1527,12 @@ initialize_locals(PyThreadState *tstate, PyFunctionObject *func,
u = (PyObject *)&_Py_SINGLETON(tuple_empty);
}
else {
u = _PyTuple_FromStackRefSteal(args + n, argcount - n);
u = _PyTuple_FromStackRefStealOnSuccess(args + n, argcount - n);
if (u == NULL) {
for (Py_ssize_t i = n; i < argcount; i++) {
PyStackRef_CLOSE(args[i]);
}
}
}
if (u == NULL) {
goto fail_post_positional;
Expand Down
12 changes: 8 additions & 4 deletions Python/executor_cases.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 2 additions & 6 deletions Python/generated_cases.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 2 additions & 3 deletions Tools/cases_generator/analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -581,7 +581,7 @@ def has_error_without_pop(op: parser.InstDef) -> bool:
"_PyGen_GetGeneratorFromFrame",
"_PyInterpreterState_GET",
"_PyList_AppendTakeRef",
"_PyList_FromStackRefSteal",
"_PyList_FromStackRefStealOnSuccess",
"_PyList_ITEMS",
"_PyLong_Add",
"_PyLong_CompactValue",
Expand All @@ -600,8 +600,7 @@ def has_error_without_pop(op: parser.InstDef) -> bool:
"_PyObject_InlineValues",
"_PyObject_ManagedDictPointer",
"_PyThreadState_HasStackSpace",
"_PyTuple_FromArraySteal",
"_PyTuple_FromStackRefSteal",
"_PyTuple_FromStackRefStealOnSuccess",
"_PyTuple_ITEMS",
"_PyType_HasFeature",
"_PyType_NewManagedObject",
Expand Down

0 comments on commit 470a0a6

Please sign in to comment.