8000 [3.12] gh-109627: duplicated small exit blocks need to be assigned ju… · python/cpython@107e148 · GitHub
[go: up one dir, main page]

Skip to content

Commit 107e148

Browse files
authored
[3.12] gh-109627: duplicated small exit blocks need to be assigned jump target labels (#109630) (#109632)
gh-109627: duplicated smalll exit blocks need to be assigned jump target labels (#109630) (cherry picked from commit 9ccf054)
1 parent 92a3479 commit 107e148

File tree

3 files changed

+28
-5
lines changed

3 files changed

+28
-5
lines changed

Lib/test/test_compile.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1216,6 +1216,15 @@ def f(x, y, z):
12161216
return a
12171217
self.assertEqual(f("x", "y", "z"), "y")
12181218

1219+
def test_duplicated_small_exit_block(self):
1220+
# See gh-109627
1221+
def f():
1222+
while element and something:
1223+
try:
1224+
return something
1225+
except:
1226+
pass
1227+
12191228

12201229
@requires_debug_ranges()
12211230
class TestSourcePositions(unittest.TestCase):
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix bug where the compiler does not assign a new jump target label to a
2+
duplicated small exit block.

Python/flowgraph.c

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -562,16 +562,23 @@ check_cfg(cfg_builder *g) {
562562
return SUCCESS;
563563
}
564564

565-
/* Calculate the actual jump target from the target_label */
566565
static int
567-
translate_jump_labels_to_targets(basicblock *entryblock)
566+
get_max_label(basicblock *entryblock)
568567
{
569-
int max_label = -1;
568+
int lbl = -1;
570569
for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
571-
if (b->b_label.id > max_label) {
572-
max_label = b->b_label.id;
570+
if (b->b_label.id > lbl) {
571+
lbl = b->b_label.id;
573572
}
574573
}
574+
return lbl;
575+
}
576+
577+
/* Calculate the actual jump target from the target_label */
578+
static int
579+
translate_jump_labels_to_targets(basicblock *entryblock)
580+
{
581+
int max_label = get_max_label(entryblock);
575582
size_t mapsize = sizeof(basicblock *) * (max_label + 1);
576583
basicblock **label2block = (basicblock **)PyMem_Malloc(mapsize);
577584
if (!label2block) {
@@ -2035,6 +2042,7 @@ is_exit_without_lineno(basicblock *b) {
20352042
return true;
20362043
}
20372044

2045+
20382046
/* PEP 626 mandates that the f_lineno of a frame is correct
20392047
* after a frame terminates. It would be prohibitively expensive
20402048
* to continuously update the f_lineno field at runtime,
@@ -2048,6 +2056,9 @@ static int
20482056
duplicate_exits_without_lineno(cfg_builder *g)
20492057
{
20502058
assert(no_empty_basic_blocks(g));
2059+
2060+
int next_lbl = get_max_label(g->g_entryblock) + 1;
2061+
20512062
/* Copy all exit blocks without line number that are targets of a jump.
20522063
*/
20532064
basicblock *entryblock = g->g_entryblock;
@@ -2066,6 +2077,7 @@ duplicate_exits_without_lineno(cfg_builder *g)
20662077
target->b_predecessors--;
20672078
new_target->b_predecessors = 1;
20682079
new_target->b_next = target->b_next;
2080+
new_target->b_label.id = next_lbl++;
20692081
target->b_next = new_target;
20702082
}
20712083
}

0 commit comments

Comments
 (0)
0