summaryrefslogtreecommitdiff
path: root/test/ruby/test_zjit.rb
AgeCommit message (Collapse)Author
2025-08-08ZJIT: Avoid compiling and direct sends to forwardable ISEQsAlan Wu
These `...` ISEQs have a special calling convention in the interpreter and our stubs and JIT calling convention don't deal well. Reject for now. Debugged with help from `@tekknolagi` and `tool/zjit_bisect.rb`. Merely avoiding direct sends is enough to pass the attached test, but also avoid compiling ISEQs with `...` parameter to limit exposure for now. `SendWithoutBlock`, which does dynamic dispatch using interpreter code, seems to handle calling into forwardable ISEQs correctly, so they are fine -- we can't predict where these dynamic sends land anyways.
2025-08-08ZJIT: Fix "memory operand with non-register base" (#14153)Takashi Kokubun
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-06ZJIT: Inline attr_reader/attr_accessor (#14126)Max Bernstein
We can rewrite SendWithoutBlock to GetIvar.
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-06ZJIT: Fix "immediate value too large" on cmp for x86_64 (#14125)Takashi Kokubun
Co-authored-by: Alan Wu <alansi.xingwu@shopify.com>
2025-08-01ZJIT: Enable IncrCounter for arm64 (#14086)Takashi Kokubun
2025-07-31ZJIT: A64: Fix splitting for large memory displacementsAlan Wu
On the ruby side, this fixes a crash for methods with 39 or more parameters. We used to miscomp those entry points due to Insn::Lea picking ADDS which cannot reference SP: # set method params: 40 mov x0, #0xfee8 movk x0, #0xffff, lsl #16 movk x0, #0xffff, lsl #32 movk x0, #0xffff, lsl #48 adds x0, xzr, x0 Have Lea work for all i32 displacements and avoid involving the split pass. Previously, direct use of Insn::Lea directly from the user (as opposed to generated by the split pass for some memory operations) wasn't split, so being able to handle the whole range in arm64_emit() was implicitly required. Also, not going through split reduces register pressure.
2025-07-30ZJIT: Prepare for sharing JIT hooks with ZJIT (#14044)Takashi Kokubun
2025-07-28ZJIT: Support invalidating constant patch points (#13998)Stan Lo
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-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: Give up JIT-to-JIT calls for 6+ args (#13939)Takashi Kokubun
2025-07-16ZJIT: Split shift with immediate operand (#13914)Max Bernstein
Fix https://github.com/Shopify/ruby/issues/627
2025-07-16ZJIT: Fix SP alignment on JIT entry for x86_64Takashi Kokubun
2025-07-15ZJIT: Add failing test to test_spilled_method_args()Alan Wu
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-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: Name side-exit test cases correctlyStan Lo
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-03ZJIT: Panic on BOP redefinition only when needed (#13782)Takashi Kokubun
2025-07-03ZJIT: Bail out on register spill (#13773)Takashi Kokubun
2025-07-02ZJIT: Support spilling basic block arguments (#13761)Takashi Kokubun
Co-authored-by: Max Bernstein <max@bernsteinbear.com>
2025-07-02ZJIT: Annotate NilClass#nil? and Kernel#nil?Stan Lo
These methods return fixed `true` or `false` so we can be certain about their return types.
2025-06-30ZJIT: Add codegen for IsNilywenc
2025-06-30ZJIT: Don't compile functions with unhandled parameter types (#13749)Max Bernstein
2025-06-28ZJIT: Codegen for `defined?(yield)`Alan Wu
Lots of stdlib methods such as Integer#times and Kernel#then use this, so at least this will make writing tests slightly easier.
2025-06-27ZJIT: Add TODOs and omitted test for nested scope local accessAlan Wu
2025-06-27ZJIT: Add codegen for GetLocal and SetLocalAlan Wu
They're only used when level≠0. Same EP hopping logic as interpreter and YJIT. Change assert_compiles() to get ISeq by method name since the old code didn't support methods defined using define_method() which I need for the new test.
2025-06-19ZJIT: Add `dupn` supportAlan Wu
Notes: Merged: https://github.com/ruby/ruby/pull/13641
2025-06-18ZJIT: Support invokebuiltin opcodes (#13632)Daniel Colson
* `invokebuiltin` * `invokebuiltin_delegate` * `invokebuiltin_delegate_leave` These instructions all call out to a C function, passing EC, self, and some number of arguments. `invokebuiltin` gets the arguments from the stack, whereas the `_delegate` instructions use a subset of the locals. `opt_invokebuiltin_delegate_leave` has a fast path for `leave`, but I'm not sure we need to do anything special for that here (FWIW YJIT appears to treat the two delegate instructions the same). Notes: Merged-By: k0kubun <takashikkbn@gmail.com>
2025-06-17ZJIT: Add codegen (and FrameState) for GetConstPathAlan Wu
Issue a call to rb_vm_opt_getconstant_path() like the interpreter, but since that allocates the IC, we need to save the PC before calling. Add FrameState to GetConstPath to get access to the PC. Notes: Merged: https://github.com/ruby/ruby/pull/13628
2025-06-17ZJIT: Parse opt freeze insns to HIRDaniel Colson
* `opt_hash_freeze` * `opt_ary_freeze` * `opt_str_freeze` * `opt_str_uminus` Similar to `opt_neq`, but there are no args for `freeze` Co-authored-by: ywenc <ywenc@github.com> Co-authored-by: Max Bernstein <max@bernsteinbear.com> Notes: Merged: https://github.com/ruby/ruby/pull/13588
2025-06-17ZJIT: Add codegen for StringCopyDaniel Colson
Prior to this commit we compiled `putstring` and `putchilledstring` to `StringCopy`, but then failed to compile past HIR. This commit adds codegen for `StringCopy` to call `rb_ec_str_ressurrect` as the VM does for these instructions. Notes: Merged: https://github.com/ruby/ruby/pull/13625
2025-06-16ZJIT: Add support for putspecialobject (#13565)Stan Lo
* ZJIT: Add support for putspecialobject * Address feedback * Update tests * Adjust the indentation of a Ruby test --------- Co-authored-by: Takashi Kokubun <takashikkbn@gmail.com> Notes: Merged-By: k0kubun <takashikkbn@gmail.com>
2025-06-12ZJIT: Write a callee frame on JIT-to-JIT calls (#13579)Takashi Kokubun
Co-authored-by: Max Bernstein <tekknolagi@gmail.com> Notes: Merged-By: k0kubun <takashikkbn@gmail.com>
2025-06-09ZJIT: Parse opt_regexpmatch2 into HIRAlan Wu
Notes: Merged: https://github.com/ruby/ruby/pull/13549
2025-06-09ZJIT: Parse opt_not into HIRAlan Wu
Notes: Merged: https://github.com/ruby/ruby/pull/13549
2025-06-09ZJIT: Parse opt_or into HIRAlan Wu
Notes: Merged: https://github.com/ruby/ruby/pull/13549
2025-06-09ZJIT: Parse opt_and into HIRAlan Wu
Notes: Merged: https://github.com/ruby/ruby/pull/13549
2025-06-09ZJIT: Parse opt_succ into HIRAlan Wu
Notes: Merged: https://github.com/ruby/ruby/pull/13549
2025-06-09ZJIT: Parse opt_empty_p into HIRAlan Wu
Notes: Merged: https://github.com/ruby/ruby/pull/13549
2025-06-06ZJIT: Add codegen for uncached setinstancevariableMax Bernstein
Notes: Merged: https://github.com/ruby/ruby/pull/13527