mirror of
https://github.com/python/cpython.git
synced 2024-11-28 04:15:11 +08:00
gh-107901: duplicate blocks with no lineno that have an eval break and multiple predecessors (#113950)
This commit is contained in:
parent
e02c15b3f1
commit
8aa0088ea2
@ -1098,6 +1098,21 @@ class TestSpecifics(unittest.TestCase):
|
||||
code_lines = self.get_code_lines(test.__code__)
|
||||
self.assertEqual(expected_lines, code_lines)
|
||||
|
||||
def test_line_number_synthetic_jump_multiple_predecessors(self):
|
||||
def f():
|
||||
for x in it:
|
||||
try:
|
||||
if C1:
|
||||
yield 2
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
# Ensure that all JUMP_BACKWARDs have line number
|
||||
code = f.__code__
|
||||
for inst in dis.Bytecode(code):
|
||||
if inst.opname == 'JUMP_BACKWARD':
|
||||
self.assertIsNotNone(inst.positions.lineno)
|
||||
|
||||
def test_lineno_of_backward_jump(self):
|
||||
# Issue gh-107901
|
||||
def f():
|
||||
|
@ -0,0 +1 @@
|
||||
Compiler duplicates basic blocks that have an eval breaker check, no line number, and multiple predecessors.
|
@ -316,6 +316,16 @@ basicblock_exits_scope(const basicblock *b) {
|
||||
return last && IS_SCOPE_EXIT_OPCODE(last->i_opcode);
|
||||
}
|
||||
|
||||
static inline int
|
||||
basicblock_has_eval_break(const basicblock *b) {
|
||||
for (int i = 0; i < b->b_iused; i++) {
|
||||
if (OPCODE_HAS_EVAL_BREAK(b->b_instr[i].i_opcode)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
cfg_builder_current_block_is_terminated(cfg_builder *g)
|
||||
{
|
||||
@ -2246,16 +2256,18 @@ convert_pseudo_ops(basicblock *entryblock)
|
||||
}
|
||||
|
||||
static inline bool
|
||||
is_exit_without_lineno(basicblock *b) {
|
||||
if (!basicblock_exits_scope(b)) {
|
||||
is_exit_or_eval_check_without_lineno(basicblock *b) {
|
||||
if (basicblock_exits_scope(b) || basicblock_has_eval_break(b)) {
|
||||
for (int i = 0; i < b->b_iused; i++) {
|
||||
if (b->b_instr[i].i_loc.lineno >= 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < b->b_iused; i++) {
|
||||
if (b->b_instr[i].i_loc.lineno >= 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -2283,7 +2295,7 @@ duplicate_exits_without_lineno(cfg_builder *g)
|
||||
}
|
||||
if (is_jump(last)) {
|
||||
basicblock *target = next_nonempty_block(last->i_target);
|
||||
if (is_exit_without_lineno(target) && target->b_predecessors > 1) {
|
||||
if (is_exit_or_eval_check_without_lineno(target) && target->b_predecessors > 1) {
|
||||
basicblock *new_target = copy_basicblock(g, target);
|
||||
if (new_target == NULL) {
|
||||
return ERROR;
|
||||
@ -2303,7 +2315,7 @@ duplicate_exits_without_lineno(cfg_builder *g)
|
||||
* fall through, and thus can only have a single predecessor */
|
||||
for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
|
||||
if (BB_HAS_FALLTHROUGH(b) && b->b_next && b->b_iused > 0) {
|
||||
if (is_exit_without_lineno(b->b_next)) {
|
||||
if (is_exit_or_eval_check_without_lineno(b->b_next)) {
|
||||
cfg_instr *last = basicblock_last_instr(b);
|
||||
assert(last != NULL);
|
||||
b->b_next->b_instr[0].i_loc = last->i_loc;
|
||||
|
Loading…
Reference in New Issue
Block a user