mirror of
https://github.com/python/cpython.git
synced 2025-11-11 14:44:57 +00:00
Micro-optimize list index range checks (GH-9784)
This commit is contained in:
parent
1d26c72e6a
commit
f1aa8aed4a
1 changed files with 18 additions and 5 deletions
|
|
@ -208,6 +208,19 @@ PyList_Size(PyObject *op)
|
||||||
return Py_SIZE(op);
|
return Py_SIZE(op);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
valid_index(Py_ssize_t i, Py_ssize_t limit)
|
||||||
|
{
|
||||||
|
/* The cast to size_t lets us use just a single comparison
|
||||||
|
to check whether i is in the range: 0 <= i < limit.
|
||||||
|
|
||||||
|
See: Section 14.2 "Bounds Checking" in the Agner Fog
|
||||||
|
optimization manual found at:
|
||||||
|
https://www.agner.org/optimize/optimizing_cpp.pdf
|
||||||
|
*/
|
||||||
|
return (size_t) i < (size_t) limit;
|
||||||
|
}
|
||||||
|
|
||||||
static PyObject *indexerr = NULL;
|
static PyObject *indexerr = NULL;
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
|
|
@ -217,7 +230,7 @@ PyList_GetItem(PyObject *op, Py_ssize_t i)
|
||||||
PyErr_BadInternalCall();
|
PyErr_BadInternalCall();
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (i < 0 || i >= Py_SIZE(op)) {
|
if (!valid_index(i, Py_SIZE(op))) {
|
||||||
if (indexerr == NULL) {
|
if (indexerr == NULL) {
|
||||||
indexerr = PyUnicode_FromString(
|
indexerr = PyUnicode_FromString(
|
||||||
"list index out of range");
|
"list index out of range");
|
||||||
|
|
@ -240,7 +253,7 @@ PyList_SetItem(PyObject *op, Py_ssize_t i,
|
||||||
PyErr_BadInternalCall();
|
PyErr_BadInternalCall();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (i < 0 || i >= Py_SIZE(op)) {
|
if (!valid_index(i, Py_SIZE(op))) {
|
||||||
Py_XDECREF(newitem);
|
Py_XDECREF(newitem);
|
||||||
PyErr_SetString(PyExc_IndexError,
|
PyErr_SetString(PyExc_IndexError,
|
||||||
"list assignment index out of range");
|
"list assignment index out of range");
|
||||||
|
|
@ -426,7 +439,7 @@ list_contains(PyListObject *a, PyObject *el)
|
||||||
static PyObject *
|
static PyObject *
|
||||||
list_item(PyListObject *a, Py_ssize_t i)
|
list_item(PyListObject *a, Py_ssize_t i)
|
||||||
{
|
{
|
||||||
if (i < 0 || i >= Py_SIZE(a)) {
|
if (!valid_index(i, Py_SIZE(a))) {
|
||||||
if (indexerr == NULL) {
|
if (indexerr == NULL) {
|
||||||
indexerr = PyUnicode_FromString(
|
indexerr = PyUnicode_FromString(
|
||||||
"list index out of range");
|
"list index out of range");
|
||||||
|
|
@ -749,7 +762,7 @@ list_inplace_repeat(PyListObject *self, Py_ssize_t n)
|
||||||
static int
|
static int
|
||||||
list_ass_item(PyListObject *a, Py_ssize_t i, PyObject *v)
|
list_ass_item(PyListObject *a, Py_ssize_t i, PyObject *v)
|
||||||
{
|
{
|
||||||
if (i < 0 || i >= Py_SIZE(a)) {
|
if (!valid_index(i, Py_SIZE(a))) {
|
||||||
PyErr_SetString(PyExc_IndexError,
|
PyErr_SetString(PyExc_IndexError,
|
||||||
"list assignment index out of range");
|
"list assignment index out of range");
|
||||||
return -1;
|
return -1;
|
||||||
|
|
@ -996,7 +1009,7 @@ list_pop_impl(PyListObject *self, Py_ssize_t index)
|
||||||
}
|
}
|
||||||
if (index < 0)
|
if (index < 0)
|
||||||
index += Py_SIZE(self);
|
index += Py_SIZE(self);
|
||||||
if (index < 0 || index >= Py_SIZE(self)) {
|
if (!valid_index(index, Py_SIZE(self))) {
|
||||||
PyErr_SetString(PyExc_IndexError, "pop index out of range");
|
PyErr_SetString(PyExc_IndexError, "pop index out of range");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue