Skip to content

Commit

Permalink
pythongh-109627: duplicated smalll exit blocks need to be assigned ju…
Browse files Browse the repository at this point in the history
…mp target labels (python#109630)

(cherry picked from commit 9ccf054)
  • Loading branch information
iritkatriel committed Sep 20, 2023
1 parent 4a0c118 commit e570803
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 5 deletions.
18 changes: 18 additions & 0 deletions Lib/test/test_compile.py
Original file line number Diff line number Diff line change
Expand Up @@ -1216,6 +1216,24 @@ def f(x, y, z):
return a
self.assertEqual(f("x", "y", "z"), "y")

def test_variable_dependent(self):
# gh-104635: Since the value of b is dependent on the value of a
# the first STORE_FAST for a should not be skipped. (e.g POP_TOP).
# This test case is added to prevent potential regression from aggressive optimization.
def f():
a = 42; b = a + 54; a = 54
return a, b
self.assertEqual(f(), (54, 96))

def test_duplicated_small_exit_block(self):
# See gh-109627
def f():
while element and something:
try:
return something
except:
pass


@requires_debug_ranges()
class TestSourcePositions(unittest.TestCase):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fix bug where the compiler does not assign a new jump target label to a
duplicated small exit block.
22 changes: 17 additions & 5 deletions Python/flowgraph.c
Original file line number Diff line number Diff line change
Expand Up @@ -562,16 +562,23 @@ check_cfg(cfg_builder *g) {
return SUCCESS;
}

/* Calculate the actual jump target from the target_label */
static int
translate_jump_labels_to_targets(basicblock *entryblock)
get_max_label(basicblock *entryblock)
{
int max_label = -1;
int lbl = -1;
for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
if (b->b_label.id > max_label) {
max_label = b->b_label.id;
if (b->b_label.id > lbl) {
lbl = b->b_label.id;
}
}
return lbl;
}

/* Calculate the actual jump target from the target_label */
static int
translate_jump_labels_to_targets(basicblock *entryblock)
{
int max_label = get_max_label(entryblock);
size_t mapsize = sizeof(basicblock *) * (max_label + 1);
basicblock **label2block = (basicblock **)PyMem_Malloc(mapsize);
if (!label2block) {
Expand Down Expand Up @@ -2035,6 +2042,7 @@ is_exit_without_lineno(basicblock *b) {
return true;
}


/* PEP 626 mandates that the f_lineno of a frame is correct
* after a frame terminates. It would be prohibitively expensive
* to continuously update the f_lineno field at runtime,
Expand All @@ -2048,6 +2056,9 @@ static int
duplicate_exits_without_lineno(cfg_builder *g)
{
assert(no_empty_basic_blocks(g));

int next_lbl = get_max_label(g->g_entryblock) + 1;

/* Copy all exit blocks without line number that are targets of a jump.
*/
basicblock *entryblock = g->g_entryblock;
Expand All @@ -2066,6 +2077,7 @@ duplicate_exits_without_lineno(cfg_builder *g)
target->b_predecessors--;
new_target->b_predecessors = 1;
new_target->b_next = target->b_next;
new_target->b_label.id = next_lbl++;
target->b_next = new_target;
}
}
Expand Down

0 comments on commit e570803

Please sign in to comment.