gh-117139: Add _PyTuple_FromStackRefSteal and use it (#121244)

Avoids the extra conversion from stack refs to PyObjects.
This commit is contained in:
Sam Gross 2024-07-02 12:30:14 -04:00 committed by GitHub
parent 1ac273224a
commit 8e8d202f55
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 28 additions and 33 deletions

View File

@ -48,7 +48,7 @@ extern "C" {
CPython refcounting operations on it! CPython refcounting operations on it!
*/ */
typedef union { typedef union _PyStackRef {
uintptr_t bits; uintptr_t bits;
} _PyStackRef; } _PyStackRef;

View File

@ -21,6 +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)
extern PyObject *_PyTuple_FromArray(PyObject *const *, Py_ssize_t); extern PyObject *_PyTuple_FromArray(PyObject *const *, Py_ssize_t);
PyAPI_FUNC(PyObject *)_PyTuple_FromStackRefSteal(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 {

View File

@ -390,6 +390,27 @@ _PyTuple_FromArray(PyObject *const *src, Py_ssize_t n)
return (PyObject *)tuple; return (PyObject *)tuple;
} }
PyObject *
_PyTuple_FromStackRefSteal(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;
for (Py_ssize_t i = 0; i < n; i++) {
dst[i] = PyStackRef_AsPyObjectSteal(src[i]);
}
_PyObject_GC_TRACK(tuple);
return (PyObject *)tuple;
}
PyObject * PyObject *
_PyTuple_FromArraySteal(PyObject *const *src, Py_ssize_t n) _PyTuple_FromArraySteal(PyObject *const *src, Py_ssize_t n)
{ {

View File

@ -1780,13 +1780,7 @@ dummy_func(
} }
inst(BUILD_TUPLE, (values[oparg] -- tup)) { inst(BUILD_TUPLE, (values[oparg] -- tup)) {
STACKREFS_TO_PYOBJECTS(values, oparg, values_o); PyObject *tup_o = _PyTuple_FromStackRefSteal(values, oparg);
if (CONVERSION_FAILED(values_o)) {
DECREF_INPUTS();
ERROR_IF(true, error);
}
PyObject *tup_o = _PyTuple_FromArraySteal(values_o, oparg);
STACKREFS_TO_PYOBJECTS_CLEANUP(values_o);
ERROR_IF(tup_o == NULL, error); ERROR_IF(tup_o == NULL, error);
tup = PyStackRef_FromPyObjectSteal(tup_o); tup = PyStackRef_FromPyObjectSteal(tup_o);
} }

View File

@ -1500,13 +1500,7 @@ initialize_locals(PyThreadState *tstate, PyFunctionObject *func,
u = (PyObject *)&_Py_SINGLETON(tuple_empty); u = (PyObject *)&_Py_SINGLETON(tuple_empty);
} }
else { else {
assert(args != NULL); u = _PyTuple_FromStackRefSteal(args + n, argcount - n);
STACKREFS_TO_PYOBJECTS((_PyStackRef *)args, argcount, args_o);
if (args_o == NULL) {
goto fail_pre_positional;
}
u = _PyTuple_FromArraySteal((args_o + n), argcount - n);
STACKREFS_TO_PYOBJECTS_CLEANUP(args_o);
} }
if (u == NULL) { if (u == NULL) {
goto fail_post_positional; goto fail_post_positional;

View File

@ -1816,15 +1816,7 @@
_PyStackRef tup; _PyStackRef tup;
oparg = CURRENT_OPARG(); oparg = CURRENT_OPARG();
values = &stack_pointer[-oparg]; values = &stack_pointer[-oparg];
STACKREFS_TO_PYOBJECTS(values, oparg, values_o); PyObject *tup_o = _PyTuple_FromStackRefSteal(values, oparg);
if (CONVERSION_FAILED(values_o)) {
for (int _i = oparg; --_i >= 0;) {
PyStackRef_CLOSE(values[_i]);
}
if (true) JUMP_TO_ERROR();
}
PyObject *tup_o = _PyTuple_FromArraySteal(values_o, oparg);
STACKREFS_TO_PYOBJECTS_CLEANUP(values_o);
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;

View File

@ -769,15 +769,7 @@
_PyStackRef *values; _PyStackRef *values;
_PyStackRef tup; _PyStackRef tup;
values = &stack_pointer[-oparg]; values = &stack_pointer[-oparg];
STACKREFS_TO_PYOBJECTS(values, oparg, values_o); PyObject *tup_o = _PyTuple_FromStackRefSteal(values, oparg);
if (CONVERSION_FAILED(values_o)) {
for (int _i = oparg; --_i >= 0;) {
PyStackRef_CLOSE(values[_i]);
}
if (true) { stack_pointer += -oparg; goto error; }
}
PyObject *tup_o = _PyTuple_FromArraySteal(values_o, oparg);
STACKREFS_TO_PYOBJECTS_CLEANUP(values_o);
if (tup_o == NULL) { stack_pointer += -oparg; goto error; } if (tup_o == NULL) { stack_pointer += -oparg; goto error; }
tup = PyStackRef_FromPyObjectSteal(tup_o); tup = PyStackRef_FromPyObjectSteal(tup_o);
stack_pointer[-oparg] = tup; stack_pointer[-oparg] = tup;

View File

@ -431,6 +431,7 @@ NON_ESCAPING_FUNCTIONS = (
"CONVERSION_FAILED", "CONVERSION_FAILED",
"_PyList_FromArraySteal", "_PyList_FromArraySteal",
"_PyTuple_FromArraySteal", "_PyTuple_FromArraySteal",
"_PyTuple_FromStackRefSteal",
) )
ESCAPING_FUNCTIONS = ( ESCAPING_FUNCTIONS = (