summaryrefslogtreecommitdiff
path: root/yjit/src/codegen.rs
AgeCommit message (Collapse)Author
2023-08-30YJIT: shrink Context from 29 to 21 bytes by reducing space used by ↵Maxime Chevalier-Boisvert
TempMapping (#8321) * YJIT: merge tempmapping and temp types into a single-byte encoding YJIT: refactor to shrink Context by 8 bytes * Add tests, fix bug in TempMapping::map_to_local() * Update yjit/src/core.rs Co-authored-by: Takashi Kokubun <takashikkbn@gmail.com> * Update yjit/src/core.rs Co-authored-by: Takashi Kokubun <takashikkbn@gmail.com> * Fewer transmutes where `as` would suffice. Also repr(u8) * Update yjit/src/core.rs Co-authored-by: Takashi Kokubun <takashikkbn@gmail.com> * Update yjit/src/core.rs Co-authored-by: Takashi Kokubun <takashikkbn@gmail.com> * Update yjit/src/core.rs Co-authored-by: Takashi Kokubun <takashikkbn@gmail.com> --------- Co-authored-by: Takashi Kokubun <takashikkbn@gmail.com> Co-authored-by: Alan Wu <XrXr@users.noreply.github.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-24YJIT: Refactor to use Option<BlockHandler> in SpecValAlan Wu
We pass block around as `Option<BlockHandler>` having SpecVal match that simplifes code matching for the `None` case. Notes: Merged: https://github.com/ruby/ruby/pull/8271
2023-08-24YJIT: Move block handler SpecVal variants into BlockHandlerAlan Wu
A refactor so that the variants correspond to branches in vm_caller_setup_arg_block(). Notes: Merged: https://github.com/ruby/ruby/pull/8271
2023-08-23YJIT: Implement VM_CALL_ARGS_BLOCKARG with Proc for ISeq callsAlan Wu
Rack uses this. Speculate that the `obj` in `the_call(&obj)` will be a proc when the compile-time sample is a proc. Co-authored-by: Takashi Kokubun <takashikkbn@gmail.com> Co-authored-by: Maxime Chevalier-Boisvert <maxime.chevalierboisvert@shopify.com> Co-authored-by: Aaron Patterson <tenderlove@ruby-lang.org> Notes: Merged: https://github.com/ruby/ruby/pull/8117 Merged-By: XrXr
2023-08-23Fix guard-heap upgrades (#8264)Aaron Patterson
* Fix guard-heap upgrades `getinstancevariable` was generating more heap guards than I thought. It turns out that the upgrade code has a bug in it. Given the following Ruby code: ```ruby class Foo def initialize @a = 1 @b = 1 end def foo [@a, @b] end end foo = Foo.new 10.times { foo.foo } puts RubyVM::YJIT.disasm Foo.instance_method(:foo) ``` Before this commit, the machine code was like this: ``` == BLOCK 1/4, ISEQ RANGE [0,3), 36 bytes ====================== # Insn: 0000 getinstancevariable (stack_size: 0) 0x5562fb831023: mov rax, qword ptr [r13 + 0x18] # guard object is heap 0x5562fb831027: test al, 7 0x5562fb83102a: jne 0x5562fb833080 0x5562fb831030: test rax, rax 0x5562fb831033: je 0x5562fb833080 # guard shape 0x5562fb831039: cmp dword ptr [rax + 4], 0x18 0x5562fb83103d: jne 0x5562fb833062 # reg_temps: 00000000 -> 00000001 0x5562fb831043: mov rsi, qword ptr [rax + 0x10] == BLOCK 2/4, ISEQ RANGE [3,6), 0 bytes ======================= == BLOCK 3/4, ISEQ RANGE [3,6), 36 bytes ====================== # regenerate_branch # Insn: 0003 getinstancevariable (stack_size: 1) # regenerate_branch 0x5562fb831047: mov rax, qword ptr [r13 + 0x18] # guard object is heap 0x5562fb83104b: test al, 7 0x5562fb83104e: jne 0x5562fb8330db 0x5562fb831054: test rax, rax 0x5562fb831057: je 0x5562fb8330db # guard shape 0x5562fb83105d: cmp dword ptr [rax + 4], 0x18 0x5562fb831061: jne 0x5562fb8330ba # reg_temps: 00000001 -> 00000011 0x5562fb831067: mov rdi, qword ptr [rax + 0x18] ``` After this commit, the machine code has fewer guards for `self`: ``` == BLOCK 1/4, ISEQ RANGE [0,3), 36 bytes ====================== # Insn: 0000 getinstancevariable (stack_size: 0) 0x55cb5db5f023: mov rax, qword ptr [r13 + 0x18] # guard object is heap 0x55cb5db5f027: test al, 7 0x55cb5db5f02a: jne 0x55cb5db61080 0x55cb5db5f030: test rax, rax 0x55cb5db5f033: je 0x55cb5db61080 # guard shape 0x55cb5db5f039: cmp dword ptr [rax + 4], 0x18 0x55cb5db5f03d: jne 0x55cb5db61062 # reg_temps: 00000000 -> 00000001 0x55cb5db5f043: mov rsi, qword ptr [rax + 0x10] == BLOCK 2/4, ISEQ RANGE [3,6), 0 bytes ======================= == BLOCK 3/4, ISEQ RANGE [3,6), 18 bytes ====================== # regenerate_branch # Insn: 0003 getinstancevariable (stack_size: 1) # regenerate_branch 0x55cb5db5f047: mov rax, qword ptr [r13 + 0x18] # guard shape 0x55cb5db5f04b: cmp dword ptr [rax + 4], 0x18 0x55cb5db5f04f: jne 0x55cb5db610ba # reg_temps: 00000001 -> 00000011 0x55cb5db5f055: mov rdi, qword ptr [rax + 0x18] ``` Co-Authored-By: Takashi Kokubun <takashikkbn@gmail.com> * Fix array/string guards as well --------- Co-authored-by: Takashi Kokubun <takashikkbn@gmail.com> Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
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-17Add note about rb_f_notimplement [ci skip]Alan Wu
Co-authored-by: Takashi Kokubun <takashikkbn@gmail.com> Notes: Merged: https://github.com/ruby/ruby/pull/8239
2023-08-17YJIT: Fix Kernel#respond_to? handling of rb_f_notimplementAlan Wu
We should return false for this type of special methods but wasn't previously. Was reproducible with: make test-all TESTS=../test/-ext-/test_notimplement.rb RUN_OPTS='--yjit-call-threshold=1' Notes: Merged: https://github.com/ruby/ruby/pull/8239
2023-08-17YJIT: implement side chain fallback for setlocal to avoid exiting (#8227)Maxime Chevalier-Boisvert
* YJIT: implement side chain fallback for setlocal to avoid exiting * Update yjit/src/codegen.rs Co-authored-by: Takashi Kokubun <takashikkbn@gmail.com> --------- Co-authored-by: Takashi Kokubun <takashikkbn@gmail.com> Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
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-14YJIT: Chain guard classes on instance_of (#8209)Takashi Kokubun
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-11YJIT: increase max chain depth for expandarray (#8205)Maxime Chevalier-Boisvert
Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2023-08-11YJIT: implement codegen for rb_int_lshift (#8201)Maxime Chevalier-Boisvert
* YJIT: implement codegen for rb_int_lshift * Update yjit/src/asm/x86_64/mod.rs Co-authored-by: Takashi Kokubun <takashikkbn@gmail.com> --------- Co-authored-by: Takashi Kokubun <takashikkbn@gmail.com> Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2023-08-10YJIT: Implement checkmatch instruction (#8203)Takashi Kokubun
Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2023-08-10YJIT: Fallback megamorphic super/yield to dynamic dispatch (#8197)Takashi Kokubun
YJIT: Fallback megamorphic super/yield to dynamic dispatch Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2023-08-10YJIT: Allow VM_CALL_ARGS_BLOCKARG on invokesuper (#8198)Takashi Kokubun
Notes: Merged-By: k0kubun <takashikkbn@gmail.com>
2023-08-09YJIT: Chain guard method IDs for respond_to? (#8196)Takashi Kokubun
Notes: Merged-By: k0kubun <takashikkbn@gmail.com>
2023-08-09YJIT: Distinguish exit and fallback reasons for invokesuper/invokeblock (#8194)Takashi Kokubun
YJIT: Distinguish exit and fallback reasons for invokesuper/invokeblock Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2023-08-09YJIT: Count throw instructions for each tag (#8188)Takashi Kokubun
* YJIT: Count throw instructions for each tag * Show % of each throw type Notes: Merged-By: k0kubun <takashikkbn@gmail.com>
2023-08-09YJIT: Count all opt_getconstant_path exit reasons (#8187)Takashi Kokubun
Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2023-08-09YJIT: Correct name of a counter (#8186)Alan Wu
Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
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-04YJIT: guard for array_len >= num in expandarray (#8169)Maxime Chevalier-Boisvert
Avoid generating long dispatch chains for all array lengths seen. Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
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-08-02YJIT: Fallback setivar if the receiver isn't T_OBJECT (#8160)Jean byroot Boussier
Followup: https://github.com/ruby/ruby/pull/8152 If the receiver is a T_MODULE or T_CLASS and has a lot of ivars, `get_next_shape_internal` will return `NULL`. Co-authored-by: Jean Boussier <byroot@ruby-lang.org> Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2023-08-02YJIT: Distinguish exit and fallback reasons for send (#8159)Takashi Kokubun
Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2023-08-02YJIT: Move ROBJECT_OFFSET_* to yjit.c (#8157)Takashi Kokubun
Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2023-08-02Revert "YJIT: implement `expandarray_rhs_too_small` case (#8153)"Hiroshi SHIBATA
This reverts commit 3b88a0bee841aee77bee306d9d34e587561515cf. This commit break aarch64 platform and Apple Silicon
2023-08-01YJIT: implement `expandarray_rhs_too_small` case (#8153)Maxime Chevalier-Boisvert
* YJIT: handle expandarray_rhs_too_small case * YJIT: fix csel bug in x86 backend, add test * Remove commented out lines Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2023-08-01YJIT: Fallback setivar if the next shape is too complex (#8152)Takashi Kokubun
Notes: Merged-By: k0kubun <takashikkbn@gmail.com>
2023-07-29YJIT: Drop Copy trait from Context (#8138)Takashi Kokubun
Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2023-07-27YJIT: Count setivar too-complex exits (#8131)Takashi Kokubun
Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2023-07-27YJIT: implement missing `asm.jg` instruction in backend (#8130)Maxime Chevalier-Boisvert
YJIT: implement missing jg instruction in backend While trying to implement a specialize integer left shift, I ran into a problem where we have no way to do a greater-than comparison at the moment. Surprising we went this far without ever needing it. Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2023-07-27YJIT: getblockparamproxy for when block is a ProcAlan Wu
Notes: Merged: https://github.com/ruby/ruby/pull/8124
2023-07-27Revert "YJIT: Fix naming for a getblockparamproxy counter"Alan Wu
This reverts commit e7804963f09d7df7f6cce44fbb3e37809c9a15cc. Oops. The counter was for getblockparam, without "proxy", so it was aptly named. Notes: Merged: https://github.com/ruby/ruby/pull/8124
2023-07-27YJIT: Use dynamic dispatch for megamorphic send (#8125)Takashi Kokubun
Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2023-07-26YJIT: Count the number of dynamic send dispatches (#8122)Takashi Kokubun
Notes: Merged-By: k0kubun <takashikkbn@gmail.com>
2023-07-26YJIT: Fix naming for a getblockparamproxy counterAlan Wu
The rest of the counters are prefixed with `gbpp_` and that's what `yjit.rb` uses when printing the summary. This counter wasn't included in the summary. Notes: Merged: https://github.com/ruby/ruby/pull/8121
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-24YJIT: Fallback send instructions to vm_sendish (#8106)Takashi Kokubun
Notes: Merged-By: k0kubun <takashikkbn@gmail.com>
2023-07-20YJIT: Rename exec_instruction to yjit_insns_count (#8102)Takashi Kokubun
Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2023-07-20Get rid of obsoleted __bp__ referencesTakashi Kokubun
2023-07-20YJIT: Avoid undercounting retired_in_yjit (#8038)Takashi Kokubun
* YJIT: Count the number of failed instructions * Rename yjit_insns_count to exec_instructions instead * Hoist out the exec_instruction counter Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2023-07-17Remove __bp__ and speed-up bmethod calls (#8060)Alan Wu
Remove rb_control_frame_t::__bp__ and optimize bmethod calls This commit removes the __bp__ field from rb_control_frame_t. It was introduced to help MJIT, but since MJIT was replaced by RJIT, we can use vm_base_ptr() to compute it from the SP of the previous control frame instead. Removing the field avoids needing to set it up when pushing new frames. Simply removing __bp__ would cause crashes since RJIT and YJIT used a slightly different stack layout for bmethod calls than the interpreter. At the moment of the call, the two layouts looked as follows: ┌────────────┐ ┌────────────┐ │ frame_base │ │ frame_base │ ├────────────┤ ├────────────┤ │ ... │ │ ... │ ├────────────┤ ├────────────┤ │ args │ │ args │ ├────────────┤ └────────────┘<─prev_frame_sp │ receiver │ prev_frame_sp─>└────────────┘ RJIT & YJIT interpreter Essentially, vm_base_ptr() needs to compute the address to frame_base given prev_frame_sp in the diagrams. The presence of the receiver created an off-by-one situation. Make the interpreter use the layout the JITs use for iseq-to-iseq bmethod calls. Doing so removes unnecessary argument shifting and vm_exec_core() re-entry from the interpreter, yielding a speed improvement visible through `benchmark/vm_defined_method.yml`: patched: 7578743.1 i/s master: 4796596.3 i/s - 1.58x slower C-to-iseq bmethod calls now store one more VALUE than before, but that should have negligible impact on overall performance. Note that re-entering vm_exec_core() used to be necessary for firing TracePoint events, but that's no longer the case since 9121e57a5f50bc91bae48b3b91edb283bf96cb6b. Closes ruby/ruby#6428
2023-07-13Remove RARRAY_CONST_PTR_TRANSIENTPeter Zhu
RARRAY_CONST_PTR now does the same things as RARRAY_CONST_PTR_TRANSIENT. Notes: Merged: https://github.com/ruby/ruby/pull/8071
2023-07-11YJIT: add counter for untracked gbpp exit reason (#8052)Maxime Chevalier-Boisvert
Notes: Merged-By: maximecb <maximecb@ruby-lang.org>