8000 bpo-37207: Use vectorcall for range() by encukou · Pull Request #18464 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

bpo-37207: Use vectorcall for range() #18464

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Feb 18, 2020
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Use vectorcall for range()
  • Loading branch information
markshannon authored and encukou committed Feb 11, 2020
commit b4f32714c6140ef3ee3e15367760cf358e7316fb
61 changes: 61 additions & 0 deletions Objects/rangeobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,66 @@ range_new(PyTypeObject *type, PyObject *args, PyObject *kw)
return NULL;
}


static PyObject *
range_vectorcall(PyTypeObject *type, PyObject *const *args,
size_t nargsf, PyObject *kwnames)
{
rangeobject *obj;
size_t nargs = PyVectorcall_NARGS(nargsf);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I didn't expect a size_t here. I opened an issue to discuss PyVectorcall_NARGS() return type: https://bugs.python.org/issue39611

Copy link
Member Author
@encukou encukou Feb 18, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The return type already is Py_ssize_t. The bug was only in this patch.
(When Mark was originally writing the patch, there was a discussion of Py_ssize_t vs. size_t. Mark is a big proponent of the unsigned type, which is more correct. But also much less compatible with the existing codebase.)

PyObject *start = NULL, *stop = NULL, *step = NULL;
if (kwnames && PyTuple_GET_SIZE(kwnames) != 0) {
PyErr_Format(PyExc_TypeError, "range() takes no keyword arguments");
return NULL;
}
switch(nargs) {
case 0:
PyErr_Format(PyExc_TypeError, "range() expected 1 arguments, got 0");
return NULL;
case 1:
stop = PyNumber_Index(args[0]);
if (!stop)
return NULL;
Py_INCREF(_PyLong_Zero);
start = _PyLong_Zero;
Py_INCREF(_PyLong_One);
step = _PyLong_One;
break;
case 3:
step = args[2];
//Intentional fall through
case 2:
/* Convert borrowed refs to owned refs */
start = PyNumber_Index(args[0]);
if (!start)
return NULL;
stop = PyNumber_Index(args[1]);
if (!stop) {
Py_DECREF(start);
return NULL;
}
step = validate_step(step); /* Caution, this can clear exceptions */
if (!step) {
Py_DECREF(start);
Py_DECREF(stop);
return NULL;
}
break;
default:
PyErr_Format(PyExc_TypeError, "range() expected at most 3 arguments, got %zu", nargs);
return NULL;
}
obj = make_range_object(type, start, stop, step);
if (obj != NULL)
return (PyObject *) obj;

/* Failed to create object, release attributes */
Py_DECREF(start);
Py_DECREF(stop);
Py_DECREF(step);
return NULL;
}

PyDoc_STRVAR(range_doc,
"range(stop) -> range object\n\
range(start, stop[, step]) -> range object\n\
Expand Down Expand Up @@ -719,6 +779,7 @@ PyTypeObject PyRange_Type = {
0, /* tp_init */
0, /* tp_alloc */
range_new, /* tp_new */
.tp_vectorcall = (vectorcallfunc)range_vectorcall
};

/*********************** range Iterator **************************/
Expand Down
0