Skip to content

Commit 470a0a6

Browse files
authored
GH-128682: Change a couple of functions to only steal references on success. (GH-129132)
Change PyTuple_FromStackRefSteal and PyList_FromStackRefSteal to only steal on success to avoid escaping
1 parent a65f802 commit 470a0a6

11 files changed

+34
-32
lines changed

Include/internal/pycore_list.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ typedef struct {
6161

6262
union _PyStackRef;
6363

64-
PyAPI_FUNC(PyObject *)_PyList_FromStackRefSteal(const union _PyStackRef *src, Py_ssize_t n);
64+
PyAPI_FUNC(PyObject *)_PyList_FromStackRefStealOnSuccess(const union _PyStackRef *src, Py_ssize_t n);
6565
PyAPI_FUNC(PyObject *)_PyList_AsTupleAndClear(PyListObject *v);
6666

6767
#ifdef __cplusplus

Include/internal/pycore_opcode_metadata.h

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

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
#define _PyTuple_ITEMS(op) _Py_RVALUE(_PyTuple_CAST(op)->ob_item)
2222

2323
PyAPI_FUNC(PyObject *)_PyTuple_FromArray(PyObject *const *, Py_ssize_t);
24-
PyAPI_FUNC(PyObject *)_PyTuple_FromStackRefSteal(const union _PyStackRef *, Py_ssize_t);
24+
PyAPI_FUNC(PyObject *)_PyTuple_FromStackRefStealOnSuccess(const union _PyStackRef *, Py_ssize_t);
2525
PyAPI_FUNC(PyObject *)_PyTuple_FromArraySteal(PyObject *const *, Py_ssize_t);
2626

2727
typedef struct {

Include/internal/pycore_uop_metadata.h

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

Objects/listobject.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3190,17 +3190,14 @@ _PyList_AsTupleAndClear(PyListObject *self)
31903190
}
31913191

31923192
PyObject *
3193-
_PyList_FromStackRefSteal(const _PyStackRef *src, Py_ssize_t n)
3193+
_PyList_FromStackRefStealOnSuccess(const _PyStackRef *src, Py_ssize_t n)
31943194
{
31953195
if (n == 0) {
31963196
return PyList_New(0);
31973197
}
31983198

31993199
PyListObject *list = (PyListObject *)PyList_New(n);
32003200
if (list == NULL) {
3201-
for (Py_ssize_t i = 0; i < n; i++) {
3202-
PyStackRef_CLOSE(src[i]);
3203-
}
32043201
return NULL;
32053202
}
32063203

Objects/tupleobject.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -391,16 +391,13 @@ _PyTuple_FromArray(PyObject *const *src, Py_ssize_t n)
391391
}
392392

393393
PyObject *
394-
_PyTuple_FromStackRefSteal(const _PyStackRef *src, Py_ssize_t n)
394+
_PyTuple_FromStackRefStealOnSuccess(const _PyStackRef *src, Py_ssize_t n)
395395
{
396396
if (n == 0) {
397397
return tuple_get_empty();
398398
}
399399
PyTupleObject *tuple = tuple_alloc(n);
400400
if (tuple == NULL) {
401-
for (Py_ssize_t i = 0; i < n; i++) {
402-
PyStackRef_CLOSE(src[i]);
403-
}
404401
return NULL;
405402
}
406403
PyObject **dst = tuple->ob_item;

Python/bytecodes.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1852,16 +1852,20 @@ dummy_func(
18521852
}
18531853

18541854
inst(BUILD_TUPLE, (values[oparg] -- tup)) {
1855-
PyObject *tup_o = _PyTuple_FromStackRefSteal(values, oparg);
1855+
PyObject *tup_o = _PyTuple_FromStackRefStealOnSuccess(values, oparg);
1856+
if (tup_o == NULL) {
1857+
ERROR_NO_POP();
1858+
}
18561859
INPUTS_DEAD();
1857-
ERROR_IF(tup_o == NULL, error);
18581860
tup = PyStackRef_FromPyObjectSteal(tup_o);
18591861
}
18601862

18611863
inst(BUILD_LIST, (values[oparg] -- list)) {
1862-
PyObject *list_o = _PyList_FromStackRefSteal(values, oparg);
1864+
PyObject *list_o = _PyList_FromStackRefStealOnSuccess(values, oparg);
1865+
if (list_o == NULL) {
1866+
ERROR_NO_POP();
1867+
}
18631868
INPUTS_DEAD();
1864-
ERROR_IF(list_o == NULL, error);
18651869
list = PyStackRef_FromPyObjectSteal(list_o);
18661870
}
18671871

Python/ceval.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1527,7 +1527,12 @@ initialize_locals(PyThreadState *tstate, PyFunctionObject *func,
15271527
u = (PyObject *)&_Py_SINGLETON(tuple_empty);
15281528
}
15291529
else {
1530-
u = _PyTuple_FromStackRefSteal(args + n, argcount - n);
1530+
u = _PyTuple_FromStackRefStealOnSuccess(args + n, argcount - n);
1531+
if (u == NULL) {
1532+
for (Py_ssize_t i = n; i < argcount; i++) {
1533+
PyStackRef_CLOSE(args[i]);
1534+
}
1535+
}
15311536
}
15321537
if (u == NULL) {
15331538
goto fail_post_positional;

Python/executor_cases.c.h

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

Python/generated_cases.c.h

Lines changed: 2 additions & 6 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 & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -581,7 +581,7 @@ def has_error_without_pop(op: parser.InstDef) -> bool:
581581
"_PyGen_GetGeneratorFromFrame",
582582
"_PyInterpreterState_GET",
583583
"_PyList_AppendTakeRef",
584-
"_PyList_FromStackRefSteal",
584+
"_PyList_FromStackRefStealOnSuccess",
585585
"_PyList_ITEMS",
586586
"_PyLong_Add",
587587
"_PyLong_CompactValue",
@@ -600,8 +600,7 @@ def has_error_without_pop(op: parser.InstDef) -> bool:
600600
"_PyObject_InlineValues",
601601
"_PyObject_ManagedDictPointer",
602602
"_PyThreadState_HasStackSpace",
603-
"_PyTuple_FromArraySteal",
604-
"_PyTuple_FromStackRefSteal",
603+
"_PyTuple_FromStackRefStealOnSuccess",
605604
"_PyTuple_ITEMS",
606605
"_PyType_HasFeature",
607606
"_PyType_NewManagedObject",

0 commit comments

Comments
 (0)