From f6eafe18c004c55082de40d20cad084ef9dd3db7 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Wed, 6 Oct 2021 13:05:45 +0100 Subject: Normalize jumps in compiler. All forward jumps to use JUMP_FORWARD. (GH-28755) --- Lib/test/test_dis.py | 4 ++-- Python/ceval.c | 24 ++++++++++++------------ Python/compile.c | 23 +++++++++++++++++++++++ 3 files changed, 37 insertions(+), 14 deletions(-) diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py index 0899db6..4755e3f 100644 --- a/Lib/test/test_dis.py +++ b/Lib/test/test_dis.py @@ -1046,7 +1046,7 @@ expected_opinfo_jumpy = [ Instruction(opname='COMPARE_OP', opcode=107, arg=4, argval='>', argrepr='>', offset=34, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=21, argval=42, argrepr='to 42', offset=36, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=38, starts_line=8, is_jump_target=False, positions=None), - Instruction(opname='JUMP_ABSOLUTE', opcode=113, arg=26, argval=52, argrepr='to 52', offset=40, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='JUMP_FORWARD', opcode=110, arg=5, argval=52, argrepr='to 52', offset=40, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='JUMP_ABSOLUTE', opcode=113, arg=4, argval=8, argrepr='to 8', offset=42, starts_line=7, is_jump_target=True, positions=None), Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=44, 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=46, starts_line=None, is_jump_target=False, positions=None), @@ -1071,7 +1071,7 @@ expected_opinfo_jumpy = [ Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=84, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='COMPARE_OP', opcode=107, arg=0, argval='<', argrepr='<', offset=86, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=46, argval=92, argrepr='to 92', offset=88, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='JUMP_ABSOLUTE', opcode=113, arg=52, argval=104, argrepr='to 104', offset=90, starts_line=17, is_jump_target=False, positions=None), + Instruction(opname='JUMP_FORWARD', opcode=110, arg=6, argval=104, argrepr='to 104', offset=90, starts_line=17, is_jump_target=False, positions=None), Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=92, starts_line=11, is_jump_target=True, positions=None), Instruction(opname='POP_JUMP_IF_TRUE', opcode=115, arg=28, argval=56, argrepr='to 56', offset=94, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=96, starts_line=19, is_jump_target=True, positions=None), diff --git a/Python/ceval.c b/Python/ceval.c index 2dbc291..a3a173d 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -4051,19 +4051,18 @@ check_eval_breaker: TARGET(JUMP_ABSOLUTE) { PREDICTED(JUMP_ABSOLUTE); - if (oparg < INSTR_OFFSET()) { - /* Increment the warmup counter and quicken if warm enough - * _Py_Quicken is idempotent so we don't worry about overflow */ - if (!PyCodeObject_IsWarmedUp(co)) { - PyCodeObject_IncrementWarmup(co); - if (PyCodeObject_IsWarmedUp(co)) { - if (_Py_Quicken(co)) { - goto error; - } - int nexti = INSTR_OFFSET(); - first_instr = co->co_firstinstr; - next_instr = first_instr + nexti; + assert(oparg < INSTR_OFFSET()); + /* Increment the warmup counter and quicken if warm enough + * _Py_Quicken is idempotent so we don't worry about overflow */ + if (!PyCodeObject_IsWarmedUp(co)) { + PyCodeObject_IncrementWarmup(co); + if (PyCodeObject_IsWarmedUp(co)) { + if (_Py_Quicken(co)) { + goto error; } + int nexti = INSTR_OFFSET(); + first_instr = co->co_firstinstr; + next_instr = first_instr + nexti; } } JUMPTO(oparg); @@ -4072,6 +4071,7 @@ check_eval_breaker: } TARGET(JUMP_ABSOLUTE_QUICK) { + assert(oparg < INSTR_OFFSET()); JUMPTO(oparg); CHECK_EVAL_BREAKER(); DISPATCH(); diff --git a/Python/compile.c b/Python/compile.c index 694da29..2d82d6a 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -7221,6 +7221,26 @@ assemble_emit(struct assembler *a, struct instr *i) } static void +normalize_jumps(struct assembler *a) +{ + for (basicblock *b = a->a_entry; b != NULL; b = b->b_next) { + b->b_visited = 0; + } + for (basicblock *b = a->a_entry; b != NULL; b = b->b_next) { + b->b_visited = 1; + if (b->b_iused == 0) { + continue; + } + struct instr *last = &b->b_instr[b->b_iused-1]; + if (last->i_opcode == JUMP_ABSOLUTE && + last->i_target->b_visited == 0 + ) { + last->i_opcode = JUMP_FORWARD; + } + } +} + +static void assemble_jump_offsets(struct assembler *a, struct compiler *c) { basicblock *b; @@ -7897,6 +7917,9 @@ assemble(struct compiler *c, int addNone) clean_basic_block(b); } + /* Order of basic blocks must have been determined by now */ + normalize_jumps(&a); + /* Can't modify the bytecode after computing jump offsets. */ assemble_jump_offsets(&a, c); -- cgit v0.12