Skip to content

Commit ee28e14

Browse files
markshannonJelleZijlstra
authored andcommitted
pythonGH-100982: Restrict FOR_ITER_RANGE to a single instruction to allow instrumentation. (pythonGH-101985)
1 parent 4b96fb0 commit ee28e14

File tree

4 files changed

+22
-30
lines changed

4 files changed

+22
-30
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Restrict the scope of the :opcode:`FOR_ITER_RANGE` instruction to the scope of the
2+
original :opcode:`FOR_ITER` instruction, to allow instrumentation.

Python/bytecodes.c

+8-16
Original file line numberDiff line numberDiff line change
@@ -2184,35 +2184,27 @@ dummy_func(
21842184
// Common case: no jump, leave it to the code generator
21852185
}
21862186

2187-
// This is slightly different, when the loop isn't terminated we
2188-
// jump over the immediately following STORE_FAST instruction.
2189-
inst(FOR_ITER_RANGE, (unused/1, iter -- iter, unused)) {
2187+
inst(FOR_ITER_RANGE, (unused/1, iter -- iter, next)) {
21902188
assert(cframe.use_tracing == 0);
21912189
_PyRangeIterObject *r = (_PyRangeIterObject *)iter;
21922190
DEOPT_IF(Py_TYPE(r) != &PyRangeIter_Type, FOR_ITER);
21932191
STAT_INC(FOR_ITER, hit);
2194-
_Py_CODEUNIT next = next_instr[INLINE_CACHE_ENTRIES_FOR_ITER];
2195-
assert(_PyOpcode_Deopt[next.op.code] == STORE_FAST);
21962192
if (r->len <= 0) {
21972193
STACK_SHRINK(1);
21982194
Py_DECREF(r);
21992195
// Jump over END_FOR instruction.
22002196
JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER + oparg + 1);
2197+
DISPATCH();
22012198
}
2202-
else {
2203-
long value = r->start;
2204-
r->start = value + r->step;
2205-
r->len--;
2206-
if (_PyLong_AssignValue(&GETLOCAL(next.op.arg), value) < 0) {
2207-
goto error;
2208-
}
2209-
// The STORE_FAST is already done.
2210-
JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER + 1);
2199+
long value = r->start;
2200+
r->start = value + r->step;
2201+
r->len--;
2202+
next = PyLong_FromLong(value);
2203+
if (next == NULL) {
2204+
goto error;
22112205
}
2212-
DISPATCH();
22132206
}
22142207

2215-
// This is *not* a super-instruction, unique in the family.
22162208
inst(FOR_ITER_GEN, (unused/1, iter -- iter, unused)) {
22172209
assert(cframe.use_tracing == 0);
22182210
PyGenObject *gen = (PyGenObject *)iter;

Python/generated_cases.c.h

+11-11
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/specialize.c

+1-3
Original file line numberDiff line numberDiff line change
@@ -2155,8 +2155,6 @@ _Py_Specialize_ForIter(PyObject *iter, _Py_CODEUNIT *instr, int oparg)
21552155
assert(_PyOpcode_Caches[FOR_ITER] == INLINE_CACHE_ENTRIES_FOR_ITER);
21562156
_PyForIterCache *cache = (_PyForIterCache *)(instr + 1);
21572157
PyTypeObject *tp = Py_TYPE(iter);
2158-
_Py_CODEUNIT next = instr[1+INLINE_CACHE_ENTRIES_FOR_ITER];
2159-
int next_op = _PyOpcode_Deopt[next.op.code];
21602158
if (tp == &PyListIter_Type) {
21612159
instr->op.code = FOR_ITER_LIST;
21622160
goto success;
@@ -2165,7 +2163,7 @@ _Py_Specialize_ForIter(PyObject *iter, _Py_CODEUNIT *instr, int oparg)
21652163
instr->op.code = FOR_ITER_TUPLE;
21662164
goto success;
21672165
}
2168-
else if (tp == &PyRangeIter_Type && next_op == STORE_FAST) {
2166+
else if (tp == &PyRangeIter_Type) {
21692167
instr->op.code = FOR_ITER_RANGE;
21702168
goto success;
21712169
}

0 commit comments

Comments
 (0)