Skip to content

Commit

Permalink
bpo-47120: make POP_JUMP_IF_TRUE/FALSE/NONE/NOT_NONE relative (GH-32400)
Browse files Browse the repository at this point in the history
  • Loading branch information
iritkatriel authored Apr 11, 2022
1 parent 98ff4a6 commit dd207a6
Show file tree
Hide file tree
Showing 14 changed files with 349 additions and 127 deletions.
48 changes: 38 additions & 10 deletions Doc/library/dis.rst
Original file line number Diff line number Diff line change
Expand Up @@ -937,30 +937,58 @@ iterations of the loop.
.. versionadded:: 3.11


.. opcode:: POP_JUMP_IF_TRUE (target)
.. opcode:: POP_JUMP_FORWARD_IF_TRUE (delta)

If TOS is true, sets the bytecode counter to *target*. TOS is popped.
If TOS is true, increments the bytecode counter by *delta*. TOS is popped.

.. versionadded:: 3.1
.. versionadded:: 3.11


.. opcode:: POP_JUMP_IF_FALSE (target)
.. opcode:: POP_JUMP_BACKWARD_IF_TRUE (delta)

If TOS is false, sets the bytecode counter to *target*. TOS is popped.
If TOS is true, decrements the bytecode counter by *delta*. TOS is popped.

.. versionadded:: 3.1
.. versionadded:: 3.11


.. opcode:: POP_JUMP_FORWARD_IF_FALSE (delta)

If TOS is false, increments the bytecode counter by *delta*. TOS is popped.

.. versionadded:: 3.11


.. opcode:: POP_JUMP_BACKWARD_IF_FALSE (delta)

If TOS is false, decrements the bytecode counter by *delta*. TOS is popped.

.. versionadded:: 3.11


.. opcode:: POP_JUMP_FORWARD_IF_NOT_NONE (delta)

If TOS is not ``None``, increments the bytecode counter by *delta*. TOS is popped.

.. versionadded:: 3.11


.. opcode:: POP_JUMP_BACKWARD_IF_NOT_NONE (delta)

If TOS is not ``None``, decrements the bytecode counter by *delta*. TOS is popped.

.. versionadded:: 3.11


.. opcode:: POP_JUMP_IF_NOT_NONE (target)
.. opcode:: POP_JUMP_FORWARD_IF_NONE (delta)

If TOS is not none, sets the bytecode counter to *target*. TOS is popped.
If TOS is ``None``, increments the bytecode counter by *delta*. TOS is popped.

.. versionadded:: 3.11


.. opcode:: POP_JUMP_IF_NONE (target)
.. opcode:: POP_JUMP_BACKWARD_IF_NONE (delta)

If TOS is none, sets the bytecode counter to *target*. TOS is popped.
If TOS is ``None``, decrements the bytecode counter by *delta*. TOS is popped.

.. versionadded:: 3.11

Expand Down
15 changes: 11 additions & 4 deletions Doc/whatsnew/3.11.rst
Original file line number Diff line number Diff line change
Expand Up @@ -750,9 +750,6 @@ CPython bytecode changes
``ROT_TWO``, ``ROT_THREE``, ``ROT_FOUR``, and ``ROT_N``) with new
:opcode:`COPY` and :opcode:`SWAP` instructions.

* Add :opcode:`POP_JUMP_IF_NOT_NONE` and :opcode:`POP_JUMP_IF_NONE` opcodes to
speed up conditional jumps.

* Replaced :opcode:`JUMP_IF_NOT_EXC_MATCH` by :opcode:`CHECK_EXC_MATCH` which
performs the check but does not jump.

Expand All @@ -761,7 +758,17 @@ CPython bytecode changes

* Replaced :opcode:`JUMP_ABSOLUTE` by the relative :opcode:`JUMP_BACKWARD`.

* Added :opcode:`JUMP_BACKWARD_NO_INTERRUPT`, which is used in certain loops where it is undesirable to handle interrupts.
* Added :opcode:`JUMP_BACKWARD_NO_INTERRUPT`, which is used in certain loops where it
is undesirable to handle interrupts.

* Replaced :opcode:`POP_JUMP_IF_TRUE` and :opcode:`POP_JUMP_IF_FALSE` by
the relative :opcode:`POP_JUMP_FORWARD_IF_TRUE`, :opcode:`POP_JUMP_BACKWARD_IF_TRUE`,
:opcode:`POP_JUMP_FORWARD_IF_FALSE` and :opcode:`POP_JUMP_BACKWARD_IF_FALSE`.

* Added :opcode:`POP_JUMP_FORWARD_IF_NOT_NONE`, :opcode:`POP_JUMP_BACKWARD_IF_NOT_NONE`,
:opcode:`POP_JUMP_FORWARD_IF_NONE` and :opcode:`POP_JUMP_BACKWARD_IF_NONE`
opcodes to speed up conditional jumps.


Deprecated
==========
Expand Down
38 changes: 23 additions & 15 deletions Include/opcode.h

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

7 changes: 5 additions & 2 deletions Lib/dis.py
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,9 @@ def parse_exception_table(code):
except StopIteration:
return entries

def _is_backward_jump(op):
return 'JUMP_BACKWARD' in opname[op]

def _get_instructions_bytes(code, varname_from_oparg=None,
names=None, co_consts=None,
linestarts=None, line_offset=0,
Expand Down Expand Up @@ -442,7 +445,7 @@ def _get_instructions_bytes(code, varname_from_oparg=None,
argval = arg*2
argrepr = "to " + repr(argval)
elif op in hasjrel:
signed_arg = -arg if op == JUMP_BACKWARD else arg
signed_arg = -arg if _is_backward_jump(op) else arg
argval = offset + 2 + signed_arg*2
argrepr = "to " + repr(argval)
elif op in haslocal or op in hasfree:
Expand Down Expand Up @@ -568,7 +571,7 @@ def findlabels(code):
for offset, op, arg in _unpack_opargs(code):
if arg is not None:
if op in hasjrel:
if op == JUMP_BACKWARD:
if _is_backward_jump(op):
arg = -arg
label = offset + 2 + arg*2
elif op in hasjabs:
Expand Down
3 changes: 2 additions & 1 deletion Lib/importlib/_bootstrap_external.py
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,7 @@ def _write_atomic(path, data, mode=0o666):
# Python 3.11a6 3490 (remove JUMP_IF_NOT_EXC_MATCH, add CHECK_EXC_MATCH)
# Python 3.11a6 3491 (remove JUMP_IF_NOT_EG_MATCH, add CHECK_EG_MATCH,
# add JUMP_BACKWARD_NO_INTERRUPT, make JUMP_NO_INTERRUPT virtual)
# Python 3.11a7 3492 (make POP_JUMP_IF_NONE/NOT_NONE/TRUE/FALSE relative)

# Python 3.12 will start with magic number 3500

Expand All @@ -414,7 +415,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 = (3491).to_bytes(2, 'little') + b'\r\n'
MAGIC_NUMBER = (3492).to_bytes(2, 'little') + b'\r\n'
_RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c

_PYCACHE = '__pycache__'
Expand Down
13 changes: 9 additions & 4 deletions Lib/opcode.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,8 @@ def jabs_op(name, op, entries=0):
jrel_op('JUMP_FORWARD', 110) # Number of words to skip
jabs_op('JUMP_IF_FALSE_OR_POP', 111) # Target byte offset from beginning of code
jabs_op('JUMP_IF_TRUE_OR_POP', 112) # ""
jabs_op('POP_JUMP_IF_FALSE', 114) # ""
jabs_op('POP_JUMP_IF_TRUE', 115) # ""
jrel_op('POP_JUMP_FORWARD_IF_FALSE', 114)
jrel_op('POP_JUMP_FORWARD_IF_TRUE', 115)
name_op('LOAD_GLOBAL', 116, 5) # Index in name list
def_op('IS_OP', 117)
def_op('CONTAINS_OP', 118)
Expand All @@ -148,8 +148,8 @@ def jabs_op(name, op, entries=0):
haslocal.append(125)
def_op('DELETE_FAST', 126) # Local variable number
haslocal.append(126)
jabs_op('POP_JUMP_IF_NOT_NONE', 128)
jabs_op('POP_JUMP_IF_NONE', 129)
jrel_op('POP_JUMP_FORWARD_IF_NOT_NONE', 128)
jrel_op('POP_JUMP_FORWARD_IF_NONE', 129)
def_op('RAISE_VARARGS', 130) # Number of raise arguments (1, 2, or 3)
def_op('GET_AWAITABLE', 131)
def_op('MAKE_FUNCTION', 132) # Flags
Expand Down Expand Up @@ -197,6 +197,11 @@ def jabs_op(name, op, entries=0):
def_op('KW_NAMES', 172)
hasconst.append(172)

jrel_op('POP_JUMP_BACKWARD_IF_NOT_NONE', 173)
jrel_op('POP_JUMP_BACKWARD_IF_NONE', 174)
jrel_op('POP_JUMP_BACKWARD_IF_FALSE', 175)
jrel_op('POP_JUMP_BACKWARD_IF_TRUE', 176)


del def_op, name_op, jrel_op, jabs_op

Expand Down
28 changes: 18 additions & 10 deletions Lib/test/test_dis.py
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,7 @@ def bug42562():
%3d LOAD_GLOBAL 0 (Exception)
CHECK_EXC_MATCH
POP_JUMP_IF_FALSE 36 (to 72)
POP_JUMP_FORWARD_IF_FALSE 18 (to 72)
STORE_FAST 0 (e)
%3d LOAD_FAST 0 (e)
Expand Down Expand Up @@ -685,7 +685,15 @@ def test_widths(self):
for opcode, opname in enumerate(dis.opname):
if opname in ('BUILD_MAP_UNPACK_WITH_CALL',
'BUILD_TUPLE_UNPACK_WITH_CALL',
'JUMP_BACKWARD_NO_INTERRUPT'):
'JUMP_BACKWARD_NO_INTERRUPT',
'POP_JUMP_FORWARD_IF_NONE',
'POP_JUMP_BACKWARD_IF_NONE',
'POP_JUMP_FORWARD_IF_NOT_NONE',
'POP_JUMP_BACKWARD_IF_NOT_NONE',
'POP_JUMP_FORWARD_IF_TRUE',
'POP_JUMP_BACKWARD_IF_TRUE',
'POP_JUMP_FORWARD_IF_FALSE',
'POP_JUMP_BACKWARD_IF_FALSE'):
continue
with self.subTest(opname=opname):
width = dis._OPNAME_WIDTH
Expand Down Expand Up @@ -1227,12 +1235,12 @@ def _prepare_test_cases():
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=66, starts_line=5, is_jump_target=False, positions=None),
Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=68, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='COMPARE_OP', opcode=107, arg=0, argval='<', argrepr='<', offset=70, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=40, argval=80, argrepr='to 80', offset=76, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_JUMP_FORWARD_IF_FALSE', opcode=114, arg=1, argval=80, argrepr='to 80', offset=76, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='JUMP_BACKWARD', opcode=140, arg=24, argval=32, argrepr='to 32', offset=78, starts_line=6, is_jump_target=False, positions=None),
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=80, starts_line=7, is_jump_target=True, positions=None),
Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=6, argrepr='6', offset=82, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='COMPARE_OP', opcode=107, arg=4, argval='>', argrepr='>', offset=84, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=48, argval=96, argrepr='to 96', offset=90, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_JUMP_FORWARD_IF_FALSE', opcode=114, arg=2, argval=96, argrepr='to 96', offset=90, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=92, starts_line=8, is_jump_target=False, positions=None),
Instruction(opname='JUMP_FORWARD', opcode=110, arg=16, argval=128, argrepr='to 128', offset=94, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='JUMP_BACKWARD', opcode=140, arg=33, argval=32, argrepr='to 32', offset=96, starts_line=7, is_jump_target=True, positions=None),
Expand All @@ -1242,7 +1250,7 @@ def _prepare_test_cases():
Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=116, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=126, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=128, starts_line=11, is_jump_target=True, positions=None),
Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=102, argval=204, argrepr='to 204', offset=130, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_JUMP_FORWARD_IF_FALSE', opcode=114, arg=36, argval=204, argrepr='to 204', offset=130, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=132, starts_line=12, is_jump_target=True, positions=None),
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=144, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=146, starts_line=None, is_jump_target=False, positions=None),
Expand All @@ -1255,15 +1263,15 @@ def _prepare_test_cases():
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=172, starts_line=14, is_jump_target=False, positions=None),
Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=6, argrepr='6', offset=174, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='COMPARE_OP', opcode=107, arg=4, argval='>', argrepr='>', offset=176, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=93, argval=186, argrepr='to 186', offset=182, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_JUMP_FORWARD_IF_FALSE', opcode=114, arg=1, argval=186, argrepr='to 186', offset=182, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='JUMP_BACKWARD', opcode=140, arg=29, argval=128, argrepr='to 128', offset=184, starts_line=15, is_jump_target=False, positions=None),
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=186, starts_line=16, is_jump_target=True, positions=None),
Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=188, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='COMPARE_OP', opcode=107, arg=0, argval='<', argrepr='<', offset=190, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=100, argval=200, argrepr='to 200', offset=196, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_JUMP_FORWARD_IF_FALSE', opcode=114, arg=1, argval=200, argrepr='to 200', offset=196, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='JUMP_FORWARD', opcode=110, arg=17, argval=234, argrepr='to 234', offset=198, starts_line=17, is_jump_target=False, positions=None),
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=200, starts_line=11, is_jump_target=True, positions=None),
Instruction(opname='POP_JUMP_IF_TRUE', opcode=115, arg=66, argval=132, argrepr='to 132', offset=202, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_JUMP_BACKWARD_IF_TRUE', opcode=176, arg=36, argval=132, argrepr='to 132', offset=202, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=204, starts_line=19, is_jump_target=True, positions=None),
Instruction(opname='LOAD_CONST', opcode=100, arg=6, argval='Who let lolcatz into this test suite?', argrepr="'Who let lolcatz into this test suite?'", offset=216, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=218, starts_line=None, is_jump_target=False, positions=None),
Expand Down Expand Up @@ -1291,7 +1299,7 @@ def _prepare_test_cases():
Instruction(opname='JUMP_FORWARD', opcode=110, arg=11, argval=328, argrepr='to 328', offset=304, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=306, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='WITH_EXCEPT_START', opcode=49, arg=None, argval=None, argrepr='', offset=308, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_JUMP_IF_TRUE', opcode=115, arg=160, argval=320, argrepr='to 320', offset=310, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_JUMP_FORWARD_IF_TRUE', opcode=115, arg=4, argval=320, argrepr='to 320', offset=310, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='RERAISE', opcode=119, arg=2, argval=2, argrepr='', offset=312, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=314, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=316, starts_line=None, is_jump_target=False, positions=None),
Expand All @@ -1304,7 +1312,7 @@ def _prepare_test_cases():
Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=330, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=4, argval='ZeroDivisionError', argrepr='ZeroDivisionError', offset=332, starts_line=22, is_jump_target=False, positions=None),
Instruction(opname='CHECK_EXC_MATCH', opcode=36, arg=None, argval=None, argrepr='', offset=344, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=192, argval=384, argrepr='to 384', offset=346, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_JUMP_FORWARD_IF_FALSE', opcode=114, arg=18, argval=384, argrepr='to 384', offset=346, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=348, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=350, starts_line=23, is_jump_target=False, positions=None),
Instruction(opname='LOAD_CONST', opcode=100, arg=9, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=362, starts_line=None, is_jump_target=False, positions=None),
Expand Down
Loading

0 comments on commit dd207a6

Please sign in to comment.