Visitar URL original
phx_ptr_array.h + inliner.cpp: P2 per-site attribution counters (3 M1… · SonicField/cpython@e7c35d8 · GitHub
Skip to content

Commit e7c35d8

Browse files
committed
phx_ptr_array.h + inliner.cpp: P2 per-site attribution counters (3 M1 sites)
P2 per-site attribution substrate per sup 22:10:51Z PICK (α) + theologian 22:00:54Z + 22:09:00Z per-site disposition framework + testkeeper 22:08:07Z (P1) empirical validation. Three per-site extern counters for M1 inliner.cpp sites (excess_args / to_delete / ends), bumped at each site after capacity-change detection at the push call. Distinguishes which specific M1 site fired vs the global phx_ptr_array_resize_count. Pythia python#476 + shepard 21:48:50Z attribution-gap empirically closed: testkeeper 22:08:07Z (P1) controlled-revert revealed only Site C (ends, delta=15 of baseline 10 on Step 2.5) contributes; Sites A (excess_args) + B (to_delete) contribute 0 on the fixture. Step 3 JIT suite measurement (testkeeper 21:59:22Z+22:08:07Z) confirmed Site A delta=0 even across 1001-test suite — real coverage gap per theologian 22:09:00Z disposition. Three changes: 1. phx_ptr_array.h: extern decl for 3 per-site counters (substrate- M1-only scope per testkeeper 22:10:23Z; M2 sites add own externs incrementally per-commit). 2. builder.cpp: single-def for 3 per-site counters alongside existing global phx_ptr_array_resize_count + phx_framestate_parent_resize_count. 3. inliner.cpp: capacity-before/after detection at each of 3 M1 push sites (excess_args inside *args branch, to_delete inside tryEliminateBeginEnd with 3 push locations all instrumented, ends inside BeginInlinedFunctionElimination::Run). Pattern: read .capacity before push, compare after, bump per-site counter on change. 4. gate_phoenix.sh Step 2.5: extend ctypes probe to read all 3 per-site counters pre/post; print per-site deltas alongside global counter. Forward use per theologian 22:09:00Z M2 protocol: - M2 builder.cpp 7-site cascade adds own per-site externs per commit - Each commit measures under Step 3 JIT suite + categorizes per site: delta>0 (covered, proceed) / delta=0 + structurally bounded ≤ initial-cap (Site B class accept-with-rationale) / delta=0 + unbounded (Site A class real gap, need test) - Per-site instrumentation pattern from this commit is reusable template Site A test addition + Site B accept-with-rationale comment in follow-up per testkeeper bandwidth (testkeeper 22:09:32Z + sup 22:10:51Z sequence step 2). numstat: Python/jit/hir/builder.cpp +10/-0 (3 per-site single-defs + comment) Python/jit/hir/inliner.cpp +24/-0 (capacity-detect at 6 push call-sites: 1 excess_args + 4 to_delete + 1 ends) Python/jit/hir/phx_ptr_array.h +11/-0 (3 extern decls + comment) scripts/gate_phoenix.sh +22/-7 (per-site counter probe + delta report)
1 parent ab3fd73 commit e7c35d8

4 files changed

Lines changed: 67 additions & 7 deletions

File tree

‎Python/jit/hir/builder.cpp‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,16 @@ size_t phx_framestate_parent_resize_count = 0;
1818
* cost across all PhxPtrArray callers (inliner.cpp M1 + future
1919
* builder.cpp M2 + ...). */
2020
unsigned long phx_ptr_array_resize_count = 0;
21+
/* P2 per-site attribution single-defs per theologian 2026-05-18T22:00:54Z
22+
* + testkeeper 22:08:07Z (P1) measurement validation. M1 inliner.cpp
23+
* sites (excess_args / to_delete / ends). Per-site bumps happen at the
24+
* call-site via capacity-before/after detection (cannot be done inside
25+
* phx_ptr_arr_push without site-tagging the call). M2 sites add own
26+
* externs + defs incrementally per testkeeper 22:10:23Z
27+
* substrate-M1-only scope. */
28+
unsigned long phx_ptr_array_resize_count_inliner_excess_args = 0;
29+
unsigned long phx_ptr_array_resize_count_inliner_to_delete = 0;
30+
unsigned long phx_ptr_array_resize_count_inliner_ends = 0;
2131
}
2232
#include "cinderx/Jit/bytecode_c.h" /* BcByteOffset wrapper for emitAnyCall seam */
2333

‎Python/jit/hir/inliner.cpp‎

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,10 +323,18 @@ void inlineFunctionCall(Function& caller, AbstractCall* call_instr) {
323323
// call-site argc (typically <10, below PhxPtrArray initial-cap 8).
324324
PhxPtrArray excess_args;
325325
phx_ptr_arr_init(&excess_args);
326+
size_t excess_cap_before = excess_args.capacity;
326327
phx_ptr_arr_reserve(&excess_args, num_excess);
328+
if (excess_args.capacity != excess_cap_before) {
329+
phx_ptr_array_resize_count_inliner_excess_args++;
330+
}
327331
for (size_t i = 0; i < num_excess; i++) {
332+
excess_cap_before = excess_args.capacity;
328333
phx_ptr_arr_push(&excess_args,
329334
call_instr->arg(callee_code->co_argcount + i));
335+
if (excess_args.capacity != excess_cap_before) {
336+
phx_ptr_array_resize_count_inliner_excess_args++;
337+
}
330338
}
331339
auto* make_tuple = static_cast<Instr*>(hir_c_create_make_tuple_reg(
332340
num_excess, instr.output(), call_instr->instr->frameState()));
@@ -375,13 +383,25 @@ void tryEliminateBeginEnd(EndInlinedFunction* end) {
375383
// amortized as std::vector for void* pointers).
376384
PhxPtrArray to_delete;
377385
phx_ptr_arr_init(&to_delete);
386+
size_t to_delete_cap_before = to_delete.capacity;
378387
phx_ptr_arr_push(&to_delete, begin);
388+
if (to_delete.capacity != to_delete_cap_before) {
389+
phx_ptr_array_resize_count_inliner_to_delete++;
390+
}
391+
to_delete_cap_before = to_delete.capacity;
379392
phx_ptr_arr_push(&to_delete, end);
393+
if (to_delete.capacity != to_delete_cap_before) {
394+
phx_ptr_array_resize_count_inliner_to_delete++;
395+
}
380396
for (; &*it != end; it++) {
381397
// Snapshots reference the FrameState owned by BeginInlinedFunction and, if
382398
// not removed, will contain bad pointers.
383399
if (it->IsSnapshot()) {
400+
to_delete_cap_before = to_delete.capacity;
384401
phx_ptr_arr_push(&to_delete, &*it);
402+
if (to_delete.capacity != to_delete_cap_before) {
403+
phx_ptr_array_resize_count_inliner_to_delete++;
404+
}
385405
continue;
386406
}
387407
// Instructions that either deopt or otherwise materialize a PyFrameObject
@@ -714,7 +734,11 @@ void BeginInlinedFunctionElimination::Run(Function& irfunc) {
714734
if (!instr.IsEndInlinedFunction()) {
715735
continue;
716736
}
737+
size_t ends_cap_before = ends.capacity;
717738
phx_ptr_arr_push(&ends, &instr);
739+
if (ends.capacity != ends_cap_before) {
740+
phx_ptr_array_resize_count_inliner_ends++;
741+
}
718742
}
719743
}
720744
for (size_t i = 0; i < ends.count; i++) {

‎Python/jit/hir/phx_ptr_array.h‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,17 @@ extern "C" {
2424
* future M2 + ...). */
2525
extern unsigned long phx_ptr_array_resize_count;
2626

27+
/* P2 per-site attribution counters per theologian 2026-05-18T22:00:54Z +
28+
* testkeeper 22:08:07Z empirical verification (Sites A+B uncovered by
29+
* Step 3, Site C delta=15). Bumped at each M1 inliner.cpp site after
30+
* capacity-change detection at the push call. Global counter remains for
31+
* substrate-wide signal; per-site counters distinguish which specific
32+
* M1 caller fired. M2 sites add own externs incrementally per-commit
33+
* (substrate-M1-only scope per testkeeper 22:10:23Z). */
34+
extern unsigned long phx_ptr_array_resize_count_inliner_excess_args;
35+
extern unsigned long phx_ptr_array_resize_count_inliner_to_delete;
36+
extern unsigned long phx_ptr_array_resize_count_inliner_ends;
37+
2738
typedef struct PhxPtrArray {
2839
void **data;
2940
size_t count;

‎scripts/gate_phoenix.sh‎

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -528,11 +528,20 @@ try:
528528
pre_count = rcnt.value
529529
pacnt = ctypes.c_ulong.in_dll(libpy, 'phx_ptr_array_resize_count')
530530
pre_pa_count = pacnt.value
531+
# P2 per-site attribution counters (theologian 22:00:54Z + testkeeper
532+
# 22:08:07Z empirical verification). Distinguish which M1 site fired.
533+
psite_ea = ctypes.c_ulong.in_dll(libpy, 'phx_ptr_array_resize_count_inliner_excess_args')
534+
psite_td = ctypes.c_ulong.in_dll(libpy, 'phx_ptr_array_resize_count_inliner_to_delete')
535+
psite_en = ctypes.c_ulong.in_dll(libpy, 'phx_ptr_array_resize_count_inliner_ends')
536+
pre_psite_ea = psite_ea.value
537+
pre_psite_td = psite_td.value
538+
pre_psite_en = psite_en.value
531539
counter_present = True
532540
except (ImportError, ModuleNotFoundError, AttributeError, ValueError, OSError):
533541
counter_present = False
534542
pre_count = 0
535543
pre_pa_count = 0
544+
pre_psite_ea = pre_psite_td = pre_psite_en = 0
536545
537546
# 14 chained BinaryOps → 14 BinaryOp DeoptBases (each carries a FrameState)
538547
# + entry Snapshot + Return → 15+ frame_states in callee HIR. When the
@@ -575,19 +584,25 @@ assert result == expected, f'fs_resize_caller: got {result}, expected {expected}
575584
if counter_present:
576585
delta = rcnt.value - pre_count
577586
pa_delta = pacnt.value - pre_pa_count
587+
psite_ea_delta = psite_ea.value - pre_psite_ea
588+
psite_td_delta = psite_td.value - pre_psite_td
589+
psite_en_delta = psite_en.value - pre_psite_en
578590
print(f'phx_framestate_parent_resize_count delta: {delta} (pre={pre_count} post={rcnt.value})')
579591
print(f'phx_ptr_array_resize_count delta: {pa_delta} (pre={pre_pa_count} post={pacnt.value})')
592+
print(f'phx_ptr_array_resize_count_inliner_excess_args delta: {psite_ea_delta} (pre={pre_psite_ea} post={psite_ea.value})')
593+
print(f'phx_ptr_array_resize_count_inliner_to_delete delta: {psite_td_delta} (pre={pre_psite_td} post={psite_td.value})')
594+
print(f'phx_ptr_array_resize_count_inliner_ends delta: {psite_en_delta} (pre={pre_psite_en} post={psite_en.value})')
580595
assert delta > 0, f'PhxFrameStatePtrMap resize fixture: resize never fired (delta=0 — inliner may have rejected fs_resize_callee, or callee frame_state count < 12)'
581-
# PhxPtrArray resize coverage (M1 typed-wrapper-migration falsifier): the
582-
# to_delete site in tryEliminateBeginEnd will push begin + end + N
583-
# Snapshots; for fs_resize_callee with 14 BinaryOps, N>8 triggers resize.
584-
# If pa_delta == 0, M1 inliner.cpp PhxPtrArray sites not exercised at
585-
# gate (unexpected for this fixture); print WARN but don't fail (existing
586-
# JIT test suite is the substrate-level coverage net for M1).
596+
# P2 per-site attribution: Step 2.5 fixture is PhxFrameStatePtrMap-primary
597+
# probe; per-site M1 inliner.cpp PhxPtrArray exercise here is incidental
598+
# (only Site C ends fired per testkeeper 22:08:07Z (P1) result). The
599+
# Step 3 JIT test suite is the per-site coverage net for Sites A + B.
600+
# WARN-not-FAIL on per-site delta=0 — informational; existing test suite
601+
# measurement is load-bearing.
587602
if pa_delta == 0:
588603
print('GATE WARN: phx_ptr_array_resize_count unchanged in fs_resize fixture; PhxPtrArray sites at inliner.cpp may have insufficient exercise here (existing JIT suite Step 3 still covers).')
589604
else:
590-
print('phx_framestate_parent_resize_count + phx_ptr_array_resize_count: symbols unreadable (ctypes lookup failed); semantic check stands but resize-path exercise UNVERIFIED at this build')
605+
print('phx_framestate_parent_resize_count + phx_ptr_array_resize_count + per-site counters: symbols unreadable (ctypes lookup failed); semantic check stands but resize-path exercise UNVERIFIED at this build')
591606
592607
print(f'PhxFrameStatePtrMap resize fixture: PASS (result={result})')
593608
" 2>&1)

0 commit comments

Comments
 (0)