summaryrefslogtreecommitdiff
path: root/yjit/src/codegen.rs
AgeCommit message (Collapse)Author
2023-03-17YJIT: Rest and block_arg support (#7557)Jimmy Miller
* YJIT: Rest and block_arg support * Update bootstraptest/test_yjit.rb --------- Co-authored-by: Maxime Chevalier-Boisvert <maximechevalierb@gmail.com> Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2023-03-17YJIT: Support entry for multiple PCs per ISEQ (GH-7535)Takashi Kokubun
Notes: Merged: https://github.com/ruby/ruby/pull/7535 Merged-By: k0kubun <takashikkbn@gmail.com>
2023-03-17YJIT: Use raw pointers and shared references over `Rc<RefCell<_>>`Alan Wu
`Rc` and `RefCell` both incur runtime space costs. In addition, `RefCell` has given us some headaches with the non obvious borrow panics it likes to throw out. The latest one started with 7fd53eeb46db261bbc20025cdab70096245a5cbe and is yet to be resolved. Since we already rely on the GC to properly reclaim memory for `Block` and `Branch`, we might as well stop paying the overhead of `Rc` and `RefCell`. The `RefCell` panics go away with this change, too. On 25 iterations of `railsbench` with a stats build I got `yjit_alloc_size: 8,386,129 => 7,348,637`, with the new memory size 87.6% of the status quo. This makes the metadata and machine code size roughly line up one-to-one. The general idea here is to use `&` shared references with [interior mutability][1] with `Cell`, which doesn't take any extra space. The `noalias` requirement that `&mut` imposes is way too hard to meet and verify. Imagine replacing places where we would've gotten `BorrowError` from `RefCell` with Rust/LLVM miscompiling us due to aliasing violations. With shared references, we don't have to think about subtle cases like the GC _sometimes_ calling the mark callback while codegen has an aliasing reference in a stack frame below. We mostly only need to worry about liveness, with which the GC already helps. There is now a clean split between blocks and branches that are not yet fully constructed and ones that are "in-service", so to speak. Working with `PendingBranch` and `JITState` don't really involve `unsafe` stuff. This change allows `Branch` and `Block` to not have as many optional fields as many of them are only optional during compilation. Fields that change post-compilation are wrapped in `Cell` to facilitate mutation through shared references. I do some `unsafe` dances here. I've included just a couple tests to run with Miri (`cargo +nightly miri test miri`). We can add more Miri tests if desired. [1]: https://doc.rust-lang.org/std/cell/struct.UnsafeCell.html Notes: Merged: https://github.com/ruby/ruby/pull/7443
2023-03-16YJIT: Remove exit for rest and send combo (#7546)Jimmy Miller
Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2023-03-16YJIT: add stats to keep track of when branch direction is known (#7544)Maxime Chevalier-Boisvert
This measures the impact of changes made by @jhawthorn last year. Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2023-03-15YJIT: use u16 for insn_idx instead of u32 (#7534)Maxime Chevalier-Boisvert
Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2023-03-15Make EC required on JIT state (#7520)Aaron Patterson
* Make EC required on JIT state Lets make EC required on the JITState object so we don't need to `unwrap` it. * Minor nitpicks --------- Co-authored-by: Alan Wu <XrXr@users.noreply.github.com> Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2023-03-14YJIT: Introduce no_gc attribute (#7511)Takashi Kokubun
Notes: Merged-By: k0kubun <takashikkbn@gmail.com>
2023-03-14YJIT: Implement throw instruction (#7491)Takashi Kokubun
* Break up jit_exec from vm_sendish * YJIT: Implement throw instruction * YJIT: Explain what rb_vm_throw does [ci skip] Notes: Merged-By: k0kubun <takashikkbn@gmail.com>
2023-03-13YJIT: Handle rest+splat where non-splat < required (#7499)Jimmy Miller
Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2023-03-10YJIT: Bump SEND_MAX_DEPTH to 20 (#7469)Takashi Kokubun
* YJIT: Bump SEND_MAX_DEPTH to 20 * Fix a test failure Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2023-03-09YJIT: upgrade type in `guard_object_is_string` (#7489)Maxime Chevalier-Boisvert
* YJIT: upgrade type in guard_object_is_string Also make logic more in line with other guard_xxx methods * Update yjit/src/core.rs * Revert changes to Type::upgrade() Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2023-03-09Revert an unneeded diff in 262254dc7dTakashi Kokubun
2023-03-10rename `defined_ivar` to `definedivar`Koichi Sasada
because non-opt instructions should contain `_` char. Notes: Merged: https://github.com/ruby/ruby/pull/7485
2023-03-08Add defined_ivar as YJIT instruction as wellOle Friis Østergaard
This works much like the existing `defined` implementation, but calls out to rb_ivar_defined instead of the more general rb_vm_defined. Other difference to the existing `defined` implementation is that this new instruction has to take the same operands as the CRuby `defined_ivar` instruction. Notes: Merged: https://github.com/ruby/ruby/pull/7433
2023-03-07YJIT: Handle splat+rest for args pass greater than required (#7468)Jimmy Miller
For example: ```ruby def my_func(x, y, *rest) p [x, y, rest] end my_func(1, 2, 3, *[4, 5]) ``` Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2023-03-07YJIT: Protect strings from GC on String#<< (#7466)Takashi Kokubun
Fix https://github.com/Shopify/yjit/issues/310 [Bug #19483] Co-authored-by: Maxime Chevalier-Boisvert <maxime.chevalierboisvert@shopify.com> Co-authored-by: Jimmy Miller <jimmy.miller@shopify.com> Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2023-03-07YJIT: Handle special case of splat and rest lining up (#7422)Jimmy Miller
If you have a method that takes rest arguments and a splat call that happens to line up perfectly with that rest, you can just dupe the array rather than move anything around. We still have to dupe, because people could have a custom to_a method or something like that which means it is hard to guarantee we have exclusive access to that array. Example: ```ruby def foo(a, b, *rest) end foo(1, 2, *[3, 4]) ``` Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2023-03-07YJIT: Bump SEND_MAX_DEPTH to 10 (#7452)Takashi Kokubun
Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2023-03-03YJIT: fix CI issue reported by Koichi caused by small stack patch (#7442)Maxime Chevalier-Boisvert
Includes small reproduction produced by Kokubun. http://ci.rvm.jp/results/trunk-yjit@ruby-sp2-docker Notes: Merged-By: k0kubun <takashikkbn@gmail.com>
2023-03-02YJIT: shrink stack_size/sp_offet to u8/i8 (#7426)Maxime Chevalier-Boisvert
Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2023-03-02YJIT: Delete stale `frozen_bytes` related code (#7423)Alan Wu
The code and comments in there have been disabled by comments for a long time. The issues that the counter used to solve are now solved more comprehensively by "runningness" [tracking][1] introduced by Code GC and [delayed deallocation][2]. Having a single counter doesn't fit our current model where code pages that could be touched or not are interleaved, anyway. Just delete the code. [1]: e7c71c6c9271b0c29f210769159090e17128e740 [2]: a0b0365e905e1ac51998ace7e6fc723406a2f157 Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2023-03-02YJIT: Fix cfunc splatJimmy Miller
Follow-up for cb8a040b7906c09d9d3ac3d3fe853f633005024f. Notes: Merged: https://github.com/ruby/ruby/pull/7418 Merged-By: XrXr
2023-03-01YJIT: Properly deal with cfunc splat when no args needed (#7413)Jimmy Miller
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. Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2023-03-01YJIT: Use a boxed slice for outgoing branches and cme dependencies (#7409)Takashi Kokubun
YJIT: Use a boxed slice for outgoing branches and cme dependencies Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2023-02-28YJIT: Compress BranchGenFn and BranchShape (#7401)Takashi Kokubun
* YJIT: Compress BranchGenFn and BranchShape * YJIT: Derive Debug for Branch * YJIT: Capitalize BranchGenFn names Co-authored-by: Maxime Chevalier-Boisvert <maxime.chevalierboisvert@shopify.com> Co-authored-by: Alan Wu <alansi.xingwu@shopify.com> Notes: Merged-By: k0kubun <takashikkbn@gmail.com>
2023-02-28YJIT: Use a boxed slice for gc_obj_offsets (#7397)Takashi Kokubun
* YJIT: Use a boxed slice for gc_obj_offsets * YJIT: Stop using Option * YJIT: s/add_counter/incr_counter_by/ Co-authored-by: Maxime Chevalier-Boisvert <maxime.chevalierboisvert@shopify.com> Notes: Merged-By: k0kubun <takashikkbn@gmail.com>
2023-02-27YJIT: Detect and reject `send(:alias_for_send, :foo)`Alan Wu
Previously, YJIT failed to put the stack into the correct shape when `BasicObject#send` calls an alias method for the send method itself. This can manifest as strange `NoMethodError`s in the final non-send receiver, as [seen][1] with the kt-paperclip gem. I also found a case where it makes YJIT fail the stack size assertion while compiling `leave`. YJIT's `BasicObject#__send__` implementation already rejects sends to `send`, but didn't detect sends to aliases of `send`. Adjust the detection and reject these cases. Fixes [Bug #19464] [1]: https://github.com/Shopify/yjit/issues/306 Notes: Merged: https://github.com/ruby/ruby/pull/7377
2023-02-27YJIT: Reject __send__ with splat to cfunc for nowAlan Wu
`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. Notes: Merged: https://github.com/ruby/ruby/pull/7377
2023-02-24YJIT: Generate Block::entry_exit with block entry PCAlan Wu
Previously, when Block::entry_exit is requested from any instruction that is not the first one in the block, we generated the exit with an incorrect PC. We should always be using the PC for the entry of the block for Block::entry_exit. It was a simple typo. The bug was [introduced][1] while we were refactoring to use the current backend. Later, we had a chance to spot this issue while [preparing][2] to enable unused variable warnings, but didn't spot the issue. Fixes [Bug #19463] [1]: 27fcab995e6dde19deb91dc6e291bdb72100af68 [2]: 31461c7e0eab4963ccc8649ea8ebf27979132c0c Notes: Merged: https://github.com/ruby/ruby/pull/7374 Merged-By: XrXr
2023-02-24YJIT: Use enum for expressing type diff (#7370)Takashi Kokubun
Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2023-02-24YJIT: Compress TempMapping (#7368)Takashi Kokubun
Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2023-02-23YJIT: Trivial fixes in codegen.rsTakashi Kokubun
2023-02-23YJIT: Skip type checks on splat args and expandarray if possible (#7363)Takashi Kokubun
YJIT: Skip type checks on splat args and expandarray if possible Notes: Merged-By: k0kubun <takashikkbn@gmail.com>
2023-02-22YJIT: Introduce Opnd::Stack (#7352)Takashi Kokubun
Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2023-02-21Call rb_ivar_set instead of exiting for many ivarseileencodes
Previously, when we have a lot of ivars defined, we would exit via `jit_chain_guard` for megamorphic ivars. Now if we have more than the max depth of ivars we can call `rb_ivar_set` instead of exiting. Using the following script: ```ruby class A def initialize @a = 1 end def a @a end end N = 30 N.times do |i| eval <<-eorb class A#{i} < A def initialize @a#{i} = 1 super end end eorb end klasses = N.times.map { Object.const_get(:"A#{_1}") } 1000.times do klasses.each do |k| k.new.a end end ``` Exits before this change show exits for `setinstancevariable`: ``` ***YJIT: Printing YJIT statistics on exit*** method call exit reasons: klass_megamorphic: 24,975 (100.0%) invokeblock exit reasons: (all relevant counters are zero) invokesuper exit reasons: (all relevant counters are zero) leave exit reasons: interp_return: 26,948 (100.0%) se_interrupt: 1 ( 0.0%) getblockparamproxy exit reasons: (all relevant counters are zero) getinstancevariable exit reasons: megamorphic: 13,986 (100.0%) setinstancevariable exit reasons: megamorphic: 19,980 (100.0%) opt_aref exit reasons: (all relevant counters are zero) expandarray exit reasons: (all relevant counters are zero) opt_getinlinecache exit reasons: (all relevant counters are zero) invalidation reasons: (all relevant counters are zero) num_send: 155,823 num_send_known_class: 0 ( 0.0%) num_send_polymorphic: 119,880 (76.9%) bindings_allocations: 0 bindings_set: 0 compiled_iseq_count: 36 compiled_block_count: 158 compiled_branch_count: 240 block_next_count: 10 defer_count: 70 freed_iseq_count: 0 invalidation_count: 0 constant_state_bumps: 0 inline_code_size: 29,216 outlined_code_size: 27,948 freed_code_size: 0 code_region_size: 65,536 live_context_size: 8,322 live_context_count: 219 live_page_count: 4 freed_page_count: 0 code_gc_count: 0 num_gc_obj_refs: 130 object_shape_count: 295 side_exit_count: 58,942 total_exit_count: 85,890 yjit_insns_count: 1,023,581 avg_len_in_yjit: 11.2 Top-4 most frequent exit ops (100.0% of exits): opt_send_without_block: 24,975 (42.4%) setinstancevariable: 19,980 (33.9%) getinstancevariable: 13,986 (23.7%) leave: 1 ( 0.0%) ``` Exits after this change show we have no exits for `setinstancevariable`. ``` ***YJIT: Printing YJIT statistics on exit*** method call exit reasons: klass_megamorphic: 24,975 (100.0%) invokeblock exit reasons: (all relevant counters are zero) invokesuper exit reasons: (all relevant counters are zero) leave exit reasons: interp_return: 60,912 (100.0%) se_interrupt: 3 ( 0.0%) getblockparamproxy exit reasons: (all relevant counters are zero) getinstancevariable exit reasons: (all relevant counters are zero) setinstancevariable exit reasons: (all relevant counters are zero) opt_aref exit reasons: (all relevant counters are zero) expandarray exit reasons: (all relevant counters are zero) opt_getinlinecache exit reasons: (all relevant counters are zero) invalidation reasons: (all relevant counters are zero) num_send: 155,823 num_send_known_class: 0 ( 0.0%) num_send_polymorphic: 119,880 (76.9%) bindings_allocations: 0 bindings_set: 0 compiled_iseq_count: 36 compiled_block_count: 179 compiled_branch_count: 240 block_next_count: 11 defer_count: 70 freed_iseq_count: 0 invalidation_count: 0 constant_state_bumps: 0 inline_code_size: 31,032 outlined_code_size: 29,708 freed_code_size: 0 code_region_size: 65,536 live_context_size: 8,360 live_context_count: 220 live_page_count: 4 freed_page_count: 0 code_gc_count: 0 num_gc_obj_refs: 130 object_shape_count: 295 side_exit_count: 24,978 total_exit_count: 85,890 yjit_insns_count: 1,076,966 avg_len_in_yjit: 12.2 Top-2 most frequent exit ops (100.0% of exits): opt_send_without_block: 24,975 (100.0%) leave: 3 ( 0.0%) ``` Co-authored-by: Aaron Patterson <tenderlove@ruby-lang.org> Notes: Merged: https://github.com/ruby/ruby/pull/7335
2023-02-21YJIT: Fastpath for Module#=== (#7351)Alan Wu
Co-authored-by: Maxime Chevalier-Boisvert <maxime.chevalierboisvert@shopify.com> Co-authored-by: Jimmy Miller <jimmy.miller@shopify.com> Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2023-02-21YJIT: Avoid checking symbol ID twice on send (#7350)Takashi Kokubun
Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2023-02-21YJIT: Fix clippy issues and remove unused params (#7348)Jimmy Miller
* YJIT: Fix clippy issues and remove unused params * Remove an unnecessary whitespace --------- Co-authored-by: Takashi Kokubun <takashikkbn@gmail.com> Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2023-02-17YJIT: Consolidate jit methods in JITState impl (#7336)Jimmy Miller
These jit_* methods don't jit code, but instead check things on the JITState. We had other methods that did the same thing that were just added on the impl JITState. For consistency I added these methods there. Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2023-02-17YJIT: Use rb_ivar_get at the end of ivar chains (#7334)Takashi Kokubun
* YJIT: Use rb_ivar_get at the end of ivar chains * Rename the counter to get_ivar_max_depth Notes: Merged-By: k0kubun <takashikkbn@gmail.com>
2023-02-17Add asm comment to YJIT's rb_str_empty_pMaxime Chevalier-Boisvert
2023-02-16YJIT: Fix false assumption that String#+@ => ::StringAlan Wu
Could return a subclass. [Bug #19444] Notes: Merged: https://github.com/ruby/ruby/pull/7328
2023-02-16YJIT: jit_prepare_routine_call() for String#+@ missingAlan Wu
We saw SEGVs due to this when running with StackProf, which needs a correct PC for RUBY_INTERNAL_EVENT_NEWOBJ, the same event used for ObjectSpace allocation tracing. [Bug #19444] Notes: Merged: https://github.com/ruby/ruby/pull/7328
2023-02-16YJIT: Refactor getlocal and setlocal insns (#7320)Takashi Kokubun
Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2023-02-16YJIT: Initial support for rest args (#7311)Jimmy Miller
* YJIT: Initial support for rest args * Update yjit/src/codegen.rs --------- Co-authored-by: Maxime Chevalier-Boisvert <maximechevalierb@gmail.com> Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2023-02-16Move `attached_object` into `rb_classext_struct`Jean Boussier
Given that signleton classes don't have an allocator, we can re-use these bytes to store the attached object in `rb_classext_struct` without making it larger. Notes: Merged: https://github.com/ruby/ruby/pull/7309
2023-02-15YJIT: `Kernel#{is_a?,instance_of?}` fast paths (GH-7297)Jimmy Miller
Co-authored-by: Maxime Chevalier-Boisvert <maxime.chevalierboisvert@shopify.com> Co-authored-by: Alan Wu <XrXr@users.noreply.github.com> Notes: Merged: https://github.com/ruby/ruby/pull/7297 Merged-By: XrXr
2023-02-14YJIT: Optimize != for Integers and Strings (#7301)Takashi Kokubun
Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2023-02-14YJIT: Check correct BOP on gen_fixnum_cmp (#7303)Takashi Kokubun
Notes: Merged-By: k0kubun <takashikkbn@gmail.com>