summaryrefslogtreecommitdiff
path: root/bootstraptest/test_yjit.rb
AgeCommit message (Collapse)Author
2026-03-04YJIT: Bail out if proc would be stored above stack topRandy Stauner
Fixes [Bug #21266]. Backport of 9168cad4d63a5d281d443bde4edea6be213b0b25 to 3.3
2025-05-18merge revision(s) 80a1a1bb8ae8435b916ae4f66a483e91ad31356a: [Backport #21257]nagachika
YJIT: Fix potential infinite loop when OOM (GH-13186) Avoid generating an infinite loop in the case where: 1. Block `first` is adjacent to block `second`, and the branch from `first` to `second` is a fallthrough, and 2. Block `second` immediately exits to the interpreter, and 3. Block `second` is invalidated and YJIT is OOM While pondering how to fix this, I think I've stumbled on another related edge case: 1. Block `incoming_one` and `incoming_two` both branch to block `second`. Block `incoming_one` has a fallthrough 2. Block `second` immediately exits to the interpreter (so it starts with its exit) 3. When Block `second` is invalidated, the incoming fallthrough branch from `incoming_one` might be rewritten first, which overwrites the start of block `second` with a jump to a new branch stub. 4. YJIT runs of out memory 5. The incoming branch from `incoming_two` is then rewritten, but because we're OOM we can't generate a new stub, so we use `second`'s exit as the branch target. However `second`'s exit was already overwritten with a jump to the branch stub for `incoming_one`, so `incoming_two` will end up jumping to `incoming_one`'s branch stub. Fixes [Bug #21257]
2025-01-14YJIT: Filter & calls from specialized C method codegenTakashi Kokubun
Evident with the crash reported in [Bug #20997], the C replacement codegen functions aren't authored to handle block arguments (nor should they because the extra code from the complexity defeats optimization). Filter sites with VM_CALL_ARGS_BLOCKARG. Co-Authored-By: Alan Wu <alanwu@ruby-lang.org>
2024-06-13Don't call `Warning.warn` unless the category is enabled (#10981)Aaron Patterson
Don't call `Warning.warn` unless the category is enabled The warning category should be enabled if we want to call `Warning.warn`. This commit speeds up the following benchmark: ```ruby eval "def test; " + 1000.times.map { "' '.chomp!" }.join(";") + "; end" def run_benchmark count i = 0 while i < count start = Process.clock_gettime(Process::CLOCK_MONOTONIC) yield ms = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start puts "itr ##{i}: #{(ms * 1000).to_i}ms" i += 1 end end run_benchmark(25) do 250.times do test end end ``` On `master` this runs at about 92ms per iteration. With this patch, it is 7ms per iteration. [Bug #20573]
2024-06-05merge revision(s) f8abd24b1f28998157da1230b231419ef7b81722: [Backport #20522]Takashi Kokubun
Improve YJIT performance warning regression test [Bug #20522]
2024-06-04[3.3 backport] Do not emit shape transition warnings when YJIT is compiling ↵Jean byroot Boussier
(#10911) Do not emit shape transition warnings when YJIT is compiling [Bug #20522] If `Warning.warn` is redefined in Ruby, emitting a warning would invoke Ruby code, which can't safely be done when YJIT is compiling. Co-authored-by: Jean Boussier <jean.boussier@gmail.com> Co-authored-by: Takashi Kokubun <takashikkbn@gmail.com>
2024-06-04YJIT: Fix out of bounds access when splatting empty array (#10905)Alan Wu
This is a backport of 6c8ae44a388e5c03b7db90376af3652007b574e8 with a test tailored to crash the 3.3.x branch (from GH-10904). Previously, we read the last element array even when the array was empty, doing an out-of-bounds access. This sometimes caused a SEGV. [Bug #20496]
2024-05-28merge revision(s) ↵Takashi Kokubun
015b0e2e1d312e2be60551587389c8da5c585e6f,ac1e9e443a0d6a4d4c0801c26d1d8bd33d9eb431: [Backport #20195] YJIT: Fix unused warnings ``` warning: unused import: `condition::Condition` --> src/asm/arm64/arg/mod.rs:13:9 | 13 | pub use condition::Condition; | ^^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(unused_imports)]` on by default warning: unused import: `rb_yjit_fix_mul_fix as rb_fix_mul_fix` --> src/cruby.rs:188:9 | 188 | pub use rb_yjit_fix_mul_fix as rb_fix_mul_fix; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused import: `rb_insn_len as raw_insn_len` --> src/cruby.rs:142:9 | 142 | pub use rb_insn_len as raw_insn_len; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(unused_imports)]` on by default ``` Make asm public so it stops warning about unused public stuff in there. YJIT: Fix ruby2_keywords splat+rest and drop bogus checks YJIT didn't guard for ruby2_keywords hash in case of splat calls that land in methods with a rest parameter, creating incorrect results. The compile-time checks didn't correspond to any actual effects of ruby2_keywords, so it was masking this bug and YJIT was needlessly refusing to compile some code. About 16% of fallback reasons in `lobsters` was due to the ISeq check. We already handle the tagging part with exit_if_supplying_kw_and_has_no_kw() and should now have a dynamic guard for all splat cases. Note for backporting: You also need 7f51959ff1. [Bug #20195]
2024-05-28merge revision(s) 7f51959ff14fbe06bc1afd283d1af17b26161cf4: [Backport #20204]Takashi Kokubun
YJIT: Move guard up for a case of splat+rest Previously, YJIT put the guard for having enough items to extract from splat array at a place where the side exit is invalid, so if the guard fails, YJIT could raise something other than ArgumentError. Move the guard up to a place before any stack manipulation. [Bug #20204]
2024-05-28merge revision(s) bbd249e351af7e4929b518a5de73a832b5617273: [Backport ↵NARUSE, Yui
#20192] (#10249) * merge revision(s) bbd249e351af7e4929b518a5de73a832b5617273: [Backport #20192] YJIT: Properly reject keyword splat with `yield` We don't have support for keyword splat anywhere, but we tried to compile these anyways in case of `invokeblock`. This led to bad things happening such as passing the wrong value and passing a hash into rb_yjit_array_len(), which raised in the middle of compilation. [Bug #20192] * Skip a new test for RJIT
2024-02-05YJIT: Fix exits on splatkw instruction (#9715)Takashi Kokubun
[[Bug #20214]](https://bugs.ruby-lang.org/issues/20214)
2023-12-25Typofix under bootstraptest, spec and yjit directoriesHiroshi SHIBATA
2023-12-21RJIT: Streamline RJIT enablement checkTakashi Kokubun
in bootstrap tests so that `make btest-bruby` skips the right tests.
2023-12-12YJIT: Fix off-by-one in Kernel#send type handling (#9212)Alan Wu
Previously, if the method ID argument happens to be on one below the top of the stack, we didn't overwrite the type of the stack slot, which leaves an incorrect type for the stack slot. The included script tripped asserts both with and without --yjit-verify-ctx.
2023-12-11Skip a YJIT test on RJITAlan Wu
2023-12-11YJIT: Fix missing arity check for splat calls to methods with optionalsAlan Wu
Previously, for splat callsites that land in methods with optional parameters, we didn't reject the case where the caller supplies too many arguments. Accepting those calls previously caused YJIT to construct corrupted control frames, which leads to crashes if the callee uses certain stack walking methods such as Kernel#raise and String#gsub (for setting up the frame-local `$~`). Example crash in a debug build: Assertion Failed: ../vm_core.h:1375:VM_ENV_FLAGS:FIXNUM_P(flags)
2023-12-06YJIT: Avoid register allocation conflict with a higher stack_idx (#9143)Takashi Kokubun
YJIT: Avoid register allocation conflict with a higher stack_idx
2023-12-04YJIT: Mark and update stubs in invalidated blocks (#9104)Alan Wu
Like in the example given in delayed_deallocation(), stubs can be hit even if the block housing it is invalidated. Mark them so we don't work with invalidate ISeqs when hitting these stubs.
2023-11-22YJIT: Avoid a register spill on arm64 (#9014)Takashi Kokubun
2023-11-22YJIT: add an extra btest for shape too complex (#9013)Maxime Chevalier-Boisvert
Following Jean Boussier's comment that some shape bugs were not caught by our tests, I'm trying to improve our test coverage a tiny bit.
2023-11-07YJIT: Inline basic Ruby methods (#8855)Takashi Kokubun
* YJIT: Inline basic Ruby methods * YJIT: Fix "InsnOut operand made it past register allocation" checktype should not generate a useless instruction.
2023-10-13YJIT: Fix argument clobbering in some block_arg+rest_param calls (#8647)Alan Wu
Previously, for block argument callsites with some specific argument count and callee local variable count combinations, YJIT ended up writing over arguments that are supposed to be collected into a rest parameter array unmodified. Detect when clobbering would happen and avoid it. Also, place the block handler after the stack overflow check, since it writes to new stack space. Reported-by: Takashi Kokubun <takashikkbn@gmail.com>
2023-09-29YJIT: Chain-guard opt_mult overflow (#8554)Takashi Kokubun
* YJIT: Chain-guard opt_mult overflow * YJIT: Support regenerating Jo after Mul
2023-09-15YJIT: Fix object movement bug in iseq guard for invokeblockAlan Wu
Since the compile-time iseq used in the guard was not marked and updated during compaction, a runtime value reusing the address could falsely pass the guard. Co-authored-by: Takashi Kokubun <takashikkbn@gmail.com>
2023-09-07Add `String#getbyte` YJIT implementation (#8397)Ian Candy
* Add getbyte JIT implementation Adds an implementation for String#getbyte for YJIT, along with a bootstrap test. This should be helpful for pure Ruby implementations and to avoid unneeded allocations. Co-authored-by: John Hawthorn <jhawthorn@github.com> * Skip the getbyte test for RJIT for now --------- Co-authored-by: John Hawthorn <jhawthorn@github.com> Co-authored-by: Takashi Kokubun <takashikkbn@gmail.com> Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2023-08-28YJIT: Remove Type::CArray and limit use of Type::CStringAlan Wu
These types are essentially claims about what `RBASIC_CLASS(obj)` returns. The field changes with singleton class creation, but we didn't consider so previously and elided guards where we actually needed them. Found running ruby/spec with --yjit-verify-ctx. The assertion interface makes extensive use of singleton classes. Notes: Merged: https://github.com/ruby/ruby/pull/8299
2023-08-18YJIT: Fix return type of Integer#/ with T_FIXNUM inputsAlan Wu
Issue found by running ruby/spec with `--yjit-verify-ctx`. Thanks! Notes: Merged: https://github.com/ruby/ruby/pull/8250
2023-08-18YJIT: implement fast path for integer multiplication in opt_mult (#8204)Maxime Chevalier-Boisvert
* YJIT: implement fast path for integer multiplication in opt_mult * Update yjit/src/codegen.rs Co-authored-by: Alan Wu <XrXr@users.noreply.github.com> * Implement mul with overflow checking on arm64 * Fix missing semicolon * Add arm splitting for lshift, rshift, urshift --------- Co-authored-by: Alan Wu <XrXr@users.noreply.github.com> Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2023-08-17YJIT: Fix String#<< return typeAlan Wu
We previously falsely asserted that String#<< always returns a ::String instance. Issue was discovered on CI with `--yjit-verify-ctx`. https://github.com/ruby/ruby/actions/runs/5893760435/job/15986002531 Notes: Merged: https://github.com/ruby/ruby/pull/8240
2023-08-15YJIT: Optional parameter rework and bugfix (#8220)Alan Wu
* YJIT: Fix splatting empty array with rest param * YJIT: Rework optional parameter handling to fix corner case The old code had a few unintuitive parts. The starting PC of the callee was set in different places; `num_param`, which one would assume to be static for a particular callee seemingly tallied to different amounts depending on the what the caller passed; `opts_filled_with_splat` was greater than zero even when the opts were not filled by items in the splat array. Functionally, the bits that lets the callee know which keyword parameters are unspecified were not passed properly when there are optional parameters and a rest parameter, and then optional parameters are all filled. Make `num_param` non-mut and use parameter information in the callee iseq as-is. Move local variable nil fill and placing of the rest array out of `gen_push_frame()` as they are only ever relevant for iseq calls. Always place the rest array at `lead_num + opt_num` to fix the previously buggy situation. * YJIT: Compile splat calls to iseqs with rest params Test interactions with optional parameters. Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2023-08-11YJIT: Implement GET_BLOCK_HANDLER() for invokesuper (#8206)Takashi Kokubun
Notes: Merged-By: k0kubun <takashikkbn@gmail.com>
2023-08-08YJIT: Compile exception handlers (#8171)Takashi Kokubun
Co-authored-by: Maxime Chevalier-Boisvert <maximechevalierb@gmail.com> Notes: Merged-By: k0kubun <takashikkbn@gmail.com>
2023-08-03YJIT: handle expandarray_rhs_too_small case (#8161)Maxime Chevalier-Boisvert
* YJIT: handle expandarray_rhs_too_small case YJIT: fix csel bug in x86 backend, add test Remove commented out lines Refactor expandarray to use chain guards Propagate Type::Nil when known Update yjit/src/codegen.rs Co-authored-by: Takashi Kokubun <takashikkbn@gmail.com> * Add missing counter, use get_array_ptr() in expandarray * Make change suggested by Kokubun to reuse loop --------- Co-authored-by: Takashi Kokubun <takashikkbn@gmail.com> Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2023-07-26Implement `opt_aref_with` instruction (#8118)ywenc
Implement gen_opt_aref_with Vm opt_aref_with is available Test opt_aref_with Stats for opt_aref_with Co-authored-by: jhawthorn <jhawthorn@github.com> Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2023-07-04YJIT: Break register cycles for C arguments (take 2) (#8018)Takashi Kokubun
* Revert "Revert "YJIT: Break register cycles for C arguments (#7918)"" This reverts commit 78ca085785460de46bfc4851a898d525c1698ef8. * Use shfited_live_ranges for the last-insn check Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2023-07-04YJIT: Fix autosplat miscomp for blocks with optionals (#8006)Alan Wu
* YJIT: Fix autosplat miscomp for blocks with optionals When passing an array as the sole argument to `yield`, and the yieldee takes more than 1 optional parameter, the array is expanded similar to `*array` splat calls. This is called "autosplat" in `setup_parameters_complex()`. Previously, YJIT did not detect this autosplat condition. It passed the array without expanding it, deviating from interpreter behavior. Detect this conditon and refuse to compile it. Fixes: Shopify/yjit#313 * RJIT: Fix autosplat miscomp for blocks with optionals This is mirrors the same issue as YJIT. See previous commit. Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2023-04-25Generalize cfunc large array splat fix to fix many additional cases raising ↵Jeremy Evans
SystemStackError Originally, when 2e7bceb34ea858649e1f975a934ce1894d1f06a6 fixed cfuncs to no longer use the VM stack for large array splats, it was thought to have fully fixed Bug #4040, since the issue was fixed for methods defined in Ruby (iseqs) back in Ruby 2.2. After additional research, I determined that same issue affects almost all types of method calls, not just iseq and cfunc calls. There were two main types of remaining issues, important cases (where large array splat should work) and pedantic cases (where large array splat raised SystemStackError instead of ArgumentError). Important cases: ```ruby define_method(:a){|*a|} a(*1380888.times) def b(*a); end send(:b, *1380888.times) :b.to_proc.call(self, *1380888.times) def d; yield(*1380888.times) end d(&method(:b)) def self.method_missing(*a); end not_a_method(*1380888.times) ``` Pedantic cases: ```ruby def a; end a(*1380888.times) def b(_); end b(*1380888.times) def c(_=nil); end c(*1380888.times) c = Class.new do attr_accessor :a alias b a= end.new c.a(*1380888.times) c.b(*1380888.times) c = Struct.new(:a) do alias b a= end.new c.a(*1380888.times) c.b(*1380888.times) ``` This patch fixes all usage of CALLER_SETUP_ARG with splatting a large number of arguments, and required similar fixes to use a temporary hidden array in three other cases where the VM would use the VM stack for handling a large number of arguments. However, it is possible there may be additional cases where splatting a large number of arguments still causes a SystemStackError. This has a measurable performance impact, as it requires additional checks for a large number of arguments in many additional cases. This change is fairly invasive, as there were many different VM functions that needed to be modified to support this. To avoid too much API change, I modified struct rb_calling_info to add a heap_argv member for storing the array, so I would not have to thread it through many functions. This struct is always stack allocated, which helps ensure sure GC doesn't collect it early. Because of how invasive the changes are, and how rarely large arrays are actually splatted in Ruby code, the existing test/spec suites are not great at testing for correct behavior. To try to find and fix all issues, I tested this in CI with VM_ARGC_STACK_MAX to -1, ensuring that a temporary array is used for all array splat method calls. This was very helpful in finding breaking cases, especially ones involving flagged keyword hashes. Fixes [Bug #4040] Co-authored-by: Jimmy Miller <jimmy.miller@shopify.com> Notes: Merged: https://github.com/ruby/ruby/pull/7522
2023-04-17YJIT: Fixes failure reported by rails for opt+splat+rest (#7727)Jimmy Miller
Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2023-04-14RJIT: Skip a YJIT testAlan Wu
Despite applying a fix to RJIT similar to the YJIT fix, this test still crashes RJIT. Notes: Merged: https://github.com/ruby/ruby/pull/7718
2023-04-14YJIT: Fix false object collection when setting ivarAlan Wu
Previously, setinstancevariable could generate code that calls `rb_ensure_iv_list_size()` without first updating `cfp->sp`. This means in the event that a GC start from within said routine the top few objects would not be marked, causing them to be falsly collected. Call `jit_prepare_routine_call()` first. [Bug #19601] Notes: Merged: https://github.com/ruby/ruby/pull/7718
2023-04-13YJIT: Add support for rest with option and splat args (#7698)Jimmy Miller
Notes: Merged-By: k0kubun <takashikkbn@gmail.com>
2023-04-12YJIT: Fix missing argc check in known cfuncsJohn Hawthorn
Previously we were missing a compile-time check that the known cfuncs receive the correct number of arguments. We noticied this because in particular when using ARGS_SPLAT, which also wasn't checked, YJIT would crash on code which was otherwise correct (didn't raise exceptions in the VM). This still supports vararg (argc == -1) cfuncs. I added an additional assertion that when we use the specialized codegen for one of these known functions that the argc are popped off the stack correctly, which should help ensure they're implemented correctly (previously the crash was usually observed on a future `leave` insn). [Bug #19595] Notes: Merged: https://github.com/ruby/ruby/pull/7697
2023-04-10YJIT: Avoid using a register for unspecified_bits (#7685)Takashi Kokubun
Fix [Bug #19586] Notes: Merged-By: k0kubun <takashikkbn@gmail.com>
2023-04-05YJIT: Add codegen for Integer methods (#7665)Takashi Kokubun
* YJIT: Add codegen for Integer methods * YJIT: Update dependencies * YJIT: Fix Integer#[] for argc=2 Notes: Merged-By: k0kubun <takashikkbn@gmail.com>
2023-03-30YJIT: Test more kw and rest cases and change exit nameJimmy Miller
Notes: Merged: https://github.com/ruby/ruby/pull/7628
2023-03-29YJIT: Rest and keyword (non-supplying) (#7608)Jimmy Miller
* YJIT: Rest and keyword (non-supplying) * Update yjit/src/codegen.rs --------- Co-authored-by: Maxime Chevalier-Boisvert <maximechevalierb@gmail.com> Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2023-03-24YJIT: Rest and block_arg support (#7584)Jimmy Miller
Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2023-03-23YJIT: Use starting context for status === CantCompile (#7583)Jimmy Miller
Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2023-03-23Use shape information in YJIT's definedivar implementation (#7579)Ole Friis Østergaard
* Use shape information in YJIT's definedivar implementation * Handle complex shape for definedivar Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2023-03-21YJIT: Fix large ISeq rejection (#7576)Alan Wu
We crashed in some edge cases due to the recent change to not compile encoded iseqs that are larger than `u16::MAX`. - Match the C signature of rb_yjit_constant_ic_update() and clamp down to `IseqIdx` size - Return failure instead of panicking with `unwrap()` in codegen when the iseq is too large Co-authored-by: Maxime Chevalier-Boisvert <maxime.chevalierboisvert@shopify.com> Co-authored-by: Noah Gibbs <noah.gibbs@shopify.com> Notes: Merged-By: maximecb <maximecb@ruby-lang.org>