summaryrefslogtreecommitdiff
path: root/bootstraptest/test_yjit.rb
Commit message (Collapse)AuthorAgeFilesLines
* YJIT: Fix cfunc splatJimmy Miller2023-03-021-1/+12
| | | Follow-up for cb8a040b7906c09d9d3ac3d3fe853f633005024f.
* YJIT: Properly deal with cfunc splat when no args needed (#7413)Jimmy Miller2023-03-011-0/+10
| | | | | | | | | | Related to: https://github.com/ruby/ruby/pull/7377 Previously it was believed that there was a problem with a combination of cfuncs + splat + send, but it turns out the same issue happened without send. For example `Integer.sqrt(1, *[])`. The issue was happened not because of send, but because of setting the wrong argc when we don't need to splat any args.
* YJIT: Reject __send__ with splat to cfunc for nowAlan Wu2023-02-271-0/+5
| | | | | | | | | | `make test-spec` revealed this issue after applying an unrelated bug fix. A crashing case is included, though I suspect there are other scenarios where it misbehaves. Don't compile for now. Note that this is *not* an issue on the 3.2.x series; it has `send_args_splat_non_iseq` which already rejects all splats to cfuncs, including sends with splats.
* YJIT: `Kernel#{is_a?,instance_of?}` fast paths (GH-7297)Jimmy Miller2023-02-151-0/+27
| | | | Co-authored-by: Maxime Chevalier-Boisvert <maxime.chevalierboisvert@shopify.com> Co-authored-by: Alan Wu <XrXr@users.noreply.github.com>
* YJIT: Check correct BOP on gen_fixnum_cmp (#7303)Takashi Kokubun2023-02-141-0/+39
|
* YJIT: Support invokesuper in a block (#7264)Maple Ong2023-02-091-0/+32
| | | | | | | Support invokesuper in a block on YJIT invokesuper previously side exited when it is in a block. To make sure we're compiling the correct method in super, we now use the local environment pointer (LEP) to get the method, which will work in a block. Co-authored-by: John Hawthorn <john@hawthorn.email>
* Implement splat for cfuncs. Split exit exit cases to better capture where we ↵Jimmy Miller2023-01-191-0/+25
| | | | | | | | | | | | | | are exiting (#6929) YJIT: Implement splat for cfuncs. Split exit cases This also implements a new check for ruby2keywords as the last argument of a splat. This does mean that we generate more code, but in actual benchmarks where we gained speed from this (binarytrees) I don't see any significant slow down. I did have to struggle here with the register allocator to find code that didn't allocate too many registers. It's a bit hard when everything is implicit. But I think I got to the minimal amount of copying and stuff given our current allocation strategy.
* MJIT: Cancel all on disastrous situations (#7019)Takashi Kokubun2022-12-241-3/+3
| | | | | | | | | | I noticed this while running test_yjit with --mjit-call-threshold=1, which redefines `Integer#<`. When Ruby is monkey-patched, MJIT itself could be broken. Similarly, Ruby scripts could break MJIT in many different ways. I prepared the same set of hooks as YJIT so that we could possibly override it and disable it on those moments. Every constant under RubyVM::MJIT is private and thus it's an unsupported behavior though.
* YJIT: Make case-when optimization respect === redefinition (#6846)Alan Wu2022-12-021-0/+20
| | | | | | | | | | | | | | | | | | * YJIT: Make case-when optimization respect === redefinition Even when a fixnum key is in the dispatch hash, if there is a case such that its basic operations for === is redefined, we need to fall back to checking each case like the interpreter. Semantically we're always checking each case by calling === in order, it's just that this is not observable when basic operations are intact. When all the keys are fixnums, though, we can do the optimization we're doing right now. Check for this condition. * Update yjit/src/cruby_bindings.inc.rs Co-authored-by: Takashi Kokubun <takashikkbn@gmail.com> Co-authored-by: Takashi Kokubun <takashikkbn@gmail.com>
* YJIT: Deallocate `struct Block` to plug memory leaksAlan Wu2022-11-301-0/+13
| | | | | | | | | | | | | | | Previously we essentially never freed block even after invalidation. Their reference count never reached zero for a couple of reasons: 1. `Branch::block` formed a cycle with the block holding the branch 2. Strong count on a branch that has ever contained a stub never reached 0 because we increment the `.clone()` call for `BranchRef::into_raw()` didn't have a matching decrement. It's not safe to immediately deallocate blocks during invalidation since `branch_stub_hit()` can end up running with a branch pointer from an invalidated branch. To plug the leaks, we wait until code GC or global invalidation and deallocate the blocks for iseqs that are definitely not running.
* Fix bug involving .send and overwritten methods. (#6752)Jimmy Miller2022-11-171-0/+23
| | | | | | | | | @casperisfine reporting a bug in this gist https://gist.github.com/casperisfine/d59e297fba38eb3905a3d7152b9e9350 After investigating I found it was caused by a combination of send and a c_func that we have overwritten in the JIT. For send calls, we need to do some stack manipulation before making the call. Because of the way exits works, we need to do that stack manipulation at the last possible moment. In this case, we weren't doing that stack manipulation at all. Unfortunately, with how the code is structured there isn't a great place to do that stack manipulation for our overridden C funcs. Each overridden C func can return a boolean stating that it shouldn't be used. We would need to do the stack manipulation after all of those checks are done. We could pass a lambda(?) or separate out the logic for "can I run this override" from "now generate the code for it". Since we are coming up on a release, I went with the path of least resistence and just decided to not use these overrides if we are in a send call. We definitely should revist this in the future.
* YJIT: Fix invalidation for c_call and c_return (#6719)Alan Wu2022-11-131-0/+20
| | | | | | | | | | | Follow-up for 2b8191bdad7545b71f270d2b25a34cd2b3afa02f. Since that commit, we stopped doing code invalidation the second time the call and return events are enabled. We need to do it every time these events are enabled because we might have generated code while these events are disabled. Also rename locals and edit comments to make it more clear that the iseq rewrite code path only happens the first time a particular iseq trace event is enabled.
* YJIT: Support nil and blockparamproxy as blockarg in send (#6492)Matthew Draper2022-10-261-0/+43
| | | | | Co-authored-by: John Hawthorn <john@hawthorn.email> Co-authored-by: John Hawthorn <john@hawthorn.email>
* YJIT: add support for calling bmethods (#6489)Alan Wu2022-10-041-0/+28
| | | | | | | | | | | | | | | | | | | | | | | | * YJIT: fix a parameter name * YJIT: add support for calling bmethods This commit adds support for the VM_METHOD_TYPE_BMETHOD method type in YJIT. You can get these type of methods from facilities like Kernel#define_singleton_method and Module#define_method. Even though the body of these methods are blocks, the parameter setup for them is exactly the same as VM_METHOD_TYPE_ISEQ, so we can reuse the same logic in gen_send_iseq(). You can see this from how vm_call_bmethod() eventually calls setup_parameters_complex() with arg_setup_method. Bmethods do need their frame environment to be setup differently. We handle this by allowing callers of gen_send_iseq() to control the iseq, the frame flag, and the prev_ep. The `prev_ep` goes into the same location as the block handler would go into in an iseq method frame. Co-authored-by: John Hawthorn <john@hawthorn.email> Co-authored-by: John Hawthorn <john@hawthorn.email>
* YJIT: Implement specialized respond_to? (#6363)John Hawthorn2022-09-141-0/+54
| | | | | | | | | | | * Add rb_callable_method_entry_or_negative * YJIT: Implement specialized respond_to? This implements a specialized respond_to? in YJIT. * Update yjit/src/codegen.rs Co-authored-by: Maxime Chevalier-Boisvert <maximechevalierb@gmail.com>
* YJIT: Implement concatarray in yjit (https://github.com/Shopify/ruby/pull/405)Maple Ong2022-08-291-0/+10
| | | | | | | | | | | | | | | | * Create code generation func * Make rb_vm_concat_array available to use in Rust * Map opcode to code gen func * Implement code gen for concatarray * Add test for concatarray * Use new asm backend * Add comment to C func wrapper
* Fix code invalidation while OOM and OOM simulation ↵Alan Wu2022-08-291-0/+9
| | | | | | | | | | | | | | | | | | | | (https://github.com/Shopify/ruby/pull/395) `YJIT.simulate_oom!` used to leave one byte of space in the code block, so our test didn't expose a problem with asserting that the write position is in bounds in `CodeBlock::set_pos`. We do the following when patching code: 1. save current write position 2. seek to middle of the code block and patch 3. restore old write position The bounds check fails on (3) when the code block is already filled up. Leaving one byte of space also meant that when we write that byte, we need to fill the entire code region with trapping instruction in `VirtualMem`, which made the OOM tests unnecessarily slow. Remove the incorrect bounds check and stop leaving space in the code block when simulating OOM.
* Port getblockparamproxy and getblockparam ↵Takashi Kokubun2022-08-291-0/+16
| | | | (https://github.com/Shopify/ruby/pull/394)
* Port the remaining method types in opt_send_without_block ↵Takashi Kokubun2022-08-291-0/+22
| | | | (https://github.com/Shopify/ruby/pull/390)
* Port gen_send_iseq to the new backend IR ↵Takashi Kokubun2022-08-291-0/+33
| | | | | | | | | | | (https://github.com/Shopify/ruby/pull/381) * Port gen_send_iseq to the new backend IR * Replace occurrences of 8 by SIZEOF_VALUE Co-authored-by: Maxime Chevalier-Boisvert <maximechevalierb@gmail.com> Co-authored-by: Maxime Chevalier-Boisvert <maxime.chevalierboisvert@shopify.com>
* Port invokebuiltin* insns to the new backend IR ↵Takashi Kokubun2022-08-291-0/+22
| | | | | | | | (https://github.com/Shopify/ruby/pull/375) * Port invokebuiltin* insns to the new backend IR * Fix the C_ARG_OPNDS check boundary
* Port objtostring to the new backend (https://github.com/Shopify/ruby/pull/369)Takashi Kokubun2022-08-291-2/+2
|
* Port gen_send_cfunc to the new backend ↵Takashi Kokubun2022-08-291-0/+32
| | | | | | | | | | | | | | | | | | | | (https://github.com/Shopify/ruby/pull/357) * Port gen_send_cfunc to the new backend * Remove an obsoleted test * Add more cfunc tests * Use csel_e instead and more into() Co-authored-by: Maxime Chevalier-Boisvert <maximechevalierb@gmail.com> * Add a missing lea for build_kwargs * Split cfunc test cases Co-authored-by: Maxime Chevalier-Boisvert <maximechevalierb@gmail.com>
* Port gen_concatstring to new backend IR ↵Zack Deveau2022-08-291-0/+8
| | | | | | | | | | (https://github.com/Shopify/ruby/pull/350) * Port gen_concatstring to new backend IR * Update yjit/src/codegen.rs Co-authored-by: Maxime Chevalier-Boisvert <maximechevalierb@gmail.com>
* Port anytostring, intern, and toregexp ↵Takashi Kokubun2022-08-291-0/+16
| | | | | | | | | | (https://github.com/Shopify/ruby/pull/348) * Port anytostring, intern, and toregexp * Port getspecial to the new backend (#349) PR: https://github.com/Shopify/ruby/pull/349
* Port only ATTRSET of opt_send_without_block ↵Takashi Kokubun2022-08-291-0/+13
| | | | (https://github.com/Shopify/ruby/pull/351)
* Port gen_checktype to the new IR assembler backend ↵Zack Deveau2022-08-291-0/+8
| | | | (https://github.com/Shopify/ruby/pull/343)
* YJIT: Teach getblockparamproxy to handle the no-block case without exiting ↵Matthew Draper2022-07-281-0/+13
| | | | | | | | | (#6191) Teach getblockparamproxy to handle the no-block case without exiting Co-authored-by: John Hawthorn <john@hawthorn.email> Co-authored-by: John Hawthorn <john@hawthorn.email>
* Replace use of double_heap in tests with expand_heapMatt Valentine-House2022-07-111-1/+1
|
* Make sure string-operation assertions happen inside a method to be sure YJIT ↵Noah Gibbs (and/or Benchmark CI)2022-06-271-51/+92
| | | | will JIT them.
* YJIT: Add regression test for local type trackingAlan Wu2022-06-231-0/+20
| | | | | | | | | | | The test in [1] was removed because it stopped working when we limited the power of Kernel#binding in [2]. However, the underlying issue could still be reproduced using blocks. Add back a regression test. I tested the test by commenting out the fix from [1]. [1]: 54c91042ed61a869d4a66fc089b21f56d165265f [2]: 343ea9967e4a6b279eed6bd8e81ad0bdc747f254
* Add tests for a variety of string-subclass operations (#5999)Noah Gibbs2022-06-101-2/+77
| | | | This way YJIT has to match CRuby for each of them. Remove unused string_p() Rust function
* Add special-case code for the String unary plus operator (#5982)Noah Gibbs2022-06-071-0/+27
|
* Revert incorrect string-guard optimisation. (#5969)Noah Gibbs2022-06-011-1/+31
| | | | Also add jhawthorn's test to for this bug. Fix String#to_s invalidation test
* Special-case jit_guard_known_class for strings. This can remove (#5920)Noah Gibbs2022-05-201-0/+10
| | | | runtime guard-checks for String#to_s, making some blocks too short to invalidate later. Add NOPs in those cases to reserve space.
* Rust YJITAlan Wu2022-04-271-1/+45
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | In December 2021, we opened an [issue] to solicit feedback regarding the porting of the YJIT codebase from C99 to Rust. There were some reservations, but this project was given the go ahead by Ruby core developers and Matz. Since then, we have successfully completed the port of YJIT to Rust. The new Rust version of YJIT has reached parity with the C version, in that it passes all the CRuby tests, is able to run all of the YJIT benchmarks, and performs similarly to the C version (because it works the same way and largely generates the same machine code). We've even incorporated some design improvements, such as a more fine-grained constant invalidation mechanism which we expect will make a big difference in Ruby on Rails applications. Because we want to be careful, YJIT is guarded behind a configure option: ```shell ./configure --enable-yjit # Build YJIT in release mode ./configure --enable-yjit=dev # Build YJIT in dev/debug mode ``` By default, YJIT does not get compiled and cargo/rustc is not required. If YJIT is built in dev mode, then `cargo` is used to fetch development dependencies, but when building in release, `cargo` is not required, only `rustc`. At the moment YJIT requires Rust 1.60.0 or newer. The YJIT command-line options remain mostly unchanged, and more details about the build process are documented in `doc/yjit/yjit.md`. The CI tests have been updated and do not take any more resources than before. The development history of the Rust port is available at the following commit for interested parties: https://github.com/Shopify/ruby/commit/1fd9573d8b4b65219f1c2407f30a0a60e537f8be Our hope is that Rust YJIT will be compiled and included as a part of system packages and compiled binaries of the Ruby 3.2 release. We do not anticipate any major problems as Rust is well supported on every platform which YJIT supports, but to make sure that this process works smoothly, we would like to reach out to those who take care of building systems packages before the 3.2 release is shipped and resolve any issues that may come up. [issue]: https://bugs.ruby-lang.org/issues/18481 Co-authored-by: Maxime Chevalier-Boisvert <maximechevalierb@gmail.com> Co-authored-by: Noah Gibbs <the.codefolio.guy@gmail.com> Co-authored-by: Kevin Newton <kddnewton@gmail.com>
* Raise RuntimeError if Kernel#binding is called from a non-Ruby frameJeremy Evans2022-04-061-31/+0
| | | | | | | | | Check whether the current or previous frame is a Ruby frame in call_trace_func and rb_tracearg_binding before attempting to create a binding for the frame. Fixes [Bug #18487] Co-authored-by: Alan Wu <XrXr@users.noreply.github.com>
* Revert "Raise RuntimeError if Kernel#binding is called from a non-Ruby frame"Jeremy Evans2022-04-011-0/+31
| | | | | | This reverts commit 343ea9967e4a6b279eed6bd8e81ad0bdc747f254. This causes an assertion failure with -DRUBY_DEBUG=1 -DRGENGC_CHECK_MODE=2
* Raise RuntimeError if Kernel#binding is called from a non-Ruby frameJeremy Evans2022-03-241-31/+0
| | | | | | | | | Check whether the current or previous frame is a Ruby frame in call_trace_func before attempting to create a binding for the frame. Fixes [Bug #18487] Co-authored-by: Alan Wu <XrXr@users.noreply.github.com>
* YJIT: Support kwargs for cfuncJohn Hawthorn2022-01-101-0/+51
| | | | | | | This adds support for passing keyword arguments to cfuncs. This is done by calling a helper method to create the hash from the top N values on the stack (determined by the callinfo) and then moving that value onto the stack.
* YJIT: Add support for ruby array cfuncs (argc=-2)John Hawthorn2022-01-081-0/+20
| | | | | This adds support for cfuncs which take variable arguments using a Ruby array. This is specified with the method entry's argc == -2.
* YJIT: Discard local var type info on routine callAlan Wu2022-01-071-0/+31
| | | | | | | | | | | | | | | Routines that are called from YJIT's output code can call methods, and calling methods mean they can capture and change the environment of the calling frame. Discard type info whenever we perform routine calls. This is more conservative than strictly necessary as some routines need to perform GC allocation but can never call methods and so should never be able to change local variables. However, manually analyzing C functions for whether they have code paths that call methods is error prone and can go out of date as changes land in the codebase. Closes: shopify/yjit#300
* YJIT: Fix SP index with optarg and unordered kwargJohn Hawthorn2021-12-311-0/+16
| | | | | | | | Previously when we were calling a method with an optional argument and multiple keywords arguments which weren't in the order the receiver expected we would use the wrong SP index to rearrange them. Fixes Bug #18453
* YJIT: Fix check for required kwargsJohn Hawthorn2021-12-171-0/+8
| | | | | | Previously, YJIT would not check that all the required keywords were specified in the case that there were optional arguments specified. In this case YJIT would incorrectly call the method with invalid arguments.
* YJIT: Allow iseq with both opt and kwargsJohn Hawthorn2021-12-171-0/+26
| | | | | | | | | | | | Previously we mirrored the fast paths the interpreter had for having only one of kwargs or optional args. This commit aims to combine the cases and reduce complexity. Though this allows calling iseqs which have have both optional and keyword arguments, it requires that all optional arguments are specified when there are keyword arguments, since unspecified optional arguments appear before the kwargs. Support for this can be added a in a future PR.
* YJIT: Fix unexpected truncation when outputing VALUEAlan Wu2021-12-141-0/+15
| | | | | | | | | | | | | Previously, YJIT incorrectly discarded the upper 32 bits of the object pointer when writing out VALUEs to setup default keyword arguments. In addition to incorrectly truncating, the output pointers were not properly tracked for handling GC compaction moving the referenced objects. YJIT previously attempted to encode a mov instruction with a memory destination and a 64 bit immediate when there is no such encoding possible in the ISA. Add an assert to mitigate not being able to catch this at build time.
* YJIT: Fix leak in compilation loopAlan Wu2021-12-081-0/+12
| | | | | Previously, when there are too many blocks in a batch, the last block in the batch is not tracked in the array of batches and not freed.
* YJIT: Remove guard_self_is_heap()Alan Wu2021-12-071-0/+11
| | | | | | | | It's superseded by functionality added to jit_guard_known_klass(). In weird situations such as the ones in the included test, guard_self_is_heap() triggered assertions. Co-authored-by: Jemma Issroff <jemmaissroff@gmail.com>
* YJIT: Fix incomplete invalidation from opt_setinlinecacheAlan Wu2021-12-061-0/+85
| | | | | | | | | | | | | | | | As part of YJIT's strategy for promoting Ruby constant expressions into constants in the output native code, the interpreter calls rb_yjit_constant_ic_update() from opt_setinlinecache. The block invalidation loop indirectly calls rb_darray_remove_unordered(), which does a shuffle remove. Because of this, looping with an incrementing counter like done previously can miss some elements in the array. Repeatedly invalidate the first element instead. The bug this commit resolves does not seem to cause crashes or divergent behaviors. Co-authored-by: Jemma Issroff <jemmaissroff@gmail.com>
* YJIT: Enable out of memory testsAlan Wu2021-12-041-3/+3
| | | | | | | | | | | | As of [1] and [2], YJIT has enough support for out of memory conditions to pass these two basic tests. OOM code paths are prone to bugs since they are rarely exercised in common workloads. We might want to add CI runs that stress test these code paths. Maybe outside of GitHub Actions for capacity reasons. [1]: f41b4d44f95978dfa97af04af00055dc3fbf7978 [2]: b5b6ab4194f16e96ee5004288cc469ac1bca41a3