Unverified Kaydet (Commit) f1aa8aed authored tarafından Raymond Hettinger's avatar Raymond Hettinger Kaydeden (comit) GitHub

Micro-optimize list index range checks (GH-9784)

üst 1d26c72e
...@@ -208,6 +208,19 @@ PyList_Size(PyObject *op) ...@@ -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) ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment