Commit graph

547 commits

Author SHA1 Message Date
Alan Wu
94ba62c790 ZJIT: Fix build error from commit race 2025-06-06 23:14:51 +09:00
Alan Wu
677c36370f ZJIT: Fix insn arg index for defined, add tests 2025-06-06 22:30:17 +09:00
Alan Wu
657b2f064b ZJIT: Parse definedivar into HIR 2025-06-06 22:30:17 +09:00
Alan Wu
cd7c5a3484 ZJIT: Take a slice instead of Vec in test code
Shorter code and more efficient.
2025-06-06 22:30:17 +09:00
Max Bernstein
3246bbd325 ZJIT: Add codegen for uncached setinstancevariable 2025-06-06 16:17:54 +09:00
Max Bernstein
6a46ca31a7 ZJIT: Add codegen for uncached getinstancevariable
I didn't know `rb_ivar_get` existed until @Xrxr pointed me to it.
Thanks, Alan!
2025-06-06 16:17:54 +09:00
Shannon Skipper
43472a3001
ZJIT: Panic unimplemented for OOB basic block args (#13533) 2025-06-05 16:37:01 -07:00
Takashi Kokubun
1a991131a0
ZJIT: Pass self through basic block params (#13529)
* ZJIT: Pass self through basic block params

Co-authored-by: Max Bernstein <tekknolagi@gmail.com>

* Add comments for self

* Use self_param for ivar

* Make self_param a loop local

* Fix rest parameter type check

* Push self_param first

* Add a test case for putself

* Use SELF_PARAM_IDX

Co-authored-by: Max Bernstein <tekknolagi@gmail.com>

* Fix test_unknown

---------

Co-authored-by: Max Bernstein <tekknolagi@gmail.com>
2025-06-05 14:48:04 -07:00
Jean Boussier
4e39580992 Refactor raw accesses to rb_shape_t.capacity 2025-06-05 22:06:15 +02:00
Jean Boussier
772fc1f187 Get rid of rb_shape_t.flags
Now all flags are only in the `shape_id_t`, and can all be checked
without needing to dereference a pointer.
2025-06-05 07:44:44 +02:00
Stan Lo
111986f8b0
ZJIT: Add newrange support (#13505)
* Add newrange support to zjit

* Add RangeType enum for Range insn's flag

* Address other feedback
2025-06-04 18:51:53 -07:00
Takashi Kokubun
112c34252d
ZJIT: Implement side exits for entry frames (#13469)
Co-authored-by: Max Bernstein <tekknolagi@gmail.com>
Co-authored-by: Alan Wu <alansi.xingwu@shopify.com>
2025-06-04 14:14:40 -07:00
Stan Lo
a87b089349
ZJIT: Fix incorrect method name in test for Array#size 2025-06-04 20:14:44 +09:00
Jean Boussier
675f33508c Get rid of TOO_COMPLEX shape type
Instead it's now a `shape_id` flag.

This allows to check if an object is complex without having
to chase the `rb_shape_t` pointer.
2025-06-04 13:13:50 +02:00
Alan Wu
8d14d6ea2d ZJIT: Spill to the stack using arguments instead of FrameState
The FrameState on the SendWithoutBlock represents the entry state,
but for instructions that push to the stack in the middle of the
instruction before actually doing the send like opt_aref_with,
the FrameState is incorrect. We need to write to the stack using the
arguments for the instruction.
2025-06-04 06:23:30 -04:00
Alan Wu
6f0f84e5dd ZJIT: Parse opt_aref_with into HIR 2025-06-04 06:23:30 -04:00
Jean Boussier
e27404af9e Use all 32bits of shape_id_t on all platforms
Followup: https://github.com/ruby/ruby/pull/13341 / [Feature #21353]

Even thought `shape_id_t` has been make 32bits, we were still limited
to use only the lower 16 bits because they had to fit alongside `attr_index_t`
inside a `uintptr_t` in inline caches.

By enlarging inline caches we can unlock the full 32bits on all
platforms, allowing to use these extra bits for tagging.
2025-06-03 21:15:41 +02:00
Jean Boussier
e9fd44dd72 shape.c: Implement a lock-free version of get_next_shape_internal
Whenever we run into an inline cache miss when we try to set
an ivar, we may need to take the global lock, just to be able to
lookup inside `shape->edges`.

To solve that, when we're in multi-ractor mode, we can treat
the `shape->edges` as immutable. When we need to add a new
edge, we first copy the table, and then replace it with
CAS.

This increases memory allocations, however we expect that
creating new transitions becomes increasingly rare over time.

```ruby
class A
  def initialize(bool)
    @a = 1
    if bool
      @b = 2
    else
      @c = 3
    end
  end

  def test
    @d = 4
  end
end

def bench(iterations)
  i = iterations
  while i > 0
    A.new(true).test
    A.new(false).test
    i -= 1
  end
end

if ARGV.first == "ractor"
  ractors = 8.times.map do
    Ractor.new do
      bench(20_000_000 / 8)
    end
  end
  ractors.each(&:take)
else
  bench(20_000_000)
end
```

The above benchmark takes 27 seconds in Ractor mode on Ruby 3.4,
and only 1.7s with this branch.

Co-Authored-By: Étienne Barrié <etienne.barrie@gmail.com>
2025-06-02 17:49:53 +02:00
Tavian Barnes
f8db23afe5
ZJIT: Fold more fixnum operations (#13465) 2025-05-30 10:27:00 -04:00
Max Bernstein
65e9791c55
ZJIT: Assert that we're compiling a specific YARV insn to HIR (#13471) 2025-05-30 10:23:26 -04:00
Max Bernstein
9a1d6cc799
ZJIT: Add CallableMethodEntry to type lattice (GH-13459)
This will be useful when we split Send into Lookup+Call.
For reasoning about various method types during optimization.
2025-05-28 20:59:51 +00:00
John Hawthorn
d1343e12d2 Use flag for RCLASS_IS_INITIALIZED
Previously we used a flag to set whether a module was uninitialized.
When checked whether a class was initialized, we first had to check that
it had a non-zero superclass, as well as that it wasn't BasicObject.

With the advent of namespaces, RCLASS_SUPER is now an expensive
operation, and though we could just check for the prime superclass, we
might as well take this opportunity to use a flag so that we can perform
the initialized check with as few instructions as possible.

It's possible in the future that we could prevent uninitialized classes
from being available to the user, but currently there are a few ways to
do that.
2025-05-28 11:44:07 -04:00
Jean Boussier
a59835e1d5 Refactor rb_shape_get_iv_index to take a shape_id_t
Further reduce exposure of `rb_shape_t`.
2025-05-27 15:34:02 +02:00
Jean Boussier
e535f8248b Get rid of rb_shape_id(rb_shape_t *)
We should avoid conversions from `rb_shape_t *` into `shape_id_t`
outside of `shape.c` as the short term goal is to have `shape_id_t`
contain tags.
2025-05-27 12:45:24 +02:00
Max Bernstein
87d340f0e1 ZJIT: Parse branchnil into HIR 2025-05-23 16:31:28 -07:00
Max Bernstein
fa474a41e8 ZJIT: Parse opt_aref into HIR 2025-05-23 16:31:28 -07:00
Max Bernstein
5905f71a34 ZJIT: Add fast-paths for Array#length and Array#size 2025-05-23 16:31:28 -07:00
Max Bernstein
75b92c5cd6 ZJIT: Implement find for Defined 2025-05-23 13:32:49 -07:00
Max Bernstein
15618b7707 ZJIT: Mark SideExit as terminator 2025-05-23 13:32:49 -07:00
Max Bernstein
d23fe287b6 ZJIT: Side-exit into the interpreter on unknown call types 2025-05-23 13:32:49 -07:00
Max Bernstein
a0df4cf6f1 ZJIT: Side-exit into the interpreter on unknown opt_newarray_send 2025-05-23 13:32:49 -07:00
Max Bernstein
0c29ff8e8f ZJIT: Side-exit into the interpreter on unknown opcodes
No need to bail out of compilation completely; we can compile all the
code up until that point.
2025-05-23 13:32:49 -07:00
Max Bernstein
b7e751181e
ZJIT: Parse splatarray, concattoarray, pushtoarray into HIR (#13429) 2025-05-23 11:43:17 -07:00
Alan Wu
54bed7e257 [DOC] ZJIT: Function::find: Give advice instead of talking about safety
Co-Authored-By: Max Bernstein <max.bernstein@shopify.com>
2025-05-23 23:51:14 +09:00
Max Bernstein
9583b7af8f ZJIT: Parse newhash into HIR 2025-05-22 14:05:12 -07:00
Max Bernstein
f1fe3d809f ZJIT: Parse duphash into HIR 2025-05-22 14:05:12 -07:00
Max Bernstein
5a3f3f0917
ZJIT: Parse getinstancevariable, setinstancevariable into HIR (#13413) 2025-05-22 11:51:05 -07:00
Alan Wu
b4c900debd ZJIT: More type level docs in zjit::hir [DOC]
Given `InsnId` is at the top of the file and everywhere, hopefully this
will help first time readers.
2025-05-22 00:23:19 +09:00
Max Bernstein
b08e20d34a
ZJIT: Allow DCE to remove some CCalls (#13363)
Allow DCE to remove some CCalls

Add `elidable` field that signals that there would be no discernible
effect if the call to the method were removed. The default is false.
2025-05-20 15:41:37 -07:00
Alan Wu
1fed568e3e ZJIT: Add --allow-multiple-definition for make zjit-test 2025-05-21 01:22:55 +09:00
Max Bernstein
d9248856d2
ZJIT: Create more ergonomic type profiling API (#13339) 2025-05-16 10:50:48 -07:00
Max Bernstein
5e01c0e4e2 ZJIT: Remove unnecessary cloning 2025-05-16 21:08:01 +09:00
Max Bernstein
6b10d40157 ZJIT: Bail out of recursive compilation if we can't compile callee
Right now we just crash if we can't compile an ISEQ for any reason
(unimplemented in HIR, unimplemented in codegen, ...) and this fixes
that by bailing out.
2025-05-15 15:31:02 -07:00
Alan Wu
92b218fbc3 YJIT: ZJIT: Allow both JITs in the same build
This commit allows building YJIT and ZJIT simultaneously, a "combo
build". Previously, `./configure --enable-yjit --enable-zjit` failed. At
runtime, though, only one of the two can be enabled at a time.

Add a root Cargo workspace that contains both the yjit and zjit crate.
The common Rust build integration mechanisms are factored out into
defs/jit.mk.

Combo YJIT+ZJIT dev builds are supported; if either JIT uses
`--enable-*=dev`, both of them are built in dev mode.

The combo build requires Cargo, but building one JIT at a time with only
rustc in release build remains supported.
2025-05-15 00:39:03 +09:00
Alan Wu
920dc0fe3a ZJIT: Split long use line and add a module doc. 2025-05-14 20:13:26 +09:00
Alan Wu
4eff1727e3 ZJIT: More tests for parsing param forms 2025-05-14 20:13:26 +09:00
Alan Wu
37d6de5331 ZJIT: Infer ArrayExact for the rest parameter
The rest parameter is always a rb_cArray, even when anonymous. (This is
different from kw_rest, which can be nil.)
2025-05-14 20:13:26 +09:00
Alan Wu
767e8e165a ZJIT: Fix rest parameter not parsed into a BB parameter
Use total parameter size instead of lead parameter size when parsing
iseq into hir. Also, copy over IntoUsize for compile-time checked
u32->usize cast.
2025-05-14 20:13:26 +09:00
Alan Wu
074dce8370 ZJIT: Add IntoUsize, ported from YJIT 2025-05-14 20:13:26 +09:00
Takashi Kokubun
0b6cee7329
ZJIT: Stop padding side exits (#13295) 2025-05-12 08:57:15 -07:00