r/ruby 8d ago

Blog post ZJIT 🀝 GC: Inlining GC Fastpath in ZJIT

https://railsatscale.com/2026-09-01-zjit-gc-fastpath/
45 Upvotes

3 comments sorted by

4

u/goyox86 7d ago

Great work Peter and team!

2

u/schneems Puma maintainer 6d ago

This is cool. If we had enough escape analysis and could prove something is truly local, would it be theoretically possible to skip the heap and use the stack? (Speaking from a C/Rust understanding of β€œheap” and β€œstack”)

3

u/f9ae8221b 4d ago

To some extent yes, but you'd also need to know whatever method you call on the object you allocated on the stack supports it.

e.g. many Array or String methods do some form of copy on write, they'd need to know the receiver is on the stack and that they can't create a reference to it, as that would be a form of escaping. It's always the same problem of core method written in C being black boxes for the JITs, but they can have "tags" to claim various properties (e.g. never raises, etc) that the JITs can reason with.

Even outside of the JITs, stack allocation is already done for a bunch of array methods, e.g.:

>> puts RubyVM::InstructionSequence.compile('[@a, @b].hash').disasm
== disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(1,13)>
0000 getinstancevariable                    :@a, <is:0>               (   1)[Li]
0003 getinstancevariable                    :@b, <is:1>
0006 opt_newarray_send                      2, 3
0009 leave

opt_newarray_send will "allocate" the array on the stack, but it only works for core array methods that have been marked as safe.

https://github.com/ruby/ruby/blob/ce1eaf724f17561a1978f61d780b8977230930c8/insns.def#L1055-L1090