Commit graph

156 commits

Author SHA1 Message Date
Jemma Issroff
ad63b668e2
Revert "Revert "This commit implements the Object Shapes technique in CRuby.""
This reverts commit 9a6803c90b.
2022-10-11 08:40:56 -07:00
Alan Wu
7293bfe1bf
YJIT: add support for calling bmethods (#6489)
* 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>
2022-10-04 22:48:05 -04:00
John Hawthorn
70538beaa9 Fix YJIT args for rb_vm_set_ivar_idx
This was broken accidentally with the revert of shapes (it conflicted
with some unrelated cleanup).
2022-09-30 17:26:27 -07:00
John Hawthorn
1143fe340a Fix YJIT build after shapes-revert
An variable had been renamed in between the merge and revert, so the
build was broken. This restores it.
2022-09-30 16:29:10 -07:00
Aaron Patterson
9a6803c90b
Revert "This commit implements the Object Shapes technique in CRuby."
This reverts commit 68bc9e2e97d12f80df0d113e284864e225f771c2.
2022-09-30 16:01:50 -07:00
Jimmy Miller
31461c7e0e
A bunch of clippy auto fixes for yjit (#6476) 2022-09-30 11:14:55 -04:00
Jemma Issroff
d594a5a8bd
This commit implements the Object Shapes technique in CRuby.
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 <tenderlove@ruby-lang.org>
Co-Authored-By: Eileen M. Uchitelle <eileencodes@gmail.com>
Co-Authored-By: John Hawthorn <john@hawthorn.email>
2022-09-28 08:26:21 -07:00
Aaron Patterson
06abfa5be6
Revert this until we can figure out WB issues or remove shapes from GC
Revert "* expand tabs. [ci skip]"

This reverts commit 830b5b5c35.

Revert "This commit implements the Object Shapes technique in CRuby."

This reverts commit 9ddfd2ca00.
2022-09-26 16:10:11 -07:00
Jemma Issroff
9ddfd2ca00 This commit implements the Object Shapes technique in CRuby.
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 <tenderlove@ruby-lang.org>
Co-Authored-By: Eileen M. Uchitelle <eileencodes@gmail.com>
Co-Authored-By: John Hawthorn <john@hawthorn.email>
2022-09-26 09:21:30 -07:00
Maxime Chevalier-Boisvert
4e40fdbcee
YJIT: add chain guards in guard_two_fixnums (#6422)
* Add chain guards in guard_two_fixnums, opt_eq with symbols

* Remove symbol comparison in gen_equality_specialized
2022-09-22 17:47:54 -04:00
John Hawthorn
4b97f1e525
YJIT: Refactor into gen_push_frame (#6412)
This refactors the "push frame" operation common to both gen_send_iseq
and gen_send_cfunc into its own method. This allows that logic to live
in one place.
2022-09-22 17:47:26 -04:00
Takashi Kokubun
5883bc7c07
YJIT: Check if the processor supports --yjit-stats (#6401)
* YJIT: Add asm comment for incr_counter

* YJIT: Check if the processor supports --yjit-stats
2022-09-19 16:34:03 +09:00
Jimmy Miller
e75d963685
Only exit if ruby2_keywords and splat together (#6395)
Before this change railsbench spent less time in yjit than before splat. This brings it back to parity.
2022-09-19 15:09:38 +09:00
Jimmy Miller
2387fbfb34
Fix splat args (#6385)
* Fix splat args

Cfuncs were not working properly so I disabled them right now.

There were some checks above that were also actually preventing splat args from being called.

Finally I did some basic code cleanup after realizing I didn't need to mutate argc so much

* Add can't compile for direct cfunc splat call

* Fix typo

* Update yjit/src/codegen.rs

Co-authored-by: Maxime Chevalier-Boisvert <maximechevalierb@gmail.com>
2022-09-16 13:37:15 +09:00
Maxime Chevalier-Boisvert
64a020324d
Add asm comments to make disasm more readable (#6377) 2022-09-15 10:12:27 -04:00
John Hawthorn
f98d6d3f38
YJIT: Implement specialized respond_to? (#6363)
* 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>
2022-09-14 16:15:55 -04:00
Jimmy Miller
758a1d7302
Initial support for VM_CALL_ARGS_SPLAT (#6341)
* Initial support for VM_CALL_ARGS_SPLAT

This implements support for calls with splat (*) for some methods. In
benchmarks this made very little difference for most benchmarks, but a
large difference for binarytrees. Looking at side exits, many
benchmarks now don't exit for splat, but exit for some other
reason. Binarytrees however had a number of calls that used splat args
that are now much faster. In my non-scientific benchmarking this made
splat args performance on par with not using splat args at all.

* Fix wording and whitespace

Co-authored-by: Maxime Chevalier-Boisvert <maximechevalierb@gmail.com>

* Get rid of side_effect reassignment

Co-authored-by: Maxime Chevalier-Boisvert <maximechevalierb@gmail.com>
2022-09-14 10:32:22 -04:00
Takashi Kokubun
8f37e9c918
YJIT: Add Opnd#with_num_bits to use only 8 bits (#6359)
* YJIT: Add Opnd#sub_opnd to use only 8 bits

* Add with_num_bits and let arm64_split use it

* Add another assertion to with_num_bits

* Use only with_num_bits
2022-09-14 10:27:52 -04:00
John Hawthorn
5e39b3b844 YJIT: Branch directly when nil? is known from types 2022-09-09 20:29:40 -07:00
John Hawthorn
d319184390 YJIT: Branch directly when truthyness is known 2022-09-09 20:29:40 -07:00
John Hawthorn
679ef34586 New constant caching insn: opt_getconstant_path
Previously YARV bytecode implemented constant caching by having a pair
of instructions, opt_getinlinecache and opt_setinlinecache, wrapping a
series of getconstant calls (with putobject providing supporting
arguments).

This commit replaces that pattern with a new instruction,
opt_getconstant_path, handling both getting/setting the inline cache and
fetching the constant on a cache miss.

This is implemented by storing the full constant path as a
null-terminated array of IDs inside of the IC structure. idNULL is used
to signal an absolute constant reference.

    $ ./miniruby --dump=insns -e '::Foo::Bar::Baz'
    == disasm: #<ISeq:<main>@-e:1 (1,0)-(1,13)> (catch: FALSE)
    0000 opt_getconstant_path                   <ic:0 ::Foo::Bar::Baz>      (   1)[Li]
    0002 leave

The motivation for this is that we had increasingly found the need to
disassemble the instructions between the opt_getinlinecache and
opt_setinlinecache in order to determine the constant we are fetching,
or otherwise store metadata.

This disassembly was done:
* In opt_setinlinecache, to register the IC against the constant names
  it is using for granular invalidation.
* In rb_iseq_free, to unregister the IC from the invalidation table.
* In YJIT to find the position of a opt_getinlinecache instruction to
  invalidate it when the cache is populated
* In YJIT to register the constant names being used for invalidation.

With this change we no longe need disassemly for these (in fact
rb_iseq_each is now unused), as the list of constant names being
referenced is held in the IC. This should also make it possible to make
more optimizations in the future.

This may also reduce the size of iseqs, as previously each segment
required 32 bytes (on 64-bit platforms) for each constant segment. This
implementation only stores one ID per-segment.

There should be no significant performance change between this and the
previous implementation. Previously opt_getinlinecache was a "leaf"
instruction, but it included a jump (almost always to a separate cache
line). Now opt_getconstant_path is a non-leaf (it may
raise/autoload/call const_missing) but it does not jump. These seem to
even out.
2022-09-01 15:20:49 -07:00
Takashi Kokubun
4144abee42
Let --yjit-dump-disasm=all dump ocb code as well (#6309)
* Let --yjit-dump-disasm=all dump ocb code as well

* Use an enum instead

* Add a None Option to DumpDisasm (#444)

* Add a None Option to DumpDisasm

* Update yjit/src/asm/mod.rs

Co-authored-by: Maxime Chevalier-Boisvert <maximechevalierb@gmail.com>

* Fix a build failure

* Use only a single name

* Only None will be a disabled case

* Fix cargo test

* Fix --yjit-dump-disasm=all to print outlined cb

Co-authored-by: Jimmy Miller <jimmyhmiller@gmail.com>
Co-authored-by: Maxime Chevalier-Boisvert <maximechevalierb@gmail.com>
2022-09-01 11:55:39 -07:00
Takashi Kokubun
ddca3482ef
Check only symbol flag bits (#6301)
* Check only symbol flag bits

* Check all 4 bits
2022-08-29 21:05:06 -04:00
Maxime Chevalier-Boisvert
929a6a75eb Remove ir_ssa.rs as we aren't using it and it's now outdated 2022-08-29 09:09:41 -07:00
Takashi Kokubun
def3ade8a8 Add --yjit-dump-disasm to dump every compiled code (https://github.com/Shopify/ruby/pull/430)
* Add --yjit-dump-disasm to dump every compiled code

* Just use get_option

* Carve out disasm_from_addr

* Avoid push_str with format!

* Share the logic through asm.compile

* This seems to negatively impact the compilation speed
2022-08-29 09:09:41 -07:00
Kevin Newton
54c7bc67a2 Various AArch64 optimizations (https://github.com/Shopify/ruby/pull/433)
* When we're storing an immediate 0 value at a memory address, we
  can use STUR XZR, Xd instead of loading 0 into a register and
  then storing that register.
* When we're moving 0 into an argument register, we can use
  MOV Xd, XZR instead of loading the value into a register first.
* In the newarray instruction, we can skip looking at the stack at
  all if the number of values we're using is 0.
2022-08-29 09:09:41 -07:00
Noah Gibbs
93c5a5f023 Fix and re-enable String to_s, << and unary plus (https://github.com/Shopify/ruby/pull/429) 2022-08-29 09:09:41 -07:00
Alan Wu
342459576d Use VALUE for callinfos that are on the heap (https://github.com/Shopify/ruby/pull/420)
Yet another case of `jit_mov_gc_ptr()` being yanked out during the
transition to the new backend, causing a crash after object movement.
The intresting wrinkle with this one is that not all callinfos are GC'ed
objects, so the old code had an implicit assumption.

b0b9f7201a/yjit/src/codegen.rs (L4087-L4095)
2022-08-29 09:09:41 -07:00
Takashi Kokubun
5114ddce3f Avoid marking op_type on gen_defined (https://github.com/Shopify/ruby/pull/419) 2022-08-29 09:09:41 -07:00
Takashi Kokubun
a78bbef12f Use VALUE for block_iseq (https://github.com/Shopify/ruby/pull/417)
Co-authored-by: Alan Wu <alansi.xingwu@shopify.com>
2022-08-29 09:09:41 -07:00
Takashi Kokubun
e0e63b1a01 Fix a bus error on regenerate_branch (https://github.com/Shopify/ruby/pull/408)
* Fix a bus error on regenerate_branch

* Fix pad_size
2022-08-29 09:09:41 -07:00
Alan Wu
c70d1471c1 Only check lowest bit for _Bool type (https://github.com/Shopify/ruby/pull/412)
* Only check lowest bit for _Bool type

The `test AL, AL` got lost during porting and we were
generating `test RAX, RAX` instead. The upper bits of a `_Bool` return
type is unspecified and we were failing
`TestClass#test_singleton_class_should_has_own_namespace`
due to interpreterting the return value incorrectly.

* Enable test_class for test-all on x86_64
2022-08-29 09:09:41 -07:00
Maxime Chevalier-Boisvert
1cf9f56c55
Fix issue with expandarray, add missing jl, enable tests (https://github.com/Shopify/ruby/pull/409) 2022-08-29 08:47:11 -07:00
Maxime Chevalier-Boisvert
95dce1ccac
Temporarily disable rb_str_concat, add CI tests (https://github.com/Shopify/ruby/pull/407)
Make sure we can load the test-all runner and run test_yjit.rb
2022-08-29 08:47:11 -07:00
Noah Gibbs (and/or Benchmark CI)
09c12111d4
Port jit_rb_str_concat to new backend, re-enable cfunc lookup (https://github.com/Shopify/ruby/pull/402) 2022-08-29 08:47:11 -07:00
Maple Ong
5a76a15a0f
YJIT: Implement concatarray in yjit (https://github.com/Shopify/ruby/pull/405)
* 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
2022-08-29 08:47:11 -07:00
Alan Wu
2f9df46654
Use bindgen for old manual extern declarations (https://github.com/Shopify/ruby/pull/404)
We have a large extern block in cruby.rs leftover from the port. We can
use bindgen for it now and reserve the manual declaration for just a
handful of vm_insnhelper.c functions.

Fixup a few minor discrepencies bindgen found between the C declaration
and the manual declaration. Mostly missing `const` on the C side.
2022-08-29 08:47:11 -07:00
Maxime Chevalier-Boisvert
c022a60540
Fix bugs in gen_opt_getinlinecache 2022-08-29 08:47:10 -07:00
Zack Deveau
cb15886e61
Port opt_getinlinecache to the new backend (https://github.com/Shopify/ruby/pull/399) 2022-08-29 08:47:10 -07:00
Takashi Kokubun
ee1697ee07
Port opt_aref and opt_aset to the new backend IR (https://github.com/Shopify/ruby/pull/387)
* Port opt_aref and opt_aset to the new backend IR

* Recompute memory operands
2022-08-29 08:47:10 -07:00
Takashi Kokubun
df84832c75
Port getblockparamproxy and getblockparam (https://github.com/Shopify/ruby/pull/394) 2022-08-29 08:47:10 -07:00
Takashi Kokubun
e5969f8587
Port invokesuper to the new backend IR (https://github.com/Shopify/ruby/pull/391) 2022-08-29 08:47:10 -07:00
Takashi Kokubun
ca2afba4a7
Port the remaining method types in opt_send_without_block (https://github.com/Shopify/ruby/pull/390) 2022-08-29 08:47:09 -07:00
Maxime Chevalier-Boisvert
8c45b8a989
Update asm comments for gen_send_iseq 2022-08-29 08:47:09 -07:00
Noah Gibbs
6b9cec78a1
Port cfunc lookup, plus simpler cfunc generators. (https://github.com/Shopify/ruby/pull/388)
This port does *not* create invalidation regions to
ensure minimum invalidatable block sizes, and so it
does not port the to_s generator.
2022-08-29 08:47:09 -07:00
Takashi Kokubun
1cafb1a7a6
Prefer asm.store over asm.mov (https://github.com/Shopify/ruby/pull/385)
* Prefer asm.store over asm.mov

* Reverse a couple of unsure changes

* Revert changes that don't work
2022-08-29 08:47:09 -07:00
Takashi Kokubun
49c9f893f8
Port expandarray to the new backend IR (https://github.com/Shopify/ruby/pull/376)
* Port expandarray to the new backend IR

* More use of into()

* Break out live ranges

* Refactor the code further

* Reuse registers more
2022-08-29 08:47:09 -07:00
Takashi Kokubun
668b99b43b
Port gen_send_iseq to the new backend IR (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>
2022-08-29 08:47:09 -07:00
Takashi Kokubun
726a451955
Port invokebuiltin* insns to the new backend IR (https://github.com/Shopify/ruby/pull/375)
* Port invokebuiltin* insns to the new backend IR

* Fix the C_ARG_OPNDS check boundary
2022-08-29 08:47:08 -07:00
Alan Wu
8fffff536d
More concise csel with Into 2022-08-29 08:47:08 -07:00