Skip to content

Commit 678e990

Browse files
committed
W22 cluster: fix 3 cond_branch Edge::set_to bypass sites in builder_emit_c.c
GDB investigation 2026-04-23 19:11Z + librarian 19:13:55Z pointed at feedback_edge_management.md: terminator factories MUST use the C++ bridge (Edge::set_to manages BasicBlock::in_edges_) — direct .to writes leave target blocks unaware of their predecessors and corrupt CFG-DFS. Three production-path callers in builder_emit_c.c were using the BAD pure-C cond_branch factory (hir_c_create_cond_branch) instead of the required _cpp variant: Line 4207 — hir_builder_emit_send_c (SEND bytecode) Used in await/yield-from execution path. The done_block after SEND's cond branch was orphaned in CFG, causing hir_remove_unreachable_blocks_c to either crash on NULL terminator (gen_chain test) or to walk into garbage successors via stale .to pointers (await_caller test). Line 4458 — emitMatchClass (attrs_tuple type-check branch) Surfaced through earlier test runs. Line 4522 — emitMatchMappingSequence (and_result branch) Surfaced through earlier test runs. The non-_cpp factory has an explicit "DO NOT USE for production" warning at hir_instr_c.h:1170-1172 + 1184-1185. These three sites slipped past audit during W27 emit-method conversion. Verification at HEAD post-fix: /tmp/test_await_autocompile.py: PASS — await_caller is_jit_compiled= True, coro_returns_value is_jit_compiled=True (was: SIGSEGV at iter 1000 in JIT compilation of asyncio internals) test_phoenix_jit_autocompile.test_gen_chain: PASS (was: SIGSEGV in hir_remove_unreachable_blocks_c NULL terminator) /tmp/repro_min3.py yield-from: PASS (no regression) Full test_phoenix_jit_{comparisons,controlflow,autocompile}: 368 tests PASS (no regressions; was 244 PASS pre-fix, +124 from autocompile suite passing test_gen_chain) W22 surface + 3 of 4 follow-on bugs (yield-from, controlflow, comparisons, await deopt v27, await runtime, gen_chain) all FIXED via 3-commit cluster (66850a4f47bcc9 → 11db74f88c → THIS commit). Refs: feedback_edge_management.md (Edge::set_to bridge requirement); prior identical incident at 06e2ecb/7d0aff1e42 fixed by 61c319c per librarian 19:13:55Z.
1 parent f47bcc9 commit 678e990

1 file changed

Lines changed: 11 additions & 3 deletions

File tree

Python/jit/hir/builder_emit_c.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4204,7 +4204,13 @@ void hir_builder_emit_send_c(
42044204

42054205
void *done_block = hir_builder_get_block_at_off(builder, jump_target_off);
42064206
void *continue_block = hir_builder_get_block_at_off(builder, next_instr_off);
4207-
phx_tc_emit(tc, hir_c_create_cond_branch(is_done, done_block, continue_block));
4207+
/* hir_c_create_cond_branch_cpp: uses Edge::set_to which manages the
4208+
* target BasicBlock's in_edges_ set. The pure-C hir_c_create_cond_branch
4209+
* bypasses Edge::set_to (writes edge.to directly), leaving target
4210+
* blocks unaware of their predecessor — which corrupts CFG-DFS in
4211+
* hir_remove_unreachable_blocks_c (W22 cluster gen_chain/await
4212+
* crash, gdb 19:11Z + librarian 19:13:55Z + feedback_edge_management.md). */
4213+
phx_tc_emit(tc, hir_c_create_cond_branch_cpp(is_done, done_block, continue_block));
42084214
}
42094215

42104216
/* W27c #5: emitSequenceSet (SEQUENCE_SET, Static Python). Mirrors C++
@@ -4455,7 +4461,8 @@ void hir_builder_emit_match_class_c(
44554461
void *false_block = hir_cfg_alloc_block(func);
44564462
void *done = hir_cfg_alloc_block(func);
44574463

4458-
phx_tc_emit(tc, hir_c_create_cond_branch(attrs_tuple, true_block, false_block));
4464+
/* _cpp variant required: Edge::set_to manages BasicBlock in_edges_. */
4465+
phx_tc_emit(tc, hir_c_create_cond_branch_cpp(attrs_tuple, true_block, false_block));
44594466

44604467
tc->block = true_block;
44614468
phx_tc_emit(tc, hir_c_create_refine_type_reg(
@@ -4519,7 +4526,8 @@ void hir_builder_emit_match_mapping_sequence_c(
45194526

45204527
void *true_block = hir_cfg_alloc_block(func);
45214528
void *false_block = hir_cfg_alloc_block(func);
4522-
phx_tc_emit(tc, hir_c_create_cond_branch(and_result, true_block, false_block));
4529+
/* _cpp variant required: Edge::set_to manages BasicBlock in_edges_. */
4530+
phx_tc_emit(tc, hir_c_create_cond_branch_cpp(and_result, true_block, false_block));
45234531

45244532
void *result = hir_builder_temps_alloc_stack(builder);
45254533
void *done = hir_cfg_alloc_block(func);

0 commit comments

Comments
 (0)