mirror of
https://github.com/python/cpython.git
synced 2026-04-13 15:20:52 +00:00
gh-144569: Avoid creating temporary objects in BINARY_SLICE for list, tuple, and unicode (GH-144590)
* Scalar replacement of BINARY_SLICE for list, tuple, and unicode
This commit is contained in:
parent
1cf5abedeb
commit
107863ee17
13 changed files with 256 additions and 77 deletions
|
|
@ -866,19 +866,30 @@ dummy_func(
|
|||
}
|
||||
|
||||
op(_BINARY_SLICE, (container, start, stop -- res)) {
|
||||
PyObject *slice = _PyBuildSlice_ConsumeRefs(PyStackRef_AsPyObjectSteal(start),
|
||||
PyStackRef_AsPyObjectSteal(stop));
|
||||
PyObject *container_o = PyStackRef_AsPyObjectBorrow(container);
|
||||
PyObject *start_o = PyStackRef_AsPyObjectBorrow(start);
|
||||
PyObject *stop_o = PyStackRef_AsPyObjectBorrow(stop);
|
||||
PyObject *res_o;
|
||||
// Can't use ERROR_IF() here, because we haven't
|
||||
// DECREF'ed container yet, and we still own slice.
|
||||
if (slice == NULL) {
|
||||
res_o = NULL;
|
||||
if (PyList_CheckExact(container_o)) {
|
||||
res_o = _PyList_BinarySlice(container_o, start_o, stop_o);
|
||||
}
|
||||
else if (PyTuple_CheckExact(container_o)) {
|
||||
res_o = _PyTuple_BinarySlice(container_o, start_o, stop_o);
|
||||
}
|
||||
else if (PyUnicode_CheckExact(container_o)) {
|
||||
res_o = _PyUnicode_BinarySlice(container_o, start_o, stop_o);
|
||||
}
|
||||
else {
|
||||
res_o = PyObject_GetItem(PyStackRef_AsPyObjectBorrow(container), slice);
|
||||
Py_DECREF(slice);
|
||||
PyObject *slice = PySlice_New(start_o, stop_o, NULL);
|
||||
if (slice == NULL) {
|
||||
res_o = NULL;
|
||||
}
|
||||
else {
|
||||
res_o = PyObject_GetItem(container_o, slice);
|
||||
Py_DECREF(slice);
|
||||
}
|
||||
}
|
||||
PyStackRef_CLOSE(container);
|
||||
DECREF_INPUTS();
|
||||
ERROR_IF(res_o == NULL);
|
||||
res = PyStackRef_FromPyObjectSteal(res_o);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
/* Execute compiled code */
|
||||
|
||||
#include "ceval.h"
|
||||
#include "pycore_long.h"
|
||||
|
||||
int
|
||||
Py_GetRecursionLimit(void)
|
||||
|
|
@ -2883,23 +2884,10 @@ PyEval_GetFuncDesc(PyObject *func)
|
|||
int
|
||||
_PyEval_SliceIndex(PyObject *v, Py_ssize_t *pi)
|
||||
{
|
||||
PyThreadState *tstate = _PyThreadState_GET();
|
||||
if (!Py_IsNone(v)) {
|
||||
Py_ssize_t x;
|
||||
if (_PyIndex_Check(v)) {
|
||||
x = PyNumber_AsSsize_t(v, NULL);
|
||||
if (x == -1 && _PyErr_Occurred(tstate))
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
_PyErr_SetString(tstate, PyExc_TypeError,
|
||||
"slice indices must be integers or "
|
||||
"None or have an __index__ method");
|
||||
return 0;
|
||||
}
|
||||
*pi = x;
|
||||
if (Py_IsNone(v)) {
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
return _PyEval_SliceIndexNotNone(v, pi);
|
||||
}
|
||||
|
||||
int
|
||||
|
|
@ -2907,6 +2895,10 @@ _PyEval_SliceIndexNotNone(PyObject *v, Py_ssize_t *pi)
|
|||
{
|
||||
PyThreadState *tstate = _PyThreadState_GET();
|
||||
Py_ssize_t x;
|
||||
if (PyLong_CheckExact(v) && _PyLong_IsCompact((PyLongObject *)v)) {
|
||||
*pi = _PyLong_CompactValue((PyLongObject *)v);
|
||||
return 1;
|
||||
}
|
||||
if (_PyIndex_Check(v)) {
|
||||
x = PyNumber_AsSsize_t(v, NULL);
|
||||
if (x == -1 && _PyErr_Occurred(tstate))
|
||||
|
|
@ -2922,6 +2914,26 @@ _PyEval_SliceIndexNotNone(PyObject *v, Py_ssize_t *pi)
|
|||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
_PyEval_UnpackIndices(PyObject *start, PyObject *stop,
|
||||
Py_ssize_t len,
|
||||
Py_ssize_t *istart, Py_ssize_t *istop)
|
||||
{
|
||||
if (len < 0) {
|
||||
return 0;
|
||||
}
|
||||
*istart = 0;
|
||||
*istop = PY_SSIZE_T_MAX;
|
||||
if (!_PyEval_SliceIndex(start, istart)) {
|
||||
return 0;
|
||||
}
|
||||
if (!_PyEval_SliceIndex(stop, istop)) {
|
||||
return 0;
|
||||
}
|
||||
PySlice_AdjustIndices(len, istart, istop, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
PyObject *
|
||||
_PyEval_ImportName(PyThreadState *tstate, PyObject *builtins,
|
||||
PyObject *globals, PyObject *locals, PyObject *name,
|
||||
|
|
|
|||
84
Python/executor_cases.c.h
generated
84
Python/executor_cases.c.h
generated
|
|
@ -5198,33 +5198,77 @@
|
|||
stop = _stack_item_2;
|
||||
start = _stack_item_1;
|
||||
container = _stack_item_0;
|
||||
stack_pointer[0] = container;
|
||||
stack_pointer[1] = start;
|
||||
stack_pointer[2] = stop;
|
||||
stack_pointer += 3;
|
||||
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
PyObject *slice = _PyBuildSlice_ConsumeRefs(PyStackRef_AsPyObjectSteal(start),
|
||||
PyStackRef_AsPyObjectSteal(stop));
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
PyObject *container_o = PyStackRef_AsPyObjectBorrow(container);
|
||||
PyObject *start_o = PyStackRef_AsPyObjectBorrow(start);
|
||||
PyObject *stop_o = PyStackRef_AsPyObjectBorrow(stop);
|
||||
PyObject *res_o;
|
||||
if (slice == NULL) {
|
||||
res_o = NULL;
|
||||
}
|
||||
else {
|
||||
stack_pointer += -2;
|
||||
if (PyList_CheckExact(container_o)) {
|
||||
stack_pointer[0] = container;
|
||||
stack_pointer[1] = start;
|
||||
stack_pointer[2] = stop;
|
||||
stack_pointer += 3;
|
||||
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
res_o = PyObject_GetItem(PyStackRef_AsPyObjectBorrow(container), slice);
|
||||
Py_DECREF(slice);
|
||||
res_o = _PyList_BinarySlice(container_o, start_o, stop_o);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
stack_pointer += 2;
|
||||
}
|
||||
else if (PyTuple_CheckExact(container_o)) {
|
||||
stack_pointer[0] = container;
|
||||
stack_pointer[1] = start;
|
||||
stack_pointer[2] = stop;
|
||||
stack_pointer += 3;
|
||||
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
res_o = _PyTuple_BinarySlice(container_o, start_o, stop_o);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
}
|
||||
else if (PyUnicode_CheckExact(container_o)) {
|
||||
stack_pointer[0] = container;
|
||||
stack_pointer[1] = start;
|
||||
stack_pointer[2] = stop;
|
||||
stack_pointer += 3;
|
||||
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
res_o = _PyUnicode_BinarySlice(container_o, start_o, stop_o);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
}
|
||||
else {
|
||||
PyObject *slice = PySlice_New(start_o, stop_o, NULL);
|
||||
if (slice == NULL) {
|
||||
res_o = NULL;
|
||||
}
|
||||
else {
|
||||
stack_pointer[0] = container;
|
||||
stack_pointer[1] = start;
|
||||
stack_pointer[2] = stop;
|
||||
stack_pointer += 3;
|
||||
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
res_o = PyObject_GetItem(container_o, slice);
|
||||
Py_DECREF(slice);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
stack_pointer += -3;
|
||||
}
|
||||
stack_pointer += 3;
|
||||
}
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
_PyStackRef tmp = stop;
|
||||
stop = PyStackRef_NULL;
|
||||
stack_pointer[-3] = container;
|
||||
stack_pointer[-2] = start;
|
||||
stack_pointer[-1] = stop;
|
||||
PyStackRef_CLOSE(tmp);
|
||||
tmp = start;
|
||||
start = PyStackRef_NULL;
|
||||
stack_pointer[-2] = start;
|
||||
PyStackRef_CLOSE(tmp);
|
||||
tmp = container;
|
||||
container = PyStackRef_NULL;
|
||||
stack_pointer[-3] = container;
|
||||
PyStackRef_CLOSE(tmp);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
stack_pointer += -3;
|
||||
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
PyStackRef_CLOSE(container);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
if (res_o == NULL) {
|
||||
SET_CURRENT_CACHED_VALUES(0);
|
||||
JUMP_TO_ERROR();
|
||||
|
|
|
|||
57
Python/generated_cases.c.h
generated
57
Python/generated_cases.c.h
generated
|
|
@ -1396,28 +1396,53 @@
|
|||
stop = stack_pointer[-1];
|
||||
start = stack_pointer[-2];
|
||||
container = stack_pointer[-3];
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
PyObject *slice = _PyBuildSlice_ConsumeRefs(PyStackRef_AsPyObjectSteal(start),
|
||||
PyStackRef_AsPyObjectSteal(stop));
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
PyObject *container_o = PyStackRef_AsPyObjectBorrow(container);
|
||||
PyObject *start_o = PyStackRef_AsPyObjectBorrow(start);
|
||||
PyObject *stop_o = PyStackRef_AsPyObjectBorrow(stop);
|
||||
PyObject *res_o;
|
||||
if (slice == NULL) {
|
||||
res_o = NULL;
|
||||
if (PyList_CheckExact(container_o)) {
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
res_o = _PyList_BinarySlice(container_o, start_o, stop_o);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
}
|
||||
else if (PyTuple_CheckExact(container_o)) {
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
res_o = _PyTuple_BinarySlice(container_o, start_o, stop_o);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
}
|
||||
else if (PyUnicode_CheckExact(container_o)) {
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
res_o = _PyUnicode_BinarySlice(container_o, start_o, stop_o);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
}
|
||||
else {
|
||||
stack_pointer += -2;
|
||||
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
res_o = PyObject_GetItem(PyStackRef_AsPyObjectBorrow(container), slice);
|
||||
Py_DECREF(slice);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
stack_pointer += 2;
|
||||
PyObject *slice = PySlice_New(start_o, stop_o, NULL);
|
||||
if (slice == NULL) {
|
||||
res_o = NULL;
|
||||
}
|
||||
else {
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
res_o = PyObject_GetItem(container_o, slice);
|
||||
Py_DECREF(slice);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
}
|
||||
}
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
_PyStackRef tmp = stop;
|
||||
stop = PyStackRef_NULL;
|
||||
stack_pointer[-1] = stop;
|
||||
PyStackRef_CLOSE(tmp);
|
||||
tmp = start;
|
||||
start = PyStackRef_NULL;
|
||||
stack_pointer[-2] = start;
|
||||
PyStackRef_CLOSE(tmp);
|
||||
tmp = container;
|
||||
container = PyStackRef_NULL;
|
||||
stack_pointer[-3] = container;
|
||||
PyStackRef_CLOSE(tmp);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
stack_pointer += -3;
|
||||
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
PyStackRef_CLOSE(container);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
if (res_o == NULL) {
|
||||
JUMP_TO_LABEL(error);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue