Skip to content

bpo-47120: Replace the JUMP_ABSOLUTE opcode by the relative JUMP_BACKWARD #32115

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 14 commits into from
Mar 31, 2022
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions Doc/library/dis.rst
Original file line number Diff line number Diff line change
Expand Up @@ -895,6 +895,13 @@ iterations of the loop.
Increments bytecode counter by *delta*.


.. opcode:: JUMP_BACKWARD (delta)

Decrements bytecode counter by *delta*.

.. versionadded:: 3.11


.. opcode:: POP_JUMP_IF_TRUE (target)

If TOS is true, sets the bytecode counter to *target*. TOS is popped.
Expand Down Expand Up @@ -974,11 +981,6 @@ iterations of the loop.
.. versionadded:: 3.1


.. opcode:: JUMP_ABSOLUTE (target)

Set bytecode counter to *target*.


.. opcode:: JUMP_NO_INTERRUPT (target)

Set bytecode counter to *target*. Do not check for interrupts.
Expand Down
1 change: 1 addition & 0 deletions Doc/whatsnew/3.11.rst
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,7 @@ CPython bytecode changes

* :opcode:`JUMP_IF_NOT_EXC_MATCH` no longer pops the active exception.

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

Deprecated
==========
Expand Down
106 changes: 52 additions & 54 deletions Include/opcode.h

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

6 changes: 5 additions & 1 deletion Lib/dis.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
LOAD_CONST = opmap['LOAD_CONST']
LOAD_GLOBAL = opmap['LOAD_GLOBAL']
BINARY_OP = opmap['BINARY_OP']
JUMP_BACKWARD = opmap['JUMP_BACKWARD']

CACHE = opmap["CACHE"]

Expand Down Expand Up @@ -441,7 +442,8 @@ def _get_instructions_bytes(code, varname_from_oparg=None,
argval = arg*2
argrepr = "to " + repr(argval)
elif op in hasjrel:
argval = offset + 2 + arg*2
signed_arg = -arg if op == JUMP_BACKWARD else arg
argval = offset + 2 + signed_arg*2
argrepr = "to " + repr(argval)
elif op in haslocal or op in hasfree:
argval, argrepr = _get_name_info(arg, varname_from_oparg)
Expand Down Expand Up @@ -566,6 +568,8 @@ def findlabels(code):
for offset, op, arg in _unpack_opargs(code):
if arg is not None:
if op in hasjrel:
if op == JUMP_BACKWARD:
arg = -arg
label = offset + 2 + arg*2
elif op in hasjabs:
label = arg*2
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 @@ -396,6 +396,7 @@ def _write_atomic(path, data, mode=0o666):
# Python 3.11a6 3486 (Use inline caching for PRECALL and CALL)
# Python 3.11a6 3487 (Remove the adaptive "oparg counter" mechanism)
# Python 3.11a6 3488 (LOAD_GLOBAL can push additional NULL)
# Python 3.11a6 3489 (Add JUMP_BACK)

# Python 3.12 will start with magic number 3500

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

_PYCACHE = '__pycache__'
Expand Down
7 changes: 2 additions & 5 deletions Lib/opcode.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,10 +128,9 @@ def jabs_op(name, op, entries=0):
hascompare.append(107)
name_op('IMPORT_NAME', 108) # Index in name list
name_op('IMPORT_FROM', 109) # Index in name list
jrel_op('JUMP_FORWARD', 110) # Number of bytes to skip
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('JUMP_ABSOLUTE', 113) # ""
jabs_op('POP_JUMP_IF_FALSE', 114) # ""
jabs_op('POP_JUMP_IF_TRUE', 115) # ""
name_op('LOAD_GLOBAL', 116, 5) # Index in name list
Expand Down Expand Up @@ -166,6 +165,7 @@ def jabs_op(name, op, entries=0):
hasfree.append(138)
def_op('DELETE_DEREF', 139)
hasfree.append(139)
jrel_op('JUMP_BACKWARD', 140) # Number of words to skip (backwards)

def_op('CALL_FUNCTION_EX', 142) # Flags

Expand Down Expand Up @@ -259,9 +259,6 @@ def jabs_op(name, op, entries=0):
"COMPARE_OP_INT_JUMP",
"COMPARE_OP_STR_JUMP",
],
"JUMP_ABSOLUTE": [
"JUMP_ABSOLUTE_QUICK",
],
"LOAD_ATTR": [
"LOAD_ATTR_ADAPTIVE",
"LOAD_ATTR_INSTANCE_VALUE",
Expand Down
12 changes: 6 additions & 6 deletions Lib/test/test_dis.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ def bug708901():
>> FOR_ITER 2 (to 40)
STORE_FAST 0 (res)

%3d JUMP_ABSOLUTE 17 (to 34)
%3d JUMP_BACKWARD 3 (to 34)

%3d >> LOAD_CONST 0 (None)
RETURN_VALUE
Expand Down Expand Up @@ -354,7 +354,7 @@ def bug42562():
BINARY_OP 13 (+=)
STORE_NAME 0 (x)

2 JUMP_ABSOLUTE 4 (to 8)
2 JUMP_BACKWARD 6 (to 8)
"""

dis_traceback = """\
Expand Down Expand Up @@ -574,7 +574,7 @@ def foo(x):
LOAD_FAST 1 (z)
BINARY_OP 0 (+)
LIST_APPEND 2
JUMP_ABSOLUTE 4 (to 8)
JUMP_BACKWARD 8 (to 8)
>> RETURN_VALUE
""" % (dis_nested_1,
__file__,
Expand Down Expand Up @@ -1227,14 +1227,14 @@ def _prepare_test_cases():
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='JUMP_ABSOLUTE', opcode=113, arg=16, argval=32, argrepr='to 32', offset=78, starts_line=6, 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_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_ABSOLUTE', opcode=113, arg=16, argval=32, argrepr='to 32', offset=96, starts_line=7, is_jump_target=True, 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),
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=98, starts_line=10, is_jump_target=True, positions=None),
Instruction(opname='LOAD_CONST', opcode=100, arg=4, argval='I can haz else clause?', argrepr="'I can haz else clause?'", offset=110, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=112, starts_line=None, is_jump_target=False, positions=None),
Expand All @@ -1255,7 +1255,7 @@ def _prepare_test_cases():
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='JUMP_ABSOLUTE', opcode=113, arg=64, argval=128, argrepr='to 128', offset=184, starts_line=15, 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),
Expand Down
2 changes: 1 addition & 1 deletion Lib/test/test_peepholer.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ def f():
return list
for elem in ('LOAD_CONST', 'POP_JUMP_IF_FALSE'):
self.assertNotInBytecode(f, elem)
for elem in ('JUMP_ABSOLUTE',):
for elem in ('JUMP_BACKWARD',):
self.assertInBytecode(f, elem)
self.check_lnotab(f)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Replaced :opcode:`JUMP_ABSOLUTE` by the relative jump :opcode:`JUMP_BACKWARD`.

7 changes: 6 additions & 1 deletion Objects/frameobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,6 @@ mark_stacks(PyCodeObject *code_obj, int len)
stacks[i+1] = next_stack;
break;
}
case JUMP_ABSOLUTE:
case JUMP_NO_INTERRUPT:
j = get_arg(code, i);
assert(j < len);
Expand All @@ -264,6 +263,12 @@ mark_stacks(PyCodeObject *code_obj, int len)
assert(stacks[j] == UNINITIALIZED || stacks[j] == next_stack);
stacks[j] = next_stack;
break;
case JUMP_BACKWARD:
j = i + 1 - get_arg(code, i);
assert(j >= 0);
assert(stacks[j] == UNINITIALIZED || stacks[j] == next_stack);
stacks[j] = next_stack;
break;
case GET_ITER:
case GET_AITER:
next_stack = push_value(pop_value(next_stack), Iterator);
Expand Down
2 changes: 1 addition & 1 deletion Programs/test_frozenmain.h

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

Loading