mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
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
This commit is contained in:
parent
a65f802692
commit
470a0a68eb
11 changed files with 34 additions and 32 deletions
|
@ -61,7 +61,7 @@ typedef struct {
|
||||||
|
|
||||||
union _PyStackRef;
|
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);
|
PyAPI_FUNC(PyObject *)_PyList_AsTupleAndClear(PyListObject *v);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
4
Include/internal/pycore_opcode_metadata.h
generated
4
Include/internal/pycore_opcode_metadata.h
generated
|
@ -2031,12 +2031,12 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[266] = {
|
||||||
[BINARY_SUBSCR_LIST_INT] = { true, INSTR_FMT_IXC, HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG },
|
[BINARY_SUBSCR_LIST_INT] = { true, INSTR_FMT_IXC, HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG },
|
||||||
[BINARY_SUBSCR_STR_INT] = { true, INSTR_FMT_IXC, HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG },
|
[BINARY_SUBSCR_STR_INT] = { true, INSTR_FMT_IXC, HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG },
|
||||||
[BINARY_SUBSCR_TUPLE_INT] = { true, INSTR_FMT_IXC, HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG },
|
[BINARY_SUBSCR_TUPLE_INT] = { true, INSTR_FMT_IXC, HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG },
|
||||||
[BUILD_LIST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG },
|
[BUILD_LIST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG },
|
||||||
[BUILD_MAP] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
|
[BUILD_MAP] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
|
||||||
[BUILD_SET] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
|
[BUILD_SET] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
|
||||||
[BUILD_SLICE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG },
|
[BUILD_SLICE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG },
|
||||||
[BUILD_STRING] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG },
|
[BUILD_STRING] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG },
|
||||||
[BUILD_TUPLE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG },
|
[BUILD_TUPLE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG },
|
||||||
[CACHE] = { true, INSTR_FMT_IX, 0 },
|
[CACHE] = { true, INSTR_FMT_IX, 0 },
|
||||||
[CALL] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG },
|
[CALL] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG },
|
||||||
[CALL_ALLOC_AND_ENTER_INIT] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG },
|
[CALL_ALLOC_AND_ENTER_INIT] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG },
|
||||||
|
|
|
@ -21,7 +21,7 @@ extern PyStatus _PyTuple_InitGlobalObjects(PyInterpreterState *);
|
||||||
#define _PyTuple_ITEMS(op) _Py_RVALUE(_PyTuple_CAST(op)->ob_item)
|
#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_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);
|
PyAPI_FUNC(PyObject *)_PyTuple_FromArraySteal(PyObject *const *, Py_ssize_t);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
4
Include/internal/pycore_uop_metadata.h
generated
4
Include/internal/pycore_uop_metadata.h
generated
|
@ -137,8 +137,8 @@ const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = {
|
||||||
[_STORE_DEREF] = HAS_ARG_FLAG | HAS_FREE_FLAG | HAS_ESCAPES_FLAG,
|
[_STORE_DEREF] = HAS_ARG_FLAG | HAS_FREE_FLAG | HAS_ESCAPES_FLAG,
|
||||||
[_COPY_FREE_VARS] = HAS_ARG_FLAG,
|
[_COPY_FREE_VARS] = HAS_ARG_FLAG,
|
||||||
[_BUILD_STRING] = HAS_ARG_FLAG | HAS_ERROR_FLAG,
|
[_BUILD_STRING] = HAS_ARG_FLAG | HAS_ERROR_FLAG,
|
||||||
[_BUILD_TUPLE] = HAS_ARG_FLAG | HAS_ERROR_FLAG,
|
[_BUILD_TUPLE] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG,
|
||||||
[_BUILD_LIST] = HAS_ARG_FLAG | HAS_ERROR_FLAG,
|
[_BUILD_LIST] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG,
|
||||||
[_LIST_EXTEND] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG,
|
[_LIST_EXTEND] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG,
|
||||||
[_SET_UPDATE] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG,
|
[_SET_UPDATE] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG,
|
||||||
[_BUILD_SET] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG,
|
[_BUILD_SET] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG,
|
||||||
|
|
|
@ -3190,7 +3190,7 @@ _PyList_AsTupleAndClear(PyListObject *self)
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
_PyList_FromStackRefSteal(const _PyStackRef *src, Py_ssize_t n)
|
_PyList_FromStackRefStealOnSuccess(const _PyStackRef *src, Py_ssize_t n)
|
||||||
{
|
{
|
||||||
if (n == 0) {
|
if (n == 0) {
|
||||||
return PyList_New(0);
|
return PyList_New(0);
|
||||||
|
@ -3198,9 +3198,6 @@ _PyList_FromStackRefSteal(const _PyStackRef *src, Py_ssize_t n)
|
||||||
|
|
||||||
PyListObject *list = (PyListObject *)PyList_New(n);
|
PyListObject *list = (PyListObject *)PyList_New(n);
|
||||||
if (list == NULL) {
|
if (list == NULL) {
|
||||||
for (Py_ssize_t i = 0; i < n; i++) {
|
|
||||||
PyStackRef_CLOSE(src[i]);
|
|
||||||
}
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -391,16 +391,13 @@ _PyTuple_FromArray(PyObject *const *src, Py_ssize_t n)
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
_PyTuple_FromStackRefSteal(const _PyStackRef *src, Py_ssize_t n)
|
_PyTuple_FromStackRefStealOnSuccess(const _PyStackRef *src, Py_ssize_t n)
|
||||||
{
|
{
|
||||||
if (n == 0) {
|
if (n == 0) {
|
||||||
return tuple_get_empty();
|
return tuple_get_empty();
|
||||||
}
|
}
|
||||||
PyTupleObject *tuple = tuple_alloc(n);
|
PyTupleObject *tuple = tuple_alloc(n);
|
||||||
if (tuple == NULL) {
|
if (tuple == NULL) {
|
||||||
for (Py_ssize_t i = 0; i < n; i++) {
|
|
||||||
PyStackRef_CLOSE(src[i]);
|
|
||||||
}
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
PyObject **dst = tuple->ob_item;
|
PyObject **dst = tuple->ob_item;
|
||||||
|
|
|
@ -1852,16 +1852,20 @@ dummy_func(
|
||||||
}
|
}
|
||||||
|
|
||||||
inst(BUILD_TUPLE, (values[oparg] -- tup)) {
|
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();
|
INPUTS_DEAD();
|
||||||
ERROR_IF(tup_o == NULL, error);
|
|
||||||
tup = PyStackRef_FromPyObjectSteal(tup_o);
|
tup = PyStackRef_FromPyObjectSteal(tup_o);
|
||||||
}
|
}
|
||||||
|
|
||||||
inst(BUILD_LIST, (values[oparg] -- list)) {
|
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();
|
INPUTS_DEAD();
|
||||||
ERROR_IF(list_o == NULL, error);
|
|
||||||
list = PyStackRef_FromPyObjectSteal(list_o);
|
list = PyStackRef_FromPyObjectSteal(list_o);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1527,7 +1527,12 @@ initialize_locals(PyThreadState *tstate, PyFunctionObject *func,
|
||||||
u = (PyObject *)&_Py_SINGLETON(tuple_empty);
|
u = (PyObject *)&_Py_SINGLETON(tuple_empty);
|
||||||
}
|
}
|
||||||
else {
|
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) {
|
if (u == NULL) {
|
||||||
goto fail_post_positional;
|
goto fail_post_positional;
|
||||||
|
|
12
Python/executor_cases.c.h
generated
12
Python/executor_cases.c.h
generated
|
@ -2240,8 +2240,10 @@
|
||||||
_PyStackRef tup;
|
_PyStackRef tup;
|
||||||
oparg = CURRENT_OPARG();
|
oparg = CURRENT_OPARG();
|
||||||
values = &stack_pointer[-oparg];
|
values = &stack_pointer[-oparg];
|
||||||
PyObject *tup_o = _PyTuple_FromStackRefSteal(values, oparg);
|
PyObject *tup_o = _PyTuple_FromStackRefStealOnSuccess(values, oparg);
|
||||||
if (tup_o == NULL) JUMP_TO_ERROR();
|
if (tup_o == NULL) {
|
||||||
|
JUMP_TO_ERROR();
|
||||||
|
}
|
||||||
tup = PyStackRef_FromPyObjectSteal(tup_o);
|
tup = PyStackRef_FromPyObjectSteal(tup_o);
|
||||||
stack_pointer[-oparg] = tup;
|
stack_pointer[-oparg] = tup;
|
||||||
stack_pointer += 1 - oparg;
|
stack_pointer += 1 - oparg;
|
||||||
|
@ -2254,8 +2256,10 @@
|
||||||
_PyStackRef list;
|
_PyStackRef list;
|
||||||
oparg = CURRENT_OPARG();
|
oparg = CURRENT_OPARG();
|
||||||
values = &stack_pointer[-oparg];
|
values = &stack_pointer[-oparg];
|
||||||
PyObject *list_o = _PyList_FromStackRefSteal(values, oparg);
|
PyObject *list_o = _PyList_FromStackRefStealOnSuccess(values, oparg);
|
||||||
if (list_o == NULL) JUMP_TO_ERROR();
|
if (list_o == NULL) {
|
||||||
|
JUMP_TO_ERROR();
|
||||||
|
}
|
||||||
list = PyStackRef_FromPyObjectSteal(list_o);
|
list = PyStackRef_FromPyObjectSteal(list_o);
|
||||||
stack_pointer[-oparg] = list;
|
stack_pointer[-oparg] = list;
|
||||||
stack_pointer += 1 - oparg;
|
stack_pointer += 1 - oparg;
|
||||||
|
|
8
Python/generated_cases.c.h
generated
8
Python/generated_cases.c.h
generated
|
@ -732,10 +732,8 @@
|
||||||
_PyStackRef *values;
|
_PyStackRef *values;
|
||||||
_PyStackRef list;
|
_PyStackRef list;
|
||||||
values = &stack_pointer[-oparg];
|
values = &stack_pointer[-oparg];
|
||||||
PyObject *list_o = _PyList_FromStackRefSteal(values, oparg);
|
PyObject *list_o = _PyList_FromStackRefStealOnSuccess(values, oparg);
|
||||||
if (list_o == NULL) {
|
if (list_o == NULL) {
|
||||||
stack_pointer += -oparg;
|
|
||||||
assert(WITHIN_STACK_BOUNDS());
|
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
list = PyStackRef_FromPyObjectSteal(list_o);
|
list = PyStackRef_FromPyObjectSteal(list_o);
|
||||||
|
@ -905,10 +903,8 @@
|
||||||
_PyStackRef *values;
|
_PyStackRef *values;
|
||||||
_PyStackRef tup;
|
_PyStackRef tup;
|
||||||
values = &stack_pointer[-oparg];
|
values = &stack_pointer[-oparg];
|
||||||
PyObject *tup_o = _PyTuple_FromStackRefSteal(values, oparg);
|
PyObject *tup_o = _PyTuple_FromStackRefStealOnSuccess(values, oparg);
|
||||||
if (tup_o == NULL) {
|
if (tup_o == NULL) {
|
||||||
stack_pointer += -oparg;
|
|
||||||
assert(WITHIN_STACK_BOUNDS());
|
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
tup = PyStackRef_FromPyObjectSteal(tup_o);
|
tup = PyStackRef_FromPyObjectSteal(tup_o);
|
||||||
|
|
|
@ -581,7 +581,7 @@ NON_ESCAPING_FUNCTIONS = (
|
||||||
"_PyGen_GetGeneratorFromFrame",
|
"_PyGen_GetGeneratorFromFrame",
|
||||||
"_PyInterpreterState_GET",
|
"_PyInterpreterState_GET",
|
||||||
"_PyList_AppendTakeRef",
|
"_PyList_AppendTakeRef",
|
||||||
"_PyList_FromStackRefSteal",
|
"_PyList_FromStackRefStealOnSuccess",
|
||||||
"_PyList_ITEMS",
|
"_PyList_ITEMS",
|
||||||
"_PyLong_Add",
|
"_PyLong_Add",
|
||||||
"_PyLong_CompactValue",
|
"_PyLong_CompactValue",
|
||||||
|
@ -600,8 +600,7 @@ NON_ESCAPING_FUNCTIONS = (
|
||||||
"_PyObject_InlineValues",
|
"_PyObject_InlineValues",
|
||||||
"_PyObject_ManagedDictPointer",
|
"_PyObject_ManagedDictPointer",
|
||||||
"_PyThreadState_HasStackSpace",
|
"_PyThreadState_HasStackSpace",
|
||||||
"_PyTuple_FromArraySteal",
|
"_PyTuple_FromStackRefStealOnSuccess",
|
||||||
"_PyTuple_FromStackRefSteal",
|
|
||||||
"_PyTuple_ITEMS",
|
"_PyTuple_ITEMS",
|
||||||
"_PyType_HasFeature",
|
"_PyType_HasFeature",
|
||||||
"_PyType_NewManagedObject",
|
"_PyType_NewManagedObject",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue