summaryrefslogtreecommitdiff
path: root/zjit/src
AgeCommit message (Collapse)Author
2025-08-07ZJIT: Remove the need for unwrap() on with_num_bits() (#14144)Takashi Kokubun
* ZJIT: Remove the need for unwrap() on with_num_bits() * Fix arm64 tests * Track the caller of with_num_bits Co-authored-by: Alan Wu <XrXr@users.noreply.github.com> --------- Co-authored-by: Alan Wu <XrXr@users.noreply.github.com>
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: Create HeapObject Type (#14140)Max Bernstein
This is a counterpoint to the Immediate type and it represents all BasicObject subclasses except for the several immediate objects. If we know something is a HeapObject, we know we can treat it as an RBasic pointer.
2025-08-07ZJIT: Set PC before StringCopy (#14141)Max Bernstein
ZJIT: Set PC before StringCopy This function allocates.
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: x86: split: Fix live ranges index-out-of-range panicAlan Wu
Previously we crashed panicked due to index bounds check running test_fixnum.rb. On ARM and in other places in the x86 backend, this isn't a problem because they inspect the output of instructions which is never replaced.
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-05ZJIT: Fix `Kernel#Float`'s annotation (#14123)Stan Lo
As pointed out in https://github.com/ruby/ruby/pull/14078#discussion_r2255427676, the return type should be `Float` instead.
2025-08-05ZJIT: Avoid matching built-in iseq's HIR line numbers in tests (#14124)Stan Lo
ZJIT: Avoid matching built-in ISEQs' HIR line numbers in tests Co-authored-by: Author: Takashi Kokubun <takashi.kokubun@shopify.com>
2025-08-05ZJIT: Profile type+shape distributions (#13901)Max Bernstein
ZJIT uses the interpreter to take type profiles of what objects pass through the code. It stores a compressed record of the history per opcode for the opcodes we select. Before this change, we re-used the HIR Type data-structure, a shallow type lattice, to store historical type information. This was quick for bringup but is quite lossy as profiles go: we get one bit per built-in type seen, and if we see a non-built-in type in addition, we end up with BasicObject. Not very helpful. Additionally, it does not give us any notion of cardinality: how many of each type did we see? This change brings with it a much more interesting slice of type history: a histogram. A Distribution holds a record of the top-N (where N is fixed at Ruby compile-time) `(Class, ShapeId)` pairs and their counts. It also holds an *other* count in case we see more than N pairs. Using this distribution, we can make more informed decisions about when we should use type information. We can determine if we are strictly monomorphic, very nearly monomorphic, or something else. Maybe the call-site is polymorphic, so we should have a polymorphic inline cache. Exciting stuff. I also plumb this new distribution into the HIR part of the compilation pipeline.
2025-08-04ZJIT: Add helpers to prepare for C calls (#14100)Takashi Kokubun
2025-08-01ZJIT: Reject builtin annotation if its iseq has multiple invokebuiltin insnsStan Lo
2025-08-01ZJIT: Annotate Kernel#classStan Lo
2025-08-01ZJIT: Improve builtin function annotation collectionStan Lo
2025-08-01ZJIT: Support annotating builtin functionsStan Lo
This allows us to annotate builtin functions with their return type.
2025-08-01ZJIT: Enable IncrCounter for arm64 (#14086)Takashi Kokubun
2025-08-01ZJIT: Refer to scratch registers in operandsAlan Wu
Co-authored-by: Takashi Kokubun <takashi.kokubun@shopify.com>
2025-08-01ZJIT: Fix side-exit panicking when there's too many localsAlan Wu
Previously, ARM64 panicked due to compiled_side_exits() when the memory displacement got large enough to exceed the 9 bits limit. Usually, we split these kind of memory operands, but compiled_side_exits() runs after split. Using scratch registers, implement `Insn::Store` on ARM such that it can handle large displacements without split(). Do this for x86 as well, and remove arch specific code from compiled_side_exits(). We can now run `TestKeywordArguments`. Since `Insn::Store` doesn't need splitting now, users enjoy lower register pressure. Downside is, using `Assembler::SCRATCH_REG` as a base register is now sometimes an error, depending on whether `Insn::Store` also needs to use the register. It seems a fair trade off since `SCRATCH_REG` is not often used, and we don't put it as a base register anywhere at the moment.
2025-08-01ZJIT: A64: Use MOVN for small negative immediatesAlan Wu
Save a couple instructions to load a small negative constant into a register. In fact MOVN is speced to alias as `mov` in the official disassembly.
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-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-31ZJIT: Remove false comment [ci skip]Alan Wu
2025-07-31ZJIT: Only build the assembler for `target_arch`Alan Wu
Fixes test error from running the ARM assembler on x86, but then trying to disassemble it as x86.
2025-07-31ZJIT: A64: Add add_extended() which can add a register to spAlan Wu
2025-07-30ZJIT: Don't create owned Cow/String when printingMax Bernstein
2025-07-30ZJIT: Don't make unnecessary CowMax Bernstein
2025-07-30ZJIT: Don't write to StringMax Bernstein
2025-07-30ZJIT: Get rid of CallInfoMax Bernstein
2025-07-30ZJIT: Deref struct in find()Max Bernstein
2025-07-30ZJIT: Remove catch-all case to make it clearer what's unimplementedMax Bernstein
2025-07-30ZJIT: Remove unused ArraySet instructionMax Bernstein
2025-07-30ZJIT: Prepare for sharing JIT hooks with ZJIT (#14044)Takashi Kokubun
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-29Get rid of imemo_astJean Boussier
It has been marked as obsolete for a while and I see no reason to keep it.
2025-07-28ZJIT: Support invalidating constant patch points (#13998)Stan Lo
2025-07-28ZJIT: Fix land raceMax Bernstein
2025-07-28ZJIT: Mark Symbol, Float, NilClass, TrueClass, FalseClass as finalMax Bernstein
They can be subclassed but new instances cannot be created.
2025-07-28ZJIT: Remove Integer subclasses from latticeMax Bernstein
While Integer can technically be subclassed, instances of subclasses cannot be created. Remove it from the type lattice.
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-24ZJIT: Re-enable some A64 assembler testsAlan Wu
Tweak for Condition to build when `cfg!(target = "x86_64")`.
2025-07-24ZJIT: DRY up underscore rexport anti-patternAlan Wu
Keeping the same name makes re-exporting more concise.
2025-07-24Remove unused imemo_parser_strtermPeter Zhu
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]