diff --git a/pyre/bench/fannkuch.cranelift.jitstats b/pyre/bench/fannkuch.cranelift.jitstats index 2cceb0b9d90..53255eda85e 100644 --- a/pyre/bench/fannkuch.cranelift.jitstats +++ b/pyre/bench/fannkuch.cranelift.jitstats @@ -2,7 +2,10 @@ bridges_compiled=22 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=0 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=5049 internal_compile_panics=0 loops_aborted=0 diff --git a/pyre/bench/fannkuch.dynasm.jitstats b/pyre/bench/fannkuch.dynasm.jitstats index 2cceb0b9d90..53255eda85e 100644 --- a/pyre/bench/fannkuch.dynasm.jitstats +++ b/pyre/bench/fannkuch.dynasm.jitstats @@ -2,7 +2,10 @@ bridges_compiled=22 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=0 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=5049 internal_compile_panics=0 loops_aborted=0 diff --git a/pyre/bench/fannkuch.wasm.jitstats b/pyre/bench/fannkuch.wasm.jitstats index 8d8a0b964d4..5283e2b61b4 100644 --- a/pyre/bench/fannkuch.wasm.jitstats +++ b/pyre/bench/fannkuch.wasm.jitstats @@ -2,7 +2,10 @@ bridges_compiled=22 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=0 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 field_pos_attached_misplaced=0 field_pos_spec_misplaced=0 guard_failures=5049 diff --git a/pyre/bench/fib_loop.cranelift.jitstats b/pyre/bench/fib_loop.cranelift.jitstats index c2c1f34ede9..79d46bcf250 100644 --- a/pyre/bench/fib_loop.cranelift.jitstats +++ b/pyre/bench/fib_loop.cranelift.jitstats @@ -2,7 +2,10 @@ bridges_compiled=0 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=0 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=189 internal_compile_panics=0 loops_aborted=0 diff --git a/pyre/bench/fib_loop.dynasm.jitstats b/pyre/bench/fib_loop.dynasm.jitstats index c2c1f34ede9..79d46bcf250 100644 --- a/pyre/bench/fib_loop.dynasm.jitstats +++ b/pyre/bench/fib_loop.dynasm.jitstats @@ -2,7 +2,10 @@ bridges_compiled=0 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=0 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=189 internal_compile_panics=0 loops_aborted=0 diff --git a/pyre/bench/fib_loop.wasm.jitstats b/pyre/bench/fib_loop.wasm.jitstats index ef0f65b3b1e..530525191be 100644 --- a/pyre/bench/fib_loop.wasm.jitstats +++ b/pyre/bench/fib_loop.wasm.jitstats @@ -2,7 +2,10 @@ bridges_compiled=0 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=0 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 field_pos_attached_misplaced=0 field_pos_spec_misplaced=0 guard_failures=189 diff --git a/pyre/bench/fib_recursive.cranelift.jitstats b/pyre/bench/fib_recursive.cranelift.jitstats index 8b8d8bd32bc..ad463b310f8 100644 --- a/pyre/bench/fib_recursive.cranelift.jitstats +++ b/pyre/bench/fib_recursive.cranelift.jitstats @@ -2,7 +2,10 @@ bridges_compiled=3 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=0 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=406 internal_compile_panics=0 loops_aborted=0 diff --git a/pyre/bench/fib_recursive.dynasm.jitstats b/pyre/bench/fib_recursive.dynasm.jitstats index 8b8d8bd32bc..ad463b310f8 100644 --- a/pyre/bench/fib_recursive.dynasm.jitstats +++ b/pyre/bench/fib_recursive.dynasm.jitstats @@ -2,7 +2,10 @@ bridges_compiled=3 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=0 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=406 internal_compile_panics=0 loops_aborted=0 diff --git a/pyre/bench/fib_recursive.wasm.jitstats b/pyre/bench/fib_recursive.wasm.jitstats index 13f6bf4928d..00b5b2003f1 100644 --- a/pyre/bench/fib_recursive.wasm.jitstats +++ b/pyre/bench/fib_recursive.wasm.jitstats @@ -2,7 +2,10 @@ bridges_compiled=3 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=0 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 field_pos_attached_misplaced=0 field_pos_spec_misplaced=0 guard_failures=406 diff --git a/pyre/bench/float_loop.cranelift.jitstats b/pyre/bench/float_loop.cranelift.jitstats index 8beed56f050..8a6215f77a3 100644 --- a/pyre/bench/float_loop.cranelift.jitstats +++ b/pyre/bench/float_loop.cranelift.jitstats @@ -2,7 +2,10 @@ bridges_compiled=0 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=0 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=1 internal_compile_panics=0 loops_aborted=0 diff --git a/pyre/bench/float_loop.dynasm.jitstats b/pyre/bench/float_loop.dynasm.jitstats index 8beed56f050..8a6215f77a3 100644 --- a/pyre/bench/float_loop.dynasm.jitstats +++ b/pyre/bench/float_loop.dynasm.jitstats @@ -2,7 +2,10 @@ bridges_compiled=0 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=0 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=1 internal_compile_panics=0 loops_aborted=0 diff --git a/pyre/bench/float_loop.wasm.jitstats b/pyre/bench/float_loop.wasm.jitstats index 62c98090fec..59f22855e15 100644 --- a/pyre/bench/float_loop.wasm.jitstats +++ b/pyre/bench/float_loop.wasm.jitstats @@ -2,7 +2,10 @@ bridges_compiled=0 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=0 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 field_pos_attached_misplaced=0 field_pos_spec_misplaced=0 guard_failures=1 diff --git a/pyre/bench/inline_helper.cranelift.jitstats b/pyre/bench/inline_helper.cranelift.jitstats index 1cc731febcf..fceea6eee13 100644 --- a/pyre/bench/inline_helper.cranelift.jitstats +++ b/pyre/bench/inline_helper.cranelift.jitstats @@ -2,7 +2,10 @@ bridges_compiled=0 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=0 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=1 internal_compile_panics=0 loops_aborted=0 diff --git a/pyre/bench/inline_helper.dynasm.jitstats b/pyre/bench/inline_helper.dynasm.jitstats index 1cc731febcf..fceea6eee13 100644 --- a/pyre/bench/inline_helper.dynasm.jitstats +++ b/pyre/bench/inline_helper.dynasm.jitstats @@ -2,7 +2,10 @@ bridges_compiled=0 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=0 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=1 internal_compile_panics=0 loops_aborted=0 diff --git a/pyre/bench/inline_helper.wasm.jitstats b/pyre/bench/inline_helper.wasm.jitstats index a0796ff2cd2..656842672ea 100644 --- a/pyre/bench/inline_helper.wasm.jitstats +++ b/pyre/bench/inline_helper.wasm.jitstats @@ -2,7 +2,10 @@ bridges_compiled=0 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=0 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 field_pos_attached_misplaced=0 field_pos_spec_misplaced=0 guard_failures=1 diff --git a/pyre/bench/int_loop.cranelift.jitstats b/pyre/bench/int_loop.cranelift.jitstats index 8beed56f050..8a6215f77a3 100644 --- a/pyre/bench/int_loop.cranelift.jitstats +++ b/pyre/bench/int_loop.cranelift.jitstats @@ -2,7 +2,10 @@ bridges_compiled=0 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=0 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=1 internal_compile_panics=0 loops_aborted=0 diff --git a/pyre/bench/int_loop.dynasm.jitstats b/pyre/bench/int_loop.dynasm.jitstats index 8beed56f050..8a6215f77a3 100644 --- a/pyre/bench/int_loop.dynasm.jitstats +++ b/pyre/bench/int_loop.dynasm.jitstats @@ -2,7 +2,10 @@ bridges_compiled=0 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=0 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=1 internal_compile_panics=0 loops_aborted=0 diff --git a/pyre/bench/int_loop.wasm.jitstats b/pyre/bench/int_loop.wasm.jitstats index 62c98090fec..59f22855e15 100644 --- a/pyre/bench/int_loop.wasm.jitstats +++ b/pyre/bench/int_loop.wasm.jitstats @@ -2,7 +2,10 @@ bridges_compiled=0 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=0 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 field_pos_attached_misplaced=0 field_pos_spec_misplaced=0 guard_failures=1 diff --git a/pyre/bench/nbody.cranelift.jitstats b/pyre/bench/nbody.cranelift.jitstats index 434fcead556..542f628a0d7 100644 --- a/pyre/bench/nbody.cranelift.jitstats +++ b/pyre/bench/nbody.cranelift.jitstats @@ -2,7 +2,10 @@ bridges_compiled=5 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=0 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=1547 internal_compile_panics=0 loops_aborted=0 diff --git a/pyre/bench/nbody.dynasm.jitstats b/pyre/bench/nbody.dynasm.jitstats index 434fcead556..542f628a0d7 100644 --- a/pyre/bench/nbody.dynasm.jitstats +++ b/pyre/bench/nbody.dynasm.jitstats @@ -2,7 +2,10 @@ bridges_compiled=5 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=0 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=1547 internal_compile_panics=0 loops_aborted=0 diff --git a/pyre/bench/nbody.wasm.jitstats b/pyre/bench/nbody.wasm.jitstats index 8707432d056..e1f095c5920 100644 --- a/pyre/bench/nbody.wasm.jitstats +++ b/pyre/bench/nbody.wasm.jitstats @@ -2,7 +2,10 @@ bridges_compiled=5 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=0 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 field_pos_attached_misplaced=0 field_pos_spec_misplaced=0 guard_failures=1547 diff --git a/pyre/bench/nested_loop.cranelift.jitstats b/pyre/bench/nested_loop.cranelift.jitstats index 114b48b9fd0..56ae0032eed 100644 --- a/pyre/bench/nested_loop.cranelift.jitstats +++ b/pyre/bench/nested_loop.cranelift.jitstats @@ -2,7 +2,10 @@ bridges_compiled=1 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=0 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=201 internal_compile_panics=0 loops_aborted=0 diff --git a/pyre/bench/nested_loop.dynasm.jitstats b/pyre/bench/nested_loop.dynasm.jitstats index 114b48b9fd0..56ae0032eed 100644 --- a/pyre/bench/nested_loop.dynasm.jitstats +++ b/pyre/bench/nested_loop.dynasm.jitstats @@ -2,7 +2,10 @@ bridges_compiled=1 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=0 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=201 internal_compile_panics=0 loops_aborted=0 diff --git a/pyre/bench/nested_loop.wasm.jitstats b/pyre/bench/nested_loop.wasm.jitstats index 3276873edf5..1e12ce579fd 100644 --- a/pyre/bench/nested_loop.wasm.jitstats +++ b/pyre/bench/nested_loop.wasm.jitstats @@ -2,7 +2,10 @@ bridges_compiled=1 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=0 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 field_pos_attached_misplaced=0 field_pos_spec_misplaced=0 guard_failures=201 diff --git a/pyre/bench/raise_catch_loop.cranelift.jitstats b/pyre/bench/raise_catch_loop.cranelift.jitstats index 114b48b9fd0..56ae0032eed 100644 --- a/pyre/bench/raise_catch_loop.cranelift.jitstats +++ b/pyre/bench/raise_catch_loop.cranelift.jitstats @@ -2,7 +2,10 @@ bridges_compiled=1 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=0 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=201 internal_compile_panics=0 loops_aborted=0 diff --git a/pyre/bench/raise_catch_loop.dynasm.jitstats b/pyre/bench/raise_catch_loop.dynasm.jitstats index 114b48b9fd0..56ae0032eed 100644 --- a/pyre/bench/raise_catch_loop.dynasm.jitstats +++ b/pyre/bench/raise_catch_loop.dynasm.jitstats @@ -2,7 +2,10 @@ bridges_compiled=1 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=0 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=201 internal_compile_panics=0 loops_aborted=0 diff --git a/pyre/bench/raise_catch_loop.wasm.jitstats b/pyre/bench/raise_catch_loop.wasm.jitstats index 3276873edf5..1e12ce579fd 100644 --- a/pyre/bench/raise_catch_loop.wasm.jitstats +++ b/pyre/bench/raise_catch_loop.wasm.jitstats @@ -2,7 +2,10 @@ bridges_compiled=1 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=0 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 field_pos_attached_misplaced=0 field_pos_spec_misplaced=0 guard_failures=201 diff --git a/pyre/bench/spectral_norm.cranelift.jitstats b/pyre/bench/spectral_norm.cranelift.jitstats index fc43af8db38..2b79ce7e891 100644 --- a/pyre/bench/spectral_norm.cranelift.jitstats +++ b/pyre/bench/spectral_norm.cranelift.jitstats @@ -2,7 +2,10 @@ bridges_compiled=2 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=0 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=520 internal_compile_panics=0 loops_aborted=0 diff --git a/pyre/bench/spectral_norm.dynasm.jitstats b/pyre/bench/spectral_norm.dynasm.jitstats index fc43af8db38..2b79ce7e891 100644 --- a/pyre/bench/spectral_norm.dynasm.jitstats +++ b/pyre/bench/spectral_norm.dynasm.jitstats @@ -2,7 +2,10 @@ bridges_compiled=2 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=0 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=520 internal_compile_panics=0 loops_aborted=0 diff --git a/pyre/bench/spectral_norm.wasm.jitstats b/pyre/bench/spectral_norm.wasm.jitstats index c55603e53a8..fc8b4fa7afa 100644 --- a/pyre/bench/spectral_norm.wasm.jitstats +++ b/pyre/bench/spectral_norm.wasm.jitstats @@ -2,7 +2,10 @@ bridges_compiled=2 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=0 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 field_pos_attached_misplaced=0 field_pos_spec_misplaced=0 guard_failures=520 diff --git a/pyre/bench/synth/blackhole_inlined_callee_local_after_escape.cranelift.jitstats b/pyre/bench/synth/blackhole_inlined_callee_local_after_escape.cranelift.jitstats index 4332a81169a..e90a95dda3b 100644 --- a/pyre/bench/synth/blackhole_inlined_callee_local_after_escape.cranelift.jitstats +++ b/pyre/bench/synth/blackhole_inlined_callee_local_after_escape.cranelift.jitstats @@ -2,7 +2,10 @@ bridges_compiled=0 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=5 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=1 internal_compile_panics=0 loops_aborted=5 diff --git a/pyre/bench/synth/blackhole_inlined_callee_local_after_escape.dynasm.jitstats b/pyre/bench/synth/blackhole_inlined_callee_local_after_escape.dynasm.jitstats index 4332a81169a..e90a95dda3b 100644 --- a/pyre/bench/synth/blackhole_inlined_callee_local_after_escape.dynasm.jitstats +++ b/pyre/bench/synth/blackhole_inlined_callee_local_after_escape.dynasm.jitstats @@ -2,7 +2,10 @@ bridges_compiled=0 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=5 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=1 internal_compile_panics=0 loops_aborted=5 diff --git a/pyre/bench/synth/blackhole_inlined_callee_local_after_escape.wasm.jitstats b/pyre/bench/synth/blackhole_inlined_callee_local_after_escape.wasm.jitstats index 4332a81169a..e90a95dda3b 100644 --- a/pyre/bench/synth/blackhole_inlined_callee_local_after_escape.wasm.jitstats +++ b/pyre/bench/synth/blackhole_inlined_callee_local_after_escape.wasm.jitstats @@ -2,7 +2,10 @@ bridges_compiled=0 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=5 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=1 internal_compile_panics=0 loops_aborted=5 diff --git a/pyre/bench/synth/ca_bridge_multiframe_resume_double_call.cranelift.jitstats b/pyre/bench/synth/ca_bridge_multiframe_resume_double_call.cranelift.jitstats index 4434c9138cc..2ba6a41eb8d 100644 --- a/pyre/bench/synth/ca_bridge_multiframe_resume_double_call.cranelift.jitstats +++ b/pyre/bench/synth/ca_bridge_multiframe_resume_double_call.cranelift.jitstats @@ -3,6 +3,7 @@ descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=2592 internal_compile_panics=0 loops_aborted=0 diff --git a/pyre/bench/synth/ca_bridge_multiframe_resume_double_call.dynasm.jitstats b/pyre/bench/synth/ca_bridge_multiframe_resume_double_call.dynasm.jitstats index 4434c9138cc..2ba6a41eb8d 100644 --- a/pyre/bench/synth/ca_bridge_multiframe_resume_double_call.dynasm.jitstats +++ b/pyre/bench/synth/ca_bridge_multiframe_resume_double_call.dynasm.jitstats @@ -3,6 +3,7 @@ descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=2592 internal_compile_panics=0 loops_aborted=0 diff --git a/pyre/bench/synth/ca_bridge_multiframe_resume_double_call.wasm.jitstats b/pyre/bench/synth/ca_bridge_multiframe_resume_double_call.wasm.jitstats index aef30c8349a..9608ba1836a 100644 --- a/pyre/bench/synth/ca_bridge_multiframe_resume_double_call.wasm.jitstats +++ b/pyre/bench/synth/ca_bridge_multiframe_resume_double_call.wasm.jitstats @@ -2,7 +2,8 @@ bridges_compiled=16 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 -fbw_rolled_back_with_effects=1 +fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=2581 internal_compile_panics=0 loops_aborted=1 diff --git a/pyre/bench/synth/getframe_bridge_force_after_store.cranelift.jitstats b/pyre/bench/synth/getframe_bridge_force_after_store.cranelift.jitstats new file mode 100644 index 00000000000..959c5f5446c --- /dev/null +++ b/pyre/bench/synth/getframe_bridge_force_after_store.cranelift.jitstats @@ -0,0 +1,14 @@ +bridges_compiled=0 +descr_set_absent=0 +descr_set_ambiguous=0 +descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=20 +fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 +field_pos_attached_misplaced=0 +field_pos_spec_misplaced=0 +guard_failures=4114 +internal_compile_panics=0 +loops_aborted=20 +loops_compiled=1 diff --git a/pyre/bench/synth/getframe_bridge_force_after_store.dynasm.jitstats b/pyre/bench/synth/getframe_bridge_force_after_store.dynasm.jitstats new file mode 100644 index 00000000000..959c5f5446c --- /dev/null +++ b/pyre/bench/synth/getframe_bridge_force_after_store.dynasm.jitstats @@ -0,0 +1,14 @@ +bridges_compiled=0 +descr_set_absent=0 +descr_set_ambiguous=0 +descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=20 +fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 +field_pos_attached_misplaced=0 +field_pos_spec_misplaced=0 +guard_failures=4114 +internal_compile_panics=0 +loops_aborted=20 +loops_compiled=1 diff --git a/pyre/bench/synth/getframe_bridge_force_after_store.py b/pyre/bench/synth/getframe_bridge_force_after_store.py new file mode 100644 index 00000000000..3d0b95ba2b1 --- /dev/null +++ b/pyre/bench/synth/getframe_bridge_force_after_store.py @@ -0,0 +1,39 @@ +# The bridge forced-vable escape of `getframe_bridge_force_plain`, with one +# un-journaled store ahead of the forcing call. +# +# `box.n = i` lowers to a Void `store_attr_fn` residual: it writes live heap, so +# it bumps the executed-effect odometer, and no journal covers it. Rolling the +# walk back therefore cannot undo the store, and the legacy entry replay would +# apply it a second time. The escape has to capture its operand-stack mirror and +# resume forward instead, which is what the recorded +# `fbw_blackhole_adopted_single_frame` pins; `fbw_rolled_back_with_effects` back +# above zero means the capture broke and the store is running twice again. +# +# The forcing residual itself never contributes an effect: the force branch +# returns before the odometer bump, so a bridge escape needs a second, earlier +# effectful op to register at all -- which is exactly what this file adds. +import sys + +_gf = sys._getframe + + +class Box: + n = 0 + + +box = Box() + + +def main(): + total = 0 + names = 0 + for i in range(400000): + if i % 97 == 0: + box.n = i + fr = _gf(0) + names += len(fr.f_code.co_name) + total += i + return total, names, box.n + + +print(main()) diff --git a/pyre/bench/synth/getframe_bridge_force_after_store.wasm.jitstats b/pyre/bench/synth/getframe_bridge_force_after_store.wasm.jitstats new file mode 100644 index 00000000000..959c5f5446c --- /dev/null +++ b/pyre/bench/synth/getframe_bridge_force_after_store.wasm.jitstats @@ -0,0 +1,14 @@ +bridges_compiled=0 +descr_set_absent=0 +descr_set_ambiguous=0 +descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=20 +fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 +field_pos_attached_misplaced=0 +field_pos_spec_misplaced=0 +guard_failures=4114 +internal_compile_panics=0 +loops_aborted=20 +loops_compiled=1 diff --git a/pyre/bench/synth/getframe_bridge_force_plain.cranelift.jitstats b/pyre/bench/synth/getframe_bridge_force_plain.cranelift.jitstats new file mode 100644 index 00000000000..7742a65cb84 --- /dev/null +++ b/pyre/bench/synth/getframe_bridge_force_plain.cranelift.jitstats @@ -0,0 +1,12 @@ +bridges_compiled=0 +descr_set_absent=0 +descr_set_ambiguous=0 +descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=20 +fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 +guard_failures=4114 +internal_compile_panics=0 +loops_aborted=20 +loops_compiled=1 diff --git a/pyre/bench/synth/getframe_bridge_force_plain.dynasm.jitstats b/pyre/bench/synth/getframe_bridge_force_plain.dynasm.jitstats new file mode 100644 index 00000000000..7742a65cb84 --- /dev/null +++ b/pyre/bench/synth/getframe_bridge_force_plain.dynasm.jitstats @@ -0,0 +1,12 @@ +bridges_compiled=0 +descr_set_absent=0 +descr_set_ambiguous=0 +descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=20 +fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 +guard_failures=4114 +internal_compile_panics=0 +loops_aborted=20 +loops_compiled=1 diff --git a/pyre/bench/synth/getframe_bridge_force_plain.py b/pyre/bench/synth/getframe_bridge_force_plain.py new file mode 100644 index 00000000000..797d1531a77 --- /dev/null +++ b/pyre/bench/synth/getframe_bridge_force_plain.py @@ -0,0 +1,36 @@ +# Coverage for the forced-vable escape on a BRIDGE walk, which the rest of the +# corpus never produces: of 138 forced escapes across the synth fixtures, zero +# are `bridge=true`. +# +# Shape, each clause load-bearing: +# * the `for` loop compiles on the common arm; +# * `i % 97 == 0` is the rare arm, so its guard fails ~4124 times -- past +# `DEFAULT_TRACE_EAGERNESS` -- and `start_bridge_tracing` sets +# `ctx.is_bridge_trace`, making the walk over the rare arm a bridge walk; +# * `_gf(0)` is a `CallFn` residual returning a Ref that forces the +# virtualizable, and it is a builtin, so `frame_entry_count()` does not move +# and no user Python frame is entered; +# * the call sits directly in the portal frame's loop body, so the framestack +# is empty and this is not an inline sub-walk. +# +# With nothing else in the rare arm the escape's mirror image resolves and the +# walk adopts a single-frame blackhole terminal. Its sibling +# `getframe_bridge_force_after_store` puts an un-journaled store ahead of the +# forcing call and takes the replay path instead. +import sys + +_gf = sys._getframe + + +def main(): + total = 0 + names = 0 + for i in range(400000): + if i % 97 == 0: + fr = _gf(0) + names += len(fr.f_code.co_name) + total += i + return total, names + + +print(main()) diff --git a/pyre/bench/synth/getframe_bridge_force_plain.wasm.jitstats b/pyre/bench/synth/getframe_bridge_force_plain.wasm.jitstats new file mode 100644 index 00000000000..7742a65cb84 --- /dev/null +++ b/pyre/bench/synth/getframe_bridge_force_plain.wasm.jitstats @@ -0,0 +1,12 @@ +bridges_compiled=0 +descr_set_absent=0 +descr_set_ambiguous=0 +descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=20 +fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 +guard_failures=4114 +internal_compile_panics=0 +loops_aborted=20 +loops_compiled=1 diff --git a/pyre/bench/synth/getframe_caller_locals_nested_compiled_callee.cranelift.jitstats b/pyre/bench/synth/getframe_caller_locals_nested_compiled_callee.cranelift.jitstats index 8aaccc5f2c5..17a65fcb8fb 100644 --- a/pyre/bench/synth/getframe_caller_locals_nested_compiled_callee.cranelift.jitstats +++ b/pyre/bench/synth/getframe_caller_locals_nested_compiled_callee.cranelift.jitstats @@ -2,7 +2,10 @@ bridges_compiled=1 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=0 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=214 internal_compile_panics=0 loops_aborted=0 diff --git a/pyre/bench/synth/getframe_caller_locals_nested_compiled_callee.dynasm.jitstats b/pyre/bench/synth/getframe_caller_locals_nested_compiled_callee.dynasm.jitstats index 8aaccc5f2c5..17a65fcb8fb 100644 --- a/pyre/bench/synth/getframe_caller_locals_nested_compiled_callee.dynasm.jitstats +++ b/pyre/bench/synth/getframe_caller_locals_nested_compiled_callee.dynasm.jitstats @@ -2,7 +2,10 @@ bridges_compiled=1 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=0 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=214 internal_compile_panics=0 loops_aborted=0 diff --git a/pyre/bench/synth/getframe_force_cancel_journal.cranelift.jitstats b/pyre/bench/synth/getframe_force_cancel_journal.cranelift.jitstats index 17df870455c..48f9c4225bc 100644 --- a/pyre/bench/synth/getframe_force_cancel_journal.cranelift.jitstats +++ b/pyre/bench/synth/getframe_force_cancel_journal.cranelift.jitstats @@ -2,7 +2,10 @@ bridges_compiled=0 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=5 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=0 internal_compile_panics=0 loops_aborted=5 diff --git a/pyre/bench/synth/getframe_force_cancel_journal.dynasm.jitstats b/pyre/bench/synth/getframe_force_cancel_journal.dynasm.jitstats index 17df870455c..48f9c4225bc 100644 --- a/pyre/bench/synth/getframe_force_cancel_journal.dynasm.jitstats +++ b/pyre/bench/synth/getframe_force_cancel_journal.dynasm.jitstats @@ -2,7 +2,10 @@ bridges_compiled=0 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=5 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=0 internal_compile_panics=0 loops_aborted=5 diff --git a/pyre/bench/synth/getframe_force_cancel_journal.wasm.jitstats b/pyre/bench/synth/getframe_force_cancel_journal.wasm.jitstats index 17df870455c..48f9c4225bc 100644 --- a/pyre/bench/synth/getframe_force_cancel_journal.wasm.jitstats +++ b/pyre/bench/synth/getframe_force_cancel_journal.wasm.jitstats @@ -2,7 +2,10 @@ bridges_compiled=0 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=5 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=0 internal_compile_panics=0 loops_aborted=5 diff --git a/pyre/bench/synth/getframe_inline_subwalk_multiframe.cranelift.jitstats b/pyre/bench/synth/getframe_inline_subwalk_multiframe.cranelift.jitstats index 53e8eaf6bb6..b1643b10f47 100644 --- a/pyre/bench/synth/getframe_inline_subwalk_multiframe.cranelift.jitstats +++ b/pyre/bench/synth/getframe_inline_subwalk_multiframe.cranelift.jitstats @@ -2,7 +2,10 @@ bridges_compiled=0 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=5 +fbw_blackhole_adopted_single_frame=9 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=0 internal_compile_panics=0 loops_aborted=15 diff --git a/pyre/bench/synth/getframe_inline_subwalk_multiframe.dynasm.jitstats b/pyre/bench/synth/getframe_inline_subwalk_multiframe.dynasm.jitstats index 53e8eaf6bb6..b1643b10f47 100644 --- a/pyre/bench/synth/getframe_inline_subwalk_multiframe.dynasm.jitstats +++ b/pyre/bench/synth/getframe_inline_subwalk_multiframe.dynasm.jitstats @@ -2,7 +2,10 @@ bridges_compiled=0 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=5 +fbw_blackhole_adopted_single_frame=9 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=0 internal_compile_panics=0 loops_aborted=15 diff --git a/pyre/bench/synth/getframe_inline_subwalk_multiframe.wasm.jitstats b/pyre/bench/synth/getframe_inline_subwalk_multiframe.wasm.jitstats index 53e8eaf6bb6..b1643b10f47 100644 --- a/pyre/bench/synth/getframe_inline_subwalk_multiframe.wasm.jitstats +++ b/pyre/bench/synth/getframe_inline_subwalk_multiframe.wasm.jitstats @@ -2,7 +2,10 @@ bridges_compiled=0 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=5 +fbw_blackhole_adopted_single_frame=9 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=0 internal_compile_panics=0 loops_aborted=15 diff --git a/pyre/bench/synth/getframe_inlined_callee_own_frame.cranelift.jitstats b/pyre/bench/synth/getframe_inlined_callee_own_frame.cranelift.jitstats index 5d9438ae0aa..337a2cb819b 100644 --- a/pyre/bench/synth/getframe_inlined_callee_own_frame.cranelift.jitstats +++ b/pyre/bench/synth/getframe_inlined_callee_own_frame.cranelift.jitstats @@ -2,7 +2,10 @@ bridges_compiled=0 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=9 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=0 internal_compile_panics=0 loops_aborted=10 diff --git a/pyre/bench/synth/getframe_inlined_callee_own_frame.dynasm.jitstats b/pyre/bench/synth/getframe_inlined_callee_own_frame.dynasm.jitstats index 5d9438ae0aa..337a2cb819b 100644 --- a/pyre/bench/synth/getframe_inlined_callee_own_frame.dynasm.jitstats +++ b/pyre/bench/synth/getframe_inlined_callee_own_frame.dynasm.jitstats @@ -2,7 +2,10 @@ bridges_compiled=0 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=9 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=0 internal_compile_panics=0 loops_aborted=10 diff --git a/pyre/bench/synth/getframe_inlined_callee_own_frame.wasm.jitstats b/pyre/bench/synth/getframe_inlined_callee_own_frame.wasm.jitstats index 5d9438ae0aa..337a2cb819b 100644 --- a/pyre/bench/synth/getframe_inlined_callee_own_frame.wasm.jitstats +++ b/pyre/bench/synth/getframe_inlined_callee_own_frame.wasm.jitstats @@ -2,7 +2,10 @@ bridges_compiled=0 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=9 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=0 internal_compile_panics=0 loops_aborted=10 diff --git a/pyre/bench/synth/getframe_residual_callee_own_frame.cranelift.jitstats b/pyre/bench/synth/getframe_residual_callee_own_frame.cranelift.jitstats index 4332a81169a..e90a95dda3b 100644 --- a/pyre/bench/synth/getframe_residual_callee_own_frame.cranelift.jitstats +++ b/pyre/bench/synth/getframe_residual_callee_own_frame.cranelift.jitstats @@ -2,7 +2,10 @@ bridges_compiled=0 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=5 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=1 internal_compile_panics=0 loops_aborted=5 diff --git a/pyre/bench/synth/getframe_residual_callee_own_frame.dynasm.jitstats b/pyre/bench/synth/getframe_residual_callee_own_frame.dynasm.jitstats index 4332a81169a..e90a95dda3b 100644 --- a/pyre/bench/synth/getframe_residual_callee_own_frame.dynasm.jitstats +++ b/pyre/bench/synth/getframe_residual_callee_own_frame.dynasm.jitstats @@ -2,7 +2,10 @@ bridges_compiled=0 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=5 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=1 internal_compile_panics=0 loops_aborted=5 diff --git a/pyre/bench/synth/getframe_residual_callee_own_frame.wasm.jitstats b/pyre/bench/synth/getframe_residual_callee_own_frame.wasm.jitstats index 4332a81169a..e90a95dda3b 100644 --- a/pyre/bench/synth/getframe_residual_callee_own_frame.wasm.jitstats +++ b/pyre/bench/synth/getframe_residual_callee_own_frame.wasm.jitstats @@ -2,7 +2,10 @@ bridges_compiled=0 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=5 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=1 internal_compile_panics=0 loops_aborted=5 diff --git a/pyre/bench/synth/getframe_root_loop_force_blackhole_crn.cranelift.jitstats b/pyre/bench/synth/getframe_root_loop_force_blackhole_crn.cranelift.jitstats index 17df870455c..48f9c4225bc 100644 --- a/pyre/bench/synth/getframe_root_loop_force_blackhole_crn.cranelift.jitstats +++ b/pyre/bench/synth/getframe_root_loop_force_blackhole_crn.cranelift.jitstats @@ -2,7 +2,10 @@ bridges_compiled=0 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=5 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=0 internal_compile_panics=0 loops_aborted=5 diff --git a/pyre/bench/synth/getframe_root_loop_force_blackhole_crn.dynasm.jitstats b/pyre/bench/synth/getframe_root_loop_force_blackhole_crn.dynasm.jitstats index 17df870455c..48f9c4225bc 100644 --- a/pyre/bench/synth/getframe_root_loop_force_blackhole_crn.dynasm.jitstats +++ b/pyre/bench/synth/getframe_root_loop_force_blackhole_crn.dynasm.jitstats @@ -2,7 +2,10 @@ bridges_compiled=0 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=5 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=0 internal_compile_panics=0 loops_aborted=5 diff --git a/pyre/bench/synth/getframe_root_loop_force_blackhole_crn.wasm.jitstats b/pyre/bench/synth/getframe_root_loop_force_blackhole_crn.wasm.jitstats index 17df870455c..48f9c4225bc 100644 --- a/pyre/bench/synth/getframe_root_loop_force_blackhole_crn.wasm.jitstats +++ b/pyre/bench/synth/getframe_root_loop_force_blackhole_crn.wasm.jitstats @@ -2,7 +2,10 @@ bridges_compiled=0 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=5 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=0 internal_compile_panics=0 loops_aborted=5 diff --git a/pyre/bench/synth/getframe_root_loop_force_blackhole_crn_nonidempotent.cranelift.jitstats b/pyre/bench/synth/getframe_root_loop_force_blackhole_crn_nonidempotent.cranelift.jitstats index 17df870455c..48f9c4225bc 100644 --- a/pyre/bench/synth/getframe_root_loop_force_blackhole_crn_nonidempotent.cranelift.jitstats +++ b/pyre/bench/synth/getframe_root_loop_force_blackhole_crn_nonidempotent.cranelift.jitstats @@ -2,7 +2,10 @@ bridges_compiled=0 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=5 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=0 internal_compile_panics=0 loops_aborted=5 diff --git a/pyre/bench/synth/getframe_root_loop_force_blackhole_crn_nonidempotent.dynasm.jitstats b/pyre/bench/synth/getframe_root_loop_force_blackhole_crn_nonidempotent.dynasm.jitstats index 17df870455c..48f9c4225bc 100644 --- a/pyre/bench/synth/getframe_root_loop_force_blackhole_crn_nonidempotent.dynasm.jitstats +++ b/pyre/bench/synth/getframe_root_loop_force_blackhole_crn_nonidempotent.dynasm.jitstats @@ -2,7 +2,10 @@ bridges_compiled=0 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=5 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=0 internal_compile_panics=0 loops_aborted=5 diff --git a/pyre/bench/synth/getframe_root_loop_force_blackhole_crn_nonidempotent.wasm.jitstats b/pyre/bench/synth/getframe_root_loop_force_blackhole_crn_nonidempotent.wasm.jitstats index 17df870455c..48f9c4225bc 100644 --- a/pyre/bench/synth/getframe_root_loop_force_blackhole_crn_nonidempotent.wasm.jitstats +++ b/pyre/bench/synth/getframe_root_loop_force_blackhole_crn_nonidempotent.wasm.jitstats @@ -2,7 +2,10 @@ bridges_compiled=0 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=5 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=0 internal_compile_panics=0 loops_aborted=5 diff --git a/pyre/bench/synth/getframe_root_loop_force_while_merge.cranelift.jitstats b/pyre/bench/synth/getframe_root_loop_force_while_merge.cranelift.jitstats index 17df870455c..48f9c4225bc 100644 --- a/pyre/bench/synth/getframe_root_loop_force_while_merge.cranelift.jitstats +++ b/pyre/bench/synth/getframe_root_loop_force_while_merge.cranelift.jitstats @@ -2,7 +2,10 @@ bridges_compiled=0 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=5 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=0 internal_compile_panics=0 loops_aborted=5 diff --git a/pyre/bench/synth/getframe_root_loop_force_while_merge.dynasm.jitstats b/pyre/bench/synth/getframe_root_loop_force_while_merge.dynasm.jitstats index 17df870455c..48f9c4225bc 100644 --- a/pyre/bench/synth/getframe_root_loop_force_while_merge.dynasm.jitstats +++ b/pyre/bench/synth/getframe_root_loop_force_while_merge.dynasm.jitstats @@ -2,7 +2,10 @@ bridges_compiled=0 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=5 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=0 internal_compile_panics=0 loops_aborted=5 diff --git a/pyre/bench/synth/getframe_root_loop_force_while_merge.wasm.jitstats b/pyre/bench/synth/getframe_root_loop_force_while_merge.wasm.jitstats index 17df870455c..48f9c4225bc 100644 --- a/pyre/bench/synth/getframe_root_loop_force_while_merge.wasm.jitstats +++ b/pyre/bench/synth/getframe_root_loop_force_while_merge.wasm.jitstats @@ -2,7 +2,10 @@ bridges_compiled=0 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=5 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=0 internal_compile_panics=0 loops_aborted=5 diff --git a/pyre/bench/synth/getframe_stored_fback_walk.cranelift.jitstats b/pyre/bench/synth/getframe_stored_fback_walk.cranelift.jitstats index 5d9438ae0aa..c1e73e6acab 100644 --- a/pyre/bench/synth/getframe_stored_fback_walk.cranelift.jitstats +++ b/pyre/bench/synth/getframe_stored_fback_walk.cranelift.jitstats @@ -2,7 +2,10 @@ bridges_compiled=0 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=10 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=0 internal_compile_panics=0 loops_aborted=10 diff --git a/pyre/bench/synth/getframe_stored_fback_walk.dynasm.jitstats b/pyre/bench/synth/getframe_stored_fback_walk.dynasm.jitstats index 5d9438ae0aa..c1e73e6acab 100644 --- a/pyre/bench/synth/getframe_stored_fback_walk.dynasm.jitstats +++ b/pyre/bench/synth/getframe_stored_fback_walk.dynasm.jitstats @@ -2,7 +2,10 @@ bridges_compiled=0 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=10 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=0 internal_compile_panics=0 loops_aborted=10 diff --git a/pyre/bench/synth/getframe_stored_fback_walk.wasm.jitstats b/pyre/bench/synth/getframe_stored_fback_walk.wasm.jitstats index 5d9438ae0aa..c1e73e6acab 100644 --- a/pyre/bench/synth/getframe_stored_fback_walk.wasm.jitstats +++ b/pyre/bench/synth/getframe_stored_fback_walk.wasm.jitstats @@ -2,7 +2,10 @@ bridges_compiled=0 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=10 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=0 internal_compile_panics=0 loops_aborted=10 diff --git a/pyre/bench/synth/getframe_while_caller_locals_across_subwalk.cranelift.jitstats b/pyre/bench/synth/getframe_while_caller_locals_across_subwalk.cranelift.jitstats index 5d9438ae0aa..511df2a116c 100644 --- a/pyre/bench/synth/getframe_while_caller_locals_across_subwalk.cranelift.jitstats +++ b/pyre/bench/synth/getframe_while_caller_locals_across_subwalk.cranelift.jitstats @@ -2,7 +2,10 @@ bridges_compiled=0 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=5 +fbw_blackhole_adopted_single_frame=5 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=0 internal_compile_panics=0 loops_aborted=10 diff --git a/pyre/bench/synth/getframe_while_caller_locals_across_subwalk.dynasm.jitstats b/pyre/bench/synth/getframe_while_caller_locals_across_subwalk.dynasm.jitstats index 5d9438ae0aa..511df2a116c 100644 --- a/pyre/bench/synth/getframe_while_caller_locals_across_subwalk.dynasm.jitstats +++ b/pyre/bench/synth/getframe_while_caller_locals_across_subwalk.dynasm.jitstats @@ -2,7 +2,10 @@ bridges_compiled=0 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=5 +fbw_blackhole_adopted_single_frame=5 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=0 internal_compile_panics=0 loops_aborted=10 diff --git a/pyre/bench/synth/getframe_while_caller_locals_across_subwalk.wasm.jitstats b/pyre/bench/synth/getframe_while_caller_locals_across_subwalk.wasm.jitstats index 5d9438ae0aa..511df2a116c 100644 --- a/pyre/bench/synth/getframe_while_caller_locals_across_subwalk.wasm.jitstats +++ b/pyre/bench/synth/getframe_while_caller_locals_across_subwalk.wasm.jitstats @@ -2,7 +2,10 @@ bridges_compiled=0 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=5 +fbw_blackhole_adopted_single_frame=5 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=0 internal_compile_panics=0 loops_aborted=10 diff --git a/pyre/bench/synth/getframe_while_captured_frame_outlives_call.cranelift.jitstats b/pyre/bench/synth/getframe_while_captured_frame_outlives_call.cranelift.jitstats index 5d9438ae0aa..511df2a116c 100644 --- a/pyre/bench/synth/getframe_while_captured_frame_outlives_call.cranelift.jitstats +++ b/pyre/bench/synth/getframe_while_captured_frame_outlives_call.cranelift.jitstats @@ -2,7 +2,10 @@ bridges_compiled=0 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=5 +fbw_blackhole_adopted_single_frame=5 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=0 internal_compile_panics=0 loops_aborted=10 diff --git a/pyre/bench/synth/getframe_while_captured_frame_outlives_call.dynasm.jitstats b/pyre/bench/synth/getframe_while_captured_frame_outlives_call.dynasm.jitstats index 5d9438ae0aa..511df2a116c 100644 --- a/pyre/bench/synth/getframe_while_captured_frame_outlives_call.dynasm.jitstats +++ b/pyre/bench/synth/getframe_while_captured_frame_outlives_call.dynasm.jitstats @@ -2,7 +2,10 @@ bridges_compiled=0 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=5 +fbw_blackhole_adopted_single_frame=5 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=0 internal_compile_panics=0 loops_aborted=10 diff --git a/pyre/bench/synth/getframe_while_captured_frame_outlives_call.wasm.jitstats b/pyre/bench/synth/getframe_while_captured_frame_outlives_call.wasm.jitstats index 5d9438ae0aa..511df2a116c 100644 --- a/pyre/bench/synth/getframe_while_captured_frame_outlives_call.wasm.jitstats +++ b/pyre/bench/synth/getframe_while_captured_frame_outlives_call.wasm.jitstats @@ -2,7 +2,10 @@ bridges_compiled=0 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=5 +fbw_blackhole_adopted_single_frame=5 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=0 internal_compile_panics=0 loops_aborted=10 diff --git a/pyre/bench/synth/getframe_while_escaping_read_frame_identity.cranelift.jitstats b/pyre/bench/synth/getframe_while_escaping_read_frame_identity.cranelift.jitstats index f281172da6c..2ffd81217e4 100644 --- a/pyre/bench/synth/getframe_while_escaping_read_frame_identity.cranelift.jitstats +++ b/pyre/bench/synth/getframe_while_escaping_read_frame_identity.cranelift.jitstats @@ -2,7 +2,10 @@ bridges_compiled=0 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=10 +fbw_blackhole_adopted_single_frame=10 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=0 internal_compile_panics=0 loops_aborted=20 diff --git a/pyre/bench/synth/getframe_while_escaping_read_frame_identity.dynasm.jitstats b/pyre/bench/synth/getframe_while_escaping_read_frame_identity.dynasm.jitstats index f281172da6c..2ffd81217e4 100644 --- a/pyre/bench/synth/getframe_while_escaping_read_frame_identity.dynasm.jitstats +++ b/pyre/bench/synth/getframe_while_escaping_read_frame_identity.dynasm.jitstats @@ -2,7 +2,10 @@ bridges_compiled=0 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=10 +fbw_blackhole_adopted_single_frame=10 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=0 internal_compile_panics=0 loops_aborted=20 diff --git a/pyre/bench/synth/getframe_while_escaping_read_frame_identity.wasm.jitstats b/pyre/bench/synth/getframe_while_escaping_read_frame_identity.wasm.jitstats index f281172da6c..2ffd81217e4 100644 --- a/pyre/bench/synth/getframe_while_escaping_read_frame_identity.wasm.jitstats +++ b/pyre/bench/synth/getframe_while_escaping_read_frame_identity.wasm.jitstats @@ -2,7 +2,10 @@ bridges_compiled=0 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=10 +fbw_blackhole_adopted_single_frame=10 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=0 internal_compile_panics=0 loops_aborted=20 diff --git a/pyre/bench/synth/getframe_while_inlined_callee_subwalk.cranelift.jitstats b/pyre/bench/synth/getframe_while_inlined_callee_subwalk.cranelift.jitstats index 5d9438ae0aa..511df2a116c 100644 --- a/pyre/bench/synth/getframe_while_inlined_callee_subwalk.cranelift.jitstats +++ b/pyre/bench/synth/getframe_while_inlined_callee_subwalk.cranelift.jitstats @@ -2,7 +2,10 @@ bridges_compiled=0 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=5 +fbw_blackhole_adopted_single_frame=5 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=0 internal_compile_panics=0 loops_aborted=10 diff --git a/pyre/bench/synth/getframe_while_inlined_callee_subwalk.dynasm.jitstats b/pyre/bench/synth/getframe_while_inlined_callee_subwalk.dynasm.jitstats index 5d9438ae0aa..511df2a116c 100644 --- a/pyre/bench/synth/getframe_while_inlined_callee_subwalk.dynasm.jitstats +++ b/pyre/bench/synth/getframe_while_inlined_callee_subwalk.dynasm.jitstats @@ -2,7 +2,10 @@ bridges_compiled=0 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=5 +fbw_blackhole_adopted_single_frame=5 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=0 internal_compile_panics=0 loops_aborted=10 diff --git a/pyre/bench/synth/getframe_while_inlined_callee_subwalk.wasm.jitstats b/pyre/bench/synth/getframe_while_inlined_callee_subwalk.wasm.jitstats index 5d9438ae0aa..511df2a116c 100644 --- a/pyre/bench/synth/getframe_while_inlined_callee_subwalk.wasm.jitstats +++ b/pyre/bench/synth/getframe_while_inlined_callee_subwalk.wasm.jitstats @@ -2,7 +2,10 @@ bridges_compiled=0 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=5 +fbw_blackhole_adopted_single_frame=5 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=0 internal_compile_panics=0 loops_aborted=10 diff --git a/pyre/bench/synth/getframe_while_subwalk_decline_shapes.cranelift.jitstats b/pyre/bench/synth/getframe_while_subwalk_decline_shapes.cranelift.jitstats index 554ab2678f1..cce2266e45f 100644 --- a/pyre/bench/synth/getframe_while_subwalk_decline_shapes.cranelift.jitstats +++ b/pyre/bench/synth/getframe_while_subwalk_decline_shapes.cranelift.jitstats @@ -2,7 +2,10 @@ bridges_compiled=0 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=15 +fbw_blackhole_adopted_single_frame=10 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=0 internal_compile_panics=0 loops_aborted=25 diff --git a/pyre/bench/synth/getframe_while_subwalk_decline_shapes.dynasm.jitstats b/pyre/bench/synth/getframe_while_subwalk_decline_shapes.dynasm.jitstats index 554ab2678f1..cce2266e45f 100644 --- a/pyre/bench/synth/getframe_while_subwalk_decline_shapes.dynasm.jitstats +++ b/pyre/bench/synth/getframe_while_subwalk_decline_shapes.dynasm.jitstats @@ -2,7 +2,10 @@ bridges_compiled=0 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=15 +fbw_blackhole_adopted_single_frame=10 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=0 internal_compile_panics=0 loops_aborted=25 diff --git a/pyre/bench/synth/getframe_while_subwalk_decline_shapes.wasm.jitstats b/pyre/bench/synth/getframe_while_subwalk_decline_shapes.wasm.jitstats index 554ab2678f1..cce2266e45f 100644 --- a/pyre/bench/synth/getframe_while_subwalk_decline_shapes.wasm.jitstats +++ b/pyre/bench/synth/getframe_while_subwalk_decline_shapes.wasm.jitstats @@ -2,7 +2,10 @@ bridges_compiled=0 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=15 +fbw_blackhole_adopted_single_frame=10 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=0 internal_compile_panics=0 loops_aborted=25 diff --git a/pyre/bench/synth/recursive_forced_frame_kept_stack.cranelift.jitstats b/pyre/bench/synth/recursive_forced_frame_kept_stack.cranelift.jitstats index fc0cca7b7db..c6a4d14bc06 100644 --- a/pyre/bench/synth/recursive_forced_frame_kept_stack.cranelift.jitstats +++ b/pyre/bench/synth/recursive_forced_frame_kept_stack.cranelift.jitstats @@ -2,7 +2,10 @@ bridges_compiled=5 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=0 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=1000 internal_compile_panics=0 loops_aborted=0 diff --git a/pyre/bench/synth/recursive_forced_frame_kept_stack.dynasm.jitstats b/pyre/bench/synth/recursive_forced_frame_kept_stack.dynasm.jitstats index fc0cca7b7db..c6a4d14bc06 100644 --- a/pyre/bench/synth/recursive_forced_frame_kept_stack.dynasm.jitstats +++ b/pyre/bench/synth/recursive_forced_frame_kept_stack.dynasm.jitstats @@ -2,7 +2,10 @@ bridges_compiled=5 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=0 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=1000 internal_compile_panics=0 loops_aborted=0 diff --git a/pyre/bench/synth/recursive_forced_frame_kept_stack.wasm.jitstats b/pyre/bench/synth/recursive_forced_frame_kept_stack.wasm.jitstats index fc0cca7b7db..c6a4d14bc06 100644 --- a/pyre/bench/synth/recursive_forced_frame_kept_stack.wasm.jitstats +++ b/pyre/bench/synth/recursive_forced_frame_kept_stack.wasm.jitstats @@ -2,7 +2,10 @@ bridges_compiled=5 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=0 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=1000 internal_compile_panics=0 loops_aborted=0 diff --git a/pyre/bench/synth/set_hash_protocol.cranelift.jitstats b/pyre/bench/synth/set_hash_protocol.cranelift.jitstats index 114b48b9fd0..56ae0032eed 100644 --- a/pyre/bench/synth/set_hash_protocol.cranelift.jitstats +++ b/pyre/bench/synth/set_hash_protocol.cranelift.jitstats @@ -2,7 +2,10 @@ bridges_compiled=1 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=0 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=201 internal_compile_panics=0 loops_aborted=0 diff --git a/pyre/bench/synth/set_hash_protocol.dynasm.jitstats b/pyre/bench/synth/set_hash_protocol.dynasm.jitstats index 114b48b9fd0..56ae0032eed 100644 --- a/pyre/bench/synth/set_hash_protocol.dynasm.jitstats +++ b/pyre/bench/synth/set_hash_protocol.dynasm.jitstats @@ -2,7 +2,10 @@ bridges_compiled=1 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=0 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=201 internal_compile_panics=0 loops_aborted=0 diff --git a/pyre/bench/synth/set_hash_protocol.wasm.jitstats b/pyre/bench/synth/set_hash_protocol.wasm.jitstats index 114b48b9fd0..56ae0032eed 100644 --- a/pyre/bench/synth/set_hash_protocol.wasm.jitstats +++ b/pyre/bench/synth/set_hash_protocol.wasm.jitstats @@ -2,7 +2,10 @@ bridges_compiled=1 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=0 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=201 internal_compile_panics=0 loops_aborted=0 diff --git a/pyre/bench/synth/trace_too_long_effect_replay.cranelift.jitstats b/pyre/bench/synth/trace_too_long_effect_replay.cranelift.jitstats index a8d069bee2a..044dedf91f8 100644 --- a/pyre/bench/synth/trace_too_long_effect_replay.cranelift.jitstats +++ b/pyre/bench/synth/trace_too_long_effect_replay.cranelift.jitstats @@ -2,7 +2,10 @@ bridges_compiled=0 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=5 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=0 internal_compile_panics=0 loops_aborted=6 diff --git a/pyre/bench/synth/trace_too_long_effect_replay.dynasm.jitstats b/pyre/bench/synth/trace_too_long_effect_replay.dynasm.jitstats index a8d069bee2a..044dedf91f8 100644 --- a/pyre/bench/synth/trace_too_long_effect_replay.dynasm.jitstats +++ b/pyre/bench/synth/trace_too_long_effect_replay.dynasm.jitstats @@ -2,7 +2,10 @@ bridges_compiled=0 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=5 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=0 internal_compile_panics=0 loops_aborted=6 diff --git a/pyre/bench/synth/trace_too_long_effect_replay.wasm.jitstats b/pyre/bench/synth/trace_too_long_effect_replay.wasm.jitstats index 78de8010564..ccbb05691ff 100644 --- a/pyre/bench/synth/trace_too_long_effect_replay.wasm.jitstats +++ b/pyre/bench/synth/trace_too_long_effect_replay.wasm.jitstats @@ -2,7 +2,10 @@ bridges_compiled=0 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=0 +fbw_blackhole_adopted_single_frame=5 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=0 internal_compile_panics=0 loops_aborted=5 diff --git a/pyre/bench/synth/trace_too_long_inline_multiframe.cranelift.jitstats b/pyre/bench/synth/trace_too_long_inline_multiframe.cranelift.jitstats index 54b641ac5c4..c7d82ff92ef 100644 --- a/pyre/bench/synth/trace_too_long_inline_multiframe.cranelift.jitstats +++ b/pyre/bench/synth/trace_too_long_inline_multiframe.cranelift.jitstats @@ -2,7 +2,10 @@ bridges_compiled=0 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=11 +fbw_blackhole_adopted_single_frame=12 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=0 internal_compile_panics=0 loops_aborted=24 diff --git a/pyre/bench/synth/trace_too_long_inline_multiframe.dynasm.jitstats b/pyre/bench/synth/trace_too_long_inline_multiframe.dynasm.jitstats index 54b641ac5c4..c7d82ff92ef 100644 --- a/pyre/bench/synth/trace_too_long_inline_multiframe.dynasm.jitstats +++ b/pyre/bench/synth/trace_too_long_inline_multiframe.dynasm.jitstats @@ -2,7 +2,10 @@ bridges_compiled=0 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=11 +fbw_blackhole_adopted_single_frame=12 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=0 internal_compile_panics=0 loops_aborted=24 diff --git a/pyre/bench/synth/trace_too_long_inline_multiframe.wasm.jitstats b/pyre/bench/synth/trace_too_long_inline_multiframe.wasm.jitstats index 6c7a79c9c72..489851d3141 100644 --- a/pyre/bench/synth/trace_too_long_inline_multiframe.wasm.jitstats +++ b/pyre/bench/synth/trace_too_long_inline_multiframe.wasm.jitstats @@ -2,7 +2,10 @@ bridges_compiled=0 descr_set_absent=0 descr_set_ambiguous=0 descr_set_stale_absent=0 +fbw_blackhole_adopted_multi_frame=11 +fbw_blackhole_adopted_single_frame=11 fbw_rolled_back_with_effects=0 +fbw_store_journal_rollback_failed=0 guard_failures=0 internal_compile_panics=0 loops_aborted=23 diff --git a/pyre/check.py b/pyre/check.py index 490ae51c122..2b796fa98f6 100644 --- a/pyre/check.py +++ b/pyre/check.py @@ -724,6 +724,7 @@ def _parse_jit_stats(snapshot): "fbw_rolled_back_with_effects", "field_pos_spec_misplaced", "field_pos_attached_misplaced", + "fbw_store_journal_rollback_failed", ) # The three count-valued counters, and what a move in either direction means: @@ -748,6 +749,12 @@ def _parse_jit_stats(snapshot): # under ordinary tuning", which made a bridge collapse (27 -> 0) invisible for # as long as `guard_failures` stayed inside its band — the whole dead-bridge # class this suite exists to catch. +# * `fbw_blackhole_adopted_single_frame` and +# `fbw_blackhole_adopted_multi_frame` count successful full-body-walk +# blackhole adoptions: the walk handed the interpreter a resumable image +# instead of making its caller replay the region. A fall means the adoption +# path stopped firing and the legacy replay path came back; a rise means more +# walks avoided replay and the baseline should say so. # # A move is not *always* a defect: two loops merging into one trace lowers # `loops_compiled` while raising coverage. That is the bargain `loops_aborted` @@ -777,6 +784,8 @@ def _parse_jit_stats(snapshot): "loops_compiled", "bridges_compiled", "guard_failures", + "fbw_blackhole_adopted_single_frame", + "fbw_blackhole_adopted_multi_frame", ) @@ -790,9 +799,14 @@ def _parse_jit_stats(snapshot): # `loops_compiled` is inverted against the badness fields: it is the counter # that falls when the tracer stops admitting a frame at all, which aborts # nothing and *lowers* `guard_failures`, so a fall is the regression and a rise -# is the gain. +# is the gain. The blackhole adoption counters are inverted the same way: a +# fall means the interpreter stopped receiving an image and went back to replay. JITSTATS_REGRESSION_ON_RISE = JITSTATS_BADNESS_FIELDS + ("guard_failures",) -JITSTATS_REGRESSION_ON_FALL = ("loops_compiled",) +JITSTATS_REGRESSION_ON_FALL = ( + "loops_compiled", + "fbw_blackhole_adopted_single_frame", + "fbw_blackhole_adopted_multi_frame", +) # How many fresh runs a disagreeing fixture gets before its counters are called # stable. Only a fixture that already disagrees pays this, so the common path is diff --git a/pyre/pyre-jit-trace/src/jitcode_dispatch/bridge_subwalk.rs b/pyre/pyre-jit-trace/src/jitcode_dispatch/bridge_subwalk.rs index 5de1afc9f15..d4e8b5b9387 100644 --- a/pyre/pyre-jit-trace/src/jitcode_dispatch/bridge_subwalk.rs +++ b/pyre/pyre-jit-trace/src/jitcode_dispatch/bridge_subwalk.rs @@ -404,6 +404,7 @@ pub fn dispatch_via_miframe( vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -1248,6 +1249,7 @@ pub(crate) fn drive_bridge_frame_subwalk( vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, trace_ctx: ctx, @@ -1358,7 +1360,7 @@ pub(crate) fn drive_bridge_frame_subwalk( // owns their banks — `drive_bridge_carrier_walk`'s abort tail adopts // the image, and a decline there leaves the pre-existing rollback. if let Err(ref error) = outcome { - let _ = latch_abort_blackhole(&sub_wc, error.stop_pc()); + let _ = latch_abort_blackhole(&sub_wc, error.stop_pc(), "bridge1361"); } outcome }; diff --git a/pyre/pyre-jit-trace/src/jitcode_dispatch/fbw_state.rs b/pyre/pyre-jit-trace/src/jitcode_dispatch/fbw_state.rs index 1e207dc4e6a..f6712a58018 100644 --- a/pyre/pyre-jit-trace/src/jitcode_dispatch/fbw_state.rs +++ b/pyre/pyre-jit-trace/src/jitcode_dispatch/fbw_state.rs @@ -934,6 +934,7 @@ pub(crate) fn fbw_store_journal_rollback() { // shrank the list after the store — a shape the replay // already cannot undo (the residual re-runs). Surface it // under the debug gate instead of corrupting silently. + crate::trace::fbw_diag::bump(crate::trace::fbw_diag::STORE_JOURNAL_ROLLBACK_FAILED); if fbw_debug_abort_enabled() { eprintln!("[fbw-store-journal] rollback failed (index out of bounds)"); } @@ -1068,6 +1069,19 @@ pub(crate) fn fbw_store_journal_len() -> usize { FBW_STORE_JOURNAL.with(|j| j.borrow().len()) } +/// The three journals whose pushes bump [`fbw_bump_executed_effect`], as +/// `(stores, appends, cell_stores)`. Read at the walk-end epilogue before the +/// commit/rollback, their sum is the number of executed effects +/// [`fbw_store_journal_rollback`] is about to undo. The traceback journal is +/// absent because its push bumps nothing. +pub(crate) fn fbw_journaled_effect_lens() -> (usize, usize, usize) { + ( + fbw_store_journal_len(), + FBW_APPEND_JOURNAL.with(|j| j.borrow().len()), + FBW_CELL_STORE_JOURNAL.with(|j| j.borrow().len()), + ) +} + /// Mark the walk as carrying a recorded-but-unexecuted side effect only /// the legacy replay applies. pub(crate) fn fbw_mark_unjournaled_effect(cause: ResidualDecline) { diff --git a/pyre/pyre-jit-trace/src/jitcode_dispatch/inline_call.rs b/pyre/pyre-jit-trace/src/jitcode_dispatch/inline_call.rs index 807f057102e..689d6104074 100644 --- a/pyre/pyre-jit-trace/src/jitcode_dispatch/inline_call.rs +++ b/pyre/pyre-jit-trace/src/jitcode_dispatch/inline_call.rs @@ -2397,7 +2397,9 @@ pub(crate) fn try_walker_inline_builtin_call( ctx.sub_jitcode_lookup = &GLOBAL_SUB_JITCODE_LOOKUP_FN; ctx.fbw_mode.inline_subwalk = true; ctx.fbw_mode.inline_caller_py_pc = Some(call_site_py_pc); - ctx.fbw_mode.transparent_helper_subwalk = nested_helper_entry.is_some(); + // `transparent_helper_subwalk` is set by `run_sub_jitcode_walk` on the + // sub-context it builds, so every descent into a canonical helper body + // carries it — not just the ones entered from another sub-walk. let _helper_frame = nested_helper_entry.map(|frame| InlineFrameGuard::enter(ctx.session, 0, Some(frame))); let walk_result = run_sub_jitcode_walk( @@ -4159,6 +4161,7 @@ pub(crate) fn try_walker_inline_resolved_user_call( vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, trace_ctx: ctx.trace_ctx, @@ -6359,6 +6362,18 @@ pub(crate) fn run_sub_jitcode_walk( // the carried outer Python boundary. fbw_mode: FbwWalkMode { inline_subwalk: true, + // A canonical sub-jitcode body has no blackhole entry point of + // its own — the fact the `op_pc` comment above states — so the + // whole descent is transparent to the Python MIFrame stack, no + // matter whether the caller happens to be another sub-walk. + // Left inherited, a root-level descent walked with + // `inline_subwalk` set and the framestack empty, which sends + // `latch_abort_blackhole` into its multi-frame arm: that arm + // declines on the empty framestack, so the abort latched no + // image and fell back to entry replay — the outcome the + // transparent-helper exclusions at the abort-coordinate claim + // and the post-step trace-limit check exist to prevent. + transparent_helper_subwalk: true, ..ctx.fbw_mode }, session: ctx.session, @@ -6387,6 +6402,7 @@ pub(crate) fn run_sub_jitcode_walk( vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; diff --git a/pyre/pyre-jit-trace/src/jitcode_dispatch/mod.rs b/pyre/pyre-jit-trace/src/jitcode_dispatch/mod.rs index 12abc9a96d2..97fab478dd3 100644 --- a/pyre/pyre-jit-trace/src/jitcode_dispatch/mod.rs +++ b/pyre/pyre-jit-trace/src/jitcode_dispatch/mod.rs @@ -1656,6 +1656,19 @@ pub struct WalkContext<'frame, 'static_a: 'frame, Sym: WalkSym> { /// the virtualizable shadow instead of replaying stack effects. Cleared once /// the walk advances past this ceiling (py-pc order is monotonic again). pub vstack_reorder_ceiling: u32, + /// The py_pc the walk's floor lookup reports while it is inside an + /// out-of-line exception LANDING block — the unwind bookkeeping the + /// codewriter emits per catch site, after the whole body, which then jumps + /// to the handler proper. `None` when the catch target is in line with its + /// handler (nothing to skip). + /// + /// Those bytes lower no Python opcode, but they are laid out inside some + /// other opcode's floor segment, so the walk reports that opcode as a + /// boundary and the mirror would replay a stack effect from a block it + /// never ran — and, py order having gone backwards, arm the reorder region + /// over the whole handler body. Hold the handler-entry coordinate until + /// the walk leaves those bytes instead. + pub vstack_handler_landing_py: Option, /// #73: the jitcode offset of the `-live-` byte that /// precedes the CURRENT opcode's guard resume point — the `-live-` /// BEFORE (`pyjitpl.py`, normal guard resume reads at @@ -2829,7 +2842,7 @@ pub fn walk( && !carrier_owned && !abort_blackhole_latched() { - let _ = latch_abort_blackhole(ctx, error.stop_pc()); + let _ = latch_abort_blackhole(ctx, error.stop_pc(), "mod2730"); } return Err(error); } @@ -2874,6 +2887,28 @@ pub fn walk( // enclosing Python `walk()` perform this same post-step limit check at // its real per-frame coordinate, matching RPython's one-red-frame // ownership. + // + // The exemption defers the abort, it does not drop it, and the deferral + // is bounded by one descent: + // + // * `run_sub_jitcode_walk` is the only site that sets the flag, and the + // Python-callee sub-walk merely inherits it, which extends the exempt + // region downward. Every walk ROOT is built with it clear + // (`bridge_subwalk.rs`), so an exempt descent always has a non-exempt + // Python frame above it. + // * `is_too_long` is a `num_ops > trace_limit` comparison over the + // shared `TraceCtx`, not an edge, so it still holds when the helper + // returns and the enclosing frame runs this check. + // + // The exposure is therefore the ops one helper body records after + // crossing the limit. Over the 373 synth fixtures two reach it at all: + // `trace_too_long_inline_multiframe` ends at 100 ops against a limit of + // 70, and `trace_too_long_effect_replay` at 115 against 100. The size + // of that overshoot is a property of the base, not of this exemption — + // it moves whenever the walk records a different number of ops per + // helper — so re-measure it rather than inheriting the numbers. + // `helper_descent_defers_the_limit_check_to_the_enclosing_frame` pins + // both halves. if !ctx.fbw_mode.transparent_helper_subwalk && ctx.trace_ctx.is_too_long() { // `step` has advanced the register banks for `Continue`. The // other outcomes still need the match below to perform their @@ -2885,7 +2920,7 @@ pub fn walk( // replay would resume the caller without delivering the return or // raise that this step produced. let snapshot_safe = trace_too_long_blackhole_snapshot_safe(&outcome); - let blackhole_latched = snapshot_safe && latch_abort_blackhole(ctx, pc); + let blackhole_latched = snapshot_safe && latch_abort_blackhole(ctx, pc, "mod2786"); if trace_too_long_abort_safe(&outcome, blackhole_latched, fbw_executed_effect_count()) { let ops = ctx.trace_ctx.num_recorded_ops(); crate::state::note_root_trace_too_long( diff --git a/pyre/pyre-jit-trace/src/jitcode_dispatch/residual_call.rs b/pyre/pyre-jit-trace/src/jitcode_dispatch/residual_call.rs index e7a325e10f6..774a3e074d6 100644 --- a/pyre/pyre-jit-trace/src/jitcode_dispatch/residual_call.rs +++ b/pyre/pyre-jit-trace/src/jitcode_dispatch/residual_call.rs @@ -263,9 +263,10 @@ macro_rules! latchdbg { /// whole image, leaving the abort on the legacy entry replay. fn capture_vstack_mirror_image( ctx: &WalkContext<'_, '_, Sym>, + origin: &'static str, ) -> Option { if !ctx.vstack_valid { - latchdbg!("mirror-invalid"); + latchdbg!("origin={origin} mirror-invalid"); return None; } let mut slots = Vec::with_capacity(ctx.vstack_boxes.len()); @@ -276,7 +277,7 @@ fn capture_vstack_mirror_image( } other => { latchdbg!( - "mirror-slot {}/{} unresolved opref={opref:?} concrete={other:?}", + "origin={origin} mirror-slot {}/{} unresolved opref={opref:?} concrete={other:?}", slots.len(), ctx.vstack_boxes.len(), ); @@ -293,9 +294,10 @@ fn capture_vstack_mirror_image( pub(crate) fn latch_abort_blackhole( ctx: &WalkContext<'_, '_, Sym>, resume_pc: usize, + origin: &'static str, ) -> bool { if !ctx.is_authoritative_executor { - latchdbg!("not-authoritative"); + latchdbg!("origin={origin} not-authoritative"); return false; } let last_exc_value = match ctx.last_exc_value_concrete { @@ -323,12 +325,12 @@ pub(crate) fn latch_abort_blackhole( }) } }) else { - latchdbg!("no-snapshot-sym-jitcode"); + latchdbg!("origin={origin} no-snapshot-sym-jitcode"); return false; }; let Some(miframe) = build_trace_too_long_single_frame_miframe(ctx, jitcode, resume_pc) else { - latchdbg!("sf-build-miframe"); + latchdbg!("origin={origin} sf-build-miframe"); return false; }; // `walk()` has already executed this step, so returning TraceTooLong @@ -337,13 +339,13 @@ pub(crate) fn latch_abort_blackhole( // to entry replay. Keep the same boundary: incomplete images merely // keep recording until a later step supplies a complete handoff. let Some(jitcode_index) = i32::try_from(miframe.jitcode.index()).ok() else { - latchdbg!("sf-jitcode-index"); + latchdbg!("origin={origin} sf-jitcode-index"); return false; }; if ctx.trace_ctx.virtualizable_info().is_none() || crate::state::concrete_nlocals(cf_addr).is_none() { - latchdbg!("sf-no-vinfo-or-nlocals"); + latchdbg!("origin={origin} sf-no-vinfo-or-nlocals"); return false; } let root_addr = if live_root_addr != 0 { @@ -364,7 +366,7 @@ pub(crate) fn latch_abort_blackhole( || !crate::state::can_write_back_outer_locals(ctx.trace_ctx, vable_frame) || !crate::state::can_publish_frame_stack(cf_addr, vable_frame) { - latchdbg!("sf-vable-frame-mismatch"); + latchdbg!("origin={origin} sf-vable-frame-mismatch"); return false; } // Keep the per-frame red identity seeded by `frame_box`. The @@ -378,7 +380,7 @@ pub(crate) fn latch_abort_blackhole( // operand stack the adopter publishes. `ABORT_TOO_LONG` stops at an // opcode boundary and keeps the snapshot-array source; a capability-gap // abort stops mid-opcode and needs this. - let mirror_stack = capture_vstack_mirror_image(ctx); + let mirror_stack = capture_vstack_mirror_image(ctx, origin); FBW_SINGLE_FRAME_BLACKHOLE.with(|slot| { *slot.borrow_mut() = Some(LatchedSingleFrameBlackhole { miframe, @@ -390,13 +392,13 @@ pub(crate) fn latch_abort_blackhole( true } else if ctx.fbw_mode.inline_subwalk { let Some(framestack) = - build_multi_frame_miframe(ctx, resume_pc, InnermostMiframeBuild::TraceTooLong) + build_multi_frame_miframe(ctx, resume_pc, InnermostMiframeBuild::TraceTooLong, origin) else { - latchdbg!("mf-build-miframe"); + latchdbg!("origin={origin} mf-build-miframe"); return false; }; - if !multi_frame_blackhole_preflight(ctx, &framestack) { - latchdbg!("mf-preflight"); + if !multi_frame_blackhole_preflight(ctx, &framestack, origin) { + latchdbg!("origin={origin} mf-preflight"); return false; } FBW_MULTI_FRAME_BLACKHOLE.with(|slot| { @@ -419,7 +421,7 @@ pub(crate) fn latch_abort_blackhole( true } else { latchdbg!( - "no-arm framestack_empty={} inline_subwalk={}", + "origin={origin} no-arm framestack_empty={} inline_subwalk={}", ctx.session.borrow().framestack.is_empty(), ctx.fbw_mode.inline_subwalk ); @@ -436,9 +438,10 @@ pub(crate) fn latch_abort_blackhole( fn multi_frame_blackhole_preflight( ctx: &WalkContext<'_, '_, Sym>, framestack: &majit_metainterp::MIFrameStack, + origin: &'static str, ) -> bool { if ctx.trace_ctx.virtualizable_info().is_none() || ctx.fbw_mode.snapshot_sym.is_null() { - latchdbg!("pf-no-vinfo-or-sym"); + latchdbg!("origin={origin} pf-no-vinfo-or-sym"); return false; } let sym = unsafe { &*ctx.fbw_mode.snapshot_sym }; @@ -448,35 +451,42 @@ fn multi_frame_blackhole_preflight( _ => sym.live_vable_frame_addr(), }; let root = if live_root != 0 { live_root } else { snapshot }; - latchdbg!( - "pf-root-caps snapshot={snapshot:#x} root={root:#x} nlocals={} locals={} writeback={} publish={}", - crate::state::concrete_nlocals(snapshot).is_some(), - crate::state::capture_frame_locals(root).is_some(), - crate::state::can_write_back_outer_locals(ctx.trace_ctx, root), - crate::state::can_publish_frame_stack(snapshot, root) - ); - if crate::state::concrete_nlocals(snapshot).is_none() - || crate::state::capture_frame_locals(root).is_none() - || !crate::state::can_write_back_outer_locals(ctx.trace_ctx, root) - || !crate::state::can_publish_frame_stack(snapshot, root) - { + // Named by the first capability that refuses, and reported only then. + // Emitted ahead of the test, the line announced every passing preflight + // under the decline tag as well, so a census could not tell a rejected root + // from an accepted one. + let refused = if crate::state::concrete_nlocals(snapshot).is_none() { + Some("nlocals") + } else if crate::state::capture_frame_locals(root).is_none() { + Some("locals") + } else if !crate::state::can_write_back_outer_locals(ctx.trace_ctx, root) { + Some("writeback") + } else if !crate::state::can_publish_frame_stack(snapshot, root) { + Some("publish") + } else { + None + }; + if let Some(refused) = refused { + latchdbg!( + "origin={origin} pf-root-caps snapshot={snapshot:#x} root={root:#x} refused={refused}" + ); return false; } let mut seen = Vec::with_capacity(framestack.frames.len()); for (index, frame) in framestack.frames.iter().enumerate() { let Ok(jitcode_index) = i32::try_from(frame.jitcode.index()) else { - latchdbg!("pf-jitcode-index"); + latchdbg!("origin={origin} pf-jitcode-index"); return false; }; let frame_reg = crate::state::portal_red_regs_at(jitcode_index).0; if frame_reg == u16::MAX { - latchdbg!("pf-frame-reg-none"); + latchdbg!("origin={origin} pf-frame-reg-none"); return false; } let Some(frame_ptr) = frame.ref_values.get(frame_reg as usize).copied().flatten() else { latchdbg!( - "pf-frame-ptr-unset index={index}/{} jitcode={} frame_reg={frame_reg}", + "origin={origin} pf-frame-ptr-unset index={index}/{} jitcode={} frame_reg={frame_reg}", framestack.frames.len(), frame.jitcode.name() ); @@ -484,15 +494,15 @@ fn multi_frame_blackhole_preflight( }; let frame_ptr = frame_ptr as usize; let Some(stack_base) = crate::state::concrete_nlocals(frame_ptr) else { - latchdbg!("pf-nlocals"); + latchdbg!("origin={origin} pf-nlocals"); return false; }; let Some(stack_depth) = crate::state::concrete_stack_depth(frame_ptr) else { - latchdbg!("pf-stack-depth"); + latchdbg!("origin={origin} pf-stack-depth"); return false; }; let Some(array_len) = crate::state::concrete_frame_array_len(frame_ptr) else { - latchdbg!("pf-array-len"); + latchdbg!("origin={origin} pf-array-len"); return false; }; if stack_depth < stack_base @@ -501,7 +511,7 @@ fn multi_frame_blackhole_preflight( || (index > 0 && frame_ptr == root) || seen.contains(&frame_ptr) { - latchdbg!("pf-shape"); + latchdbg!("origin={origin} pf-shape"); return false; } seen.push(frame_ptr); @@ -832,11 +842,8 @@ fn build_multi_frame_miframe( ctx: &WalkContext<'_, '_, Sym>, resume_pc: usize, innermost_build: InnermostMiframeBuild, + origin: &'static str, ) -> Option { - let session = ctx.session.borrow(); - if session.framestack.is_empty() { - return None; - } macro_rules! s2dbg { ($($a:tt)*) => { if fbw_debug_abort_enabled() { @@ -844,30 +851,78 @@ fn build_multi_frame_miframe( } }; } + // The build's one success report. It has to carry its own tag: a census + // groups these lines by their `[…-decline]` prefix, so a completed build + // announced under that prefix is counted as a refusal. + macro_rules! s2built { + ($($a:tt)*) => { + if fbw_debug_abort_enabled() { + eprintln!("[s2-build-ok] {}", format!($($a)*)); + } + }; + } + let session = ctx.session.borrow(); + if session.framestack.is_empty() { + s2dbg!( + "origin={origin} framestack empty depth={} transparent_helper_subwalk={}", + session.framestack.len(), + ctx.fbw_mode.transparent_helper_subwalk + ); + return None; + } let mut frames = majit_metainterp::MIFrameStack::empty(); for (index, inline) in session.framestack.iter().enumerate() { let Some(parent) = inline.parent.as_ref() else { - s2dbg!("frame {index}: no parent"); + s2dbg!("origin={origin} frame {index}: no parent"); return None; }; let Some(concrete) = parent.blackhole.as_ref() else { - s2dbg!("frame {index}: parent.blackhole None (capture missing)"); + s2dbg!("origin={origin} frame {index}: parent.blackhole None (capture missing)"); + return None; + }; + let Some(pjc) = crate::state::pyjitcode_for_jitcode_index(parent.jitcode_index as i32) + else { + s2dbg!( + "origin={origin} frame {index}: no pyjitcode for parent jitcode_index={}", + parent.jitcode_index + ); return None; }; - let pjc = crate::state::pyjitcode_for_jitcode_index(parent.jitcode_index as i32)?; let mut miframe = majit_metainterp::MIFrame::new(pjc.jitcode.clone(), concrete.resume_pc); for &(color, value) in &concrete.int_values { - *miframe.int_values.get_mut(color)? = Some(value); + let bank_len = miframe.int_values.len(); + let Some(slot) = miframe.int_values.get_mut(color) else { + s2dbg!( + "origin={origin} frame {index}: int color {color} out of range (len {bank_len})" + ); + return None; + }; + *slot = Some(value); } for &(color, value) in &concrete.ref_values { - *miframe.ref_values.get_mut(color)? = Some(value as i64); + let bank_len = miframe.ref_values.len(); + let Some(slot) = miframe.ref_values.get_mut(color) else { + s2dbg!( + "origin={origin} frame {index}: ref color {color} out of range (len {bank_len})" + ); + return None; + }; + *slot = Some(value as i64); } for &(color, opref) in &concrete.float_values { let Some(majit_ir::Value::Float(value)) = ctx.trace_ctx.concrete_of_opref(opref) else { + s2dbg!("origin={origin} frame {index}: float opref {opref:?} not a stamped Float"); + return None; + }; + let bank_len = miframe.float_values.len(); + let Some(slot) = miframe.float_values.get_mut(color) else { + s2dbg!( + "origin={origin} frame {index}: float color {color} out of range (len {bank_len})" + ); return None; }; - *miframe.float_values.get_mut(color)? = Some(value.to_bits() as i64); + *slot = Some(value.to_bits() as i64); } frames.push(miframe); } @@ -880,13 +935,19 @@ fn build_multi_frame_miframe( // callee's own jitcode so all three share its coordinate space; fall back // to `snapshot_sym` for a top-level (non-sub-walk) abort. let innermost_jitcode = if let Some(consts) = ctx.inline_callee_consts { - let jc = crate::state::pyjitcode_for_jitcode_index(consts.jitcode_index)?; + let Some(jc) = crate::state::pyjitcode_for_jitcode_index(consts.jitcode_index) else { + s2dbg!( + "origin={origin} innermost: no pyjitcode for callee jitcode_index={}", + consts.jitcode_index + ); + return None; + }; jc.jitcode.clone() } else { unsafe { let sym = &*ctx.fbw_mode.snapshot_sym; if sym.jitcode().is_null() { - s2dbg!("innermost snapshot_sym jitcode null"); + s2dbg!("origin={origin} innermost snapshot_sym jitcode null"); return None; } (&(*sym.jitcode()).payload).jitcode.clone() @@ -901,11 +962,14 @@ fn build_multi_frame_miframe( } }; let Some(innermost) = innermost else { - s2dbg!("innermost build_single_frame_miframe declined"); + s2dbg!("origin={origin} innermost build_single_frame_miframe declined"); return None; }; frames.push(innermost); - s2dbg!("BUILT multi-frame depth={}", frames.frames.len()); + s2built!( + "origin={origin} BUILT multi-frame depth={}", + frames.frames.len() + ); Some(frames) } @@ -3087,8 +3151,7 @@ pub(crate) fn try_execute_residual_call_via_executor( // here instead left the shapes that DID commit — a re-entry guard // plus a non-idempotent store ahead of the escaping call — on the // replay path. - if !ctx.trace_ctx.is_bridge_trace - && let Some((resume_pc, result_bank, result_color)) = blackhole_result + if let Some((resume_pc, result_bank, result_color)) = blackhole_result && !ctx.fbw_mode.snapshot_sym.is_null() { let (lastop_result, last_exc_value, raising_exception) = match exec_result { @@ -3114,7 +3177,7 @@ pub(crate) fn try_execute_residual_call_via_executor( // blackhole can reach a `getarrayitem_vable_r` that // reloads an operand from the virtualizable array, so // publish the root stack from the walker's mirror. - let mirror_stack = capture_vstack_mirror_image(ctx); + let mirror_stack = capture_vstack_mirror_image(ctx, "escape-flush"); FBW_SINGLE_FRAME_BLACKHOLE.with(|slot| { *slot.borrow_mut() = Some(LatchedSingleFrameBlackhole { miframe, @@ -3155,6 +3218,7 @@ pub(crate) fn try_execute_residual_call_via_executor( ctx, resume_pc, InnermostMiframeBuild::LiveMarker(lastop_result), + "escape-flush", ) { FBW_MULTI_FRAME_BLACKHOLE.with(|slot| { diff --git a/pyre/pyre-jit-trace/src/jitcode_dispatch/tests.rs b/pyre/pyre-jit-trace/src/jitcode_dispatch/tests.rs index 9a00341a651..4f58640a15b 100644 --- a/pyre/pyre-jit-trace/src/jitcode_dispatch/tests.rs +++ b/pyre/pyre-jit-trace/src/jitcode_dispatch/tests.rs @@ -441,6 +441,7 @@ fn read_ref_reg_concrete_returns_slot_matching_symbolic_read() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -662,6 +663,7 @@ fn getfield_vable_with_none_obj_surfaces_vable_box_not_seeded() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -718,6 +720,7 @@ fn setfield_vable_with_none_obj_surfaces_vable_box_not_seeded() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -792,6 +795,7 @@ fn array_vable_handlers_with_none_obj_surface_vable_box_not_seeded() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -1043,6 +1047,7 @@ fn drive_int_add_jump_if_ovf( vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -1200,6 +1205,7 @@ fn drive_alloc_with_descr( vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -1393,6 +1399,7 @@ fn run_hint_step_with_descrs( vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -1901,6 +1908,7 @@ fn switch_id_hit_jumps_to_matching_target() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -1958,6 +1966,7 @@ fn switch_id_miss_falls_through() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -2014,6 +2023,7 @@ fn switch_id_requires_concrete_int_value() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -2079,6 +2089,7 @@ fn goto_if_not_truthy_records_guard_true_and_falls_through() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -2136,6 +2147,7 @@ fn goto_if_not_falsy_records_guard_false_and_jumps() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -2192,6 +2204,7 @@ fn goto_if_not_requires_concrete_int_value() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -2457,6 +2470,7 @@ fn inline_call_recursion_writes_subreturn_into_caller_dst_register() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -2625,6 +2639,7 @@ fn inline_call_r_i_writes_int_subreturn_into_caller_int_bank() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -2741,6 +2756,7 @@ fn inline_call_ir_r_populates_callee_int_and_ref_banks() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -2852,6 +2868,7 @@ fn inline_call_irf_r_populates_all_three_kind_banks() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -2952,6 +2969,7 @@ fn inline_call_ir_int_arity_overflow_surfaces_typed_error() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -3048,6 +3066,7 @@ fn inline_call_recursion_propagates_subraise_from_callee() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -3126,6 +3145,7 @@ fn inline_call_with_unresolvable_descr_surfaces_typed_error() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -3183,6 +3203,7 @@ fn inline_call_with_missing_sub_jitcode_lookup_surfaces_typed_error() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -3236,6 +3257,7 @@ fn step_through_live_opcode_advances_by_offset_size() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -3298,6 +3320,7 @@ fn step_through_ref_return_records_finish_with_descr_and_correct_arg() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -3358,6 +3381,7 @@ fn ref_return_with_out_of_range_register_surfaces_typed_error() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -3419,6 +3443,7 @@ fn raise_with_unwritten_register_surfaces_register_read_unbound() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -3481,6 +3506,7 @@ fn step_through_int_return_records_finish_with_int_descr() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -3560,6 +3586,7 @@ fn step_through_int_return_subwalk_surfaces_subreturn_some() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -3627,6 +3654,7 @@ fn step_through_void_return_stashes_void_finish_payload() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -3695,6 +3723,7 @@ fn step_through_void_return_subwalk_surfaces_subreturn_none() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -3751,6 +3780,7 @@ fn raise_with_out_of_range_register_surfaces_typed_error() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -3810,6 +3840,7 @@ fn step_through_goto_jumps_to_label_target() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -3869,6 +3900,7 @@ fn step_through_goto_handles_high_byte_of_label() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -3976,6 +4008,7 @@ fn step_through_catch_exception_with_active_exception_surfaces_typed_error() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -4030,6 +4063,7 @@ fn step_through_catch_exception_advances_past_label_operand() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -4098,6 +4132,7 @@ fn step_through_raise_records_outermost_finish_and_terminates() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -4180,6 +4215,7 @@ fn top_level_raise_settles_the_vable_token() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -4286,6 +4322,7 @@ fn raise_r_emits_guard_class_when_concrete_exc_pinned_in_shadow() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -4386,6 +4423,7 @@ fn step_through_reraise_at_top_level_records_outermost_finish() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -4463,6 +4501,7 @@ fn step_through_reraise_without_last_exc_value_surfaces_typed_error() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -4517,6 +4556,7 @@ fn raise_at_top_level_populates_last_exc_value_before_finish() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -4635,6 +4675,7 @@ fn inline_call_subraise_jumps_to_caller_catch_exception_target() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -4756,6 +4797,7 @@ fn inline_call_subraise_without_caller_catch_bubbles_up_in_subwalk() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -4825,6 +4867,7 @@ fn step_through_int_copy_advances_past_operand_bytes() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -4891,6 +4934,7 @@ fn int_copy_writes_src_value_into_dst_register() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -4948,6 +4992,7 @@ fn int_copy_with_out_of_range_dst_register_surfaces_typed_error() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -5004,6 +5049,7 @@ fn int_copy_with_out_of_range_src_register_surfaces_typed_error() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -5080,6 +5126,7 @@ fn step_through_ref_copy_advances_past_operand_bytes() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -5144,6 +5191,7 @@ fn ref_copy_writes_src_value_into_dst_register() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -5199,6 +5247,7 @@ fn ref_copy_with_out_of_range_dst_register_surfaces_typed_error() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -5253,6 +5302,7 @@ fn ref_copy_with_out_of_range_src_register_surfaces_typed_error() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -5318,6 +5368,7 @@ fn drive_int_binop(opname: &str, expected_opcode: majit_ir::OpCode) { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -5543,6 +5594,7 @@ fn drive_int_between( vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -5680,6 +5732,7 @@ fn drive_float_binop(opname: &str, expected_opcode: majit_ir::OpCode) { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -5770,6 +5823,7 @@ fn drive_float_unop(opname: &str, expected_opcode: majit_ir::OpCode) { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -5848,6 +5902,7 @@ fn drive_int_unop(opname: &str, expected_opcode: majit_ir::OpCode) { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -5946,6 +6001,7 @@ fn drive_ptr_compare(opname: &str, expected_opcode: majit_ir::OpCode) { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -6117,6 +6173,7 @@ fn run_float_step( vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -6311,6 +6368,7 @@ fn float_add_with_out_of_range_src_register_surfaces_typed_error() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -6366,6 +6424,7 @@ fn int_add_with_out_of_range_src_register_surfaces_typed_error() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -6423,6 +6482,7 @@ fn int_add_with_out_of_range_dst_register_surfaces_typed_error() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -6488,6 +6548,7 @@ fn unsupported_opname_surfaces_typed_error() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -6544,6 +6605,7 @@ fn ptr_nonzero_records_ptrne_with_box_and_null() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -6693,6 +6755,7 @@ fn abort_result_r_is_pure_pc_advance() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -6759,6 +6822,7 @@ fn ref_guard_value_records_guardvalue_with_concrete_constant() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -6843,6 +6907,7 @@ fn int_guard_value_records_guardvalue_with_concrete_constant() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -6928,6 +6993,7 @@ fn ref_guard_value_on_const_records_nothing() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -7023,6 +7089,7 @@ fn step_through_residual_call_r_r_records_callr_with_descr_and_args() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -7192,6 +7259,7 @@ fn residual_call_r_r_with_elidable_cannot_raise_records_callpurer_no_guard() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -7278,6 +7346,7 @@ fn authoritative_walker_executes_may_force_call_and_stamps_result() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -7336,6 +7405,7 @@ fn non_authoritative_walker_does_not_execute_may_force_call() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -7409,6 +7479,7 @@ fn authoritative_walker_transcribes_may_force_raise_to_last_exc() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -7506,6 +7577,7 @@ fn may_force_with_active_vable_executes_and_clears_token() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -7607,6 +7679,7 @@ fn may_force_vable_escape_surfaces_typed_abort() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -7683,6 +7756,7 @@ fn residual_call_r_r_with_not_in_trace_oopspec_returns_typed_error() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -7746,6 +7820,7 @@ fn residual_call_r_r_with_jit_force_virtual_oopspec_returns_typed_error() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -7803,6 +7878,7 @@ fn residual_call_r_r_with_elidable_can_raise_records_callpurer_plus_guard() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -7872,6 +7948,7 @@ fn residual_call_r_r_with_cannot_raise_records_callr_no_guard() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -7943,6 +8020,7 @@ fn residual_call_r_r_writes_recorder_result_into_dst_register() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -8034,6 +8112,7 @@ fn residual_call_r_r_can_raise_writes_dst_before_guard_no_exception() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -8114,6 +8193,7 @@ fn residual_call_ir_r_can_raise_writes_dst_before_guard_no_exception() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -8193,6 +8273,7 @@ fn residual_call_r_r_with_out_of_range_dst_register_surfaces_typed_error() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -8252,6 +8333,7 @@ fn residual_call_r_r_with_descr_index_out_of_range_surfaces_typed_error() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -8349,6 +8431,7 @@ fn step_through_residual_call_r_i_records_calli_with_int_dst_writeback() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -8445,6 +8528,7 @@ fn residual_call_r_i_with_elidable_cannot_raise_records_callpurei_no_guard() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -8549,6 +8633,7 @@ fn step_through_residual_call_ir_r_records_callr_with_int_and_ref_args() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -8685,6 +8770,7 @@ fn residual_call_ir_r_permutes_argboxes_per_arg_types_abi() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -8757,6 +8843,7 @@ fn residual_call_descr_not_call_descr_surfaces_typed_error() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -8815,6 +8902,7 @@ fn residual_call_r_r_with_out_of_range_arg_register_surfaces_typed_error() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -8897,6 +8985,7 @@ fn walk_return_value_helper_terminates_at_first_ref_return() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -9010,6 +9099,7 @@ fn walk_pop_top_helper_terminates_with_recorded_ops() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -9047,6 +9137,121 @@ fn walk_pop_top_helper_terminates_with_recorded_ops() { // this fixture. } +/// The post-step trace-limit check (`pyjitpl.py:2865 _interpret`) is skipped +/// inside a canonical helper descent, which has no blackhole entry point to +/// abort at, and runs on the enclosing Python frame instead. +/// +/// Both halves are load-bearing and only their composition bounds the trace: +/// exempting the descent without the enclosing frame still checking would let a +/// helper record past `trace_limit` with nothing to stop it. The caller here is +/// one `inline_call_r_v/dR` — the descent — followed by its terminator, walked +/// with the limit already crossed, so the two settings of the flag differ in +/// exactly the frame that owns the check. +#[test] +fn helper_descent_defers_the_limit_check_to_the_enclosing_frame() { + fn walk_past_the_limit( + transparent_helper_subwalk: bool, + ) -> Result<(DispatchOutcome, usize), DispatchError> { + let void_ret = *insns_opname_to_byte() + .get("void_return/") + .expect("`void_return/` must be in insns table"); + let inline_byte = *insns_opname_to_byte() + .get("inline_call_r_v/dR") + .expect("`inline_call_r_v/dR` must be in insns table"); + let callee_code: &'static [u8] = Box::leak(Box::new([void_ret])); + let sub_body = SubJitCodeBody { + code: callee_code, + num_regs_r: 1, + num_regs_i: 0, + num_regs_f: 0, + constants_i: &[], + constants_r: &[], + constants_f: &[], + }; + let lookup = { + let sub_body = sub_body.clone(); + move |idx: usize| (idx == 7).then(|| sub_body.clone()) + }; + let caller_code = [ + inline_byte, + 0x07, + 0x00, // descr index 7 + 0x01, + 0x00, // R: len=1, arg=r0 + void_ret, // caller terminates + ]; + let mut tc = fresh_trace_ctx(); + let mut regs_r = distinct_const_refs(&mut tc, 4); + // One recorded op against a zero limit: the walk is over budget before + // its first step, so whichever frame owns the check aborts immediately. + tc.record_op(majit_ir::OpCode::PtrEq, &[]); + tc.set_trace_limit(0); + assert!(tc.is_too_long(), "the walk must start over budget"); + // Bridge-shaped (pyjitpl.py:2908), so the abort's warm-state half — + // `note_root_trace_too_long`, which reaches the driver through the + // merge point — is a no-op and the frame that owns the check is the + // only thing this fixture measures. + tc.clear_merge_points(); + let mut descr_pool: Vec = (0..16).map(|i| make_fail_descr(1 + i)).collect(); + descr_pool[7] = make_jitcode_descr(7); + let session = std::cell::RefCell::new(WalkSession::default()); + let mut wc = WalkContext { + callee_shadow: None, + inline_callee_consts: None, + fbw_mode: FbwWalkMode { + transparent_helper_subwalk, + ..test_fbw_mode() + }, + session: &session, + registers_r: &mut regs_r, + registers_i: &mut [], + registers_f: &mut [], + concrete_registers_r: &mut [], + concrete_registers_i: &mut [], + descr_refs: &descr_pool, + raw_descrs: RawDescrPool::Global, + is_authoritative_executor: false, + trace_ctx: &mut tc, + is_top_level: true, + sub_jitcode_lookup: &lookup, + last_exc_value: None, + last_exc_value_concrete: ConcreteValue::Null, + entry_py_pc: EntryPyPc::Py(0), + outer_resume_marker_jit_pc: None, + outer_jitcode_index: 0, + outer_active_boxes: Vec::new(), + store_subscr_fn_addr: None, + pending_guard_snapshot_error: None, + vstack_boxes: Vec::new(), + vstack_depth: 0, + vstack_cur_pypc: 0, + vstack_valid: false, + vstack_last_ref: OpRef::NONE, + vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, + live_before_jit_pc: usize::MAX, + live_after_jit_pc: usize::MAX, + }; + walk(&caller_code, 0, &mut wc) + } + + // The descent runs inside the caller's first step, so the abort coordinate + // states which frame took it: pc 0 is the `inline_call_r_v/dR` itself, and + // the callee body — whose own offsets index a different JitCode — is never + // a legal abort pc for the enclosing walk. + assert_eq!( + walk_past_the_limit(false), + Err(DispatchError::TraceTooLong { pc: 0, ops: 1 }), + "an enclosing Python frame must abort at its own step", + ); + + assert_eq!( + walk_past_the_limit(true).map(|(outcome, _)| outcome), + Ok(DispatchOutcome::Terminate), + "a helper descent must finish its body and leave the check to its caller", + ); +} + #[test] fn inline_call_with_more_args_than_callee_regs_surfaces_arity_mismatch() { // codewriter shape contract says `R-list.len() <= @@ -9113,6 +9318,7 @@ fn inline_call_with_more_args_than_callee_regs_surfaces_arity_mismatch() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -9215,6 +9421,7 @@ fn inline_call_r_v_accepts_void_returning_callee() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -9296,6 +9503,7 @@ fn inline_call_r_v_rejects_non_void_returning_callee() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -9380,6 +9588,7 @@ fn inline_call_ir_v_accepts_void_returning_callee() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -9462,6 +9671,7 @@ fn inline_call_ir_v_rejects_non_void_returning_callee() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -9549,6 +9759,7 @@ fn inline_call_irf_v_accepts_void_returning_callee() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -9634,6 +9845,7 @@ fn inline_call_irf_v_rejects_non_void_returning_callee() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -9708,6 +9920,7 @@ fn getfield_gc_i_cache_miss_records_op_and_writes_dst() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -9803,6 +10016,7 @@ fn getfield_gc_i_cache_hit_returns_cached_box_without_recording() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -9876,6 +10090,7 @@ fn getfield_gc_r_cache_miss_records_op_and_writes_ref_dst() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -9937,6 +10152,7 @@ fn getfield_gc_with_out_of_range_obj_register_surfaces_typed_error() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -10010,6 +10226,7 @@ fn getfield_vable_i_routes_through_metainterp_and_writes_dst() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -10103,6 +10320,7 @@ fn setfield_vable_i_routes_through_metainterp_records_setfield_gc_fallback() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -10186,6 +10404,7 @@ fn setfield_gc_i_redundant_write_skips_recording() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -10247,6 +10466,7 @@ fn setfield_gc_i_fresh_write_records_op_and_caches_value() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -10334,6 +10554,7 @@ fn setfield_gc_r_records_setfieldgc_with_ref_valuebox() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -10404,6 +10625,7 @@ fn getarrayitem_gc_r_cache_miss_records_op_and_writes_dst() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -10548,6 +10770,7 @@ fn getarrayitem_gc_pure_const_operands_fold_without_recording_or_counting() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -10625,6 +10848,7 @@ fn getarrayitem_gc_r_cache_hit_returns_cached_box() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -10694,6 +10918,7 @@ fn setarrayitem_gc_r_records_setarrayitemgc_with_three_args() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -11012,6 +11237,7 @@ fn walk_undecodable_byte_surfaces_typed_error() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -11090,6 +11316,7 @@ fn jit_merge_point_first_visit_continues_then_closes_loop() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -11178,6 +11405,7 @@ fn loop_header_stamps_seen_flag() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -11245,6 +11473,7 @@ fn jit_merge_point_int_form_resolves_jdindex_from_the_int_bank() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -11308,6 +11537,7 @@ fn jit_merge_point_unresolved_green_key_fails_loud() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -11649,6 +11879,7 @@ fn int_scratch_move_carries_the_concrete_shadow_to_the_destination() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -11843,6 +12074,7 @@ fn walker_folds_a_float_result_pure_call_from_the_float_return_register() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; @@ -11942,6 +12174,7 @@ fn mayforce_null_ref_arg_exempts_the_unread_load_global_namespace() { vstack_valid: false, vstack_last_ref: OpRef::NONE, vstack_reorder_ceiling: u32::MAX, + vstack_handler_landing_py: None, live_before_jit_pc: usize::MAX, live_after_jit_pc: usize::MAX, }; diff --git a/pyre/pyre-jit-trace/src/jitcode_dispatch/vstack_mirror.rs b/pyre/pyre-jit-trace/src/jitcode_dispatch/vstack_mirror.rs index 686b366cead..6dbce7071e2 100644 --- a/pyre/pyre-jit-trace/src/jitcode_dispatch/vstack_mirror.rs +++ b/pyre/pyre-jit-trace/src/jitcode_dispatch/vstack_mirror.rs @@ -413,8 +413,40 @@ pub(crate) fn reconcile_vstack_at_boundary( | Instruction::Reraise { .. } | Instruction::RaiseVarargs { .. } ); - let cfg_successor = (has_fallthrough && new_pypc as usize == fallthrough) - || crate::liveness::target_pc(code, &instr, prev_pypc, op_arg) == Some(new_pypc as usize); + // A boundary that reports the SAME py_pc is not a block transition at all: + // the walk has not left this Python opcode, so no source block was visited + // out of order. One opcode's jitcode expansion can carry more than one + // boundary marker, and treating the repeat as a backed-off transition armed + // the permutation region on the spot, which forces `ShadowReseed` below and + // clears every mirror slot — including the ones this opcode did not touch. + // The `layout_only_boundary` arm already models a repeat correctly (the + // observed depth matches neither successor of the previous opcode, so it + // preserves the surviving slots), and it is the arm the reorder region + // excludes. A genuine self-branch is unaffected: `target_pc` reports it, + // so the clause below already accepts it. + // The handler an exception raised at `prev_pypc` transfers to is a CFG + // successor as much as a branch delta is; it just lives in + // `co_exceptiontable` instead of the opcode's operand, so `target_pc` + // cannot report it. Left out, an unwind to the handler read as a block + // permutation and armed the reorder region over the whole handler body, + // where `ShadowReseed` drops every operand box the shadow does not carry. + let cfg_successor = new_pypc as usize == prev_pypc + || (has_fallthrough && new_pypc as usize == fallthrough) + || crate::liveness::target_pc(code, &instr, prev_pypc, op_arg) == Some(new_pypc as usize) + || crate::liveness::exception_target_pc(code, prev_pypc) == Some(new_pypc as usize); + // #389(b): leave the out-of-order permutation region once the walk has + // advanced PAST the py_pc it backed off from — py order is monotonic again + // and the per-op reconcile is valid from here, INCLUDING at this boundary. + // Tested after the class had already been applied, the region covered one + // boundary too many: the exiting step is an ordinary sequential one whose + // previous opcode really did produce `vstack_last_ref`, and `ShadowReseed` + // dropped that box for the reseed, which cannot recover a slot the shadow + // does not carry. Ordered before the arming below so a boundary that both + // passes the old ceiling and is itself out of order opens a new region + // instead of running unprotected. + if ctx.vstack_reorder_ceiling != u32::MAX && new_pypc > ctx.vstack_reorder_ceiling { + ctx.vstack_reorder_ceiling = u32::MAX; + } if !cfg_successor && ctx.vstack_reorder_ceiling == u32::MAX { ctx.vstack_reorder_ceiling = (new_pypc as usize).max(prev_pypc) as u32; } @@ -423,10 +455,20 @@ pub(crate) fn reconcile_vstack_at_boundary( crate::liveness::stack_effects(&instr, op_arg, ctx.vstack_depth); if std::env::var_os("PYRE_VSTACK_DIAG").is_some() { eprintln!( - "[vstack-reconcile] prev_pypc={prev_pypc} new_pypc={new_pypc} \ + "[vstack-reconcile] code={} sub={} prev_pypc={prev_pypc} new_pypc={new_pypc} \ new_depth={new_depth} prev_depth={} class={class:?} reorder={in_reorder_region} \ - last_ref={:?} instr={instr:?}", - ctx.vstack_depth, ctx.vstack_last_ref + succ=(ft={},br={:?},exc={:?}) last_ref={:?} instr={instr:?}", + code.obj_name, + ctx.fbw_mode.inline_subwalk, + ctx.vstack_depth, + if has_fallthrough { + fallthrough as isize + } else { + -1 + }, + crate::liveness::target_pc(code, &instr, prev_pypc, op_arg), + crate::liveness::exception_target_pc(code, prev_pypc), + ctx.vstack_last_ref ); } // A JitCode's block layout can visit source-PC floor segments out of @@ -620,12 +662,6 @@ pub(crate) fn reconcile_vstack_at_boundary( ctx.vstack_depth = new_depth; ctx.vstack_last_ref = OpRef::NONE; } - // #389(b): leave the out-of-order permutation region once the walk has - // advanced PAST the py_pc it backed off from — py order is monotonic again - // and the per-op reconcile is valid from here. - if ctx.vstack_reorder_ceiling != u32::MAX && new_pypc > ctx.vstack_reorder_ceiling { - ctx.vstack_reorder_ceiling = u32::MAX; - } } /// Fill missing operand-stack boxes from the active inline frame's own @@ -866,8 +902,24 @@ pub(crate) fn step_vstack_mirror(ctx: &mut WalkContext<'_, '_, Sym } }; if new_pypc == ctx.vstack_cur_pypc { + // Reporting the mirror's own coordinate: whatever landing block the + // walk was crossing is behind it, so stop holding that py_pc. + ctx.vstack_handler_landing_py = None; + return; + } + // Still inside the landing block a catch target opened: these bytes belong + // to no Python opcode, so hold the handler-entry coordinate rather than + // treating the segment they were laid out in as a boundary. Any other + // py_pc means the walk has left them; the mirror resumes stepping from the + // handler entry, which is where the reconstruction placed it. Together + // with the clear above the hold lasts exactly as far as the landing block: + // a later boundary that happens to name the same py_pc — the opcode those + // bytes were laid out inside really is walked eventually — reconciles + // normally. + if ctx.vstack_handler_landing_py == Some(new_pypc) { return; } + ctx.vstack_handler_landing_py = None; // The Python-opcode boundary: sample the executed-effect odometer for any // abort leg that resumes the interpreter AT this opcode, which re-executes // it whole (`FBW_OPCODE_ENTRY_EFFECTS`). Top-level only — a sub-walk's @@ -894,6 +946,7 @@ pub(crate) fn seed_callee_vstack_mirror( ctx.vstack_depth = 0; ctx.vstack_cur_pypc = first_pypc; ctx.vstack_last_ref = OpRef::NONE; + ctx.vstack_handler_landing_py = None; ctx.vstack_valid = true; } @@ -1004,9 +1057,67 @@ pub(crate) fn seed_vstack_mirror( ctx.vstack_depth = depth; ctx.vstack_cur_pypc = first_pypc; ctx.vstack_last_ref = OpRef::NONE; + ctx.vstack_handler_landing_py = None; ctx.vstack_valid = true; } +/// Python-opcode coordinate of the handler a catch target enters. +/// +/// The obvious source — the floor segment of the catch target's JitCode offset +/// — is not reliable here. A catch target can be an out-of-line block that +/// only performs the unwind bookkeeping and then jumps to the handler proper, +/// and such a block carries no py pivot of its own, so the floor answers with +/// whatever segment it happened to be laid out inside. Observed: a catch +/// target near the end of the JitCode floored onto the `RERAISE` that ENDS the +/// handler (py 53) while the walk went on to report the handler's +/// `PUSH_EXC_INFO` entry (py 35), which armed the reorder region across the +/// whole handler body. +/// +/// `co_exceptiontable` states the same edge exactly, at the Python level the +/// mirror models: the unwind target of the entry covering the raising opcode. +/// Fall back to the floor when no entry covers it — the JitCode-level catch +/// then belongs to a construct the table does not describe. +fn handler_entry_py_pc( + code_ptr: *const pyre_interpreter::CodeObject, + raising_py_pc: u32, + floor_py: u32, +) -> u32 { + // SAFETY: the caller resolved `code_ptr` from a live jitcode payload. + let code = unsafe { &*code_ptr }; + crate::liveness::exception_target_pc(code, raising_py_pc as usize) + .and_then(|py| u32::try_from(py).ok()) + .unwrap_or(floor_py) +} + +/// Static-liveness operand-stack depth on entry to the Python opcode at `py`. +fn py_stack_depth(code_ptr: *const pyre_interpreter::CodeObject, py: u32) -> usize { + crate::liveness::liveness_for(code_ptr) + .depth_at_py_pc() + .get(py as usize) + .copied() + .unwrap_or(0) as usize +} + +/// The handler-entry coordinate the mirror adopted, under `PYRE_VSTACK_DIAG`. +/// `floor_py` is reported next to it: the two disagreeing is what an +/// out-of-line catch target looks like from the walk's side, and without both +/// numbers a spurious reorder region downstream cannot be attributed. +fn vstack_handler_diag( + arm: &str, + handler_jit_pc: usize, + from_pypc: u32, + handler_py: u32, + floor_py: u32, + handler_depth: usize, +) { + if std::env::var_os("PYRE_VSTACK_DIAG").is_some() { + eprintln!( + "[vstack-handler] {arm} handler_jit_pc={handler_jit_pc} from_pypc={from_pypc} \ + handler_py={handler_py} floor_py={floor_py} handler_depth={handler_depth}" + ); + } +} + /// #370: model the exception-unwind boundary on the operand-stack mirror. /// When a raised exception is caught by THIS frame's handler (the SubRaise /// catch in the dispatch loop), the unwinder truncates the operand stack to @@ -1053,7 +1164,7 @@ pub(crate) fn vstack_enter_exception_handler( ctx.vstack_valid = false; return; } - let (handler_py, code_ptr, twin_depth, twin_populated) = unsafe { + let (floor_py, code_ptr, twin_depth, twin_populated) = unsafe { let jc = &*sym.jitcode(); if jc.payload.code_ptr.is_null() { ctx.vstack_valid = false; @@ -1066,27 +1177,24 @@ pub(crate) fn vstack_enter_exception_handler( jc.payload.depth_containing_populated(), ) }; - // Raw py_pc-keyed static-liveness read: the unpopulated-twin fallback - // (skeleton / fixture) and the audit oracle. - let raw_depth = || { - crate::liveness::liveness_for(code_ptr) - .depth_at_py_pc() - .get(handler_py as usize) - .copied() - .unwrap_or(0) as usize - }; - let handler_depth = if twin_populated { + let handler_py = handler_entry_py_pc(code_ptr, ctx.vstack_cur_pypc, floor_py); + // The twin is a py_pc-keyed static-liveness read behind a JitCode offset, + // so it can only answer for the floor segment; on the exception-table + // coordinate it would report the landing block's segment depth. Read the + // handler's own py depth there, and on the unpopulated-twin fallback + // (skeleton / fixture). + let handler_depth = if twin_populated && handler_py == floor_py { let depth = twin_depth.unwrap_or(0) as usize; if pcmap_containing_audit_enabled() { assert_eq!( depth, - raw_depth(), - "PYRE_PCMAP_CONTAINING_AUDIT: enter-handler containing-depth twin diverged at jit_pc {handler_jit_pc} (py {handler_py})" + py_stack_depth(code_ptr, floor_py), + "PYRE_PCMAP_CONTAINING_AUDIT: enter-handler containing-depth twin diverged at jit_pc {handler_jit_pc} (py {floor_py})" ); } depth } else { - raw_depth() + py_stack_depth(code_ptr, handler_py) }; ctx.vstack_boxes.clear(); ctx.vstack_boxes.resize(handler_depth, OpRef::NONE); @@ -1094,9 +1202,18 @@ pub(crate) fn vstack_enter_exception_handler( if handler_depth >= 1 && exc != OpRef::NONE { ctx.vstack_boxes[handler_depth - 1] = exc; } + vstack_handler_diag( + "outer", + handler_jit_pc, + ctx.vstack_cur_pypc, + handler_py, + floor_py, + handler_depth, + ); ctx.vstack_cur_pypc = handler_py; ctx.vstack_depth = handler_depth; ctx.vstack_last_ref = OpRef::NONE; + ctx.vstack_handler_landing_py = (floor_py != handler_py).then_some(floor_py); // Revive: the handler-entry state is shadow-sourced, independent of the // pre-raise mirror. ctx.vstack_valid = true; @@ -1136,12 +1253,20 @@ fn vstack_enter_exception_handler_callee( ctx.vstack_valid = false; return; }; - let Some((handler_py, _code_ptr, handler_depth)) = + let Some((floor_py, code_ptr, floor_depth)) = frame.vstack_coordinate_for_jitcode_pc(handler_jit_pc) else { ctx.vstack_valid = false; return; }; + // Same out-of-line catch target as on the full-body arm, resolved against + // the callee's own code object. + let handler_py = handler_entry_py_pc(code_ptr, ctx.vstack_cur_pypc, floor_py); + let handler_depth = if handler_py == floor_py { + floor_depth + } else { + py_stack_depth(code_ptr, handler_py) + }; // Truncate to the handler's setup depth, keeping the tracked survivors; a // mirror shallower than the handler depth pads with NONE holes, which // `mirror_covers_kept` declines per slot rather than latching invalid. @@ -1150,7 +1275,16 @@ fn vstack_enter_exception_handler_callee( if handler_depth >= 1 && exc != OpRef::NONE { ctx.vstack_boxes[handler_depth - 1] = exc; } + vstack_handler_diag( + "callee", + handler_jit_pc, + ctx.vstack_cur_pypc, + handler_py, + floor_py, + handler_depth, + ); ctx.vstack_cur_pypc = handler_py; ctx.vstack_depth = handler_depth; ctx.vstack_last_ref = OpRef::NONE; + ctx.vstack_handler_landing_py = (floor_py != handler_py).then_some(floor_py); } diff --git a/pyre/pyre-jit-trace/src/liveness.rs b/pyre/pyre-jit-trace/src/liveness.rs index b2a98fd8b19..e016176d8fa 100644 --- a/pyre/pyre-jit-trace/src/liveness.rs +++ b/pyre/pyre-jit-trace/src/liveness.rs @@ -880,6 +880,25 @@ pub(crate) fn target_pc( } } +/// Handler PC an exception raised at `pc` transfers to, or `None` when no +/// entry covers `pc`. +/// +/// [`target_pc`] only reads a branch delta out of the instruction's own +/// operand, so it cannot see this edge: under the zero-cost exception tables +/// the target lives in `co_exceptiontable`, not in the raising opcode. The +/// edge is no less a control-flow successor for that — a caller enumerating +/// an opcode's successors needs both. +/// +/// `lookup_exceptiontable` speaks byte offsets and the walk speaks code-unit +/// indices, so both ends are converted here, the same convention the +/// codewriter states at its own decode sites. +pub(crate) fn exception_target_pc(code: &CodeObject, pc: usize) -> Option { + let offset = u32::try_from(pc * 2).ok()?; + let (target, _depth, _lasti) = + pyre_interpreter::pycode::lookup_exceptiontable(&code.exceptiontable, offset)?; + Some(target as usize / 2) +} + /// Cache liveness info per CodeObject pointer. /// codewriter/liveness.py parity: thread-local cache of computed liveness. pub fn liveness_for(code: *const CodeObject) -> &'static LiveVars { diff --git a/pyre/pyre-jit-trace/src/state.rs b/pyre/pyre-jit-trace/src/state.rs index 2bad450819d..a22166d0262 100644 --- a/pyre/pyre-jit-trace/src/state.rs +++ b/pyre/pyre-jit-trace/src/state.rs @@ -3182,6 +3182,11 @@ pub(crate) fn note_root_trace_too_long( // pyjitpl.py:2843-2844. warm_state.trace_next_iteration(merge_key); warm_state.mark_force_finish_tracing(merge_key); + // pyjitpl.py:2846 `warmstate.dont_trace_here(greenkey)`, the third call + // of the same arm. Without it the two above ask for the loop to be + // re-traced and force-finished while its callers may still inline it, + // so the next attempt can rebuild the very trace that overflowed. + warm_state.disable_noninlinable_function(merge_key); } if let Some(source_jct) = source_token.as_ref() { // pyjitpl.py:2857 `loop_token.retraced_count |= FORCE_BRIDGE_SEGMENTING`. diff --git a/pyre/pyre-jit-trace/src/trace.rs b/pyre/pyre-jit-trace/src/trace.rs index fe2f26726be..fd7cf96d08b 100644 --- a/pyre/pyre-jit-trace/src/trace.rs +++ b/pyre/pyre-jit-trace/src/trace.rs @@ -2656,6 +2656,7 @@ fn try_adopt_single_frame_blackhole( // The blackhole ran the region to a frame terminal, so the resume is // the frame's RESULT, not a pc that re-runs anything. let _ = commit_walk_end(commit_leg, WalkEndResume::Terminal); + fbw_diag::bump(fbw_diag::BLACKHOLE_ADOPTED_SINGLE_FRAME); if crate::jitcode_dispatch::fbw_debug_abort_enabled() { eprintln!( "[fbw-blackhole] adopted single-frame terminal at jitcode_index={} \ @@ -2701,8 +2702,21 @@ fn try_adopt_multi_frame_blackhole( } }; } + // Same gate, for a line that reports recovered state rather than a refusal. + // A census groups these lines by their tag, so a report emitted under the + // decline tag is counted as one. + macro_rules! mfstate { + ($($a:tt)*) => { + if crate::jitcode_dispatch::fbw_debug_abort_enabled() { + eprintln!("[s2-adopt-state] {}", format!($($a)*)); + } + }; + } let Some(mut latched) = crate::jitcode_dispatch::take_multi_frame_blackhole() else { - mfdbg!("no latched multi-frame image"); + // `try_adopt_blackhole` tries this arm first and the single-frame arm + // second, so an absent multi-frame image is the ordinary dispatch + // fallthrough for every single-frame latch, not a capability gap. + mfdbg!("no latched multi-frame image; single-frame adopt follows"); return false; }; let depth = latched.framestack.len(); @@ -2806,7 +2820,7 @@ fn try_adopt_multi_frame_blackhole( // The root gate stays regardless: a residual-intermediate chain is not an // MIFrame stack rooted at this portal and cannot reuse this walk's restart // coordinate. - mfdbg!( + mfstate!( "chain root={root_addr:#x} cf_addr={cf_addr:#x} levels=[{}]", per_frame .iter() @@ -3154,6 +3168,7 @@ fn try_adopt_multi_frame_blackhole( crate::jitcode_dispatch::fbw_foriter_inflight_clear(); // Same as the single-frame adoption: a frame terminal, not a resume pc. let _ = commit_walk_end(commit_leg, WalkEndResume::Terminal); + fbw_diag::bump(fbw_diag::BLACKHOLE_ADOPTED_MULTI_FRAME); if crate::jitcode_dispatch::fbw_debug_abort_enabled() { eprintln!("[fbw-blackhole] adopted multi-frame terminal depth={depth}"); } @@ -4708,7 +4723,8 @@ fn run_perfn_walk( ); } let committed = WALK_END_FLUSH_COMMITTED.with(|c| c.get()) || terminate_no_replay; - let journal = crate::jitcode_dispatch::fbw_store_journal_len(); + let (jstore, jappend, jcell) = crate::jitcode_dispatch::fbw_journaled_effect_lens(); + let journaled = jstore + jappend + jcell; if committed { crate::jitcode_dispatch::fbw_store_journal_commit(); crate::jitcode_dispatch::fbw_exit_last_instr_commit(); @@ -4737,12 +4753,20 @@ fn run_perfn_walk( } let (unj_val, unj_sym) = crate::jitcode_dispatch::fbw_unjournaled_kinds(); let (exec_v, exec_mf, exec_pl) = crate::jitcode_dispatch::fbw_executed_residual_counts(); - // `effects` is the gh#467 executed-effect odometer: residual calls that - // were not provably side-effect free AND either wrote the live heap or - // entered a Python frame. A `committed=false` walk rolls its own store - // journal back but cannot undo these, so `committed=false effects>0` - // marks a walk whose caller is about to replay an irreversible region. + // `effects` is the gh#467 executed-effect odometer, and it counts two + // unlike things: residual calls that were not provably side-effect free + // AND either wrote the live heap or entered a Python frame, plus every + // push onto the three journals. The journal pushes are undone by the + // `fbw_store_journal_rollback` above without the odometer moving, so + // only the remainder is what a `committed=false` walk leaves behind for + // its caller's replay to apply a second time. + // + // The subtraction cannot under-report: the odometer is zeroed only by + // `fbw_store_journal_reset`, which clears all three journals in the + // same breath, so `journaled <= effects` holds for every walk. let effects = crate::jitcode_dispatch::fbw_executed_effect_count(); + debug_assert!(journaled <= effects); + let unrecoverable = effects.saturating_sub(journaled); // The same record, into a static the wasm host reads back through the // `pyre_fbw_diag` export. The guest cannot see `PYRE_FBW_CENSUS`, so // without this the wasm target has no walk-level observability at all. @@ -4752,7 +4776,8 @@ fn run_perfn_walk( committed, ctx.is_bridge_trace, effects, - journal, + journaled, + unrecoverable, exec_mf, leg, ); @@ -4760,7 +4785,8 @@ fn run_perfn_walk( eprintln!( "[fbw-census] end={end} committed={committed} leg={leg} bridge={} \ unj_val={unj_val} unj_sym={unj_sym} exec_v={exec_v} exec_mf={exec_mf} \ - exec_pl={exec_pl} effects={effects} journal={journal}", + exec_pl={exec_pl} effects={effects} jstore={jstore} jappend={jappend} \ + jcell={jcell} unrecoverable={unrecoverable}", ctx.is_bridge_trace, ); } @@ -6122,12 +6148,19 @@ pub mod fbw_diag { pub const ESCAPE_PORTAL_AND_PUBLISHED_CALLEE: usize = 8; pub const ESCAPE_FORCE_BY_PORTAL: usize = 9; pub const ESCAPE_FORCE_BY_CALLEE_ONLY: usize = 10; + pub const STORE_JOURNAL_ROLLBACK_FAILED: usize = 11; + /// Successful single-frame blackhole adoptions. A fall means the walk + /// stopped handing the interpreter an image and went back to legacy replay. + pub const BLACKHOLE_ADOPTED_SINGLE_FRAME: usize = 12; + /// Successful multi-frame blackhole adoptions. A fall means the walk + /// stopped handing the interpreter an image and went back to legacy replay. + pub const BLACKHOLE_ADOPTED_MULTI_FRAME: usize = 13; /// One ring entry per walk: four slots of outcome name (8 ASCII bytes per /// slot, little-endian) followed by one slot of packed counters. A `u64` /// export cannot carry a string, and the outcome set is far too large to /// spend a tally slot per variant. - pub const RING_BASE: usize = 11; + pub const RING_BASE: usize = 14; pub const RING_ENTRIES: usize = 24; pub const RING_STRIDE: usize = 5; pub const NAME_SLOTS: usize = 4; @@ -6172,12 +6205,13 @@ pub mod fbw_diag { committed: bool, bridge: bool, effects: usize, - journal: usize, + journaled: usize, + unrecoverable: usize, exec_mf: u32, leg: u8, ) { let index = FBW_DIAG[WALKS].fetch_add(1, Ordering::Relaxed) as usize; - if !committed && effects > 0 { + if !committed && unrecoverable > 0 { FBW_DIAG[ROLLED_BACK_WITH_EFFECTS].fetch_add(1, Ordering::Relaxed); } if index >= RING_ENTRIES { @@ -6198,7 +6232,7 @@ pub mod fbw_diag { | if committed { FLAG_COMMITTED } else { 0 } | ((effects as u64).min(FIELD_MASK) << SHIFT_EFFECTS) | if bridge { FLAG_BRIDGE } else { 0 } - | ((journal as u64).min(FIELD_MASK) << SHIFT_JOURNAL) + | ((journaled as u64).min(FIELD_MASK) << SHIFT_JOURNAL) | ((exec_mf as u64).min(FIELD_MASK) << SHIFT_EXEC_MF) | ((leg as u64) << SHIFT_LEG); FBW_DIAG[entry + NAME_SLOTS].store(flags, Ordering::Relaxed); diff --git a/pyre/pyre-wasm-runner/src/main.rs b/pyre/pyre-wasm-runner/src/main.rs index 6602f7f3dad..479c6096d56 100644 --- a/pyre/pyre-wasm-runner/src/main.rs +++ b/pyre/pyre-wasm-runner/src/main.rs @@ -620,7 +620,7 @@ fn run(module_path: &PathBuf, source: &str, script: &Path) -> Result { // which the guest cannot read. Slot layout in // `pyre_jit_trace::trace::fbw_diag`. if let Ok(fbw) = instance.get_typed_func::(&mut store, "pyre_fbw_diag") { - const RING_BASE: u32 = 11; + const RING_BASE: u32 = 14; const RING_ENTRIES: u32 = 24; const RING_STRIDE: u32 = 5; const NAME_SLOTS: u32 = 4; @@ -628,12 +628,14 @@ fn run(module_path: &PathBuf, source: &str, script: &Path) -> Result { let walks = slot(0); eprintln!( "[jit-stats] fbw_diag walks={walks} ROLLED_BACK_WITH_EFFECTS={} \ - midbody_latch={}/{} escape_plain_fallback={}/{}", + midbody_latch={}/{} escape_plain_fallback={}/{} \ + fbw_store_journal_rollback_failed={}", slot(1), slot(3), slot(2), slot(5), slot(4), + slot(11), ); for entry in 0..RING_ENTRIES.min(walks as u32) { let base = RING_BASE + entry * RING_STRIDE; @@ -654,7 +656,7 @@ fn run(module_path: &PathBuf, source: &str, script: &Path) -> Result { let field = |shift: u32| (flags >> shift) & 0xffff; eprintln!( "[fbw-census] end={end} committed={} leg={} bridge={} exec_mf={} \ - effects={} journal={}", + effects={} journaled={}", flags & (1 << 1) != 0, (flags >> 56) & 0xff, flags & (1 << 2) != 0, @@ -858,14 +860,29 @@ fn run(module_path: &PathBuf, source: &str, script: &Path) -> Result { // the same key the native backends print, because `_jit_stats_change` // compares by name and a name only one backend emits gates nothing on // the others. - let fbw_rolled_back_with_effects = match instance + // Slot 11 is `STORE_JOURNAL_ROLLBACK_FAILED`, the store restores the + // rollback could not perform — the one journaled effect the walk-end + // subtraction must not silently absorb. Both slots come from one + // export lookup so an absent export names itself once. + let ( + fbw_rolled_back_with_effects, + fbw_store_journal_rollback_failed, + fbw_blackhole_adopted_single_frame, + fbw_blackhole_adopted_multi_frame, + ) = match instance .get_typed_func::(&mut store, "pyre_fbw_diag") - .and_then(|f| f.call(&mut store, 1)) - { - Ok(v) => v, + .and_then(|f| { + Ok(( + f.call(&mut store, 1)?, + f.call(&mut store, 11)?, + f.call(&mut store, 12)?, + f.call(&mut store, 13)?, + )) + }) { + Ok(slots) => slots, Err(_) => { missing.push("pyre_fbw_diag"); - 0 + (0, 0, 0, 0) } }; if !missing.is_empty() { @@ -890,7 +907,10 @@ fn run(module_path: &PathBuf, source: &str, script: &Path) -> Result { field_pos_spec_checked={field_pos_spec_checked} \ field_pos_spec_misplaced={field_pos_spec_misplaced} \ field_pos_attached_checked={field_pos_attached_checked} \ - field_pos_attached_misplaced={field_pos_attached_misplaced}" + field_pos_attached_misplaced={field_pos_attached_misplaced} \ + fbw_store_journal_rollback_failed={fbw_store_journal_rollback_failed} \ + fbw_blackhole_adopted_single_frame={fbw_blackhole_adopted_single_frame} \ + fbw_blackhole_adopted_multi_frame={fbw_blackhole_adopted_multi_frame}" ); } let packed = match run_result { diff --git a/pyre/pyrex/src/lib.rs b/pyre/pyrex/src/lib.rs index b4d94e6e29d..2ec3e25188b 100644 --- a/pyre/pyrex/src/lib.rs +++ b/pyre/pyrex/src/lib.rs @@ -832,15 +832,30 @@ fn maybe_print_jit_stats() { pyre_jit::fbw_diag_counter(9), pyre_jit::fbw_diag_counter(10), ); - // Walks that ended uncommitted after a residual had already run an - // irreversible effect: the store journal cannot undo a residual that wrote - // live heap or entered a Python frame, so the replay the caller falls back - // to applies those effects twice. `fbw_diag::ROLLED_BACK_WITH_EFFECTS`, - // which the wasm runner already exports; a nonzero value names a walk-abort - // variant that reaches `run_perfn_walk`'s epilogue without an adopt leg. + // Walks that ended uncommitted after a residual had already run an effect + // no journal undoes — it wrote live heap or entered a Python frame — so the + // replay the caller falls back to applies that effect twice. + // `fbw_diag::ROLLED_BACK_WITH_EFFECTS`, which the wasm runner also exports; + // a nonzero value names a walk-abort variant that reaches + // `run_perfn_walk`'s epilogue without an adopt leg. + // + // `STORE_JOURNAL_ROLLBACK_FAILED` is the hole that subtraction would + // otherwise open: a journaled store the rollback could not restore is + // subtracted out of the count above, so it needs one of its own. + // + // The two adoption tallies are the same population read from the other end: + // the walks that DID hand the interpreter a resumable image. Nothing else + // counts them, so a change that silently sends a shape back to the legacy + // replay moves no gated counter without these. eprintln!( - "[jit-stats] fbw_rolled_back_with_effects={}", + "[jit-stats] fbw_rolled_back_with_effects={} \ + fbw_store_journal_rollback_failed={} \ + fbw_blackhole_adopted_single_frame={} \ + fbw_blackhole_adopted_multi_frame={}", pyre_jit::fbw_diag_counter(1), + pyre_jit::fbw_diag_counter(11), + pyre_jit::fbw_diag_counter(12), + pyre_jit::fbw_diag_counter(13), ); let stats = pyre_jit::eval::driver_pair().0.get_stats(); eprintln!(