Commit 874a68f
committed
ZJIT: Inline
Argument-forwarding delegators are everywhere in Rails -- `Module#delegate`,
`SimpleDelegator`, `ActiveRecord::Delegation` -- and every one of them costs a
`rb_vm_sendforward()` call out of JIT code, 664K of them per lobsters run. The
callinfo a `bar(...)` needs to replay the call lives in the `...` local, which
only the caller knows, so the standalone compilation of a forwardable ISEQ can
never see it. Inlining the callee is what makes it a compile-time constant.
Two halves:
* `can_inline` now accepts a forwardable callee, and `inline_methods` maps its
sole parameter -- the `...` local -- to an `Insn::ForwardingCallInfo` carrying
the call site's callinfo. `Insn::PushInlineFrame` grows the frame by the call
site's argument count and copies the arguments and the callinfo into it, the
layout `vm_call_iseq_forwardable` builds. That layout is not optional: a side
exit lands the interpreter on the `sendforward`, whose
`vm_adjust_stack_forwarding` reads the arguments back out from below the frame
at `lep - (local_table_size + argc + 2)`. `FrameState` records the extension so
a JITFrame stack map still finds the caller's slots below the taller frame.
* `specialize_send_forward` merges the site's callinfo with the caller's the way
`vm_caller_setup_fwd_args` does -- site method name, site arguments followed by
the caller's, caller's keyword table, `VM_CALL_ARGS_SIMPLE` dropped -- and emits
a `SendDirect`. The merged shape travels as a `CallShape` rather than a
synthesized `rb_callinfo`: there is no object to point at and no way to root
one. A site this declines keeps its `Insn::SendForward`, which the interpreter
still completes out of the frame extension; it never becomes a generic `Send`,
whose `cd` would report the wrong argument count. Chained forwarding falls out
of `CallShape::ci` being `None`, since a forwardable target's `...` local has to
receive a real callinfo. A block handed to the forwarder is read back out of the
frame's EP and installed as the merged call's, matching
`bh = VM_ENV_BLOCK_HANDLER(GET_LEP())`; re-deriving a literal block would capture
the wrong frame.
`sendforward` gains a ZJIT profiling variant so the merged call has a receiver
type to guard, skipping the top-of-stack slot: the `...` local is a callinfo
pointer, not a `VALUE`.
`super(...)` is untouched -- `vm_search_super_method` rebuilds the callinfo at run
time -- and `invokesuperforward` is out of scope.
lobsters, 15 iterations: sendforward fallbacks 663,770 -> 507,391 (-24%),
dynamic_send_count 8,293,928 -> 8,116,616 (-2.1%), code_region_bytes +0.6%.
The 446K that remain run in forwardable frames reached through megamorphic call
sites, which are compiled standalone and so still have no callinfo to merge.
Ported from zjit/all (e307fee). Adaptations for this branch:
* `PushInlineFrame` has no `guard_state` field here, so `forwarded` is the only
field added and the operand visitor and the codegen arm drop it.
* `type_specialize`'s `freeze`/`-@` arms are this branch's `try_rewrite_freeze`
and `try_rewrite_uminus`; only the new `SendForward` arm is added ahead of
them.
* `super`'s direct-send path was rewritten here by the visibility work, so the
`CallShape::from_ci(ci)` threading lands in `emit_specialized_super` instead.
* `Function::guard_profiled_type` does not exist here; the merged send's
receiver guard is the `guard_type_recompile(Type::from_profiled_type(..))`
that the ordinary `Send` path uses.
* `FrameState` still derives `Clone` and `profile.rs` still keeps `opnd_types`
in a `Vec`, so `profile_operands_below_top` sizes it with `resize()`.
* The bindings gain `YARVINSN_zjit_sendforward` at 233 and
`VM_INSTRUCTION_SIZE` 260 -> 261 in both yjit/ and zjit/, hand-patched (no
bindgen here) and checked against `RubyVM::INSTRUCTION_NAMES`.
* `PushInlineFrame`'s codegen and `build_stack_map` keep taking an owned,
resolved `FrameState` from `Function::frame_state` rather than upstream's
`frame_state_ref`. On this branch `frame_state_ref` documents itself as
returning the stored state with *stale* operand ids, and both callers feed
those ids to `jit.get_opnd`: the borrowed form panics with
"Failed to get_opnd" on the stack-overflow-check side exit as soon as an
inlined frame's snapshot holds a value that was later replaced.
[reorder port note] Pulled forward from stack position 48 to position 10, onto a
base that predates roughly 38 of the commits its diff carried context from. What
changed relative to the original:
* Dropped as foreign context, none of it present in this stack: the `super`
specialization helpers (`emit_super_call_guards`, `emit_super_chain`,
`emit_specialized_super`, `UnwrapSvar`), `yield`/block-handler inlining
(`InlinedBlock`, `inline_block_at_yield`, `block_fallback_specializable_share`,
`inline_yield_bonus_count`, the `getblockparamproxy_handler_*` and
`InvokeBlockAutosplatMiss`/`InvokeBlockDynamicMiss` counters and reasons),
`PushInlineFrame`'s `block_arg`/`captured` fields, `AddIseqMode::Inlined`'s
`block`/`block_return_pops`, the `YARVINSN_splatarray` profiling arm, the
Symbol-block guard in the ISEQ direct-send path, and the `test_kwrest_*`
codegen tests. `CallShape::from_ci(ci)` threading lands on this branch's
inline `super` direct-send path in `type_specialize` rather than in
`emit_specialized_super`.
* Behaviour dropped, deliberately: a `bar(...)` whose inlined `def foo(...)`
frame was handed a block is no longer expanded. Upstream reads the frame's
block handler out of its EP and installs it as the merged `SendDirect`'s
`block_arg`, but this branch's `SendDirectData` has no `block_arg` field and
`BlockHandler::BlockArg` is `unreachable!()` in `gen_send_iseq_direct`, so
there is no way to hand a run-time handler to a direct send. Such a site keeps
its `Insn::SendForward`, which the interpreter still completes out of the frame
extension, and is counted as `send_forward_reject_complex_args`.
`Insn::ForwardingCallInfo::has_block` is retained and is what drives the
rejection, so restoring the passthrough is a local change once `block_arg`
exists. `has_block` is derived from the inlining site's `blockiseq`, which on
this branch is the only way an inlined frame can carry a block.
* Adapted rather than taken verbatim: `specialize_send_forward` uses
`assume_no_singleton_classes` + an explicit `Invariant::MethodRedefined`
patch point instead of `assume_no_singleton_classes_for_send` /
`assume_cme_for_send`, and resolves the receiver with
`resolve_receiver_type` alone -- `Function::ancestor_dispatch_class` and the
ancestor-guard dispatch it feeds do not exist here.
`build_send_direct_args` takes four arguments here (no
`block_arg_passthrough`).
* Bindings renumbered for this stack rather than copied: this tree has 226
non-ZJIT instructions and, with `sendforward`, 33 `zjit_profile` ones, so
`YARVINSN_zjit_sendforward` is 231 and `VM_INSTRUCTION_SIZE` 258 -> 259 in
`zjit/src/cruby_bindings.inc.rs`. `yjit/src/cruby_bindings.inc.rs` is shifted
by the same +1 (sendforward 232, size 259 -> 260) but keeps a stale
`YARVINSN_zjit_getblockparamproxy` that c651c0a removed from insns.def and
from the ZJIT bindings without updating the YJIT copy; that pre-existing
one-instruction skew belongs to c651c0a, not here.
* `zjit/src/hir/opt_tests.rs`'s `super`-forwarding snapshot was merged
best-effort: this branch's guard sequence (no `UnwrapSvar`, no `recompile`
suffix) with the new inlined body appended. Snapshot text is `#[cfg(test)]`
and may need `INSTA_FORCE_UPDATE` once the suite runs.
[reorder port note 2] Re-ported onto zjit-lobsters4 (master 76b1775 + front
block), whose PR #18606 already compiles direct sends to forwardable callees
with the forwardable checks folded into `can_direct_send`:
* `can_direct_send_forwardable` is not re-introduced; the commit's two new
checks land in `can_direct_send`'s forwardable arm instead (`ci.is_none()`
joins the FORWARDABLE_CALLEE_BLOCKERS rejection, and the
`original.len() != argc` ArgcParamMismatch guard precedes the u16 check).
* The base's `CallerArguments` (kwarg_count/splat_arg_idx form from #18369)
keeps its shape; only the commit's `argc`/`ci` fields and the
`CallShape`-taking constructor are added, and every `CallerArguments::new`
caller wraps its callinfo with `CallShape::from_ci(ci)`.
* `build_send_direct_args` takes five arguments here (#18567's
`block_arg_passthrough`); `specialize_send_forward` passes `false` and its
`SendDirectData` gains the base's `block_arg: None` field.
* The Symbol-block-forwardable rejection and `send_block_arg` threading from
this base's front block are kept as-is around the touched call sites.
* Bindings regenerated canonically: `zjit_sendforward` is 232 and
`VM_INSTRUCTION_SIZE` 260 in BOTH checked-in copies (this base has
`zjit_expandarray` and no `zjit_getblockparamproxy`).
* Upstream #18606's `call_method_forwardable_param_with_block_literal`
expectation ("stays a direct send") is superseded: the callee is now inlined
and the inner `bar(...)` keeps its SendForward because the frame carries a
block, matching this commit's documented block-handling rejection.def foo(...) callees and compile the bar(...) inside them1 parent 91d3e3c commit 874a68f
10 files changed
Lines changed: 756 additions & 110 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
876 | 876 | | |
877 | 877 | | |
878 | 878 | | |
| 879 | + | |
879 | 880 | | |
880 | 881 | | |
881 | 882 | | |
| |||
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1110 | 1110 | | |
1111 | 1111 | | |
1112 | 1112 | | |
| 1113 | + | |
| 1114 | + | |
| 1115 | + | |
| 1116 | + | |
| 1117 | + | |
| 1118 | + | |
1113 | 1119 | | |
1114 | 1120 | | |
1115 | 1121 | | |
| |||
1165 | 1171 | | |
1166 | 1172 | | |
1167 | 1173 | | |
1168 | | - | |
1169 | | - | |
| 1174 | + | |
| 1175 | + | |
| 1176 | + | |
| 1177 | + | |
| 1178 | + | |
1170 | 1179 | | |
1171 | 1180 | | |
1172 | 1181 | | |
| |||
2282 | 2291 | | |
2283 | 2292 | | |
2284 | 2293 | | |
| 2294 | + | |
2285 | 2295 | | |
2286 | | - | |
| 2296 | + | |
| 2297 | + | |
| 2298 | + | |
| 2299 | + | |
| 2300 | + | |
| 2301 | + | |
| 2302 | + | |
| 2303 | + | |
| 2304 | + | |
| 2305 | + | |
| 2306 | + | |
| 2307 | + | |
2287 | 2308 | | |
2288 | 2309 | | |
2289 | 2310 | | |
| |||
2325 | 2346 | | |
2326 | 2347 | | |
2327 | 2348 | | |
2328 | | - | |
| 2349 | + | |
2329 | 2350 | | |
2330 | 2351 | | |
| 2352 | + | |
| 2353 | + | |
| 2354 | + | |
| 2355 | + | |
| 2356 | + | |
| 2357 | + | |
| 2358 | + | |
| 2359 | + | |
| 2360 | + | |
| 2361 | + | |
| 2362 | + | |
| 2363 | + | |
| 2364 | + | |
| 2365 | + | |
| 2366 | + | |
| 2367 | + | |
| 2368 | + | |
| 2369 | + | |
| 2370 | + | |
2331 | 2371 | | |
2332 | 2372 | | |
2333 | 2373 | | |
| |||
2392 | 2432 | | |
2393 | 2433 | | |
2394 | 2434 | | |
2395 | | - | |
| 2435 | + | |
| 2436 | + | |
| 2437 | + | |
| 2438 | + | |
2396 | 2439 | | |
2397 | 2440 | | |
2398 | 2441 | | |
| |||
4273 | 4316 | | |
4274 | 4317 | | |
4275 | 4318 | | |
| 4319 | + | |
| 4320 | + | |
| 4321 | + | |
4276 | 4322 | | |
4277 | 4323 | | |
4278 | 4324 | | |
| |||
4287 | 4333 | | |
4288 | 4334 | | |
4289 | 4335 | | |
4290 | | - | |
| 4336 | + | |
4291 | 4337 | | |
4292 | 4338 | | |
4293 | 4339 | | |
4294 | 4340 | | |
4295 | 4341 | | |
4296 | | - | |
| 4342 | + | |
4297 | 4343 | | |
4298 | 4344 | | |
4299 | 4345 | | |
4300 | | - | |
| 4346 | + | |
| 4347 | + | |
| 4348 | + | |
4301 | 4349 | | |
4302 | 4350 | | |
4303 | 4351 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
819 | 819 | | |
820 | 820 | | |
821 | 821 | | |
| 822 | + | |
| 823 | + | |
| 824 | + | |
| 825 | + | |
| 826 | + | |
| 827 | + | |
| 828 | + | |
| 829 | + | |
| 830 | + | |
| 831 | + | |
| 832 | + | |
| 833 | + | |
| 834 | + | |
| 835 | + | |
| 836 | + | |
| 837 | + | |
| 838 | + | |
| 839 | + | |
| 840 | + | |
| 841 | + | |
| 842 | + | |
| 843 | + | |
| 844 | + | |
| 845 | + | |
| 846 | + | |
| 847 | + | |
| 848 | + | |
| 849 | + | |
| 850 | + | |
| 851 | + | |
| 852 | + | |
| 853 | + | |
| 854 | + | |
| 855 | + | |
| 856 | + | |
| 857 | + | |
| 858 | + | |
| 859 | + | |
| 860 | + | |
| 861 | + | |
| 862 | + | |
| 863 | + | |
| 864 | + | |
| 865 | + | |
| 866 | + | |
| 867 | + | |
| 868 | + | |
| 869 | + | |
| 870 | + | |
| 871 | + | |
| 872 | + | |
| 873 | + | |
| 874 | + | |
| 875 | + | |
| 876 | + | |
| 877 | + | |
| 878 | + | |
| 879 | + | |
| 880 | + | |
| 881 | + | |
| 882 | + | |
| 883 | + | |
| 884 | + | |
| 885 | + | |
| 886 | + | |
| 887 | + | |
| 888 | + | |
| 889 | + | |
| 890 | + | |
| 891 | + | |
| 892 | + | |
| 893 | + | |
| 894 | + | |
| 895 | + | |
| 896 | + | |
| 897 | + | |
| 898 | + | |
| 899 | + | |
| 900 | + | |
| 901 | + | |
| 902 | + | |
| 903 | + | |
| 904 | + | |
| 905 | + | |
| 906 | + | |
| 907 | + | |
| 908 | + | |
| 909 | + | |
| 910 | + | |
| 911 | + | |
| 912 | + | |
| 913 | + | |
| 914 | + | |
| 915 | + | |
| 916 | + | |
| 917 | + | |
| 918 | + | |
| 919 | + | |
| 920 | + | |
| 921 | + | |
| 922 | + | |
| 923 | + | |
| 924 | + | |
| 925 | + | |
| 926 | + | |
| 927 | + | |
| 928 | + | |
| 929 | + | |
| 930 | + | |
| 931 | + | |
| 932 | + | |
| 933 | + | |
| 934 | + | |
| 935 | + | |
| 936 | + | |
| 937 | + | |
| 938 | + | |
| 939 | + | |
| 940 | + | |
| 941 | + | |
| 942 | + | |
| 943 | + | |
| 944 | + | |
| 945 | + | |
| 946 | + | |
| 947 | + | |
| 948 | + | |
| 949 | + | |
| 950 | + | |
| 951 | + | |
| 952 | + | |
| 953 | + | |
| 954 | + | |
| 955 | + | |
| 956 | + | |
| 957 | + | |
| 958 | + | |
| 959 | + | |
| 960 | + | |
| 961 | + | |
| 962 | + | |
| 963 | + | |
| 964 | + | |
| 965 | + | |
| 966 | + | |
| 967 | + | |
| 968 | + | |
| 969 | + | |
| 970 | + | |
| 971 | + | |
| 972 | + | |
| 973 | + | |
| 974 | + | |
| 975 | + | |
| 976 | + | |
| 977 | + | |
| 978 | + | |
| 979 | + | |
| 980 | + | |
| 981 | + | |
| 982 | + | |
| 983 | + | |
| 984 | + | |
| 985 | + | |
| 986 | + | |
822 | 987 | | |
823 | 988 | | |
824 | 989 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1083 | 1083 | | |
1084 | 1084 | | |
1085 | 1085 | | |
| 1086 | + | |
| 1087 | + | |
| 1088 | + | |
| 1089 | + | |
| 1090 | + | |
1086 | 1091 | | |
1087 | 1092 | | |
1088 | 1093 | | |
| |||
0 commit comments