bpo-47120: Replace the JUMP_ABSOLUTE opcode by the relative JUMP_BACKWARD (GH-32115)

This commit is contained in:
Irit Katriel 2022-03-31 14:14:15 +01:00 committed by GitHub
parent b36d222110
commit a00518d9ad
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 147 additions and 113 deletions

View file

@ -895,6 +895,13 @@ iterations of the loop.
Increments bytecode counter by *delta*. Increments bytecode counter by *delta*.
.. opcode:: JUMP_BACKWARD (delta)
Decrements bytecode counter by *delta*.
.. versionadded:: 3.11
.. opcode:: POP_JUMP_IF_TRUE (target) .. opcode:: POP_JUMP_IF_TRUE (target)
If TOS is true, sets the bytecode counter to *target*. TOS is popped. If TOS is true, sets the bytecode counter to *target*. TOS is popped.
@ -974,11 +981,6 @@ iterations of the loop.
.. versionadded:: 3.1 .. versionadded:: 3.1
.. opcode:: JUMP_ABSOLUTE (target)
Set bytecode counter to *target*.
.. opcode:: JUMP_NO_INTERRUPT (target) .. opcode:: JUMP_NO_INTERRUPT (target)
Set bytecode counter to *target*. Do not check for interrupts. Set bytecode counter to *target*. Do not check for interrupts.

View file

@ -522,6 +522,7 @@ CPython bytecode changes
* :opcode:`JUMP_IF_NOT_EXC_MATCH` no longer pops the active exception. * :opcode:`JUMP_IF_NOT_EXC_MATCH` no longer pops the active exception.
* Replaced :opcode:`JUMP_ABSOLUTE` by the relative :opcode:`JUMP_BACKWARD`.
Deprecated Deprecated
========== ==========

16
Include/opcode.h generated
View file

@ -67,7 +67,6 @@ extern "C" {
#define JUMP_FORWARD 110 #define JUMP_FORWARD 110
#define JUMP_IF_FALSE_OR_POP 111 #define JUMP_IF_FALSE_OR_POP 111
#define JUMP_IF_TRUE_OR_POP 112 #define JUMP_IF_TRUE_OR_POP 112
#define JUMP_ABSOLUTE 113
#define POP_JUMP_IF_FALSE 114 #define POP_JUMP_IF_FALSE 114
#define POP_JUMP_IF_TRUE 115 #define POP_JUMP_IF_TRUE 115
#define LOAD_GLOBAL 116 #define LOAD_GLOBAL 116
@ -94,6 +93,7 @@ extern "C" {
#define LOAD_DEREF 137 #define LOAD_DEREF 137
#define STORE_DEREF 138 #define STORE_DEREF 138
#define DELETE_DEREF 139 #define DELETE_DEREF 139
#define JUMP_BACKWARD 140
#define CALL_FUNCTION_EX 142 #define CALL_FUNCTION_EX 142
#define EXTENDED_ARG 144 #define EXTENDED_ARG 144
#define LIST_APPEND 145 #define LIST_APPEND 145
@ -135,7 +135,7 @@ extern "C" {
#define COMPARE_OP_FLOAT_JUMP 27 #define COMPARE_OP_FLOAT_JUMP 27
#define COMPARE_OP_INT_JUMP 28 #define COMPARE_OP_INT_JUMP 28
#define COMPARE_OP_STR_JUMP 29 #define COMPARE_OP_STR_JUMP 29
#define JUMP_ABSOLUTE_QUICK 34 #define JUMP_BACKWARD_QUICK 34
#define LOAD_ATTR_ADAPTIVE 36 #define LOAD_ATTR_ADAPTIVE 36
#define LOAD_ATTR_INSTANCE_VALUE 37 #define LOAD_ATTR_INSTANCE_VALUE 37
#define LOAD_ATTR_MODULE 38 #define LOAD_ATTR_MODULE 38
@ -168,7 +168,7 @@ extern "C" {
#define PRECALL_NO_KW_METHOD_DESCRIPTOR_O 79 #define PRECALL_NO_KW_METHOD_DESCRIPTOR_O 79
#define PRECALL_NO_KW_STR_1 80 #define PRECALL_NO_KW_STR_1 80
#define PRECALL_NO_KW_TUPLE_1 81 #define PRECALL_NO_KW_TUPLE_1 81
#define PRECALL_NO_KW_TYPE_1 140 #define PRECALL_NO_KW_TYPE_1 113
#define PRECALL_PYFUNC 141 #define PRECALL_PYFUNC 141
#define RESUME_QUICK 143 #define RESUME_QUICK 143
#define STORE_ATTR_ADAPTIVE 150 #define STORE_ATTR_ADAPTIVE 150
@ -196,7 +196,7 @@ static const uint32_t _PyOpcode_RelativeJump[8] = {
0U, 0U,
536870912U, 536870912U,
134234112U, 134234112U,
0U, 4096U,
0U, 0U,
0U, 0U,
0U, 0U,
@ -205,8 +205,8 @@ static const uint32_t _PyOpcode_Jump[8] = {
0U, 0U,
0U, 0U,
536870912U, 536870912U,
2316288000U, 2316156928U,
67U, 4163U,
0U, 0U,
0U, 0U,
0U, 0U,
@ -289,8 +289,8 @@ const uint8_t _PyOpcode_Deopt[256] = {
[IMPORT_NAME] = IMPORT_NAME, [IMPORT_NAME] = IMPORT_NAME,
[IMPORT_STAR] = IMPORT_STAR, [IMPORT_STAR] = IMPORT_STAR,
[IS_OP] = IS_OP, [IS_OP] = IS_OP,
[JUMP_ABSOLUTE] = JUMP_ABSOLUTE, [JUMP_BACKWARD] = JUMP_BACKWARD,
[JUMP_ABSOLUTE_QUICK] = JUMP_ABSOLUTE, [JUMP_BACKWARD_QUICK] = JUMP_BACKWARD,
[JUMP_FORWARD] = JUMP_FORWARD, [JUMP_FORWARD] = JUMP_FORWARD,
[JUMP_IF_FALSE_OR_POP] = JUMP_IF_FALSE_OR_POP, [JUMP_IF_FALSE_OR_POP] = JUMP_IF_FALSE_OR_POP,
[JUMP_IF_NOT_EG_MATCH] = JUMP_IF_NOT_EG_MATCH, [JUMP_IF_NOT_EG_MATCH] = JUMP_IF_NOT_EG_MATCH,

View file

@ -30,6 +30,7 @@ MAKE_FUNCTION_FLAGS = ('defaults', 'kwdefaults', 'annotations', 'closure')
LOAD_CONST = opmap['LOAD_CONST'] LOAD_CONST = opmap['LOAD_CONST']
LOAD_GLOBAL = opmap['LOAD_GLOBAL'] LOAD_GLOBAL = opmap['LOAD_GLOBAL']
BINARY_OP = opmap['BINARY_OP'] BINARY_OP = opmap['BINARY_OP']
JUMP_BACKWARD = opmap['JUMP_BACKWARD']
CACHE = opmap["CACHE"] CACHE = opmap["CACHE"]
@ -441,7 +442,8 @@ def _get_instructions_bytes(code, varname_from_oparg=None,
argval = arg*2 argval = arg*2
argrepr = "to " + repr(argval) argrepr = "to " + repr(argval)
elif op in hasjrel: 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) argrepr = "to " + repr(argval)
elif op in haslocal or op in hasfree: elif op in haslocal or op in hasfree:
argval, argrepr = _get_name_info(arg, varname_from_oparg) argval, argrepr = _get_name_info(arg, varname_from_oparg)
@ -566,6 +568,8 @@ def findlabels(code):
for offset, op, arg in _unpack_opargs(code): for offset, op, arg in _unpack_opargs(code):
if arg is not None: if arg is not None:
if op in hasjrel: if op in hasjrel:
if op == JUMP_BACKWARD:
arg = -arg
label = offset + 2 + arg*2 label = offset + 2 + arg*2
elif op in hasjabs: elif op in hasjabs:
label = arg*2 label = arg*2

View file

@ -396,6 +396,7 @@ _code_type = type(_write_atomic.__code__)
# Python 3.11a6 3486 (Use inline caching for PRECALL and CALL) # Python 3.11a6 3486 (Use inline caching for PRECALL and CALL)
# Python 3.11a6 3487 (Remove the adaptive "oparg counter" mechanism) # Python 3.11a6 3487 (Remove the adaptive "oparg counter" mechanism)
# Python 3.11a6 3488 (LOAD_GLOBAL can push additional NULL) # Python 3.11a6 3488 (LOAD_GLOBAL can push additional NULL)
# Python 3.11a6 3489 (Add JUMP_BACKWARD, remove JUMP_ABSOLUTE)
# Python 3.12 will start with magic number 3500 # Python 3.12 will start with magic number 3500
@ -410,7 +411,7 @@ _code_type = type(_write_atomic.__code__)
# Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array # Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array
# in PC/launcher.c must also be updated. # 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 _RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c
_PYCACHE = '__pycache__' _PYCACHE = '__pycache__'

View file

@ -128,10 +128,9 @@ def_op('COMPARE_OP', 107, 2) # Comparison operator
hascompare.append(107) hascompare.append(107)
name_op('IMPORT_NAME', 108) # Index in name list name_op('IMPORT_NAME', 108) # Index in name list
name_op('IMPORT_FROM', 109) # 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_FALSE_OR_POP', 111) # Target byte offset from beginning of code
jabs_op('JUMP_IF_TRUE_OR_POP', 112) # "" 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_FALSE', 114) # ""
jabs_op('POP_JUMP_IF_TRUE', 115) # "" jabs_op('POP_JUMP_IF_TRUE', 115) # ""
name_op('LOAD_GLOBAL', 116, 5) # Index in name list name_op('LOAD_GLOBAL', 116, 5) # Index in name list
@ -166,6 +165,7 @@ def_op('STORE_DEREF', 138)
hasfree.append(138) hasfree.append(138)
def_op('DELETE_DEREF', 139) def_op('DELETE_DEREF', 139)
hasfree.append(139) hasfree.append(139)
jrel_op('JUMP_BACKWARD', 140) # Number of words to skip (backwards)
def_op('CALL_FUNCTION_EX', 142) # Flags def_op('CALL_FUNCTION_EX', 142) # Flags
@ -259,8 +259,8 @@ _specializations = {
"COMPARE_OP_INT_JUMP", "COMPARE_OP_INT_JUMP",
"COMPARE_OP_STR_JUMP", "COMPARE_OP_STR_JUMP",
], ],
"JUMP_ABSOLUTE": [ "JUMP_BACKWARD": [
"JUMP_ABSOLUTE_QUICK", "JUMP_BACKWARD_QUICK",
], ],
"LOAD_ATTR": [ "LOAD_ATTR": [
"LOAD_ATTR_ADAPTIVE", "LOAD_ATTR_ADAPTIVE",

View file

@ -149,7 +149,7 @@ dis_bug708901 = """\
>> FOR_ITER 2 (to 40) >> FOR_ITER 2 (to 40)
STORE_FAST 0 (res) STORE_FAST 0 (res)
%3d JUMP_ABSOLUTE 17 (to 34) %3d JUMP_BACKWARD 3 (to 34)
%3d >> LOAD_CONST 0 (None) %3d >> LOAD_CONST 0 (None)
RETURN_VALUE RETURN_VALUE
@ -354,7 +354,7 @@ dis_compound_stmt_str = """\
BINARY_OP 13 (+=) BINARY_OP 13 (+=)
STORE_NAME 0 (x) STORE_NAME 0 (x)
2 JUMP_ABSOLUTE 4 (to 8) 2 JUMP_BACKWARD 6 (to 8)
""" """
dis_traceback = """\ dis_traceback = """\
@ -574,7 +574,7 @@ Disassembly of <code object <listcomp> at 0x..., file "%s", line %d>:
LOAD_FAST 1 (z) LOAD_FAST 1 (z)
BINARY_OP 0 (+) BINARY_OP 0 (+)
LIST_APPEND 2 LIST_APPEND 2
JUMP_ABSOLUTE 4 (to 8) JUMP_BACKWARD 8 (to 8)
>> RETURN_VALUE >> RETURN_VALUE
""" % (dis_nested_1, """ % (dis_nested_1,
__file__, __file__,
@ -1227,14 +1227,14 @@ expected_opinfo_jumpy = [
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='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='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_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_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='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='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_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='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_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_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='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), Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=112, starts_line=None, is_jump_target=False, positions=None),
@ -1255,7 +1255,7 @@ expected_opinfo_jumpy = [
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='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='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_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_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='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='COMPARE_OP', opcode=107, arg=0, argval='<', argrepr='<', offset=190, starts_line=None, is_jump_target=False, positions=None),

View file

@ -127,7 +127,7 @@ class TestTranforms(BytecodeTestCase):
return list return list
for elem in ('LOAD_CONST', 'POP_JUMP_IF_FALSE'): for elem in ('LOAD_CONST', 'POP_JUMP_IF_FALSE'):
self.assertNotInBytecode(f, elem) self.assertNotInBytecode(f, elem)
for elem in ('JUMP_ABSOLUTE',): for elem in ('JUMP_BACKWARD',):
self.assertInBytecode(f, elem) self.assertInBytecode(f, elem)
self.check_lnotab(f) self.check_lnotab(f)

View file

@ -0,0 +1,2 @@
Replaced :opcode:`JUMP_ABSOLUTE` by the relative jump :opcode:`JUMP_BACKWARD`.

View file

@ -237,7 +237,6 @@ mark_stacks(PyCodeObject *code_obj, int len)
stacks[i+1] = next_stack; stacks[i+1] = next_stack;
break; break;
} }
case JUMP_ABSOLUTE:
case JUMP_NO_INTERRUPT: case JUMP_NO_INTERRUPT:
j = get_arg(code, i); j = get_arg(code, i);
assert(j < len); assert(j < len);
@ -264,6 +263,12 @@ mark_stacks(PyCodeObject *code_obj, int len)
assert(stacks[j] == UNINITIALIZED || stacks[j] == next_stack); assert(stacks[j] == UNINITIALIZED || stacks[j] == next_stack);
stacks[j] = next_stack; stacks[j] = next_stack;
break; 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_ITER:
case GET_AITER: case GET_AITER:
next_stack = push_value(pop_value(next_stack), Iterator); next_stack = push_value(pop_value(next_stack), Iterator);

View file

@ -12,7 +12,7 @@ unsigned char M_test_frozenmain[] = {
68,0,93,25,90,6,2,0,101,2,100,6,101,6,155,0, 68,0,93,25,90,6,2,0,101,2,100,6,101,6,155,0,
100,7,101,5,101,6,25,0,0,0,0,0,0,0,0,0, 100,7,101,5,101,6,25,0,0,0,0,0,0,0,0,0,
155,0,157,4,166,1,0,0,171,1,0,0,0,0,0,0, 155,0,157,4,166,1,0,0,171,1,0,0,0,0,0,0,
0,0,1,0,113,60,100,1,83,0,41,8,233,0,0,0, 0,0,1,0,140,26,100,1,83,0,41,8,233,0,0,0,
0,78,122,18,70,114,111,122,101,110,32,72,101,108,108,111, 0,78,122,18,70,114,111,122,101,110,32,72,101,108,108,111,
32,87,111,114,108,100,122,8,115,121,115,46,97,114,103,118, 32,87,111,114,108,100,122,8,115,121,115,46,97,114,103,118,
218,6,99,111,110,102,105,103,41,5,90,12,112,114,111,103, 218,6,99,111,110,102,105,103,41,5,90,12,112,114,111,103,

View file

@ -2218,7 +2218,7 @@ handle_eval_breaker:
Py_DECREF(v); Py_DECREF(v);
if (err != 0) if (err != 0)
goto error; goto error;
PREDICT(JUMP_ABSOLUTE); PREDICT(JUMP_BACKWARD_QUICK);
DISPATCH(); DISPATCH();
} }
@ -2230,7 +2230,7 @@ handle_eval_breaker:
Py_DECREF(v); Py_DECREF(v);
if (err != 0) if (err != 0)
goto error; goto error;
PREDICT(JUMP_ABSOLUTE); PREDICT(JUMP_BACKWARD_QUICK);
DISPATCH(); DISPATCH();
} }
@ -3396,7 +3396,7 @@ handle_eval_breaker:
if (_PyDict_SetItem_Take2((PyDictObject *)map, key, value) != 0) { if (_PyDict_SetItem_Take2((PyDictObject *)map, key, value) != 0) {
goto error; goto error;
} }
PREDICT(JUMP_ABSOLUTE); PREDICT(JUMP_BACKWARD_QUICK);
DISPATCH(); DISPATCH();
} }
@ -3926,6 +3926,11 @@ handle_eval_breaker:
DISPATCH(); DISPATCH();
} }
TARGET(JUMP_BACKWARD) {
_PyCode_Warmup(frame->f_code);
JUMP_TO_INSTRUCTION(JUMP_BACKWARD_QUICK);
}
TARGET(POP_JUMP_IF_FALSE) { TARGET(POP_JUMP_IF_FALSE) {
PREDICTED(POP_JUMP_IF_FALSE); PREDICTED(POP_JUMP_IF_FALSE);
PyObject *cond = POP(); PyObject *cond = POP();
@ -4053,12 +4058,6 @@ handle_eval_breaker:
DISPATCH(); DISPATCH();
} }
TARGET(JUMP_ABSOLUTE) {
PREDICTED(JUMP_ABSOLUTE);
_PyCode_Warmup(frame->f_code);
JUMP_TO_INSTRUCTION(JUMP_ABSOLUTE_QUICK);
}
TARGET(JUMP_NO_INTERRUPT) { TARGET(JUMP_NO_INTERRUPT) {
/* This bytecode is used in the `yield from` or `await` loop. /* This bytecode is used in the `yield from` or `await` loop.
* If there is an interrupt, we want it handled in the innermost * If there is an interrupt, we want it handled in the innermost
@ -4069,10 +4068,10 @@ handle_eval_breaker:
DISPATCH(); DISPATCH();
} }
TARGET(JUMP_ABSOLUTE_QUICK) { TARGET(JUMP_BACKWARD_QUICK) {
PREDICTED(JUMP_ABSOLUTE_QUICK); PREDICTED(JUMP_BACKWARD_QUICK);
assert(oparg < INSTR_OFFSET()); assert(oparg < INSTR_OFFSET());
JUMPTO(oparg); JUMPBY(-oparg);
CHECK_EVAL_BREAKER(); CHECK_EVAL_BREAKER();
DISPATCH(); DISPATCH();
} }

View file

@ -76,6 +76,7 @@
#define SETUP_CLEANUP 254 #define SETUP_CLEANUP 254
#define SETUP_WITH 253 #define SETUP_WITH 253
#define POP_BLOCK 252 #define POP_BLOCK 252
#define JUMP 251
#define IS_TOP_LEVEL_AWAIT(c) ( \ #define IS_TOP_LEVEL_AWAIT(c) ( \
(c->c_flags->cf_flags & PyCF_ALLOW_TOP_LEVEL_AWAIT) \ (c->c_flags->cf_flags & PyCF_ALLOW_TOP_LEVEL_AWAIT) \
@ -127,7 +128,9 @@ is_relative_jump(struct instr *i)
static inline int static inline int
is_jump(struct instr *i) is_jump(struct instr *i)
{ {
return i->i_opcode >= SETUP_WITH || is_bit_set_in_table(_PyOpcode_Jump, i->i_opcode); return i->i_opcode >= SETUP_WITH ||
i->i_opcode == JUMP ||
is_bit_set_in_table(_PyOpcode_Jump, i->i_opcode);
} }
static int static int
@ -985,7 +988,8 @@ stack_effect(int opcode, int oparg, int jump)
/* Jumps */ /* Jumps */
case JUMP_FORWARD: case JUMP_FORWARD:
case JUMP_ABSOLUTE: case JUMP_BACKWARD:
case JUMP:
case JUMP_NO_INTERRUPT: case JUMP_NO_INTERRUPT:
return 0; return 0;
@ -2839,7 +2843,7 @@ compiler_jump_if(struct compiler *c, expr_ty e, basicblock *next, int cond)
return 0; return 0;
if (!compiler_jump_if(c, e->v.IfExp.body, next, cond)) if (!compiler_jump_if(c, e->v.IfExp.body, next, cond))
return 0; return 0;
ADDOP_JUMP_NOLINE(c, JUMP_FORWARD, end); ADDOP_JUMP_NOLINE(c, JUMP, end);
compiler_use_next_block(c, next2); compiler_use_next_block(c, next2);
if (!compiler_jump_if(c, e->v.IfExp.orelse, next, cond)) if (!compiler_jump_if(c, e->v.IfExp.orelse, next, cond))
return 0; return 0;
@ -2870,11 +2874,11 @@ compiler_jump_if(struct compiler *c, expr_ty e, basicblock *next, int cond)
basicblock *end = compiler_new_block(c); basicblock *end = compiler_new_block(c);
if (end == NULL) if (end == NULL)
return 0; return 0;
ADDOP_JUMP_NOLINE(c, JUMP_FORWARD, end); ADDOP_JUMP_NOLINE(c, JUMP, end);
compiler_use_next_block(c, cleanup); compiler_use_next_block(c, cleanup);
ADDOP(c, POP_TOP); ADDOP(c, POP_TOP);
if (!cond) { if (!cond) {
ADDOP_JUMP_NOLINE(c, JUMP_FORWARD, next); ADDOP_JUMP_NOLINE(c, JUMP, next);
} }
compiler_use_next_block(c, end); compiler_use_next_block(c, end);
return 1; return 1;
@ -2908,7 +2912,7 @@ compiler_ifexp(struct compiler *c, expr_ty e)
if (!compiler_jump_if(c, e->v.IfExp.test, next, 0)) if (!compiler_jump_if(c, e->v.IfExp.test, next, 0))
return 0; return 0;
VISIT(c, expr, e->v.IfExp.body); VISIT(c, expr, e->v.IfExp.body);
ADDOP_JUMP_NOLINE(c, JUMP_FORWARD, end); ADDOP_JUMP_NOLINE(c, JUMP, end);
compiler_use_next_block(c, next); compiler_use_next_block(c, next);
VISIT(c, expr, e->v.IfExp.orelse); VISIT(c, expr, e->v.IfExp.orelse);
compiler_use_next_block(c, end); compiler_use_next_block(c, end);
@ -2995,7 +2999,7 @@ compiler_if(struct compiler *c, stmt_ty s)
} }
VISIT_SEQ(c, stmt, s->v.If.body); VISIT_SEQ(c, stmt, s->v.If.body);
if (asdl_seq_LEN(s->v.If.orelse)) { if (asdl_seq_LEN(s->v.If.orelse)) {
ADDOP_JUMP_NOLINE(c, JUMP_FORWARD, end); ADDOP_JUMP_NOLINE(c, JUMP, end);
compiler_use_next_block(c, next); compiler_use_next_block(c, next);
VISIT_SEQ(c, stmt, s->v.If.orelse); VISIT_SEQ(c, stmt, s->v.If.orelse);
} }
@ -3027,7 +3031,7 @@ compiler_for(struct compiler *c, stmt_ty s)
VISIT_SEQ(c, stmt, s->v.For.body); VISIT_SEQ(c, stmt, s->v.For.body);
/* Mark jump as artificial */ /* Mark jump as artificial */
UNSET_LOC(c); UNSET_LOC(c);
ADDOP_JUMP(c, JUMP_ABSOLUTE, start); ADDOP_JUMP(c, JUMP, start);
compiler_use_next_block(c, cleanup); compiler_use_next_block(c, cleanup);
compiler_pop_fblock(c, FOR_LOOP, start); compiler_pop_fblock(c, FOR_LOOP, start);
@ -3072,7 +3076,7 @@ compiler_async_for(struct compiler *c, stmt_ty s)
/* Success block for __anext__ */ /* Success block for __anext__ */
VISIT(c, expr, s->v.AsyncFor.target); VISIT(c, expr, s->v.AsyncFor.target);
VISIT_SEQ(c, stmt, s->v.AsyncFor.body); VISIT_SEQ(c, stmt, s->v.AsyncFor.body);
ADDOP_JUMP(c, JUMP_ABSOLUTE, start); ADDOP_JUMP(c, JUMP, start);
compiler_pop_fblock(c, FOR_LOOP, start); compiler_pop_fblock(c, FOR_LOOP, start);
@ -3184,7 +3188,7 @@ compiler_break(struct compiler *c)
if (!compiler_unwind_fblock(c, loop, 0)) { if (!compiler_unwind_fblock(c, loop, 0)) {
return 0; return 0;
} }
ADDOP_JUMP(c, JUMP_ABSOLUTE, loop->fb_exit); ADDOP_JUMP(c, JUMP, loop->fb_exit);
return 1; return 1;
} }
@ -3200,7 +3204,7 @@ compiler_continue(struct compiler *c)
if (loop == NULL) { if (loop == NULL) {
return compiler_error(c, "'continue' not properly in loop"); return compiler_error(c, "'continue' not properly in loop");
} }
ADDOP_JUMP(c, JUMP_ABSOLUTE, loop->fb_block); ADDOP_JUMP(c, JUMP, loop->fb_block);
return 1; return 1;
} }
@ -3261,7 +3265,7 @@ compiler_try_finally(struct compiler *c, stmt_ty s)
ADDOP_NOLINE(c, POP_BLOCK); ADDOP_NOLINE(c, POP_BLOCK);
compiler_pop_fblock(c, FINALLY_TRY, body); compiler_pop_fblock(c, FINALLY_TRY, body);
VISIT_SEQ(c, stmt, s->v.Try.finalbody); VISIT_SEQ(c, stmt, s->v.Try.finalbody);
ADDOP_JUMP_NOLINE(c, JUMP_FORWARD, exit); ADDOP_JUMP_NOLINE(c, JUMP, exit);
/* `finally` block */ /* `finally` block */
compiler_use_next_block(c, end); compiler_use_next_block(c, end);
@ -3315,7 +3319,7 @@ compiler_try_star_finally(struct compiler *c, stmt_ty s)
ADDOP_NOLINE(c, POP_BLOCK); ADDOP_NOLINE(c, POP_BLOCK);
compiler_pop_fblock(c, FINALLY_TRY, body); compiler_pop_fblock(c, FINALLY_TRY, body);
VISIT_SEQ(c, stmt, s->v.TryStar.finalbody); VISIT_SEQ(c, stmt, s->v.TryStar.finalbody);
ADDOP_JUMP_NOLINE(c, JUMP_FORWARD, exit); ADDOP_JUMP_NOLINE(c, JUMP, exit);
/* `finally` block */ /* `finally` block */
compiler_use_next_block(c, end); compiler_use_next_block(c, end);
@ -3345,13 +3349,13 @@ compiler_try_star_finally(struct compiler *c, stmt_ty s)
[] SETUP_FINALLY L1 [] SETUP_FINALLY L1
[] <code for S> [] <code for S>
[] POP_BLOCK [] POP_BLOCK
[] JUMP_FORWARD L0 [] JUMP L0
[exc] L1: <evaluate E1> ) [exc] L1: <evaluate E1> )
[exc, E1] JUMP_IF_NOT_EXC_MATCH L2 ) only if E1 [exc, E1] JUMP_IF_NOT_EXC_MATCH L2 ) only if E1
[exc] <assign to V1> (or POP if no V1) [exc] <assign to V1> (or POP if no V1)
[] <code for S1> [] <code for S1>
JUMP_FORWARD L0 JUMP L0
[exc] L2: <evaluate E2> [exc] L2: <evaluate E2>
.............................etc....................... .............................etc.......................
@ -3384,7 +3388,7 @@ compiler_try_except(struct compiler *c, stmt_ty s)
if (s->v.Try.orelse && asdl_seq_LEN(s->v.Try.orelse)) { if (s->v.Try.orelse && asdl_seq_LEN(s->v.Try.orelse)) {
VISIT_SEQ(c, stmt, s->v.Try.orelse); VISIT_SEQ(c, stmt, s->v.Try.orelse);
} }
ADDOP_JUMP_NOLINE(c, JUMP_FORWARD, end); ADDOP_JUMP_NOLINE(c, JUMP, end);
n = asdl_seq_LEN(s->v.Try.handlers); n = asdl_seq_LEN(s->v.Try.handlers);
compiler_use_next_block(c, except); compiler_use_next_block(c, except);
@ -3447,7 +3451,7 @@ compiler_try_except(struct compiler *c, stmt_ty s)
ADDOP_LOAD_CONST(c, Py_None); ADDOP_LOAD_CONST(c, Py_None);
compiler_nameop(c, handler->v.ExceptHandler.name, Store); compiler_nameop(c, handler->v.ExceptHandler.name, Store);
compiler_nameop(c, handler->v.ExceptHandler.name, Del); compiler_nameop(c, handler->v.ExceptHandler.name, Del);
ADDOP_JUMP(c, JUMP_FORWARD, end); ADDOP_JUMP(c, JUMP, end);
/* except: */ /* except: */
compiler_use_next_block(c, cleanup_end); compiler_use_next_block(c, cleanup_end);
@ -3477,7 +3481,7 @@ compiler_try_except(struct compiler *c, stmt_ty s)
UNSET_LOC(c); UNSET_LOC(c);
ADDOP(c, POP_BLOCK); ADDOP(c, POP_BLOCK);
ADDOP(c, POP_EXCEPT); ADDOP(c, POP_EXCEPT);
ADDOP_JUMP(c, JUMP_FORWARD, end); ADDOP_JUMP(c, JUMP, end);
} }
compiler_use_next_block(c, except); compiler_use_next_block(c, except);
} }
@ -3501,7 +3505,7 @@ compiler_try_except(struct compiler *c, stmt_ty s)
[] SETUP_FINALLY L1 [] SETUP_FINALLY L1
[] <code for S> [] <code for S>
[] POP_BLOCK [] POP_BLOCK
[] JUMP_FORWARD L0 [] JUMP L0
[exc] L1: COPY 1 ) save copy of the original exception [exc] L1: COPY 1 ) save copy of the original exception
[orig, exc] BUILD_LIST ) list for raised/reraised excs ("result") [orig, exc] BUILD_LIST ) list for raised/reraised excs ("result")
@ -3514,7 +3518,7 @@ compiler_try_except(struct compiler *c, stmt_ty s)
[orig, res, rest] SETUP_FINALLY R1 [orig, res, rest] SETUP_FINALLY R1
[orig, res, rest] <code for S1> [orig, res, rest] <code for S1>
[orig, res, rest] JUMP_FORWARD L2 [orig, res, rest] JUMP L2
[orig, res, rest, i, v] R1: LIST_APPEND 3 ) exc raised in except* body - add to res [orig, res, rest, i, v] R1: LIST_APPEND 3 ) exc raised in except* body - add to res
[orig, res, rest, i] POP [orig, res, rest, i] POP
@ -3528,7 +3532,7 @@ compiler_try_except(struct compiler *c, stmt_ty s)
[exc] COPY 1 [exc] COPY 1
[exc, exc] POP_JUMP_IF_NOT_NONE RER [exc, exc] POP_JUMP_IF_NOT_NONE RER
[exc] POP_TOP [exc] POP_TOP
[] JUMP_FORWARD L0 [] JUMP L0
[exc] RER: SWAP 2 [exc] RER: SWAP 2
[exc, prev_exc_info] POP_EXCEPT [exc, prev_exc_info] POP_EXCEPT
@ -3572,7 +3576,7 @@ compiler_try_star_except(struct compiler *c, stmt_ty s)
VISIT_SEQ(c, stmt, s->v.TryStar.body); VISIT_SEQ(c, stmt, s->v.TryStar.body);
compiler_pop_fblock(c, TRY_EXCEPT, body); compiler_pop_fblock(c, TRY_EXCEPT, body);
ADDOP_NOLINE(c, POP_BLOCK); ADDOP_NOLINE(c, POP_BLOCK);
ADDOP_JUMP_NOLINE(c, JUMP_FORWARD, orelse); ADDOP_JUMP_NOLINE(c, JUMP, orelse);
Py_ssize_t n = asdl_seq_LEN(s->v.TryStar.handlers); Py_ssize_t n = asdl_seq_LEN(s->v.TryStar.handlers);
compiler_use_next_block(c, except); compiler_use_next_block(c, except);
@ -3657,7 +3661,7 @@ compiler_try_star_except(struct compiler *c, stmt_ty s)
compiler_nameop(c, handler->v.ExceptHandler.name, Store); compiler_nameop(c, handler->v.ExceptHandler.name, Store);
compiler_nameop(c, handler->v.ExceptHandler.name, Del); compiler_nameop(c, handler->v.ExceptHandler.name, Del);
} }
ADDOP_JUMP(c, JUMP_FORWARD, except); ADDOP_JUMP(c, JUMP, except);
/* except: */ /* except: */
compiler_use_next_block(c, cleanup_end); compiler_use_next_block(c, cleanup_end);
@ -3675,13 +3679,13 @@ compiler_try_star_except(struct compiler *c, stmt_ty s)
ADDOP_I(c, LIST_APPEND, 3); // exc ADDOP_I(c, LIST_APPEND, 3); // exc
ADDOP(c, POP_TOP); // lasti ADDOP(c, POP_TOP); // lasti
ADDOP_JUMP(c, JUMP_ABSOLUTE, except); ADDOP_JUMP(c, JUMP, except);
compiler_use_next_block(c, except); compiler_use_next_block(c, except);
if (i == n - 1) { if (i == n - 1) {
/* Add exc to the list (if not None it's the unhandled part of the EG) */ /* Add exc to the list (if not None it's the unhandled part of the EG) */
ADDOP_I(c, LIST_APPEND, 1); ADDOP_I(c, LIST_APPEND, 1);
ADDOP_JUMP(c, JUMP_FORWARD, reraise_star); ADDOP_JUMP(c, JUMP, reraise_star);
} }
} }
/* Mark as artificial */ /* Mark as artificial */
@ -3701,7 +3705,7 @@ compiler_try_star_except(struct compiler *c, stmt_ty s)
ADDOP(c, POP_TOP); ADDOP(c, POP_TOP);
ADDOP(c, POP_BLOCK); ADDOP(c, POP_BLOCK);
ADDOP(c, POP_EXCEPT); ADDOP(c, POP_EXCEPT);
ADDOP_JUMP(c, JUMP_FORWARD, end); ADDOP_JUMP(c, JUMP, end);
compiler_use_next_block(c, reraise); compiler_use_next_block(c, reraise);
ADDOP(c, POP_BLOCK); ADDOP(c, POP_BLOCK);
ADDOP_I(c, SWAP, 2); ADDOP_I(c, SWAP, 2);
@ -4542,7 +4546,7 @@ compiler_compare(struct compiler *c, expr_ty e)
basicblock *end = compiler_new_block(c); basicblock *end = compiler_new_block(c);
if (end == NULL) if (end == NULL)
return 0; return 0;
ADDOP_JUMP_NOLINE(c, JUMP_FORWARD, end); ADDOP_JUMP_NOLINE(c, JUMP, end);
compiler_use_next_block(c, cleanup); compiler_use_next_block(c, cleanup);
ADDOP_I(c, SWAP, 2); ADDOP_I(c, SWAP, 2);
ADDOP(c, POP_TOP); ADDOP(c, POP_TOP);
@ -5172,7 +5176,7 @@ compiler_sync_comprehension_generator(struct compiler *c,
} }
compiler_use_next_block(c, if_cleanup); compiler_use_next_block(c, if_cleanup);
if (start) { if (start) {
ADDOP_JUMP(c, JUMP_ABSOLUTE, start); ADDOP_JUMP(c, JUMP, start);
compiler_use_next_block(c, anchor); compiler_use_next_block(c, anchor);
} }
@ -5266,7 +5270,7 @@ compiler_async_comprehension_generator(struct compiler *c,
} }
} }
compiler_use_next_block(c, if_cleanup); compiler_use_next_block(c, if_cleanup);
ADDOP_JUMP(c, JUMP_ABSOLUTE, start); ADDOP_JUMP(c, JUMP, start);
compiler_pop_fblock(c, ASYNC_COMPREHENSION_GENERATOR, start); compiler_pop_fblock(c, ASYNC_COMPREHENSION_GENERATOR, start);
@ -5542,7 +5546,7 @@ compiler_async_with(struct compiler *c, stmt_ty s, int pos)
ADDOP(c, POP_TOP); ADDOP(c, POP_TOP);
ADDOP_JUMP(c, JUMP_ABSOLUTE, exit); ADDOP_JUMP(c, JUMP, exit);
/* For exceptional outcome: */ /* For exceptional outcome: */
compiler_use_next_block(c, final); compiler_use_next_block(c, final);
@ -5571,7 +5575,7 @@ compiler_async_with(struct compiler *c, stmt_ty s, int pos)
<code for BLOCK> <code for BLOCK>
LOAD_CONST (None, None, None) LOAD_CONST (None, None, None)
CALL_FUNCTION_EX 0 CALL_FUNCTION_EX 0
JUMP_FORWARD EXIT JUMP EXIT
E: WITH_EXCEPT_START (calls EXPR.__exit__) E: WITH_EXCEPT_START (calls EXPR.__exit__)
POP_JUMP_IF_TRUE T: POP_JUMP_IF_TRUE T:
RERAISE RERAISE
@ -5638,7 +5642,7 @@ compiler_with(struct compiler *c, stmt_ty s, int pos)
if (!compiler_call_exit_with_nones(c)) if (!compiler_call_exit_with_nones(c))
return 0; return 0;
ADDOP(c, POP_TOP); ADDOP(c, POP_TOP);
ADDOP_JUMP(c, JUMP_FORWARD, exit); ADDOP_JUMP(c, JUMP, exit);
/* For exceptional outcome: */ /* For exceptional outcome: */
compiler_use_next_block(c, final); compiler_use_next_block(c, final);
@ -6687,7 +6691,7 @@ compiler_pattern_or(struct compiler *c, pattern_ty p, pattern_context *pc)
} }
} }
assert(control); assert(control);
if (!compiler_addop_j(c, JUMP_FORWARD, end) || if (!compiler_addop_j(c, JUMP, end) ||
!emit_and_reset_fail_pop(c, pc)) !emit_and_reset_fail_pop(c, pc))
{ {
goto error; goto error;
@ -6699,7 +6703,7 @@ compiler_pattern_or(struct compiler *c, pattern_ty p, pattern_context *pc)
// Need to NULL this for the PyObject_Free call in the error block. // Need to NULL this for the PyObject_Free call in the error block.
old_pc.fail_pop = NULL; old_pc.fail_pop = NULL;
// No match. Pop the remaining copy of the subject and fail: // No match. Pop the remaining copy of the subject and fail:
if (!compiler_addop(c, POP_TOP) || !jump_to_fail_pop(c, pc, JUMP_FORWARD)) { if (!compiler_addop(c, POP_TOP) || !jump_to_fail_pop(c, pc, JUMP)) {
goto error; goto error;
} }
compiler_use_next_block(c, end); compiler_use_next_block(c, end);
@ -6906,7 +6910,7 @@ compiler_match_inner(struct compiler *c, stmt_ty s, pattern_context *pc)
ADDOP(c, POP_TOP); ADDOP(c, POP_TOP);
} }
VISIT_SEQ(c, stmt, m->body); VISIT_SEQ(c, stmt, m->body);
ADDOP_JUMP(c, JUMP_FORWARD, end); ADDOP_JUMP(c, JUMP, end);
// If the pattern fails to match, we want the line number of the // If the pattern fails to match, we want the line number of the
// cleanup to be associated with the failed pattern, not the last line // cleanup to be associated with the failed pattern, not the last line
// of the body // of the body
@ -7045,9 +7049,10 @@ stackdepth(struct compiler *c)
stackdepth_push(&sp, instr->i_target, target_depth); stackdepth_push(&sp, instr->i_target, target_depth);
} }
depth = new_depth; depth = new_depth;
if (instr->i_opcode == JUMP_ABSOLUTE || assert(instr->i_opcode != JUMP_FORWARD);
instr->i_opcode == JUMP_NO_INTERRUPT || assert(instr->i_opcode != JUMP_BACKWARD);
instr->i_opcode == JUMP_FORWARD || if (instr->i_opcode == JUMP_NO_INTERRUPT ||
instr->i_opcode == JUMP ||
instr->i_opcode == RETURN_VALUE || instr->i_opcode == RETURN_VALUE ||
instr->i_opcode == RAISE_VARARGS || instr->i_opcode == RAISE_VARARGS ||
instr->i_opcode == RERAISE) instr->i_opcode == RERAISE)
@ -7559,14 +7564,14 @@ normalize_jumps(struct assembler *a)
continue; continue;
} }
struct instr *last = &b->b_instr[b->b_iused-1]; struct instr *last = &b->b_instr[b->b_iused-1];
if (last->i_opcode == JUMP_ABSOLUTE) { assert(last->i_opcode != JUMP_FORWARD);
assert(last->i_opcode != JUMP_BACKWARD);
if (last->i_opcode == JUMP) {
if (last->i_target->b_visited == 0) { if (last->i_target->b_visited == 0) {
last->i_opcode = JUMP_FORWARD; last->i_opcode = JUMP_FORWARD;
} }
} else {
if (last->i_opcode == JUMP_FORWARD) { last->i_opcode = JUMP_BACKWARD;
if (last->i_target->b_visited == 1) {
last->i_opcode = JUMP_ABSOLUTE;
} }
} }
} }
@ -7602,7 +7607,14 @@ assemble_jump_offsets(struct assembler *a, struct compiler *c)
if (is_jump(instr)) { if (is_jump(instr)) {
instr->i_oparg = instr->i_target->b_offset; instr->i_oparg = instr->i_target->b_offset;
if (is_relative_jump(instr)) { if (is_relative_jump(instr)) {
instr->i_oparg -= bsize; if (instr->i_oparg < bsize) {
assert(instr->i_opcode == JUMP_BACKWARD);
instr->i_oparg = bsize - instr->i_oparg;
}
else {
assert(instr->i_opcode != JUMP_BACKWARD);
instr->i_oparg -= bsize;
}
} }
if (instr_size(instr) != isize) { if (instr_size(instr) != isize) {
extended_arg_recompile = 1; extended_arg_recompile = 1;
@ -8621,10 +8633,14 @@ optimize_basic_block(struct compiler *c, basicblock *bb, PyObject *consts)
inst->i_target = inst->i_target->b_next; inst->i_target = inst->i_target->b_next;
} }
target = &inst->i_target->b_instr[0]; target = &inst->i_target->b_instr[0];
assert(target->i_opcode != JUMP_FORWARD);
assert(target->i_opcode != JUMP_BACKWARD);
} }
else { else {
target = &nop; target = &nop;
} }
assert(inst->i_opcode != JUMP_FORWARD);
assert(inst->i_opcode != JUMP_BACKWARD);
switch (inst->i_opcode) { switch (inst->i_opcode) {
/* Remove LOAD_CONST const; conditional jump */ /* Remove LOAD_CONST const; conditional jump */
case LOAD_CONST: case LOAD_CONST:
@ -8647,7 +8663,7 @@ optimize_basic_block(struct compiler *c, basicblock *bb, PyObject *consts)
inst->i_opcode = NOP; inst->i_opcode = NOP;
jump_if_true = nextop == POP_JUMP_IF_TRUE; jump_if_true = nextop == POP_JUMP_IF_TRUE;
if (is_true == jump_if_true) { if (is_true == jump_if_true) {
bb->b_instr[i+1].i_opcode = JUMP_ABSOLUTE; bb->b_instr[i+1].i_opcode = JUMP;
bb->b_nofallthrough = 1; bb->b_nofallthrough = 1;
} }
else { else {
@ -8667,7 +8683,7 @@ optimize_basic_block(struct compiler *c, basicblock *bb, PyObject *consts)
} }
jump_if_true = nextop == JUMP_IF_TRUE_OR_POP; jump_if_true = nextop == JUMP_IF_TRUE_OR_POP;
if (is_true == jump_if_true) { if (is_true == jump_if_true) {
bb->b_instr[i+1].i_opcode = JUMP_ABSOLUTE; bb->b_instr[i+1].i_opcode = JUMP;
bb->b_nofallthrough = 1; bb->b_nofallthrough = 1;
} }
else { else {
@ -8738,8 +8754,7 @@ optimize_basic_block(struct compiler *c, basicblock *bb, PyObject *consts)
case POP_JUMP_IF_FALSE: case POP_JUMP_IF_FALSE:
i -= jump_thread(inst, target, POP_JUMP_IF_FALSE); i -= jump_thread(inst, target, POP_JUMP_IF_FALSE);
break; break;
case JUMP_ABSOLUTE: case JUMP:
case JUMP_FORWARD:
case JUMP_IF_FALSE_OR_POP: case JUMP_IF_FALSE_OR_POP:
i -= jump_thread(inst, target, JUMP_IF_FALSE_OR_POP); i -= jump_thread(inst, target, JUMP_IF_FALSE_OR_POP);
break; break;
@ -8761,8 +8776,7 @@ optimize_basic_block(struct compiler *c, basicblock *bb, PyObject *consts)
case POP_JUMP_IF_TRUE: case POP_JUMP_IF_TRUE:
i -= jump_thread(inst, target, POP_JUMP_IF_TRUE); i -= jump_thread(inst, target, POP_JUMP_IF_TRUE);
break; break;
case JUMP_ABSOLUTE: case JUMP:
case JUMP_FORWARD:
case JUMP_IF_TRUE_OR_POP: case JUMP_IF_TRUE_OR_POP:
i -= jump_thread(inst, target, JUMP_IF_TRUE_OR_POP); i -= jump_thread(inst, target, JUMP_IF_TRUE_OR_POP);
break; break;
@ -8782,36 +8796,38 @@ optimize_basic_block(struct compiler *c, basicblock *bb, PyObject *consts)
case POP_JUMP_IF_NOT_NONE: case POP_JUMP_IF_NOT_NONE:
case POP_JUMP_IF_NONE: case POP_JUMP_IF_NONE:
switch (target->i_opcode) { switch (target->i_opcode) {
case JUMP_ABSOLUTE: case JUMP:
case JUMP_FORWARD:
i -= jump_thread(inst, target, inst->i_opcode); i -= jump_thread(inst, target, inst->i_opcode);
} }
break; break;
case POP_JUMP_IF_FALSE: case POP_JUMP_IF_FALSE:
switch (target->i_opcode) { switch (target->i_opcode) {
case JUMP_ABSOLUTE: case JUMP:
case JUMP_FORWARD:
i -= jump_thread(inst, target, POP_JUMP_IF_FALSE); i -= jump_thread(inst, target, POP_JUMP_IF_FALSE);
} }
break; break;
case POP_JUMP_IF_TRUE: case POP_JUMP_IF_TRUE:
switch (target->i_opcode) { switch (target->i_opcode) {
case JUMP_ABSOLUTE: case JUMP:
case JUMP_FORWARD:
i -= jump_thread(inst, target, POP_JUMP_IF_TRUE); i -= jump_thread(inst, target, POP_JUMP_IF_TRUE);
} }
break; break;
case JUMP_ABSOLUTE: case JUMP:
case JUMP_FORWARD:
switch (target->i_opcode) { switch (target->i_opcode) {
case JUMP_ABSOLUTE: case JUMP:
case JUMP_FORWARD: i -= jump_thread(inst, target, JUMP);
i -= jump_thread(inst, target, JUMP_ABSOLUTE);
} }
break; break;
case FOR_ITER: case FOR_ITER:
if (target->i_opcode == JUMP_FORWARD) { if (target->i_opcode == JUMP) {
/* This will not work now because the jump (at target) could
* be forward or backward and FOR_ITER only jumps forward. We
* can re-enable this if ever we implement a backward version
* of FOR_ITER.
*/
/*
i -= jump_thread(inst, target, FOR_ITER); i -= jump_thread(inst, target, FOR_ITER);
*/
} }
break; break;
case SWAP: case SWAP:
@ -8852,7 +8868,9 @@ extend_block(basicblock *bb) {
return 0; return 0;
} }
struct instr *last = &bb->b_instr[bb->b_iused-1]; struct instr *last = &bb->b_instr[bb->b_iused-1];
if (last->i_opcode != JUMP_ABSOLUTE && last->i_opcode != JUMP_FORWARD) { if (last->i_opcode != JUMP &&
last->i_opcode != JUMP_FORWARD &&
last->i_opcode != JUMP_BACKWARD) {
return 0; return 0;
} }
if (last->i_target->b_exit && last->i_target->b_iused <= MAX_COPY_SIZE) { if (last->i_target->b_exit && last->i_target->b_iused <= MAX_COPY_SIZE) {
@ -8923,6 +8941,8 @@ normalize_basic_block(basicblock *bb) {
/* Mark blocks as exit and/or nofallthrough. /* Mark blocks as exit and/or nofallthrough.
Raise SystemError if CFG is malformed. */ Raise SystemError if CFG is malformed. */
for (int i = 0; i < bb->b_iused; i++) { for (int i = 0; i < bb->b_iused; i++) {
assert(bb->b_instr[i].i_opcode != JUMP_FORWARD);
assert(bb->b_instr[i].i_opcode != JUMP_BACKWARD);
switch(bb->b_instr[i].i_opcode) { switch(bb->b_instr[i].i_opcode) {
case RETURN_VALUE: case RETURN_VALUE:
case RAISE_VARARGS: case RAISE_VARARGS:
@ -8930,8 +8950,7 @@ normalize_basic_block(basicblock *bb) {
bb->b_exit = 1; bb->b_exit = 1;
bb->b_nofallthrough = 1; bb->b_nofallthrough = 1;
break; break;
case JUMP_ABSOLUTE: case JUMP:
case JUMP_FORWARD:
case JUMP_NO_INTERRUPT: case JUMP_NO_INTERRUPT:
bb->b_nofallthrough = 1; bb->b_nofallthrough = 1;
/* fall through */ /* fall through */
@ -9116,9 +9135,10 @@ optimize_cfg(struct compiler *c, struct assembler *a, PyObject *consts)
for (basicblock *b = a->a_entry; b != NULL; b = b->b_next) { for (basicblock *b = a->a_entry; b != NULL; b = b->b_next) {
if (b->b_iused > 0) { if (b->b_iused > 0) {
struct instr *b_last_instr = &b->b_instr[b->b_iused - 1]; struct instr *b_last_instr = &b->b_instr[b->b_iused - 1];
if (b_last_instr->i_opcode == JUMP_ABSOLUTE || assert(b_last_instr->i_opcode != JUMP_FORWARD);
b_last_instr->i_opcode == JUMP_NO_INTERRUPT || assert(b_last_instr->i_opcode != JUMP_BACKWARD);
b_last_instr->i_opcode == JUMP_FORWARD) { if (b_last_instr->i_opcode == JUMP ||
b_last_instr->i_opcode == JUMP_NO_INTERRUPT) {
if (b_last_instr->i_target == b->b_next) { if (b_last_instr->i_target == b->b_next) {
assert(b->b_next->b_iused); assert(b->b_next->b_iused);
b->b_nofallthrough = 0; b->b_nofallthrough = 0;

View file

@ -33,7 +33,7 @@ static void *opcode_targets[256] = {
&&TARGET_MATCH_MAPPING, &&TARGET_MATCH_MAPPING,
&&TARGET_MATCH_SEQUENCE, &&TARGET_MATCH_SEQUENCE,
&&TARGET_MATCH_KEYS, &&TARGET_MATCH_KEYS,
&&TARGET_JUMP_ABSOLUTE_QUICK, &&TARGET_JUMP_BACKWARD_QUICK,
&&TARGET_PUSH_EXC_INFO, &&TARGET_PUSH_EXC_INFO,
&&TARGET_LOAD_ATTR_ADAPTIVE, &&TARGET_LOAD_ATTR_ADAPTIVE,
&&TARGET_LOAD_ATTR_INSTANCE_VALUE, &&TARGET_LOAD_ATTR_INSTANCE_VALUE,
@ -112,7 +112,7 @@ static void *opcode_targets[256] = {
&&TARGET_JUMP_FORWARD, &&TARGET_JUMP_FORWARD,
&&TARGET_JUMP_IF_FALSE_OR_POP, &&TARGET_JUMP_IF_FALSE_OR_POP,
&&TARGET_JUMP_IF_TRUE_OR_POP, &&TARGET_JUMP_IF_TRUE_OR_POP,
&&TARGET_JUMP_ABSOLUTE, &&TARGET_PRECALL_NO_KW_TYPE_1,
&&TARGET_POP_JUMP_IF_FALSE, &&TARGET_POP_JUMP_IF_FALSE,
&&TARGET_POP_JUMP_IF_TRUE, &&TARGET_POP_JUMP_IF_TRUE,
&&TARGET_LOAD_GLOBAL, &&TARGET_LOAD_GLOBAL,
@ -139,7 +139,7 @@ static void *opcode_targets[256] = {
&&TARGET_LOAD_DEREF, &&TARGET_LOAD_DEREF,
&&TARGET_STORE_DEREF, &&TARGET_STORE_DEREF,
&&TARGET_DELETE_DEREF, &&TARGET_DELETE_DEREF,
&&TARGET_PRECALL_NO_KW_TYPE_1, &&TARGET_JUMP_BACKWARD,
&&TARGET_PRECALL_PYFUNC, &&TARGET_PRECALL_PYFUNC,
&&TARGET_CALL_FUNCTION_EX, &&TARGET_CALL_FUNCTION_EX,
&&TARGET_RESUME_QUICK, &&TARGET_RESUME_QUICK,

View file

@ -270,8 +270,8 @@ _PyCode_Quicken(PyCodeObject *code)
else { else {
assert(!_PyOpcode_Caches[opcode]); assert(!_PyOpcode_Caches[opcode]);
switch (opcode) { switch (opcode) {
case JUMP_ABSOLUTE: case JUMP_BACKWARD:
_Py_SET_OPCODE(instructions[i], JUMP_ABSOLUTE_QUICK); _Py_SET_OPCODE(instructions[i], JUMP_BACKWARD_QUICK);
break; break;
case RESUME: case RESUME:
_Py_SET_OPCODE(instructions[i], RESUME_QUICK); _Py_SET_OPCODE(instructions[i], RESUME_QUICK);