]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
GH-100982: Restrict `FOR_ITER_RANGE` to a single instruction to allow instrumentation...
authorMark Shannon <mark@hotpy.org>
Wed, 22 Feb 2023 11:11:57 +0000 (11:11 +0000)
committerGitHub <noreply@github.com>
Wed, 22 Feb 2023 11:11:57 +0000 (11:11 +0000)
Misc/NEWS.d/next/Core and Builtins/2023-02-17-10-12-13.gh-issue-100982.mJGJQw.rst [new file with mode: 0644]
Python/bytecodes.c
Python/generated_cases.c.h
Python/specialize.c

diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-02-17-10-12-13.gh-issue-100982.mJGJQw.rst b/Misc/NEWS.d/next/Core and Builtins/2023-02-17-10-12-13.gh-issue-100982.mJGJQw.rst
new file mode 100644 (file)
index 0000000..53bbc86
--- /dev/null
@@ -0,0 +1,2 @@
+Restrict the scope of the :opcode:`FOR_ITER_RANGE` instruction to the scope of the
+original :opcode:`FOR_ITER` instruction, to allow instrumentation.
index c5959f2f994fdc90cf71d8445da53ff9adb64840..ad68c794fe7acb0257709e2a98a8fefec7e84f9b 100644 (file)
@@ -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;
index 487e63d855d14a82a521d95f13dc85d405fe66c3..2987adc3bba566e4b4300666b2be71e1599972b7 100644 (file)
 
         TARGET(FOR_ITER_RANGE) {
             PyObject *iter = PEEK(1);
+            PyObject *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;
             }
+            STACK_GROW(1);
+            POKE(1, next);
+            JUMPBY(1);
             DISPATCH();
         }
 
index c9555f8ad4dccb73c560ec18f2877c417332e22a..3405d2b0ab068039d6f2ffbafa7ab3c49dd8508e 100644 (file)
@@ -2155,8 +2155,6 @@ _Py_Specialize_ForIter(PyObject *iter, _Py_CODEUNIT *instr, int oparg)
     assert(_PyOpcode_Caches[FOR_ITER] == INLINE_CACHE_ENTRIES_FOR_ITER);
     _PyForIterCache *cache = (_PyForIterCache *)(instr + 1);
     PyTypeObject *tp = Py_TYPE(iter);
-    _Py_CODEUNIT next = instr[1+INLINE_CACHE_ENTRIES_FOR_ITER];
-    int next_op = _PyOpcode_Deopt[next.op.code];
     if (tp == &PyListIter_Type) {
         instr->op.code = FOR_ITER_LIST;
         goto success;
@@ -2165,7 +2163,7 @@ _Py_Specialize_ForIter(PyObject *iter, _Py_CODEUNIT *instr, int oparg)
         instr->op.code = FOR_ITER_TUPLE;
         goto success;
     }
-    else if (tp == &PyRangeIter_Type && next_op == STORE_FAST) {
+    else if (tp == &PyRangeIter_Type) {
         instr->op.code = FOR_ITER_RANGE;
         goto success;
     }