Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 748c6c0

Browse files
GH-100110: Specialize FOR_ITER for tuples (GH-100109)
* Specialize FOR_ITER for tuples
1 parent 0448dea commit 748c6c0

File tree

10 files changed

+122
-67
lines changed

10 files changed

+122
-67
lines changed

Include/internal/pycore_opcode.h

Lines changed: 13 additions & 13 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Include/internal/pycore_tuple.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,13 @@ struct _Py_tuple_state {
6767
extern PyObject *_PyTuple_FromArray(PyObject *const *, Py_ssize_t);
6868
extern PyObject *_PyTuple_FromArraySteal(PyObject *const *, Py_ssize_t);
6969

70+
71+
typedef struct {
72+
PyObject_HEAD
73+
Py_ssize_t it_index;
74+
PyTupleObject *it_seq; /* Set to NULL when iterator is exhausted */
75+
} _PyTupleIterObject;
76+
7077
#ifdef __cplusplus
7178
}
7279
#endif

Include/opcode.h

Lines changed: 29 additions & 28 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Lib/opcode.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,7 @@ def pseudo_op(name, op, real_ops):
320320
],
321321
"FOR_ITER": [
322322
"FOR_ITER_LIST",
323+
"FOR_ITER_TUPLE",
323324
"FOR_ITER_RANGE",
324325
"FOR_ITER_GEN",
325326
],
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Specialize ``FOR_ITER`` for tuples.

Objects/tupleobject.c

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -995,29 +995,24 @@ _PyTuple_ClearFreeList(PyInterpreterState *interp)
995995

996996
/*********************** Tuple Iterator **************************/
997997

998-
typedef struct {
999-
PyObject_HEAD
1000-
Py_ssize_t it_index;
1001-
PyTupleObject *it_seq; /* Set to NULL when iterator is exhausted */
1002-
} tupleiterobject;
1003998

1004999
static void
1005-
tupleiter_dealloc(tupleiterobject *it)
1000+
tupleiter_dealloc(_PyTupleIterObject *it)
10061001
{
10071002
_PyObject_GC_UNTRACK(it);
10081003
Py_XDECREF(it->it_seq);
10091004
PyObject_GC_Del(it);
10101005
}
10111006

10121007
static int
1013-
tupleiter_traverse(tupleiterobject *it, visitproc visit, void *arg)
1008+
tupleiter_traverse(_PyTupleIterObject *it, visitproc visit, void *arg)
10141009
{
10151010
Py_VISIT(it->it_seq);
10161011
return 0;
10171012
}
10181013

10191014
static PyObject *
1020-
tupleiter_next(tupleiterobject *it)
1015+
tupleiter_next(_PyTupleIterObject *it)
10211016
{
10221017
PyTupleObject *seq;
10231018
PyObject *item;
@@ -1040,7 +1035,7 @@ tupleiter_next(tupleiterobject *it)
10401035
}
10411036

10421037
static PyObject *
1043-
tupleiter_len(tupleiterobject *it, PyObject *Py_UNUSED(ignored))
1038+
tupleiter_len(_PyTupleIterObject *it, PyObject *Py_UNUSED(ignored))
10441039
{
10451040
Py_ssize_t len = 0;
10461041
if (it->it_seq)
@@ -1051,7 +1046,7 @@ tupleiter_len(tupleiterobject *it, PyObject *Py_UNUSED(ignored))
10511046
PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it)).");
10521047

10531048
static PyObject *
1054-
tupleiter_reduce(tupleiterobject *it, PyObject *Py_UNUSED(ignored))
1049+
tupleiter_reduce(_PyTupleIterObject *it, PyObject *Py_UNUSED(ignored))
10551050
{
10561051
if (it->it_seq)
10571052
return Py_BuildValue("N(O)n", _PyEval_GetBuiltin(&_Py_ID(iter)),
@@ -1061,7 +1056,7 @@ tupleiter_reduce(tupleiterobject *it, PyObject *Py_UNUSED(ignored))
10611056
}
10621057

10631058
static PyObject *
1064-
tupleiter_setstate(tupleiterobject *it, PyObject *state)
1059+
tupleiter_setstate(_PyTupleIterObject *it, PyObject *state)
10651060
{
10661061
Py_ssize_t index = PyLong_AsSsize_t(state);
10671062
if (index == -1 && PyErr_Occurred())
@@ -1089,7 +1084,7 @@ static PyMethodDef tupleiter_methods[] = {
10891084
PyTypeObject PyTupleIter_Type = {
10901085
PyVarObject_HEAD_INIT(&PyType_Type, 0)
10911086
"tuple_iterator", /* tp_name */
1092-
sizeof(tupleiterobject), /* tp_basicsize */
1087+
sizeof(_PyTupleIterObject), /* tp_basicsize */
10931088
0, /* tp_itemsize */
10941089
/* methods */
10951090
(destructor)tupleiter_dealloc, /* tp_dealloc */
@@ -1122,13 +1117,13 @@ PyTypeObject PyTupleIter_Type = {
11221117
static PyObject *
11231118
tuple_iter(PyObject *seq)
11241119
{
1125-
tupleiterobject *it;
1120+
_PyTupleIterObject *it;
11261121

11271122
if (!PyTuple_Check(seq)) {
11281123
PyErr_BadInternalCall();
11291124
return NULL;
11301125
}
1131-
it = PyObject_GC_New(tupleiterobject, &PyTupleIter_Type);
1126+
it = PyObject_GC_New(_PyTupleIterObject, &PyTupleIter_Type);
11321127
if (it == NULL)
11331128
return NULL;
11341129
it->it_index = 0;

Python/bytecodes.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2523,6 +2523,29 @@ dummy_func(
25232523
end_for_iter_list:
25242524
}
25252525

2526+
// stack effect: ( -- __0)
2527+
inst(FOR_ITER_TUPLE) {
2528+
assert(cframe.use_tracing == 0);
2529+
_PyTupleIterObject *it = (_PyTupleIterObject *)TOP();
2530+
DEOPT_IF(Py_TYPE(it) != &PyTupleIter_Type, FOR_ITER);
2531+
STAT_INC(FOR_ITER, hit);
2532+
PyTupleObject *seq = it->it_seq;
2533+
if (seq) {
2534+
if (it->it_index < PyTuple_GET_SIZE(seq)) {
2535+
PyObject *next = PyTuple_GET_ITEM(seq, it->it_index++);
2536+
PUSH(Py_NewRef(next));
2537+
JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER);
2538+
goto end_for_iter_tuple; // End of this instruction
2539+
}
2540+
it->it_seq = NULL;
2541+
Py_DECREF(seq);
2542+
}
2543+
STACK_SHRINK(1);
2544+
Py_DECREF(it);
2545+
JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER + oparg + 1);
2546+
end_for_iter_tuple:
2547+
}
2548+
25262549
// stack effect: ( -- __0)
25272550
inst(FOR_ITER_RANGE) {
25282551
assert(cframe.use_tracing == 0);

Python/generated_cases.c.h

Lines changed: 23 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)