summaryrefslogtreecommitdiff
path: root/doc/csv/options/generating/write_converters.rdoc
diff options
context:
space:
mode:
authorGodfrey Chan <godfreykfc@gmail.com>2026-01-28 13:32:33 -0800
committerGitHub <noreply@github.com>2026-01-28 21:32:33 +0000
commit2d5460e4d78032584dbf261259a8b05b856dffdf (patch)
treee784124c767d16ffcd67ffb383b4a38e0ae4d79e /doc/csv/options/generating/write_converters.rdoc
parent72f11c8bfaedb4260fe9d29b2f9bd26d83b8c18a (diff)
ZJIT: Optimize send-with-block to iseq methods (#15911)HEADmaster
~~Two commits:~~ ### zjit: Optimize send-with-block to iseq methods This commit enables JIT-to-JIT calls for send instructions with literal blocks (e.g., `foo { |x| x * 2 }`), rather than falling back to the `rb_vm_send` C wrapper. This optimization applies to both methods with explicit block parameters (`def foo(&block)`) and methods implicitly accepting a block (`def foo; yield if block_given?; end`). Prior to this change, any callsite with a block would miss out on the JIT-to-JIT fast path and goes through a `rb_vm_send` C wrapper call. Initially, as https://github.com/Shopify/ruby/issues/931 suggested, we assumed this would involve changes to the JIT-to-JIT calling convention to accommodate passing a block argument. However, during implementation, I discovered that @nirvdrum had already wired up the `specval` protocol used by the interpreter in their `invokesuper` work (https://github.com/ruby/ruby/pull/887). That infrastructure remained dormant but was exactly what we needed here. After plumbing everything through, it Just Worked™. It may be possible to design a more direct JIT-to-JIT protocol for passing blocks. In the HIR for `def foo(&block)`, the BB for the JIT entrypoint already takes two arguments (self + &block, presumably), and since `yield` is a keyword, it may be possible to rewrite the implicit case to be explicit (thanks @tenderlove for the idea), and do "better" than passing via `specval`. I'm not sure if that's a goal eventually, but in any case, if `specval` works, there is no harm in enabling this optimization today. Implementation notes: This initial pass largely duplicates the existing `SendWithoutBlock` to `SendWithoutBlockDirect` specialization logic. A future refactor could potentially collapse Send and SendWithoutBlock into a single instruction variant (with `blockiseq: Option<IseqPtr>`, you can always pattern match the Option if needed), since they now follow very similar paths. However, I wanted to keep this PR focused and also get feedback on that direction first before committing to such a big refactor. The optimization currently handles `VM_METHOD_TYPE_ISEQ` only. It does not handle "block to block" `VM_METHOD_TYPE_BMETHOD`. It's unclear if that'd be all that difficult, I just didn't try. Happy to do it as a follow-up. Any callsites not handled by this specialization continue to fallthrough to the existing rb_vm_send harness safely. Test coverage includes both explicit block parameters and yield-based methods. Thanks to @tenderlove for initial ideas and walkthrough, and @nirvdrum for the foundation this builds on. Closes https://github.com/Shopify/ruby/issues/931 ### ~~zjit: Allow SendWithoutBlockDirect to def f(&blk)~~ Saving this for another time ### Follow-ups * [ ] Refactor and simplify by merging `hir::Insn::Send` and `hir::Insn::SendWithoutBlock`. (Pending feedback/approval.) * [ ] Handle block-to-block `VM_METHOD_TYPE_BMETHOD` calls. It appears that `gen_send_iseq_direct` already attempted to handle it. * [ ] As far as I can tell, we should be able to just enable `super { ... }` too, happy to do that as a follow-up if @nirvdrum doesn't have time for it.
Diffstat (limited to 'doc/csv/options/generating/write_converters.rdoc')
0 files changed, 0 insertions, 0 deletions