gh-109627: duplicated smalll exit blocks need to be assigned jump target labels (#109630)
This commit is contained in:
parent
14cdefa667
commit
9ccf0545ef
@ -1252,6 +1252,15 @@ class TestSpecifics(unittest.TestCase):
|
|||||||
return a, b
|
return a, b
|
||||||
self.assertEqual(f(), (54, 96))
|
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()
|
@requires_debug_ranges()
|
||||||
class TestSourcePositions(unittest.TestCase):
|
class TestSourcePositions(unittest.TestCase):
|
||||||
|
@ -0,0 +1,2 @@
|
|||||||
|
Fix bug where the compiler does not assign a new jump target label to a
|
||||||
|
duplicated small exit block.
|
@ -575,16 +575,23 @@ check_cfg(cfg_builder *g) {
|
|||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
get_max_label(basicblock *entryblock)
|
||||||
|
{
|
||||||
|
int lbl = -1;
|
||||||
|
for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
|
||||||
|
if (b->b_label.id > lbl) {
|
||||||
|
lbl = b->b_label.id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lbl;
|
||||||
|
}
|
||||||
|
|
||||||
/* Calculate the actual jump target from the target_label */
|
/* Calculate the actual jump target from the target_label */
|
||||||
static int
|
static int
|
||||||
translate_jump_labels_to_targets(basicblock *entryblock)
|
translate_jump_labels_to_targets(basicblock *entryblock)
|
||||||
{
|
{
|
||||||
int max_label = -1;
|
int max_label = get_max_label(entryblock);
|
||||||
for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
|
|
||||||
if (b->b_label.id > max_label) {
|
|
||||||
max_label = b->b_label.id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
size_t mapsize = sizeof(basicblock *) * (max_label + 1);
|
size_t mapsize = sizeof(basicblock *) * (max_label + 1);
|
||||||
basicblock **label2block = (basicblock **)PyMem_Malloc(mapsize);
|
basicblock **label2block = (basicblock **)PyMem_Malloc(mapsize);
|
||||||
if (!label2block) {
|
if (!label2block) {
|
||||||
@ -2229,6 +2236,7 @@ is_exit_without_lineno(basicblock *b) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* PEP 626 mandates that the f_lineno of a frame is correct
|
/* PEP 626 mandates that the f_lineno of a frame is correct
|
||||||
* after a frame terminates. It would be prohibitively expensive
|
* after a frame terminates. It would be prohibitively expensive
|
||||||
* to continuously update the f_lineno field at runtime,
|
* to continuously update the f_lineno field at runtime,
|
||||||
@ -2242,6 +2250,9 @@ static int
|
|||||||
duplicate_exits_without_lineno(cfg_builder *g)
|
duplicate_exits_without_lineno(cfg_builder *g)
|
||||||
{
|
{
|
||||||
assert(no_empty_basic_blocks(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.
|
/* Copy all exit blocks without line number that are targets of a jump.
|
||||||
*/
|
*/
|
||||||
basicblock *entryblock = g->g_entryblock;
|
basicblock *entryblock = g->g_entryblock;
|
||||||
@ -2260,6 +2271,7 @@ duplicate_exits_without_lineno(cfg_builder *g)
|
|||||||
target->b_predecessors--;
|
target->b_predecessors--;
|
||||||
new_target->b_predecessors = 1;
|
new_target->b_predecessors = 1;
|
||||||
new_target->b_next = target->b_next;
|
new_target->b_next = target->b_next;
|
||||||
|
new_target->b_label.id = next_lbl++;
|
||||||
target->b_next = new_target;
|
target->b_next = new_target;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user