aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPetr Viktorin <encukou@gmail.com>2020-02-18 16:13:17 +0100
committerGitHub <noreply@github.com>2020-02-18 07:13:17 -0800
commit6e35da976370e7c2e028165c65d7d7d42772a71f (patch)
treed589a75b9f8f2d1f1bf73947feb57a6b83cffebb /Objects/rangeobject.c
parentbpo-36347: stop using RESTRICTED constants (GH-12684) (diff)
downloadcpython-6e35da976370e7c2e028165c65d7d7d42772a71f.tar.gz
cpython-6e35da976370e7c2e028165c65d7d7d42772a71f.tar.bz2
cpython-6e35da976370e7c2e028165c65d7d7d42772a71f.zip
bpo-37207: Use vectorcall for range() (GH-18464)
This continues the `range()` part of #13930. The complete pull request is stalled on discussions around dicts, but `range()` should not be controversial. (And I plan to open PRs for other parts if this is merged.) On top of Mark's change, I unified `range_new` and `range_vectorcall`, which had a lot of duplicate code. https://bugs.python.org/issue37207
Diffstat (limited to 'Objects/rangeobject.c')
-rw-r--r--Objects/rangeobject.c50
1 files changed, 33 insertions, 17 deletions
diff --git a/Objects/rangeobject.c b/Objects/rangeobject.c
index 343a80c76b0..123ca0b032e 100644
--- a/Objects/rangeobject.c
+++ b/Objects/rangeobject.c
@@ -2,6 +2,7 @@
#include "Python.h"
#include "structmember.h"
+#include "pycore_tupleobject.h"
/* Support objects whose length is > PY_SSIZE_T_MAX.
@@ -71,34 +72,27 @@ make_range_object(PyTypeObject *type, PyObject *start,
range(0, 5, -1)
*/
static PyObject *
-range_new(PyTypeObject *type, PyObject *args, PyObject *kw)
+range_from_array(PyTypeObject *type, PyObject *const *args, Py_ssize_t num_args)
{
rangeobject *obj;
PyObject *start = NULL, *stop = NULL, *step = NULL;
- if (!_PyArg_NoKeywords("range", kw))
- return NULL;
-
- Py_ssize_t num_args = PyTuple_GET_SIZE(args);
switch (num_args) {
case 3:
- step = PyTuple_GET_ITEM(args, 2);
+ step = args[2];
/* fallthrough */
case 2:
- start = PyTuple_GET_ITEM(args, 0);
- start = PyNumber_Index(start);
+ /* Convert borrowed refs to owned refs */
+ start = PyNumber_Index(args[0]);
if (!start) {
return NULL;
}
-
- stop = PyTuple_GET_ITEM(args, 1);
- stop = PyNumber_Index(stop);
+ stop = PyNumber_Index(args[1]);
if (!stop) {
Py_DECREF(start);
return NULL;
}
-
- step = validate_step(step);
+ step = validate_step(step); /* Caution, this can clear exceptions */
if (!step) {
Py_DECREF(start);
Py_DECREF(stop);
@@ -106,8 +100,7 @@ range_new(PyTypeObject *type, PyObject *args, PyObject *kw)
}
break;
case 1:
- stop = PyTuple_GET_ITEM(args, 0);
- stop = PyNumber_Index(stop);
+ stop = PyNumber_Index(args[0]);
if (!stop) {
return NULL;
}
@@ -126,10 +119,10 @@ range_new(PyTypeObject *type, PyObject *args, PyObject *kw)
num_args);
return NULL;
}
-
obj = make_range_object(type, start, stop, step);
- if (obj != NULL)
+ if (obj != NULL) {
return (PyObject *) obj;
+ }
/* Failed to create object, release attributes */
Py_DECREF(start);
@@ -138,6 +131,28 @@ range_new(PyTypeObject *type, PyObject *args, PyObject *kw)
return NULL;
}
+static PyObject *
+range_new(PyTypeObject *type, PyObject *args, PyObject *kw)
+{
+ if (!_PyArg_NoKeywords("range", kw))
+ return NULL;
+
+ return range_from_array(type, _PyTuple_ITEMS(args), PyTuple_GET_SIZE(args));
+}
+
+
+static PyObject *
+range_vectorcall(PyTypeObject *type, PyObject *const *args,
+ size_t nargsf, PyObject *kwnames)
+{
+ Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
+ if (kwnames && PyTuple_GET_SIZE(kwnames) != 0) {
+ PyErr_Format(PyExc_TypeError, "range() takes no keyword arguments");
+ return NULL;
+ }
+ return range_from_array(type, args, nargs);
+}
+
PyDoc_STRVAR(range_doc,
"range(stop) -> range object\n\
range(start, stop[, step]) -> range object\n\
@@ -719,6 +734,7 @@ PyTypeObject PyRange_Type = {
0, /* tp_init */
0, /* tp_alloc */
range_new, /* tp_new */
+ .tp_vectorcall = (vectorcallfunc)range_vectorcall
};
/*********************** range Iterator **************************/