From 2ad036e0882f6034ad2309fed322f9934ba09e7b Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 24 Mar 2022 15:15:21 +0000 Subject: [PATCH 01/10] bpo-47120: add the JUMP_BACKWARD opcode --- Doc/library/dis.rst | 7 ++++++ Include/opcode.h | 36 +++++++++++++++------------- Lib/dis.py | 6 ++++- Lib/importlib/_bootstrap_external.py | 3 ++- Lib/opcode.py | 3 ++- Lib/test/test_dis.py | 12 +++++----- Lib/test/test_peepholer.py | 2 +- Objects/frameobject.c | 6 +++++ Programs/test_frozenmain.h | 2 +- Python/ceval.c | 5 ++++ Python/compile.c | 36 ++++++++++++++++++++++++---- Python/opcode_targets.h | 16 ++++++------- 12 files changed, 93 insertions(+), 41 deletions(-) diff --git a/Doc/library/dis.rst b/Doc/library/dis.rst index 877e11b7376b77..a889f43a5b4f17 100644 --- a/Doc/library/dis.rst +++ b/Doc/library/dis.rst @@ -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. diff --git a/Include/opcode.h b/Include/opcode.h index dfc7b72e3cdc68..4ab2591875b2d1 100644 --- a/Include/opcode.h +++ b/Include/opcode.h @@ -94,6 +94,7 @@ extern "C" { #define LOAD_DEREF 137 #define STORE_DEREF 138 #define DELETE_DEREF 139 +#define JUMP_BACKWARD 140 #define CALL_FUNCTION_EX 142 #define EXTENDED_ARG 144 #define LIST_APPEND 145 @@ -168,21 +169,21 @@ extern "C" { #define PRECALL_NO_KW_STR_1 79 #define PRECALL_NO_KW_TUPLE_1 80 #define PRECALL_NO_KW_TYPE_1 81 -#define PRECALL_PYFUNC 140 -#define RESUME_QUICK 141 -#define STORE_ATTR_ADAPTIVE 143 -#define STORE_ATTR_INSTANCE_VALUE 150 -#define STORE_ATTR_SLOT 153 -#define STORE_ATTR_WITH_HINT 154 -#define STORE_FAST__LOAD_FAST 158 -#define STORE_FAST__STORE_FAST 159 -#define STORE_SUBSCR_ADAPTIVE 161 -#define STORE_SUBSCR_DICT 167 -#define STORE_SUBSCR_LIST_INT 168 -#define UNPACK_SEQUENCE_ADAPTIVE 169 -#define UNPACK_SEQUENCE_LIST 170 -#define UNPACK_SEQUENCE_TUPLE 173 -#define UNPACK_SEQUENCE_TWO_TUPLE 174 +#define PRECALL_PYFUNC 141 +#define RESUME_QUICK 143 +#define STORE_ATTR_ADAPTIVE 150 +#define STORE_ATTR_INSTANCE_VALUE 153 +#define STORE_ATTR_SLOT 154 +#define STORE_ATTR_WITH_HINT 158 +#define STORE_FAST__LOAD_FAST 159 +#define STORE_FAST__STORE_FAST 161 +#define STORE_SUBSCR_ADAPTIVE 167 +#define STORE_SUBSCR_DICT 168 +#define STORE_SUBSCR_LIST_INT 169 +#define UNPACK_SEQUENCE_ADAPTIVE 170 +#define UNPACK_SEQUENCE_LIST 173 +#define UNPACK_SEQUENCE_TUPLE 174 +#define UNPACK_SEQUENCE_TWO_TUPLE 175 #define DO_TRACING 255 extern const uint8_t _PyOpcode_Caches[256]; @@ -195,7 +196,7 @@ static const uint32_t _PyOpcode_RelativeJump[8] = { 0U, 536870912U, 134234112U, - 0U, + 4096U, 0U, 0U, 0U, @@ -205,7 +206,7 @@ static const uint32_t _PyOpcode_Jump[8] = { 0U, 536870912U, 2316288000U, - 67U, + 4163U, 0U, 0U, 0U, @@ -290,6 +291,7 @@ const uint8_t _PyOpcode_Deopt[256] = { [IS_OP] = IS_OP, [JUMP_ABSOLUTE] = JUMP_ABSOLUTE, [JUMP_ABSOLUTE_QUICK] = JUMP_ABSOLUTE, + [JUMP_BACKWARD] = JUMP_BACKWARD, [JUMP_FORWARD] = JUMP_FORWARD, [JUMP_IF_FALSE_OR_POP] = JUMP_IF_FALSE_OR_POP, [JUMP_IF_NOT_EG_MATCH] = JUMP_IF_NOT_EG_MATCH, diff --git a/Lib/dis.py b/Lib/dis.py index 3b7747b03ffb1c..d9936ce1a002c3 100644 --- a/Lib/dis.py +++ b/Lib/dis.py @@ -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"] @@ -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) @@ -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 diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py index 48b55bb821f8bb..0dc82fda486774 100644 --- a/Lib/importlib/_bootstrap_external.py +++ b/Lib/importlib/_bootstrap_external.py @@ -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 @@ -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__' diff --git a/Lib/opcode.py b/Lib/opcode.py index 7a52c13579af7c..2ddb4f0cd3ae99 100644 --- a/Lib/opcode.py +++ b/Lib/opcode.py @@ -128,7 +128,7 @@ 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) # "" @@ -166,6 +166,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 diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py index 16bfee188e0461..99db8ba0ac3b9a 100644 --- a/Lib/test/test_dis.py +++ b/Lib/test/test_dis.py @@ -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 @@ -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 = """\ @@ -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__, @@ -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), @@ -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), diff --git a/Lib/test/test_peepholer.py b/Lib/test/test_peepholer.py index 6f24b291b00b59..ab715e2e8f6cbd 100644 --- a/Lib/test/test_peepholer.py +++ b/Lib/test/test_peepholer.py @@ -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) diff --git a/Objects/frameobject.c b/Objects/frameobject.c index 5c6a8bcb9008da..594a3466225e94 100644 --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -264,6 +264,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); diff --git a/Programs/test_frozenmain.h b/Programs/test_frozenmain.h index 8cae77a4899f12..a3c09529116cc1 100644 --- a/Programs/test_frozenmain.h +++ b/Programs/test_frozenmain.h @@ -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, 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, - 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, 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, diff --git a/Python/ceval.c b/Python/ceval.c index e1d961fee6a832..7b0e0f4fd30ce1 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -3921,6 +3921,11 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int DISPATCH(); } + TARGET(JUMP_BACKWARD) { + JUMPBY(-oparg); + DISPATCH(); + } + TARGET(POP_JUMP_IF_FALSE) { PREDICTED(POP_JUMP_IF_FALSE); PyObject *cond = POP(); diff --git a/Python/compile.c b/Python/compile.c index e24f425229b6af..d9e50240250c8a 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -985,6 +985,7 @@ stack_effect(int opcode, int oparg, int jump) /* Jumps */ case JUMP_FORWARD: + case JUMP_BACKWARD: case JUMP_ABSOLUTE: case JUMP_NO_INTERRUPT: return 0; @@ -7038,6 +7039,7 @@ stackdepth(struct compiler *c) if (instr->i_opcode == JUMP_ABSOLUTE || instr->i_opcode == JUMP_NO_INTERRUPT || instr->i_opcode == JUMP_FORWARD || + instr->i_opcode == JUMP_BACKWARD || instr->i_opcode == RETURN_VALUE || instr->i_opcode == RAISE_VARARGS || instr->i_opcode == RERAISE) @@ -7553,12 +7555,18 @@ normalize_jumps(struct assembler *a) if (last->i_target->b_visited == 0) { last->i_opcode = JUMP_FORWARD; } + else { + last->i_opcode = JUMP_BACKWARD; + } } if (last->i_opcode == JUMP_FORWARD) { if (last->i_target->b_visited == 1) { - last->i_opcode = JUMP_ABSOLUTE; + last->i_opcode = JUMP_BACKWARD; } } + if (last->i_opcode == JUMP_BACKWARD) { + assert(last->i_target->b_visited == 1); + } } } @@ -7592,7 +7600,14 @@ assemble_jump_offsets(struct assembler *a, struct compiler *c) if (is_jump(instr)) { instr->i_oparg = instr->i_target->b_offset; 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) { extended_arg_recompile = 1; @@ -8730,6 +8745,7 @@ optimize_basic_block(struct compiler *c, basicblock *bb, PyObject *consts) break; case JUMP_ABSOLUTE: case JUMP_FORWARD: + case JUMP_BACKWARD: case JUMP_IF_FALSE_OR_POP: i -= jump_thread(inst, target, JUMP_IF_FALSE_OR_POP); break; @@ -8753,6 +8769,7 @@ optimize_basic_block(struct compiler *c, basicblock *bb, PyObject *consts) break; case JUMP_ABSOLUTE: case JUMP_FORWARD: + case JUMP_BACKWARD: case JUMP_IF_TRUE_OR_POP: i -= jump_thread(inst, target, JUMP_IF_TRUE_OR_POP); break; @@ -8774,6 +8791,7 @@ optimize_basic_block(struct compiler *c, basicblock *bb, PyObject *consts) switch (target->i_opcode) { case JUMP_ABSOLUTE: case JUMP_FORWARD: + case JUMP_BACKWARD: i -= jump_thread(inst, target, inst->i_opcode); } break; @@ -8781,6 +8799,7 @@ optimize_basic_block(struct compiler *c, basicblock *bb, PyObject *consts) switch (target->i_opcode) { case JUMP_ABSOLUTE: case JUMP_FORWARD: + case JUMP_BACKWARD: i -= jump_thread(inst, target, POP_JUMP_IF_FALSE); } break; @@ -8788,19 +8807,22 @@ optimize_basic_block(struct compiler *c, basicblock *bb, PyObject *consts) switch (target->i_opcode) { case JUMP_ABSOLUTE: case JUMP_FORWARD: + case JUMP_BACKWARD: i -= jump_thread(inst, target, POP_JUMP_IF_TRUE); } break; case JUMP_ABSOLUTE: case JUMP_FORWARD: + case JUMP_BACKWARD: switch (target->i_opcode) { case JUMP_ABSOLUTE: case JUMP_FORWARD: + case JUMP_BACKWARD: i -= jump_thread(inst, target, JUMP_ABSOLUTE); } break; case FOR_ITER: - if (target->i_opcode == JUMP_FORWARD) { + if (target->i_opcode == JUMP_FORWARD || target->i_opcode == JUMP_BACKWARD) { i -= jump_thread(inst, target, FOR_ITER); } break; @@ -8842,7 +8864,9 @@ extend_block(basicblock *bb) { return 0; } 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_ABSOLUTE && + last->i_opcode != JUMP_FORWARD && + last->i_opcode != JUMP_BACKWARD) { return 0; } if (last->i_target->b_exit && last->i_target->b_iused <= MAX_COPY_SIZE) { @@ -8922,6 +8946,7 @@ normalize_basic_block(basicblock *bb) { break; case JUMP_ABSOLUTE: case JUMP_FORWARD: + case JUMP_BACKWARD: case JUMP_NO_INTERRUPT: bb->b_nofallthrough = 1; /* fall through */ @@ -9108,7 +9133,8 @@ optimize_cfg(struct compiler *c, struct assembler *a, PyObject *consts) struct instr *b_last_instr = &b->b_instr[b->b_iused - 1]; if (b_last_instr->i_opcode == JUMP_ABSOLUTE || b_last_instr->i_opcode == JUMP_NO_INTERRUPT || - b_last_instr->i_opcode == JUMP_FORWARD) { + b_last_instr->i_opcode == JUMP_FORWARD || + b_last_instr->i_opcode == JUMP_BACKWARD) { if (b_last_instr->i_target == b->b_next) { assert(b->b_next->b_iused); b->b_nofallthrough = 0; diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h index 2aa6471abf99a1..ad19be99d204d7 100644 --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -139,39 +139,40 @@ static void *opcode_targets[256] = { &&TARGET_LOAD_DEREF, &&TARGET_STORE_DEREF, &&TARGET_DELETE_DEREF, + &&TARGET_JUMP_BACKWARD, &&TARGET_PRECALL_PYFUNC, - &&TARGET_RESUME_QUICK, &&TARGET_CALL_FUNCTION_EX, - &&TARGET_STORE_ATTR_ADAPTIVE, + &&TARGET_RESUME_QUICK, &&TARGET_EXTENDED_ARG, &&TARGET_LIST_APPEND, &&TARGET_SET_ADD, &&TARGET_MAP_ADD, &&TARGET_LOAD_CLASSDEREF, &&TARGET_COPY_FREE_VARS, - &&TARGET_STORE_ATTR_INSTANCE_VALUE, + &&TARGET_STORE_ATTR_ADAPTIVE, &&TARGET_RESUME, &&TARGET_MATCH_CLASS, + &&TARGET_STORE_ATTR_INSTANCE_VALUE, &&TARGET_STORE_ATTR_SLOT, - &&TARGET_STORE_ATTR_WITH_HINT, &&TARGET_FORMAT_VALUE, &&TARGET_BUILD_CONST_KEY_MAP, &&TARGET_BUILD_STRING, + &&TARGET_STORE_ATTR_WITH_HINT, &&TARGET_STORE_FAST__LOAD_FAST, - &&TARGET_STORE_FAST__STORE_FAST, &&TARGET_LOAD_METHOD, - &&TARGET_STORE_SUBSCR_ADAPTIVE, + &&TARGET_STORE_FAST__STORE_FAST, &&TARGET_LIST_EXTEND, &&TARGET_SET_UPDATE, &&TARGET_DICT_MERGE, &&TARGET_DICT_UPDATE, &&TARGET_PRECALL, + &&TARGET_STORE_SUBSCR_ADAPTIVE, &&TARGET_STORE_SUBSCR_DICT, &&TARGET_STORE_SUBSCR_LIST_INT, &&TARGET_UNPACK_SEQUENCE_ADAPTIVE, - &&TARGET_UNPACK_SEQUENCE_LIST, &&TARGET_CALL, &&TARGET_KW_NAMES, + &&TARGET_UNPACK_SEQUENCE_LIST, &&TARGET_UNPACK_SEQUENCE_TUPLE, &&TARGET_UNPACK_SEQUENCE_TWO_TUPLE, &&_unknown_opcode, @@ -253,6 +254,5 @@ static void *opcode_targets[256] = { &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, - &&_unknown_opcode, &&TARGET_DO_TRACING }; From 61b8c3f2e3d198214999cd6b68abc0ea84d29fbc Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Fri, 25 Mar 2022 15:12:50 +0000 Subject: [PATCH 02/10] need eval breaker for JUMP_BACKWARD --- Python/ceval.c | 1 + 1 file changed, 1 insertion(+) diff --git a/Python/ceval.c b/Python/ceval.c index 7b0e0f4fd30ce1..9e75a6ba7fe06d 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -3923,6 +3923,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int TARGET(JUMP_BACKWARD) { JUMPBY(-oparg); + CHECK_EVAL_BREAKER(); DISPATCH(); } From dfe2476a39f2e30398aefe6a01fa1e6b59805448 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Fri, 25 Mar 2022 16:04:59 +0000 Subject: [PATCH 03/10] remove JUMP_ABSOLUTE* opcodes and add virtual opcode JUMP --- Doc/library/dis.rst | 5 -- Include/opcode.h | 100 +++++++++++++++++++--------------------- Lib/opcode.py | 4 -- Objects/frameobject.c | 1 - Python/ceval.c | 21 ++------- Python/compile.c | 53 +++++++++++---------- Python/opcode_targets.h | 38 +++++++-------- Python/specialize.c | 3 -- 8 files changed, 99 insertions(+), 126 deletions(-) diff --git a/Doc/library/dis.rst b/Doc/library/dis.rst index a889f43a5b4f17..d1a0cecd82841f 100644 --- a/Doc/library/dis.rst +++ b/Doc/library/dis.rst @@ -981,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. diff --git a/Include/opcode.h b/Include/opcode.h index 4ab2591875b2d1..a83f1dc65c9702 100644 --- a/Include/opcode.h +++ b/Include/opcode.h @@ -67,7 +67,6 @@ extern "C" { #define JUMP_FORWARD 110 #define JUMP_IF_FALSE_OR_POP 111 #define JUMP_IF_TRUE_OR_POP 112 -#define JUMP_ABSOLUTE 113 #define POP_JUMP_IF_FALSE 114 #define POP_JUMP_IF_TRUE 115 #define LOAD_GLOBAL 116 @@ -136,54 +135,53 @@ extern "C" { #define COMPARE_OP_FLOAT_JUMP 27 #define COMPARE_OP_INT_JUMP 28 #define COMPARE_OP_STR_JUMP 29 -#define JUMP_ABSOLUTE_QUICK 34 -#define LOAD_ATTR_ADAPTIVE 36 -#define LOAD_ATTR_INSTANCE_VALUE 37 -#define LOAD_ATTR_MODULE 38 -#define LOAD_ATTR_SLOT 39 -#define LOAD_ATTR_WITH_HINT 40 -#define LOAD_CONST__LOAD_FAST 41 -#define LOAD_FAST__LOAD_CONST 42 -#define LOAD_FAST__LOAD_FAST 43 -#define LOAD_GLOBAL_ADAPTIVE 44 -#define LOAD_GLOBAL_BUILTIN 45 -#define LOAD_GLOBAL_MODULE 46 -#define LOAD_METHOD_ADAPTIVE 47 -#define LOAD_METHOD_CLASS 48 -#define LOAD_METHOD_MODULE 55 -#define LOAD_METHOD_NO_DICT 56 -#define LOAD_METHOD_WITH_DICT 57 -#define LOAD_METHOD_WITH_VALUES 58 -#define PRECALL_ADAPTIVE 59 -#define PRECALL_BOUND_METHOD 62 -#define PRECALL_BUILTIN_CLASS 63 -#define PRECALL_BUILTIN_FAST_WITH_KEYWORDS 64 -#define PRECALL_NO_KW_BUILTIN_FAST 65 -#define PRECALL_NO_KW_BUILTIN_O 66 -#define PRECALL_NO_KW_ISINSTANCE 67 -#define PRECALL_NO_KW_LEN 72 -#define PRECALL_NO_KW_LIST_APPEND 73 -#define PRECALL_NO_KW_METHOD_DESCRIPTOR_FAST 76 -#define PRECALL_NO_KW_METHOD_DESCRIPTOR_NOARGS 77 -#define PRECALL_NO_KW_METHOD_DESCRIPTOR_O 78 -#define PRECALL_NO_KW_STR_1 79 -#define PRECALL_NO_KW_TUPLE_1 80 -#define PRECALL_NO_KW_TYPE_1 81 -#define PRECALL_PYFUNC 141 -#define RESUME_QUICK 143 -#define STORE_ATTR_ADAPTIVE 150 -#define STORE_ATTR_INSTANCE_VALUE 153 -#define STORE_ATTR_SLOT 154 -#define STORE_ATTR_WITH_HINT 158 -#define STORE_FAST__LOAD_FAST 159 -#define STORE_FAST__STORE_FAST 161 -#define STORE_SUBSCR_ADAPTIVE 167 -#define STORE_SUBSCR_DICT 168 -#define STORE_SUBSCR_LIST_INT 169 -#define UNPACK_SEQUENCE_ADAPTIVE 170 -#define UNPACK_SEQUENCE_LIST 173 -#define UNPACK_SEQUENCE_TUPLE 174 -#define UNPACK_SEQUENCE_TWO_TUPLE 175 +#define LOAD_ATTR_ADAPTIVE 34 +#define LOAD_ATTR_INSTANCE_VALUE 36 +#define LOAD_ATTR_MODULE 37 +#define LOAD_ATTR_SLOT 38 +#define LOAD_ATTR_WITH_HINT 39 +#define LOAD_CONST__LOAD_FAST 40 +#define LOAD_FAST__LOAD_CONST 41 +#define LOAD_FAST__LOAD_FAST 42 +#define LOAD_GLOBAL_ADAPTIVE 43 +#define LOAD_GLOBAL_BUILTIN 44 +#define LOAD_GLOBAL_MODULE 45 +#define LOAD_METHOD_ADAPTIVE 46 +#define LOAD_METHOD_CLASS 47 +#define LOAD_METHOD_MODULE 48 +#define LOAD_METHOD_NO_DICT 55 +#define LOAD_METHOD_WITH_DICT 56 +#define LOAD_METHOD_WITH_VALUES 57 +#define PRECALL_ADAPTIVE 58 +#define PRECALL_BOUND_METHOD 59 +#define PRECALL_BUILTIN_CLASS 62 +#define PRECALL_BUILTIN_FAST_WITH_KEYWORDS 63 +#define PRECALL_NO_KW_BUILTIN_FAST 64 +#define PRECALL_NO_KW_BUILTIN_O 65 +#define PRECALL_NO_KW_ISINSTANCE 66 +#define PRECALL_NO_KW_LEN 67 +#define PRECALL_NO_KW_LIST_APPEND 72 +#define PRECALL_NO_KW_METHOD_DESCRIPTOR_FAST 73 +#define PRECALL_NO_KW_METHOD_DESCRIPTOR_NOARGS 76 +#define PRECALL_NO_KW_METHOD_DESCRIPTOR_O 77 +#define PRECALL_NO_KW_STR_1 78 +#define PRECALL_NO_KW_TUPLE_1 79 +#define PRECALL_NO_KW_TYPE_1 80 +#define PRECALL_PYFUNC 81 +#define RESUME_QUICK 113 +#define STORE_ATTR_ADAPTIVE 141 +#define STORE_ATTR_INSTANCE_VALUE 143 +#define STORE_ATTR_SLOT 150 +#define STORE_ATTR_WITH_HINT 153 +#define STORE_FAST__LOAD_FAST 154 +#define STORE_FAST__STORE_FAST 158 +#define STORE_SUBSCR_ADAPTIVE 159 +#define STORE_SUBSCR_DICT 161 +#define STORE_SUBSCR_LIST_INT 167 +#define UNPACK_SEQUENCE_ADAPTIVE 168 +#define UNPACK_SEQUENCE_LIST 169 +#define UNPACK_SEQUENCE_TUPLE 170 +#define UNPACK_SEQUENCE_TWO_TUPLE 173 #define DO_TRACING 255 extern const uint8_t _PyOpcode_Caches[256]; @@ -205,7 +203,7 @@ static const uint32_t _PyOpcode_Jump[8] = { 0U, 0U, 536870912U, - 2316288000U, + 2316156928U, 4163U, 0U, 0U, @@ -289,8 +287,6 @@ const uint8_t _PyOpcode_Deopt[256] = { [IMPORT_NAME] = IMPORT_NAME, [IMPORT_STAR] = IMPORT_STAR, [IS_OP] = IS_OP, - [JUMP_ABSOLUTE] = JUMP_ABSOLUTE, - [JUMP_ABSOLUTE_QUICK] = JUMP_ABSOLUTE, [JUMP_BACKWARD] = JUMP_BACKWARD, [JUMP_FORWARD] = JUMP_FORWARD, [JUMP_IF_FALSE_OR_POP] = JUMP_IF_FALSE_OR_POP, diff --git a/Lib/opcode.py b/Lib/opcode.py index 2ddb4f0cd3ae99..4d5b231665ef6f 100644 --- a/Lib/opcode.py +++ b/Lib/opcode.py @@ -131,7 +131,6 @@ 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('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 @@ -260,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", diff --git a/Objects/frameobject.c b/Objects/frameobject.c index 594a3466225e94..45180da3b788d1 100644 --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -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); diff --git a/Python/ceval.c b/Python/ceval.c index 9e75a6ba7fe06d..18f9550101aa8d 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2213,7 +2213,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int Py_DECREF(v); if (err != 0) goto error; - PREDICT(JUMP_ABSOLUTE); + PREDICT(JUMP_BACKWARD); DISPATCH(); } @@ -2225,7 +2225,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int Py_DECREF(v); if (err != 0) goto error; - PREDICT(JUMP_ABSOLUTE); + PREDICT(JUMP_BACKWARD); DISPATCH(); } @@ -3391,7 +3391,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int if (_PyDict_SetItem_Take2((PyDictObject *)map, key, value) != 0) { goto error; } - PREDICT(JUMP_ABSOLUTE); + PREDICT(JUMP_BACKWARD); DISPATCH(); } @@ -3922,6 +3922,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int } TARGET(JUMP_BACKWARD) { + PREDICTED(JUMP_BACKWARD); JUMPBY(-oparg); CHECK_EVAL_BREAKER(); DISPATCH(); @@ -4054,12 +4055,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int DISPATCH(); } - TARGET(JUMP_ABSOLUTE) { - PREDICTED(JUMP_ABSOLUTE); - _PyCode_Warmup(frame->f_code); - JUMP_TO_INSTRUCTION(JUMP_ABSOLUTE_QUICK); - } - TARGET(JUMP_NO_INTERRUPT) { /* This bytecode is used in the `yield from` or `await` loop. * If there is an interrupt, we want it handled in the innermost @@ -4070,14 +4065,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int DISPATCH(); } - TARGET(JUMP_ABSOLUTE_QUICK) { - PREDICTED(JUMP_ABSOLUTE_QUICK); - assert(oparg < INSTR_OFFSET()); - JUMPTO(oparg); - CHECK_EVAL_BREAKER(); - DISPATCH(); - } - TARGET(GET_LEN) { // PUSH(len(TOS)) Py_ssize_t len_i = PyObject_Length(TOP()); diff --git a/Python/compile.c b/Python/compile.c index d9e50240250c8a..dd5503baa218cc 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -76,6 +76,7 @@ #define SETUP_CLEANUP 254 #define SETUP_WITH 253 #define POP_BLOCK 252 +#define JUMP 251 #define IS_TOP_LEVEL_AWAIT(c) ( \ (c->c_flags->cf_flags & PyCF_ALLOW_TOP_LEVEL_AWAIT) \ @@ -127,7 +128,9 @@ is_relative_jump(struct instr *i) static inline int 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 @@ -986,7 +989,7 @@ stack_effect(int opcode, int oparg, int jump) /* Jumps */ case JUMP_FORWARD: case JUMP_BACKWARD: - case JUMP_ABSOLUTE: + case JUMP: case JUMP_NO_INTERRUPT: return 0; @@ -3018,7 +3021,7 @@ compiler_for(struct compiler *c, stmt_ty s) VISIT_SEQ(c, stmt, s->v.For.body); /* Mark jump as artificial */ UNSET_LOC(c); - ADDOP_JUMP(c, JUMP_ABSOLUTE, start); + ADDOP_JUMP(c, JUMP, start); compiler_use_next_block(c, cleanup); compiler_pop_fblock(c, FOR_LOOP, start); @@ -3063,7 +3066,7 @@ compiler_async_for(struct compiler *c, stmt_ty s) /* Success block for __anext__ */ VISIT(c, expr, s->v.AsyncFor.target); 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); @@ -3175,7 +3178,7 @@ compiler_break(struct compiler *c) if (!compiler_unwind_fblock(c, loop, 0)) { return 0; } - ADDOP_JUMP(c, JUMP_ABSOLUTE, loop->fb_exit); + ADDOP_JUMP(c, JUMP, loop->fb_exit); return 1; } @@ -3191,7 +3194,7 @@ compiler_continue(struct compiler *c) if (loop == NULL) { 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; } @@ -3666,7 +3669,7 @@ compiler_try_star_except(struct compiler *c, stmt_ty s) ADDOP_I(c, LIST_APPEND, 3); // exc ADDOP(c, POP_TOP); // lasti - ADDOP_JUMP(c, JUMP_ABSOLUTE, except); + ADDOP_JUMP(c, JUMP, except); compiler_use_next_block(c, except); if (i == n - 1) { @@ -5163,7 +5166,7 @@ compiler_sync_comprehension_generator(struct compiler *c, } compiler_use_next_block(c, if_cleanup); if (start) { - ADDOP_JUMP(c, JUMP_ABSOLUTE, start); + ADDOP_JUMP(c, JUMP, start); compiler_use_next_block(c, anchor); } @@ -5257,7 +5260,7 @@ compiler_async_comprehension_generator(struct compiler *c, } } 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); @@ -5533,7 +5536,7 @@ compiler_async_with(struct compiler *c, stmt_ty s, int pos) ADDOP(c, POP_TOP); - ADDOP_JUMP(c, JUMP_ABSOLUTE, exit); + ADDOP_JUMP(c, JUMP, exit); /* For exceptional outcome: */ compiler_use_next_block(c, final); @@ -7036,7 +7039,7 @@ stackdepth(struct compiler *c) stackdepth_push(&sp, instr->i_target, target_depth); } depth = new_depth; - if (instr->i_opcode == JUMP_ABSOLUTE || + if (instr->i_opcode == JUMP || instr->i_opcode == JUMP_NO_INTERRUPT || instr->i_opcode == JUMP_FORWARD || instr->i_opcode == JUMP_BACKWARD || @@ -7551,7 +7554,7 @@ normalize_jumps(struct assembler *a) continue; } struct instr *last = &b->b_instr[b->b_iused-1]; - if (last->i_opcode == JUMP_ABSOLUTE) { + if (last->i_opcode == JUMP) { if (last->i_target->b_visited == 0) { last->i_opcode = JUMP_FORWARD; } @@ -8652,7 +8655,7 @@ optimize_basic_block(struct compiler *c, basicblock *bb, PyObject *consts) inst->i_opcode = NOP; jump_if_true = nextop == POP_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; } else { @@ -8672,7 +8675,7 @@ optimize_basic_block(struct compiler *c, basicblock *bb, PyObject *consts) } jump_if_true = nextop == JUMP_IF_TRUE_OR_POP; 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; } else { @@ -8743,7 +8746,7 @@ optimize_basic_block(struct compiler *c, basicblock *bb, PyObject *consts) case POP_JUMP_IF_FALSE: i -= jump_thread(inst, target, POP_JUMP_IF_FALSE); break; - case JUMP_ABSOLUTE: + case JUMP: case JUMP_FORWARD: case JUMP_BACKWARD: case JUMP_IF_FALSE_OR_POP: @@ -8767,7 +8770,7 @@ optimize_basic_block(struct compiler *c, basicblock *bb, PyObject *consts) case POP_JUMP_IF_TRUE: i -= jump_thread(inst, target, POP_JUMP_IF_TRUE); break; - case JUMP_ABSOLUTE: + case JUMP: case JUMP_FORWARD: case JUMP_BACKWARD: case JUMP_IF_TRUE_OR_POP: @@ -8789,7 +8792,7 @@ optimize_basic_block(struct compiler *c, basicblock *bb, PyObject *consts) case POP_JUMP_IF_NOT_NONE: case POP_JUMP_IF_NONE: switch (target->i_opcode) { - case JUMP_ABSOLUTE: + case JUMP: case JUMP_FORWARD: case JUMP_BACKWARD: i -= jump_thread(inst, target, inst->i_opcode); @@ -8797,7 +8800,7 @@ optimize_basic_block(struct compiler *c, basicblock *bb, PyObject *consts) break; case POP_JUMP_IF_FALSE: switch (target->i_opcode) { - case JUMP_ABSOLUTE: + case JUMP: case JUMP_FORWARD: case JUMP_BACKWARD: i -= jump_thread(inst, target, POP_JUMP_IF_FALSE); @@ -8805,20 +8808,20 @@ optimize_basic_block(struct compiler *c, basicblock *bb, PyObject *consts) break; case POP_JUMP_IF_TRUE: switch (target->i_opcode) { - case JUMP_ABSOLUTE: + case JUMP: case JUMP_FORWARD: case JUMP_BACKWARD: i -= jump_thread(inst, target, POP_JUMP_IF_TRUE); } break; - case JUMP_ABSOLUTE: + case JUMP: case JUMP_FORWARD: case JUMP_BACKWARD: switch (target->i_opcode) { - case JUMP_ABSOLUTE: + case JUMP: case JUMP_FORWARD: case JUMP_BACKWARD: - i -= jump_thread(inst, target, JUMP_ABSOLUTE); + i -= jump_thread(inst, target, JUMP); } break; case FOR_ITER: @@ -8864,7 +8867,7 @@ extend_block(basicblock *bb) { return 0; } struct instr *last = &bb->b_instr[bb->b_iused-1]; - if (last->i_opcode != JUMP_ABSOLUTE && + if (last->i_opcode != JUMP && last->i_opcode != JUMP_FORWARD && last->i_opcode != JUMP_BACKWARD) { return 0; @@ -8944,7 +8947,7 @@ normalize_basic_block(basicblock *bb) { bb->b_exit = 1; bb->b_nofallthrough = 1; break; - case JUMP_ABSOLUTE: + case JUMP: case JUMP_FORWARD: case JUMP_BACKWARD: case JUMP_NO_INTERRUPT: @@ -9131,7 +9134,7 @@ optimize_cfg(struct compiler *c, struct assembler *a, PyObject *consts) for (basicblock *b = a->a_entry; b != NULL; b = b->b_next) { if (b->b_iused > 0) { struct instr *b_last_instr = &b->b_instr[b->b_iused - 1]; - if (b_last_instr->i_opcode == JUMP_ABSOLUTE || + if (b_last_instr->i_opcode == JUMP || b_last_instr->i_opcode == JUMP_NO_INTERRUPT || b_last_instr->i_opcode == JUMP_FORWARD || b_last_instr->i_opcode == JUMP_BACKWARD) { diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h index ad19be99d204d7..49fda697ad8a46 100644 --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -33,9 +33,8 @@ static void *opcode_targets[256] = { &&TARGET_MATCH_MAPPING, &&TARGET_MATCH_SEQUENCE, &&TARGET_MATCH_KEYS, - &&TARGET_JUMP_ABSOLUTE_QUICK, - &&TARGET_PUSH_EXC_INFO, &&TARGET_LOAD_ATTR_ADAPTIVE, + &&TARGET_PUSH_EXC_INFO, &&TARGET_LOAD_ATTR_INSTANCE_VALUE, &&TARGET_LOAD_ATTR_MODULE, &&TARGET_LOAD_ATTR_SLOT, @@ -48,39 +47,40 @@ static void *opcode_targets[256] = { &&TARGET_LOAD_GLOBAL_MODULE, &&TARGET_LOAD_METHOD_ADAPTIVE, &&TARGET_LOAD_METHOD_CLASS, + &&TARGET_LOAD_METHOD_MODULE, &&TARGET_WITH_EXCEPT_START, &&TARGET_GET_AITER, &&TARGET_GET_ANEXT, &&TARGET_BEFORE_ASYNC_WITH, &&TARGET_BEFORE_WITH, &&TARGET_END_ASYNC_FOR, - &&TARGET_LOAD_METHOD_MODULE, &&TARGET_LOAD_METHOD_NO_DICT, &&TARGET_LOAD_METHOD_WITH_DICT, &&TARGET_LOAD_METHOD_WITH_VALUES, &&TARGET_PRECALL_ADAPTIVE, + &&TARGET_PRECALL_BOUND_METHOD, &&TARGET_STORE_SUBSCR, &&TARGET_DELETE_SUBSCR, - &&TARGET_PRECALL_BOUND_METHOD, &&TARGET_PRECALL_BUILTIN_CLASS, &&TARGET_PRECALL_BUILTIN_FAST_WITH_KEYWORDS, &&TARGET_PRECALL_NO_KW_BUILTIN_FAST, &&TARGET_PRECALL_NO_KW_BUILTIN_O, &&TARGET_PRECALL_NO_KW_ISINSTANCE, + &&TARGET_PRECALL_NO_KW_LEN, &&TARGET_GET_ITER, &&TARGET_GET_YIELD_FROM_ITER, &&TARGET_PRINT_EXPR, &&TARGET_LOAD_BUILD_CLASS, - &&TARGET_PRECALL_NO_KW_LEN, &&TARGET_PRECALL_NO_KW_LIST_APPEND, + &&TARGET_PRECALL_NO_KW_METHOD_DESCRIPTOR_FAST, &&TARGET_LOAD_ASSERTION_ERROR, &&TARGET_RETURN_GENERATOR, - &&TARGET_PRECALL_NO_KW_METHOD_DESCRIPTOR_FAST, &&TARGET_PRECALL_NO_KW_METHOD_DESCRIPTOR_NOARGS, &&TARGET_PRECALL_NO_KW_METHOD_DESCRIPTOR_O, &&TARGET_PRECALL_NO_KW_STR_1, &&TARGET_PRECALL_NO_KW_TUPLE_1, &&TARGET_PRECALL_NO_KW_TYPE_1, + &&TARGET_PRECALL_PYFUNC, &&TARGET_LIST_TO_TUPLE, &&TARGET_RETURN_VALUE, &&TARGET_IMPORT_STAR, @@ -112,7 +112,7 @@ static void *opcode_targets[256] = { &&TARGET_JUMP_FORWARD, &&TARGET_JUMP_IF_FALSE_OR_POP, &&TARGET_JUMP_IF_TRUE_OR_POP, - &&TARGET_JUMP_ABSOLUTE, + &&TARGET_RESUME_QUICK, &&TARGET_POP_JUMP_IF_FALSE, &&TARGET_POP_JUMP_IF_TRUE, &&TARGET_LOAD_GLOBAL, @@ -140,40 +140,38 @@ static void *opcode_targets[256] = { &&TARGET_STORE_DEREF, &&TARGET_DELETE_DEREF, &&TARGET_JUMP_BACKWARD, - &&TARGET_PRECALL_PYFUNC, + &&TARGET_STORE_ATTR_ADAPTIVE, &&TARGET_CALL_FUNCTION_EX, - &&TARGET_RESUME_QUICK, + &&TARGET_STORE_ATTR_INSTANCE_VALUE, &&TARGET_EXTENDED_ARG, &&TARGET_LIST_APPEND, &&TARGET_SET_ADD, &&TARGET_MAP_ADD, &&TARGET_LOAD_CLASSDEREF, &&TARGET_COPY_FREE_VARS, - &&TARGET_STORE_ATTR_ADAPTIVE, + &&TARGET_STORE_ATTR_SLOT, &&TARGET_RESUME, &&TARGET_MATCH_CLASS, - &&TARGET_STORE_ATTR_INSTANCE_VALUE, - &&TARGET_STORE_ATTR_SLOT, + &&TARGET_STORE_ATTR_WITH_HINT, + &&TARGET_STORE_FAST__LOAD_FAST, &&TARGET_FORMAT_VALUE, &&TARGET_BUILD_CONST_KEY_MAP, &&TARGET_BUILD_STRING, - &&TARGET_STORE_ATTR_WITH_HINT, - &&TARGET_STORE_FAST__LOAD_FAST, - &&TARGET_LOAD_METHOD, &&TARGET_STORE_FAST__STORE_FAST, + &&TARGET_STORE_SUBSCR_ADAPTIVE, + &&TARGET_LOAD_METHOD, + &&TARGET_STORE_SUBSCR_DICT, &&TARGET_LIST_EXTEND, &&TARGET_SET_UPDATE, &&TARGET_DICT_MERGE, &&TARGET_DICT_UPDATE, &&TARGET_PRECALL, - &&TARGET_STORE_SUBSCR_ADAPTIVE, - &&TARGET_STORE_SUBSCR_DICT, &&TARGET_STORE_SUBSCR_LIST_INT, &&TARGET_UNPACK_SEQUENCE_ADAPTIVE, - &&TARGET_CALL, - &&TARGET_KW_NAMES, &&TARGET_UNPACK_SEQUENCE_LIST, &&TARGET_UNPACK_SEQUENCE_TUPLE, + &&TARGET_CALL, + &&TARGET_KW_NAMES, &&TARGET_UNPACK_SEQUENCE_TWO_TUPLE, &&_unknown_opcode, &&_unknown_opcode, @@ -254,5 +252,7 @@ static void *opcode_targets[256] = { &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, &&TARGET_DO_TRACING }; diff --git a/Python/specialize.c b/Python/specialize.c index ce091a2c5f0784..f901c5bd9616d2 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -270,9 +270,6 @@ _PyCode_Quicken(PyCodeObject *code) else { assert(!_PyOpcode_Caches[opcode]); switch (opcode) { - case JUMP_ABSOLUTE: - _Py_SET_OPCODE(instructions[i], JUMP_ABSOLUTE_QUICK); - break; case RESUME: _Py_SET_OPCODE(instructions[i], RESUME_QUICK); break; From c75cbcbb3f9cdae70852f12fa308d6a83468c68f Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Fri, 25 Mar 2022 18:17:04 +0000 Subject: [PATCH 04/10] codegen emits JUMP instead of JUMP_FORWARD --- Python/compile.c | 105 ++++++++++++++++++++++------------------------- 1 file changed, 48 insertions(+), 57 deletions(-) diff --git a/Python/compile.c b/Python/compile.c index dd5503baa218cc..b917cd6dd53c3d 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -2833,7 +2833,7 @@ compiler_jump_if(struct compiler *c, expr_ty e, basicblock *next, int cond) return 0; if (!compiler_jump_if(c, e->v.IfExp.body, next, cond)) return 0; - ADDOP_JUMP_NOLINE(c, JUMP_FORWARD, end); + ADDOP_JUMP_NOLINE(c, JUMP, end); compiler_use_next_block(c, next2); if (!compiler_jump_if(c, e->v.IfExp.orelse, next, cond)) return 0; @@ -2864,11 +2864,11 @@ compiler_jump_if(struct compiler *c, expr_ty e, basicblock *next, int cond) basicblock *end = compiler_new_block(c); if (end == NULL) return 0; - ADDOP_JUMP_NOLINE(c, JUMP_FORWARD, end); + ADDOP_JUMP_NOLINE(c, JUMP, end); compiler_use_next_block(c, cleanup); ADDOP(c, POP_TOP); if (!cond) { - ADDOP_JUMP_NOLINE(c, JUMP_FORWARD, next); + ADDOP_JUMP_NOLINE(c, JUMP, next); } compiler_use_next_block(c, end); return 1; @@ -2902,7 +2902,7 @@ compiler_ifexp(struct compiler *c, expr_ty e) if (!compiler_jump_if(c, e->v.IfExp.test, next, 0)) return 0; 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); VISIT(c, expr, e->v.IfExp.orelse); compiler_use_next_block(c, end); @@ -2989,7 +2989,7 @@ compiler_if(struct compiler *c, stmt_ty s) } VISIT_SEQ(c, stmt, s->v.If.body); 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); VISIT_SEQ(c, stmt, s->v.If.orelse); } @@ -3255,7 +3255,7 @@ compiler_try_finally(struct compiler *c, stmt_ty s) ADDOP_NOLINE(c, POP_BLOCK); compiler_pop_fblock(c, FINALLY_TRY, body); VISIT_SEQ(c, stmt, s->v.Try.finalbody); - ADDOP_JUMP_NOLINE(c, JUMP_FORWARD, exit); + ADDOP_JUMP_NOLINE(c, JUMP, exit); /* `finally` block */ compiler_use_next_block(c, end); @@ -3309,7 +3309,7 @@ compiler_try_star_finally(struct compiler *c, stmt_ty s) ADDOP_NOLINE(c, POP_BLOCK); compiler_pop_fblock(c, FINALLY_TRY, body); VISIT_SEQ(c, stmt, s->v.TryStar.finalbody); - ADDOP_JUMP_NOLINE(c, JUMP_FORWARD, exit); + ADDOP_JUMP_NOLINE(c, JUMP, exit); /* `finally` block */ compiler_use_next_block(c, end); @@ -3339,13 +3339,13 @@ compiler_try_star_finally(struct compiler *c, stmt_ty s) [] SETUP_FINALLY L1 [] [] POP_BLOCK - [] JUMP_FORWARD L0 + [] JUMP L0 [exc] L1: ) [exc, E1] JUMP_IF_NOT_EXC_MATCH L2 ) only if E1 [exc] (or POP if no V1) [] - JUMP_FORWARD L0 + JUMP L0 [exc] L2: .............................etc....................... @@ -3378,7 +3378,7 @@ compiler_try_except(struct compiler *c, stmt_ty s) if (s->v.Try.orelse && asdl_seq_LEN(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); compiler_use_next_block(c, except); @@ -3441,7 +3441,7 @@ compiler_try_except(struct compiler *c, stmt_ty s) ADDOP_LOAD_CONST(c, Py_None); compiler_nameop(c, handler->v.ExceptHandler.name, Store); compiler_nameop(c, handler->v.ExceptHandler.name, Del); - ADDOP_JUMP(c, JUMP_FORWARD, end); + ADDOP_JUMP(c, JUMP, end); /* except: */ compiler_use_next_block(c, cleanup_end); @@ -3471,7 +3471,7 @@ compiler_try_except(struct compiler *c, stmt_ty s) UNSET_LOC(c); ADDOP(c, POP_BLOCK); ADDOP(c, POP_EXCEPT); - ADDOP_JUMP(c, JUMP_FORWARD, end); + ADDOP_JUMP(c, JUMP, end); } compiler_use_next_block(c, except); } @@ -3495,7 +3495,7 @@ compiler_try_except(struct compiler *c, stmt_ty s) [] SETUP_FINALLY L1 [] [] POP_BLOCK - [] JUMP_FORWARD L0 + [] JUMP L0 [exc] L1: COPY 1 ) save copy of the original exception [orig, exc] BUILD_LIST ) list for raised/reraised excs ("result") @@ -3508,7 +3508,7 @@ compiler_try_except(struct compiler *c, stmt_ty s) [orig, res, rest] SETUP_FINALLY R1 [orig, res, rest] - [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] POP @@ -3522,7 +3522,7 @@ compiler_try_except(struct compiler *c, stmt_ty s) [exc] COPY 1 [exc, exc] POP_JUMP_IF_NOT_NONE RER [exc] POP_TOP - [] JUMP_FORWARD L0 + [] JUMP L0 [exc] RER: SWAP 2 [exc, prev_exc_info] POP_EXCEPT @@ -3566,7 +3566,7 @@ compiler_try_star_except(struct compiler *c, stmt_ty s) VISIT_SEQ(c, stmt, s->v.TryStar.body); compiler_pop_fblock(c, TRY_EXCEPT, body); 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); compiler_use_next_block(c, except); @@ -3651,7 +3651,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, Del); } - ADDOP_JUMP(c, JUMP_FORWARD, except); + ADDOP_JUMP(c, JUMP, except); /* except: */ compiler_use_next_block(c, cleanup_end); @@ -3675,7 +3675,7 @@ compiler_try_star_except(struct compiler *c, stmt_ty s) if (i == n - 1) { /* Add exc to the list (if not None it's the unhandled part of the EG) */ ADDOP_I(c, LIST_APPEND, 1); - ADDOP_JUMP(c, JUMP_FORWARD, reraise_star); + ADDOP_JUMP(c, JUMP, reraise_star); } } /* Mark as artificial */ @@ -3695,7 +3695,7 @@ compiler_try_star_except(struct compiler *c, stmt_ty s) ADDOP(c, POP_TOP); ADDOP(c, POP_BLOCK); ADDOP(c, POP_EXCEPT); - ADDOP_JUMP(c, JUMP_FORWARD, end); + ADDOP_JUMP(c, JUMP, end); compiler_use_next_block(c, reraise); ADDOP(c, POP_BLOCK); ADDOP_I(c, SWAP, 2); @@ -4536,7 +4536,7 @@ compiler_compare(struct compiler *c, expr_ty e) basicblock *end = compiler_new_block(c); if (end == NULL) return 0; - ADDOP_JUMP_NOLINE(c, JUMP_FORWARD, end); + ADDOP_JUMP_NOLINE(c, JUMP, end); compiler_use_next_block(c, cleanup); ADDOP_I(c, SWAP, 2); ADDOP(c, POP_TOP); @@ -5565,7 +5565,7 @@ compiler_async_with(struct compiler *c, stmt_ty s, int pos) LOAD_CONST (None, None, None) CALL_FUNCTION_EX 0 - JUMP_FORWARD EXIT + JUMP EXIT E: WITH_EXCEPT_START (calls EXPR.__exit__) POP_JUMP_IF_TRUE T: RERAISE @@ -5632,7 +5632,7 @@ compiler_with(struct compiler *c, stmt_ty s, int pos) if (!compiler_call_exit_with_nones(c)) return 0; ADDOP(c, POP_TOP); - ADDOP_JUMP(c, JUMP_FORWARD, exit); + ADDOP_JUMP(c, JUMP, exit); /* For exceptional outcome: */ compiler_use_next_block(c, final); @@ -6681,7 +6681,7 @@ compiler_pattern_or(struct compiler *c, pattern_ty p, pattern_context *pc) } } assert(control); - if (!compiler_addop_j(c, JUMP_FORWARD, end) || + if (!compiler_addop_j(c, JUMP, end) || !emit_and_reset_fail_pop(c, pc)) { goto error; @@ -6693,7 +6693,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. old_pc.fail_pop = NULL; // 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; } compiler_use_next_block(c, end); @@ -6900,7 +6900,7 @@ compiler_match_inner(struct compiler *c, stmt_ty s, pattern_context *pc) ADDOP(c, POP_TOP); } 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 // cleanup to be associated with the failed pattern, not the last line // of the body @@ -7039,10 +7039,10 @@ stackdepth(struct compiler *c) stackdepth_push(&sp, instr->i_target, target_depth); } depth = new_depth; - if (instr->i_opcode == JUMP || - instr->i_opcode == JUMP_NO_INTERRUPT || - instr->i_opcode == JUMP_FORWARD || - instr->i_opcode == JUMP_BACKWARD || + assert(instr->i_opcode != JUMP_FORWARD); + assert(instr->i_opcode != JUMP_BACKWARD); + if (instr->i_opcode == JUMP_NO_INTERRUPT || + instr->i_opcode == JUMP || instr->i_opcode == RETURN_VALUE || instr->i_opcode == RAISE_VARARGS || instr->i_opcode == RERAISE) @@ -7554,6 +7554,8 @@ normalize_jumps(struct assembler *a) continue; } struct instr *last = &b->b_instr[b->b_iused-1]; + assert(last->i_opcode != JUMP_FORWARD); + assert(last->i_opcode != JUMP_BACKWARD); if (last->i_opcode == JUMP) { if (last->i_target->b_visited == 0) { last->i_opcode = JUMP_FORWARD; @@ -7562,14 +7564,6 @@ normalize_jumps(struct assembler *a) last->i_opcode = JUMP_BACKWARD; } } - if (last->i_opcode == JUMP_FORWARD) { - if (last->i_target->b_visited == 1) { - last->i_opcode = JUMP_BACKWARD; - } - } - if (last->i_opcode == JUMP_BACKWARD) { - assert(last->i_target->b_visited == 1); - } } } @@ -8629,10 +8623,14 @@ optimize_basic_block(struct compiler *c, basicblock *bb, PyObject *consts) inst->i_target = inst->i_target->b_next; } target = &inst->i_target->b_instr[0]; + assert(target->i_opcode != JUMP_FORWARD); + assert(target->i_opcode != JUMP_BACKWARD); } else { target = &nop; } + assert(inst->i_opcode != JUMP_FORWARD); + assert(inst->i_opcode != JUMP_BACKWARD); switch (inst->i_opcode) { /* Remove LOAD_CONST const; conditional jump */ case LOAD_CONST: @@ -8747,8 +8745,6 @@ optimize_basic_block(struct compiler *c, basicblock *bb, PyObject *consts) i -= jump_thread(inst, target, POP_JUMP_IF_FALSE); break; case JUMP: - case JUMP_FORWARD: - case JUMP_BACKWARD: case JUMP_IF_FALSE_OR_POP: i -= jump_thread(inst, target, JUMP_IF_FALSE_OR_POP); break; @@ -8771,8 +8767,6 @@ optimize_basic_block(struct compiler *c, basicblock *bb, PyObject *consts) i -= jump_thread(inst, target, POP_JUMP_IF_TRUE); break; case JUMP: - case JUMP_FORWARD: - case JUMP_BACKWARD: case JUMP_IF_TRUE_OR_POP: i -= jump_thread(inst, target, JUMP_IF_TRUE_OR_POP); break; @@ -8793,40 +8787,37 @@ optimize_basic_block(struct compiler *c, basicblock *bb, PyObject *consts) case POP_JUMP_IF_NONE: switch (target->i_opcode) { case JUMP: - case JUMP_FORWARD: - case JUMP_BACKWARD: i -= jump_thread(inst, target, inst->i_opcode); } break; case POP_JUMP_IF_FALSE: switch (target->i_opcode) { case JUMP: - case JUMP_FORWARD: - case JUMP_BACKWARD: i -= jump_thread(inst, target, POP_JUMP_IF_FALSE); } break; case POP_JUMP_IF_TRUE: switch (target->i_opcode) { case JUMP: - case JUMP_FORWARD: - case JUMP_BACKWARD: i -= jump_thread(inst, target, POP_JUMP_IF_TRUE); } break; case JUMP: - case JUMP_FORWARD: - case JUMP_BACKWARD: switch (target->i_opcode) { case JUMP: - case JUMP_FORWARD: - case JUMP_BACKWARD: i -= jump_thread(inst, target, JUMP); } break; case FOR_ITER: - if (target->i_opcode == JUMP_FORWARD || target->i_opcode == JUMP_BACKWARD) { + 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); + */ } break; case SWAP: @@ -8940,6 +8931,8 @@ normalize_basic_block(basicblock *bb) { /* Mark blocks as exit and/or nofallthrough. Raise SystemError if CFG is malformed. */ 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) { case RETURN_VALUE: case RAISE_VARARGS: @@ -8948,8 +8941,6 @@ normalize_basic_block(basicblock *bb) { bb->b_nofallthrough = 1; break; case JUMP: - case JUMP_FORWARD: - case JUMP_BACKWARD: case JUMP_NO_INTERRUPT: bb->b_nofallthrough = 1; /* fall through */ @@ -9134,10 +9125,10 @@ optimize_cfg(struct compiler *c, struct assembler *a, PyObject *consts) for (basicblock *b = a->a_entry; b != NULL; b = b->b_next) { if (b->b_iused > 0) { struct instr *b_last_instr = &b->b_instr[b->b_iused - 1]; + assert(b_last_instr->i_opcode != JUMP_FORWARD); + assert(b_last_instr->i_opcode != JUMP_BACKWARD); if (b_last_instr->i_opcode == JUMP || - b_last_instr->i_opcode == JUMP_NO_INTERRUPT || - b_last_instr->i_opcode == JUMP_FORWARD || - b_last_instr->i_opcode == JUMP_BACKWARD) { + b_last_instr->i_opcode == JUMP_NO_INTERRUPT) { if (b_last_instr->i_target == b->b_next) { assert(b->b_next->b_iused); b->b_nofallthrough = 0; From e28e93bf10458552e2210deae5db243121602c86 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Fri, 25 Mar 2022 21:49:25 +0000 Subject: [PATCH 05/10] update whatsnew --- Doc/whatsnew/3.11.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index b2fdb4852360d5..252fc044190628 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -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 ========== From f3c65cb0c8f8b70a28d7f5db410e4451175d2366 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Fri, 25 Mar 2022 21:52:24 +0000 Subject: [PATCH 06/10] add news --- .../Core and Builtins/2022-03-25-21-51-10.bpo-47120.9YJ-Xw.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2022-03-25-21-51-10.bpo-47120.9YJ-Xw.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-03-25-21-51-10.bpo-47120.9YJ-Xw.rst b/Misc/NEWS.d/next/Core and Builtins/2022-03-25-21-51-10.bpo-47120.9YJ-Xw.rst new file mode 100644 index 00000000000000..65208c73543d37 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-03-25-21-51-10.bpo-47120.9YJ-Xw.rst @@ -0,0 +1,2 @@ +Replaced :opcode:`JUMP_ABSOLUTE` by the relative jump :opcode:`JUMP_BACKWARD`. + From c75fde822775cfda5a356d9fecc322fae1e00b73 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Mon, 28 Mar 2022 20:06:04 +0100 Subject: [PATCH 07/10] update comment --- Lib/importlib/_bootstrap_external.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py index 0dc82fda486774..744fefd5e21e79 100644 --- a/Lib/importlib/_bootstrap_external.py +++ b/Lib/importlib/_bootstrap_external.py @@ -396,7 +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.11a6 3489 (Add JUMP_BACKWARD, remove JUMP_ABSOLUTE) # Python 3.12 will start with magic number 3500 From 5a36560540064486754c7c7cbe8d115a995d681f Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Mon, 28 Mar 2022 20:14:10 +0100 Subject: [PATCH 08/10] regen --- Include/opcode.h | 108 ++++++++++++++++++++-------------------- Python/opcode_targets.h | 32 ++++++------ 2 files changed, 69 insertions(+), 71 deletions(-) diff --git a/Include/opcode.h b/Include/opcode.h index 0ce7c158bbd588..648a8dd76ab33b 100644 --- a/Include/opcode.h +++ b/Include/opcode.h @@ -67,7 +67,6 @@ extern "C" { #define JUMP_FORWARD 110 #define JUMP_IF_FALSE_OR_POP 111 #define JUMP_IF_TRUE_OR_POP 112 -#define JUMP_ABSOLUTE 113 #define POP_JUMP_IF_FALSE 114 #define POP_JUMP_IF_TRUE 115 #define LOAD_GLOBAL 116 @@ -94,6 +93,7 @@ extern "C" { #define LOAD_DEREF 137 #define STORE_DEREF 138 #define DELETE_DEREF 139 +#define JUMP_BACKWARD 140 #define CALL_FUNCTION_EX 142 #define EXTENDED_ARG 144 #define LIST_APPEND 145 @@ -135,55 +135,54 @@ extern "C" { #define COMPARE_OP_FLOAT_JUMP 27 #define COMPARE_OP_INT_JUMP 28 #define COMPARE_OP_STR_JUMP 29 -#define JUMP_ABSOLUTE_QUICK 34 -#define LOAD_ATTR_ADAPTIVE 36 -#define LOAD_ATTR_INSTANCE_VALUE 37 -#define LOAD_ATTR_MODULE 38 -#define LOAD_ATTR_SLOT 39 -#define LOAD_ATTR_WITH_HINT 40 -#define LOAD_CONST__LOAD_FAST 41 -#define LOAD_FAST__LOAD_CONST 42 -#define LOAD_FAST__LOAD_FAST 43 -#define LOAD_GLOBAL_ADAPTIVE 44 -#define LOAD_GLOBAL_BUILTIN 45 -#define LOAD_GLOBAL_MODULE 46 -#define LOAD_METHOD_ADAPTIVE 47 -#define LOAD_METHOD_CLASS 48 -#define LOAD_METHOD_MODULE 55 -#define LOAD_METHOD_NO_DICT 56 -#define LOAD_METHOD_WITH_DICT 57 -#define LOAD_METHOD_WITH_VALUES 58 -#define PRECALL_ADAPTIVE 59 -#define PRECALL_BOUND_METHOD 62 -#define PRECALL_BUILTIN_CLASS 63 -#define PRECALL_BUILTIN_FAST_WITH_KEYWORDS 64 -#define PRECALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS 65 -#define PRECALL_NO_KW_BUILTIN_FAST 66 -#define PRECALL_NO_KW_BUILTIN_O 67 -#define PRECALL_NO_KW_ISINSTANCE 72 -#define PRECALL_NO_KW_LEN 73 -#define PRECALL_NO_KW_LIST_APPEND 76 -#define PRECALL_NO_KW_METHOD_DESCRIPTOR_FAST 77 -#define PRECALL_NO_KW_METHOD_DESCRIPTOR_NOARGS 78 -#define PRECALL_NO_KW_METHOD_DESCRIPTOR_O 79 -#define PRECALL_NO_KW_STR_1 80 -#define PRECALL_NO_KW_TUPLE_1 81 -#define PRECALL_NO_KW_TYPE_1 140 -#define PRECALL_PYFUNC 141 -#define RESUME_QUICK 143 -#define STORE_ATTR_ADAPTIVE 150 -#define STORE_ATTR_INSTANCE_VALUE 153 -#define STORE_ATTR_SLOT 154 -#define STORE_ATTR_WITH_HINT 158 -#define STORE_FAST__LOAD_FAST 159 -#define STORE_FAST__STORE_FAST 161 -#define STORE_SUBSCR_ADAPTIVE 167 -#define STORE_SUBSCR_DICT 168 -#define STORE_SUBSCR_LIST_INT 169 -#define UNPACK_SEQUENCE_ADAPTIVE 170 -#define UNPACK_SEQUENCE_LIST 173 -#define UNPACK_SEQUENCE_TUPLE 174 -#define UNPACK_SEQUENCE_TWO_TUPLE 175 +#define LOAD_ATTR_ADAPTIVE 34 +#define LOAD_ATTR_INSTANCE_VALUE 36 +#define LOAD_ATTR_MODULE 37 +#define LOAD_ATTR_SLOT 38 +#define LOAD_ATTR_WITH_HINT 39 +#define LOAD_CONST__LOAD_FAST 40 +#define LOAD_FAST__LOAD_CONST 41 +#define LOAD_FAST__LOAD_FAST 42 +#define LOAD_GLOBAL_ADAPTIVE 43 +#define LOAD_GLOBAL_BUILTIN 44 +#define LOAD_GLOBAL_MODULE 45 +#define LOAD_METHOD_ADAPTIVE 46 +#define LOAD_METHOD_CLASS 47 +#define LOAD_METHOD_MODULE 48 +#define LOAD_METHOD_NO_DICT 55 +#define LOAD_METHOD_WITH_DICT 56 +#define LOAD_METHOD_WITH_VALUES 57 +#define PRECALL_ADAPTIVE 58 +#define PRECALL_BOUND_METHOD 59 +#define PRECALL_BUILTIN_CLASS 62 +#define PRECALL_BUILTIN_FAST_WITH_KEYWORDS 63 +#define PRECALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS 64 +#define PRECALL_NO_KW_BUILTIN_FAST 65 +#define PRECALL_NO_KW_BUILTIN_O 66 +#define PRECALL_NO_KW_ISINSTANCE 67 +#define PRECALL_NO_KW_LEN 72 +#define PRECALL_NO_KW_LIST_APPEND 73 +#define PRECALL_NO_KW_METHOD_DESCRIPTOR_FAST 76 +#define PRECALL_NO_KW_METHOD_DESCRIPTOR_NOARGS 77 +#define PRECALL_NO_KW_METHOD_DESCRIPTOR_O 78 +#define PRECALL_NO_KW_STR_1 79 +#define PRECALL_NO_KW_TUPLE_1 80 +#define PRECALL_NO_KW_TYPE_1 81 +#define PRECALL_PYFUNC 113 +#define RESUME_QUICK 141 +#define STORE_ATTR_ADAPTIVE 143 +#define STORE_ATTR_INSTANCE_VALUE 150 +#define STORE_ATTR_SLOT 153 +#define STORE_ATTR_WITH_HINT 154 +#define STORE_FAST__LOAD_FAST 158 +#define STORE_FAST__STORE_FAST 159 +#define STORE_SUBSCR_ADAPTIVE 161 +#define STORE_SUBSCR_DICT 167 +#define STORE_SUBSCR_LIST_INT 168 +#define UNPACK_SEQUENCE_ADAPTIVE 169 +#define UNPACK_SEQUENCE_LIST 170 +#define UNPACK_SEQUENCE_TUPLE 173 +#define UNPACK_SEQUENCE_TWO_TUPLE 174 #define DO_TRACING 255 extern const uint8_t _PyOpcode_Caches[256]; @@ -196,7 +195,7 @@ static const uint32_t _PyOpcode_RelativeJump[8] = { 0U, 536870912U, 134234112U, - 0U, + 4096U, 0U, 0U, 0U, @@ -205,8 +204,8 @@ static const uint32_t _PyOpcode_Jump[8] = { 0U, 0U, 536870912U, - 2316288000U, - 67U, + 2316156928U, + 4163U, 0U, 0U, 0U, @@ -289,8 +288,7 @@ const uint8_t _PyOpcode_Deopt[256] = { [IMPORT_NAME] = IMPORT_NAME, [IMPORT_STAR] = IMPORT_STAR, [IS_OP] = IS_OP, - [JUMP_ABSOLUTE] = JUMP_ABSOLUTE, - [JUMP_ABSOLUTE_QUICK] = JUMP_ABSOLUTE, + [JUMP_BACKWARD] = JUMP_BACKWARD, [JUMP_FORWARD] = JUMP_FORWARD, [JUMP_IF_FALSE_OR_POP] = JUMP_IF_FALSE_OR_POP, [JUMP_IF_NOT_EG_MATCH] = JUMP_IF_NOT_EG_MATCH, diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h index dbcacee7e02055..f6cacbd4df6f8d 100644 --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -33,9 +33,8 @@ static void *opcode_targets[256] = { &&TARGET_MATCH_MAPPING, &&TARGET_MATCH_SEQUENCE, &&TARGET_MATCH_KEYS, - &&TARGET_JUMP_ABSOLUTE_QUICK, - &&TARGET_PUSH_EXC_INFO, &&TARGET_LOAD_ATTR_ADAPTIVE, + &&TARGET_PUSH_EXC_INFO, &&TARGET_LOAD_ATTR_INSTANCE_VALUE, &&TARGET_LOAD_ATTR_MODULE, &&TARGET_LOAD_ATTR_SLOT, @@ -48,39 +47,40 @@ static void *opcode_targets[256] = { &&TARGET_LOAD_GLOBAL_MODULE, &&TARGET_LOAD_METHOD_ADAPTIVE, &&TARGET_LOAD_METHOD_CLASS, + &&TARGET_LOAD_METHOD_MODULE, &&TARGET_WITH_EXCEPT_START, &&TARGET_GET_AITER, &&TARGET_GET_ANEXT, &&TARGET_BEFORE_ASYNC_WITH, &&TARGET_BEFORE_WITH, &&TARGET_END_ASYNC_FOR, - &&TARGET_LOAD_METHOD_MODULE, &&TARGET_LOAD_METHOD_NO_DICT, &&TARGET_LOAD_METHOD_WITH_DICT, &&TARGET_LOAD_METHOD_WITH_VALUES, &&TARGET_PRECALL_ADAPTIVE, + &&TARGET_PRECALL_BOUND_METHOD, &&TARGET_STORE_SUBSCR, &&TARGET_DELETE_SUBSCR, - &&TARGET_PRECALL_BOUND_METHOD, &&TARGET_PRECALL_BUILTIN_CLASS, &&TARGET_PRECALL_BUILTIN_FAST_WITH_KEYWORDS, &&TARGET_PRECALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS, &&TARGET_PRECALL_NO_KW_BUILTIN_FAST, &&TARGET_PRECALL_NO_KW_BUILTIN_O, + &&TARGET_PRECALL_NO_KW_ISINSTANCE, &&TARGET_GET_ITER, &&TARGET_GET_YIELD_FROM_ITER, &&TARGET_PRINT_EXPR, &&TARGET_LOAD_BUILD_CLASS, - &&TARGET_PRECALL_NO_KW_ISINSTANCE, &&TARGET_PRECALL_NO_KW_LEN, + &&TARGET_PRECALL_NO_KW_LIST_APPEND, &&TARGET_LOAD_ASSERTION_ERROR, &&TARGET_RETURN_GENERATOR, - &&TARGET_PRECALL_NO_KW_LIST_APPEND, &&TARGET_PRECALL_NO_KW_METHOD_DESCRIPTOR_FAST, &&TARGET_PRECALL_NO_KW_METHOD_DESCRIPTOR_NOARGS, &&TARGET_PRECALL_NO_KW_METHOD_DESCRIPTOR_O, &&TARGET_PRECALL_NO_KW_STR_1, &&TARGET_PRECALL_NO_KW_TUPLE_1, + &&TARGET_PRECALL_NO_KW_TYPE_1, &&TARGET_LIST_TO_TUPLE, &&TARGET_RETURN_VALUE, &&TARGET_IMPORT_STAR, @@ -112,7 +112,7 @@ static void *opcode_targets[256] = { &&TARGET_JUMP_FORWARD, &&TARGET_JUMP_IF_FALSE_OR_POP, &&TARGET_JUMP_IF_TRUE_OR_POP, - &&TARGET_JUMP_ABSOLUTE, + &&TARGET_PRECALL_PYFUNC, &&TARGET_POP_JUMP_IF_FALSE, &&TARGET_POP_JUMP_IF_TRUE, &&TARGET_LOAD_GLOBAL, @@ -139,40 +139,39 @@ static void *opcode_targets[256] = { &&TARGET_LOAD_DEREF, &&TARGET_STORE_DEREF, &&TARGET_DELETE_DEREF, - &&TARGET_PRECALL_NO_KW_TYPE_1, - &&TARGET_PRECALL_PYFUNC, - &&TARGET_CALL_FUNCTION_EX, + &&TARGET_JUMP_BACKWARD, &&TARGET_RESUME_QUICK, + &&TARGET_CALL_FUNCTION_EX, + &&TARGET_STORE_ATTR_ADAPTIVE, &&TARGET_EXTENDED_ARG, &&TARGET_LIST_APPEND, &&TARGET_SET_ADD, &&TARGET_MAP_ADD, &&TARGET_LOAD_CLASSDEREF, &&TARGET_COPY_FREE_VARS, - &&TARGET_STORE_ATTR_ADAPTIVE, + &&TARGET_STORE_ATTR_INSTANCE_VALUE, &&TARGET_RESUME, &&TARGET_MATCH_CLASS, - &&TARGET_STORE_ATTR_INSTANCE_VALUE, &&TARGET_STORE_ATTR_SLOT, + &&TARGET_STORE_ATTR_WITH_HINT, &&TARGET_FORMAT_VALUE, &&TARGET_BUILD_CONST_KEY_MAP, &&TARGET_BUILD_STRING, - &&TARGET_STORE_ATTR_WITH_HINT, &&TARGET_STORE_FAST__LOAD_FAST, - &&TARGET_LOAD_METHOD, &&TARGET_STORE_FAST__STORE_FAST, + &&TARGET_LOAD_METHOD, + &&TARGET_STORE_SUBSCR_ADAPTIVE, &&TARGET_LIST_EXTEND, &&TARGET_SET_UPDATE, &&TARGET_DICT_MERGE, &&TARGET_DICT_UPDATE, &&TARGET_PRECALL, - &&TARGET_STORE_SUBSCR_ADAPTIVE, &&TARGET_STORE_SUBSCR_DICT, &&TARGET_STORE_SUBSCR_LIST_INT, &&TARGET_UNPACK_SEQUENCE_ADAPTIVE, + &&TARGET_UNPACK_SEQUENCE_LIST, &&TARGET_CALL, &&TARGET_KW_NAMES, - &&TARGET_UNPACK_SEQUENCE_LIST, &&TARGET_UNPACK_SEQUENCE_TUPLE, &&TARGET_UNPACK_SEQUENCE_TWO_TUPLE, &&_unknown_opcode, @@ -254,5 +253,6 @@ static void *opcode_targets[256] = { &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, + &&_unknown_opcode, &&TARGET_DO_TRACING }; From e9f4e64a9043f00ac1745e476a2fdef269a7fa6a Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Tue, 29 Mar 2022 17:40:01 +0100 Subject: [PATCH 09/10] put back quickening for backwards jumps --- Include/opcode.h | 98 +++++++++++++++++++++-------------------- Lib/opcode.py | 3 ++ Python/ceval.c | 13 ++++-- Python/opcode_targets.h | 30 ++++++------- Python/specialize.c | 3 ++ 5 files changed, 81 insertions(+), 66 deletions(-) diff --git a/Include/opcode.h b/Include/opcode.h index 648a8dd76ab33b..3a7db438ede1f3 100644 --- a/Include/opcode.h +++ b/Include/opcode.h @@ -135,54 +135,55 @@ extern "C" { #define COMPARE_OP_FLOAT_JUMP 27 #define COMPARE_OP_INT_JUMP 28 #define COMPARE_OP_STR_JUMP 29 -#define LOAD_ATTR_ADAPTIVE 34 -#define LOAD_ATTR_INSTANCE_VALUE 36 -#define LOAD_ATTR_MODULE 37 -#define LOAD_ATTR_SLOT 38 -#define LOAD_ATTR_WITH_HINT 39 -#define LOAD_CONST__LOAD_FAST 40 -#define LOAD_FAST__LOAD_CONST 41 -#define LOAD_FAST__LOAD_FAST 42 -#define LOAD_GLOBAL_ADAPTIVE 43 -#define LOAD_GLOBAL_BUILTIN 44 -#define LOAD_GLOBAL_MODULE 45 -#define LOAD_METHOD_ADAPTIVE 46 -#define LOAD_METHOD_CLASS 47 -#define LOAD_METHOD_MODULE 48 -#define LOAD_METHOD_NO_DICT 55 -#define LOAD_METHOD_WITH_DICT 56 -#define LOAD_METHOD_WITH_VALUES 57 -#define PRECALL_ADAPTIVE 58 -#define PRECALL_BOUND_METHOD 59 -#define PRECALL_BUILTIN_CLASS 62 -#define PRECALL_BUILTIN_FAST_WITH_KEYWORDS 63 -#define PRECALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS 64 -#define PRECALL_NO_KW_BUILTIN_FAST 65 -#define PRECALL_NO_KW_BUILTIN_O 66 -#define PRECALL_NO_KW_ISINSTANCE 67 -#define PRECALL_NO_KW_LEN 72 -#define PRECALL_NO_KW_LIST_APPEND 73 -#define PRECALL_NO_KW_METHOD_DESCRIPTOR_FAST 76 -#define PRECALL_NO_KW_METHOD_DESCRIPTOR_NOARGS 77 -#define PRECALL_NO_KW_METHOD_DESCRIPTOR_O 78 -#define PRECALL_NO_KW_STR_1 79 -#define PRECALL_NO_KW_TUPLE_1 80 -#define PRECALL_NO_KW_TYPE_1 81 -#define PRECALL_PYFUNC 113 -#define RESUME_QUICK 141 -#define STORE_ATTR_ADAPTIVE 143 -#define STORE_ATTR_INSTANCE_VALUE 150 -#define STORE_ATTR_SLOT 153 -#define STORE_ATTR_WITH_HINT 154 -#define STORE_FAST__LOAD_FAST 158 -#define STORE_FAST__STORE_FAST 159 -#define STORE_SUBSCR_ADAPTIVE 161 -#define STORE_SUBSCR_DICT 167 -#define STORE_SUBSCR_LIST_INT 168 -#define UNPACK_SEQUENCE_ADAPTIVE 169 -#define UNPACK_SEQUENCE_LIST 170 -#define UNPACK_SEQUENCE_TUPLE 173 -#define UNPACK_SEQUENCE_TWO_TUPLE 174 +#define JUMP_BACKWARD_QUICK 34 +#define LOAD_ATTR_ADAPTIVE 36 +#define LOAD_ATTR_INSTANCE_VALUE 37 +#define LOAD_ATTR_MODULE 38 +#define LOAD_ATTR_SLOT 39 +#define LOAD_ATTR_WITH_HINT 40 +#define LOAD_CONST__LOAD_FAST 41 +#define LOAD_FAST__LOAD_CONST 42 +#define LOAD_FAST__LOAD_FAST 43 +#define LOAD_GLOBAL_ADAPTIVE 44 +#define LOAD_GLOBAL_BUILTIN 45 +#define LOAD_GLOBAL_MODULE 46 +#define LOAD_METHOD_ADAPTIVE 47 +#define LOAD_METHOD_CLASS 48 +#define LOAD_METHOD_MODULE 55 +#define LOAD_METHOD_NO_DICT 56 +#define LOAD_METHOD_WITH_DICT 57 +#define LOAD_METHOD_WITH_VALUES 58 +#define PRECALL_ADAPTIVE 59 +#define PRECALL_BOUND_METHOD 62 +#define PRECALL_BUILTIN_CLASS 63 +#define PRECALL_BUILTIN_FAST_WITH_KEYWORDS 64 +#define PRECALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS 65 +#define PRECALL_NO_KW_BUILTIN_FAST 66 +#define PRECALL_NO_KW_BUILTIN_O 67 +#define PRECALL_NO_KW_ISINSTANCE 72 +#define PRECALL_NO_KW_LEN 73 +#define PRECALL_NO_KW_LIST_APPEND 76 +#define PRECALL_NO_KW_METHOD_DESCRIPTOR_FAST 77 +#define PRECALL_NO_KW_METHOD_DESCRIPTOR_NOARGS 78 +#define PRECALL_NO_KW_METHOD_DESCRIPTOR_O 79 +#define PRECALL_NO_KW_STR_1 80 +#define PRECALL_NO_KW_TUPLE_1 81 +#define PRECALL_NO_KW_TYPE_1 113 +#define PRECALL_PYFUNC 141 +#define RESUME_QUICK 143 +#define STORE_ATTR_ADAPTIVE 150 +#define STORE_ATTR_INSTANCE_VALUE 153 +#define STORE_ATTR_SLOT 154 +#define STORE_ATTR_WITH_HINT 158 +#define STORE_FAST__LOAD_FAST 159 +#define STORE_FAST__STORE_FAST 161 +#define STORE_SUBSCR_ADAPTIVE 167 +#define STORE_SUBSCR_DICT 168 +#define STORE_SUBSCR_LIST_INT 169 +#define UNPACK_SEQUENCE_ADAPTIVE 170 +#define UNPACK_SEQUENCE_LIST 173 +#define UNPACK_SEQUENCE_TUPLE 174 +#define UNPACK_SEQUENCE_TWO_TUPLE 175 #define DO_TRACING 255 extern const uint8_t _PyOpcode_Caches[256]; @@ -289,6 +290,7 @@ const uint8_t _PyOpcode_Deopt[256] = { [IMPORT_STAR] = IMPORT_STAR, [IS_OP] = IS_OP, [JUMP_BACKWARD] = JUMP_BACKWARD, + [JUMP_BACKWARD_QUICK] = JUMP_BACKWARD, [JUMP_FORWARD] = JUMP_FORWARD, [JUMP_IF_FALSE_OR_POP] = JUMP_IF_FALSE_OR_POP, [JUMP_IF_NOT_EG_MATCH] = JUMP_IF_NOT_EG_MATCH, diff --git a/Lib/opcode.py b/Lib/opcode.py index 5d0d8fa35ba10e..6bc64177ac8fc6 100644 --- a/Lib/opcode.py +++ b/Lib/opcode.py @@ -259,6 +259,9 @@ def jabs_op(name, op, entries=0): "COMPARE_OP_INT_JUMP", "COMPARE_OP_STR_JUMP", ], + "JUMP_BACKWARD": [ + "JUMP_BACKWARD_QUICK", + ], "LOAD_ATTR": [ "LOAD_ATTR_ADAPTIVE", "LOAD_ATTR_INSTANCE_VALUE", diff --git a/Python/ceval.c b/Python/ceval.c index fe187ac5ff0c0f..6e5fa8532e10db 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -3928,9 +3928,8 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int TARGET(JUMP_BACKWARD) { PREDICTED(JUMP_BACKWARD); - JUMPBY(-oparg); - CHECK_EVAL_BREAKER(); - DISPATCH(); + _PyCode_Warmup(frame->f_code); + JUMP_TO_INSTRUCTION(JUMP_BACKWARD_QUICK); } TARGET(POP_JUMP_IF_FALSE) { @@ -4070,6 +4069,14 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int DISPATCH(); } + TARGET(JUMP_BACKWARD_QUICK) { + PREDICTED(JUMP_BACKWARD_QUICK); + assert(oparg < INSTR_OFFSET()); + JUMPBY(-oparg); + CHECK_EVAL_BREAKER(); + DISPATCH(); + } + TARGET(GET_LEN) { // PUSH(len(TOS)) Py_ssize_t len_i = PyObject_Length(TOP()); diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h index f6cacbd4df6f8d..3afaf0b0298314 100644 --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -33,8 +33,9 @@ static void *opcode_targets[256] = { &&TARGET_MATCH_MAPPING, &&TARGET_MATCH_SEQUENCE, &&TARGET_MATCH_KEYS, - &&TARGET_LOAD_ATTR_ADAPTIVE, + &&TARGET_JUMP_BACKWARD_QUICK, &&TARGET_PUSH_EXC_INFO, + &&TARGET_LOAD_ATTR_ADAPTIVE, &&TARGET_LOAD_ATTR_INSTANCE_VALUE, &&TARGET_LOAD_ATTR_MODULE, &&TARGET_LOAD_ATTR_SLOT, @@ -47,40 +48,39 @@ static void *opcode_targets[256] = { &&TARGET_LOAD_GLOBAL_MODULE, &&TARGET_LOAD_METHOD_ADAPTIVE, &&TARGET_LOAD_METHOD_CLASS, - &&TARGET_LOAD_METHOD_MODULE, &&TARGET_WITH_EXCEPT_START, &&TARGET_GET_AITER, &&TARGET_GET_ANEXT, &&TARGET_BEFORE_ASYNC_WITH, &&TARGET_BEFORE_WITH, &&TARGET_END_ASYNC_FOR, + &&TARGET_LOAD_METHOD_MODULE, &&TARGET_LOAD_METHOD_NO_DICT, &&TARGET_LOAD_METHOD_WITH_DICT, &&TARGET_LOAD_METHOD_WITH_VALUES, &&TARGET_PRECALL_ADAPTIVE, - &&TARGET_PRECALL_BOUND_METHOD, &&TARGET_STORE_SUBSCR, &&TARGET_DELETE_SUBSCR, + &&TARGET_PRECALL_BOUND_METHOD, &&TARGET_PRECALL_BUILTIN_CLASS, &&TARGET_PRECALL_BUILTIN_FAST_WITH_KEYWORDS, &&TARGET_PRECALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS, &&TARGET_PRECALL_NO_KW_BUILTIN_FAST, &&TARGET_PRECALL_NO_KW_BUILTIN_O, - &&TARGET_PRECALL_NO_KW_ISINSTANCE, &&TARGET_GET_ITER, &&TARGET_GET_YIELD_FROM_ITER, &&TARGET_PRINT_EXPR, &&TARGET_LOAD_BUILD_CLASS, + &&TARGET_PRECALL_NO_KW_ISINSTANCE, &&TARGET_PRECALL_NO_KW_LEN, - &&TARGET_PRECALL_NO_KW_LIST_APPEND, &&TARGET_LOAD_ASSERTION_ERROR, &&TARGET_RETURN_GENERATOR, + &&TARGET_PRECALL_NO_KW_LIST_APPEND, &&TARGET_PRECALL_NO_KW_METHOD_DESCRIPTOR_FAST, &&TARGET_PRECALL_NO_KW_METHOD_DESCRIPTOR_NOARGS, &&TARGET_PRECALL_NO_KW_METHOD_DESCRIPTOR_O, &&TARGET_PRECALL_NO_KW_STR_1, &&TARGET_PRECALL_NO_KW_TUPLE_1, - &&TARGET_PRECALL_NO_KW_TYPE_1, &&TARGET_LIST_TO_TUPLE, &&TARGET_RETURN_VALUE, &&TARGET_IMPORT_STAR, @@ -112,7 +112,7 @@ static void *opcode_targets[256] = { &&TARGET_JUMP_FORWARD, &&TARGET_JUMP_IF_FALSE_OR_POP, &&TARGET_JUMP_IF_TRUE_OR_POP, - &&TARGET_PRECALL_PYFUNC, + &&TARGET_PRECALL_NO_KW_TYPE_1, &&TARGET_POP_JUMP_IF_FALSE, &&TARGET_POP_JUMP_IF_TRUE, &&TARGET_LOAD_GLOBAL, @@ -140,38 +140,39 @@ static void *opcode_targets[256] = { &&TARGET_STORE_DEREF, &&TARGET_DELETE_DEREF, &&TARGET_JUMP_BACKWARD, - &&TARGET_RESUME_QUICK, + &&TARGET_PRECALL_PYFUNC, &&TARGET_CALL_FUNCTION_EX, - &&TARGET_STORE_ATTR_ADAPTIVE, + &&TARGET_RESUME_QUICK, &&TARGET_EXTENDED_ARG, &&TARGET_LIST_APPEND, &&TARGET_SET_ADD, &&TARGET_MAP_ADD, &&TARGET_LOAD_CLASSDEREF, &&TARGET_COPY_FREE_VARS, - &&TARGET_STORE_ATTR_INSTANCE_VALUE, + &&TARGET_STORE_ATTR_ADAPTIVE, &&TARGET_RESUME, &&TARGET_MATCH_CLASS, + &&TARGET_STORE_ATTR_INSTANCE_VALUE, &&TARGET_STORE_ATTR_SLOT, - &&TARGET_STORE_ATTR_WITH_HINT, &&TARGET_FORMAT_VALUE, &&TARGET_BUILD_CONST_KEY_MAP, &&TARGET_BUILD_STRING, + &&TARGET_STORE_ATTR_WITH_HINT, &&TARGET_STORE_FAST__LOAD_FAST, - &&TARGET_STORE_FAST__STORE_FAST, &&TARGET_LOAD_METHOD, - &&TARGET_STORE_SUBSCR_ADAPTIVE, + &&TARGET_STORE_FAST__STORE_FAST, &&TARGET_LIST_EXTEND, &&TARGET_SET_UPDATE, &&TARGET_DICT_MERGE, &&TARGET_DICT_UPDATE, &&TARGET_PRECALL, + &&TARGET_STORE_SUBSCR_ADAPTIVE, &&TARGET_STORE_SUBSCR_DICT, &&TARGET_STORE_SUBSCR_LIST_INT, &&TARGET_UNPACK_SEQUENCE_ADAPTIVE, - &&TARGET_UNPACK_SEQUENCE_LIST, &&TARGET_CALL, &&TARGET_KW_NAMES, + &&TARGET_UNPACK_SEQUENCE_LIST, &&TARGET_UNPACK_SEQUENCE_TUPLE, &&TARGET_UNPACK_SEQUENCE_TWO_TUPLE, &&_unknown_opcode, @@ -253,6 +254,5 @@ static void *opcode_targets[256] = { &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, - &&_unknown_opcode, &&TARGET_DO_TRACING }; diff --git a/Python/specialize.c b/Python/specialize.c index 6d3229fc86853d..56d225423aa698 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -270,6 +270,9 @@ _PyCode_Quicken(PyCodeObject *code) else { assert(!_PyOpcode_Caches[opcode]); switch (opcode) { + case JUMP_BACKWARD: + _Py_SET_OPCODE(instructions[i], JUMP_BACKWARD_QUICK); + break; case RESUME: _Py_SET_OPCODE(instructions[i], RESUME_QUICK); break; From bbf005ede5c7dc9cec33117a4356ad4a04ef2756 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 31 Mar 2022 11:32:30 +0100 Subject: [PATCH 10/10] predict JUMP_BACKWARD_QUICK instead of JUMP_BACKWARD --- Python/ceval.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Python/ceval.c b/Python/ceval.c index 6e5fa8532e10db..02c381849e2b5c 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2218,7 +2218,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int Py_DECREF(v); if (err != 0) goto error; - PREDICT(JUMP_BACKWARD); + PREDICT(JUMP_BACKWARD_QUICK); DISPATCH(); } @@ -2230,7 +2230,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int Py_DECREF(v); if (err != 0) goto error; - PREDICT(JUMP_BACKWARD); + PREDICT(JUMP_BACKWARD_QUICK); DISPATCH(); } @@ -3396,7 +3396,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int if (_PyDict_SetItem_Take2((PyDictObject *)map, key, value) != 0) { goto error; } - PREDICT(JUMP_BACKWARD); + PREDICT(JUMP_BACKWARD_QUICK); DISPATCH(); } @@ -3927,7 +3927,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int } TARGET(JUMP_BACKWARD) { - PREDICTED(JUMP_BACKWARD); _PyCode_Warmup(frame->f_code); JUMP_TO_INSTRUCTION(JUMP_BACKWARD_QUICK); }