Skip to content

Commit be046ee

Browse files
authored
GH-123044: Give the POP_TOP after a case test a location in the body, not the pattern. (GH-130627)
1 parent 91d6db7 commit be046ee

File tree

6 files changed

+52
-6
lines changed

6 files changed

+52
-6
lines changed

Include/internal/pycore_symtable.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ typedef struct {
5858
.end_col_offset = (n)->end_col_offset }
5959

6060
static const _Py_SourceLocation NO_LOCATION = {-1, -1, -1, -1};
61+
static const _Py_SourceLocation NEXT_LOCATION = {-2, -2, -2, -2};
6162

6263
/* __future__ information */
6364
typedef struct {

Lib/test/test_monitoring.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1681,6 +1681,35 @@ async def foo():
16811681
('branch left', 'func', 12, 12)])
16821682

16831683

1684+
def test_match(self):
1685+
1686+
def func(v=1):
1687+
x = 0
1688+
for v in range(4):
1689+
match v:
1690+
case 1:
1691+
x += 1
1692+
case 2:
1693+
x += 2
1694+
case _:
1695+
x += 3
1696+
return x
1697+
1698+
self.check_events(func, recorders = BRANCHES_RECORDERS, expected = [
1699+
('branch left', 'func', 2, 2),
1700+
('branch right', 'func', 4, 6),
1701+
('branch right', 'func', 6, 8),
1702+
('branch left', 'func', 2, 2),
1703+
('branch left', 'func', 4, 5),
1704+
('branch left', 'func', 2, 2),
1705+
('branch right', 'func', 4, 6),
1706+
('branch left', 'func', 6, 7),
1707+
('branch left', 'func', 2, 2),
1708+
('branch right', 'func', 4, 6),
1709+
('branch right', 'func', 6, 8),
1710+
('branch right', 'func', 2, 10)])
1711+
1712+
16841713
class TestBranchConsistency(MonitoringTestBase, unittest.TestCase):
16851714

16861715
def check_branches(self, run_func, test_func=None, tool=TEST_TOOL, recorders=BRANCH_OFFSET_RECORDERS):
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Make sure that the location of branch targets in ``match`` cases is in the
2+
body, not the pattern.

Python/assemble.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,7 @@ write_location_info_entry(struct assembler* a, location loc, int isize)
291291
RETURN_IF_ERROR(_PyBytes_Resize(&a->a_linetable, len*2));
292292
}
293293
if (loc.lineno < 0) {
294+
assert(loc.lineno == NO_LOCATION.lineno);
294295
write_location_info_none(a, isize);
295296
return SUCCESS;
296297
}
@@ -341,6 +342,18 @@ assemble_location_info(struct assembler *a, instr_sequence *instrs,
341342
{
342343
a->a_lineno = firstlineno;
343344
location loc = NO_LOCATION;
345+
for (int i = instrs->s_used-1; i >= 0; i--) {
346+
instruction *instr = &instrs->s_instrs[i];
347+
if (same_location(instr->i_loc, NEXT_LOCATION)) {
348+
if (IS_TERMINATOR_OPCODE(instr->i_opcode)) {
349+
instr->i_loc = NO_LOCATION;
350+
}
351+
else {
352+
assert(i < instrs->s_used-1);
353+
instr->i_loc = instr[1].i_loc;
354+
}
355+
}
356+
}
344357
int size = 0;
345358
for (int i = 0; i < instrs->s_used; i++) {
346359
instruction *instr = &instrs->s_instrs[i];

Python/codegen.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6124,7 +6124,8 @@ codegen_match_inner(compiler *c, stmt_ty s, pattern_context *pc)
61246124
}
61256125
// Success! Pop the subject off, we're done with it:
61266126
if (i != cases - has_default - 1) {
6127-
ADDOP(c, LOC(m->pattern), POP_TOP);
6127+
/* Use the next location to give better locations for branch events */
6128+
ADDOP(c, NEXT_LOCATION, POP_TOP);
61286129
}
61296130
VISIT_SEQ(c, stmt, m->body);
61306131
ADDOP_JUMP(c, NO_LOCATION, JUMP, end);

Python/flowgraph.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1078,8 +1078,8 @@ basicblock_remove_redundant_nops(basicblock *bb) {
10781078
location next_loc = NO_LOCATION;
10791079
for (int next_i=0; next_i < next->b_iused; next_i++) {
10801080
cfg_instr *instr = &next->b_instr[next_i];
1081-
if (instr->i_opcode == NOP && instr->i_loc.lineno == NO_LOCATION.lineno) {
1082-
/* Skip over NOPs without location, they will be removed */
1081+
if (instr->i_opcode == NOP && instr->i_loc.lineno < 0) {
1082+
/* Skip over NOPs without a location, they will be removed */
10831083
continue;
10841084
}
10851085
next_loc = instr->i_loc;
@@ -2976,7 +2976,7 @@ propagate_line_numbers(basicblock *entryblock) {
29762976

29772977
location prev_location = NO_LOCATION;
29782978
for (int i = 0; i < b->b_iused; i++) {
2979-
if (b->b_instr[i].i_loc.lineno < 0) {
2979+
if (b->b_instr[i].i_loc.lineno == NO_LOCATION.lineno) {
29802980
b->b_instr[i].i_loc = prev_location;
29812981
}
29822982
else {
@@ -2985,15 +2985,15 @@ propagate_line_numbers(basicblock *entryblock) {
29852985
}
29862986
if (BB_HAS_FALLTHROUGH(b) && b->b_next->b_predecessors == 1) {
29872987
if (b->b_next->b_iused > 0) {
2988-
if (b->b_next->b_instr[0].i_loc.lineno < 0) {
2988+
if (b->b_next->b_instr[0].i_loc.lineno == NO_LOCATION.lineno) {
29892989
b->b_next->b_instr[0].i_loc = prev_location;
29902990
}
29912991
}
29922992
}
29932993
if (is_jump(last)) {
29942994
basicblock *target = last->i_target;
29952995
if (target->b_predecessors == 1) {
2996-
if (target->b_instr[0].i_loc.lineno < 0) {
2996+
if (target->b_instr[0].i_loc.lineno == NO_LOCATION.lineno) {
29972997
target->b_instr[0].i_loc = prev_location;
29982998
}
29992999
}

0 commit comments

Comments
 (0)