GH-91432: Specialize FOR_ITER (GH-91713)

* Adds FOR_ITER_LIST and FOR_ITER_RANGE specializations.

* Adds _PyLong_AssignValue() internal function to avoid temporary boxing of ints.
This commit is contained in:
Dennis Sweeney 2022-06-21 06:19:26 -04:00 committed by GitHub
parent c735d54534
commit 5fcfdd87c9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
22 changed files with 447 additions and 282 deletions

View file

@ -3,7 +3,7 @@
#include "Python.h"
#include "pycore_abstract.h" // _PyIndex_Check()
#include "pycore_interp.h" // PyInterpreterState.list
#include "pycore_list.h" // struct _Py_list_state
#include "pycore_list.h" // struct _Py_list_state, _PyListIterObject
#include "pycore_object.h" // _PyObject_GC_TRACK()
#include "pycore_tuple.h" // _PyTuple_FromArray()
#include <stddef.h>
@ -3188,19 +3188,13 @@ PyTypeObject PyList_Type = {
/*********************** List Iterator **************************/
typedef struct {
PyObject_HEAD
Py_ssize_t it_index;
PyListObject *it_seq; /* Set to NULL when iterator is exhausted */
} listiterobject;
static void listiter_dealloc(listiterobject *);
static int listiter_traverse(listiterobject *, visitproc, void *);
static PyObject *listiter_next(listiterobject *);
static PyObject *listiter_len(listiterobject *, PyObject *);
static void listiter_dealloc(_PyListIterObject *);
static int listiter_traverse(_PyListIterObject *, visitproc, void *);
static PyObject *listiter_next(_PyListIterObject *);
static PyObject *listiter_len(_PyListIterObject *, PyObject *);
static PyObject *listiter_reduce_general(void *_it, int forward);
static PyObject *listiter_reduce(listiterobject *, PyObject *);
static PyObject *listiter_setstate(listiterobject *, PyObject *state);
static PyObject *listiter_reduce(_PyListIterObject *, PyObject *);
static PyObject *listiter_setstate(_PyListIterObject *, PyObject *state);
PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it)).");
PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");
@ -3216,7 +3210,7 @@ static PyMethodDef listiter_methods[] = {
PyTypeObject PyListIter_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
"list_iterator", /* tp_name */
sizeof(listiterobject), /* tp_basicsize */
sizeof(_PyListIterObject), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
(destructor)listiter_dealloc, /* tp_dealloc */
@ -3250,13 +3244,13 @@ PyTypeObject PyListIter_Type = {
static PyObject *
list_iter(PyObject *seq)
{
listiterobject *it;
_PyListIterObject *it;
if (!PyList_Check(seq)) {
PyErr_BadInternalCall();
return NULL;
}
it = PyObject_GC_New(listiterobject, &PyListIter_Type);
it = PyObject_GC_New(_PyListIterObject, &PyListIter_Type);
if (it == NULL)
return NULL;
it->it_index = 0;
@ -3267,7 +3261,7 @@ list_iter(PyObject *seq)
}
static void
listiter_dealloc(listiterobject *it)
listiter_dealloc(_PyListIterObject *it)
{
_PyObject_GC_UNTRACK(it);
Py_XDECREF(it->it_seq);
@ -3275,14 +3269,14 @@ listiter_dealloc(listiterobject *it)
}
static int
listiter_traverse(listiterobject *it, visitproc visit, void *arg)
listiter_traverse(_PyListIterObject *it, visitproc visit, void *arg)
{
Py_VISIT(it->it_seq);
return 0;
}
static PyObject *
listiter_next(listiterobject *it)
listiter_next(_PyListIterObject *it)
{
PyListObject *seq;
PyObject *item;
@ -3306,7 +3300,7 @@ listiter_next(listiterobject *it)
}
static PyObject *
listiter_len(listiterobject *it, PyObject *Py_UNUSED(ignored))
listiter_len(_PyListIterObject *it, PyObject *Py_UNUSED(ignored))
{
Py_ssize_t len;
if (it->it_seq) {
@ -3318,13 +3312,13 @@ listiter_len(listiterobject *it, PyObject *Py_UNUSED(ignored))
}
static PyObject *
listiter_reduce(listiterobject *it, PyObject *Py_UNUSED(ignored))
listiter_reduce(_PyListIterObject *it, PyObject *Py_UNUSED(ignored))
{
return listiter_reduce_general(it, 1);
}
static PyObject *
listiter_setstate(listiterobject *it, PyObject *state)
listiter_setstate(_PyListIterObject *it, PyObject *state)
{
Py_ssize_t index = PyLong_AsSsize_t(state);
if (index == -1 && PyErr_Occurred())
@ -3499,7 +3493,7 @@ listiter_reduce_general(void *_it, int forward)
/* the objects are not the same, index is of different types! */
if (forward) {
listiterobject *it = (listiterobject *)_it;
_PyListIterObject *it = (_PyListIterObject *)_it;
if (it->it_seq) {
return Py_BuildValue("N(O)n", _PyEval_GetBuiltin(&_Py_ID(iter)),
it->it_seq, it->it_index);