Skip to content

GH-96793: Change FOR_ITER to not pop the iterator on exhaustion. #96801

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Oct 27, 2022
Merged
13 changes: 12 additions & 1 deletion Doc/library/dis.rst
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,15 @@ The Python compiler currently generates the following bytecode instructions.
Removes the top-of-stack (TOS) item.


.. opcode:: END_FOR

Removes the top two values from the stack.
Equivalent to POP_TOP; POP_TOP.
Used to clean up at the end of loops, hence the name.

.. versionadded:: 3.12


.. opcode:: COPY (i)

Push the *i*-th item to the top of the stack. The item is not removed from its
Expand Down Expand Up @@ -1088,9 +1097,11 @@ iterations of the loop.

TOS is an :term:`iterator`. Call its :meth:`~iterator.__next__` method. If
this yields a new value, push it on the stack (leaving the iterator below
it). If the iterator indicates it is exhausted, TOS is popped, and the byte
it). If the iterator indicates it is exhausted then the byte
code counter is incremented by *delta*.

.. versionchanged:: 3.12
Up until 3.11 the iterator was popped when it was exhausted.

.. opcode:: LOAD_GLOBAL (namei)

Expand Down
40 changes: 20 additions & 20 deletions Include/internal/pycore_opcode.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

145 changes: 73 additions & 72 deletions Include/opcode.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Lib/importlib/_bootstrap_external.py
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,7 @@ def _write_atomic(path, data, mode=0o666):
# Python 3.12a1 3507 (Set lineno of module's RESUME to 0)
# Python 3.12a1 3508 (Add CLEANUP_THROW)
# Python 3.12a1 3509 (Conditional jumps only jump forward)
# Python 3.12a1 3510 (FOR_ITER leaves iterator on the stack)

# Python 3.13 will start with 3550

Expand All @@ -435,7 +436,7 @@ def _write_atomic(path, data, mode=0o666):
# Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array
# in PC/launcher.c must also be updated.

MAGIC_NUMBER = (3509).to_bytes(2, 'little') + b'\r\n'
MAGIC_NUMBER = (3510).to_bytes(2, 'little') + b'\r\n'

_RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c

Expand Down
2 changes: 2 additions & 0 deletions Lib/opcode.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ def pseudo_op(name, op, real_ops):
def_op('POP_TOP', 1)
def_op('PUSH_NULL', 2)

def_op('END_FOR', 4)

def_op('NOP', 9)
def_op('UNARY_POSITIVE', 10)
def_op('UNARY_NEGATIVE', 11)
Expand Down
Loading