https://github.com/python/cpython/commit/be046ee6e06d3eea5f249c524861b76df6c9f003 commit: be046ee6e06d3eea5f249c524861b76df6c9f003 branch: main author: Mark Shannon <m...@hotpy.org> committer: markshannon <m...@hotpy.org> date: 2025-03-10T17:31:16Z summary:
GH-123044: Give the `POP_TOP` after a case test a location in the body, not the pattern. (GH-130627) files: A Misc/NEWS.d/next/Core_and_Builtins/2025-02-27-10-47-09.gh-issue-123044.8182Un.rst M Include/internal/pycore_symtable.h M Lib/test/test_monitoring.py M Python/assemble.c M Python/codegen.c M Python/flowgraph.c diff --git a/Include/internal/pycore_symtable.h b/Include/internal/pycore_symtable.h index 3b87a7f869c4d7..fd6b9bcbe5abd8 100644 --- a/Include/internal/pycore_symtable.h +++ b/Include/internal/pycore_symtable.h @@ -58,6 +58,7 @@ typedef struct { .end_col_offset = (n)->end_col_offset } static const _Py_SourceLocation NO_LOCATION = {-1, -1, -1, -1}; +static const _Py_SourceLocation NEXT_LOCATION = {-2, -2, -2, -2}; /* __future__ information */ typedef struct { diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index fc98b9eee383e4..23b0d56c767b4f 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -1681,6 +1681,35 @@ async def foo(): ('branch left', 'func', 12, 12)]) + def test_match(self): + + def func(v=1): + x = 0 + for v in range(4): + match v: + case 1: + x += 1 + case 2: + x += 2 + case _: + x += 3 + return x + + self.check_events(func, recorders = BRANCHES_RECORDERS, expected = [ + ('branch left', 'func', 2, 2), + ('branch right', 'func', 4, 6), + ('branch right', 'func', 6, 8), + ('branch left', 'func', 2, 2), + ('branch left', 'func', 4, 5), + ('branch left', 'func', 2, 2), + ('branch right', 'func', 4, 6), + ('branch left', 'func', 6, 7), + ('branch left', 'func', 2, 2), + ('branch right', 'func', 4, 6), + ('branch right', 'func', 6, 8), + ('branch right', 'func', 2, 10)]) + + class TestBranchConsistency(MonitoringTestBase, unittest.TestCase): def check_branches(self, run_func, test_func=None, tool=TEST_TOOL, recorders=BRANCH_OFFSET_RECORDERS): diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-02-27-10-47-09.gh-issue-123044.8182Un.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-02-27-10-47-09.gh-issue-123044.8182Un.rst new file mode 100644 index 00000000000000..75ad311d7cd7e4 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-02-27-10-47-09.gh-issue-123044.8182Un.rst @@ -0,0 +1,2 @@ +Make sure that the location of branch targets in ``match`` cases is in the +body, not the pattern. diff --git a/Python/assemble.c b/Python/assemble.c index e33918edf8e4b9..6fdc0c86c0fe39 100644 --- a/Python/assemble.c +++ b/Python/assemble.c @@ -291,6 +291,7 @@ write_location_info_entry(struct assembler* a, location loc, int isize) RETURN_IF_ERROR(_PyBytes_Resize(&a->a_linetable, len*2)); } if (loc.lineno < 0) { + assert(loc.lineno == NO_LOCATION.lineno); write_location_info_none(a, isize); return SUCCESS; } @@ -341,6 +342,18 @@ assemble_location_info(struct assembler *a, instr_sequence *instrs, { a->a_lineno = firstlineno; location loc = NO_LOCATION; + for (int i = instrs->s_used-1; i >= 0; i--) { + instruction *instr = &instrs->s_instrs[i]; + if (same_location(instr->i_loc, NEXT_LOCATION)) { + if (IS_TERMINATOR_OPCODE(instr->i_opcode)) { + instr->i_loc = NO_LOCATION; + } + else { + assert(i < instrs->s_used-1); + instr->i_loc = instr[1].i_loc; + } + } + } int size = 0; for (int i = 0; i < instrs->s_used; i++) { instruction *instr = &instrs->s_instrs[i]; diff --git a/Python/codegen.c b/Python/codegen.c index 7a3f787aec0d2d..908711250d14bc 100644 --- a/Python/codegen.c +++ b/Python/codegen.c @@ -6124,7 +6124,8 @@ codegen_match_inner(compiler *c, stmt_ty s, pattern_context *pc) } // Success! Pop the subject off, we're done with it: if (i != cases - has_default - 1) { - ADDOP(c, LOC(m->pattern), POP_TOP); + /* Use the next location to give better locations for branch events */ + ADDOP(c, NEXT_LOCATION, POP_TOP); } VISIT_SEQ(c, stmt, m->body); ADDOP_JUMP(c, NO_LOCATION, JUMP, end); diff --git a/Python/flowgraph.c b/Python/flowgraph.c index 6ba60d4312e56c..286f8999902e32 100644 --- a/Python/flowgraph.c +++ b/Python/flowgraph.c @@ -1078,8 +1078,8 @@ basicblock_remove_redundant_nops(basicblock *bb) { location next_loc = NO_LOCATION; for (int next_i=0; next_i < next->b_iused; next_i++) { cfg_instr *instr = &next->b_instr[next_i]; - if (instr->i_opcode == NOP && instr->i_loc.lineno == NO_LOCATION.lineno) { - /* Skip over NOPs without location, they will be removed */ + if (instr->i_opcode == NOP && instr->i_loc.lineno < 0) { + /* Skip over NOPs without a location, they will be removed */ continue; } next_loc = instr->i_loc; @@ -2976,7 +2976,7 @@ propagate_line_numbers(basicblock *entryblock) { location prev_location = NO_LOCATION; for (int i = 0; i < b->b_iused; i++) { - if (b->b_instr[i].i_loc.lineno < 0) { + if (b->b_instr[i].i_loc.lineno == NO_LOCATION.lineno) { b->b_instr[i].i_loc = prev_location; } else { @@ -2985,7 +2985,7 @@ propagate_line_numbers(basicblock *entryblock) { } if (BB_HAS_FALLTHROUGH(b) && b->b_next->b_predecessors == 1) { if (b->b_next->b_iused > 0) { - if (b->b_next->b_instr[0].i_loc.lineno < 0) { + if (b->b_next->b_instr[0].i_loc.lineno == NO_LOCATION.lineno) { b->b_next->b_instr[0].i_loc = prev_location; } } @@ -2993,7 +2993,7 @@ propagate_line_numbers(basicblock *entryblock) { if (is_jump(last)) { basicblock *target = last->i_target; if (target->b_predecessors == 1) { - if (target->b_instr[0].i_loc.lineno < 0) { + if (target->b_instr[0].i_loc.lineno == NO_LOCATION.lineno) { target->b_instr[0].i_loc = prev_location; } } _______________________________________________ Python-checkins mailing list -- python-checkins@python.org To unsubscribe send an email to python-checkins-le...@python.org https://mail.python.org/mailman3/lists/python-checkins.python.org/ Member address: arch...@mail-archive.com