[Python-checkins] GH-100982: Restrict `FOR_ITER_RANGE` to a single instruction to allow instrumentation. (GH-101985)
markshannon
webhook-mailer at python.org
Wed Feb 22 06:12:17 EST 2023
https://github.com/python/cpython/commit/7c106a443f8cf1111947a425eed11ecf9e615ce3
commit: 7c106a443f8cf1111947a425eed11ecf9e615ce3
branch: main
author: Mark Shannon <mark at hotpy.org>
committer: markshannon <mark at hotpy.org>
date: 2023-02-22T11:11:57Z
summary:
GH-100982: Restrict `FOR_ITER_RANGE` to a single instruction to allow instrumentation. (GH-101985)
files:
A Misc/NEWS.d/next/Core and Builtins/2023-02-17-10-12-13.gh-issue-100982.mJGJQw.rst
M Python/bytecodes.c
M Python/generated_cases.c.h
M 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
index 000000000000..53bbc860c53f
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2023-02-17-10-12-13.gh-issue-100982.mJGJQw.rst
@@ -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.
diff --git a/Python/bytecodes.c b/Python/bytecodes.c
index c5959f2f994f..ad68c794fe7a 100644
--- a/Python/bytecodes.c
+++ b/Python/bytecodes.c
@@ -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;
diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h
index 487e63d855d1..2987adc3bba5 100644
--- a/Python/generated_cases.c.h
+++ b/Python/generated_cases.c.h
@@ -2756,28 +2756,28 @@
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();
}
diff --git a/Python/specialize.c b/Python/specialize.c
index c9555f8ad4dc..3405d2b0ab06 100644
--- a/Python/specialize.c
+++ b/Python/specialize.c
@@ -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;
}
More information about the Python-checkins
mailing list