Skip to content

check.py: direction-labelled jit-stats gate, per-platform baselines; re-record cranelift and wasm - #1021

Merged
youknowone merged 2 commits into
mainfrom
perf-bridge
Aug 4, 2026
Merged

check.py: direction-labelled jit-stats gate, per-platform baselines; re-record cranelift and wasm#1021
youknowone merged 2 commits into
mainfrom
perf-bridge

Conversation

@youknowone

@youknowone youknowone commented Aug 4, 2026

Copy link
Copy Markdown
Owner

Follow-up to #1019, which did the dynasm half. Same drift, other two backends,
plus three changes to the gate itself.

check.py

Direction. _jit_stats_change returns (regressions, improvements). A rise
in the badness fields or guard_failures is a regression; a fall in
loops_compiled is a regression; the opposite moves are gains. Both still fail
— the labels only say whether to investigate (REGRESSED) or just re-record
(IMPROVED), and each line carries the --snapshot command that re-records it.

bridges_compiled is deliberately in neither list, so both its directions
report as regressions. It is not interpretable alone: a fall to 0 is the
dead-bridge regression when guards still fail, and a gain when they stopped —
list_length_hint_validate fell 4 → 0 as guard_failures fell 828 → 1. A rise
is either wider coverage or a guard storm.

Reproducibility. A fixture that disagrees with its baseline is re-run
JITSTATS_STABILITY_RUNS times. If a repeat of the same binary reports
different counters, the comparison is reported UNSTABLE and not gated —
there is nothing to gate on exactly when the number will not reproduce.
Measured on this tree: two runs of one pyre-dynasm binary disagreed by
loops_compiled +2 on five unrelated fixtures. Instability is measured per
invocation; no fixture is annotated as flaky.

Per-platform baselines. _jitstats_baseline_path prefers
<name>.<backend>.<sys.platform>.jitstats when present. windows-latest
cranelift reports closure_per_call guard_failures 416 and
recursive_call_frame_relocation 637 where macos-latest and ubuntu-24.04 both
report 415 and 638 — two independent runs, every other counter equal, and that
same windows host passing its dynasm leg 371/371. This records the host fact
instead of widening the gate for all 371 fixtures on all three backends.

Baselines

Eight cranelift baselines, all three OS legs reporting identical deltas.

Ten wasm baselines taken from the ubuntu CI log rather than recorded
locally
: a local macOS run reports closure_per_call guard_failures 471
where ubuntu reports 468, and ubuntu is the only host that runs the wasm leg.
Two independent CI runs reported the ten byte-identically.

wide_callkw_resume carried no bridges_compiled, guard_failures or
loops_compiled at all. Absent on both sides compares equal, so those three
were never gated on it; they are now written explicitly.

Verification

_jit_stats_change direction mapping checked on eleven cases. The IMPROVED
and UNSTABLE paths were each exercised end-to-end — UNSTABLE warns and the
run still reports ALL PASSED, IMPROVED still fails.

Local dynasm and cranelift suites disagree with CI on a further eight fixtures
on this machine only; they reproduce locally, CI's macOS leg reports the
committed values, and the local descr_set_resolved (1445) matches CI's macOS
exactly. Not yet explained, and not touched here.

authored by Claude

Summary by CodeRabbit

  • New Features

    • Added Win32 JIT benchmark statistics for closure calls and recursive call-frame relocation.
    • Added clearer JIT-stat comparison results, including improvements, regressions, missing data, and unstable results.
    • Added platform-specific baseline support and colored warning output.
  • Bug Fixes

    • Improved snapshot checks by retrying inconsistent results and distinguishing warnings from failures.
    • Enhanced benchmark summaries to report all comparison outcomes.

@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

The change updates JIT-stat baselines and extends pyre/check.py to classify, retry, gate, and report JIT-stat changes. Platform-specific baselines and yellow output are supported.

Changes

JIT statistics validation

Layer / File(s) Summary
Synthetic JIT-stat baseline updates
pyre/bench/synth/*.cranelift.win32.jitstats
Added Win32 Cranelift counters for closure-per-call and recursive call-frame relocation benchmarks.
JIT-stat comparison and stability handling
pyre/check.py
Classifies counter changes as regressions or improvements, retries discrepant fixtures, detects unstable results, and prefers platform-specific baselines.
JIT-stat result reporting
pyre/check.py
Tracks improved and unstable fixtures, adds yellow output, and reports expanded JIT-stat result categories.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related PRs

Sequence Diagram(s)

sequenceDiagram
  participant JITStatFixture
  participant BaselineLookup
  participant JITStatsChange
  participant SnapshotGating
  JITStatFixture->>BaselineLookup: Load platform-specific baseline
  BaselineLookup->>JITStatsChange: Compare counter values
  JITStatsChange->>SnapshotGating: Return regressions and improvements
  SnapshotGating->>JITStatFixture: Repeat discrepant fixture
  JITStatFixture-->>SnapshotGating: Return stable or unstable result
Loading

Poem

A rabbit checks the counters bright,
With yellow text to mark the light.
Bridges loop and guards report,
Stable runs pass through the court.
“Hop!” says the rabbit, “baselines are right.”

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the direction-labelled JIT-stat gate, per-platform baselines, and baseline re-recording changes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch perf-bridge

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown

🤖 Codex parity review

Static analysis of this diff vs the local RPython/PyPy sources (commit 09f6ee0).
Updated: 2026-08-04T13:39:10.643Z

Files in the reviewed diff
pyre/check.py

1. Regressions to PyPy parity introduced by this patch

None.

2. Other mismatches introduced by this patch

  • pyre/check.py:1260 ↔ rpython/jit/metainterp/jitprof.py:167: “baseline comparison … is not gated” turns a baseline mismatch into a passing result whenever either repeat differs from the first run. The upstream profiler only reports the final compiled-loop count; a different run does not invalidate the first run’s observed JIT behavior. This weakens the checker’s parity signal.

  • pyre/check.py:741 ↔ rpython/jit/metainterp/compile.py:550: the patch labels any rise in loops_compiled as “improved.” PyPy increments its compiled-loop total for every newly compiled loop, so an increase can also represent unwanted retracing/fragmentation; the counter has no universally positive direction.

3. Pre-existing mismatches (already present before this patch)

  • pyre/check.py:733 ↔ rpython/jit/metainterp/jitprof.py:140: missing statistics fields are read as "0", so a field omitted from both baseline and result silently compares equal. PyPy’s profiler emits its standard counters explicitly; a vanished counter is not equivalent to zero. This behavior predates the patch.

4. Structural adaptations

  • pyre/check.py:1159 ↔ rpython/jit/metainterp/jitprof.py:124: rerunning an external pyrex process and comparing committed .jitstats snapshots is a repository-level regression harness; PyPy’s JitProfiler only opens a jit-summary logging section. There is no 1:1 upstream checker to port.

  • pyre/check.py:1202 ↔ rpython/jit/metainterp/jitprof.py:167: selecting platform-specific baseline files is a host/build-environment adaptation. PyPy reports process-local totals and has no cross-host golden-baseline mechanism.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0b8d377221

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread pyre/check.py
Comment on lines +1237 to +1241
drifted = next(
(s for s in repeats or () if s != jitstats), None
)
if drifted is not None:
moved = _jit_stats_change(jitstats, drifted)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Keep reproducible regressions gated amid unrelated drift

If one counter is noisy while another has a deterministic regression, any difference between the initial snapshot and a repeat marks the entire fixture unstable, and the caller records it as passed. For example, loops_aborted can be 0 in the baseline and 1 in all three runs while loops_compiled varies in only one run; this branch then waives the persistent loops_aborted regression. Determine stability per counter and continue gating baseline differences that reproduce across the repeats rather than discarding the whole comparison.

Useful? React with 👍 / 👎.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pyre/check.py`:
- Around line 1241-1250: Update the instability branch around _jit_stats_change
to store the unstable reason instead of returning immediately. Continue through
the existing output snapshot and threshold gates, and return "unstable" with the
stored reason only after both gates pass; preserve the existing gate behavior
and unstable JIT tracking.
- Around line 1752-1754: Update the status-label mapping near self._record in
the per-fixture reporting flow so snap_status == "regressed" produces
"REGRESSED", while "fail" remains the only state producing "SNAPDIFF"; preserve
the existing "IMPROVED" mapping and associated color behavior.
- Around line 1149-1155: Update the repeat-validation flow around
`_jitstats_repeats` to accept the already validated initial stdout and compare
every repeat’s stdout against it. For each repeat, reject the result when the
exit code is nonzero, stdout differs, `_jit_panic_reason(stderr)` is present, or
`_jit_stats_snapshot(stderr)` is missing; only append valid snapshots so
nondeterministic repeats cannot be reported as merely `UNSTABLE`.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: f6a8dfaa-c567-491a-ab46-1f9a24338d50

📥 Commits

Reviewing files that changed from the base of the PR and between 40c82e5 and 0b8d377.

📒 Files selected for processing (21)
  • pyre/bench/synth/closure_per_call.cranelift.win32.jitstats
  • pyre/bench/synth/closure_per_call.wasm.jitstats
  • pyre/bench/synth/exception_bridge_traceback_head.cranelift.jitstats
  • pyre/bench/synth/exception_bridge_traceback_head.wasm.jitstats
  • pyre/bench/synth/exception_escape_caller_frame_tb_node.cranelift.jitstats
  • pyre/bench/synth/exception_escape_caller_frame_tb_node.wasm.jitstats
  • pyre/bench/synth/exception_raise_caught_same_frame_tb.cranelift.jitstats
  • pyre/bench/synth/exception_residual_raise_caught_in_frame.cranelift.jitstats
  • pyre/bench/synth/exception_traceback_frame_lineno.cranelift.jitstats
  • pyre/bench/synth/exception_traceback_frame_lineno.wasm.jitstats
  • pyre/bench/synth/gc_bug_bridge_flavor_traceback_names.cranelift.jitstats
  • pyre/bench/synth/gc_bug_bridge_flavor_traceback_names.wasm.jitstats
  • pyre/bench/synth/list_length_hint_validate.cranelift.jitstats
  • pyre/bench/synth/mutate_uncaught_raise_delivery.wasm.jitstats
  • pyre/bench/synth/raise_reg_unbound_jitstress.wasm.jitstats
  • pyre/bench/synth/recursive_call_frame_relocation.cranelift.win32.jitstats
  • pyre/bench/synth/recursive_call_frame_relocation.wasm.jitstats
  • pyre/bench/synth/slots_class_var_conflict.cranelift.jitstats
  • pyre/bench/synth/str_fstring.wasm.jitstats
  • pyre/bench/synth/wide_callkw_resume.wasm.jitstats
  • pyre/check.py

Comment thread pyre/check.py
Comment on lines +1149 to +1155
_output, _elapsed, code, stderr = run_timed(
[self._pyre(backend), script],
timeout_s=effective_timeout, env=pyre_env(),
)
if code != 0:
return None
snapshots.append(_jit_stats_snapshot(stderr))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Validate each repeat before reporting UNSTABLE.

Line 1149 discards repeat stdout. Line 1153 checks only the exit code. If the initial execution matches PyPy but a repeat returns different stdout or emits a JIT panic with changed counters, Lines 1237-1250 classify the fixture as unstable. Lines 1741-1746 then record the fixture as passed. This can convert a nondeterministic output failure into a warning.

Pass the validated initial output into _jitstats_repeats. Treat changed stdout, _jit_panic_reason(stderr), and a missing JIT-stat snapshot as an invalid repeat.

Proposed fix
-    def _jitstats_repeats(self, backend, script, timeout):
+    def _jitstats_repeats(self, backend, script, timeout, expected_output):
         ...
-            _output, _elapsed, code, stderr = run_timed(
+            repeat_output, _elapsed, code, stderr = run_timed(
                 [self._pyre(backend), script],
                 timeout_s=effective_timeout, env=pyre_env(),
             )
-            if code != 0:
+            snapshot = _jit_stats_snapshot(stderr)
+            if (
+                code != 0
+                or repeat_output != expected_output
+                or _jit_panic_reason(stderr)
+                or snapshot is None
+            ):
                 return None
-            snapshots.append(_jit_stats_snapshot(stderr))
+            snapshots.append(snapshot)
         return snapshots
...
-                repeats = self._jitstats_repeats(backend, script, timeout)
+                repeats = self._jitstats_repeats(
+                    backend, script, timeout, output,
+                )
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
_output, _elapsed, code, stderr = run_timed(
[self._pyre(backend), script],
timeout_s=effective_timeout, env=pyre_env(),
)
if code != 0:
return None
snapshots.append(_jit_stats_snapshot(stderr))
repeat_output, _elapsed, code, stderr = run_timed(
[self._pyre(backend), script],
timeout_s=effective_timeout, env=pyre_env(),
)
snapshot = _jit_stats_snapshot(stderr)
if (
code != 0
or repeat_output != expected_output
or _jit_panic_reason(stderr)
or snapshot is None
):
return None
snapshots.append(snapshot)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pyre/check.py` around lines 1149 - 1155, Update the repeat-validation flow
around `_jitstats_repeats` to accept the already validated initial stdout and
compare every repeat’s stdout against it. For each repeat, reject the result
when the exit code is nonzero, stdout differs, `_jit_panic_reason(stderr)` is
present, or `_jit_stats_snapshot(stderr)` is missing; only append valid
snapshots so nondeterministic repeats cannot be reported as merely `UNSTABLE`.

Comment thread pyre/check.py
Comment on lines +1241 to +1250
moved = _jit_stats_change(jitstats, drifted)
self.jitstats_unstable.append(f"{backend}/{name}")
return "unstable", (
"jit-stats unstable — re-running the same binary moved "
+ ", ".join(moved[0] + moved[1])
+ ", so this run's counters are not a property of the "
"tree and the baseline comparison ("
+ ", ".join(regressions + improvements)
+ ") is not gated"
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Run independent snapshot gates before returning unstable.

Line 1243 returns before the output snapshot check at Lines 1275-1282 and the threshold check at Lines 1288-1299. If --snapshot-diff is enabled, PyPy and Pyre can produce the same changed output while unstable JIT counters cause this fixture to pass at Line 1744.

Store the instability reason. Run the output and threshold gates. Return unstable only if those gates pass.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pyre/check.py` around lines 1241 - 1250, Update the instability branch around
_jit_stats_change to store the unstable reason instead of returning immediately.
Continue through the existing output snapshot and threshold gates, and return
"unstable" with the stored reason only after both gates pass; preserve the
existing gate behavior and unstable JIT tracking.

Comment thread pyre/check.py
Comment on lines +1752 to 1754
label = "IMPROVED" if snap_status == "improved" else "SNAPDIFF"
paint = yellow if snap_status == "improved" else red
self._record(backend, False, name, snap_reason)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Report a JIT-stat regression as REGRESSED.

Line 1262 returns regressed, but Line 1752 maps that state to SNAPDIFF. The per-fixture status label then does not distinguish a JIT-stat regression from a generic snapshot failure. Reserve SNAPDIFF for fail.

Proposed fix
-            label = "IMPROVED" if snap_status == "improved" else "SNAPDIFF"
-            paint = yellow if snap_status == "improved" else red
+            if snap_status == "improved":
+                label, paint = "IMPROVED", yellow
+            elif snap_status == "regressed":
+                label, paint = "REGRESSED", red
+            else:
+                label, paint = "SNAPDIFF", red
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
label = "IMPROVED" if snap_status == "improved" else "SNAPDIFF"
paint = yellow if snap_status == "improved" else red
self._record(backend, False, name, snap_reason)
label = "IMPROVED" if snap_status == "improved" else "SNAPDIFF"
paint = yellow if snap_status == "improved" else red
if snap_status == "improved":
label, paint = "IMPROVED", yellow
elif snap_status == "regressed":
label, paint = "REGRESSED", red
else:
label, paint = "SNAPDIFF", red
self._record(backend, False, name, snap_reason)
🧰 Tools
🪛 Ruff (0.16.0)

[warning] 1754-1754: Boolean positional value in function call

(FBT003)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pyre/check.py` around lines 1752 - 1754, Update the status-label mapping near
self._record in the per-fixture reporting flow so snap_status == "regressed"
produces "REGRESSED", while "fail" remains the only state producing "SNAPDIFF";
preserve the existing "IMPROVED" mapping and associated color behavior.

…at do not

reproduce, and resolve a per-platform baseline

Three changes to the jit-stats gate.

Direction. `_jit_stats_change` now returns (regressions, improvements) instead
of one string, classified per counter: a rise in the badness fields or in
guard_failures is a regression, a fall in loops_compiled is a regression, and
the opposite moves are gains. bridges_compiled is in neither list, so both its
directions report as regressions — a fall to 0 is the dead-bridge case when
guards still fail and a gain when they stopped (list_length_hint_validate fell
4 -> 0 as guard_failures fell 828 -> 1), and a rise is either wider coverage or
a guard storm. Both outcomes still fail; the labels are REGRESSED and IMPROVED,
and each carries the --snapshot command that re-records it.

Reproducibility. A fixture that disagrees with its baseline is now re-run
JITSTATS_STABILITY_RUNS times. If a repeat of the same binary reports different
counters, the comparison is reported as UNSTABLE and not gated. Measured on this
tree: two runs of one pyre-dynasm binary disagreed by loops_compiled +2 on five
unrelated fixtures. Instability is measured per invocation, not annotated per
fixture.

Per-platform baselines. `_jitstats_baseline_path` prefers
<name>.<backend>.<sys.platform>.jitstats when it exists. windows-latest
cranelift reports closure_per_call guard_failures 416 and
recursive_call_frame_relocation 637 where macos-latest and ubuntu-24.04 both
report 415 and 638, on two independent runs, with every other counter equal and
that host's dynasm leg passing 371/371. Those two overlays are added here; the
shared files still gate the other two platforms exactly.

Assisted-by: Claude

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pyre/check.py`:
- Around line 1252-1254: Validate the current snapshot in the flow calling
_jit_stats_change before comparing it with the baseline: require every field
listed in JITSTATS_SNAPSHOT_FIELDS to be present, rather than relying on omitted
fields being interpreted as "0". Reject incomplete snapshots, including missing
loops_aborted, so the corresponding gate is not disabled; leave complete
snapshot comparisons unchanged.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 2a1b2be3-3039-45dc-9775-51c4100bd08f

📥 Commits

Reviewing files that changed from the base of the PR and between 0b8d377 and 6224ba1.

📒 Files selected for processing (3)
  • pyre/bench/synth/closure_per_call.cranelift.win32.jitstats
  • pyre/bench/synth/recursive_call_frame_relocation.cranelift.win32.jitstats
  • pyre/check.py

Comment thread pyre/check.py
Comment on lines +1252 to 1254
regressions, improvements = _jit_stats_change(
jitstats_path.read_text(encoding="utf-8"), jitstats
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Reject incomplete current JIT-stat snapshots.

_jit_stats_snapshot omits absent fields, and _jit_stats_change reads each omitted field as "0". If a backend stops emitting loops_aborted while its baseline is 0, this comparison reports no change and disables that counter's gate. Validate every JITSTATS_SNAPSHOT_FIELDS member before comparison.

Proposed fix
             if not jitstats_path.exists():
                 ...
+            current_fields = _parse_jit_stats(jitstats)
+            missing_fields = [
+                field
+                for field in JITSTATS_SNAPSHOT_FIELDS
+                if field not in current_fields
+            ]
+            if missing_fields:
+                return "fail", (
+                    "missing gated [jit-stats] field(s): "
+                    + ", ".join(missing_fields)
+                )
             regressions, improvements = _jit_stats_change(
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pyre/check.py` around lines 1252 - 1254, Validate the current snapshot in the
flow calling _jit_stats_change before comparing it with the baseline: require
every field listed in JITSTATS_SNAPSHOT_FIELDS to be present, rather than
relying on omitted fields being interpreted as "0". Reject incomplete snapshots,
including missing loops_aborted, so the corresponding gate is not disabled;
leave complete snapshot comparisons unchanged.

The overlay recorded guard_failures=637, while the windows cranelift run
produces 638 — the value the shared baseline already carries. The overlay
only made the fixture fail on windows.

Assisted-by: Claude
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant