8000 gh-92228: disable the compiler's 'small exit block inlining' optimiza… · python/cpython@bde06e1 · GitHub
[go: up one dir, main page]

Skip to content

Commit bde06e1

Browse files
authored
gh-92228: disable the compiler's 'small exit block inlining' optimization for blocks that have a line number (GH-94592)
Inlining of code that corresponds to source code lines, can make it hard to distinguish later between code which is only reachable from except handlers, and that which is reachable in normal control flow. This caused problems with the debugger's jump feature. This PR turns off the inlining optimisation for code which has line numbers. We still inline things like the implicit "return None".
1 parent 9498860 commit bde06e1

File tree

5 files changed

+33
-20
lines changed

5 files changed

+33
-20
lines changed

Lib/test/test_dis.py

Lines changed: 7 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -360,13 +360,13 @@ def bug42562():
360360
--> BINARY_OP 11 (/)
361361
POP_TOP
362362
363-
%3d LOAD_FAST_CHECK 1 (tb)
363+
%3d >> LOAD_FAST_CHECK 1 (tb)
364364
RETURN_VALUE
365365
>> PUSH_EXC_INFO
366366
367367
%3d LOAD_GLOBAL 0 (Exception)
368368
CHECK_EXC_MATCH
369-
POP_JUMP_FORWARD_IF_FALSE 23 (to 82)
369+
POP_JUMP_FORWARD_IF_FALSE 22 (to 80)
370370
STORE_FAST 0 (e)
371371
372372
%3d LOAD_FAST 0 (e)
@@ -376,9 +376,7 @@ def bug42562():
376376
LOAD_CONST 0 (None)
377377
STORE_FAST 0 (e)
378378
DELETE_FAST 0 (e)
379-
380-
%3d LOAD_FAST 1 (tb)
381-
RETURN_VALUE
379+
JUMP_BACKWARD 29 (to 14)
382380
>> LOAD_CONST 0 (None)
383381
STORE_FAST 0 (e)
384382
DELETE_FAST 0 (e)
@@ -396,7 +394,6 @@ def bug42562():
396394
TRACEBACK_CODE.co_firstlineno + 5,
397395
TRACEBACK_CODE.co_firstlineno + 3,
398396
TRACEBACK_CODE.co_firstlineno + 4,
399-
TRACEBACK_CODE.co_firstlineno + 5,
400397
TRACEBACK_CODE.co_firstlineno + 3)
401398

402399
def _fstring(a, b, c, d):
@@ -443,7 +440,7 @@ def _with(c):
443440
CALL 2
444441
POP_TOP
445442
446-
%3d LOAD_CONST 2 (2)
443+
%3d >> LOAD_CONST 2 (2)
447444
STORE_FAST 2 (y)
448445
LOAD_CONST 0 (None)
449446
RETURN_VALUE
@@ -456,11 +453,7 @@ def _with(c):
456453
POP_EXCEPT
457454
POP_TOP
458455
POP_TOP
459-
460-
%3d LOAD_CONST 2 (2)
461-
STORE_FAST 2 (y)
462-
LOAD_CONST 0 (None)
463-
RETURN_VALUE
456+
JUMP_BACKWARD 13 (to 30)
464457
>> COPY 3
465458
POP_EXCEPT
466459
RERAISE 1
@@ -472,7 +465,6 @@ def _with(c):
472465
_with.__code__.co_firstlineno + 1,
473466
_with.__code__.co_firstlineno + 3,
474467
_with.__code__.co_firstlineno + 1,
475-
_with.__code__.co_firstlineno + 3,
476468
)
477469

478470
async def _asyncwith(c):
@@ -510,7 +502,7 @@ async def _asyncwith(c):
510502
JUMP_BACKWARD_NO_INTERRUPT 4 (to 48)
511503
>> POP_TOP
512504
513-
%3d LOAD_CONST 2 (2)
505+
%3d >> LOAD_CONST 2 (2)
514506
STORE_FAST 2 (y)
515507
LOAD_CONST 0 (None)
516508
RETURN_VALUE
@@ -529,11 +521,7 @@ async def _asyncwith(c):
529521
POP_EXCEPT
530522
POP_TOP
531523
POP_TOP
532-
533-
%3d LOAD_CONST 2 (2)
534-
STORE_FAST 2 (y)
535-
LOAD_CONST 0 (None)
536-
RETURN_VALUE
524+
JUMP_BACKWARD 19 (to 58)
537525
>> COPY 3
538526
POP_EXCEPT
539527
RERAISE 1
@@ -545,7 +533,6 @@ async def _asyncwith(c):
545533
_asyncwith.__code__.co_firstlineno + 1,
546534
_asyncwith.__code__.co_firstlineno + 3,
547535
_asyncwith.__code__.co_firstlineno + 1,
548-
_asyncwith.__code__.co_firstlineno + 3,
549536
)
550537

551538

Lib/test/test_peepholer.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,8 @@ def f(x):
345345
self.assertEqual(len(returns), 1)
346346
self.check_lnotab(f)
347347

348+
@unittest.skip("Following gh-92228 the return has two predecessors "
349+
"and that prevents jump elimination.")
348350
def test_elim_jump_to_return(self):
349351
# JUMP_FORWARD to RETURN --> RETURN
350352
def f(cond, true_value, false_value):

Lib/test/test_sys_settrace.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2042,6 +2042,15 @@ def test_no_jump_within_except_block(output):
20422042
output.append(6)
20432043
output.append(7)
20442044

2045+
@jump_test(6, 1, [1, 5, 1, 5])
2046+
def test_jump_over_try_except(output):
2047+
output.append(1)
2048+
try:
2049+
1 / 0
2050+
except ZeroDivisionError as e:
2051+
output.append(5)
2052+
x = 42 # has to be a two-instruction block
2053+
20452054
@jump_test(2, 4, [1, 4, 5, -4])
20462055
def test_jump_across_with(output):
20472056
output.append(1)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
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.

Python/compile.c

Lines changed: 14 additions & 0 deletions
< 6953 td data-grid-cell-id="diff-ebc983d9f91e5bcf73500e377ac65e85863c4f77fd5b6b6caf4fcdf7c0f0b057-9242-9253-0" data-selected="false" role="gridcell" style="background-color:var(--diffBlob-additionNum-bgColor, var(--diffBlob-addition-bgColor-num));text-align:center" tabindex="-1" valign="top" class="focusable-grid-cell diff-line-number position-relative left-side">
Original file line numberDiff line numberDiff line change
@@ -9224,6 +9224,16 @@ optimize_basic_block(PyObject *const_cache, basicblock *bb, PyObject *consts)
92249224
return -1;
92259225
}
92269226

9227+
static bool
9228+
basicblock_has_lineno(const basicblock *bb) {
9229+
for (int i = 0; i < bb->b_iused; i++) {
9230+
if (bb->b_instr[i].i_loc.lineno > 0) {
9231+
return true;
9232+
}
9233+
}
9234+
return false;
9235+
}
9236+
92279237
/* If this block ends with an unconditional jump to an exit block,
92289238
* then remove the jump and extend this block with the target.
92299239
*/
@@ -9240,6 +9250,10 @@ extend_block(basicblock *bb) {
92409250
}
92419251
if (basicblock_exits_scope(last->i_target) && last->i_target->b_iused <= MAX_COPY_SIZE) {
92429252
basicblock *to_copy = last->i_target;
9253+
if (basicblock_has_lineno(to_copy)) {
9254+
/* copy only blocks without line number (like implicit 'return None's) */
9255+
return 0;
9256+
}
92439257
last->i_opcode = NOP;
92449258
for (int i = 0; i < to_copy->b_iused; i++) {
92459259
int index = basicblock_next_instr(bb);

0 commit comments

Comments
 (0)
0