◐ Shell
clean mode source ↗

GH-100982: Restrict `FOR_ITER_RANGE` to a single instruction to allow instrumentation. by markshannon · Pull Request #101985 · python/cpython

Expand Up @@ -2178,35 +2178,27 @@ dummy_func( // Common case: no jump, leave it to the code generator }
// This is slightly different, when the loop isn't terminated we // jump over the immediately following STORE_FAST instruction. inst(FOR_ITER_RANGE, (unused/1, iter -- iter, unused)) { inst(FOR_ITER_RANGE, (unused/1, iter -- iter, next)) { assert(cframe.use_tracing == 0); _PyRangeIterObject *r = (_PyRangeIterObject *)iter; DEOPT_IF(Py_TYPE(r) != &PyRangeIter_Type, FOR_ITER); STAT_INC(FOR_ITER, hit); _Py_CODEUNIT next = next_instr[INLINE_CACHE_ENTRIES_FOR_ITER]; assert(_PyOpcode_Deopt[next.op.code] == STORE_FAST); if (r->len <= 0) { STACK_SHRINK(1); Py_DECREF(r); // Jump over END_FOR instruction. JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER + oparg + 1); DISPATCH(); } else { long value = r->start; r->start = value + r->step; r->len--; if (_PyLong_AssignValue(&GETLOCAL(next.op.arg), value) < 0) { goto error; } // The STORE_FAST is already done. JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER + 1); long value = r->start; r->start = value + r->step; r->len--; next = PyLong_FromLong(value); if (next == NULL) { goto error; } DISPATCH(); }
// This is *not* a super-instruction, unique in the family. inst(FOR_ITER_GEN, (unused/1, iter -- iter, unused)) { assert(cframe.use_tracing == 0); PyGenObject *gen = (PyGenObject *)iter; Expand Down