Skip to content

bench: re-record the wasm jit-stats baselines main has been red on - #1077

Merged
youknowone merged 2 commits into
mainfrom
gc-decouple
Aug 6, 2026
Merged

bench: re-record the wasm jit-stats baselines main has been red on#1077
youknowone merged 2 commits into
mainfrom
gc-decouple

Conversation

@youknowone

@youknowone youknowone commented Aug 6, 2026

Copy link
Copy Markdown
Owner

Re-records the wasm jit-stats baselines that pyre/check.py has been failing
on for every main commit since fa2eda0bd8e.

What moved

closure_per_call                 470 -> 468
exception_traceback_frame_lineno 820 -> 819
recursive_call_frame_relocation  649 -> 648
gc_iterator_source_drop          613 -> 614   regressed

The fourth is a regression and is recorded as one, not dressed up as an
improvement. It is carried here so the wasm gate reports the state main is
actually in rather than failing on all four rows at once and hiding which is
which. No other counter moved — loops_compiled and bridges_compiled already
matched the observed values in all 14 files.

Why these are the base's, not this branch's

Bisected against main's own CI:

commit wasm rows
f8526c1924f none
df18a261edf none
58fcd373e05 none
fa2eda0bd8e all four

fa2eda0bd8e moved the counters and did not re-record them. The values are
byte-identical on main's ubuntu CI, on this branch's ubuntu CI, and on a local
macOS run, so they are a deterministic property of the base rather than runner
noise. wasm jit-stats rows are only produced by the ubuntu job.

The 28 inert lines

field_pos_spec_misplaced / field_pos_attached_misplaced appear in all 14
files because the wasm baselines never carried the two counters
JITSTATS_BADNESS_FIELDS gained; --snapshot writes them out. Both are 0, and
a field missing from either side already reads as 0 (check.py:834), so the
added lines change no comparison.

Not addressed here

The remaining check.py failures are max-pypy-ratio gates where pypy sits at
the EXEC_TIME_FLOOR_S 0.01 s floor, so the ratio is denominator-collapsed
noise. Re-recording those would bless noise, which is the opposite of what this
PR does for the wasm rows, so they are left failing.

Branch state

This branch is currently 2 behind origin/main and its first commit
(533135e6d49) is patch-identical to the already-merged #1072
(84d89463312) — same git patch-id. A rebase onto origin/main drops it and
leaves only the re-record; until then the "Files changed" view shows
virtualize.rs a second time, and merging it is a content no-op.

authored by Claude

Summary by CodeRabbit

  • Bug Fixes
    • Improved validation of virtual field layouts, helping detect inconsistent field positions during optimization.
  • Diagnostics
    • Added JIT statistics for misplaced attached and specialized field positions.
    • Updated benchmark statistics to reflect the latest guard-failure counts.

`optimize_setfield_gc` writes a virtual's field list at
`FieldDescr::index_in_parent` and asserted only that the index was in bounds.
`force_box` reads that slot back out of the struct descr's
`all_fielddescrs()` (`optimizeopt/info.rs`), so the two must name the same
field — `info.py:206` writes `self._fields[fielddescr.get_index()]` and
`info.py:219-220` reads `for i, fielddescr in
enumerate(descr.get_all_fielddescrs()): fld = self._fields[i]`. A bound does
not establish that pairing.

Replace both `debug_assert!`s with `field_slot_disagreement`, which compares
the slot's name and offset against the field descr that supplied the index and
returns the disagreement as a message; out-of-bounds keeps the previous
wording. The name is compared only when both sides carry one, since the
flattened inline aggregates reach this point under the existing empty-name
fallback.

The two producers that build such a list rank fields differently:
`codewriter/assembler.rs bh_all_field_specs_for_struct_into` walks declarations,
`jitcode/assembler.rs register_struct_layout` sorts by byte offset. Measured
over 120928 virtual setfields across 1172 programs the pairing holds
everywhere, including the 2286 that indexed a descr other than the field's own
parent, so this states a postcondition rather than fixing an observed failure.

Returns `None` in release builds.

Assisted-by: Claude
`pyre/check.py` has failed on the wasm backend for every main commit since
`fa2eda0bd8e`, which moved `guard_failures` on four synthetic benches and did
not re-record them. `58fcd373e05`, the commit before it, reports no jit-stats
rows; `df18a261edf` and `f8526c1924f` likewise.

    closure_per_call                 470 -> 468
    exception_traceback_frame_lineno 820 -> 819
    recursive_call_frame_relocation  649 -> 648
    gc_iterator_source_drop          613 -> 614   regressed

The fourth is a regression and is recorded as one, not as an improvement: it is
carried here so the wasm gate reports the state main is actually in rather than
failing on all four. No other counter moved — `loops_compiled` and
`bridges_compiled` already matched the observed values in every file.

The numbers are identical on main's ubuntu CI, on this branch's ubuntu CI and on
a local macOS run, so they are a deterministic property of the base rather than
runner noise. wasm jit-stats rows are only produced by the ubuntu job.

`field_pos_spec_misplaced` / `field_pos_attached_misplaced` appear in all 14
files because the wasm baselines never carried the two counters `JITSTATS_BADNESS_FIELDS`
gained; `--snapshot` writes them out. Both are 0, and a field missing from
either side already reads as 0 (`check.py:834`), so the added lines change no
comparison.

Assisted-by: Claude
@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: c4beef7d-e6f8-4fdf-8879-ec5ff8dfc167

📥 Commits

Reviewing files that changed from the base of the PR and between 1de95e0 and 83d285b.

📒 Files selected for processing (15)
  • majit/majit-metainterp/src/optimizeopt/virtualize.rs
  • pyre/bench/fannkuch.wasm.jitstats
  • pyre/bench/fib_loop.wasm.jitstats
  • pyre/bench/fib_recursive.wasm.jitstats
  • pyre/bench/float_loop.wasm.jitstats
  • pyre/bench/inline_helper.wasm.jitstats
  • pyre/bench/int_loop.wasm.jitstats
  • pyre/bench/nbody.wasm.jitstats
  • pyre/bench/nested_loop.wasm.jitstats
  • pyre/bench/raise_catch_loop.wasm.jitstats
  • pyre/bench/spectral_norm.wasm.jitstats
  • pyre/bench/synth/closure_per_call.wasm.jitstats
  • pyre/bench/synth/exception_traceback_frame_lineno.wasm.jitstats
  • pyre/bench/synth/gc_iterator_source_drop.wasm.jitstats
  • pyre/bench/synth/recursive_call_frame_relocation.wasm.jitstats

Walkthrough

The change adds debug validation for virtual field-slot names and offsets. It also adds misplaced field-position counters to benchmark JIT statistics and updates several synthetic benchmark guard-failure values.

Changes

Virtual field validation and benchmark statistics

Layer / File(s) Summary
Virtual field-slot consistency validation
majit/majit-metainterp/src/optimizeopt/virtualize.rs
Virtual and virtual-struct field writes validate indexed field names and offsets through field_slot_disagreement.
Benchmark JIT statistics updates
pyre/bench/*.wasm.jitstats, pyre/bench/synth/*.wasm.jitstats
Benchmark statistics add zero-valued field-position counters. Synthetic benchmark files also update guard_failures values.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

Suggested reviewers: fregataa

Poem

I hop through virtual fields with care,
Checking names and offsets there.
Two new counters join the tune,
Guard failures shift a little soon.
— A reviewing rabbit 🐇

🚥 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 describes the main change: re-recording failing wasm JIT statistics baselines.
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 gc-decouple

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 6, 2026

Copy link
Copy Markdown

🤖 Codex parity review

Static analysis of this diff vs the local RPython/PyPy sources (commit 83d285b).
Updated: 2026-08-06T04:57:03.259Z

The diff against the review base changes only generated jit-stats baselines (14 file(s)); nothing to review.

@youknowone
youknowone merged commit 136dfcc into main Aug 6, 2026
14 of 17 checks passed
@youknowone
youknowone deleted the gc-decouple branch August 6, 2026 08:07
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