Skip to content

check.py: derive the pypy floor from the ceiling, and refit the ceilings to measured ratios - #1086

Merged
youknowone merged 19 commits into
mainfrom
fbw
Aug 8, 2026
Merged

check.py: derive the pypy floor from the ceiling, and refit the ceilings to measured ratios#1086
youknowone merged 19 commits into
mainfrom
fbw

Conversation

@youknowone

@youknowone youknowone commented Aug 6, 2026

Copy link
Copy Markdown
Owner

What this changes

check.py no longer takes a hand-written pypy floor per fixture. The floor a bench must not read below is derived from its ceiling:

def perf_gate_floor(ceiling):
    return min(PERF_GATE_FLOOR_RATIO, ceiling / PERF_GATE_FLOOR_DIVISOR)

PERF_GATE_FLOOR_RATIO = 1.0 — parity. What we want from every bench is to reach pypy, so a hand-written floor asserts that a fixture must stay some number of times slower than pypy, which is not a thing anyone wants to be true, and is one more number to re-fit whenever the ceiling moves. The 240 # pyre-check: min-pypy-ratio= header lines are deleted and the header is now rejected rather than ignored, so it cannot creep back.

Why the divisor is 40

The divisor is what lets one number bound a fixture at both ends, so it has to clear that fixture's own host span twice over: a ceiling sits at twice the slowest runner's ratio, and the derived floor still has to land under the fastest runner's. Measured across the runner logs, a fixture's ratio spans as much as 17.8x end to end (defaults_reassigned_midloop reads 1.0x and 17.8x; class_attrs_methods and foriter_inplace_immutable are barely narrower), so a ceiling honestly fitted to the slow end sits ~36x above the fast end's reading. A divisor under that turns raising a ceiling into a floor failure on the fast runner — the one way this pair of bounds can fight itself.

FLOOR_GATE_MIN_BASELINE_S also goes from 3x to 10x the execution floor. At 3x the baseline is 3 Windows scheduler ticks and each side of the ratio carries ±1 tick, so a "you got fast" verdict was being read off a number carrying a third of its own magnitude in quantization error. One run failed comprehension_accumulators on windows for reading 0.3x against a 0.05s pypy baseline while the same fixture read 1.6x and 2.5x on macos.

Ceilings refitted

30 ceilings are refitted to twice the slowest ratio the runners actually report, each with the observation stated in its header. Two classes of landmine are behind them: #853 gave every synth fixture a blanket ceiling, and #1033 tightened 182 ceilings to a single run's numbers.

The bound is computed per platform rather than from the printed ratio. The gate compares exec > baseline * limit + compare_buffer, and windows adds 2*(1/64)*(1 + limit) to that buffer — 0.47s at limit=14, more than a short bench's whole execution time. A raw ratio > ceiling census reported 30 fixtures over; against the effective bound the count is 0, and none of those 30 had failed CI.

One gate removed

getattr_attribute_fallbacks loses its max-pypy-ratio line instead of getting a wider one. The fixture has no loop and records loops_compiled=0 on dynasm, cranelift and wasm, so its ratio compares two interpreters' startup rather than any compiled code — it reads between 1.0x and 12.2x across the runners without the fixture changing. 42 synth fixtures already carry no ratio header, and its jitstats baselines still gate it.

Verification

  • Full synthetic suite, this machine: dynasm 374/374, cranelift 374/374, wasm 373/373.
  • Derived-floor audit over 11 runner logs: of 369 observations whose pypy baseline is large enough to arm the floor gate, 0 read below their derived floor.

Also in this branch: three parity fixtures that exited 0 without a final OK line now print one, os_stat_file_descriptor is marked platforms=linux,darwin (windows has no dir_fd, so the reference raises NotImplementedError where the fixture pins the ValueError before it), and run.py reports an rc=0 with no OK as exactly that rather than as rc=0 last=''.

opened by Claude

Summary by CodeRabbit

  • Bug Fixes

    • Improved benchmark reliability by recalibrating performance thresholds across numerous benchmark scenarios.
    • Reduced false performance-gate failures caused by normal variation between runtime environments.
  • Documentation

    • Added measurement-based explanations for updated benchmark limits.
    • Clarified how cross-environment performance variability informs threshold selection.

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

Too many files!

This PR contains 1197 files, which is 1097 over the limit of 100.

To get a review, reduce the PR to 100 files or fewer by splitting it into smaller PRs or changing its base branch.

Upgrade to a paid plan to raise the limit.

Usage-priced reviews support at most 300 files.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 53c20a21-6595-41ef-bc97-0c02205fffd2

📥 Commits

Reviewing files that changed from the base of the PR and between 7d1025d and fa123a5.

📒 Files selected for processing (1197)
  • pyre/bench/fannkuch.cranelift.jitstats
  • pyre/bench/fannkuch.dynasm.jitstats
  • pyre/bench/fib_loop.cranelift.jitstats
  • pyre/bench/fib_loop.dynasm.jitstats
  • pyre/bench/fib_recursive.cranelift.jitstats
  • pyre/bench/fib_recursive.dynasm.jitstats
  • pyre/bench/float_loop.cranelift.jitstats
  • pyre/bench/float_loop.dynasm.jitstats
  • pyre/bench/inline_helper.cranelift.jitstats
  • pyre/bench/inline_helper.dynasm.jitstats
  • pyre/bench/int_loop.cranelift.jitstats
  • pyre/bench/int_loop.dynasm.jitstats
  • pyre/bench/nbody.cranelift.jitstats
  • pyre/bench/nbody.dynasm.jitstats
  • pyre/bench/nested_loop.cranelift.jitstats
  • pyre/bench/nested_loop.dynasm.jitstats
  • pyre/bench/raise_catch_loop.cranelift.jitstats
  • pyre/bench/raise_catch_loop.dynasm.jitstats
  • pyre/bench/spectral_norm.cranelift.jitstats
  • pyre/bench/spectral_norm.dynasm.jitstats
  • pyre/bench/synth/abstractmethods_metaclass_getattr.cranelift.jitstats
  • pyre/bench/synth/abstractmethods_metaclass_getattr.dynasm.jitstats
  • pyre/bench/synth/abstractmethods_metaclass_getattr.py
  • pyre/bench/synth/abstractmethods_metaclass_getattr.wasm.jitstats
  • pyre/bench/synth/abstractmethods_nonstring_name.cranelift.jitstats
  • pyre/bench/synth/abstractmethods_nonstring_name.dynasm.jitstats
  • pyre/bench/synth/abstractmethods_nonstring_name.py
  • pyre/bench/synth/abstractmethods_nonstring_name.wasm.jitstats
  • pyre/bench/synth/aiter_anext.cranelift.jitstats
  • pyre/bench/synth/aiter_anext.dynasm.jitstats
  • pyre/bench/synth/aiter_anext.py
  • pyre/bench/synth/aiter_anext.wasm.jitstats
  • pyre/bench/synth/arith_int_bool.cranelift.jitstats
  • pyre/bench/synth/arith_int_bool.dynasm.jitstats
  • pyre/bench/synth/arith_int_bool.wasm.jitstats
  • pyre/bench/synth/array_deopt_resume.cranelift.jitstats
  • pyre/bench/synth/array_deopt_resume.dynasm.jitstats
  • pyre/bench/synth/array_deopt_resume.wasm.jitstats
  • pyre/bench/synth/assert_in_loop.cranelift.jitstats
  • pyre/bench/synth/assert_in_loop.dynasm.jitstats
  • pyre/bench/synth/assert_in_loop.wasm.jitstats
  • pyre/bench/synth/ast_compile_roundtrip.cranelift.jitstats
  • pyre/bench/synth/ast_compile_roundtrip.dynasm.jitstats
  • pyre/bench/synth/ast_compile_roundtrip.wasm.jitstats
  • pyre/bench/synth/attr_cache_invalidation.cranelift.jitstats
  • pyre/bench/synth/attr_cache_invalidation.dynasm.jitstats
  • pyre/bench/synth/attr_cache_invalidation.py
  • pyre/bench/synth/attr_cache_invalidation.wasm.jitstats
  • pyre/bench/synth/attr_delete.cranelift.jitstats
  • pyre/bench/synth/attr_delete.dynasm.jitstats
  • pyre/bench/synth/attr_delete.wasm.jitstats
  • pyre/bench/synth/attr_instance_shadows_class.cranelift.jitstats
  • pyre/bench/synth/attr_instance_shadows_class.dynasm.jitstats
  • pyre/bench/synth/attr_instance_shadows_class.wasm.jitstats
  • pyre/bench/synth/attr_store_add_transition.cranelift.jitstats
  • pyre/bench/synth/attr_store_add_transition.dynasm.jitstats
  • pyre/bench/synth/attr_store_add_transition.wasm.jitstats
  • pyre/bench/synth/attr_store_cache.cranelift.jitstats
  • pyre/bench/synth/attr_store_cache.dynasm.jitstats
  • pyre/bench/synth/attr_store_cache.wasm.jitstats
  • pyre/bench/synth/bases_reassign_cache.cranelift.jitstats
  • pyre/bench/synth/bases_reassign_cache.dynasm.jitstats
  • pyre/bench/synth/bases_reassign_cache.py
  • pyre/bench/synth/bases_reassign_cache.wasm.jitstats
  • pyre/bench/synth/binary_slice_index.cranelift.jitstats
  • pyre/bench/synth/binary_slice_index.dynasm.jitstats
  • pyre/bench/synth/binary_slice_index.wasm.jitstats
  • pyre/bench/synth/bool_dunder_error_no_leak.cranelift.jitstats
  • pyre/bench/synth/bool_dunder_error_no_leak.dynasm.jitstats
  • pyre/bench/synth/bool_dunder_error_no_leak.wasm.jitstats
  • pyre/bench/synth/bound_method_builtin_fold.cranelift.jitstats
  • pyre/bench/synth/bound_method_builtin_fold.dynasm.jitstats
  • pyre/bench/synth/bound_method_builtin_fold.py
  • pyre/bench/synth/bound_method_builtin_fold.wasm.jitstats
  • pyre/bench/synth/break_except_live_local.cranelift.jitstats
  • pyre/bench/synth/break_except_live_local.dynasm.jitstats
  • pyre/bench/synth/break_except_live_local.wasm.jitstats
  • pyre/bench/synth/bridge_branchy_callee.cranelift.jitstats
  • pyre/bench/synth/bridge_branchy_callee.dynasm.jitstats
  • pyre/bench/synth/bridge_branchy_callee.wasm.jitstats
  • pyre/bench/synth/bridge_global_fold_invalidate_hot.cranelift.jitstats
  • pyre/bench/synth/bridge_global_fold_invalidate_hot.dynasm.jitstats
  • pyre/bench/synth/bridge_global_fold_invalidate_hot.wasm.jitstats
  • pyre/bench/synth/bridge_recursion_overflow.cranelift.jitstats
  • pyre/bench/synth/bridge_recursion_overflow.dynasm.jitstats
  • pyre/bench/synth/bridge_recursion_overflow.wasm.jitstats
  • pyre/bench/synth/build_class_surrogate_namespace.cranelift.jitstats
  • pyre/bench/synth/build_class_surrogate_namespace.dynasm.jitstats
  • pyre/bench/synth/build_class_surrogate_namespace.py
  • pyre/bench/synth/build_class_surrogate_namespace.wasm.jitstats
  • pyre/bench/synth/build_container_return_resume.cranelift.jitstats
  • pyre/bench/synth/build_container_return_resume.dynasm.jitstats
  • pyre/bench/synth/build_container_return_resume.wasm.jitstats
  • pyre/bench/synth/build_list_resume.cranelift.jitstats
  • pyre/bench/synth/build_list_resume.dynasm.jitstats
  • pyre/bench/synth/build_list_resume.py
  • pyre/bench/synth/build_list_resume.wasm.jitstats
  • pyre/bench/synth/build_set_hashability.cranelift.jitstats
  • pyre/bench/synth/build_set_hashability.dynasm.jitstats
  • pyre/bench/synth/build_set_hashability.py
  • pyre/bench/synth/build_set_hashability.wasm.jitstats
  • pyre/bench/synth/builtin_type_surface.cranelift.jitstats
  • pyre/bench/synth/builtin_type_surface.dynasm.jitstats
  • pyre/bench/synth/builtin_type_surface.py
  • pyre/bench/synth/builtin_type_surface.wasm.jitstats
  • pyre/bench/synth/bytes_split_whitespace_maxsplit.cranelift.jitstats
  • pyre/bench/synth/bytes_split_whitespace_maxsplit.dynasm.jitstats
  • pyre/bench/synth/bytes_split_whitespace_maxsplit.py
  • pyre/bench/synth/bytes_split_whitespace_maxsplit.wasm.jitstats
  • pyre/bench/synth/ca_bridge_multiframe_resume_double_call.cranelift.jitstats
  • pyre/bench/synth/ca_bridge_multiframe_resume_double_call.dynasm.jitstats
  • pyre/bench/synth/ca_bridge_multiframe_resume_double_call.wasm.jitstats
  • pyre/bench/synth/call_ex_kwargs_mapping.cranelift.jitstats
  • pyre/bench/synth/call_ex_kwargs_mapping.dynasm.jitstats
  • pyre/bench/synth/call_ex_kwargs_mapping.py
  • pyre/bench/synth/call_ex_kwargs_mapping.wasm.jitstats
  • pyre/bench/synth/call_kw_hot_loop.cranelift.jitstats
  • pyre/bench/synth/call_kw_hot_loop.dynasm.jitstats
  • pyre/bench/synth/call_kw_hot_loop.wasm.jitstats
  • pyre/bench/synth/call_loop_local_function.cranelift.jitstats
  • pyre/bench/synth/call_loop_local_function.dynasm.jitstats
  • pyre/bench/synth/call_loop_local_function.py
  • pyre/bench/synth/call_loop_local_function.wasm.jitstats
  • pyre/bench/synth/call_slot_descriptor_protocol.cranelift.jitstats
  • pyre/bench/synth/call_slot_descriptor_protocol.dynasm.jitstats
  • pyre/bench/synth/call_slot_descriptor_protocol.wasm.jitstats
  • pyre/bench/synth/call_star_forms_inlined_callee.cranelift.jitstats
  • pyre/bench/synth/call_star_forms_inlined_callee.dynasm.jitstats
  • pyre/bench/synth/call_star_forms_inlined_callee.wasm.jitstats
  • pyre/bench/synth/callable_iterator_type.cranelift.jitstats
  • pyre/bench/synth/callable_iterator_type.dynasm.jitstats
  • pyre/bench/synth/callable_iterator_type.wasm.jitstats
  • pyre/bench/synth/callee_return_side_effect.cranelift.jitstats
  • pyre/bench/synth/callee_return_side_effect.dynasm.jitstats
  • pyre/bench/synth/callee_return_side_effect.wasm.jitstats
  • pyre/bench/synth/callee_store_global_read_after_call.cranelift.jitstats
  • pyre/bench/synth/callee_store_global_read_after_call.dynasm.jitstats
  • pyre/bench/synth/callee_store_global_read_after_call.wasm.jitstats
  • pyre/bench/synth/calls_closures.cranelift.jitstats
  • pyre/bench/synth/calls_closures.dynasm.jitstats
  • pyre/bench/synth/calls_closures.wasm.jitstats
  • pyre/bench/synth/chained_comparison.cranelift.jitstats
  • pyre/bench/synth/chained_comparison.dynasm.jitstats
  • pyre/bench/synth/chained_comparison.wasm.jitstats
  • pyre/bench/synth/check_exc_match_invalid_class.cranelift.jitstats
  • pyre/bench/synth/check_exc_match_invalid_class.dynasm.jitstats
  • pyre/bench/synth/check_exc_match_invalid_class.wasm.jitstats
  • pyre/bench/synth/class_attrs_methods.cranelift.jitstats
  • pyre/bench/synth/class_attrs_methods.dynasm.jitstats
  • pyre/bench/synth/class_attrs_methods.py
  • pyre/bench/synth/class_attrs_methods.wasm.jitstats
  • pyre/bench/synth/class_reassign_hot.cranelift.jitstats
  • pyre/bench/synth/class_reassign_hot.dynasm.jitstats
  • pyre/bench/synth/class_reassign_hot.wasm.jitstats
  • pyre/bench/synth/classmethod_type_dispatch_hot.cranelift.jitstats
  • pyre/bench/synth/classmethod_type_dispatch_hot.dynasm.jitstats
  • pyre/bench/synth/classmethod_type_dispatch_hot.wasm.jitstats
  • pyre/bench/synth/closure_freevar_branch_resume.cranelift.jitstats
  • pyre/bench/synth/closure_freevar_branch_resume.dynasm.jitstats
  • pyre/bench/synth/closure_freevar_branch_resume.wasm.jitstats
  • pyre/bench/synth/closure_per_call.cranelift.jitstats
  • pyre/bench/synth/closure_per_call.dynasm.jitstats
  • pyre/bench/synth/closure_per_call.wasm.jitstats
  • pyre/bench/synth/complex_from_index.cranelift.jitstats
  • pyre/bench/synth/complex_from_index.dynasm.jitstats
  • pyre/bench/synth/complex_from_index.wasm.jitstats
  • pyre/bench/synth/complex_real_imag.cranelift.jitstats
  • pyre/bench/synth/complex_real_imag.dynasm.jitstats
  • pyre/bench/synth/complex_real_imag.py
  • pyre/bench/synth/complex_real_imag.wasm.jitstats
  • pyre/bench/synth/comprehension_accumulators.cranelift.jitstats
  • pyre/bench/synth/comprehension_accumulators.dynasm.jitstats
  • pyre/bench/synth/comprehension_accumulators.wasm.jitstats
  • pyre/bench/synth/comprehension_module_scope.cranelift.jitstats
  • pyre/bench/synth/comprehension_module_scope.dynasm.jitstats
  • pyre/bench/synth/comprehension_module_scope.wasm.jitstats
  • pyre/bench/synth/comprehension_object_append_hot.cranelift.jitstats
  • pyre/bench/synth/comprehension_object_append_hot.dynasm.jitstats
  • pyre/bench/synth/comprehension_object_append_hot.py
  • pyre/bench/synth/comprehension_object_append_hot.wasm.jitstats
  • pyre/bench/synth/comprehension_param_range_call_flush.cranelift.jitstats
  • pyre/bench/synth/comprehension_param_range_call_flush.dynasm.jitstats
  • pyre/bench/synth/comprehension_param_range_call_flush.wasm.jitstats
  • pyre/bench/synth/condexpr_heap_const_merge.cranelift.jitstats
  • pyre/bench/synth/condexpr_heap_const_merge.dynasm.jitstats
  • pyre/bench/synth/condexpr_heap_const_merge.py
  • pyre/bench/synth/condexpr_heap_const_merge.wasm.jitstats
  • pyre/bench/synth/const_arg_call_resume.cranelift.jitstats
  • pyre/bench/synth/const_arg_call_resume.dynasm.jitstats
  • pyre/bench/synth/const_arg_call_resume.wasm.jitstats
  • pyre/bench/synth/context_manager.cranelift.jitstats
  • pyre/bench/synth/context_manager.dynasm.jitstats
  • pyre/bench/synth/context_manager.wasm.jitstats
  • pyre/bench/synth/defaults_reassigned_midloop.cranelift.jitstats
  • pyre/bench/synth/defaults_reassigned_midloop.dynasm.jitstats
  • pyre/bench/synth/defaults_reassigned_midloop.py
  • pyre/bench/synth/defaults_reassigned_midloop.wasm.jitstats
  • pyre/bench/synth/del_cellvar_walk_commit.cranelift.jitstats
  • pyre/bench/synth/del_cellvar_walk_commit.dynasm.jitstats
  • pyre/bench/synth/del_cellvar_walk_commit.wasm.jitstats
  • pyre/bench/synth/delete_negative_open_slice_hot.cranelift.jitstats
  • pyre/bench/synth/delete_negative_open_slice_hot.dynasm.jitstats
  • pyre/bench/synth/delete_negative_open_slice_hot.py
  • pyre/bench/synth/delete_negative_open_slice_hot.wasm.jitstats
  • pyre/bench/synth/dict_ctor_consume.cranelift.jitstats
  • pyre/bench/synth/dict_ctor_consume.dynasm.jitstats
  • pyre/bench/synth/dict_ctor_consume.wasm.jitstats
  • pyre/bench/synth/dict_hash_protocol.cranelift.jitstats
  • pyre/bench/synth/dict_hash_protocol.dynasm.jitstats
  • pyre/bench/synth/dict_hash_protocol.wasm.jitstats
  • pyre/bench/synth/dict_set.cranelift.jitstats
  • pyre/bench/synth/dict_set.dynasm.jitstats
  • pyre/bench/synth/dict_set.wasm.jitstats
  • pyre/bench/synth/dict_set_key_eq_operand_order.cranelift.jitstats
  • pyre/bench/synth/dict_set_key_eq_operand_order.dynasm.jitstats
  • pyre/bench/synth/dict_set_key_eq_operand_order.wasm.jitstats
  • pyre/bench/synth/dict_update_hot.cranelift.jitstats
  • pyre/bench/synth/dict_update_hot.dynasm.jitstats
  • pyre/bench/synth/dict_update_hot.wasm.jitstats
  • pyre/bench/synth/dict_update_source_mutation.cranelift.jitstats
  • pyre/bench/synth/dict_update_source_mutation.dynasm.jitstats
  • pyre/bench/synth/dict_update_source_mutation.py
  • pyre/bench/synth/dict_update_source_mutation.wasm.jitstats
  • pyre/bench/synth/dict_view_set_ops.cranelift.jitstats
  • pyre/bench/synth/dict_view_set_ops.dynasm.jitstats
  • pyre/bench/synth/dict_view_set_ops.wasm.jitstats
  • pyre/bench/synth/dir_custom.cranelift.jitstats
  • pyre/bench/synth/dir_custom.dynasm.jitstats
  • pyre/bench/synth/dir_custom.py
  • pyre/bench/synth/dir_custom.wasm.jitstats
  • pyre/bench/synth/dir_dict_class_attrs.cranelift.jitstats
  • pyre/bench/synth/dir_dict_class_attrs.dynasm.jitstats
  • pyre/bench/synth/dir_dict_class_attrs.py
  • pyre/bench/synth/dir_dict_class_attrs.wasm.jitstats
  • pyre/bench/synth/dir_full_mro.cranelift.jitstats
  • pyre/bench/synth/dir_full_mro.dynasm.jitstats
  • pyre/bench/synth/dir_full_mro.py
  • pyre/bench/synth/dir_full_mro.wasm.jitstats
  • pyre/bench/synth/divmod_long_int_pair.cranelift.jitstats
  • pyre/bench/synth/divmod_long_int_pair.dynasm.jitstats
  • pyre/bench/synth/divmod_long_int_pair.wasm.jitstats
  • pyre/bench/synth/dunder_repr_str_errors.cranelift.jitstats
  • pyre/bench/synth/dunder_repr_str_errors.dynasm.jitstats
  • pyre/bench/synth/dunder_repr_str_errors.py
  • pyre/bench/synth/dunder_repr_str_errors.wasm.jitstats
  • pyre/bench/synth/enumerate_bignum_start.cranelift.jitstats
  • pyre/bench/synth/enumerate_bignum_start.dynasm.jitstats
  • pyre/bench/synth/enumerate_bignum_start.py
  • pyre/bench/synth/enumerate_bignum_start.wasm.jitstats
  • pyre/bench/synth/exc_caught_in_callee_return_loop.cranelift.jitstats
  • pyre/bench/synth/exc_caught_in_callee_return_loop.dynasm.jitstats
  • pyre/bench/synth/exc_caught_in_callee_return_loop.wasm.jitstats
  • pyre/bench/synth/exc_in_loop_divzero_continue.cranelift.jitstats
  • pyre/bench/synth/exc_in_loop_divzero_continue.dynasm.jitstats
  • pyre/bench/synth/exc_in_loop_divzero_continue.py
  • pyre/bench/synth/exc_in_loop_divzero_continue.wasm.jitstats
  • pyre/bench/synth/exc_info_module_loop_hot.cranelift.jitstats
  • pyre/bench/synth/exc_info_module_loop_hot.dynasm.jitstats
  • pyre/bench/synth/exc_info_module_loop_hot.wasm.jitstats
  • pyre/bench/synth/exc_mixed_classes_bridge_flavor.cranelift.jitstats
  • pyre/bench/synth/exc_mixed_classes_bridge_flavor.dynasm.jitstats
  • pyre/bench/synth/exc_mixed_classes_bridge_flavor.wasm.jitstats
  • pyre/bench/synth/except_star.cranelift.jitstats
  • pyre/bench/synth/except_star.dynasm.jitstats
  • pyre/bench/synth/except_star.py
  • pyre/bench/synth/except_star.wasm.jitstats
  • pyre/bench/synth/except_tuple_clause_hot.cranelift.jitstats
  • pyre/bench/synth/except_tuple_clause_hot.dynasm.jitstats
  • pyre/bench/synth/except_tuple_clause_hot.wasm.jitstats
  • pyre/bench/synth/exception_args_virtual.cranelift.jitstats
  • pyre/bench/synth/exception_args_virtual.dynasm.jitstats
  • pyre/bench/synth/exception_args_virtual.wasm.jitstats
  • pyre/bench/synth/exception_as_cell_cleanup.cranelift.jitstats
  • pyre/bench/synth/exception_as_cell_cleanup.dynasm.jitstats
  • pyre/bench/synth/exception_as_cell_cleanup.wasm.jitstats
  • pyre/bench/synth/exception_bare_reraise_nested_outer.cranelift.jitstats
  • pyre/bench/synth/exception_bare_reraise_nested_outer.dynasm.jitstats
  • pyre/bench/synth/exception_bare_reraise_nested_outer.py
  • pyre/bench/synth/exception_bare_reraise_nested_outer.wasm.jitstats
  • pyre/bench/synth/exception_bare_reraise_restore.cranelift.jitstats
  • pyre/bench/synth/exception_bare_reraise_restore.dynasm.jitstats
  • pyre/bench/synth/exception_bare_reraise_restore.wasm.jitstats
  • pyre/bench/synth/exception_bridge_traceback_head.cranelift.jitstats
  • pyre/bench/synth/exception_bridge_traceback_head.dynasm.jitstats
  • pyre/bench/synth/exception_bridge_traceback_head.wasm.jitstats
  • pyre/bench/synth/exception_catching_frame_tb_node.cranelift.jitstats
  • pyre/bench/synth/exception_catching_frame_tb_node.dynasm.jitstats
  • pyre/bench/synth/exception_catching_frame_tb_node.py
  • pyre/bench/synth/exception_const_operand_resume.cranelift.jitstats
  • pyre/bench/synth/exception_const_operand_resume.dynasm.jitstats
  • pyre/bench/synth/exception_const_operand_resume.py
  • pyre/bench/synth/exception_const_operand_resume.wasm.jitstats
  • pyre/bench/synth/exception_context_chain_inhandler.cranelift.jitstats
  • pyre/bench/synth/exception_context_chain_inhandler.dynasm.jitstats
  • pyre/bench/synth/exception_context_chain_inhandler.wasm.jitstats
  • pyre/bench/synth/exception_dict_slot_reject.cranelift.jitstats
  • pyre/bench/synth/exception_dict_slot_reject.dynasm.jitstats
  • pyre/bench/synth/exception_dict_slot_reject.py
  • pyre/bench/synth/exception_dict_slot_reject.wasm.jitstats
  • pyre/bench/synth/exception_escape_caller_frame_tb_node.cranelift.jitstats
  • pyre/bench/synth/exception_escape_caller_frame_tb_node.dynasm.jitstats
  • pyre/bench/synth/exception_escape_caller_frame_tb_node.wasm.jitstats
  • pyre/bench/synth/exception_escape_inlined_midframe_tb_node.cranelift.jitstats
  • pyre/bench/synth/exception_escape_inlined_midframe_tb_node.dynasm.jitstats
  • pyre/bench/synth/exception_escape_inlined_midframe_tb_node.wasm.jitstats
  • pyre/bench/synth/exception_group_type.cranelift.jitstats
  • pyre/bench/synth/exception_group_type.dynasm.jitstats
  • pyre/bench/synth/exception_group_type.py
  • pyre/bench/synth/exception_group_type.wasm.jitstats
  • pyre/bench/synth/exception_inline_callee_tb_frame_locals.cranelift.jitstats
  • pyre/bench/synth/exception_inline_callee_tb_frame_locals.dynasm.jitstats
  • pyre/bench/synth/exception_inline_callee_tb_frame_locals.wasm.jitstats
  • pyre/bench/synth/exception_inlined_callee_caught.cranelift.jitstats
  • pyre/bench/synth/exception_inlined_callee_caught.dynasm.jitstats
  • pyre/bench/synth/exception_inlined_callee_caught.wasm.jitstats
  • pyre/bench/synth/exception_loop_warmup.cranelift.jitstats
  • pyre/bench/synth/exception_loop_warmup.dynasm.jitstats
  • pyre/bench/synth/exception_loop_warmup.wasm.jitstats
  • pyre/bench/synth/exception_metadata_hot.cranelift.jitstats
  • pyre/bench/synth/exception_metadata_hot.dynasm.jitstats
  • pyre/bench/synth/exception_metadata_hot.wasm.jitstats
  • pyre/bench/synth/exception_metadata_jitstress.cranelift.jitstats
  • pyre/bench/synth/exception_metadata_jitstress.dynasm.jitstats
  • pyre/bench/synth/exception_metadata_jitstress.wasm.jitstats
  • pyre/bench/synth/exception_multi_handler_warmup.cranelift.jitstats
  • pyre/bench/synth/exception_multi_handler_warmup.dynasm.jitstats
  • pyre/bench/synth/exception_multi_handler_warmup.wasm.jitstats
  • pyre/bench/synth/exception_nested_exc_info_restore.cranelift.jitstats
  • pyre/bench/synth/exception_nested_exc_info_restore.dynasm.jitstats
  • pyre/bench/synth/exception_nested_exc_info_restore.wasm.jitstats
  • pyre/bench/synth/exception_oserror_fields.cranelift.jitstats
  • pyre/bench/synth/exception_oserror_fields.dynasm.jitstats
  • pyre/bench/synth/exception_oserror_fields.wasm.jitstats
  • pyre/bench/synth/exception_reduce.cranelift.jitstats
  • pyre/bench/synth/exception_reduce.dynasm.jitstats
  • pyre/bench/synth/exception_reduce.py
  • pyre/bench/synth/exception_reduce.wasm.jitstats
  • pyre/bench/synth/exception_reentry_guard_finally_residual.cranelift.jitstats
  • pyre/bench/synth/exception_reentry_guard_finally_residual.dynasm.jitstats
  • pyre/bench/synth/exception_reentry_guard_finally_residual.wasm.jitstats
  • pyre/bench/synth/exception_reraise_tb_depth_hot.cranelift.jitstats
  • pyre/bench/synth/exception_reraise_tb_depth_hot.dynasm.jitstats
  • pyre/bench/synth/exception_reraise_tb_depth_hot.wasm.jitstats
  • pyre/bench/synth/exception_reraise_tb_depth_jitstress.cranelift.jitstats
  • pyre/bench/synth/exception_reraise_tb_depth_jitstress.dynasm.jitstats
  • pyre/bench/synth/exception_reraise_tb_depth_jitstress.wasm.jitstats
  • pyre/bench/synth/exception_residual_raise_caught_in_frame.cranelift.jitstats
  • pyre/bench/synth/exception_residual_raise_caught_in_frame.dynasm.jitstats
  • pyre/bench/synth/exception_reused_object_tb_not_doubled.cranelift.jitstats
  • pyre/bench/synth/exception_reused_object_tb_not_doubled.dynasm.jitstats
  • pyre/bench/synth/exception_subclass_attrs.cranelift.jitstats
  • pyre/bench/synth/exception_subclass_attrs.dynasm.jitstats
  • pyre/bench/synth/exception_subclass_attrs.py
  • pyre/bench/synth/exception_subclass_attrs.wasm.jitstats
  • pyre/bench/synth/exception_traceback_loop_forms.cranelift.jitstats
  • pyre/bench/synth/exception_traceback_loop_forms.dynasm.jitstats
  • pyre/bench/synth/exception_traceback_loop_forms.wasm.jitstats
  • pyre/bench/synth/exception_try_call_inlined_callee_raise.cranelift.jitstats
  • pyre/bench/synth/exception_try_call_inlined_callee_raise.dynasm.jitstats
  • pyre/bench/synth/exception_try_call_inlined_callee_raise.wasm.jitstats
  • pyre/bench/synth/exception_vable_frame_virtual_local.cranelift.jitstats
  • pyre/bench/synth/exception_vable_frame_virtual_local.dynasm.jitstats
  • pyre/bench/synth/exception_vable_frame_virtual_local.wasm.jitstats
  • pyre/bench/synth/exception_value_op_caught.cranelift.jitstats
  • pyre/bench/synth/exception_value_op_caught.dynasm.jitstats
  • pyre/bench/synth/exception_value_op_caught.wasm.jitstats
  • pyre/bench/synth/exceptions.cranelift.jitstats
  • pyre/bench/synth/exceptions.dynasm.jitstats
  • pyre/bench/synth/exceptions.py
  • pyre/bench/synth/exceptions.wasm.jitstats
  • pyre/bench/synth/exec_defined_global_read.cranelift.jitstats
  • pyre/bench/synth/exec_defined_global_read.dynasm.jitstats
  • pyre/bench/synth/exec_defined_global_read.wasm.jitstats
  • pyre/bench/synth/exec_fresh_globals_delete_name.cranelift.jitstats
  • pyre/bench/synth/exec_fresh_globals_delete_name.dynasm.jitstats
  • pyre/bench/synth/exec_fresh_globals_delete_name.wasm.jitstats
  • pyre/bench/synth/fast_local_swap.cranelift.jitstats
  • pyre/bench/synth/fast_local_swap.dynasm.jitstats
  • pyre/bench/synth/fast_local_swap.py
  • pyre/bench/synth/fast_local_swap.wasm.jitstats
  • pyre/bench/synth/finally_bare_raise.cranelift.jitstats
  • pyre/bench/synth/finally_bare_raise.dynasm.jitstats
  • pyre/bench/synth/finally_bare_raise.wasm.jitstats
  • pyre/bench/synth/float_builtin_hot.cranelift.jitstats
  • pyre/bench/synth/float_builtin_hot.dynasm.jitstats
  • pyre/bench/synth/float_builtin_hot.py
  • pyre/bench/synth/float_builtin_hot.wasm.jitstats
  • pyre/bench/synth/float_div_zero_caught_loop.cranelift.jitstats
  • pyre/bench/synth/float_div_zero_caught_loop.dynasm.jitstats
  • pyre/bench/synth/float_div_zero_caught_loop.wasm.jitstats
  • pyre/bench/synth/float_pow_overflow_exp.cranelift.jitstats
  • pyre/bench/synth/float_pow_overflow_exp.dynasm.jitstats
  • pyre/bench/synth/float_pow_overflow_exp.wasm.jitstats
  • pyre/bench/synth/float_subclass_binop_dispatch.cranelift.jitstats
  • pyre/bench/synth/float_subclass_binop_dispatch.dynasm.jitstats
  • pyre/bench/synth/float_subclass_binop_dispatch.wasm.jitstats
  • pyre/bench/synth/for_iter_conditional_store_bridge.cranelift.jitstats
  • pyre/bench/synth/for_iter_conditional_store_bridge.dynasm.jitstats
  • pyre/bench/synth/for_iter_conditional_store_bridge.wasm.jitstats
  • pyre/bench/synth/for_iter_select_receiver_swap.cranelift.jitstats
  • pyre/bench/synth/for_iter_select_receiver_swap.dynasm.jitstats
  • pyre/bench/synth/for_iter_select_receiver_swap.py
  • pyre/bench/synth/for_iter_select_receiver_swap.wasm.jitstats
  • pyre/bench/synth/foriter_body_return.cranelift.jitstats
  • pyre/bench/synth/foriter_body_return.dynasm.jitstats
  • pyre/bench/synth/foriter_body_return.wasm.jitstats
  • pyre/bench/synth/foriter_call_body.cranelift.jitstats
  • pyre/bench/synth/foriter_call_body.dynasm.jitstats
  • pyre/bench/synth/foriter_call_body.wasm.jitstats
  • pyre/bench/synth/foriter_call_resume_drops_iteration.cranelift.jitstats
  • pyre/bench/synth/foriter_call_resume_drops_iteration.dynasm.jitstats
  • pyre/bench/synth/foriter_exempt_nested_foriter.cranelift.jitstats
  • pyre/bench/synth/foriter_exempt_nested_foriter.dynasm.jitstats
  • pyre/bench/synth/foriter_exempt_nested_foriter.wasm.jitstats
  • pyre/bench/synth/foriter_exempt_shared_generator.cranelift.jitstats
  • pyre/bench/synth/foriter_exempt_shared_generator.dynasm.jitstats
  • pyre/bench/synth/foriter_exempt_shared_generator.wasm.jitstats
  • pyre/bench/synth/foriter_in_while.cranelift.jitstats
  • pyre/bench/synth/foriter_in_while.dynasm.jitstats
  • pyre/bench/synth/foriter_in_while.wasm.jitstats
  • pyre/bench/synth/foriter_inplace_immutable.cranelift.jitstats
  • pyre/bench/synth/foriter_inplace_immutable.dynasm.jitstats
  • pyre/bench/synth/foriter_inplace_immutable.wasm.jitstats
  • pyre/bench/synth/foriter_loadglobal_body.cranelift.jitstats
  • pyre/bench/synth/foriter_loadglobal_body.dynasm.jitstats
  • pyre/bench/synth/foriter_loadglobal_body.wasm.jitstats
  • pyre/bench/synth/foriter_user_iter_kept_stack.cranelift.jitstats
  • pyre/bench/synth/foriter_user_iter_kept_stack.dynasm.jitstats
  • pyre/bench/synth/foriter_user_iter_kept_stack.wasm.jitstats
  • pyre/bench/synth/format_z_negative_zero.cranelift.jitstats
  • pyre/bench/synth/format_z_negative_zero.dynasm.jitstats
  • pyre/bench/synth/format_z_negative_zero.py
  • pyre/bench/synth/format_z_negative_zero.wasm.jitstats
  • pyre/bench/synth/gc_bug_bridge_flavor_traceback_names.cranelift.jitstats
  • pyre/bench/synth/gc_bug_bridge_flavor_traceback_names.dynasm.jitstats
  • pyre/bench/synth/gc_deque_backing_list.cranelift.jitstats
  • pyre/bench/synth/gc_deque_backing_list.dynasm.jitstats
  • pyre/bench/synth/gc_deque_backing_list.wasm.jitstats
  • pyre/bench/synth/gc_iterator_source_drop.cranelift.jitstats
  • pyre/bench/synth/gc_iterator_source_drop.dynasm.jitstats
  • pyre/bench/synth/gc_iterator_source_drop.wasm.jitstats
  • pyre/bench/synth/generator_pep479.cranelift.jitstats
  • pyre/bench/synth/generator_pep479.dynasm.jitstats
  • pyre/bench/synth/generator_pep479.wasm.jitstats
  • pyre/bench/synth/generator_tree_recursion.cranelift.jitstats
  • pyre/bench/synth/generator_tree_recursion.dynasm.jitstats
  • pyre/bench/synth/generator_tree_recursion.wasm.jitstats
  • pyre/bench/synth/getattr_attribute_fallbacks.cranelift.jitstats
  • pyre/bench/synth/getattr_attribute_fallbacks.dynasm.jitstats
  • pyre/bench/synth/getattr_attribute_fallbacks.py
  • pyre/bench/synth/getattr_attribute_fallbacks.wasm.jitstats
  • pyre/bench/synth/getattr_hook_binding.cranelift.jitstats
  • pyre/bench/synth/getattr_hook_binding.dynasm.jitstats
  • pyre/bench/synth/getattr_hook_binding.wasm.jitstats
  • pyre/bench/synth/getattr_surrogate_hook.cranelift.jitstats
  • pyre/bench/synth/getattr_surrogate_hook.dynasm.jitstats
  • pyre/bench/synth/getattr_surrogate_hook.py
  • pyre/bench/synth/getattr_surrogate_hook.wasm.jitstats
  • pyre/bench/synth/getattribute_intercepts_dunder.cranelift.jitstats
  • pyre/bench/synth/getattribute_intercepts_dunder.dynasm.jitstats
  • pyre/bench/synth/getattribute_intercepts_dunder.py
  • pyre/bench/synth/getattribute_intercepts_dunder.wasm.jitstats
  • pyre/bench/synth/getattribute_override_no_bind.cranelift.jitstats
  • pyre/bench/synth/getattribute_override_no_bind.dynasm.jitstats
  • pyre/bench/synth/getframe_caller_locals_nested_compiled_callee.cranelift.jitstats
  • pyre/bench/synth/getframe_caller_locals_nested_compiled_callee.dynasm.jitstats
  • pyre/bench/synth/getframe_force_cancel_journal.cranelift.jitstats
  • pyre/bench/synth/getframe_force_cancel_journal.dynasm.jitstats
  • pyre/bench/synth/getframe_force_cancel_journal.py
  • pyre/bench/synth/getframe_force_cancel_journal.wasm.jitstats
  • pyre/bench/synth/getframe_inline_subwalk_multiframe.cranelift.jitstats
  • pyre/bench/synth/getframe_inline_subwalk_multiframe.dynasm.jitstats
  • pyre/bench/synth/getframe_inline_subwalk_multiframe.py
  • pyre/bench/synth/getframe_inline_subwalk_multiframe.wasm.jitstats
  • pyre/bench/synth/getframe_inlined_callee_own_frame.py
  • pyre/bench/synth/getframe_stored_fback_walk.py
  • pyre/bench/synth/getframe_while_caller_locals_across_subwalk.py
  • pyre/bench/synth/getframe_while_captured_frame_outlives_call.py
  • pyre/bench/synth/getframe_while_escaping_read_frame_identity.py
  • pyre/bench/synth/getframe_while_inlined_callee_subwalk.py
  • pyre/bench/synth/getframe_while_subwalk_decline_shapes.py
  • pyre/bench/synth/global_cell_shortpreamble_hot.cranelift.jitstats
  • pyre/bench/synth/global_cell_shortpreamble_hot.dynasm.jitstats
  • pyre/bench/synth/global_cell_shortpreamble_hot.py
  • pyre/bench/synth/global_cell_shortpreamble_hot.wasm.jitstats
  • pyre/bench/synth/global_quasiimmut_invalidation.cranelift.jitstats
  • pyre/bench/synth/global_quasiimmut_invalidation.dynasm.jitstats
  • pyre/bench/synth/global_quasiimmut_invalidation.py
  • pyre/bench/synth/global_quasiimmut_invalidation.wasm.jitstats
  • pyre/bench/synth/global_reassign.cranelift.jitstats
  • pyre/bench/synth/global_reassign.dynasm.jitstats
  • pyre/bench/synth/global_reassign.py
  • pyre/bench/synth/global_reassign.wasm.jitstats
  • pyre/bench/synth/global_reassign_invalidation.cranelift.jitstats
  • pyre/bench/synth/global_reassign_invalidation.dynasm.jitstats
  • pyre/bench/synth/global_reassign_invalidation.wasm.jitstats
  • pyre/bench/synth/global_store_plain_dict_globals.cranelift.jitstats
  • pyre/bench/synth/global_store_plain_dict_globals.dynasm.jitstats
  • pyre/bench/synth/global_store_plain_dict_globals.wasm.jitstats
  • pyre/bench/synth/goto_if_not_same_box.cranelift.jitstats
  • pyre/bench/synth/goto_if_not_same_box.dynasm.jitstats
  • pyre/bench/synth/goto_if_not_same_box.py
  • pyre/bench/synth/goto_if_not_same_box.wasm.jitstats
  • pyre/bench/synth/handler_reraise_second_exc.cranelift.jitstats
  • pyre/bench/synth/handler_reraise_second_exc.dynasm.jitstats
  • pyre/bench/synth/handler_reraise_second_exc.wasm.jitstats
  • pyre/bench/synth/hash_subclass_disabled.cranelift.jitstats
  • pyre/bench/synth/hash_subclass_disabled.dynasm.jitstats
  • pyre/bench/synth/hash_subclass_disabled.wasm.jitstats
  • pyre/bench/synth/hot_loop_exit_then_class_stmt.cranelift.jitstats
  • pyre/bench/synth/hot_loop_exit_then_class_stmt.dynasm.jitstats
  • pyre/bench/synth/hot_loop_exit_then_class_stmt.wasm.jitstats
  • pyre/bench/synth/if_else_jump_forward.cranelift.jitstats
  • pyre/bench/synth/if_else_jump_forward.dynasm.jitstats
  • pyre/bench/synth/if_else_jump_forward.py
  • pyre/bench/synth/if_else_jump_forward.wasm.jitstats
  • pyre/bench/synth/imp_lock_rlock_semantics.cranelift.jitstats
  • pyre/bench/synth/imp_lock_rlock_semantics.dynasm.jitstats
  • pyre/bench/synth/imp_lock_rlock_semantics.wasm.jitstats
  • pyre/bench/synth/import_from_hot.cranelift.jitstats
  • pyre/bench/synth/import_from_hot.dynasm.jitstats
  • pyre/bench/synth/import_from_hot.wasm.jitstats
  • pyre/bench/synth/import_from_name_path.cranelift.jitstats
  • pyre/bench/synth/import_from_name_path.dynasm.jitstats
  • pyre/bench/synth/import_from_name_path.py
  • pyre/bench/synth/import_from_name_path.wasm.jitstats
  • pyre/bench/synth/import_math.cranelift.jitstats
  • pyre/bench/synth/import_math.dynasm.jitstats
  • pyre/bench/synth/import_math.py
  • pyre/bench/synth/import_math.wasm.jitstats
  • pyre/bench/synth/import_name.cranelift.jitstats
  • pyre/bench/synth/import_name.dynasm.jitstats
  • pyre/bench/synth/import_name.wasm.jitstats
  • pyre/bench/synth/import_none_sentinel.cranelift.jitstats
  • pyre/bench/synth/import_none_sentinel.dynasm.jitstats
  • pyre/bench/synth/import_none_sentinel.py
  • pyre/bench/synth/import_none_sentinel.wasm.jitstats
  • pyre/bench/synth/inheritance_dispatch.cranelift.jitstats
  • pyre/bench/synth/inheritance_dispatch.dynasm.jitstats
  • pyre/bench/synth/inheritance_dispatch.py
  • pyre/bench/synth/inheritance_dispatch.wasm.jitstats
  • pyre/bench/synth/inline_bignum_bridge_twoclamp.cranelift.jitstats
  • pyre/bench/synth/inline_bignum_bridge_twoclamp.dynasm.jitstats
  • pyre/bench/synth/inline_bignum_bridge_twoclamp.wasm.jitstats
  • pyre/bench/synth/inline_callee_constructs_object.cranelift.jitstats
  • pyre/bench/synth/inline_callee_constructs_object.dynasm.jitstats
  • pyre/bench/synth/inline_callee_constructs_object.wasm.jitstats
  • pyre/bench/synth/inline_chain_depth_typeflip.cranelift.jitstats
  • pyre/bench/synth/inline_chain_depth_typeflip.dynasm.jitstats
  • pyre/bench/synth/inline_chain_depth_typeflip.wasm.jitstats
  • pyre/bench/synth/inline_freevar_after_mayforce.cranelift.jitstats
  • pyre/bench/synth/inline_freevar_after_mayforce.dynasm.jitstats
  • pyre/bench/synth/inline_freevar_after_mayforce.py
  • pyre/bench/synth/inline_freevar_after_mayforce.wasm.jitstats
  • pyre/bench/synth/inline_gate_operand_provenance.cranelift.jitstats
  • pyre/bench/synth/inline_gate_operand_provenance.dynasm.jitstats
  • pyre/bench/synth/inline_gate_operand_provenance.wasm.jitstats
  • pyre/bench/synth/inline_multiframe_branchy_carrier.cranelift.jitstats
  • pyre/bench/synth/inline_multiframe_branchy_carrier.dynasm.jitstats
  • pyre/bench/synth/inline_multiframe_branchy_carrier.py
  • pyre/bench/synth/inline_multiframe_branchy_carrier.wasm.jitstats
  • pyre/bench/synth/inline_subwalk_mutating_residual.cranelift.jitstats
  • pyre/bench/synth/inline_subwalk_mutating_residual.dynasm.jitstats
  • pyre/bench/synth/inline_subwalk_mutating_residual.py
  • pyre/bench/synth/inline_subwalk_mutating_residual.wasm.jitstats
  • pyre/bench/synth/inline_subwalk_property_mutates.cranelift.jitstats
  • pyre/bench/synth/inline_subwalk_property_mutates.dynasm.jitstats
  • pyre/bench/synth/inline_subwalk_property_mutates.wasm.jitstats
  • pyre/bench/synth/inline_subwalk_radd_consumed.cranelift.jitstats
  • pyre/bench/synth/inline_subwalk_radd_consumed.dynasm.jitstats
  • pyre/bench/synth/inline_subwalk_radd_consumed.wasm.jitstats
  • pyre/bench/synth/inline_subwalk_user_iterator.cranelift.jitstats
  • pyre/bench/synth/inline_subwalk_user_iterator.dynasm.jitstats
  • pyre/bench/synth/inline_subwalk_user_iterator.wasm.jitstats
  • pyre/bench/synth/inlined_callee_extended_arg_handler.cranelift.jitstats
  • pyre/bench/synth/inlined_callee_extended_arg_handler.dynasm.jitstats
  • pyre/bench/synth/inlined_callee_extended_arg_handler.wasm.jitstats
  • pyre/bench/synth/inlined_helper_arith_hot.cranelift.jitstats
  • pyre/bench/synth/inlined_helper_arith_hot.dynasm.jitstats
  • pyre/bench/synth/inlined_helper_arith_hot.wasm.jitstats
  • pyre/bench/synth/inlined_helper_mutation.cranelift.jitstats
  • pyre/bench/synth/inlined_helper_mutation.dynasm.jitstats
  • pyre/bench/synth/inlined_helper_mutation.py
  • pyre/bench/synth/inlined_helper_mutation.wasm.jitstats
  • pyre/bench/synth/instance_dict_reassign.cranelift.jitstats
  • pyre/bench/synth/instance_dict_reassign.dynasm.jitstats
  • pyre/bench/synth/instance_dict_reassign.py
  • pyre/bench/synth/instance_dict_reassign.wasm.jitstats
  • pyre/bench/synth/instance_surrogate_attrs.cranelift.jitstats
  • pyre/bench/synth/instance_surrogate_attrs.dynasm.jitstats
  • pyre/bench/synth/instance_surrogate_attrs.wasm.jitstats
  • pyre/bench/synth/int_base0_error_literal.cranelift.jitstats
  • pyre/bench/synth/int_base0_error_literal.dynasm.jitstats
  • pyre/bench/synth/int_base0_error_literal.py
  • pyre/bench/synth/int_base0_error_literal.wasm.jitstats
  • pyre/bench/synth/int_from_bad_dunder.cranelift.jitstats
  • pyre/bench/synth/int_from_bad_dunder.dynasm.jitstats
  • pyre/bench/synth/int_from_bad_dunder.wasm.jitstats
  • pyre/bench/synth/int_lshift_memoryerror.cranelift.jitstats
  • pyre/bench/synth/int_lshift_memoryerror.dynasm.jitstats
  • pyre/bench/synth/int_lshift_memoryerror.wasm.jitstats
  • pyre/bench/synth/int_max_str_digits.cranelift.jitstats
  • pyre/bench/synth/int_max_str_digits.dynasm.jitstats
  • pyre/bench/synth/int_max_str_digits.py
  • pyre/bench/synth/int_max_str_digits.wasm.jitstats
  • pyre/bench/synth/int_mul_ovf_bignum_promote.cranelift.jitstats
  • pyre/bench/synth/int_mul_ovf_bignum_promote.dynasm.jitstats
  • pyre/bench/synth/int_mul_ovf_bignum_promote.wasm.jitstats
  • pyre/bench/synth/is_op_identity.cranelift.jitstats
  • pyre/bench/synth/is_op_identity.dynasm.jitstats
  • pyre/bench/synth/is_op_identity.wasm.jitstats
  • pyre/bench/synth/iter_sentinel_stopiteration.cranelift.jitstats
  • pyre/bench/synth/iter_sentinel_stopiteration.dynasm.jitstats
  • pyre/bench/synth/iter_sentinel_stopiteration.py
  • pyre/bench/synth/iter_sentinel_stopiteration.wasm.jitstats
  • pyre/bench/synth/iteration_protocol.cranelift.jitstats
  • pyre/bench/synth/iteration_protocol.dynasm.jitstats
  • pyre/bench/synth/iteration_protocol.wasm.jitstats
  • pyre/bench/synth/itertools_cycle.cranelift.jitstats
  • pyre/bench/synth/itertools_cycle.dynasm.jitstats
  • pyre/bench/synth/itertools_cycle.py
  • pyre/bench/synth/itertools_cycle.wasm.jitstats
  • pyre/bench/synth/jit_callee_raised_exc_value.cranelift.jitstats
  • pyre/bench/synth/jit_callee_raised_exc_value.dynasm.jitstats
  • pyre/bench/synth/jit_callee_raised_exc_value.wasm.jitstats
  • pyre/bench/synth/jit_reg_const_pool_256_slot_decline.cranelift.jitstats
  • pyre/bench/synth/jit_reg_const_pool_256_slot_decline.dynasm.jitstats
  • pyre/bench/synth/jit_reg_const_pool_256_slot_decline.wasm.jitstats
  • pyre/bench/synth/kept_stack_aliased_swap_boxed.cranelift.jitstats
  • pyre/bench/synth/kept_stack_aliased_swap_boxed.dynasm.jitstats
  • pyre/bench/synth/kept_stack_aliased_swap_boxed.py
  • pyre/bench/synth/kept_stack_aliased_swap_boxed.wasm.jitstats
  • pyre/bench/synth/kept_stack_boxed_in_handler.cranelift.jitstats
  • pyre/bench/synth/kept_stack_boxed_in_handler.dynasm.jitstats
  • pyre/bench/synth/kept_stack_boxed_in_handler.py
  • pyre/bench/synth/kept_stack_boxed_in_handler.wasm.jitstats
  • pyre/bench/synth/kept_stack_branch_depths.cranelift.jitstats
  • pyre/bench/synth/kept_stack_branch_depths.dynasm.jitstats
  • pyre/bench/synth/kept_stack_branch_depths.wasm.jitstats
  • pyre/bench/synth/kept_stack_deep_var_condexpr.cranelift.jitstats
  • pyre/bench/synth/kept_stack_deep_var_condexpr.dynasm.jitstats
  • pyre/bench/synth/kept_stack_deep_var_condexpr.wasm.jitstats
  • pyre/bench/synth/kept_stack_deep_var_nested_call.cranelift.jitstats
  • pyre/bench/synth/kept_stack_deep_var_nested_call.dynasm.jitstats
  • pyre/bench/synth/kept_stack_deep_var_nested_call.py
  • pyre/bench/synth/kept_stack_deep_var_nested_call.wasm.jitstats
  • pyre/bench/synth/kept_stack_deep_var_shortcircuit.cranelift.jitstats
  • pyre/bench/synth/kept_stack_deep_var_shortcircuit.dynasm.jitstats
  • pyre/bench/synth/kept_stack_deep_var_shortcircuit.wasm.jitstats
  • pyre/bench/synth/kept_stack_depth_gt1.cranelift.jitstats
  • pyre/bench/synth/kept_stack_depth_gt1.dynasm.jitstats
  • pyre/bench/synth/kept_stack_depth_gt1.py
  • pyre/bench/synth/kept_stack_depth_gt1.wasm.jitstats
  • pyre/bench/synth/kept_stack_depth_gt1_heap.cranelift.jitstats
  • pyre/bench/synth/kept_stack_depth_gt1_heap.dynasm.jitstats
  • pyre/bench/synth/kept_stack_depth_gt1_heap.py
  • pyre/bench/synth/kept_stack_depth_gt1_heap.wasm.jitstats
  • pyre/bench/synth/key_eq_resize_restart.cranelift.jitstats
  • pyre/bench/synth/key_eq_resize_restart.dynasm.jitstats
  • pyre/bench/synth/key_eq_resize_restart.wasm.jitstats
  • pyre/bench/synth/key_eq_restart_forgets.cranelift.jitstats
  • pyre/bench/synth/key_eq_restart_forgets.dynasm.jitstats
  • pyre/bench/synth/key_eq_restart_forgets.wasm.jitstats
  • pyre/bench/synth/kwargs_positional_only.cranelift.jitstats
  • pyre/bench/synth/kwargs_positional_only.dynasm.jitstats
  • pyre/bench/synth/kwargs_positional_only.py
  • pyre/bench/synth/kwargs_positional_only.wasm.jitstats
  • pyre/bench/synth/len_dunder_validation.cranelift.jitstats
  • pyre/bench/synth/len_dunder_validation.dynasm.jitstats
  • pyre/bench/synth/len_dunder_validation.py
  • pyre/bench/synth/len_dunder_validation.wasm.jitstats
  • pyre/bench/synth/list_append_funcentry_helper.cranelift.jitstats
  • pyre/bench/synth/list_append_funcentry_helper.dynasm.jitstats
  • pyre/bench/synth/list_append_funcentry_helper.py
  • pyre/bench/synth/list_append_funcentry_helper.wasm.jitstats
  • pyre/bench/synth/list_append_virtual_payload.cranelift.jitstats
  • pyre/bench/synth/list_append_virtual_payload.dynasm.jitstats
  • pyre/bench/synth/list_append_virtual_payload.wasm.jitstats
  • pyre/bench/synth/list_bound_method_mutation.cranelift.jitstats
  • pyre/bench/synth/list_bound_method_mutation.dynasm.jitstats
  • pyre/bench/synth/list_bound_method_mutation.wasm.jitstats
  • pyre/bench/synth/list_error_parity.cranelift.jitstats
  • pyre/bench/synth/list_error_parity.dynasm.jitstats
  • pyre/bench/synth/list_error_parity.wasm.jitstats
  • pyre/bench/synth/list_inplace_mul_parity.cranelift.jitstats
  • pyre/bench/synth/list_inplace_mul_parity.dynasm.jitstats
  • pyre/bench/synth/list_inplace_mul_parity.wasm.jitstats
  • pyre/bench/synth/list_insert.cranelift.jitstats
  • pyre/bench/synth/list_insert.dynasm.jitstats
  • pyre/bench/synth/list_insert.wasm.jitstats
  • pyre/bench/synth/list_insert_pop_index.cranelift.jitstats
  • pyre/bench/synth/list_insert_pop_index.dynasm.jitstats
  • pyre/bench/synth/list_insert_pop_index.wasm.jitstats
  • pyre/bench/synth/list_length_hint_validate.cranelift.jitstats
  • pyre/bench/synth/list_length_hint_validate.dynasm.jitstats
  • pyre/bench/synth/list_length_hint_validate.wasm.jitstats
  • pyre/bench/synth/list_nan_identity.cranelift.jitstats
  • pyre/bench/synth/list_nan_identity.dynasm.jitstats
  • pyre/bench/synth/list_nan_identity.wasm.jitstats
  • pyre/bench/synth/list_ops.cranelift.jitstats
  • pyre/bench/synth/list_ops.dynasm.jitstats
  • pyre/bench/synth/list_ops.wasm.jitstats
  • pyre/bench/synth/list_pop_append.cranelift.jitstats
  • pyre/bench/synth/list_pop_append.dynasm.jitstats
  • pyre/bench/synth/list_pop_append.py
  • pyre/bench/synth/list_pop_append.wasm.jitstats
  • pyre/bench/synth/list_reverse.cranelift.jitstats
  • pyre/bench/synth/list_reverse.dynasm.jitstats
  • pyre/bench/synth/list_reverse.wasm.jitstats
  • pyre/bench/synth/list_setslice.cranelift.jitstats
  • pyre/bench/synth/list_setslice.dynasm.jitstats
  • pyre/bench/synth/list_setslice.py
  • pyre/bench/synth/list_setslice.wasm.jitstats
  • pyre/bench/synth/list_subscript_index.cranelift.jitstats
  • pyre/bench/synth/list_subscript_index.dynasm.jitstats
  • pyre/bench/synth/list_subscript_index.wasm.jitstats
  • pyre/bench/synth/list_to_tuple_star.cranelift.jitstats
  • pyre/bench/synth/list_to_tuple_star.dynasm.jitstats
  • pyre/bench/synth/list_to_tuple_star.py
  • pyre/bench/synth/list_to_tuple_star.wasm.jitstats
  • pyre/bench/synth/listcomp_hot.cranelift.jitstats
  • pyre/bench/synth/listcomp_hot.dynasm.jitstats
  • pyre/bench/synth/listcomp_hot.wasm.jitstats
  • pyre/bench/synth/load_attr_blackhole_resume.cranelift.jitstats
  • pyre/bench/synth/load_attr_blackhole_resume.dynasm.jitstats
  • pyre/bench/synth/load_attr_blackhole_resume.wasm.jitstats
  • pyre/bench/synth/load_fast_check.cranelift.jitstats
  • pyre/bench/synth/load_fast_check.dynasm.jitstats
  • pyre/bench/synth/load_fast_check.py
  • pyre/bench/synth/load_fast_check.wasm.jitstats
  • pyre/bench/synth/load_super_attr.cranelift.jitstats
  • pyre/bench/synth/load_super_attr.dynasm.jitstats
  • pyre/bench/synth/load_super_attr.wasm.jitstats
  • pyre/bench/synth/locals_forced_frame.cranelift.jitstats
  • pyre/bench/synth/locals_forced_frame.dynasm.jitstats
  • pyre/bench/synth/locals_forced_frame.wasm.jitstats
  • pyre/bench/synth/loop_callee_return.cranelift.jitstats
  • pyre/bench/synth/loop_callee_return.dynasm.jitstats
  • pyre/bench/synth/loop_callee_return.py
  • pyre/bench/synth/loop_callee_return.wasm.jitstats
  • pyre/bench/synth/loop_callee_shared_mutation.cranelift.jitstats
  • pyre/bench/synth/loop_callee_shared_mutation.dynasm.jitstats
  • pyre/bench/synth/loop_callee_shared_mutation.py
  • pyre/bench/synth/loop_callee_shared_mutation.wasm.jitstats
  • pyre/bench/synth/loop_exit_empty_dict_local_clobber.cranelift.jitstats
  • pyre/bench/synth/loop_exit_empty_dict_local_clobber.dynasm.jitstats
  • pyre/bench/synth/loop_exit_empty_dict_local_clobber.py
  • pyre/bench/synth/loop_exit_empty_dict_local_clobber.wasm.jitstats
  • pyre/bench/synth/loop_in_try_raise_into_handler.cranelift.jitstats
  • pyre/bench/synth/loop_in_try_raise_into_handler.dynasm.jitstats
  • pyre/bench/synth/loop_in_try_raise_into_handler.py
  • pyre/bench/synth/loop_in_try_raise_into_handler.wasm.jitstats
  • pyre/bench/synth/loop_in_try_tail_raise_and_second_loop.cranelift.jitstats
  • pyre/bench/synth/loop_in_try_tail_raise_and_second_loop.dynasm.jitstats
  • pyre/bench/synth/loop_in_try_tail_raise_and_second_loop.py
  • pyre/bench/synth/loop_in_try_tail_raise_and_second_loop.wasm.jitstats
  • pyre/bench/synth/loop_in_try_tail_unbound_check.cranelift.jitstats
  • pyre/bench/synth/loop_in_try_tail_unbound_check.dynasm.jitstats
  • pyre/bench/synth/loop_in_try_tail_unbound_check.py
  • pyre/bench/synth/loop_in_try_tail_unbound_check.wasm.jitstats
  • pyre/bench/synth/loops_comprehension.cranelift.jitstats
  • pyre/bench/synth/loops_comprehension.dynasm.jitstats
  • pyre/bench/synth/loops_comprehension.wasm.jitstats
  • pyre/bench/synth/make_function_inline.cranelift.jitstats
  • pyre/bench/synth/make_function_inline.dynasm.jitstats
  • pyre/bench/synth/make_function_inline.wasm.jitstats
  • pyre/bench/synth/mapdict_frozen_unboxing_fold.cranelift.jitstats
  • pyre/bench/synth/mapdict_frozen_unboxing_fold.dynasm.jitstats
  • pyre/bench/synth/mapdict_frozen_unboxing_fold.py
  • pyre/bench/synth/mapdict_frozen_unboxing_fold.wasm.jitstats
  • pyre/bench/synth/mapdict_polymorphic_map_attr.cranelift.jitstats
  • pyre/bench/synth/mapdict_polymorphic_map_attr.dynasm.jitstats
  • pyre/bench/synth/mapdict_polymorphic_map_attr.wasm.jitstats
  • pyre/bench/synth/mapdict_unboxed_type_change_attr.cranelift.jitstats
  • pyre/bench/synth/mapdict_unboxed_type_change_attr.dynasm.jitstats
  • pyre/bench/synth/mapdict_unboxed_type_change_attr.wasm.jitstats
  • pyre/bench/synth/match_sequence_of_class_patterns.cranelift.jitstats
  • pyre/bench/synth/match_sequence_of_class_patterns.dynasm.jitstats
  • pyre/bench/synth/match_sequence_of_class_patterns.wasm.jitstats
  • pyre/bench/synth/math_isqrt_compare_bridge_resume.cranelift.jitstats
  • pyre/bench/synth/math_isqrt_compare_bridge_resume.dynasm.jitstats
  • pyre/bench/synth/math_isqrt_compare_bridge_resume.wasm.jitstats
  • pyre/bench/synth/math_log_trig_hot.cranelift.jitstats
  • pyre/bench/synth/math_log_trig_hot.dynasm.jitstats
  • pyre/bench/synth/math_log_trig_hot.py
  • pyre/bench/synth/math_log_trig_hot.wasm.jitstats
  • pyre/bench/synth/math_sqrt_hot.cranelift.jitstats
  • pyre/bench/synth/math_sqrt_hot.dynasm.jitstats
  • pyre/bench/synth/math_sqrt_hot.py
  • pyre/bench/synth/math_sqrt_hot.wasm.jitstats
  • pyre/bench/synth/metaclass_conflict.cranelift.jitstats
  • pyre/bench/synth/metaclass_conflict.dynasm.jitstats
  • pyre/bench/synth/metaclass_conflict.py
  • pyre/bench/synth/metaclass_conflict.wasm.jitstats
  • pyre/bench/synth/metaclass_getattr.cranelift.jitstats
  • pyre/bench/synth/metaclass_getattr.dynasm.jitstats
  • pyre/bench/synth/metaclass_getattr.wasm.jitstats
  • pyre/bench/synth/metaclass_getattribute_delattr.cranelift.jitstats
  • pyre/bench/synth/metaclass_getattribute_delattr.dynasm.jitstats
  • pyre/bench/synth/metaclass_getattribute_delattr.wasm.jitstats
  • pyre/bench/synth/metatype_property_dunder.cranelift.jitstats
  • pyre/bench/synth/metatype_property_dunder.dynasm.jitstats
  • pyre/bench/synth/metatype_property_dunder.py
  • pyre/bench/synth/metatype_property_dunder.wasm.jitstats
  • pyre/bench/synth/method_reassign_after_warmup.cranelift.jitstats
  • pyre/bench/synth/method_reassign_after_warmup.dynasm.jitstats
  • pyre/bench/synth/method_reassign_after_warmup.py
  • pyre/bench/synth/method_reassign_after_warmup.wasm.jitstats
  • pyre/bench/synth/minmax_key_rooting.cranelift.jitstats
  • pyre/bench/synth/minmax_key_rooting.dynasm.jitstats
  • pyre/bench/synth/minmax_key_rooting.wasm.jitstats
  • pyre/bench/synth/module_attr_message.cranelift.jitstats
  • pyre/bench/synth/module_attr_message.dynasm.jitstats
  • pyre/bench/synth/module_attr_message.py
  • pyre/bench/synth/module_attr_message.wasm.jitstats
  • pyre/bench/synth/module_body_truncated_jitcode_replay.cranelift.jitstats
  • pyre/bench/synth/module_body_truncated_jitcode_replay.dynasm.jitstats
  • pyre/bench/synth/module_body_truncated_jitcode_replay.wasm.jitstats
  • pyre/bench/synth/module_dir_dunder.cranelift.jitstats
  • pyre/bench/synth/module_dir_dunder.dynasm.jitstats
  • pyre/bench/synth/module_dir_dunder.py
  • pyre/bench/synth/module_dir_dunder.wasm.jitstats
  • pyre/bench/synth/module_function_not_descriptor.cranelift.jitstats
  • pyre/bench/synth/module_function_not_descriptor.dynasm.jitstats
  • pyre/bench/synth/module_function_not_descriptor.wasm.jitstats
  • pyre/bench/synth/module_getattr.cranelift.jitstats
  • pyre/bench/synth/module_getattr.dynasm.jitstats
  • pyre/bench/synth/module_getattr.py
  • pyre/bench/synth/module_getattr.wasm.jitstats
  • pyre/bench/synth/module_getattr_descr_error.cranelift.jitstats
  • pyre/bench/synth/module_getattr_descr_error.dynasm.jitstats
  • pyre/bench/synth/module_getattr_descr_error.wasm.jitstats
  • pyre/bench/synth/module_getattr_surrogate_cls.cranelift.jitstats
  • pyre/bench/synth/module_getattr_surrogate_cls.dynasm.jitstats
  • pyre/bench/synth/module_getattr_surrogate_cls.wasm.jitstats
  • pyre/bench/synth/mutate_then_raise_caught.cranelift.jitstats
  • pyre/bench/synth/mutate_then_raise_caught.dynasm.jitstats
  • pyre/bench/synth/mutate_then_raise_caught.wasm.jitstats
  • pyre/bench/synth/mutate_uncaught_raise_delivery.cranelift.jitstats
  • pyre/bench/synth/mutate_uncaught_raise_delivery.dynasm.jitstats
  • pyre/bench/synth/mutate_uncaught_raise_delivery.wasm.jitstats
  • pyre/bench/synth/named_reraise_sibling_hot.cranelift.jitstats
  • pyre/bench/synth/named_reraise_sibling_hot.dynasm.jitstats
  • pyre/bench/synth/named_reraise_sibling_hot.wasm.jitstats
  • pyre/bench/synth/nested_break_not_hot.cranelift.jitstats
  • pyre/bench/synth/nested_break_not_hot.dynasm.jitstats
  • pyre/bench/synth/nested_break_not_hot.py
  • pyre/bench/synth/nested_break_not_hot.wasm.jitstats
  • pyre/bench/synth/nested_callee_chain_mutation_abort.cranelift.jitstats
  • pyre/bench/synth/nested_callee_chain_mutation_abort.dynasm.jitstats
  • pyre/bench/synth/nested_callee_chain_mutation_abort.wasm.jitstats
  • pyre/bench/synth/nested_for_int_scratch_bridge.cranelift.jitstats
  • pyre/bench/synth/nested_for_int_scratch_bridge.dynasm.jitstats
  • pyre/bench/synth/nested_for_int_scratch_bridge.wasm.jitstats
  • pyre/bench/synth/nested_for_outer_local_postread.cranelift.jitstats
  • pyre/bench/synth/nested_for_outer_local_postread.dynasm.jitstats
  • pyre/bench/synth/nested_for_outer_local_postread.wasm.jitstats
  • pyre/bench/synth/nested_for_varying_trip.cranelift.jitstats
  • pyre/bench/synth/nested_for_varying_trip.dynasm.jitstats
  • pyre/bench/synth/nested_for_varying_trip.wasm.jitstats
  • pyre/bench/synth/nested_foriter_poly.cranelift.jitstats
  • pyre/bench/synth/nested_foriter_poly.dynasm.jitstats
  • pyre/bench/synth/nested_foriter_poly.wasm.jitstats
  • pyre/bench/synth/nested_list_comprehension_hot.cranelift.jitstats
  • pyre/bench/synth/nested_list_comprehension_hot.dynasm.jitstats
  • pyre/bench/synth/nested_list_comprehension_hot.wasm.jitstats
  • pyre/bench/synth/nested_loop_correctness.cranelift.jitstats
  • pyre/bench/synth/nested_loop_correctness.dynasm.jitstats
  • pyre/bench/synth/nested_loop_correctness.wasm.jitstats
  • pyre/bench/synth/nested_loop_gate_switch.cranelift.jitstats
  • pyre/bench/synth/nested_loop_gate_switch.dynasm.jitstats
  • pyre/bench/synth/nested_loop_gate_switch.wasm.jitstats
  • pyre/bench/synth/newslice_step_hot.cranelift.jitstats
  • pyre/bench/synth/newslice_step_hot.dynasm.jitstats
  • pyre/bench/synth/newslice_step_hot.wasm.jitstats
  • pyre/bench/synth/object_getattribute_no_hook.cranelift.jitstats
  • pyre/bench/synth/object_getattribute_no_hook.dynasm.jitstats
  • pyre/bench/synth/object_getattribute_no_hook.py
  • pyre/bench/synth/object_getattribute_no_hook.wasm.jitstats
  • pyre/bench/synth/operator_error_typename.cranelift.jitstats
  • pyre/bench/synth/operator_error_typename.dynasm.jitstats
  • pyre/bench/synth/operator_error_typename.py
  • pyre/bench/synth/operator_error_typename.wasm.jitstats
  • pyre/bench/synth/operator_set_inplace_ops.cranelift.jitstats
  • pyre/bench/synth/operator_set_inplace_ops.dynasm.jitstats
  • pyre/bench/synth/operator_set_inplace_ops.wasm.jitstats
  • pyre/bench/synth/or_chain_fresh_alloc_arg.cranelift.jitstats
  • pyre/bench/synth/or_chain_fresh_alloc_arg.dynasm.jitstats
  • pyre/bench/synth/or_chain_fresh_alloc_arg.wasm.jitstats
  • pyre/bench/synth/p2_local_result_bridge.cranelift.jitstats
  • pyre/bench/synth/p2_local_result_bridge.dynasm.jitstats
  • pyre/bench/synth/p2_local_result_bridge.py
  • pyre/bench/synth/p2_local_result_bridge.wasm.jitstats
  • pyre/bench/synth/pickle_ctor_args.cranelift.jitstats
  • pyre/bench/synth/pickle_ctor_args.dynasm.jitstats
  • pyre/bench/synth/pickle_ctor_args.wasm.jitstats
  • pyre/bench/synth/pickle_terminal_raise_resume.cranelift.jitstats
  • pyre/bench/synth/pickle_terminal_raise_resume.dynasm.jitstats
  • pyre/bench/synth/pickle_terminal_raise_resume.wasm.jitstats
  • pyre/bench/synth/polymorphic_binary_receiver.cranelift.jitstats
  • pyre/bench/synth/polymorphic_binary_receiver.dynasm.jitstats
  • pyre/bench/synth/polymorphic_binary_receiver.wasm.jitstats
  • pyre/bench/synth/polymorphic_slot_retype.cranelift.jitstats
  • pyre/bench/synth/polymorphic_slot_retype.dynasm.jitstats
  • pyre/bench/synth/polymorphic_slot_retype.wasm.jitstats
  • pyre/bench/synth/pow3_arg_types.cranelift.jitstats
  • pyre/bench/synth/pow3_arg_types.dynasm.jitstats
  • pyre/bench/synth/pow3_arg_types.wasm.jitstats
  • pyre/bench/synth/print_stdout_redirect.cranelift.jitstats
  • pyre/bench/synth/print_stdout_redirect.dynasm.jitstats
  • pyre/bench/synth/print_stdout_redirect.py
  • pyre/bench/synth/print_stdout_redirect.wasm.jitstats
  • pyre/bench/synth/property_custom_hook_decline.cranelift.jitstats
  • pyre/bench/synth/property_custom_hook_decline.dynasm.jitstats
  • pyre/bench/synth/property_custom_hook_decline.wasm.jitstats
  • pyre/bench/synth/property_getattr_exceptions.cranelift.jitstats
  • pyre/bench/synth/property_getattr_exceptions.dynasm.jitstats
  • pyre/bench/synth/property_getattr_exceptions.wasm.jitstats
  • pyre/bench/synth/property_protocol_hot.cranelift.jitstats
  • pyre/bench/synth/property_protocol_hot.dynasm.jitstats
  • pyre/bench/synth/property_protocol_hot.wasm.jitstats
  • pyre/bench/synth/pure_listload_raw.cranelift.jitstats
  • pyre/bench/synth/pure_listload_raw.dynasm.jitstats
  • pyre/bench/synth/pure_listload_raw.py
  • pyre/bench/synth/pure_listload_raw.wasm.jitstats
  • pyre/bench/synth/pure_tupleload.cranelift.jitstats
  • pyre/bench/synth/pure_tupleload.dynasm.jitstats
  • pyre/bench/synth/pure_tupleload.wasm.jitstats
  • pyre/bench/synth/pypy_dict_primitives_nonbinding.cranelift.jitstats
  • pyre/bench/synth/pypy_dict_primitives_nonbinding.dynasm.jitstats
  • pyre/bench/synth/pypy_dict_primitives_nonbinding.wasm.jitstats
  • pyre/bench/synth/pypy_type_surface.cranelift.jitstats
  • pyre/bench/synth/pypy_type_surface.dynasm.jitstats
  • pyre/bench/synth/pypy_type_surface.wasm.jitstats
  • pyre/bench/synth/raise_reg_unbound_jitstress.cranelift.jitstats
  • pyre/bench/synth/raise_reg_unbound_jitstress.dynasm.jitstats
  • pyre/bench/synth/raise_reg_unbound_jitstress.wasm.jitstats
  • pyre/bench/synth/range_ctor_in_loop.cranelift.jitstats
  • pyre/bench/synth/range_ctor_in_loop.dynasm.jitstats
  • pyre/bench/synth/range_ctor_in_loop.wasm.jitstats
  • pyre/bench/synth/recursion_memo_branch.cranelift.jitstats
  • pyre/bench/synth/recursion_memo_branch.dynasm.jitstats
  • pyre/bench/synth/recursion_memo_branch.wasm.jitstats
  • pyre/bench/synth/recursive_call_frame_relocation.cranelift.jitstats
  • pyre/bench/synth/recursive_call_frame_relocation.dynasm.jitstats
  • pyre/bench/synth/recursive_call_frame_relocation.wasm.jitstats
  • pyre/bench/synth/recursive_forced_frame_kept_stack.cranelift.jitstats
  • pyre/bench/synth/recursive_forced_frame_kept_stack.dynasm.jitstats
  • pyre/bench/synth/recursive_forced_frame_kept_stack.wasm.jitstats
  • pyre/bench/synth/reentrant_key_eq_mutation.cranelift.jitstats
  • pyre/bench/synth/reentrant_key_eq_mutation.dynasm.jitstats
  • pyre/bench/synth/reentrant_key_eq_mutation.py
  • pyre/bench/synth/reentrant_key_eq_mutation.wasm.jitstats
  • pyre/bench/synth/residual_raise_except_resume.cranelift.jitstats
  • pyre/bench/synth/residual_raise_except_resume.dynasm.jitstats
  • pyre/bench/synth/residual_raise_except_resume.wasm.jitstats
  • pyre/bench/synth/reversed_disabled.cranelift.jitstats
  • pyre/bench/synth/reversed_disabled.dynasm.jitstats
  • pyre/bench/synth/reversed_disabled.py
  • pyre/bench/synth/reversed_disabled.wasm.jitstats
  • pyre/bench/synth/selfrec_tail_exception_unwind.cranelift.jitstats
  • pyre/bench/synth/selfrec_tail_exception_unwind.dynasm.jitstats
  • pyre/bench/synth/selfrec_tail_exception_unwind.wasm.jitstats
  • pyre/bench/synth/seq_repeat_overflow.cranelift.jitstats
  • pyre/bench/synth/seq_repeat_overflow.dynasm.jitstats
  • pyre/bench/synth/seq_repeat_overflow.wasm.jitstats
  • pyre/bench/synth/seqiter_getitem_lazy.cranelift.jitstats
  • pyre/bench/synth/seqiter_getitem_lazy.dynasm.jitstats
  • pyre/bench/synth/seqiter_getitem_lazy.wasm.jitstats
  • pyre/bench/synth/seqiter_pickle_parity.cranelift.jitstats
  • pyre/bench/synth/seqiter_pickle_parity.dynasm.jitstats
  • pyre/bench/synth/seqiter_pickle_parity.wasm.jitstats
  • pyre/bench/synth/seqiter_tuple_error_parity.cranelift.jitstats
  • pyre/bench/synth/seqiter_tuple_error_parity.dynasm.jitstats
  • pyre/bench/synth/seqiter_tuple_error_parity.wasm.jitstats
  • pyre/bench/synth/sequence_repeat_index.cranelift.jitstats
  • pyre/bench/synth/sequence_repeat_index.dynasm.jitstats
  • pyre/bench/synth/sequence_repeat_index.wasm.jitstats
  • pyre/bench/synth/set_contains_frozenset.cranelift.jitstats
  • pyre/bench/synth/set_contains_frozenset.dynasm.jitstats
  • pyre/bench/synth/set_contains_frozenset.py
  • pyre/bench/synth/set_contains_frozenset.wasm.jitstats
  • pyre/bench/synth/set_hash_protocol.cranelift.jitstats
  • pyre/bench/synth/set_hash_protocol.dynasm.jitstats
  • pyre/bench/synth/set_hash_protocol.wasm.jitstats
  • pyre/bench/synth/set_intersection_operand.cranelift.jitstats
  • pyre/bench/synth/set_intersection_operand.dynasm.jitstats
  • pyre/bench/synth/set_intersection_operand.py
  • pyre/bench/synth/set_intersection_operand.wasm.jitstats
  • pyre/bench/synth/set_key_protocol.cranelift.jitstats
  • pyre/bench/synth/set_key_protocol.dynasm.jitstats
  • pyre/bench/synth/set_key_protocol.wasm.jitstats
  • pyre/bench/synth/set_method_arity.cranelift.jitstats
  • pyre/bench/synth/set_method_arity.dynasm.jitstats
  • pyre/bench/synth/set_method_arity.py
  • pyre/bench/synth/set_method_arity.wasm.jitstats
  • pyre/bench/synth/set_name_filtered_dict.cranelift.jitstats
  • pyre/bench/synth/set_name_filtered_dict.dynasm.jitstats
  • pyre/bench/synth/set_name_filtered_dict.py
  • pyre/bench/synth/set_name_filtered_dict.wasm.jitstats
  • pyre/bench/synth/set_reentrant_eq_mutation.cranelift.jitstats
  • pyre/bench/synth/set_reentrant_eq_mutation.dynasm.jitstats
  • pyre/bench/synth/set_reentrant_eq_mutation.py
  • pyre/bench/synth/set_reentrant_eq_mutation.wasm.jitstats
  • pyre/bench/synth/set_remove_ord_errors.cranelift.jitstats
  • pyre/bench/synth/set_remove_ord_errors.dynasm.jitstats
  • pyre/bench/synth/set_remove_ord_errors.wasm.jitstats
  • pyre/bench/synth/set_update_hash_other.cranelift.jitstats
  • pyre/bench/synth/set_update_hash_other.dynasm.jitstats
  • pyre/bench/synth/set_update_hash_other.py
  • pyre/bench/synth/set_update_hash_other.wasm.jitstats
  • pyre/bench/synth/set_update_hot.cranelift.jitstats
  • pyre/bench/synth/set_update_hot.dynasm.jitstats
  • pyre/bench/synth/set_update_hot.wasm.jitstats
  • pyre/bench/synth/set_update_materialize_rhs.cranelift.jitstats
  • pyre/bench/synth/set_update_materialize_rhs.dynasm.jitstats
  • pyre/bench/synth/set_update_materialize_rhs.py
  • pyre/bench/synth/set_update_materialize_rhs.wasm.jitstats
  • pyre/bench/synth/short_circuit_boxed_int_cross_fn.cranelift.jitstats
  • pyre/bench/synth/short_circuit_boxed_int_cross_fn.dynasm.jitstats
  • pyre/bench/synth/short_circuit_boxed_int_cross_fn.py
  • pyre/bench/synth/short_circuit_boxed_int_cross_fn.wasm.jitstats
  • pyre/bench/synth/short_circuit_falsy_func_entry_resume.cranelift.jitstats
  • pyre/bench/synth/short_circuit_falsy_func_entry_resume.dynasm.jitstats
  • pyre/bench/synth/short_circuit_falsy_func_entry_resume.wasm.jitstats
  • pyre/bench/synth/short_circuit_side_effects.cranelift.jitstats
  • pyre/bench/synth/short_circuit_side_effects.dynasm.jitstats
  • pyre/bench/synth/short_circuit_side_effects.wasm.jitstats
  • pyre/bench/synth/short_circuit_value_kept_stack.cranelift.jitstats
  • pyre/bench/synth/short_circuit_value_kept_stack.dynasm.jitstats
  • pyre/bench/synth/short_circuit_value_kept_stack.py
  • pyre/bench/synth/short_circuit_value_kept_stack.wasm.jitstats
  • pyre/bench/synth/short_circuit_value_local_kept.cranelift.jitstats
  • pyre/bench/synth/short_circuit_value_local_kept.dynasm.jitstats
  • pyre/bench/synth/short_circuit_value_local_kept.py
  • pyre/bench/synth/short_circuit_value_local_kept.wasm.jitstats
  • pyre/bench/synth/simple_namespace_type.cranelift.jitstats
  • pyre/bench/synth/simple_namespace_type.dynasm.jitstats
  • pyre/bench/synth/simple_namespace_type.py
  • pyre/bench/synth/simple_namespace_type.wasm.jitstats
  • pyre/bench/synth/slots_class_var_conflict.cranelift.jitstats
  • pyre/bench/synth/slots_class_var_conflict.dynasm.jitstats
  • pyre/bench/synth/slots_class_var_conflict.wasm.jitstats
  • pyre/bench/synth/sre_pattern_methods.cranelift.jitstats
  • pyre/bench/synth/sre_pattern_methods.dynasm.jitstats
  • pyre/bench/synth/sre_pattern_methods.wasm.jitstats
  • pyre/bench/synth/sre_wasm_min.cranelift.jitstats
  • pyre/bench/synth/sre_wasm_min.dynasm.jitstats
  • pyre/bench/synth/sre_wasm_min.wasm.jitstats
  • pyre/bench/synth/sre_wasm_min1.cranelift.jitstats
  • pyre/bench/synth/sre_wasm_min1.dynasm.jitstats
  • pyre/bench/synth/sre_wasm_min1.wasm.jitstats
  • pyre/bench/synth/store_global_hot.cranelift.jitstats
  • pyre/bench/synth/store_global_hot.dynasm.jitstats
  • pyre/bench/synth/store_global_hot.wasm.jitstats
  • pyre/bench/synth/store_slice_hot.cranelift.jitstats
  • pyre/bench/synth/store_slice_hot.dynasm.jitstats
  • pyre/bench/synth/store_slice_hot.py
  • pyre/bench/synth/store_slice_hot.wasm.jitstats
  • pyre/bench/synth/str_encode_text_codec.cranelift.jitstats
  • pyre/bench/synth/str_encode_text_codec.dynasm.jitstats
  • pyre/bench/synth/str_encode_text_codec.wasm.jitstats
  • pyre/bench/synth/str_fstring.cranelift.jitstats
  • pyre/bench/synth/str_fstring.dynasm.jitstats
  • pyre/bench/synth/str_fstring.wasm.jitstats
  • pyre/bench/synth/str_getitem_len_hot.cranelift.jitstats
  • pyre/bench/synth/str_getitem_len_hot.dynasm.jitstats
  • pyre/bench/synth/str_getitem_len_hot.wasm.jitstats
  • pyre/bench/synth/str_index_bytes_iter_surface.cranelift.jitstats
  • pyre/bench/synth/str_index_bytes_iter_surface.dynasm.jitstats
  • pyre/bench/synth/str_index_bytes_iter_surface.wasm.jitstats
  • pyre/bench/synth/str_search_index_bounds.cranelift.jitstats
  • pyre/bench/synth/str_search_index_bounds.dynasm.jitstats
  • pyre/bench/synth/str_search_index_bounds.wasm.jitstats
  • pyre/bench/synth/str_startswith_bounds.cranelift.jitstats
  • pyre/bench/synth/str_startswith_bounds.dynasm.jitstats
  • pyre/bench/synth/str_startswith_bounds.wasm.jitstats
  • pyre/bench/synth/struct_pack_unpack.cranelift.jitstats
  • pyre/bench/synth/struct_pack_unpack.dynasm.jitstats
  • pyre/bench/synth/struct_pack_unpack.wasm.jitstats
  • pyre/bench/synth/subscr_negative_index_deopt.cranelift.jitstats
  • pyre/bench/synth/subscr_negative_index_deopt.dynasm.jitstats
  • pyre/bench/synth/subscr_negative_index_deopt.wasm.jitstats
  • pyre/bench/synth/subscr_user_getitem_inline.cranelift.jitstats
  • pyre/bench/synth/subscr_user_getitem_inline.dynasm.jitstats
  • pyre/bench/synth/subscr_user_getitem_inline.wasm.jitstats
  • pyre/bench/synth/surrogate_class_kwargs.cranelift.jitstats
  • pyre/bench/synth/surrogate_class_kwargs.dynasm.jitstats
  • pyre/bench/synth/surrogate_class_kwargs.py
  • pyre/bench/synth/surrogate_class_kwargs.wasm.jitstats
  • pyre/bench/synth/surrogate_dir.cranelift.jitstats
  • pyre/bench/synth/surrogate_dir.dynasm.jitstats
  • pyre/bench/synth/surrogate_dir.py
  • pyre/bench/synth/surrogate_dir.wasm.jitstats
  • pyre/bench/synth/surrogate_kwargs.cranelift.jitstats
  • pyre/bench/synth/surrogate_kwargs.dynasm.jitstats
  • pyre/bench/synth/surrogate_kwargs.wasm.jitstats
  • pyre/bench/synth/surrogate_metaclass_kwargs.cranelift.jitstats
  • pyre/bench/synth/surrogate_metaclass_kwargs.dynasm.jitstats
  • pyre/bench/synth/surrogate_metaclass_kwargs.py
  • pyre/bench/synth/surrogate_metaclass_kwargs.wasm.jitstats
  • pyre/bench/synth/swap_except_return_resume.cranelift.jitstats
  • pyre/bench/synth/swap_except_return_resume.dynasm.jitstats
  • pyre/bench/synth/swap_except_return_resume.py
  • pyre/bench/synth/swap_except_return_resume.wasm.jitstats
  • pyre/bench/synth/syntaxerror_location.cranelift.jitstats
  • pyre/bench/synth/syntaxerror_location.dynasm.jitstats
  • pyre/bench/synth/syntaxerror_location.py
  • pyre/bench/synth/syntaxerror_location.wasm.jitstats
  • pyre/bench/synth/syntaxerror_str.cranelift.jitstats
  • pyre/bench/synth/syntaxerror_str.dynasm.jitstats
  • pyre/bench/synth/syntaxerror_str.py
  • pyre/bench/synth/syntaxerror_str.wasm.jitstats
  • pyre/bench/synth/trace_too_long_effect_replay.cranelift.jitstats
  • pyre/bench/synth/trace_too_long_effect_replay.dynasm.jitstats
  • pyre/bench/synth/trace_too_long_effect_replay.py
  • pyre/bench/synth/trace_too_long_effect_replay.wasm.jitstats
  • pyre/bench/synth/trace_too_long_inline_multiframe.cranelift.jitstats
  • pyre/bench/synth/trace_too_long_inline_multiframe.dynasm.jitstats
  • pyre/bench/synth/trace_too_long_inline_multiframe.wasm.jitstats
  • pyre/bench/synth/tuple_contains_eq_raises.cranelift.jitstats
  • pyre/bench/synth/tuple_contains_eq_raises.dynasm.jitstats
  • pyre/bench/synth/tuple_contains_eq_raises.py
  • pyre/bench/synth/tuple_contains_eq_raises.wasm.jitstats
  • pyre/bench/synth/tuple_str_bytes_subscript_index.cranelift.jitstats
  • pyre/bench/synth/tuple_str_bytes_subscript_index.dynasm.jitstats
  • pyre/bench/synth/tuple_str_bytes_subscript_index.wasm.jitstats
  • pyre/bench/synth/tuple_unpack_array_backed_hot.cranelift.jitstats
  • pyre/bench/synth/tuple_unpack_array_backed_hot.dynasm.jitstats
  • pyre/bench/synth/tuple_unpack_array_backed_hot.wasm.jitstats
  • pyre/bench/synth/type_call_inline_init_branch_deopt.cranelift.jitstats
  • pyre/bench/synth/type_call_inline_init_branch_deopt.dynasm.jitstats
  • pyre/bench/synth/type_call_inline_init_branch_deopt.wasm.jitstats
  • pyre/bench/synth/type_descr_get_metaclass_getattr.cranelift.jitstats
  • pyre/bench/synth/type_descr_get_metaclass_getattr.dynasm.jitstats
  • pyre/bench/synth/type_descr_get_metaclass_getattr.py
  • pyre/bench/synth/type_descr_get_metaclass_getattr.wasm.jitstats
  • pyre/bench/synth/type_dict_surrogate.cranelift.jitstats
  • pyre/bench/synth/type_dict_surrogate.dynasm.jitstats
  • pyre/bench/synth/type_dict_surrogate.wasm.jitstats
  • pyre/bench/synth/type_dotted_name.cranelift.jitstats
  • pyre/bench/synth/type_dotted_name.dynasm.jitstats
  • pyre/bench/synth/type_dotted_name.py
  • pyre/bench/synth/type_dotted_name.wasm.jitstats
  • pyre/bench/synth/type_error_message_parity.cranelift.jitstats
  • pyre/bench/synth/type_error_message_parity.dynasm.jitstats
  • pyre/bench/synth/type_error_message_parity.py
  • pyre/bench/synth/type_error_message_parity.wasm.jitstats
  • pyre/bench/synth/type_immutable_reject.cranelift.jitstats
  • pyre/bench/synth/type_immutable_reject.dynasm.jitstats
  • pyre/bench/synth/type_immutable_reject.wasm.jitstats
  • pyre/bench/synth/type_metatype_data_descr.cranelift.jitstats
  • pyre/bench/synth/type_metatype_data_descr.dynasm.jitstats
  • pyre/bench/synth/type_metatype_data_descr.py
  • pyre/bench/synth/type_metatype_data_descr.wasm.jitstats
  • pyre/bench/synth/type_name_setter.cranelift.jitstats
  • pyre/bench/synth/type_name_setter.dynasm.jitstats
  • pyre/bench/synth/type_name_setter.wasm.jitstats
  • pyre/bench/synth/type_name_surrogate_reject.cranelift.jitstats
  • pyre/bench/synth/type_name_surrogate_reject.dynasm.jitstats
  • pyre/bench/synth/type_name_surrogate_reject.wasm.jitstats
  • pyre/bench/synth/unary_int_loop_carried.cranelift.jitstats
  • pyre/bench/synth/unary_int_loop_carried.dynasm.jitstats
  • pyre/bench/synth/unary_int_loop_carried.wasm.jitstats
  • pyre/bench/synth/unary_negative.cranelift.jitstats
  • pyre/bench/synth/unary_negative.dynasm.jitstats
  • pyre/bench/synth/unary_negative.py
  • pyre/bench/synth/unary_negative.wasm.jitstats
  • pyre/bench/synth/unary_positive_resume.cranelift.jitstats
  • pyre/bench/synth/unary_positive_resume.dynasm.jitstats
  • pyre/bench/synth/unary_positive_resume.py
  • pyre/bench/synth/unary_positive_resume.wasm.jitstats
  • pyre/bench/synth/unpack_drain_star_raise.cranelift.jitstats
  • pyre/bench/synth/unpack_drain_star_raise.dynasm.jitstats
  • pyre/bench/synth/unpack_drain_star_raise.py
  • pyre/bench/synth/unpack_drain_star_raise.wasm.jitstats
  • pyre/bench/synth/unpack_ex_hot.cranelift.jitstats
  • pyre/bench/synth/unpack_ex_hot.dynasm.jitstats
  • pyre/bench/synth/unpack_ex_hot.wasm.jitstats
  • pyre/bench/synth/unpack_wrong_arity_caught.cranelift.jitstats
  • pyre/bench/synth/unpack_wrong_arity_caught.dynasm.jitstats
  • pyre/bench/synth/unpack_wrong_arity_caught.wasm.jitstats
  • pyre/bench/synth/wasm_ca_trampoline_decline.cranelift.jitstats
  • pyre/bench/synth/wasm_ca_trampoline_decline.dynasm.jitstats
  • pyre/bench/synth/wasm_ca_trampoline_decline.wasm.jitstats
  • pyre/bench/synth/while_is_none.cranelift.jitstats
  • pyre/bench/synth/while_is_none.dynasm.jitstats
  • pyre/bench/synth/while_is_none.wasm.jitstats
  • pyre/bench/synth/wide_callkw_resume.cranelift.jitstats
  • pyre/bench/synth/wide_callkw_resume.dynasm.jitstats
  • pyre/bench/synth/wide_callkw_resume.wasm.jitstats
  • pyre/bench/synth/with_except_start_function_resume.cranelift.jitstats
  • pyre/bench/synth/with_except_start_function_resume.dynasm.jitstats
  • pyre/bench/synth/with_except_start_function_resume.py
  • pyre/bench/synth/with_except_start_function_resume.wasm.jitstats
  • pyre/check.py
  • pyre/pyre-interpreter/src/builtins.rs

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

The change recalibrates PERF_GATE_FLOOR_DIVISOR and updates PyPy ratio ceilings across synthetic benchmarks. Comments now record measured runner ratios and threshold calculations.

Changes

Performance gate calibration

Layer / File(s) Summary
Shared performance-gate divisor
pyre/check.py
PERF_GATE_FLOOR_DIVISOR increases from 25 to 40. The comments describe the measured cross-runner ratio span.
Synthetic benchmark thresholds
pyre/bench/synth/*
PyPy ratio ceilings are updated or removed based on observed runner measurements. Comments document rounding rules, benchmark variance, and cases without compiled loops.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

Poem

I’m a rabbit with benchmarks to tune,
Ratios now match each measured moon.
Gates rise where runners run slow,
Comments explain each number’s flow.
Hop, hop—clean thresholds glow!

✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fbw

`object_getattribute_no_hook` reads 6.8x on the macos runner and up to 7.8x
here against a ceiling of 5; `operator_error_typename` reads 11.0x there
against 10. Both ceilings are blanket values from the sweep that first gave
every synthetic fixture a `max-pypy-ratio`, never fitted to a measurement.
Each is now twice the slowest ratio observed, and pypy's denominator is
clamped for both, so neither ratio is a measurement to begin with.

Assisted-by: Claude
The linux runner fails `exception_const_operand_resume` at 23.9x against a
ceiling of 20, `getframe_force_cancel_journal` at 30.8x against 29, and
`unpack_drain_star_raise` at 52.7x against 49.

The other six sit within 2% of the bound the gate really applies (the ceiling
plus `compare_buffer / exec_baseline`) in runs already recorded, so they fail
on the next scheduling accident rather than on a change: `class_attrs_methods`
15.7x/15, `exception_dict_slot_reject` 5.8x/5, `defaults_reassigned_midloop`
17.8x/17, `store_slice_hot` 15.8x/15, `exception_reduce` 32.5x/32,
`comprehension_object_append_hot` 51.0x/41.

Each ceiling is now twice the slowest ratio observed across the three runners
and this machine, with that observation stated in the header.

Assisted-by: Claude
…span

The divisor has to clear that span twice over: a ceiling sits at twice the
slowest runner's ratio, and the floor derived from it still has to land under
the fastest runner's. `defaults_reassigned_midloop` reads 1.0x and 17.8x
across the runners, `foriter_inplace_immutable` 1.0x and 16.9x,
`class_attrs_methods` 1.0x and 15.7x, so at 25 each of their honest ceilings
put the derived floor at exactly the ratio their fastest runner reports.

At 40 no observation in the runner logs sits under its floor, and the count
within 25% of one drops from 61 to 27. Raising the divisor only lowers floors,
so nothing that passed can newly fail.

Assisted-by: Claude
…oopless fixture

The macos runner failed five synthetic ratio gates. Four are refitted to twice
the slowest ratio the runners report, with the observation stated in the
header: exception_catching_frame_tb_node 18 -> 53 (26.2x),
global_cell_shortpreamble_hot 19 -> 46 (22.7x),
inline_subwalk_mutating_residual 40 -> 102 (50.9x), float_builtin_hot 8 -> 27
(13.5x, read against a floor-clamped pypy baseline, so a lower bound).

getattr_attribute_fallbacks loses its `max-pypy-ratio` line instead. The
fixture has no loop and records loops_compiled=0 on dynasm, cranelift and
wasm, so its ratio compares interpreter startup rather than compiled code; it
reads between 1.0x and 12.2x across the runners without the fixture changing.
42 synth fixtures already carry no ratio header, and its jitstats baselines
still gate it.

Assisted-by: Claude
Ranking every synth fixture by the worst ratio the runners report against the
gate's effective bound (limit + compare_buffer/exec_baseline, which on posix
with a clamped baseline is limit + 1) leaves fifteen whose worst reading is
under 1.0 of that bound -- close enough that one noisy run reds them. Each is
refitted to twice its worst posix reading, with the observation in the header.

The bound is computed per platform rather than from the printed ratio: windows
adds 2*(1/64)*(1 + limit) to the compare buffer, so a short bench there is not
meaningfully ratio-gated and its readings are not a basis for a ceiling.

Assisted-by: Claude
…loop

Each of these records `loops_compiled=0` in its jitstats, so the ratio the gate
reads is the difference between two interpreters' process startup, not the cost
of anything generated. None of the 69 has a pypy baseline above 0.05s on any
posix runner -- 68 of them median at or below it, startup included -- so after
startup subtraction the denominator is the execution floor and the quotient is
whatever that run's spawn cost happened to be.

Measured on one fixture of this shape, the reading moved between 1.0x and 12.2x
across runners with nothing about the fixture changing.

Their jitstats baselines still gate them.

Assisted-by: Claude
…er than ungate them

`loops_compiled=0` has two causes and the previous commit treated them as one.
A fixture with no loop cannot be ratio-gated at any size. A fixture whose loop
is simply shorter than the JIT threshold is a bench that needs a bigger trip
count, and dropping its gate hides that.

Scaled to the smallest size at which the loop compiles and pyre's own execution
is an order of magnitude above a scheduler tick:

  condexpr_heap_const_merge  N      1000 -> 64000  loops_compiled 0 -> 2
  surrogate_class_kwargs     REPEAT  100 -> 3200   loops_compiled 0 -> 3
  surrogate_dir              REPEAT  100 -> 1600   loops_compiled 0 -> 1

Their ratio gates are restored at four times the slowest ratio check.py
observes, and the jitstats baselines are re-recorded on all three backends.
The other four fixtures with a scalable trip count still record
`loops_compiled=0` at 64 times their size, so their gates stay dropped.

Assisted-by: Claude
`--snapshot` writes fbw_blackhole_adopted_multi_frame,
fbw_blackhole_adopted_single_frame, fbw_rolled_back_with_effects,
fbw_store_journal_rollback_failed, field_pos_attached_misplaced and
field_pos_spec_misplaced into every fixture baseline. All read zero, and no
counter that already had a value changes.

Assisted-by: Claude
…p count

Measured pypy execution net of an empty-script baseline at both sizes: these 26
cross 50ms, the value `_performance_gate_passed` requires of a baseline before
it arms the derived floor. Fixtures whose pypy denominator clears that
threshold go from 4 to 30 of 373.

A wider calibration covering 135 fixtures was measured and discarded. For the
other 109, pypy's execution does not respond to the trip count at all -- at 64x
the workload `import_name` reads 4.4ms then 2.2ms and
`defaults_reassigned_midloop` 3.2ms then 2.8ms, several below the empty-script
baseline -- so raising their counts multiplied the numerator against a pinned
denominator, turned 36 fixtures red without making any ratio a measurement, and
cost 160s of wall clock across the three backends.

Four ceilings are refitted against the denominators that are now real. Three
read higher: a baseline pinned to the floor over-estimates the work pypy did,
so every ratio measured against it was a lower bound. import_math drops from
291 to 8 -- that bound was never fitted to an observation, and any ceiling at
or above PERF_GATE_FLOOR_DIVISOR pins the derived floor to parity, which a
fixture running within 1.3x of pypy cannot hold on a host where pyre lands
faster.

Assisted-by: Claude
…ming out

Sizing these three so pypy's execution is a measurement also put them past
`SYNTHETIC_CPYTHON_REFERENCE_TIMEOUT_S`. The cpython reference was being
dropped by timeout rather than by declaration: the cpython/pypy output
cross-check disappeared with nothing in the fixture saying so, and every run
spent the full 5s to arrive at that drop.

The two requirements do not both fit. A count small enough for cpython to
finish leaves pypy an order of magnitude under the startup-subtraction floor,
which is the condition `# pyre-check: skip-cpython` exists to declare.

Assisted-by: Claude
pypy's execution for this fixture sits on the startup-subtraction floor and
crosses it between runs. With pyre's time identical at 0.11s on one host,
back-to-back runs read 6.4x/8.4x and 11.9x/22.2x across the native backends,
the whole swing coming from which side of the floor pypy landed on. The 17 it
carried sits inside that swing.

Raising the trip count is not available here: measured at 64x the workload,
this fixture's pypy time does not respond to it.

Assisted-by: Claude
`guard_failures` drops 202 -> 201 on all three backends under the JIT work this
branch was rebased onto. The baseline it replaces was recorded before that base.

Assisted-by: Claude
`range_index_bound` converted every bound to a `BigInt` and back. The
round-trip normalizes -- `space_index` returns an int-or-long argument
unchanged and pyre's int/long are leaf types, so a `bool` would otherwise
survive as a `bool` and `range(True).stop` would expose `True` -- but only
the `bool` case needs a new object. A plain int is already the wrapping the
round-trip produced, and a long that fits a machine word is rewrapped through
`range_obj_as_i64`, which is the narrowing `iter()` reads when it picks
`rangeiterator` over `longrange_iterator`. The `BigInt` path stays for a
long that does not fit.

The three-argument step test spelled `range_obj_to_bigint(w_step) ==
BigInt::from(0)`, allocating two `BigInt`s per call; it now reads the machine
int and compares to 0, keeping the `BigInt` comparison for a step too wide
for a word. `functional.py W_Range.descr_new` spells this `space.int_w`.

Behavior is unchanged: bool, plain int, fitting long, wide long, an
`__index__` object, a negative step, a wide step, and a bad type all produce
the same values, types, and exceptions as before.

Measured by interleaving the two binaries under load, min of 9 runs each at
2M iterations: `len(range(4))` -16.8ns/iter, `len(range(n))` -31.5ns,
`len(range(0, 10, 2))` -19.0ns, `len(range(True))` -43.9ns,
`len(range(Index(4)))` -91.8ns, against +1.5ns for the empty-loop control.
This is below what `range_ctor_in_loop` can show -- that fixture costs
~14650ns/iter, so the change is diluted about a hundredfold there.

Assisted-by: Claude
`closure_per_call` reads guard_failures 418 where the baseline holds 420. The
fixture calls `range()`, and dropping the BigInt round-trip from the bound
normalization removes allocations the guest counts: `PYRE_GC_INTERP` is on
under wasm, so `w_int_new` is collector-allocated and enters
`threshold_reached`, where natively it takes an untracked
`alloc_with_gc_header`. Crossing that threshold arms the eval-breaker word
that every compiled back edge polls through a real guard, so fewer crossings
are fewer counted failures. `check.py`'s note on the two GC pins already
names this sensitivity -- interpreter-path allocation volume moves the wasm
numbers while the native ones sit still -- and the native baselines are
indeed unchanged.

Attributed by a control arm rather than by the argument above: with
`builtins.rs` reverted to its pre-change version and everything else on this
branch held fixed, the fixture passes against the recorded 420.

Assisted-by: Claude
#999 re-recorded this fixture's wasm baseline from 638 to 637. The guest reads
638 here, and 638 is also the value `check.py`'s own note on the two GC pins
states the guest produces -- "the guest ... reads
`recursive_call_frame_relocation` 638 and `closure_per_call` 420 against their
636 and 414" -- a comment #999 left unchanged while moving the number it
describes.

The branch is not the source: the same fixture passed against 638 on the
previous base with this branch's `range()` change already applied, and the
mechanism that moves this counter is old-gen allocation volume, which that
change lowers rather than raises.

Assisted-by: Claude
…loor

A clamped pypy baseline no longer gates anything. #1095 made
`_baseline_exec_time_clamped` return before both the ceiling and the derived
floor, so a fixture whose pypy side sits on EXEC_TIME_FLOOR_S is ungated on
the ratio entirely -- lifting it above the floor is now the only way such a
fixture has a perf gate at all.

The trip counts are solved, not guessed. Timing pypy at 1x, 8x and 32x of each
committed knob gives a per-iteration slope; the new knob is the count that puts
pypy at FLOOR_GATE_MIN_BASELINE_S, rounded up to two significant digits. Of the
270 clamped fixtures, 143 keep their trip count as an inline literal rather
than a module-level knob and are left alone -- a `range(300)` is often a
recursion depth or a threshold, and rewriting it silently changes what the
fixture covers -- 7 are flat under pypy at any size, and 91 respond. 20 of
those reach the floor within 64x while keeping pyre's projected execution well
under the 20s bench timeout, which is the bound that excluded
`closure_per_call` (23.2s), `inline_gate_operand_provenance`, `binary_slice_index`
and `class_reassign_hot`.

Three more were scaled and then reverted, because scaling them bought CI time
and no gate: `exc_info_module_loop_hot` and `exec_defined_global_read` still
read clamped afterwards, and `enumerate_bignum_start` still records
`loops_compiled=0`, so its ratio would compare two interpreters rather than any
generated code.

Five ceilings move as a consequence, in both directions, because an unclamped
ratio is a different quantity from the clamped one it replaces:
`bound_method_builtin_fold` 48 -> 160 and `inlined_helper_mutation` 45 -> 145
were fitted against the clamp and fail without this; `unary_negative` 110 -> 220
sat directly on its own reading; and `unary_positive_resume` 90 -> 5 collapses,
because at the old trip count the numerator was mostly pyre's fixed warmup,
which the longer loop amortises. `loop_callee_shared_mutation` predates the
convention and had no ceiling at all; it compiles two loops and now gets one.

Measured cost: +273s per check.py run, about 14 minutes across the three
runners.

Assisted-by: Claude
The fixture arrived with #999 recording bridges_compiled=5 and
guard_failures=1011, and the JIT changes that landed after it moved both
without a re-record. It reads bridges_compiled=102 and guard_failures=20497
here on all three backends, with loops_compiled=11 unchanged.

Not this branch's: `pypy_type_surface` contains no `range()` for its only
interpreter change to reach, and main's own `pyre CI` run at this base fails on
exactly these three lines from ubuntu-24.04 -- `bridges_compiled 5 -> 102,
guard_failures 1011 -> 20497 (observed loops_compiled=11 bridges_compiled=102)`
-- so the recorded value reproduces on neither platform. Re-recording it agrees
with both.

Assisted-by: Claude
`list_append_funcentry_helper` reads 61.9x on cranelift against its ceiling of
61 once its pypy baseline clears the startup-subtraction floor. Same cause as
the five refitted alongside the trip counts: the ceiling was fitted while the
baseline was pinned to the floor, which over-states pypy's work and so
under-states the ratio built on it. Twice the slowest backend observed.

Assisted-by: Claude

@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: 7bce6dd91d

ℹ️ 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 on lines +1 to +2
# No `max-pypy-ratio`: this fixture compiles no loop -- its jitstats record
# `loops_compiled=0` -- so a pypy ratio compares two interpreters' startup

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Keep ratio gates on fixtures that compile loops

The stated reason for removing this gate is false: the committed dynasm, cranelift, and wasm baselines all record loops_compiled=2, not 0. The same misclassification affects getframe_stored_fback_walk, getframe_while_caller_locals_across_subwalk, getframe_while_captured_frame_outlives_call, getframe_while_escaping_read_frame_identity, getframe_while_inlined_callee_subwalk, and getframe_while_subwalk_decline_shapes, whose baselines record one or two compiled loops on every backend. On a runner where PyPy's execution clears the timing floor, removing these ceilings allows a slowdown in the generated getframe paths to pass whenever structural jitstats counts remain unchanged; retain/refit their ratio gates rather than treating them as startup-only fixtures.

Useful? React with 👍 / 👎.

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown

🤖 Codex parity review

Static analysis of this diff vs the local RPython/PyPy sources (commit fa123a5).
Updated: 2026-08-08T12:54:50.577Z

Files in the reviewed diff
pyre/bench/synth/abstractmethods_metaclass_getattr.py
pyre/bench/synth/abstractmethods_nonstring_name.py
pyre/bench/synth/aiter_anext.py
pyre/bench/synth/attr_cache_invalidation.py
pyre/bench/synth/bases_reassign_cache.py
pyre/bench/synth/bound_method_builtin_fold.py
pyre/bench/synth/build_class_surrogate_namespace.py
pyre/bench/synth/build_list_resume.py
pyre/bench/synth/build_set_hashability.py
pyre/bench/synth/builtin_type_surface.py
pyre/bench/synth/bytes_split_whitespace_maxsplit.py
pyre/bench/synth/call_ex_kwargs_mapping.py
pyre/bench/synth/call_loop_local_function.py
pyre/bench/synth/class_attrs_methods.py
pyre/bench/synth/complex_real_imag.py
pyre/bench/synth/comprehension_object_append_hot.py
pyre/bench/synth/condexpr_heap_const_merge.py
pyre/bench/synth/defaults_reassigned_midloop.py
pyre/bench/synth/delete_negative_open_slice_hot.py
pyre/bench/synth/dict_update_source_mutation.py
pyre/bench/synth/dir_custom.py
pyre/bench/synth/dir_dict_class_attrs.py
pyre/bench/synth/dir_full_mro.py
pyre/bench/synth/dunder_repr_str_errors.py
pyre/bench/synth/enumerate_bignum_start.py
pyre/bench/synth/exc_in_loop_divzero_continue.py
pyre/bench/synth/except_star.py
pyre/bench/synth/exception_bare_reraise_nested_outer.py
pyre/bench/synth/exception_catching_frame_tb_node.py
pyre/bench/synth/exception_const_operand_resume.py
pyre/bench/synth/exception_dict_slot_reject.py
pyre/bench/synth/exception_group_type.py
pyre/bench/synth/exception_reduce.py
pyre/bench/synth/exception_subclass_attrs.py
pyre/bench/synth/exceptions.py
pyre/bench/synth/fast_local_swap.py
pyre/bench/synth/float_builtin_hot.py
pyre/bench/synth/for_iter_select_receiver_swap.py
pyre/bench/synth/format_z_negative_zero.py
pyre/bench/synth/getattr_attribute_fallbacks.py
pyre/bench/synth/getattr_surrogate_hook.py
pyre/bench/synth/getattribute_intercepts_dunder.py
pyre/bench/synth/getframe_force_cancel_journal.py
pyre/bench/synth/getframe_inline_subwalk_multiframe.py
pyre/bench/synth/getframe_inlined_callee_own_frame.py
pyre/bench/synth/getframe_stored_fback_walk.py
pyre/bench/synth/getframe_while_caller_locals_across_subwalk.py
pyre/bench/synth/getframe_while_captured_frame_outlives_call.py
pyre/bench/synth/getframe_while_escaping_read_frame_identity.py
pyre/bench/synth/getframe_while_inlined_callee_subwalk.py
pyre/bench/synth/getframe_while_subwalk_decline_shapes.py
pyre/bench/synth/global_cell_shortpreamble_hot.py
pyre/bench/synth/global_quasiimmut_invalidation.py
pyre/bench/synth/global_reassign.py
pyre/bench/synth/goto_if_not_same_box.py
pyre/bench/synth/if_else_jump_forward.py
pyre/bench/synth/import_from_name_path.py
pyre/bench/synth/import_math.py
pyre/bench/synth/import_none_sentinel.py
pyre/bench/synth/inheritance_dispatch.py
pyre/bench/synth/inline_freevar_after_mayforce.py
pyre/bench/synth/inline_multiframe_branchy_carrier.py
pyre/bench/synth/inline_subwalk_mutating_residual.py
pyre/bench/synth/inlined_helper_mutation.py
pyre/bench/synth/instance_dict_reassign.py
pyre/bench/synth/int_base0_error_literal.py
pyre/bench/synth/int_max_str_digits.py
pyre/bench/synth/iter_sentinel_stopiteration.py
pyre/bench/synth/itertools_cycle.py
pyre/bench/synth/kept_stack_aliased_swap_boxed.py
pyre/bench/synth/kept_stack_boxed_in_handler.py
pyre/bench/synth/kept_stack_deep_var_nested_call.py
pyre/bench/synth/kept_stack_depth_gt1.py
pyre/bench/synth/kept_stack_depth_gt1_heap.py
pyre/bench/synth/kwargs_positional_only.py
pyre/bench/synth/len_dunder_validation.py
pyre/bench/synth/list_append_funcentry_helper.py
pyre/bench/synth/list_pop_append.py
pyre/bench/synth/list_setslice.py
pyre/bench/synth/list_to_tuple_star.py
pyre/bench/synth/load_fast_check.py
pyre/bench/synth/loop_callee_return.py
pyre/bench/synth/loop_callee_shared_mutation.py
pyre/bench/synth/loop_exit_empty_dict_local_clobber.py
pyre/bench/synth/loop_in_try_raise_into_handler.py
pyre/bench/synth/loop_in_try_tail_raise_and_second_loop.py
pyre/bench/synth/loop_in_try_tail_unbound_check.py
pyre/bench/synth/mapdict_frozen_unboxing_fold.py
pyre/bench/synth/math_log_trig_hot.py
pyre/bench/synth/math_sqrt_hot.py
pyre/bench/synth/metaclass_conflict.py
pyre/bench/synth/metatype_property_dunder.py
pyre/bench/synth/method_reassign_after_warmup.py
pyre/bench/synth/module_attr_message.py
pyre/bench/synth/module_dir_dunder.py
pyre/bench/synth/module_getattr.py
pyre/bench/synth/nested_break_not_hot.py
pyre/bench/synth/object_getattribute_no_hook.py
pyre/bench/synth/operator_error_typename.py
pyre/bench/synth/p2_local_result_bridge.py
pyre/bench/synth/print_stdout_redirect.py
pyre/bench/synth/pure_listload_raw.py
pyre/bench/synth/reentrant_key_eq_mutation.py
pyre/bench/synth/reversed_disabled.py
pyre/bench/synth/set_contains_frozenset.py
pyre/bench/synth/set_intersection_operand.py
pyre/bench/synth/set_method_arity.py
pyre/bench/synth/set_name_filtered_dict.py
pyre/bench/synth/set_reentrant_eq_mutation.py
pyre/bench/synth/set_update_hash_other.py
pyre/bench/synth/set_update_materialize_rhs.py
pyre/bench/synth/short_circuit_boxed_int_cross_fn.py
pyre/bench/synth/short_circuit_value_kept_stack.py
pyre/bench/synth/short_circuit_value_local_kept.py
pyre/bench/synth/simple_namespace_type.py
pyre/bench/synth/store_slice_hot.py
pyre/bench/synth/surrogate_class_kwargs.py
pyre/bench/synth/surrogate_dir.py
pyre/bench/synth/surrogate_metaclass_kwargs.py
pyre/bench/synth/swap_except_return_resume.py
pyre/bench/synth/syntaxerror_location.py
pyre/bench/synth/syntaxerror_str.py
pyre/bench/synth/trace_too_long_effect_replay.py
pyre/bench/synth/tuple_contains_eq_raises.py
pyre/bench/synth/type_descr_get_metaclass_getattr.py
pyre/bench/synth/type_dotted_name.py
pyre/bench/synth/type_error_message_parity.py
pyre/bench/synth/type_metatype_data_descr.py
pyre/bench/synth/unary_negative.py
pyre/bench/synth/unary_positive_resume.py
pyre/bench/synth/unpack_drain_star_raise.py
pyre/bench/synth/with_except_start_function_resume.py
pyre/check.py
pyre/pyre-interpreter/src/builtins.rs

1. Regressions to PyPy parity introduced by this patch

None.

2. Other mismatches introduced by this patch

None.

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

  • pyre/pyre-interpreter/src/baseobjspace.rs:13238 ↔ pypy/objspace/descroperation.py:622: space_index(True) returns the original bool because is_int_or_long accepts bool; PyPy’s index() always re-wraps a non-exact int, yielding plain int(1). The patched range-specific normalization fixes this only for range bounds.

4. Structural adaptations

  • pyre/pyre-interpreter/src/builtins.rs:4021 ↔ pypy/module/__builtin__/functional.py:475: Rust uses range_obj_as_i64 plus a BigInt zero comparison instead of PyPy’s space.int_w()/OperationError control flow. This preserves the same zero-step decision while adapting PyPy’s boxed machine-int overflow path to Rust’s Option<i64> representation.

@youknowone
youknowone merged commit e5eff81 into main Aug 8, 2026
7 of 8 checks passed
@youknowone
youknowone deleted the fbw branch August 8, 2026 12:52

@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

https://github.com/youknowone/pyre/blob/fa123a57560394c7e2d2624cbe7e71c85fa4b746/pyre-interpreter/src/builtins.rs#L4019-L4020
P2 Badge Normalize int subclasses before storing range bounds

When a bound is a direct strict int subclass instance, space_index returns that same object and is_int is true because subclasses share the integer layout, so this branch stores the subclass unchanged. Consequently, range(I(5)).stop and the arguments exposed by __reduce__ retain an I instance rather than the required plain int; the previous conversion through range_bigint_to_obj normalized it correctly. Check exact class identity here or re-wrap the value before returning.

AGENTS.md reference: AGENTS.md:L231-L233

ℹ️ 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".

youknowone added a commit that referenced this pull request Aug 8, 2026
`pypy_type_surface` reads bridges_compiled=5 and guard_failures=1011 on all
three backends, the figures #999 `dad2a722907` recorded. #1097 `d51ea7f32a0`
moved them to 102/20497 by folding `Cls.__name__` across a `getset_descriptor`
whose `w_class` slot is null, and #1107 `9614f37fb1e` declined that fold again;
#1107's own message records the fixture reading 11/5/0/1011 afterwards. #1086
`e5eff816849` sits between the two and wrote the regressed pair in as the
baseline, so the restored reading has failed the gate on every runner since.

The same commit reverted three wasm guard_failures counters to their pre-#1106
values while keeping #1106 `4555e3d76ba`'s other fields:
ca_bridge_multiframe_resume_double_call 2592 -> 2581, wasm_ca_trampoline_decline
601 -> 404, recursion_memo_branch 4704 -> 4724. The guest reads #1106's values
both here and on ubuntu-24.04, the only runner that runs wasm, and each
fixture's loops_compiled and bridges_compiled already agree with what both
observe.

Measured with `pyre/check.py --snapshot-diff` per backend and pattern: dynasm
18/18, cranelift 18/18, and wasm 15/15 for each of the three wasm fixtures.

Assisted-by: Claude
youknowone added a commit that referenced this pull request Aug 9, 2026
#1106 `4555e3d76b` dropped the wasm32 arm of the self-recursive root-bridge
inline and recorded what that moved: `ca_bridge_multiframe_resume_double_call`
2581 -> 2592, `wasm_ca_trampoline_decline` 404 -> 601 and
`recursion_memo_branch` 4724 -> 4704. #1086 `e5eff81684` wrote all three back
to their pre-#1106 values, and ubuntu has failed on them every run since.

#1086 resizes 130 fixtures so pypy's side clears the measurement floor, and
re-recording a resized fixture's counters is part of that. It moves 34 baseline
values; 26 sit in fixtures whose `.py` it also changed. These three — and
`pypy_type_surface`, restored in 958f66c — are among the eight it moved with
no workload change beside them, which is a snapshot taken on a base predating
#1106.

Measured rather than reverted: a local wasm run reads 2592, 601 and 4704, which
are #1106's figures and the ones ubuntu observes. The remaining two of those
eight, `closure_per_call` 418 and `recursive_call_frame_relocation` 638, read
what they already record and are left alone.

The lower counts are not the better state. #1106 measured removing the decline
at -20.1%/-20.7% wasm CPU on `wasm_ca_trampoline_decline`; the +197 guard
failures buy that. `ca_bridge_multiframe_resume_double_call` pays +1.2%/+2.7%
and in exchange reports the 16 bridges / 0 aborts the dynasm baseline records,
where the decline left wasm at 16/1.

`retraces_compiled=0` comes with the re-record: these were the only wasm
baselines missing the key, which `_parse_jit_stats` was defaulting.
youknowone added a commit that referenced this pull request Aug 9, 2026
…t was hiding (#1104)

* extra_tests: report the parity runner's failures where a CI log is read

The per-failure detail and the `N failure(s)` count went to stderr while the
213-row result table went to stdout.  A piped stdout is block-buffered and
stderr is not, so the whole report arrived in the log *above* the run's own
header, and the last thing before the runner's non-zero exit was a passing
row -- a failed job named none of what failed in it.

The report is printed last now, on stdout, and echoes each child's stderr
verbatim instead of a `repr` of the whole thing on one line: a traceback only
reads as one when its line breaks survive.  Each failing row also carries its
one-line verdict beneath it, and under `GITHUB_ACTIONS` every failure emits an
`::error file=` annotation carrying that verdict and the exception line, which
shows on the pull request without opening the log.

stdout is line-buffered so a run that dies mid-way names the scripts it got
through, and pinned to UTF-8 because the report echoes a child's stderr: these
scripts are largely about names no console codepage can spell, and printing
one of those raised `UnicodeEncodeError` out of the runner instead of the
failure it was in the middle of explaining.

`_run` returns the reason and the stderr as separate values, which `Failure`
carries.

* posix: the pre-epoch utime Windows refused, and six answers beside it

`os.utime` on Windows turned away every time before 1970.  The host call
takes its times as a `Duration`, which has no second below its epoch at all,
so `u64::try_from(sec)` was the whole pre-epoch range's refusal.  A FILETIME
counts 100ns ticks from 1601-01-01, so shifting the epoch is what makes such
a second a positive tick count; `SetFileTime` is called here now, over the
handle `host_env::fs::open_write_with_custom_flags` opens, with the same
wrapping `__int64` arithmetic `time_t_to_FILE_TIME` is written in.

Measured against CPython 3.14 on the same host, `os.utime(p, times=(-5.0,
-6.0))` now reads back as -6_000_000_000 where it raised, and `ns=(-1, -1)`
as the -100 a FILETIME's granularity leaves.

Six more answers along the same argument, each measured against 3.14:

  ('a', 'b')     ValueError: could not convert string to float
                   -> TypeError: argument must be int or float, not str
  (1e30, 0)      ValueError: utime: timestamp out of range
                   -> OverflowError: timestamp out of range for platform time_t
  (2**200, 0)    the same, and by the exact integer rather than through a
                   float that rounded the seconds it could not hold
  (nan, 0)       ValueError: utime: timestamp out of range
                   -> ValueError: Invalid value NaN (not a number)
  (1,)           utime: 'times' must be a tuple of two ints
                   -> ... must be either a tuple of two ints or None
  ns=(2**80, 0)  OverflowError -> written.  `split_py_long_to_s_and_ns`
                   splits with `divmod` BEFORE it narrows anything, so a
                   nanosecond count too wide for a `time_t` is refused only
                   when the second it names is; 2**80 ns is a second that
                   fits.  Dividing after the narrowing turned away the range.
                   `divmod` is also what answers for `ns=('a', 'b')`.

`os.truncate`/`os.ftruncate` on Windows read their length with a bare
`int_w`: no `__index__`, and `int too large to convert to int` where
`Py_off_t_converter` says `int too big to convert`.  Both now go through
`truncate_length_w`, which is hoisted out of the unix arm and names the C
type the platform's converter names.

`st_atime_ns` and its two siblings took `sec * 1_000_000_000` in `i64`, which
runs out in 2262 -- a file dated later, which every FILETIME up to the year
30828 can be, read back as the wrap.  The product is taken in `i128` and the
field is an int of whatever width it needs.

`parity_tests/os_utime_pathconf_truncate` covers all of it and no longer
skips its negative-time section on Windows; only the exact-nanosecond value
is platform-dependent there.  Its `pathconf` section is now gated on the name
existing, because neither CPython nor this build carries `pathconf` on
Windows and the reference failed the script before any backend could -- which
is what made the whole script red on every Windows runner.

* jit: assert `guard_exact_w_class` pins a `w_class` its operand carries

`is_exact_builtin_instance` (pyobject.rs:149-163) reads a null `w_class` as a
second spelling of "exact builtin", beside the one where the slot holds the
canonical type object, and `is_plain_int1` (listobject.rs:424-460) accepts both
for `int` and for a fits-int `W_LongObject`. `walker_guard_exact_w_class` reads
the slot and pins a single value, so an operand admitted under the null spelling
and pinned against the canonical gets a guard its own recorded operand fails —
and nothing writes the slot afterwards, so it fails on every execution without
converging, one bridge per `trace_eagerness` bucket. That is the shape
`try_walker_specialize_load_type_name_attr` shipped with, where the fold took
its metaclass from `typedef::type`'s `gettypefor(ob_type)` fallback while the
guard read the raw field.

The 40-odd other call sites establish the operand carries what they pin —
through `walker_exact_builtin_class`, which returns `None` on a null slot, or
through `is_plain_int1` / a local `is_exact_int` — but nothing checked that they
do. Measured across `bench/synth`, `bench` and `extra_tests/parity_tests`,
under a probe that reported the recorded slot against the pinned value at every
site: 1217 pins over 131 files, all carrying what they pin, and no site reaching
the guard without a concrete operand. The null spelling is reachable — `bool`,
`None`, functions, generators, iterators, sets and the itertools objects are all
built with a null slot, and `SMALL_INTS` is written that way behind
`WITHPREBUILTINT` — so what holds is that no admitting predicate currently pairs
one with a canonical pin, not that it could not.

`debug_assert!` rather than a decline: there is no live site to decline, release
codegen is unchanged, and the next occurrence fails loudly instead of costing a
20x jit-stats drift that takes a baseline diff to notice.

* sys, pyrex: the three Windows parity failures behind a job that named none

`pyre/check.py (windows-latest)` on #1109 ends on a passing row and exit code 1;
the three scripts it failed on are 200 lines up, in the stderr the neighbouring
commit here moves. They are main's, not that PR's, and independent of each
other.

**`keyboard_interrupt_exit_status`.** A Win32 process has no SIGINT to die of.
`app_main.py:1146-1151` restores `SIG_DFL` and calls `raise(SIGINT)`, saying the
MSVC runtime then exits with `STATUS_CONTROL_C_EXIT`; measured, that pair
returns through the CRT's default action and the process ends with status 3 —
`signal.signal(SIGINT, SIG_DFL); signal.raise_signal(SIGINT)` under CPython
exits 3 as well, while an uncaught `KeyboardInterrupt` there exits 0xC000013A.
`raise` never terminates, so `terminate_by_sigint` fell through to
`process::abort`, whose status 3 is what the fixture read. Windows exits with
`STATUS_CONTROL_C_EXIT` directly; both callers have already finalized.

**`builtin_module_loader_spec`.** Two missing names, both reached from
`test.support`'s import:
- `_sysconfig.config_vars()` answered an empty dict. `sysconfig._init_non_posix`
  SUBSCRIPTS `Py_GIL_DISABLED` and `Py_DEBUG` to spell `ABIFLAGS`, so under
  `os.name == 'nt'` an absent key is a `KeyError` out of the first
  `get_config_var` rather than the `None` the `.get()` readers take. Both are 0,
  which is what an empty `sys.abiflags` already says. `EXT_SUFFIX` and `SOABI`,
  the other two keys the call carries, name an extension ABI that
  `_imp.extension_suffixes()` says does not exist here, so they stay absent.
- `sys.getwindowsversion` was absent and `_init_config_vars` subscripts
  `sys._vpath` beside it. The version is a five-field sequence with five
  named-only fields over it, built the way `os.stat_result` carries its `st_*_ns`
  extras, off `host_env::windows::get_windows_version`. Every field matches
  CPython 3.14 on the same host except `build`: the sequence reports kernel32's
  file version, because `GetVersionEx` answers with the version an unmanifested
  binary is shimmed to, and `platform_version` — the field that exists because of
  that shimming — agrees with it here instead of correcting it.

**`frame_clear_finalization`** imported `resource` for one CPU-time bound at the
end. It is a POSIX module, absent from CPython on Windows too, so the import
took all six checks off the platform and left the reference failing beside the
backends. `time.process_time` is the same measurement and is everywhere.

extra_tests/parity_tests: 213/213 on both backends, bar
`builtin_module_loader_spec` under a local CPython with no `test` package
installed — the runner that CI uses has it and reported `cpython=OK`.

* display: spell a repr's address the way the platform's `%p` spells it

`PyUnicode_FromFormat`'s `%p` hands the pointer to the platform's own `printf`
and normalizes only the prefix — guaranteed to start with a literal `0x`
"regardless of what the platform's printf yields". The platforms disagree about
everything after it: the MSVC runtime pads to the pointer width and uppercases,
glibc does neither. So on Windows CPython reads
`<function f at 0x000001B7AF7FFCC0>` where it reads `<function f at
0x1b7af7ffcc0>` elsewhere, and Rust's `{:p}` — along with `{:?}` on a raw
pointer and a hand-written `0x{:x}` — is only ever the second spelling.

Every address-bearing repr was therefore wrong on Windows. Measured against
CPython 3.14 on the same host, fifteen kinds disagreed: function, object,
generator, coroutine, async_generator, bound and built-in method,
method-wrapper, cell, weakref, memoryview, ContextVar, Token, code, frame and
both `_thread` locks. They now go through one `display::repr_addr`, and the
shapes are identical. `_pickle`'s cyclic-object message names an address the
same way and is the one such site that is not a repr.

`surrogate_name_messages` asserted the glibc spelling against `id()`, so it was
the REFERENCE that failed it on every Windows runner — a script that fails on
CPython measures nothing, and the backends were being compared against a failing
oracle. It builds the platform's spelling now.

The frame repr's `file '...'` is left raw: `pyframe.py:849-853` interpolates
`'%s'`, and CPython's `%R` there escapes the backslashes a Windows path is full
of. That is a parity-source disagreement rather than this fix's business.

* bench/synth: re-record pypy_type_surface's jit-stats baseline

`bridges_compiled 102 -> 5` and `guard_failures 20497 -> 1011`, byte-identical
on dynasm, cranelift and wasm.

The recorded 102/20497 are the counters the `Cls.__name__` fold produced while
its metaclass guard could not be discharged — it read the raw `w_class` slot
where the fast path answers through the `gettypefor(ob_type)` fallback, so a
receiver reached through that fallback got a `guard_value(NULL, type)` that
failed on every execution. #1106 narrowed the fold; the baseline still names
what the defect measured.

Read back rather than predicted: ubuntu-24.04, macos-latest and windows-latest
all report 5/1011 on main, and so does a local windows run. `retraces_compiled`
joins the file because the recorder now writes it; it is 0, which is what the
comparison already read for its absence.

* sys, parity: a structseq type built once, a decoded timeout stderr, and two NTFS-only assertions

`sys.getwindowsversion` built its structseq type inside the call, so every
answer was an instance of a different class and
`type(sys.getwindowsversion()) is type(sys.getwindowsversion())` read False
where CPython reads True. It was the one of pyre's ten structseq types that did
not already cache its type in a `OnceLock` — `stat_result`, `terminal_size`,
`uname_result`, `statvfs_result`, `waitid_result`, `times_result`,
`struct_time`, `_ExceptHookArgs` and `UnraisableHookArgs` all do — and it now
does the same. Measured: a probe over every structseq both runtimes carry
reports the types equal for all nine others and for all of CPython's, so this
constructor was the whole divergence. That the cache is a bare `usize` the GC
cannot see is the established pattern rather than a new bet, and it holds: 200
`os.stat` answers dropped across forced collections plus 60MB of churn leave the
cached type identical and its fields readable.

`structseq_type_identity` pins the property for every structseq the host
carries, and fails on the binary built before this commit naming exactly
`sys.getwindowsversion`.

The parity runner decoded its child's stderr on the normal path only.
`subprocess.run(text=True)` decodes what `communicate()` returns; the timeout
path raises with the raw chunks it had joined, which is bytes on POSIX and str
on Windows. A timed-out script would have reported one `b'...\n...'` line — the
unreadable shape the rest of this branch exists to remove.

Two assertions in `os_utime_pathconf_truncate` could only ever have held on
NTFS. The step that runs them has not reached ubuntu or macos: `check.py` runs
first in that job and has been failing, so the parity suite never starts there.

* `ns=(2**62, 2**62)` read back `4611686018427387900`, which is 2**62 rounded
  down to a FILETIME's 100ns tick. ext4 and APFS keep the nanosecond and answer
  `...904`. Both spellings now come from one `storable()`, which also replaces
  the `-1`/`-100` conditional above it.
* `utime(p, (8.8e11, 8.8e11))` names the year 29880, which no filesystem but
  NTFS reaches — an APFS timestamp is itself an int64 of nanoseconds, so 2262
  bounds it too, and ext4 stores a 34-bit second and stops in 2446. What every
  platform is held to is the identity the `i128` widening buys,
  `st_mtime_ns == int(st_mtime) * 1_000_000_000`, wherever the write succeeds;
  the exact value is asserted only where the second survived the round trip.

The remaining review note asked for f-strings in `surrogate_name_messages`.
Left alone: the file builds every expected repr with `%` formatting, including
the assertions this branch did not touch, and nothing lints for it.

* cpython_tests: report the cases unittest named, the tail of a timed-out run, and decode the report

`classify` recorded `last_stderr_line` for a FAIL. This runner sets
`MAJIT_STATS`, so the last thing every process writes is the JIT summary:
every FAIL in the suite recorded `rc=1 Compilation time: <n>ms`, a line that
names no test. The nightly report carries 118 of them, all the same. A FAIL
now carries unittest's own account instead — the closing `FAILED (...)` and
the `FAIL:`/`ERROR:` case headers, up to four of them and a count of the rest.
An IMPORTERROR never reached unittest, so it keeps the tail.

`TimeoutExpired` was caught and discarded, leaving `timeout 120s`. It carries
the output the child had produced, which for a unittest module is the progress
dots — the record of which case it stopped in. `text=True` decodes what
`communicate()` returns, not what the timeout path raises, so the partial
arrives as bytes on POSIX and str on Windows and both are accepted.

The report's box-drawing killed the run with a `UnicodeEncodeError` on a
console whose codepage cannot spell it, before any test ran; stdout is
reconfigured the way the parity runner's is.

* _locale: the Windows category numbers, no LC_MESSAGES there, and a setlocale that reaches the CRT

The `LC_*` values came from libc under `cfg(unix)` and from a hardcoded POSIX
table everywhere else, so Windows published `LC_CTYPE=0, LC_ALL=6` where the
MSVC CRT numbers them `LC_ALL=0, LC_COLLATE=1, LC_CTYPE=2`. Every constant
named a different category than the one it was passed to. They now come from
libc there too, which carries the CRT's own numbering.

`LC_MESSAGES` is a POSIX category the MSVC CRT has no counterpart for, and
CPython does not define it on Windows; it is registered under `cfg(unix)`.

`setlocale` was gated on `all(unix, host_env)`, so on Windows it fell to the
no-libc arm and answered "C" for every name it was handed, reporting success
for a locale that was not installed. `host_env::locale::setlocale` is not
unix-only — it calls `libc::setlocale`, which Windows has. The gate now admits
Windows, and an uninstallable name raises `locale.Error` as CPython's does.

Measured against CPython 3.14 on Windows: the six category numbers agree,
neither has `LC_MESSAGES`, `en_US.iso88591` raises `locale.Error` on both and
`en_US.utf8` and `English_United States.1252` are accepted by both.
`locale_categories` pins all three properties and fails on the prior binary.

* bench/synth: restore the three wasm jit-stats baselines #1086 reverted

#1106 `4555e3d76b` dropped the wasm32 arm of the self-recursive root-bridge
inline and recorded what that moved: `ca_bridge_multiframe_resume_double_call`
2581 -> 2592, `wasm_ca_trampoline_decline` 404 -> 601 and
`recursion_memo_branch` 4724 -> 4704. #1086 `e5eff81684` wrote all three back
to their pre-#1106 values, and ubuntu has failed on them every run since.

#1086 resizes 130 fixtures so pypy's side clears the measurement floor, and
re-recording a resized fixture's counters is part of that. It moves 34 baseline
values; 26 sit in fixtures whose `.py` it also changed. These three — and
`pypy_type_surface`, restored in 958f66c — are among the eight it moved with
no workload change beside them, which is a snapshot taken on a base predating
#1106.

Measured rather than reverted: a local wasm run reads 2592, 601 and 4704, which
are #1106's figures and the ones ubuntu observes. The remaining two of those
eight, `closure_per_call` 418 and `recursive_call_frame_relocation` 638, read
what they already record and are left alone.

The lower counts are not the better state. #1106 measured removing the decline
at -20.1%/-20.7% wasm CPU on `wasm_ca_trampoline_decline`; the +197 guard
failures buy that. `ca_bridge_multiframe_resume_double_call` pays +1.2%/+2.7%
and in exchange reports the 16 bridges / 0 aborts the dynasm baseline records,
where the decline left wasm at 16/1.

`retraces_compiled=0` comes with the re-record: these were the only wasm
baselines missing the key, which `_parse_jit_stats` was defaulting.
youknowone added a commit that referenced this pull request Aug 9, 2026
Rebasing onto `a7eb493079f` moved these counters. Measured on the final tree
with all three backends rebuilt from a full `extract-llbc.py`.

  synth/pypy_type_surface (all 3)   bridges_compiled 102 -> 5,
                                    guard_failures 20497 -> 1011
  synth/mapdict_frozen_unboxing_fold (all 3)  guard_failures 8 -> 11
  synth/ca_bridge_multiframe_resume_double_call (wasm)
                                    guard_failures 2581 -> 2592
  synth/closure_per_call (wasm)     guard_failures 418 -> 426
  synth/wasm_ca_trampoline_decline (wasm)  guard_failures 404 -> 601
  synth/recursion_memo_branch (wasm)  guard_failures 4724 -> 4704

`pypy_type_surface` returns to the values #999 committed. #1086 had rewritten
the file to 102 / 20497 — the numbers the `Cls.__name__` metaclass fold
produced while it guarded the raw `w_class` slot its oracle's `gettypefor`
fallback never read — and #1086 landed before #1106 declined that fold, so
the file has named a defect since. The fixed fold gives 5 / 1011 again.

`pypy_type_surface`, `ca_bridge_multiframe_resume_double_call` and
`wasm_ca_trampoline_decline` are also red on main's own CI at `b925c3e5ead`
(run 31283765874, ubuntu leg), so those three do not originate here.

An in-place control arm reverting only this branch's vable shadow write-back
reproduces every one of these numbers, so none of them is that change.

Assisted-by: Claude
youknowone added a commit that referenced this pull request Aug 9, 2026
Rebasing onto `a7eb493079f` moved these counters. Measured on the final tree
with all three backends rebuilt from a full `extract-llbc.py`.

  synth/pypy_type_surface (all 3)   bridges_compiled 102 -> 5,
                                    guard_failures 20497 -> 1011
  synth/mapdict_frozen_unboxing_fold (all 3)  guard_failures 8 -> 11
  synth/ca_bridge_multiframe_resume_double_call (wasm)
                                    guard_failures 2581 -> 2592
  synth/closure_per_call (wasm)     guard_failures 418 -> 426
  synth/wasm_ca_trampoline_decline (wasm)  guard_failures 404 -> 601
  synth/recursion_memo_branch (wasm)  guard_failures 4724 -> 4704

`pypy_type_surface` returns to the values #999 committed. #1086 had rewritten
the file to 102 / 20497 — the numbers the `Cls.__name__` metaclass fold
produced while it guarded the raw `w_class` slot its oracle's `gettypefor`
fallback never read — and #1086 landed before #1106 declined that fold, so
the file has named a defect since. The fixed fold gives 5 / 1011 again.

`pypy_type_surface`, `ca_bridge_multiframe_resume_double_call` and
`wasm_ca_trampoline_decline` are also red on main's own CI at `b925c3e5ead`
(run 31283765874, ubuntu leg), so those three do not originate here.

An in-place control arm reverting only this branch's vable shadow write-back
reproduces every one of these numbers, so none of them is that change.

Assisted-by: Claude
youknowone added a commit that referenced this pull request Aug 9, 2026
Rebasing onto `a7eb493079f` moved these counters. Measured on the final tree
with all three backends rebuilt from a full `extract-llbc.py`.

  synth/pypy_type_surface (all 3)   bridges_compiled 102 -> 5,
                                    guard_failures 20497 -> 1011
  synth/mapdict_frozen_unboxing_fold (all 3)  guard_failures 8 -> 11
  synth/ca_bridge_multiframe_resume_double_call (wasm)
                                    guard_failures 2581 -> 2592
  synth/closure_per_call (wasm)     guard_failures 418 -> 426
  synth/wasm_ca_trampoline_decline (wasm)  guard_failures 404 -> 601
  synth/recursion_memo_branch (wasm)  guard_failures 4724 -> 4704

`pypy_type_surface` returns to the values #999 committed. #1086 had rewritten
the file to 102 / 20497 — the numbers the `Cls.__name__` metaclass fold
produced while it guarded the raw `w_class` slot its oracle's `gettypefor`
fallback never read — and #1086 landed before #1106 declined that fold, so
the file has named a defect since. The fixed fold gives 5 / 1011 again.

`pypy_type_surface`, `ca_bridge_multiframe_resume_double_call` and
`wasm_ca_trampoline_decline` are also red on main's own CI at `b925c3e5ead`
(run 31283765874, ubuntu leg), so those three do not originate here.

An in-place control arm reverting only this branch's vable shadow write-back
reproduces every one of these numbers, so none of them is that change.

Assisted-by: Claude
youknowone added a commit that referenced this pull request Aug 10, 2026
Rebasing onto `a7eb493079f` moved these counters. Measured on the final tree
with all three backends rebuilt from a full `extract-llbc.py`.

  synth/pypy_type_surface (all 3)   bridges_compiled 102 -> 5,
                                    guard_failures 20497 -> 1011
  synth/mapdict_frozen_unboxing_fold (all 3)  guard_failures 8 -> 11
  synth/ca_bridge_multiframe_resume_double_call (wasm)
                                    guard_failures 2581 -> 2592
  synth/closure_per_call (wasm)     guard_failures 418 -> 426
  synth/wasm_ca_trampoline_decline (wasm)  guard_failures 404 -> 601
  synth/recursion_memo_branch (wasm)  guard_failures 4724 -> 4704

`pypy_type_surface` returns to the values #999 committed. #1086 had rewritten
the file to 102 / 20497 — the numbers the `Cls.__name__` metaclass fold
produced while it guarded the raw `w_class` slot its oracle's `gettypefor`
fallback never read — and #1086 landed before #1106 declined that fold, so
the file has named a defect since. The fixed fold gives 5 / 1011 again.

`pypy_type_surface`, `ca_bridge_multiframe_resume_double_call` and
`wasm_ca_trampoline_decline` are also red on main's own CI at `b925c3e5ead`
(run 31283765874, ubuntu leg), so those three do not originate here.

An in-place control arm reverting only this branch's vable shadow write-back
reproduces every one of these numbers, so none of them is that change.

Assisted-by: Claude
youknowone added a commit that referenced this pull request Aug 10, 2026
…ts, and a measured FOR_ITER gate widening (#1103)

* list: give the unused typed strategy an empty array, not a block

`build_list_storage` called `IntArray::from_vec` and `FloatArray::from_vec`
unconditionally, and `try_alloc_typed_items_block` clamps `cap` to 1 into the
old-gen `try_gc_alloc_stable_raw`, so every list allocated two blocks whose
strategy never reads them. The trace emitters leave those fields null:
`emit_empty_list_inline` and `emit_object_list_inline` set only `length` /
`items` / `strategy`, and `emit_typed_list_inline` writes one typed pair.

Add `IntArray::empty()` / `FloatArray::empty()` and use them where emptiness is
statically known — `build_list_storage`'s non-matching arms,
`switch_to_object_strategy`, `w_list_clear`. `switch_to_correct_strategy` keeps
`from_vec`, since its twin `emit_promote_empty_list_inline` emits a capacity-1
block and seeds the capacity getfield cache with 1.

`base()` takes `wrapping_add`, so the null block yields the items offset — a
non-null, 8-aligned address `from_raw_parts` accepts at length zero.

`list_object_custom_trace` skips the ownership query on a null typed block.

Assisted-by: Claude

* optimizeopt: answer an unwritten field of a virtual with its typed zero

virtualize.py:184-190 optimize_GETFIELD_GC_* resolves a field the virtual has
never been written to through optimizer.new_const(fielddescr).  Pyre carried
only the written-field arm, so such a read fell through to OptEarlyForce,
which forces every argument of a non-exempt operation and materialised the
struct along with everything its fields reach.

The array counterpart was already in place: NEW_ARRAY_CLEAR seeds every slot
with the typed zero at creation (virtualize.py:27-35, info.py:507-514).

typeptr keeps its own arm.  heaptracker.py:66 excludes it from the virtual
field set and the block above answers it from the descr vtable, so a struct
whose descr carries no vtable must not fold its class pointer to null.

Assisted-by: Claude

* mapdict: keep builtin storage on user subclasses

Restore exact int and bool objects to 24 bytes, Unicode objects to 64 bytes, and tuple objects to 40 bytes. Add distinct user-subclass layouts carrying mapdict map and storage fields, with their own GC types and traces.

Select the wider layouts from builtin subclass constructors and resolve mapdict field descriptors from each concrete carrier layout. Keep the specialized attribute load guarded by the subclass map and storage descriptors.

Record the wasm guard-count changes caused by the restored exact-object heap trajectory.

Assisted-by: Claude

* jit: record integer zero-divisor raising arms

Assisted-by: Claude

* mapdict: harden builtin subclass carriers

Guard the live Python class before native mapdict field access. Size map descriptors to the target word and exclude specialised tuple layouts. Mark private user layouts as GC objects without adding duplicate subclass-range peers. Re-root every mapdict carrier on class reassignment and allocate hasdict structseq values with tuple-user storage. Extend parity coverage for exact-value exits, descriptors, slots, GC inspection, and structseq extras.

Assisted-by: Claude

* jit: initialize inline allocation scalar fields

Assisted-by: Claude

* jit: record range zero-step raising arms

Assisted-by: Claude

* jit: record float zero-divisor raising arms

Assisted-by: Claude

* jit: record bigint zero-divisor raising arms

Assisted-by: Claude

* jit: record negative bigint shift raising arms

Assisted-by: Claude

* jit: scope FOR_ITER safety to escaping range loops

Assisted-by: Claude

* bench: re-record seven wasm jitstats baselines on the rebased base

Five of them (`exception_traceback_loop_forms`,
`gc_bug_bridge_flavor_traceback_names`, `loops_comprehension`,
`newslice_step_hot`, `unpack_ex_hot`) return to the values already committed on
the base; the rebase conflict resolution had kept this branch's older
measurements over them. Their only remaining difference from the base is added
counter keys.

`range_ctor_in_loop` compiles and enters its loop for the first time, so
loops_compiled 1 -> 5, bridges_compiled 0 -> 3 and guard_failures 0 -> 1009: a
fixture that never entered compiled code reported zero guard failures
trivially. An in-place revert of the FOR_ITER admission reproduced the old
values.

`closure_per_call` guard_failures moves 420 -> 417. This one is not attributed
by a control arm.

Assisted-by: Claude

* jit: diagnose FOR_ITER gate opcode declines

Assisted-by: Claude

* jit: gate FOR_ITER decline census allocation

Assisted-by: Claude

* jit: gate FOR_ITER decline census collection

Assisted-by: Claude

* jit: guard numeric binary specialization classes

Assisted-by: Claude

* jit: retain context on specialized builtin raises

Assisted-by: Claude

* jit: skip redundant numeric class guards

Assisted-by: Claude

* test: drive the numeric subclass fixture through the specialized pc

The fixture fed its subclass operand to a tail expression at a different
BINARY_OP pc than the loop that went hot, so that site was never specialized
and the check passed on a binary without the class guards.  Iterate a list
whose tail holds the subclass instead, so it arrives at the pc under test.

Adds left-operand cases and a bool-driven case, which reaches the tagged and
bool path where walker_numeric_builtin_class returns null and no class guard
is emitted at all.

Assisted-by: Claude

* Grow FOR_ITER regions through handler rejoins

Assisted-by: Claude

* Tighten escaping range append recognition

Assisted-by: Claude

* Update range constructor loop jitstats

Assisted-by: Claude

* jit: admit LIST_EXTEND in FOR_ITER bodies

Assisted-by: Claude

* jit: admit call-bearing LIST_APPEND bodies in the FOR_ITER gate

A LIST_APPEND body was admitted only when the body performed no call, because
a mid-body abort after the append routed through fbw_foriter_inflight_take,
which refuses delivery and dropped the iteration's item.

range_ctor_in_loop goes from mc_entered=0 to 813.

The surrounding comment previously cited blackhole.py as authority for the
append being rolled back and replayed once.  It is not: blackhole.py:1712 is
setposition, which continues from the coordinate already reached, and upstream
places the resume coordinate past a residual call so the effect is never
re-executed.  State instead what pyre actually relies on, and record that a
non-committed walk exit still keeps the legacy entry replay whose delivery can
be refused.

Assisted-by: Claude

* jit: census in-flight FOR_ITER delivery outcomes

Assisted-by: Claude

* bench: re-record nineteen jit-stats baselines

Five fixtures enter compiled code where they previously did not, so their
zero counters were zero trivially:

  exception_group_type      loops_compiled 0 -> 1, guard_failures 0 -> 1
  list_append_virtual_payload  loops_compiled 0 -> 2, bridges 0 -> 8,
                            guard_failures 0 -> 1603
  minmax_key_rooting        loops_compiled 1 -> 2, bridges 0 -> 2,
                            guard_failures 5 -> 409
  range_ctor_in_loop        loops_compiled 1 -> 3, bridges 0 -> 3,
                            guard_failures 0 -> 811 (812 on wasm)
  global_store_plain_dict_globals (wasm)  loops_compiled 5 -> 6,
                            loops_aborted 1 -> 2, guard_failures 1 -> 18
  pickle_terminal_raise_resume (wasm)  loops_compiled 67 -> 68,
                            loops_aborted 13 -> 14, guard_failures 339 -> 356

mapdict_frozen_unboxing_fold takes guard_failures 2 -> 8 with
loops_compiled unchanged at 3. An A/B across the call-bearing LIST_APPEND
admission alone gives mc_entered 2 -> 8 on the same fixture, so the counter
tracks compiled-code entries one for one: its `[C(i) for i in range(n)]`
comprehension is a call-bearing LIST_APPEND body.

gc_bug_bridge_flavor_traceback_names (wasm) improves guard_failures
2027 -> 1670.

exception_reused_object_tb_not_doubled (wasm) loses
fbw_blackhole_adopted_single_frame 3 -> 0. A binary built from
128590c with no branch commits applied reports 0 on the same fixture,
so the fall is the base's; the baseline was last recorded at 779da08.
Every other counter on that fixture is unchanged (loops 4, bridges 3,
aborted 3, guard_failures 600) and its traceback-shape oracle passes.

The recorder also writes the fbw_* and field_pos_* keys that were absent
from baselines recorded before those counters existed.

Assisted-by: Claude

* Trace traceback escape marking in exception attribute fold

Assisted-by: Claude

* Trace fresh container allocations in FOR_ITER callees

Admit replay-safe fresh tuple and list allocation helpers during nested callee tracing. Specialize len() for empty-list storage and add a cross-backend parity fixture for the admitted shape.

Assisted-by: Claude

* Admit tuple copies from exact lists during replay

Assisted-by: Claude

* Identify traceback walk bridge training

The 603 guard failures comprise three 200-hit bridge thresholds and three one-off transition failures. The final bridge reconnects the traceback walk to its compiled inner-loop token, so no resume-semantics change is required.

Assisted-by: Claude

* bench: add a synthetic fixture for the subscript inline's index operand

`Seq.__getitem__` reached as `p[len(EMPTY)]`, so the index arrives on the
operand stack rather than from a constant or a local, with an
`isinstance(index, slice)` branch in the body so the inline has a residual to
abort on. Prints 276000 under cpython, pypy3 and pyre.

The defect the shape covers — the FOR_ITER deferred admission reading
`arg_class_guard.is_none()` as a proxy for "the entry opcode is a CALL", which
admitted the BINARY_OP-entered subscript inline and let the flush resume one
operand short — is fixed in #1082, which names the property directly and
carries its own parity test. This holds the shape under the jit-stats gate too.

Assisted-by: Claude

* bench: re-record the wasm pickle terminal-raise baseline

`loops_compiled` 66 -> 67, `loops_aborted` 14 -> 15 and `guard_failures`
339 -> 356 on the wasm leg of `synth/pickle_terminal_raise_resume`.  The file
already carried the 356 from an earlier recording; the two loop counters did
not.  `retraces_compiled=0` joins the recorded set.

Bisected to `jit: admit call-bearing LIST_APPEND bodies in the FOR_ITER gate`
by in-place whole-tree control arms at four points of this branch: the base and
the trees at the three commits below it read 66 / 14 / 339, the tree at that
commit reads 67 / 15 / 356, and every counter moves there together.  A base
control arm reproduces main's committed 66 / 14 / 339 on this host, so the move
is this branch's and not the host's.

The dynasm and cranelift baselines for the same fixture are byte-identical to
main's (30 compiled, 1 aborted, 338 guard failures) and are unchanged here: the
loop the widened gate admits is one only the guest reaches, which compiles 66
loops in this fixture where the native backends compile 30.  The extra abort is
one more attempt at a loop the gate now allows, recorded beside the compile it
gained.

Not the collection schedule: `PYPY_GC_MIN` at 256MB, 384MB and 512MB gives
identical counters, and three repeats agree exactly.

Assisted-by: Claude

* jit: pair the vable static shadow write with a heap write-back

`mirror_vable_static_to_boxes` wrote `virtualizable_boxes` without the
`synchronize_virtualizable()` half `_opimpl_setfield_vable` performs
(pyjitpl.py:1188-1199). `walker_capture_snapshot_for_last_guard_impl`
publishes `last_instr = py_pc - 1` through it, and the walk never runs the
interpreter's own `frame.last_instr = pc` store, so the live frame stayed one
opcode behind the shadow and `check_synchronized_virtualizable`
(pyjitpl.py:3463-3468) failed under `debug_assertions` in
`gc_stress::module_dict_move_to_end_reentrant_survives_python_callbacks`.

Add `TraceCtx::synchronize_virtualizable_static`, a single-static
`write_boxes` that keeps `synchronize_virtualizable`'s guards and its
`VableArrayStorage::RustVec` carve-out. The full `write_all_boxes` is not
usable here: the shadow's array half holds NULL for the operand slots a
mid-opcode guard resumes before, and writing it back would stamp those NULLs
into the live frame. Call it from `mirror_vable_static_to_boxes`.

`try_execute_residual_call_via_executor` saves the `last_instr` shadow entry
before publishing the executing pc and restores it after the residual
returns, matching `LiveLastInstrGuard`'s save/restore of the heap half. The
restore is skipped when the callee forced the virtualizable.

Assisted-by: Claude

* docs: list the two FOR_ITER gate diagnostics in gate-triage

`PYRE_FOR_ITER_GATE_DIAG` (pyre-jit-trace/src/jitcode_dispatch/mod.rs,
pyre-jit/src/eval.rs) and `PYRE_FORITER_INFLIGHT_CENSUS`
(pyre-jit-trace/src/jitcode_dispatch/mod.rs) are read through
`env::var_os(..).is_some()`, so both are default-OFF diagnostics and belong in
§6c. `pyre/pyrex/tests/gate_triage_complete.rs
::every_live_pyre_gate_has_a_gate_triage_entry` failed on their absence.

Assisted-by: Claude

* bench: re-record ten jit-stats baselines after the rebase

Rebasing onto `a7eb493079f` moved these counters. Measured on the final tree
with all three backends rebuilt from a full `extract-llbc.py`.

  synth/pypy_type_surface (all 3)   bridges_compiled 102 -> 5,
                                    guard_failures 20497 -> 1011
  synth/mapdict_frozen_unboxing_fold (all 3)  guard_failures 8 -> 11
  synth/ca_bridge_multiframe_resume_double_call (wasm)
                                    guard_failures 2581 -> 2592
  synth/closure_per_call (wasm)     guard_failures 418 -> 426
  synth/wasm_ca_trampoline_decline (wasm)  guard_failures 404 -> 601
  synth/recursion_memo_branch (wasm)  guard_failures 4724 -> 4704

`pypy_type_surface` returns to the values #999 committed. #1086 had rewritten
the file to 102 / 20497 — the numbers the `Cls.__name__` metaclass fold
produced while it guarded the raw `w_class` slot its oracle's `gettypefor`
fallback never read — and #1086 landed before #1106 declined that fold, so
the file has named a defect since. The fixed fold gives 5 / 1011 again.

`pypy_type_surface`, `ca_bridge_multiframe_resume_double_call` and
`wasm_ca_trampoline_decline` are also red on main's own CI at `b925c3e5ead`
(run 31283765874, ubuntu leg), so those three do not originate here.

An in-place control arm reverting only this branch's vable shadow write-back
reproduces every one of these numbers, so none of them is that change.

Assisted-by: Claude

* jit: follow the InflightForiterBody field rename in the census

`InflightForiterBody::Jit` carries `jitcode_index: i32` since #1111, which
also made the identity negative when unresolvable. The census `code_ptr`
resolution still destructured the former `outer_jitcode_index: u32` and cast
it, so the crate stopped compiling once both sides met.

`raw_code_for_jitcode_index` indexes with the value, so a negative index
misses and the census keeps the live frame's code.

Assisted-by: Claude

* mapdict: split the layout predicate from the storage predicate

`has_mapdict_layout` answers the physical question — the allocation
carries the `MapdictStorageMixin` slots — and no longer consults
`w_type_get_hasdict` for the generated int/str/tuple user layouts.
`has_mapdict_storage` is that test plus the owning class's `hasdict`
flag, and `mapdict_carrier` now asserts the layout predicate, so a
`__slots__`-only native subclass no longer trips the assertion.

`is_generated_user_layout_family` carries the specialised-tuple
exclusion for the layout test, the storage test, and the carrier's
`W_TupleObjectUser` arm.

Assisted-by: Claude

* _structseq: re-read the pinned class after the tuple allocation

The array-backed tuple constructor can collect, so the class pointer
read before it can be stale when it is stored into the new object's
`w_class`. Re-read it from the shadow-stack slot after the allocation.

Assisted-by: Claude

* jit: gate the in-flight FOR_ITER census key lookup on the census

`raw_code_for_jitcode_index` runs `ensure_finish_setup` and borrows
`METAINTERP_SD`; `fbw_foriter_inflight_take` called it on every take
even though `census_record_foriter_inflight` returns immediately unless
`PYRE_FORITER_INFLIGHT_CENSUS` or `PYRE_FBW_DEBUG_ABORT` is set. The
enable check moves into `foriter_inflight_census_enabled`, which both
sites share.

Assisted-by: Claude

* jit: correct the exception descr group note on w_context

`w_context` is written by the raise lowering, not left zeroed by GC
pointer clearing.

Assisted-by: Claude

* test: scan the loop-region fixture in two passes

`loop_region_includes_out_of_line_handler_rejoining_mid_body` compared
each backward target against `outer_header` while still lowering it, so
a jump seen before the smallest target was missed. The scan now runs
twice over a shared target closure, each pass with its own `OpArgState`.

Assisted-by: Claude

* test: cover synchronize_virtualizable_static

Five cases: the single-field write-back, absent virtualizable state, an
out-of-range index, a RustVec-backed array field, and a shadow slot
holding no concrete.

Assisted-by: Claude

* majit: exclude the identity slot from the static write-back bound

`virtualizable_values`'s last slot holds the vable identity
(`virtualizable_boxes[-1]`), not a field value.
`synchronize_virtualizable_static` bounded `index` by the full vector
length, so a shadow shorter than the declared static count would have
written the identity ref into a static field. Bound by the data length.

Assisted-by: Claude

* jit: read PYRE_FOR_ITER_GATE_DIAG through one accessor

The per-opcode decline and the whole-region decline each owned a
function-local `OnceLock` for the same variable.

Assisted-by: Claude

* jit: admit builtin subclass carriers in the mapdict storage helpers

The seven mapdict residual wrappers tested their receiver with
`is_instance`, which is true only for an ordinary `W_ObjectObject`. The
generated int/str/tuple user layouts failed that test, and the wrappers
answer a value rather than declining: the unboxed reads returned 0 and
0.0, the boxed read returned PY_NULL, and all three writes returned
without storing.

`Flag.__or__` reads `other._value_`, so `Perm.R & Perm.R` computed
`4 & 0`; `test.test_enum`'s `OldTestIntFlag` test_and/test_or/test_xor/
test_type failed on that. Measured on the release dynasm build, an
unboxed int attribute read on an int/str/tuple subclass was wrong 1756/
2411/2498 times per run and correct under PYRE_NO_JIT=1.

The receiver test is now `has_mapdict_layout`, which is `mapdict_carrier`'s
own precondition, shared through `is_mapdict_carrier`.

The parity fixture gains loops that validate the loaded and stored values
for the unboxed int and float slots; the existing ones discard what they
load and so never observed this.

Assisted-by: Claude

* Revert "jit: admit call-bearing LIST_APPEND bodies in the FOR_ITER gate"

This reverts commit 2a0f91f.

The decline it removed is load-bearing. A comprehension whose body calls
a user Python function drops an element:
`[random.randrange(25) for i in range(size)]` returned 22 items for
size=23, and PYRE_FORITER_INFLIGHT_CENSUS reported DELIVERED=0 REFUSED=1
for that body pc on the same run. `test.test_heapq`'s test_heapsort
failed on the shortened list, raising IndexError from `heappop`.

The reverted commit argued the append always sits past the resume
coordinate; the census shows the refusal path is reachable, because the
call commits body effects that `fbw_foriter_inflight_take` sees as a
committed effect since the consume.

The parity fixture records the shape.

Assisted-by: Claude

* majit: drop the narrowed virtualizable static synchronizer

`mirror_vable_static_to_boxes` now calls `synchronize_virtualizable()`,
the shape `_opimpl_setfield_vable` uses (`pyjitpl.py:1188-1199`), so the
narrowed single-field variant and its tests have no caller.

Assisted-by: Claude

* bench: restore five jit-stats baselines the reverted gate had moved

The call-bearing LIST_APPEND admission raised loops_compiled and
bridges_compiled on exception_group_type, list_append_virtual_payload,
minmax_key_rooting, range_ctor_in_loop and subscr_user_getitem_stack_index;
reverting it returns them to what main records. mapdict_frozen_unboxing_fold's
guard_failures returns to 2, the value main carries — the branch's 11 was
recorded while the mapdict storage helpers answered zero.

dynasm only; the cranelift and wasm baselines follow.

Assisted-by: Claude

* bench: restore the cranelift jit-stats baselines to match

Same six benches as the dynasm pass, same direction and magnitude.

Assisted-by: Claude

* bench: restore the wasm jit-stats baselines to match

The same six benches as the dynasm and cranelift passes, plus
global_store_plain_dict_globals and pickle_terminal_raise_resume, whose
observed loops_compiled / loops_aborted / guard_failures all return to the
values main records.

closure_per_call keeps main's guard_failures: its loops_compiled and
bridges_compiled are unchanged, so the count drifts without a shape change.

Assisted-by: Claude
youknowone added a commit that referenced this pull request Aug 15, 2026
Twenty-four files, twelve fixtures across dynasm and cranelift.  Every moved
counter was attributed against an in-place control arm built from the same
base with a8c159480ef reverted.

Control and HEAD agree, both differ from the recorded baseline, so the move
came from the base rather than from a8c159480ef:

  comprehension_object_append_hot       bridges 18->14, guards 3610->2810
  comprehension_param_range_call_flush  bridges  3->2,  guards  600->400
  const_arg_call_resume                 bridges  9->6,  guards 1804->1204
  foriter_setadd_call_consuming_body    bridges 22->21, guards 3980->3780
  list_append_write_barrier_gc          bridges  5->4,  guards 1348->1152
  nested_list_comprehension_hot         bridges  6->4,  guards 1202->802
  recursive_forced_frame_kept_stack     bridges  5->4,  guards 1000->800,
                                        fbw_rolled_back_with_effects 0->1
  listcomp_hot                          guards 239->220

Those eight were last recorded at #1086, #1166 and 7cb84760d5b.

Moved by a8c159480ef.  Timings are direct min-of-N runs of the two binaries,
dynasm then cranelift:

  generator_tree_recursion         guards +/-1 (dynasm 2952->2951, cranelift
                                   2951->2952); -3.3% / -4.4%
  exc_mixed_classes_bridge_flavor  loops 1->2, bridges 3->4, guards 601->802;
                                   -25.5% / -22.7% at N=6000000
  inline_chain_depth_typeflip      bridges 18->19, guards 3702->3819;
                                   -17.8% / -24.8%
  exception_bridge_traceback_head  loops 1->2, bridges 3->4, guards 601->802;
                                   +6.4% / +3.6% at N=600000

exception_bridge_traceback_head is the only fixture that got slower.  It
carries the same counter movement as exc_mixed_classes_bridge_flavor, which
gets 25% faster, and differs from it only by reading
e.__traceback__.tb_frame.f_code.co_name in the handler.

Output is byte-identical to the control for all twelve fixtures on both
backends, rc=0.  retraces_compiled=0 is written into the files that lacked
the key.

Assisted-by: Claude
youknowone added a commit that referenced this pull request Aug 15, 2026
Twenty-four files, twelve fixtures across dynasm and cranelift.  Every moved
counter was attributed against an in-place control arm built from the same
base with a8c159480ef reverted.

Control and HEAD agree, both differ from the recorded baseline, so the move
came from the base rather than from a8c159480ef:

  comprehension_object_append_hot       bridges 18->14, guards 3610->2810
  comprehension_param_range_call_flush  bridges  3->2,  guards  600->400
  const_arg_call_resume                 bridges  9->6,  guards 1804->1204
  foriter_setadd_call_consuming_body    bridges 22->21, guards 3980->3780
  list_append_write_barrier_gc          bridges  5->4,  guards 1348->1152
  nested_list_comprehension_hot         bridges  6->4,  guards 1202->802
  recursive_forced_frame_kept_stack     bridges  5->4,  guards 1000->800,
                                        fbw_rolled_back_with_effects 0->1
  listcomp_hot                          guards 239->220

Those eight were last recorded at #1086, #1166 and 7cb84760d5b.

Moved by a8c159480ef.  Timings are direct min-of-N runs of the two binaries,
dynasm then cranelift:

  generator_tree_recursion         guards +/-1 (dynasm 2952->2951, cranelift
                                   2951->2952); -3.3% / -4.4%
  exc_mixed_classes_bridge_flavor  loops 1->2, bridges 3->4, guards 601->802;
                                   -25.5% / -22.7% at N=6000000
  inline_chain_depth_typeflip      bridges 18->19, guards 3702->3819;
                                   -17.8% / -24.8%
  exception_bridge_traceback_head  loops 1->2, bridges 3->4, guards 601->802;
                                   +6.4% / +3.6% at N=600000

exception_bridge_traceback_head is the only fixture that got slower.  It
carries the same counter movement as exc_mixed_classes_bridge_flavor, which
gets 25% faster, and differs from it only by reading
e.__traceback__.tb_frame.f_code.co_name in the handler.

Output is byte-identical to the control for all twelve fixtures on both
backends, rc=0.  retraces_compiled=0 is written into the files that lacked
the key.

Assisted-by: Claude
youknowone added a commit that referenced this pull request Aug 15, 2026
Twenty-four files, twelve fixtures across dynasm and cranelift.  Every moved
counter was attributed against an in-place control arm built from the same
base with a8c159480ef reverted.

Control and HEAD agree, both differ from the recorded baseline, so the move
came from the base rather than from a8c159480ef:

  comprehension_object_append_hot       bridges 18->14, guards 3610->2810
  comprehension_param_range_call_flush  bridges  3->2,  guards  600->400
  const_arg_call_resume                 bridges  9->6,  guards 1804->1204
  foriter_setadd_call_consuming_body    bridges 22->21, guards 3980->3780
  list_append_write_barrier_gc          bridges  5->4,  guards 1348->1152
  nested_list_comprehension_hot         bridges  6->4,  guards 1202->802
  recursive_forced_frame_kept_stack     bridges  5->4,  guards 1000->800,
                                        fbw_rolled_back_with_effects 0->1
  listcomp_hot                          guards 239->220

Those eight were last recorded at #1086, #1166 and 7cb84760d5b.

Moved by a8c159480ef.  Timings are direct min-of-N runs of the two binaries,
dynasm then cranelift:

  generator_tree_recursion         guards +/-1 (dynasm 2952->2951, cranelift
                                   2951->2952); -3.3% / -4.4%
  exc_mixed_classes_bridge_flavor  loops 1->2, bridges 3->4, guards 601->802;
                                   -25.5% / -22.7% at N=6000000
  inline_chain_depth_typeflip      bridges 18->19, guards 3702->3819;
                                   -17.8% / -24.8%
  exception_bridge_traceback_head  loops 1->2, bridges 3->4, guards 601->802;
                                   +6.4% / +3.6% at N=600000

exception_bridge_traceback_head is the only fixture that got slower.  It
carries the same counter movement as exc_mixed_classes_bridge_flavor, which
gets 25% faster, and differs from it only by reading
e.__traceback__.tb_frame.f_code.co_name in the handler.

Output is byte-identical to the control for all twelve fixtures on both
backends, rc=0.  retraces_compiled=0 is written into the files that lacked
the key.

Assisted-by: Claude
youknowone added a commit that referenced this pull request Aug 15, 2026
* jit: stop forcing the appended value's box in the list-append fold

`orthodox_list_append_commit` recorded an identity CastPtrToInt ->
CastIntToPtr pair on the appended value before descending the
`w_list_append` sub-walk, which made the value's pointer identity
observable and so materialized an otherwise non-escaping virtual. The
pair came in with the range FOR_ITER virtualization (#683) to stop the
sub-walk unboxing a loop-carried trace-entry scalar.

The forwarding it emulated is already there: `trace_box_int` /
`trace_box_float` stamp `class_now_known` and cache the payload field's
current SSA box at the boxing site, and `getfield_gc_i_pureornot`
returns that cached box on a hit, so the descended unbox reads this
iteration's payload with the value left virtual — the same forwarding
`OptVirtualize.optimize_GETFIELD_GC_I` performs in
rpython/jit/metainterp/optimizeopt/virtualize.py. The two
`set_opref_concrete` calls went with the pair; they stamped the OpRefs
the casts created, and the incoming `value_op` already carries its
concrete Ref.

Measured on bench/synth/list_pop_append, dynasm, GC-rewritten
steady-state loop body: 32 ops -> 22, one CallMallocNursery(32) and the
four stores initializing that box -> none, 8 guards -> 6 (the GuardClass
and w_class GuardValue applied to the freshly created box fold away once
the value keeps the class the boxing site already stamped). Reverting
the change puts the allocation back.

bench/synth/list_append_write_barrier_gc reports guard_failures 938 ->
941 on all three backends with loops_compiled, bridges_compiled and
loops_aborted unchanged; an in-place control arm at the previous base
reads 938 before the change and 941 after. Its Object-strategy appends
store the value itself, so the box is materialized at the store either
way and only the forcing point moves. Baselines re-recorded.

Assisted-by: Claude
Assisted-by: Codex

* jit: preserve box identity across short preambles

* jit: lazily load frozen indirect call targets

* jit: load the build-time descr pool per index instead of as one table

`descrs.bin` was one `bincode::serialize(&Vec<BhDescr>)`, and the blackhole
builder's `setup_descrs` took the deserialized slice, so constructing the
builder materialized all 4897 entries. `size_of::<BhDescr>()` is 552 bytes and
the per-entry `String`/`Vec`/`HashMap` payloads sit behind that, so the 1.78 MB
artefact expanded to 10.7 MB of retained heap. A run names 7 to 33 of those
entries.

Serialize each entry independently and add `descrs_index.bin` carrying the byte
offsets, matching the `jitcodes.bin` / `jitcodes_index.bin` pair. `descrs` on
the builder and on each blackhole frame becomes `&'static dyn DescrTable`;
`blackhole.py:102-103` only ever indexes the list, so the interface is
unchanged. Entries materialize on the index that names them and are leaked for
`&'static`, as the sibling jitcode table already does.

`rehydrate_build_descr_raw_sets` keeps its ordering and still visits every
entry, but through `load_descr_uncached`, which drops each one after use:
visiting the pool no longer implies retaining it. `descr_ref_at` calls the
rehydration `Once` before resolving so the container groups are published
before `make_descr_from_bh` reads the gccache.

`DescrTable::get` takes `&'static self`. Every holder is already a
`&'static dyn DescrTable`, and it lets the slice impl return a `&'static
BhDescr` without widening a borrow the type system never checked.

Adds `PYRE_DESCR_DEMAND`, which tallies the distinct pool indices a run
resolves, and an ignored `descr_startup_rss_decomposition` measurement.

Release RSS, same-run A/B against the parent binary:
`pass` 74.6 -> 52.4 MB, int loop 87.2 -> 62.1, list_pop_append 92.9 -> 66.6,
call_loop_local 89.7 -> 63.6.

Trace shape is unchanged: loops_compiled, bridges_compiled and guard_failures
are identical on both binaries for exception_traceback_loop_forms,
inline_chain_depth_typeflip and check_exc_match_invalid_class, and
descr_set_absent / ambiguous / stale_absent stay zero.

Assisted-by: Claude

* descr: mint the ExecutionContext group as a non-GC-managed struct

`EC_DESCR_GROUP` used `make_simple_descr_group`, which hardcodes the
GC-managed, headered shape. `ExecutionContext` is a plain Rust struct —
`EC_SIZE` is `size_of::<ExecutionContext>()` and the field offsets come from
`offset_of!` — so it carries no type-id word at `ref - GcHeader::SIZE`.

`StructPtrInfo.make_guards` gates `GUARD_GC_TYPE` on `is_gc_managed() &&
!headerless()`, so the group emitted `GUARD_GC_TYPE(ec, 0)`: a guard reading
the word before the EC allocation and comparing it against the group's own
`type_id 0`. It failed on every loop re-entry once the exported short-preamble
state began carrying a `StructPtrInfo` for the EC pointer.

Mint through `make_simple_descr_group_with_flags` with `is_gc_managed = false`.

On dynasm, `check_exc_match_invalid_class`, `type_immutable_reject` and
`exception_value_op_caught` return to their recorded jitstats
(`check_exc_match_invalid_class` guard_failures 201 -> 1), and no
`GuardGcType` remains in the compiled loop.

Assisted-by: Claude

* optimizeopt: skip GUARD_GC_TYPE when the descr names no type id

`StructPtrInfo.make_guards` / `ArrayPtrInfo.make_guards` read
`descr.type_id()` and emit `GUARD_GC_TYPE` against it. A serialized
`BhDescr::Array` that carries neither a `gc_type_id` nor a cache key resolves
to 0 through `BhDescr::resolve_gc_tid`, because the runtime array type ids are
handed out by `gc.register_type` at interpreter startup and the build-time
analyzer cannot see them. The guard was then emitted as `GUARD_GC_TYPE(x, 0)`.

0 is not an absent value at runtime — it is the `rclass.OBJECT` root header —
so the guard is wrong in both directions: it fails on every object with a real
header, and passes on a plain `object`, certifying a layout the optimizer never
named. The tid allocator starts at 1, so a 0 on the descr means no identity was
ever assigned.

Gate both arms on `type_id() != 0`. `GUARD_GC_TYPE` installs no info in the
optimizer (`rewrite.rs` passes it through or removes it on a constant), so the
skip costs only the runtime re-check.

On dynasm this returns `list_pop_append` (guard_failures 201 -> 1),
`minmax_key_rooting` (205 -> 5) and `listcomp_hot` (470 -> 239, bridges 2 -> 1)
to their recorded jitstats, with `list_pop_append` still answering `5 0` and the
`from_opref` rotation-loop reproducers still silent.

Assisted-by: Claude

* majit: bind a rebuilt short preamble's inputarg domain for the next retrace

`ExtendedShortPreambleBuilder::setup` seeded `phase1_to_inputarg` only from
each entry's `arg_mapping`, so an op whose argument was the original loop's
`InputArgRef` — not a mapped Label position — had no binding. Seed the map
positionally from `short_preamble.inputargs` first, and record the remapped
domain in a new `ShortPreamble::phase1_inputargs` so a preamble rebuilt by an
active builder can be re-bound by the next one. `jump_to_preamble` seeds the
same domain from the live builder's label args.

Heap replay in `OptContext` now emits `preamble_op.arg(0)` / `.arg(1)` rather
than routing them through `dep_or_materialize`, which collapsed the
`preamble_op` and `source_op` receiver identities and produced guards on an
exporting-phase box. `resolve_arg` is still called to decide whether the
operands are bindable at all.

`retrace_outer_loop_type_flip` goes from `loops_aborted=2 retraces_compiled=0`
back to its recorded `loops_aborted=0 retraces_compiled=1 bridges_compiled=1
guard_failures=201`; six other synth fixtures return to their recorded
jit-stats.

Assisted-by: Claude

* bench: re-record the synth jit-stats this branch moves

Each counter below was attributed against an `origin/main` (d5ae680)
control arm built in place from the branch's touched-file list, on both the
dynasm and cranelift backends. Only fixtures where the control reproduces the
committed baseline exactly — that is, where the delta is this branch's — are
re-recorded here. No badness field moved in any of them.

exc_mixed_classes_bridge_flavor, exception_bridge_traceback_head
  loops_compiled 2 -> 1, bridges_compiled 4 -> 3, guard_failures 802 -> 601.
  Reverting `jit: preserve box identity across short preambles` reproduces
  4/802/2, so that commit accounts for the whole delta. The dropped loop and
  bridge are not declines: FIRED=3, cb_entered=3, bridges_compiled=3 with
  cb_invalidloop, cb_arity_giveup, ceb_*, retrace_bailed, wct_declined and
  cl_hct_giveup all zero on both backends. A guard site that used to fail 201
  extra times is gone, so its bridge is never requested. Both fixtures still
  print their pinned expected output.

inline_chain_depth_typeflip   guard_failures 3681 -> 3702
list_append_write_barrier_gc  guard_failures 1345 -> 1348
bound_method_builtin_fold     guard_failures  458 ->  459 (cranelift only)
  Structure is unchanged — loops_compiled and bridges_compiled hold. The
  first reproduces 3702 across three runs against the control's 3681 across
  two. `list_append_write_barrier_gc` prints the same five lines as CPython.

Left alone deliberately: `gc_bug_bridge_flavor_traceback_names` (+3) and
`exception_escape_hot_callee_tb_node_once` (loops_compiled 16 -> 15) reproduce
identically on the control, and `sre_pattern_methods` / `sre_wasm_min` are
byte-identical between branch and control. Those baselines are stale against
main, not against this branch. The `.wasm.jitstats` files are untouched because
no wasm arm was measured; wasm counters are not a copy of dynasm's
(`inline_chain_depth_typeflip` records 3820 there, not 3681).

Assisted-by: Claude

* bench: restore the three small jit-stats deltas to their committed values

The previous commit re-recorded five fixtures. Three of them are being put
back: `inline_chain_depth_typeflip`, `list_append_write_barrier_gc` and
`bound_method_builtin_fold` (cranelift). Their deltas were +21, +3 and +1
guard_failures with loops_compiled and bridges_compiled unchanged, which is the
profile of warmup-table drift rather than a codegen change: `make_green_key`
builds the JitCell uhash from the pycode heap address, so which counter cells
cohabit a bucket — and therefore which units reach their trace threshold —
depends on total prior allocation, i.e. on every byte of the binary.

The decisive evidence is that these counters are not a single number across
platforms. For `inline_chain_depth_typeflip` the windows leg of run
31723002466 compared against `bridges_compiled=19, guard_failures=3818` while
the shared file records 18/3681, and the macOS leg did not flag the fixture at
all. Writing a number measured from one local darwin binary into a baseline
shared by every platform would trade a row that passes on macOS for one that
does not.

That is the same standard already applied to `gc_bug_bridge_flavor_traceback_
names`, `exception_escape_hot_callee_tb_node_once` and the `sre_*` pair, which
were left untouched for the same reason.

`exc_mixed_classes_bridge_flavor` and `exception_bridge_traceback_head` keep
their new values. Those are structural — a whole loop and a whole bridge — they
were attributed to a single commit by reverting it, and CI measured exactly the
same transition (`loops_compiled 2 -> 1, bridges_compiled 4 -> 3,
guard_failures 802 -> 601`) on its own binary.

Assisted-by: Claude

* gate-triage: register PYRE_DESCR_DEMAND, and re-record four CI-confirmed benches

`every_live_pyre_gate_has_a_gate_triage_entry` failed on all three cargo-test
legs: `PYRE_DESCR_DEMAND`, added with the per-index descr pool loader, reads the
environment but had no row in pyre/gate-triage.md. It is a default-OFF
measurement probe with no ON behaviour to graduate, so it joins §5's
diagnostics bucket with a note that it retires with the demand counter itself.

The jit-stats re-records are the four benches CI observed at exactly the values
measured here, which is the corroboration the previous commit was missing when
it put three of them back:

  inline_chain_depth_typeflip   guard_failures 3681 -> 3702
  list_append_write_barrier_gc  guard_failures 1345 -> 1348
  inheritance_dispatch          bridges_compiled 3 -> 4, guard_failures  601 ->  801
  nested_loop_gate_switch       bridges_compiled 6 -> 7, guard_failures 1796 -> 1900

The macOS leg of run 31796630818 printed those transitions verbatim, so they
are a property of the tree rather than of one local binary.

The last two are a compile-set effect, not codegen. Saved arms bisect them to
`majit: bind a rebuilt short preamble's inputarg domain for the next retrace`:
the arm carrying every other commit reproduces 3/601 and 6/1796. For
`inheritance_dispatch` the GC-rewritten steady loop is identical across the two
arms — 40 ops, same opcodes in the same order, differing only in SSA numbering
and in heap addresses embedded as GuardClass/GuardValue immediates — so the
extra bridge is an extra compiled unit, not a changed loop body.

Still not re-recorded, because the value measured here is not the value CI
reports: `str_fstring` (cranelift) and `bound_method_builtin_fold` (cranelift)
pass locally against their darwin baselines.

Assisted-by: Claude

* optimizeopt: resolve a layout guard's runtime tid, or decline the short preamble

`StructPtrInfo`/`ArrayPtrInfo::make_guards` read the descr's stamped
`type_id()` and skipped `GUARD_GC_TYPE` when it was 0. The skip removed the
only layout check on that short-preamble entry, so a loop could be re-entered
with a different GC representation while the hoisted accesses kept the
original descr's element interpretation.

0 is never a legitimate stamp — the allocator starts at 1 — but it is a live
header value (the `rclass.OBJECT` root), so guarding on it is wrong in both
directions and skipping it is unsound. Resolve the dense tid from the
structural `cache_key` through `gc_cache`, the same route `resolve_gc_tid`
takes, and decline through `signal_invalid_loop` when even that fails.
`make_guards` returns `bool`; `collect_use_box_guards` returns `Option`.

Resolved array tids are stamped back through `set_type_id`. Struct tids are
not: `SizeDescr` has no shared-reference setter.

Assisted-by: Claude

* optimizeopt: assert import_state's source/target on box identity

`unroll.py:496 assert source is not target` compares Box identity. The port
compared `OpRef` positions, which the surrounding code expects to coincide —
that is why it forwards to the carried `Rc` instead of re-materializing by
position — so the assertion fired in debug builds. Compare the resolved
`Operand`s, whose `PartialEq` is `Rc::ptr_eq`.

Also record why the neighbouring short-preamble seed zips two lists of
different lengths: the builder's Label domain and the body's jump args agree
only on their common prefix. Requiring equal arities takes
`retrace_outer_loop_type_flip` to `loops_aborted` 0 -> 2,
`retraces_compiled` 1 -> 0, `guard_failures` 201 -> 590 on both backends.

Assisted-by: Claude

* jit: keep the first index for a folded runtime fnaddr

Identical-code folding can map several build-time addresses onto one runtime
address, which the `FNADDR_CORRESPONDENCE` note already describes, so the
`assert!` on a duplicate insert aborted the process on a legitimate layout.
Keep the first index instead.

`indirect_target_lookup_decodes_only_the_matched_jitcode` compared
`JitCode.fnaddr`, a build address, against a runtime-address map key;
translate before comparing. Its cell-count assertions are absolute because
`load_jitcode_cells` leaks a fresh slice per thread, so the `spawn` is the
isolation — say so at the test.

Record why `frozen_indirectcall_dict` stays on the thread-local state: it is
what gives repeated lookups one `JitCode` object, and the jitcode arena it
derives from is per-thread, so a process-wide map would hand one thread a
body minted from another thread's family.

Assisted-by: Claude

* bench: re-record the six wasm jit-stats baselines this branch moves

The recorded wasm values encoded a wasm-vs-dynasm divergence that no longer
exists. Against the dynasm baselines checked in beside them, the values CI
observes on wasm now match exactly for five of the six —
exc_mixed_classes_bridge_flavor and exception_bridge_traceback_head at
1/3/601, inheritance_dispatch at 1/4/801, list_append_write_barrier_gc at
12/5/1348, nested_loop_gate_switch at 2/7/1900 — and inline_chain_depth_typeflip
agrees on loops and bridges (6/18) while its guard_failures reads 3745. The
direction differs per fixture, always toward dynasm, so this is convergence
rather than drift.

Two ubuntu CI runs (31805976746 and 31817779249) report identical numbers for
every one of the six, and no fixture header forbids re-recording. Only
loops_compiled, bridges_compiled and guard_failures are rewritten; no badness
field moved.

Assisted-by: Claude

* descr: mint the four PyCode field descrs as one group

`PYCODE_CODE_PTR_FIELD_DESCR`, `PYCODE_W_NAME_FIELD_DESCR`,
`PYCODE_CO_FIRSTLINENO_FIELD_DESCR` and `PYCODE_HIDDEN_APPLEVEL_FIELD_DESCR`
were standalone `PyreFieldDescr`s carrying `parent_descr: None`, but all four
are handed to `GetfieldGc*`. `ensure_ptr_info_arg0` reads
`descr.get_parent_descr()` whenever arg0 has no pointer info yet
(`optimizer.py:478`) and panicked there:
`getframe_root_loop_force_blackhole_crn_nonidempotent` aborted on all three
backends. The same `parent_descr: None` is present on the base revision; this
branch reached the path.

Mint the four through `make_simple_descr_group_with_flags`, so each field's
`parent_descr` is the owning SizeDescr and `index_in_parent` is its
offset-sorted slot. Offsets, field sizes, field types, signedness, mutability
and names are unchanged.

The group carries `W_CODE_GC_TYPE_ID` with `is_gc_managed = true`. The unkeyed
factory publishes only into the JIT descriptor snapshot —
`register_external_size` appends to `_cache_size_order` and never writes
`_cache_size[key]`, which is what `resolve_struct_tid` reads — so the
collector's `TypeInfo` table stays solely owned by `eval::initialize_gc`, and
`StructPtrInfo::make_guards` can emit `GUARD_GC_TYPE(code, 43)` against the
header `gc.register_type` already stamps.

Assisted-by: Claude

* majit: log the pre-optimization trace under jit-log-noopt

`compile.py:49-50 CompileData.optimize_trace` calls
`logger_noopt.log_loop_from_trace(self.trace)`, which `logger.py:15-24` wraps
in a `jit-log-noopt` section headed by the traced op count. pyre emitted only
`jit-log-opt-loop` / `jit-log-opt-bridge`, so no section showed the trace as
the optimizer receives it.

Emit the section at the optimizer entry in `compile_loop`, alongside the
existing `[jit-diag] entering optimizer` line.

Assisted-by: Claude

* majit: cache ordinary heap fields read off a virtualizable receiver

`PtrInfo::Virtualizable(VirtualizableFieldState)` had no arm in any field
accessor: `setfield` and `clear_field` fell through to `_ => {}`, `getfield`
and `has_preamble_field` to `_ => None` / `false`, and `set_preamble_field`'s
catch-all re-seated the whole PtrInfo as an `InstancePtrInfo`, dropping the
tracked virtualizable state. `ensure_ptr_info_arg0` also lists the variant
among the kinds it returns unchanged, so it is never upgraded to an info that
can hold fields. Every ordinary heap field written to a virtualizable receiver
was therefore discarded and every later read of it missed.

`info.py` has no virtualizable-specific subclass — the hierarchy ends at
`InstancePtrInfo` / `StructPtrInfo` — so upstream a virtualizable frame carries
a plain `InstancePtrInfo` and `optimizer.py:484 init_fields` gives each slot a
home in the one `_fields` list the heap cache consults.

Add `heap_fields` to `VirtualizableFieldState`, keyed by
`FieldDescr::index_in_parent`, and give the five accessors their arm. It cannot
share the existing `fields` vec, which is indexed in
`VirtualizableInfo::static_fields` order. `clear_field` is what
`CachedField::invalidate` clears through, so without that arm a cached value
would survive a call.

PyFrame is the virtualizable, so `inline_helper` traced six unfolded
`getfield_gc_r(p0, PyFrame.execution_context)` off one frame. Because those
receivers were distinct, the frame push/pop `topframeref` stores landed in
different slots and never coalesced; an emitted store of a virtual VRef forces
it, which is where the `NewWithVtable(VRefSizeDescr)` and the per-enter/leave
`ForceToken` came from.

Measured on `pyre/bench/inline_helper.py`, dynasm, `PYRE_NO_UNROLL=1` compiled
loop: 74 -> 52 ops, execution_context loads 6 -> 1, topframeref 10 -> 1,
NewWithVtable 4 -> 2. Peeled: 125 -> 79 ops, execution_context 12 -> 1,
topframeref 20 -> 1, NewWithVtable 4 -> 0. Output, loops_compiled,
bridges_compiled and guard_failures unchanged. Wall clock, min of 9 against
pypy 7.3.20: dynasm 1.80x -> 1.35x, cranelift 2.94x -> 1.37x.

Assisted-by: Claude

* bench: re-record twelve synthetic jitstats baselines

Twenty-four files, twelve fixtures across dynasm and cranelift.  Every moved
counter was attributed against an in-place control arm built from the same
base with a8c159480ef reverted.

Control and HEAD agree, both differ from the recorded baseline, so the move
came from the base rather than from a8c159480ef:

  comprehension_object_append_hot       bridges 18->14, guards 3610->2810
  comprehension_param_range_call_flush  bridges  3->2,  guards  600->400
  const_arg_call_resume                 bridges  9->6,  guards 1804->1204
  foriter_setadd_call_consuming_body    bridges 22->21, guards 3980->3780
  list_append_write_barrier_gc          bridges  5->4,  guards 1348->1152
  nested_list_comprehension_hot         bridges  6->4,  guards 1202->802
  recursive_forced_frame_kept_stack     bridges  5->4,  guards 1000->800,
                                        fbw_rolled_back_with_effects 0->1
  listcomp_hot                          guards 239->220

Those eight were last recorded at #1086, #1166 and 7cb84760d5b.

Moved by a8c159480ef.  Timings are direct min-of-N runs of the two binaries,
dynasm then cranelift:

  generator_tree_recursion         guards +/-1 (dynasm 2952->2951, cranelift
                                   2951->2952); -3.3% / -4.4%
  exc_mixed_classes_bridge_flavor  loops 1->2, bridges 3->4, guards 601->802;
                                   -25.5% / -22.7% at N=6000000
  inline_chain_depth_typeflip      bridges 18->19, guards 3702->3819;
                                   -17.8% / -24.8%
  exception_bridge_traceback_head  loops 1->2, bridges 3->4, guards 601->802;
                                   +6.4% / +3.6% at N=600000

exception_bridge_traceback_head is the only fixture that got slower.  It
carries the same counter movement as exc_mixed_classes_bridge_flavor, which
gets 25% faster, and differs from it only by reading
e.__traceback__.tb_frame.f_code.co_name in the handler.

Output is byte-identical to the control for all twelve fixtures on both
backends, rc=0.  retraces_compiled=0 is written into the files that lacked
the key.

Assisted-by: Claude

* bench: re-record eleven synthetic wasm jitstats baselines

Measured from a wasm run of `pyre/check.py --snapshot --backend wasm` on the
rebased tree.  The dynasm and cranelift halves of these fixtures were recorded
in the previous commit; the wasm halves were not, and the linux leg is the only
one that runs the wasm backend.

The wasm counters are not a copy of the other two backends'.  Two fixtures read
differently there:

  comprehension_object_append_hot  bridges 18->17, guards 3610->3410
                                   (dynasm/cranelift: 18->14, 3610->2810)
  inline_chain_depth_typeflip      guards 3745->3818
                                   (dynasm/cranelift: 3702->3819)

The remaining nine move as their dynasm and cranelift counterparts do.

Assisted-by: Claude

* bench: correct three synthetic wasm jitstats baselines

  arith_int_bool                  bridges 10 -> 11, guards 2211 -> 2307
  comprehension_object_append_hot bridges 17 -> 14, guards 3410 -> 2810
  short_circuit_value_kept_stack  bridges 12 -> 11, guards 2510 -> 2201

Each value is what the ubuntu leg observed on run 31879590864 and what a local
wasm run now reads, so the two agree exactly.

comprehension_object_append_hot was recorded at 17/3410 one commit ago.  That
reading came from a wasm run whose wasmtime `.cwasm` module cache had not been
rebuilt for the tree under test, so it measured an older module; the shared
baseline it produced disagreed with every other backend on the same host.  A
wasm re-record is only valid against a freshly built module.

arith_int_bool and short_circuit_value_kept_stack were not touched by this
branch.  Their counters moved under #1231, which keys the applied
write-barrier set through SameAs forwarding.

Assisted-by: Claude
youknowone added a commit that referenced this pull request Aug 16, 2026
Twenty-four files, twelve fixtures across dynasm and cranelift.  Every moved
counter was attributed against an in-place control arm built from the same
base with a8c159480ef reverted.

Control and HEAD agree, both differ from the recorded baseline, so the move
came from the base rather than from a8c159480ef:

  comprehension_object_append_hot       bridges 18->14, guards 3610->2810
  comprehension_param_range_call_flush  bridges  3->2,  guards  600->400
  const_arg_call_resume                 bridges  9->6,  guards 1804->1204
  foriter_setadd_call_consuming_body    bridges 22->21, guards 3980->3780
  list_append_write_barrier_gc          bridges  5->4,  guards 1348->1152
  nested_list_comprehension_hot         bridges  6->4,  guards 1202->802
  recursive_forced_frame_kept_stack     bridges  5->4,  guards 1000->800,
                                        fbw_rolled_back_with_effects 0->1
  listcomp_hot                          guards 239->220

Those eight were last recorded at #1086, #1166 and 7cb84760d5b.

Moved by a8c159480ef.  Timings are direct min-of-N runs of the two binaries,
dynasm then cranelift:

  generator_tree_recursion         guards +/-1 (dynasm 2952->2951, cranelift
                                   2951->2952); -3.3% / -4.4%
  exc_mixed_classes_bridge_flavor  loops 1->2, bridges 3->4, guards 601->802;
                                   -25.5% / -22.7% at N=6000000
  inline_chain_depth_typeflip      bridges 18->19, guards 3702->3819;
                                   -17.8% / -24.8%
  exception_bridge_traceback_head  loops 1->2, bridges 3->4, guards 601->802;
                                   +6.4% / +3.6% at N=600000

exception_bridge_traceback_head is the only fixture that got slower.  It
carries the same counter movement as exc_mixed_classes_bridge_flavor, which
gets 25% faster, and differs from it only by reading
e.__traceback__.tb_frame.f_code.co_name in the handler.

Output is byte-identical to the control for all twelve fixtures on both
backends, rc=0.  retraces_compiled=0 is written into the files that lacked
the key.

Assisted-by: Claude
youknowone added a commit that referenced this pull request Aug 16, 2026
Twenty-four files, twelve fixtures across dynasm and cranelift.  Every moved
counter was attributed against an in-place control arm built from the same
base with a8c159480ef reverted.

Control and HEAD agree, both differ from the recorded baseline, so the move
came from the base rather than from a8c159480ef:

  comprehension_object_append_hot       bridges 18->14, guards 3610->2810
  comprehension_param_range_call_flush  bridges  3->2,  guards  600->400
  const_arg_call_resume                 bridges  9->6,  guards 1804->1204
  foriter_setadd_call_consuming_body    bridges 22->21, guards 3980->3780
  list_append_write_barrier_gc          bridges  5->4,  guards 1348->1152
  nested_list_comprehension_hot         bridges  6->4,  guards 1202->802
  recursive_forced_frame_kept_stack     bridges  5->4,  guards 1000->800,
                                        fbw_rolled_back_with_effects 0->1
  listcomp_hot                          guards 239->220

Those eight were last recorded at #1086, #1166 and 7cb84760d5b.

Moved by a8c159480ef.  Timings are direct min-of-N runs of the two binaries,
dynasm then cranelift:

  generator_tree_recursion         guards +/-1 (dynasm 2952->2951, cranelift
                                   2951->2952); -3.3% / -4.4%
  exc_mixed_classes_bridge_flavor  loops 1->2, bridges 3->4, guards 601->802;
                                   -25.5% / -22.7% at N=6000000
  inline_chain_depth_typeflip      bridges 18->19, guards 3702->3819;
                                   -17.8% / -24.8%
  exception_bridge_traceback_head  loops 1->2, bridges 3->4, guards 601->802;
                                   +6.4% / +3.6% at N=600000

exception_bridge_traceback_head is the only fixture that got slower.  It
carries the same counter movement as exc_mixed_classes_bridge_flavor, which
gets 25% faster, and differs from it only by reading
e.__traceback__.tb_frame.f_code.co_name in the handler.

Output is byte-identical to the control for all twelve fixtures on both
backends, rc=0.  retraces_compiled=0 is written into the files that lacked
the key.

Assisted-by: Claude
youknowone added a commit that referenced this pull request Aug 16, 2026
Twenty-four files, twelve fixtures across dynasm and cranelift.  Every moved
counter was attributed against an in-place control arm built from the same
base with a8c159480ef reverted.

Control and HEAD agree, both differ from the recorded baseline, so the move
came from the base rather than from a8c159480ef:

  comprehension_object_append_hot       bridges 18->14, guards 3610->2810
  comprehension_param_range_call_flush  bridges  3->2,  guards  600->400
  const_arg_call_resume                 bridges  9->6,  guards 1804->1204
  foriter_setadd_call_consuming_body    bridges 22->21, guards 3980->3780
  list_append_write_barrier_gc          bridges  5->4,  guards 1348->1152
  nested_list_comprehension_hot         bridges  6->4,  guards 1202->802
  recursive_forced_frame_kept_stack     bridges  5->4,  guards 1000->800,
                                        fbw_rolled_back_with_effects 0->1
  listcomp_hot                          guards 239->220

Those eight were last recorded at #1086, #1166 and 7cb84760d5b.

Moved by a8c159480ef.  Timings are direct min-of-N runs of the two binaries,
dynasm then cranelift:

  generator_tree_recursion         guards +/-1 (dynasm 2952->2951, cranelift
                                   2951->2952); -3.3% / -4.4%
  exc_mixed_classes_bridge_flavor  loops 1->2, bridges 3->4, guards 601->802;
                                   -25.5% / -22.7% at N=6000000
  inline_chain_depth_typeflip      bridges 18->19, guards 3702->3819;
                                   -17.8% / -24.8%
  exception_bridge_traceback_head  loops 1->2, bridges 3->4, guards 601->802;
                                   +6.4% / +3.6% at N=600000

exception_bridge_traceback_head is the only fixture that got slower.  It
carries the same counter movement as exc_mixed_classes_bridge_flavor, which
gets 25% faster, and differs from it only by reading
e.__traceback__.tb_frame.f_code.co_name in the handler.

Output is byte-identical to the control for all twelve fixtures on both
backends, rc=0.  retraces_compiled=0 is written into the files that lacked
the key.

Assisted-by: Claude
youknowone added a commit that referenced this pull request Aug 16, 2026
…able (#1262)

* bench: re-record the synth jit-stats this branch moves

Each counter below was attributed against an `origin/main` (d5ae680)
control arm built in place from the branch's touched-file list, on both the
dynasm and cranelift backends. Only fixtures where the control reproduces the
committed baseline exactly — that is, where the delta is this branch's — are
re-recorded here. No badness field moved in any of them.

exc_mixed_classes_bridge_flavor, exception_bridge_traceback_head
  loops_compiled 2 -> 1, bridges_compiled 4 -> 3, guard_failures 802 -> 601.
  Reverting `jit: preserve box identity across short preambles` reproduces
  4/802/2, so that commit accounts for the whole delta. The dropped loop and
  bridge are not declines: FIRED=3, cb_entered=3, bridges_compiled=3 with
  cb_invalidloop, cb_arity_giveup, ceb_*, retrace_bailed, wct_declined and
  cl_hct_giveup all zero on both backends. A guard site that used to fail 201
  extra times is gone, so its bridge is never requested. Both fixtures still
  print their pinned expected output.

inline_chain_depth_typeflip   guard_failures 3681 -> 3702
list_append_write_barrier_gc  guard_failures 1345 -> 1348
bound_method_builtin_fold     guard_failures  458 ->  459 (cranelift only)
  Structure is unchanged — loops_compiled and bridges_compiled hold. The
  first reproduces 3702 across three runs against the control's 3681 across
  two. `list_append_write_barrier_gc` prints the same five lines as CPython.

Left alone deliberately: `gc_bug_bridge_flavor_traceback_names` (+3) and
`exception_escape_hot_callee_tb_node_once` (loops_compiled 16 -> 15) reproduce
identically on the control, and `sre_pattern_methods` / `sre_wasm_min` are
byte-identical between branch and control. Those baselines are stale against
main, not against this branch. The `.wasm.jitstats` files are untouched because
no wasm arm was measured; wasm counters are not a copy of dynasm's
(`inline_chain_depth_typeflip` records 3820 there, not 3681).

Assisted-by: Claude

* bench: re-record the six wasm jit-stats baselines this branch moves

The recorded wasm values encoded a wasm-vs-dynasm divergence that no longer
exists. Against the dynasm baselines checked in beside them, the values CI
observes on wasm now match exactly for five of the six —
exc_mixed_classes_bridge_flavor and exception_bridge_traceback_head at
1/3/601, inheritance_dispatch at 1/4/801, list_append_write_barrier_gc at
12/5/1348, nested_loop_gate_switch at 2/7/1900 — and inline_chain_depth_typeflip
agrees on loops and bridges (6/18) while its guard_failures reads 3745. The
direction differs per fixture, always toward dynasm, so this is convergence
rather than drift.

Two ubuntu CI runs (31805976746 and 31817779249) report identical numbers for
every one of the six, and no fixture header forbids re-recording. Only
loops_compiled, bridges_compiled and guard_failures are rewritten; no badness
field moved.

Assisted-by: Claude

* bench: re-record twelve synthetic jitstats baselines

Twenty-four files, twelve fixtures across dynasm and cranelift.  Every moved
counter was attributed against an in-place control arm built from the same
base with a8c159480ef reverted.

Control and HEAD agree, both differ from the recorded baseline, so the move
came from the base rather than from a8c159480ef:

  comprehension_object_append_hot       bridges 18->14, guards 3610->2810
  comprehension_param_range_call_flush  bridges  3->2,  guards  600->400
  const_arg_call_resume                 bridges  9->6,  guards 1804->1204
  foriter_setadd_call_consuming_body    bridges 22->21, guards 3980->3780
  list_append_write_barrier_gc          bridges  5->4,  guards 1348->1152
  nested_list_comprehension_hot         bridges  6->4,  guards 1202->802
  recursive_forced_frame_kept_stack     bridges  5->4,  guards 1000->800,
                                        fbw_rolled_back_with_effects 0->1
  listcomp_hot                          guards 239->220

Those eight were last recorded at #1086, #1166 and 7cb84760d5b.

Moved by a8c159480ef.  Timings are direct min-of-N runs of the two binaries,
dynasm then cranelift:

  generator_tree_recursion         guards +/-1 (dynasm 2952->2951, cranelift
                                   2951->2952); -3.3% / -4.4%
  exc_mixed_classes_bridge_flavor  loops 1->2, bridges 3->4, guards 601->802;
                                   -25.5% / -22.7% at N=6000000
  inline_chain_depth_typeflip      bridges 18->19, guards 3702->3819;
                                   -17.8% / -24.8%
  exception_bridge_traceback_head  loops 1->2, bridges 3->4, guards 601->802;
                                   +6.4% / +3.6% at N=600000

exception_bridge_traceback_head is the only fixture that got slower.  It
carries the same counter movement as exc_mixed_classes_bridge_flavor, which
gets 25% faster, and differs from it only by reading
e.__traceback__.tb_frame.f_code.co_name in the handler.

Output is byte-identical to the control for all twelve fixtures on both
backends, rc=0.  retraces_compiled=0 is written into the files that lacked
the key.

Assisted-by: Claude

* bench: restore three wasm jit-stats baselines to their pre-rebase values

The rebase onto `origin/main` resolved the conflicting regions of
`exc_mixed_classes_bridge_flavor.wasm`, `exception_bridge_traceback_head.wasm`
and `inline_chain_depth_typeflip.wasm` to the base, but non-conflicting hunks
of the same three files auto-merged from an older re-record on this branch,
leaving `bridges_compiled` 3/3/18 and `guard_failures` 601/601/3702. The
pre-rebase tip and `origin/main` both carry 4/4/19 and 802/802/3818.

Assisted-by: Claude

* llbc: derive the fingerprint input set from the artefact's own file table

`source=` hashed the whole cargo dependency closure of the extracted crate,
which is a superset of what the artefact holds: `majit-rlib` hashed 68 `.rs`
files for an artefact built from 8, and `pyre-jit` hashed 700 for 224. An edit
anywhere in that superset stales the artefact and fails the build through
`fail_if_llbc_stale`.

Every `.ullbc` carries `translated.files`, the repo-relative source files
Charon parsed. Persist those beside the artefact as `<output_name>.readfiles`
on each successful extraction, and hash that set instead. Two kinds of input
cannot appear there and are unioned in from `cargo metadata` rather than
listed: a proc macro contributes no file-table entry because its expansion is
inlined into the consumer, and a build script writes into `OUT_DIR`, which is
not repo-relative. `include_closure` still runs, for an `include*!` argument
that climbs out of the crate — `pyre-native`'s
`include_bytes!("../../../lib-python/3/test/certdata/keycert3.pem")` is
reached that way and the file table never names it.

The former whole-closure hash is kept as a new stamp field `closure=`. A
`source=` mismatch stays stale; a `closure=` mismatch alone warns, because the
file table cannot see a trait impl outside it changing method resolution. A
stamp without `closure=` is unknown, not fresh. Crates with no `.readfiles`
fall back to the wide set, so bootstrap does not produce a narrow answer.

`CrateSpec.excluded_deps` and its post-extraction symbol guard are removed: a
package with no read files now contributes no inputs by construction. The
guard is replaced by its inverse, which refuses an artefact whose file-table
crates escape the derived set. `fingerprint_pathspecs` stays for `corpus` and
for the fallback. `FINGERPRINT_SCHEMA` goes to 3.

`--self-test` gains a check that the derived set is closed under `include*!`;
removing the `include_closure` call makes it fail and name `keycert3.pem`.

Assisted-by: Claude

* llbc: judge an artefact file-table name by its drive, not only by absoluteness

`prepare Charon/LLBC (windows-latest)` refused extraction with
`C:Users/runneradmin/.../std/src/lib.rs:626 includes ...core_simd_docs.md,
which is outside the repository`. Charon spells the toolchain's own sources
drive-relative on Windows, and `PureWindowsPath("C:Users/x").is_absolute()` is
False because the name carries a drive with no root after it, so both
absolute-path checks passed it into the read set. `root / value` then discards
`root` and resolves against that drive's working directory, where the file
exists, so `include_closure` read rustc's `std/src/lib.rs` and refused the
`include_str!` reaching out of it.

Judge the name with `is_repo_relative_name`, which rejects a Windows drive
whether or not a root follows, and use it in both the artefact reader and the
`.readfiles` loader. The `C:/Users/...` spelling was already rejected by
`PureWindowsPath.is_absolute`; only the drive-relative one leaked.

`self_test_ullbc_files_table` gains both spellings. Removing the drive check
makes it fail with the toolchain file admitted as repo-local.

Assisted-by: Claude

* llbc: read both path separators in an artefact file-table name

`prepare Charon/LLBC (windows-latest)` refused `pyre-interpreter.ullbc` for a
file-table crate outside its derived fingerprint, naming
`pyre/pyre-interpreter/src/module/_immutables_map/../../../../../lib_pypy/_immutables_map.py`.
That is `_immutables_map/mod.rs`'s `include_str!` target, `lib_pypy/_immutables_map.py`,
with its `../` chain intact.

Charon separates with backslashes on that leg. `posixpath.normpath` reads no
separator in them, so the whole spelling stayed one component, the `..`
survived, and `Path(*parts)` re-split it only once a `WindowsPath` got hold of
it — which is why the refusal printed forward slashes for a name that arrived
with none. The result matched nothing `git ls-files` reports, so the file was
both uncovered and unhashed.

Canonicalise through `PureWindowsPath`, which reads both separators, before
normalising, and use that in the artefact reader and the `.readfiles` loader.
No file in this repository carries a backslash in its name, so nothing else
changes shape.

`self_test_ullbc_files_table` gains a backslash-separated name with a `../`
chain. Reverting the canonicalisation makes it fail with the `..` unresolved.

Assisted-by: Claude

* ci: restore the LLBC readfiles sidecar alongside its artefact

The per-crate LLBC caches listed `.ullbc`, `.ullbc.fingerprint` and the
layout sidecars but not `.ullbc.readfiles`, which now carries the file
table `source=` hashes. A run whose four caches all hit skips the
`Extract LLBC` step at the workflow level, so the extractor never gets
to notice the missing sidecar and re-derive it; every consumer then
computed `source=` over the whole cargo closure and reported all four
crates STALE against a current artefact.

Add the sidecar to the four cache paths and move the keys to an
`llbc2-` namespace: the key is the wide closure digest, which no change
to the extraction driver moves, so the already-stored sidecar-less
entries would keep restoring under the old keys.

`Compute LLBC fingerprints` now takes the `source=` line alone --
`--fingerprint` prints three fields and `$GITHUB_OUTPUT` parses one
`name=value` per line -- and fails when that line is absent.

`Verify prepared Charon/LLBC` asserts the sidecar in each consumer job.

Assisted-by: Claude

* llbc: fold the cross-target file tables into the derived read set

A layout pass compiles the crate again for its cross target and keeps
only `type_decls` from the result, deleting the full artefact. Its file
table went with it, so a source that only the cross-target translation
reads could never enter `source=` while the sidecar it shaped was
consumed as current. Take each cross-target file table before its
artefact is deleted and merge it into the persisted read set.

Measured after a full re-extraction of all four crates: every derived
digest is unchanged (`majit-rlib` 5f87e4de, `pyre-interpreter` 65542060,
identical to the values computed from the pre-existing sidecars) and the
read sets keep their sizes of 8/66/236/224. Today every cross-target
table is a subset of its host table, so this closes the gap in the
derivation without moving any current fingerprint. `FINGERPRINT_SCHEMA`
therefore stays at 3 -- the recorded digests still equal what this code
computes, and anything a cross-target table could add is in the
cross-target cargo closure that `closure=` already unions.

This is not the `majit-backend-wasm` case: `pyre-interpreter` reaches
four `majit-metainterp` files and never the backend on any target, so
those sources are outside its file table entirely and `closure=` is the
only channel that can see them.

`assert_readfiles_resolve` refuses a read set naming files that are not
in the repository. Charon roots a `Local` name at the extracted crate's
cargo workspace, which is the repository root only for members of the
top-level workspace; `majit/charon-corpus` carries its own `Cargo.lock`
and reports `src/lib.rs`. Such a set hashes nothing, so the artefact
would keep reading fresh no matter what its sources did.

The format test bound `closure` to the same digest as `source`, so a
parse that swapped the two, or filled `closure` from the source line,
passed. `fail_if_llbc_stale` splits stale from warning on that pair.

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