Skip to content

Commit

Permalink
gh-117139: Add _PyTuple_FromStackRefSteal and use it (#121244)
Browse files Browse the repository at this point in the history
Avoids the extra conversion from stack refs to PyObjects.
  • Loading branch information
colesbury authored Jul 2, 2024
1 parent 1ac2732 commit 8e8d202
Show file tree
Hide file tree
Showing 8 changed files with 28 additions and 33 deletions.
2 changes: 1 addition & 1 deletion Include/internal/pycore_stackref.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ extern "C" {
CPython refcounting operations on it!
*/

typedef union {
typedef union _PyStackRef {
uintptr_t bits;
} _PyStackRef;

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

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);

typedef struct {
Expand Down
21 changes: 21 additions & 0 deletions Objects/tupleobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,27 @@ _PyTuple_FromArray(PyObject *const *src, Py_ssize_t n)
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 *
_PyTuple_FromArraySteal(PyObject *const *src, Py_ssize_t n)
{
Expand Down
8 changes: 1 addition & 7 deletions Python/bytecodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -1780,13 +1780,7 @@ dummy_func(
}

inst(BUILD_TUPLE, (values[oparg] -- tup)) {
STACKREFS_TO_PYOBJECTS(values, oparg, values_o);
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);
PyObject *tup_o = _PyTuple_FromStackRefSteal(values, oparg);
ERROR_IF(tup_o == NULL, error);
tup = PyStackRef_FromPyObjectSteal(tup_o);
}
Expand Down
8 changes: 1 addition & 7 deletions Python/ceval.c
Original file line number Diff line number Diff line change
Expand Up @@ -1500,13 +1500,7 @@ initialize_locals(PyThreadState *tstate, PyFunctionObject *func,
u = (PyObject *)&_Py_SINGLETON(tuple_empty);
}
else {
assert(args != NULL);
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);
u = _PyTuple_FromStackRefSteal(args + n, argcount - n);
}
if (u == NULL) {
goto fail_post_positional;
Expand Down
10 changes: 1 addition & 9 deletions Python/executor_cases.c.h

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

10 changes: 1 addition & 9 deletions Python/generated_cases.c.h

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

1 change: 1 addition & 0 deletions Tools/cases_generator/analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,7 @@ def has_error_without_pop(op: parser.InstDef) -> bool:
"CONVERSION_FAILED",
"_PyList_FromArraySteal",
"_PyTuple_FromArraySteal",
"_PyTuple_FromStackRefSteal",
)

ESCAPING_FUNCTIONS = (
Expand Down

0 comments on commit 8e8d202

Please sign in to comment.