summaryrefslogtreecommitdiff
path: root/zjit/src/codegen.rs
AgeCommit message (Collapse)Author
2025-08-07ZJIT: Implement `defined?` codegen for non-yield calls (#14101)Stan Lo
2025-08-07ZJIT: Optimize class guards by directly reading klass field (#14136)Stan Lo
Replace `rb_yarv_class_of` call with: - a constant check for special constants (nil, fixnums, symbols, etc) - a check for false - direct memory read at offset 8 for regular heap objects for the class check
2025-08-07ZJIT: Remove GC offsets overwritten by invalidation (#14102)Takashi Kokubun
ZJIT: Remove GC offsts overwritten by invalidation
2025-08-07ZJIT: Set PC before StringCopy (#14141)Max Bernstein
ZJIT: Set PC before StringCopy This function allocates.
2025-08-06ZJIT: Implement SingleRactorMode invalidation (#14121)Stan Lo
* ZJIT: Implement SingleRactorMode invalidation * ZJIT: Add macro for compiling jumps * ZJIT: Fix typo in comment * YJIT: Fix typo in comment * ZJIT: Avoid using unexported types in zjit.h `enum ruby_vminsn_type` is declared in `insns.inc` and is not exported. Using it in `zjit.h` would cause build errors when the file including it doesn't include `insns.inc`.
2025-08-04ZJIT: Add helpers to prepare for C calls (#14100)Takashi Kokubun
2025-08-01ZJIT: Support annotating builtin functionsStan Lo
This allows us to annotate builtin functions with their return type.
2025-07-31ZJIT: Add the ISEQ name to Block asm comments (#14070)Takashi Kokubun
2025-07-31ZJIT: Stub JIT-to-JIT calls (#14052)Takashi Kokubun
2025-07-30ZJIT: Get rid of CallInfoMax Bernstein
2025-07-30ZJIT: Remove catch-all case to make it clearer what's unimplementedMax Bernstein
2025-07-29ZJIT: Catch more failed recursive compilations (#14042)Max Bernstein
Untangle the logic a bit and specifically: * catch `gen_entry` failures * don't set `start_ptr` until all recursive calls succeed Co-authored-by: Alan Wu <alanwu@ruby-lang.org>
2025-07-29ZJIT: Create delta debugging script to narrow JIT failures (#14041)Max Bernstein
Add support for `--zjit-allowed-iseqs=SomeFile` and `--zjit-log-compiled-iseqs=SomeFile` so we can restrict and inspect which ISEQs get compiled. Then add `jit_bisect.rb` which we can run to try and narrow a failing script. For example: plum% ../tool/zjit_bisect.rb ../build-dev/miniruby "test.rb" I, [2025-07-29T12:41:18.657177 #96899] INFO -- : Starting with JIT list of 4 items. I, [2025-07-29T12:41:18.657229 #96899] INFO -- : Verifying items I, [2025-07-29T12:41:18.726213 #96899] INFO -- : step fixed[0] and items[4] I, [2025-07-29T12:41:18.726246 #96899] INFO -- : 4 candidates I, [2025-07-29T12:41:18.797212 #96899] INFO -- : 2 candidates Reduced JIT list: bar@test.rb:8 plum% We start with 4 compiled functions and shrink to just one.
2025-07-29ZJIT: Add --zjit-stats (#14034)Takashi Kokubun
2025-07-28ZJIT: Support invalidating constant patch points (#13998)Stan Lo
2025-07-28ZJIT: Fix land raceMax Bernstein
2025-07-28ZJIT: Inline guard type checks for some built-in types (#14017)Stan Lo
This implements similar fast-path guard type checks as YJIT.
2025-07-28ZJIT: Keep a frame pointer and use it for memory paramsAlan Wu
Previously, ZJIT miscompiled the following because of native SP interference. def a(n1,n2,n3,n4,n5,n6,n7,n8) = [n8] a(0,0,0,0,0,0,0, :ok) Commented problematic disassembly: ; call rb_ary_new_capa mov x0, #1 mov x16, #0x1278 movk x16, #0x4bc, lsl #16 movk x16, #1, lsl #32 blr x16 ; call rb_ary_push mov x1, x0 str x1, [sp, #-0x10]! ; c_push() from alloc_regs() mov x0, x1 ; arg0, the array ldur x1, [sp] ; meant to be arg1=n8, but sp just moved! mov x16, #0x3968 movk x16, #0x4bc, lsl #16 movk x16, #1, lsl #32 blr x16 Since the frame pointer stays constant in the body of the function, static offsets based on it don't run the risk of being invalidated by SP movements. Pass the registers to preserve through Insn::FrameSetup. This allows ARM to use STP and waste no gaps between EC, SP, and CFP. x86 now preserves and restores RBP since we use it as the frame pointer. Since all arches now have a frame pointer, remove offset based SP movement in the epilogue and restore registers using the frame pointer.
2025-07-23ZJIT: Fix clobbering register for `self` in gen_entry_params()Alan Wu
Previously, for 8+ params we wound up clobbering the self param when putting the last param in memory in the JIT entry point: # ZJIT entry point: a@../test.rb:5 <snip> ldur x0, [x19, #0x18] # set method params: 8 ldur x1, [x21, #-0x58] ldur x2, [x21, #-0x50] ldur x3, [x21, #-0x48] ldur x4, [x21, #-0x40] ldur x5, [x21, #-0x38] ldur x11, [x21, #-0x30] ldur x12, [x21, #-0x28] ldur x0, [x21, #-0x20] stur x0, [sp, #-0x20] bl #0x11e17018c Doing the memcpys for parameters in memory first avoids this clobbering. # set method params: 8 ldur x0, [x21, #-0x20] stur x0, [sp, #-0x20] ldur x12, [x21, #-0x28] ldur x11, [x21, #-0x30] ldur x5, [x21, #-0x38] ldur x4, [x21, #-0x40] ldur x3, [x21, #-0x48] ldur x2, [x21, #-0x50] ldur x1, [x21, #-0x58] ldur x0, [x19, #0x18]
2025-07-22ZJIT: Use rb_vm_env_write() for `hir::Insn::SetLocal`Alan Wu
We weren't firing write barriers before when writing to imemo/env objects. Wbcheck caught this with test/ruby/test_refinement.rb: ruby -v: ruby 3.5.0dev (2025-07-22T17:05:58Z wbcheck 2569a80954) +ZJIT dev +PRISM +GC[wbcheck] [x86_64-linux] WBCHECK ERROR: Missed write barrier detected! Parent object: 0x558de9f4e6e0 (wb_protected: true) rb_obj_info_dump: 0x0000558de9f4e6e0 T_IMEMO/<env> Reference counts - snapshot: 3, writebarrier: 0, current: 4, missed: 1 Missing reference to: 0x558decf37c30 rb_obj_info_dump: 0x0000558decf37c30 method/UnboundMethod method WBCHECK SUMMARY: Found 1 objects with missed write barriers (1 total violations)
2025-07-21ZJIT: Load return value before frame teardownAlan Wu
Or else the following returns garbage since it loads after moving SP. Prior bad disassembly: def a(n1,n2,n3,n4,n5,n6,n7,n8) = n8 a(1,1,1,1,1,1,1,0) # Block: bb0(v0, v1, v2, v3, v4, v5, v6, v7, v8) stp x29, x30, [sp, #-0x10]! mov x29, sp # bump C stack pointer sub sp, sp, #0x10 # Insn: v10 Return v8 # pop stack frame adds x19, x19, #0x38 stur x19, [x20, #0x10] # restore C stack pointer add sp, sp, #0x10 mov sp, x29 ldp x29, x30, [sp], #0x10 ldur x0, [sp] ret
2025-07-18ZJIT: Support invalidating on method redefinition (#13875)Stan Lo
ZJIT: Support invalidating method redefinition This commit adds support for the MethodRedefined invariant to be invalidated when a method is redefined. Changes: - Added CME pointer to the MethodRedefined invariant in HIR - Updated all places where MethodRedefined invariants are created to include the CME pointer - Added handling for MethodRedefined invariants in gen_patch_point to call track_cme_assumption, which registers the patch point for invalidation when rb_zjit_cme_invalidate is called This ensures that when a method is redefined, all JIT code that depends on that method will be properly invalidated.
2025-07-17ZJIT: Create perf map files for profilers (#13941)Max Bernstein
This lets us ZJIT compiled functions show up in the profiles of, say, perf, or samply. Fix https://github.com/Shopify/ruby/issues/634
2025-07-17ZJIT: Give up JIT-to-JIT calls for 6+ args (#13939)Takashi Kokubun
2025-07-17ZJIT: Precise GC writebarriersJohn Hawthorn
This issues writebarriers for objects added via gc_offsets or by profiling. This may be slower than writebarrier_remember, but we would like it to be more debuggable. Co-authored-by: Max Bernstein <ruby@bernsteinbear.com> Co-authored-by: Stan Lo <stan001212@gmail.com>
2025-07-17Tweak the comment on mark_all_executable() a little [ci skip]Takashi Kokubun
2025-07-17ZJIT: Mark the code region executable on partial failures (#13937)Takashi Kokubun
2025-07-16Use a const blockTakashi Kokubun
Co-authored-by: Alan Wu <XrXr@users.noreply.github.com>
2025-07-16ZJIT: Restore SP on side-exit chainsTakashi Kokubun
2025-07-16ZJIT: Fix SP alignment on JIT entry for x86_64Takashi Kokubun
2025-07-15ZJIT: Redo JIT function native stack frame layoutAlan Wu
Previously, gen_param() access slots at `SP-x` for `x≥0` after subtracting from SP, so it was accessing slots from above the top of the stack. Also, the slots gen_entry_params() wrote to at entry point did not correspond to the slots access inside the JIT function. Redo the stack frame layout so that inside the function slots are at `SP+x`. Write to those slots in the entry point by anticipating the size of the frame. Fixes test_spilled_method_args().
2025-07-15ZJIT: Ban `asm.load_into(Mem, ..)` and avoid it in gen_entry_params()Alan Wu
Now that params can be in memory, this particular load_into() was panicking with "Invalid operands for LDUR" with test_spilled_method_args() on ARM. Since it's documented to be for register destinations let's validate it.
2025-07-14ZJIT: Make lir::Opnd::const_ptr take any pointer to save on castsAlan Wu
2025-07-14ZJIT: Add a ccall macro that also adds an LIR commentAlan Wu
This DRYs up the `asm_comment!` + `asm.ccall` combo, and makes ccalls have a comment by default.
2025-07-14ZJIT: Restore SP register after JIT-to-JIT call (#13882)Takashi Kokubun
Co-authored-by: Alan Wu <alansi.xingwu@shopify.com> Co-authored-by: Stan Lo <stan.lo@shopify.com>
2025-07-11ZJIT: Mark objects baked in JIT code (#13862)Takashi Kokubun
2025-07-11ZJIT: Improve asm comments for side exits (#13853)Takashi Kokubun
* ZJIT: Improve asm comments for side exits * Use GuardType(Type) and GuardBitEquals(VALUE)
2025-07-10ZJIT: Implement patch points on BOP redefinition (#13850)Takashi Kokubun
Co-authored-by: Max Bernstein <max@bernsteinbear.com>
2025-07-10ZJIT: Avoid optimizing locals on eval (#13840)Takashi Kokubun
* ZJIT: Avoid optimizing locals on eval * Maintain the local state for eval
2025-07-09ZJIT: Mark profiled objects when marking ISEQ (#13784)Takashi Kokubun
2025-07-09ZJIT: Optimize `opt_and` and `opt_or` instructions for FixnumStan Lo
2025-07-08ZJIT: Support guarding *Exact types (#13797)Stan Lo
ZJIT already can generate guard type instructions for *Exact types. For example: ``` def test(strings) strings.map do |string| string.bytesize end end test(["foo", "bar"]) ``` ``` HIR: fn block in test: bb0(v0:BasicObject, v1:BasicObject): PatchPoint MethodRedefined(String@0x1014be890, bytesize@0x19f1) v7:StringExact = GuardType v1, StringExact v8:Fixnum = CCall bytesize@0x16fa4cc18, v7 Return v8 ``` But zjit only supported guarding fixnums so this script would panic. This commit adds support for guarding *Exact types.
2025-07-07ZJIT: Add opnds macro for Vec<InsnId> to Vec<Opnd> (#13805)Daniel Colson
Along the same lines as the `opnd` macro we already have, but for a `Vec<InsnId>` instead of a single `InsnId`. This gets a few for loops and `jit.get_opnd` calls out of the `gen_` functions.
2025-07-07ZJIT: Add a simple HIR validator (#13780)Ken Jin
This PR adds a simple validator for ZJIT's HIR. See issue https://github.com/Shopify/ruby/issues/591
2025-07-03ZJIT: Panic on BOP redefinition only when needed (#13782)Takashi Kokubun
2025-07-02ZJIT: Reject ISEQs with too-large stack_max (#13770)Takashi Kokubun
2025-07-02ZJIT: Add reason for SideExit (#13768)Max Bernstein
This makes it clearer what is unimplemented when looking at HIR dumps.
2025-07-02ZJIT: Support spilling basic block arguments (#13761)Takashi Kokubun
Co-authored-by: Max Bernstein <max@bernsteinbear.com>
2025-07-01ZJIT: Stop tracking EP == BP assumption on JIT entry (#13752)Takashi Kokubun
* ZJIT: Stop tracking EP == BP assumption on JIT entry * Enable test_method.rb as well
2025-06-30ZJIT: Add codegen for IsNilywenc