diff options
author | Raymond Hettinger <rhettinger@users.noreply.github.com> | 2018-10-11 03:37:28 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-10-11 03:37:28 (GMT) |
commit | f1aa8aed4a8ce9753ffa8713e7d3461663e0624d (patch) | |
tree | 8ffff1e5e92b83b48b4d072acc4136a72977af3f /Objects/listobject.c | |
parent | 1d26c72e6a9c5b28b27c158f2f196217707dbb0f (diff) | |
download | cpython-f1aa8aed4a8ce9753ffa8713e7d3461663e0624d.zip cpython-f1aa8aed4a8ce9753ffa8713e7d3461663e0624d.tar.gz cpython-f1aa8aed4a8ce9753ffa8713e7d3461663e0624d.tar.bz2 |
Micro-optimize list index range checks (GH-9784)
Diffstat (limited to 'Objects/listobject.c')
-rw-r--r-- | Objects/listobject.c | 23 |
1 files changed, 18 insertions, 5 deletions
diff --git a/Objects/listobject.c b/Objects/listobject.c index 3d4a187..fa26444 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -208,6 +208,19 @@ PyList_Size(PyObject *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; PyObject * @@ -217,7 +230,7 @@ PyList_GetItem(PyObject *op, Py_ssize_t i) PyErr_BadInternalCall(); return NULL; } - if (i < 0 || i >= Py_SIZE(op)) { + if (!valid_index(i, Py_SIZE(op))) { if (indexerr == NULL) { indexerr = PyUnicode_FromString( "list index out of range"); @@ -240,7 +253,7 @@ PyList_SetItem(PyObject *op, Py_ssize_t i, PyErr_BadInternalCall(); return -1; } - if (i < 0 || i >= Py_SIZE(op)) { + if (!valid_index(i, Py_SIZE(op))) { Py_XDECREF(newitem); PyErr_SetString(PyExc_IndexError, "list assignment index out of range"); @@ -426,7 +439,7 @@ list_contains(PyListObject *a, PyObject *el) static PyObject * 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) { indexerr = PyUnicode_FromString( "list index out of range"); @@ -749,7 +762,7 @@ list_inplace_repeat(PyListObject *self, Py_ssize_t n) static int 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, "list assignment index out of range"); return -1; @@ -996,7 +1009,7 @@ list_pop_impl(PyListObject *self, Py_ssize_t index) } if (index < 0) 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"); return NULL; } |