summaryrefslogtreecommitdiff
path: root/yjit/bindgen/src
AgeCommit message (Collapse)Author
2023-07-27YJIT: getblockparamproxy for when block is a ProcAlan Wu
Notes: Merged: https://github.com/ruby/ruby/pull/8124
2023-07-24YJIT: Fallback send instructions to vm_sendish (#8106)Takashi Kokubun
Notes: Merged-By: k0kubun <[email protected]>
2023-07-17YJIT: refactoring to allow for fancier call threshold logic (#8078)Maxime Chevalier-Boisvert
* YJIT: refactoring to allow for fancier call threshold logic * Avoid potentially compiling functions multiple times. * Update vm.c Co-authored-by: Alan Wu <[email protected]> --------- Co-authored-by: Alan Wu <[email protected]> Notes: Merged-By: maximecb <[email protected]>
2023-07-13YJIT: Make ratio_in_yjit always available (#8064)Takashi Kokubun
Notes: Merged-By: maximecb <[email protected]>
2023-06-06YJIT: Avoid identity-based known-class guards for IO objects (#7911)Alan Wu
`IO#reopen` is very special in that it is able to change the class and singleton class of IO instances. In its presence, it is not correct to assume that IO instances has a stable class/singleton class and guard by comparing identity. Notes: Merged-By: maximecb <[email protected]>
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 <[email protected]>
2023-04-04[Feature #19579] Remove !USE_RVARGC code (#7655)Peter Zhu
Remove !USE_RVARGC code [Feature #19579] The Variable Width Allocation feature was turned on by default in Ruby 3.2. Since then, we haven't received bug reports or backports to the non-Variable Width Allocation code paths, so we assume that nobody is using it. We also don't plan on maintaining the non-Variable Width Allocation code, so we are going to remove it. Notes: Merged-By: maximecb <[email protected]>
2023-04-03YJIT: Add codegen for Array#<< (#7645)Takashi Kokubun
Notes: Merged-By: k0kubun <[email protected]>
2023-04-01Remove an unneeded function copyTakashi Kokubun
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 <[email protected]>
2023-03-15YJIT: Assert that we have the VM lock while markingAlan Wu
Somewhat important because having the lock is a key part of the soundness reasoning for the `unsafe` usage here. Notes: Merged: https://github.com/ruby/ruby/pull/7530
2023-03-14YJIT: Introduce no_gc attribute (#7511)Takashi Kokubun
Notes: Merged-By: k0kubun <[email protected]>
2023-03-13YJIT: Handle rest+splat where non-splat < required (#7499)Jimmy Miller
Notes: Merged-By: maximecb <[email protected]>
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 <[email protected]>
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 <[email protected]>
2023-02-27Merge internal/intern/gc.h into internal/gc.hMatt Valentine-House
Notes: Merged: https://github.com/ruby/ruby/pull/7330
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 <[email protected]> Co-authored-by: Alan Wu <[email protected]> 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 <[email protected]>
2023-02-02YJIT: log the names of methods we call to in disasm (#7231)Maxime Chevalier-Boisvert
* YJIT: log the names of methods we call to in disasm * Assert that pointer is not null * Handle case where UTF8 conversion not possible Notes: Merged-By: maximecb <[email protected]>
2023-02-02YJIT: Crash with rb_bug() when panickingAlan Wu
Helps with getting good bug reports in the wild. Intended to be backported to the 3.2.x series. Notes: Merged: https://github.com/ruby/ruby/pull/7232
2023-01-31YJIT: Handle splat with opt more fully (#7209)Jimmy Miller
* YJIT: Handle splat with opt more fully * Update yjit/src/codegen.rs --------- Co-authored-by: Maxime Chevalier-Boisvert <[email protected]> Notes: Merged-By: maximecb <[email protected]>
2023-01-19Implement splat for cfuncs. Split exit exit cases to better capture where we ↵Jimmy Miller
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. Notes: Merged-By: maximecb <[email protected]>
2023-01-18YJIT: implement codegen for `String#empty?` (#7148)Maxime Chevalier-Boisvert
YJIT: implement codegen for String#empty? Notes: Merged-By: maximecb <[email protected]>
2023-01-06YJIT: Make iseq_get_location consistent with iseq.c (#7074)Takashi Kokubun
* YJIT: Make iseq_get_location consistent with iseq.c * YJIT: Call it "YJIT entry point" Co-authored-by: Maxime Chevalier-Boisvert <[email protected]> Co-authored-by: Maxime Chevalier-Boisvert <[email protected]> Notes: Merged-By: k0kubun <[email protected]>
2022-12-15Transition complex objects to "too complex" shapeJemma Issroff
When an object becomes "too complex" (in other words it has too many variations in the shape tree), we transition it to use a "too complex" shape and use a hash for storing instance variables. Without this patch, there were rare cases where shape tree growth could "explode" and cause performance degradation on what would otherwise have been cached fast paths. This patch puts a limit on shape tree growth, and gracefully degrades in the rare case where there could be a factorial growth in the shape tree. For example: ```ruby class NG; end HUGE_NUMBER.times do NG.new.instance_variable_set(:"@unique_ivar_#{_1}", 1) end ``` We consider objects to be "too complex" when the object's class has more than SHAPE_MAX_VARIATIONS (currently 8) leaf nodes in the shape tree and the object introduces a new variation (a new leaf node) associated with that class. For example, new variations on instances of the following class would be considered "too complex" because those instances create more than 8 leaves in the shape tree: ```ruby class Foo; end 9.times { Foo.new.instance_variable_set(":@uniq_#{_1}", 1) } ``` However, the following class is *not* too complex because it only has one leaf in the shape tree: ```ruby class Foo def initialize @a = @b = @c = @d = @e = @f = @g = @h = @i = nil end end 9.times { Foo.new } `` This case is rare, so we don't expect this change to impact performance of most applications, but it needs to be handled. Co-Authored-By: Aaron Patterson <[email protected]> Notes: Merged: https://github.com/ruby/ruby/pull/6931
2022-12-08YJIT: Upgrade bindgen to stabilize and reduce outputAlan Wu
The new version has an option to merge everything into a big `extern "C"` block and it's nicer. More importantly, this upgrade fixes an issue where Ubuntu with Clang 12 and macOS with Clang 14 gave a one line diff for `rb_shape_t`. It was slightly annoying because we use macOS locally. Notes: Merged: https://github.com/ruby/ruby/pull/6887
2022-12-05YJIT: Extract SHAPE_ID_NUM_BITS into a constant (#6863)Jemma Issroff
Notes: Merged-By: k0kubun <[email protected]>
2022-12-02Remove unused rb_shape_flag_shift and rb_shape_flag_maskJemma Issroff
Notes: Merged: https://github.com/ruby/ruby/pull/6767
2022-12-02Extracted rb_shape_id_offsetJemma Issroff
Notes: Merged: https://github.com/ruby/ruby/pull/6767
2022-12-02bail on compilation if the comptime receiver is frozenAaron Patterson
Notes: Merged: https://github.com/ruby/ruby/pull/6767
2022-12-02implement IV writesAaron Patterson
Notes: Merged: https://github.com/ruby/ruby/pull/6767
2022-12-02YJIT: Make case-when optimization respect === redefinition (#6846)Alan Wu
* 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 <[email protected]> Co-authored-by: Takashi Kokubun <[email protected]> Notes: Merged-By: maximecb <[email protected]>
2022-12-01YJIT: Reorder branches for Fixnum opt_case_dispatch (#6841)Takashi Kokubun
* YJIT: Reorder branches for Fixnum opt_case_dispatch Co-authored-by: Maxime Chevalier-Boisvert <[email protected]> Co-authored-by: Alan Wu <[email protected]> * YJIT: Don't support too large values Co-authored-by: Maxime Chevalier-Boisvert <[email protected]> Co-authored-by: Alan Wu <[email protected]> Notes: Merged-By: maximecb <[email protected]>
2022-11-1832 bit comparison on shape idAaron Patterson
This commit changes the shape id comparisons to use a 32 bit comparison rather than 64 bit. That means we don't need to load the shape id to a register on x86 machines. Given the following program: ```ruby class Foo def initialize @foo = 1 @bar = 1 end def read [@foo, @bar] end end foo = Foo.new foo.read foo.read foo.read foo.read foo.read puts RubyVM::YJIT.disasm(Foo.instance_method(:read)) ``` The machine code we generated _before_ this change is like this: ``` == BLOCK 1/4, ISEQ RANGE [0,3), 65 bytes ====================== # getinstancevariable 0x559a18623023: mov rax, qword ptr [r13 + 0x18] # guard object is heap 0x559a18623027: test al, 7 0x559a1862302a: jne 0x559a1862502d 0x559a18623030: cmp rax, 4 0x559a18623034: jbe 0x559a1862502d # guard shape, embedded, and T_OBJECT 0x559a1862303a: mov rcx, qword ptr [rax] 0x559a1862303d: movabs r11, 0xffff00000000201f 0x559a18623047: and rcx, r11 0x559a1862304a: movabs r11, 0xb000000002001 0x559a18623054: cmp rcx, r11 0x559a18623057: jne 0x559a18625046 0x559a1862305d: mov rax, qword ptr [rax + 0x18] 0x559a18623061: mov qword ptr [rbx], rax == BLOCK 2/4, ISEQ RANGE [3,6), 0 bytes ======================= == BLOCK 3/4, ISEQ RANGE [3,6), 47 bytes ====================== # gen_direct_jmp: fallthrough # getinstancevariable # regenerate_branch # getinstancevariable # regenerate_branch 0x559a18623064: mov rax, qword ptr [r13 + 0x18] # guard shape, embedded, and T_OBJECT 0x559a18623068: mov rcx, qword ptr [rax] 0x559a1862306b: movabs r11, 0xffff00000000201f 0x559a18623075: and rcx, r11 0x559a18623078: movabs r11, 0xb000000002001 0x559a18623082: cmp rcx, r11 0x559a18623085: jne 0x559a18625099 0x559a1862308b: mov rax, qword ptr [rax + 0x20] 0x559a1862308f: mov qword ptr [rbx + 8], rax ``` After this change, it's like this: ``` == BLOCK 1/4, ISEQ RANGE [0,3), 41 bytes ====================== # getinstancevariable 0x5560c986d023: mov rax, qword ptr [r13 + 0x18] # guard object is heap 0x5560c986d027: test al, 7 0x5560c986d02a: jne 0x5560c986f02d 0x5560c986d030: cmp rax, 4 0x5560c986d034: jbe 0x5560c986f02d # guard shape 0x5560c986d03a: cmp word ptr [rax + 6], 0x19 0x5560c986d03f: jne 0x5560c986f046 0x5560c986d045: mov rax, qword ptr [rax + 0x10] 0x5560c986d049: mov qword ptr [rbx], rax == BLOCK 2/4, ISEQ RANGE [3,6), 0 bytes ======================= == BLOCK 3/4, ISEQ RANGE [3,6), 23 bytes ====================== # gen_direct_jmp: fallthrough # getinstancevariable # regenerate_branch # getinstancevariable # regenerate_branch 0x5560c986d04c: mov rax, qword ptr [r13 + 0x18] # guard shape 0x5560c986d050: cmp word ptr [rax + 6], 0x19 0x5560c986d055: jne 0x5560c986f099 0x5560c986d05b: mov rax, qword ptr [rax + 0x18] 0x5560c986d05f: mov qword ptr [rbx + 8], rax ``` The first ivar read is a bit more complex, but the second ivar read is much simpler. I think eventually we could teach the context about the shape, then emit only one shape guard. Notes: Merged: https://github.com/ruby/ruby/pull/6737
2022-11-14Remove USE_RVARGC codeAaron Patterson
We don't need this constant to be exposed anymore, so remove it Notes: Merged: https://github.com/ruby/ruby/pull/6728
2022-11-08Implement optimize call (#6691)Jimmy Miller
This dispatches to a c func for doing the dynamic lookup. I experimented with chain on the proc but wasn't able to detect which call sites would be monomorphic vs polymorphic. There is definitely room for optimization here, but it does reduce exits. Notes: Merged-By: maximecb <[email protected]>
2022-11-02YJIT: Support invokeblock (#6640)Takashi Kokubun
* YJIT: Support invokeblock * Update yjit/src/backend/arm64/mod.rs * Update yjit/src/codegen.rs Co-authored-by: Maxime Chevalier-Boisvert <[email protected]> Notes: Merged-By: maximecb <[email protected]>
2022-10-26YJIT: Support nil and blockparamproxy as blockarg in send (#6492)Matthew Draper
Co-authored-by: John Hawthorn <[email protected]> Co-authored-by: John Hawthorn <[email protected]> Notes: Merged-By: maximecb <[email protected]>
2022-10-25YJIT: GC and recompile all code pages (#6406)Takashi Kokubun
when it fails to allocate a new page. Co-authored-by: Alan Wu <[email protected]> Notes: Merged-By: k0kubun <[email protected]>
2022-10-20YJIT: incorporate ruby_special_constsNobuyoshi Nakada
Notes: Merged: https://github.com/ruby/ruby/pull/6600
2022-10-14YJIT doesn't need rb_obj_ensure_iv_index_mappingAaron Patterson
We should make this function static and remove it from YJIT bindings. Notes: Merged: https://github.com/ruby/ruby/pull/6553
2022-10-11Implement optimize send in yjit (#6488)Jimmy Miller
* Implement optimize send in yjit This successfully makes all our benchmarks exit way less for optimize send reasons. It makes some benchmarks faster, but not by as much as I'd like. I think this implementation works, but there are definitely more optimial arrangements. For example, what if we compiled send to a jump table? That seems like perhaps the most optimal we could do, but not obvious (to me) how to implement give our current setup. Co-authored-by: Alan Wu <[email protected]> * Attempt at fixing the issues raised by @XrXr * fix allowlist * returns 0 instead of nil when not found * remove comment about encoding exception * Fix up c changes * Update assert Co-authored-by: Alan Wu <[email protected]> * get rid of unneeded code and fix the flags * Apply suggestions from code review Co-authored-by: Alan Wu <[email protected]> * rename and fix typo Co-authored-by: Alan Wu <[email protected]> Notes: Merged-By: maximecb <[email protected]>
2022-10-11Revert "Revert "This commit implements the Object Shapes technique in CRuby.""Jemma Issroff
This reverts commit 9a6803c90b817f70389cae10d60b50ad752da48f.
2022-10-04YJIT: add support for calling bmethods (#6489)Alan Wu
* 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 <[email protected]> Co-authored-by: John Hawthorn <[email protected]> Notes: Merged-By: maximecb <[email protected]>
2022-09-30Revert "This commit implements the Object Shapes technique in CRuby."Aaron Patterson
This reverts commit 68bc9e2e97d12f80df0d113e284864e225f771c2.
2022-09-28This commit implements the Object Shapes technique in CRuby.Jemma Issroff
Object Shapes is used for accessing instance variables and representing the "frozenness" of objects. Object instances have a "shape" and the shape represents some attributes of the object (currently which instance variables are set and the "frozenness"). Shapes form a tree data structure, and when a new instance variable is set on an object, that object "transitions" to a new shape in the shape tree. Each shape has an ID that is used for caching. The shape structure is independent of class, so objects of different types can have the same shape. For example: ```ruby class Foo def initialize # Starts with shape id 0 @a = 1 # transitions to shape id 1 @b = 1 # transitions to shape id 2 end end class Bar def initialize # Starts with shape id 0 @a = 1 # transitions to shape id 1 @b = 1 # transitions to shape id 2 end end foo = Foo.new # `foo` has shape id 2 bar = Bar.new # `bar` has shape id 2 ``` Both `foo` and `bar` instances have the same shape because they both set instance variables of the same name in the same order. This technique can help to improve inline cache hits as well as generate more efficient machine code in JIT compilers. This commit also adds some methods for debugging shapes on objects. See `RubyVM::Shape` for more details. For more context on Object Shapes, see [Feature: #18776] Co-Authored-By: Aaron Patterson <[email protected]> Co-Authored-By: Eileen M. Uchitelle <[email protected]> Co-Authored-By: John Hawthorn <[email protected]>
2022-09-26Revert this until we can figure out WB issues or remove shapes from GCAaron Patterson
Revert "* expand tabs. [ci skip]" This reverts commit 830b5b5c351c5c6efa5ad461ae4ec5085e5f0275. Revert "This commit implements the Object Shapes technique in CRuby." This reverts commit 9ddfd2ca004d1952be79cf1b84c52c79a55978f4.
2022-09-26This commit implements the Object Shapes technique in CRuby.Jemma Issroff
Object Shapes is used for accessing instance variables and representing the "frozenness" of objects. Object instances have a "shape" and the shape represents some attributes of the object (currently which instance variables are set and the "frozenness"). Shapes form a tree data structure, and when a new instance variable is set on an object, that object "transitions" to a new shape in the shape tree. Each shape has an ID that is used for caching. The shape structure is independent of class, so objects of different types can have the same shape. For example: ```ruby class Foo def initialize # Starts with shape id 0 @a = 1 # transitions to shape id 1 @b = 1 # transitions to shape id 2 end end class Bar def initialize # Starts with shape id 0 @a = 1 # transitions to shape id 1 @b = 1 # transitions to shape id 2 end end foo = Foo.new # `foo` has shape id 2 bar = Bar.new # `bar` has shape id 2 ``` Both `foo` and `bar` instances have the same shape because they both set instance variables of the same name in the same order. This technique can help to improve inline cache hits as well as generate more efficient machine code in JIT compilers. This commit also adds some methods for debugging shapes on objects. See `RubyVM::Shape` for more details. For more context on Object Shapes, see [Feature: #18776] Co-Authored-By: Aaron Patterson <[email protected]> Co-Authored-By: Eileen M. Uchitelle <[email protected]> Co-Authored-By: John Hawthorn <[email protected]> Notes: Merged: https://github.com/ruby/ruby/pull/6386