-
-
Notifications
You must be signed in to change notification settings - Fork 158
ci(compiler-output-regression): restore the native-region-proof gate that is red on main #7158
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| **ci(compiler-output-regression):** the `native-region-proof` gate accounts for | ||
| #7088's inline shadow-slot root barrier, restoring green on `main`. | ||
|
|
||
| #7088 moved the per-store shadow-stack root store — and its | ||
| incremental-mark root-shading barrier — from a `js_shadow_slot_bind` / | ||
| `js_shadow_slot_set` runtime call to inline IR. That barrier was always | ||
| emitted; it just lived *inside* the runtime function, invisible to the | ||
| harness's static call counter. Inlining made the `js_write_barrier_root_nanbox` | ||
| call site visible, so `write_barriers_static` jumped (e.g. h1_native_rep_equivalence | ||
| 0→3, one per rooted Buffer local) and every affected `native-region-proof` | ||
| workload tripped its heap-barrier budget. The same inline lowering inserts | ||
| `ss.*` blocks ahead of the module-init loops, shifting the deterministic | ||
| per-function block counter by 12 and blanking the `direct_bounded` / | ||
| `local_cast` / `helper_index` region labels (`for.body.2/6/10` → `14/18/22`). | ||
|
|
||
| Neither is a real regression: the root-shading barrier is gated behind | ||
| `PERRY_INCREMENTAL_MARK_BARRIER_ACTIVE_COUNT`, never fires in these workloads | ||
| (`write_barriers_traced` stays 0), and #7088 proves it observationally | ||
| identical to the call it replaced. The barriers sit in guarded `ss.barrier` | ||
| blocks at root-bind sites, never inside the native loops, which still carry | ||
| raw `load i8`/`store i8` with alias metadata and no runtime calls. | ||
|
|
||
| - `structural_counters` now scores `write_barriers_static` on the | ||
| optimizer-controlled *heap* barriers (`js_write_barrier`, | ||
| `js_write_barrier_slot`) only. The shadow-stack root-shading barriers | ||
| (`js_write_barrier_root_nanbox`, `js_write_barrier_root_heap_word`) are | ||
| reported under a new `root_shading_barriers_static` field — still visible, | ||
| no longer inflating the heap-barrier budget. Real regressions stay caught: | ||
| heap barriers are still counted, and a root barrier that actually *fires* | ||
| is caught by the `write_barriers_traced` budget. | ||
| - `h1_native_rep_equivalence`'s region selectors follow the renumbered loop | ||
| bodies (`for.body.14/18/22`). | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -221,9 +221,23 @@ def structural_counters(ir_before: str, ir_after: str, assembly: str) -> dict[st | |
| "ptrtoint": ir_after.count(" ptrtoint "), | ||
| "runtime_calls": runtime_calls, | ||
| "boxed_number_allocations": after_calls.get("js_boxed_number_new", 0), | ||
| # Heap write barriers — the perf-relevant, optimizer-controlled | ||
| # barriers this gate exists to catch. Counted statically because a | ||
| # native region that stores a GC pointer into a heap object needs | ||
| # one; the proof budgets bound how many. | ||
| "write_barriers": after_calls.get("js_write_barrier", 0) | ||
| + after_calls.get("js_write_barrier_slot", 0) | ||
| + after_calls.get("js_write_barrier_root_nanbox", 0) | ||
| + after_calls.get("js_write_barrier_slot", 0), | ||
| # GC shadow-stack root-shading barriers (#7088). Before #7088 these | ||
| # lived inside the `js_shadow_slot_bind` / `js_shadow_slot_set` | ||
| # runtime calls and were invisible to this static IR counter; #7088 | ||
| # emits the shadow-slot store — and its barrier — inline, so the | ||
| # call site is now visible here. Each is emitted once per rooted | ||
| # pointer-capable local (a structural constant, not an optimizer | ||
| # choice) and is gated behind PERRY_INCREMENTAL_MARK_BARRIER_ACTIVE_COUNT, | ||
| # so it never fires unless incremental marking is live — meaning it | ||
| # is caught, if it ever regresses at runtime, by write_barriers_traced. | ||
| # Tracked separately so it does not inflate the heap-barrier budget. | ||
| "root_shading_barriers": after_calls.get("js_write_barrier_root_nanbox", 0) | ||
|
Comment on lines
+224
to
+240
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
rg -n -C 6 \
'write_barrier_calls|js_write_barrier_root_(nanbox|heap_word)|PERRY_INCREMENTAL_MARK_BARRIER_ACTIVE_COUNT' .Repository: PerryTS/perry Length of output: 50369 🏁 Script executed: #!/bin/bash
set -euo pipefail
echo "== runtime implementations containing root barrier calls =="
rg -n -C 8 \
'js_write_barrier_root_(nanbox|heap_word)|runtime_write_barrier|write_barrier_calls|trace' \
crates/perry-runtime crates/perry-core scripts || true
echo
echo "== analyzers relevant functions =="
sed -n '420,510p' scripts/compiler_output_harness/analyzers.py
sed -n '140,255p' scripts/compiler_output_harness/analyzers.py
echo
echo "== test regression relevant section =="
sed -n '1500,1590p' tests/test_compiler_output_regression.pyRepository: PerryTS/perry Length of output: 50370 🏁 Script executed: #!/bin/bash
set -euo pipefail
echo "== files defining root barrier implementations =="
rg -n -C 12 \
'fn js_write_barrier_root_(nanbox|heap_word)|pub.*js_write_barrier_root_(nanbox|heap_word)|js_write_barrier_root_(nanbox|heap_word)\(' \
crates/perry-runtime/src 2>/dev/null || true
echo
echo "== runtime_write_barrier tracing helpers =="
rg -n -C 10 \
'runtime_write_barrier(_root_(nanbox|heap_word))?|record_write_barrier|gc_cycle_trace|write_barrier_calls|take_write_barrier_trace' \
crates/perry-runtime/src/gc crates/perry-runtime/src 2>/dev/null \
--glob '!**/target/**' \
--glob '!**/tests/**' || true
echo
echo "== analyzer summary and structural_counter gate =="
sed -n '200,245p' scripts/compiler_output_harness/analyzers.py
sed -n '430,510p' scripts/compiler_output_harness/analyzers.py
echo
echo "== tests using root-barrier runtime counters =="
rg -n -C 8 \
'write_barriers_traced|write_barrier_calls|js_write_barrier_root_(nanbox|heap_word)|root_shading_barriers_static' \
tests scripts crates/perry-runtime/src/gc/tests 2>/dev/null || trueRepository: PerryTS/perry Length of output: 50370 Add runtime coverage for root-shading barriers.
🤖 Prompt for AI Agents |
||
| + after_calls.get("js_write_barrier_root_heap_word", 0), | ||
| "buffer_slow_path_calls": sum( | ||
| count | ||
|
|
@@ -445,6 +459,7 @@ def runtime_counter_summary( | |
| "allocations_traced": traced_allocations, | ||
| "gc_collections_traced": gc_collections, | ||
| "write_barriers_static": int(after.get("write_barriers", 0) or 0), | ||
| "root_shading_barriers_static": int(after.get("root_shading_barriers", 0) or 0), | ||
| "write_barriers_traced": traced_write_barriers, | ||
| "boxed_number_allocations_static": int( | ||
| after.get("boxed_number_allocations", 0) or 0 | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Avoid Markdown heading parsing for issue references.
The leading
#7088tokens on Line 2 and Line 4 trigger markdownlint MD018. WriteIssue 7088or escape the hash so these lines remain prose.Proposed Markdown fix
📝 Committable suggestion
🧰 Tools
🪛 markdownlint-cli2 (0.23.1)
[warning] 2-2: No space after hash on atx style heading
(MD018, no-missing-space-atx)
[warning] 4-4: No space after hash on atx style heading
(MD018, no-missing-space-atx)
🤖 Prompt for AI Agents
Source: Linters/SAST tools