diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py index 256004855d4..440e4ed5eac 100644 --- a/Lib/test/test_dis.py +++ b/Lib/test/test_dis.py @@ -360,13 +360,13 @@ dis_traceback = """\ --> BINARY_OP 11 (/) POP_TOP -%3d LOAD_FAST_CHECK 1 (tb) +%3d >> LOAD_FAST_CHECK 1 (tb) RETURN_VALUE >> PUSH_EXC_INFO %3d LOAD_GLOBAL 0 (Exception) CHECK_EXC_MATCH - POP_JUMP_FORWARD_IF_FALSE 23 (to 82) + POP_JUMP_FORWARD_IF_FALSE 22 (to 80) STORE_FAST 0 (e) %3d LOAD_FAST 0 (e) @@ -376,9 +376,7 @@ dis_traceback = """\ LOAD_CONST 0 (None) STORE_FAST 0 (e) DELETE_FAST 0 (e) - -%3d LOAD_FAST 1 (tb) - RETURN_VALUE + JUMP_BACKWARD 29 (to 14) >> LOAD_CONST 0 (None) STORE_FAST 0 (e) DELETE_FAST 0 (e) @@ -396,7 +394,6 @@ ExceptionTable: TRACEBACK_CODE.co_firstlineno + 5, TRACEBACK_CODE.co_firstlineno + 3, TRACEBACK_CODE.co_firstlineno + 4, - TRACEBACK_CODE.co_firstlineno + 5, TRACEBACK_CODE.co_firstlineno + 3) def _fstring(a, b, c, d): @@ -443,7 +440,7 @@ dis_with = """\ CALL 2 POP_TOP -%3d LOAD_CONST 2 (2) +%3d >> LOAD_CONST 2 (2) STORE_FAST 2 (y) LOAD_CONST 0 (None) RETURN_VALUE @@ -456,11 +453,7 @@ dis_with = """\ POP_EXCEPT POP_TOP POP_TOP - -%3d LOAD_CONST 2 (2) - STORE_FAST 2 (y) - LOAD_CONST 0 (None) - RETURN_VALUE + JUMP_BACKWARD 13 (to 30) >> COPY 3 POP_EXCEPT RERAISE 1 @@ -472,7 +465,6 @@ ExceptionTable: _with.__code__.co_firstlineno + 1, _with.__code__.co_firstlineno + 3, _with.__code__.co_firstlineno + 1, - _with.__code__.co_firstlineno + 3, ) async def _asyncwith(c): @@ -510,7 +502,7 @@ dis_asyncwith = """\ JUMP_BACKWARD_NO_INTERRUPT 4 (to 48) >> POP_TOP -%3d LOAD_CONST 2 (2) +%3d >> LOAD_CONST 2 (2) STORE_FAST 2 (y) LOAD_CONST 0 (None) RETURN_VALUE @@ -529,11 +521,7 @@ dis_asyncwith = """\ POP_EXCEPT POP_TOP POP_TOP - -%3d LOAD_CONST 2 (2) - STORE_FAST 2 (y) - LOAD_CONST 0 (None) - RETURN_VALUE + JUMP_BACKWARD 19 (to 58) >> COPY 3 POP_EXCEPT RERAISE 1 @@ -545,7 +533,6 @@ ExceptionTable: _asyncwith.__code__.co_firstlineno + 1, _asyncwith.__code__.co_firstlineno + 3, _asyncwith.__code__.co_firstlineno + 1, - _asyncwith.__code__.co_firstlineno + 3, ) diff --git a/Lib/test/test_peepholer.py b/Lib/test/test_peepholer.py index 2c3b1ab65a8..e03c42c2f82 100644 --- a/Lib/test/test_peepholer.py +++ b/Lib/test/test_peepholer.py @@ -345,6 +345,8 @@ class TestTranforms(BytecodeTestCase): self.assertEqual(len(returns), 1) self.check_lnotab(f) + @unittest.skip("Following gh-92228 the return has two predecessors " + "and that prevents jump elimination.") def test_elim_jump_to_return(self): # JUMP_FORWARD to RETURN --> RETURN def f(cond, true_value, false_value): diff --git a/Lib/test/test_sys_settrace.py b/Lib/test/test_sys_settrace.py index 7ec290dbf04..f03b03e19a2 100644 --- a/Lib/test/test_sys_settrace.py +++ b/Lib/test/test_sys_settrace.py @@ -2042,6 +2042,15 @@ class JumpTestCase(unittest.TestCase): output.append(6) output.append(7) + @jump_test(6, 1, [1, 5, 1, 5]) + def test_jump_over_try_except(output): + output.append(1) + try: + 1 / 0 + except ZeroDivisionError as e: + output.append(5) + x = 42 # has to be a two-instruction block + @jump_test(2, 4, [1, 4, 5, -4]) def test_jump_across_with(output): output.append(1) diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-07-06-14-02-26.gh-issue-92228.44Cbly.rst b/Misc/NEWS.d/next/Core and Builtins/2022-07-06-14-02-26.gh-issue-92228.44Cbly.rst new file mode 100644 index 00000000000..458ad897cef --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-07-06-14-02-26.gh-issue-92228.44Cbly.rst @@ -0,0 +1 @@ +Disable the compiler's inline-small-exit-blocks optimization for exit blocks that are associated with source code lines. This fixes a bug where the debugger cannot tell where an exception handler ends and the following code block begins. diff --git a/Python/compile.c b/Python/compile.c index 77176893f60..f36a6e85a54 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -9224,6 +9224,16 @@ error: return -1; } +static bool +basicblock_has_lineno(const basicblock *bb) { + for (int i = 0; i < bb->b_iused; i++) { + if (bb->b_instr[i].i_loc.lineno > 0) { + return true; + } + } + return false; +} + /* If this block ends with an unconditional jump to an exit block, * then remove the jump and extend this block with the target. */ @@ -9240,6 +9250,10 @@ extend_block(basicblock *bb) { } if (basicblock_exits_scope(last->i_target) && last->i_target->b_iused <= MAX_COPY_SIZE) { basicblock *to_copy = last->i_target; + if (basicblock_has_lineno(to_copy)) { + /* copy only blocks without line number (like implicit 'return None's) */ + return 0; + } last->i_opcode = NOP; for (int i = 0; i < to_copy->b_iused; i++) { int index = basicblock_next_instr(bb);