ruby/yjit
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
..
bindgen Get rid of rb_shape_id(rb_shape_t *) 2025-05-27 12:45:24 +02:00
src shape.c: Implement a lock-free version of get_next_shape_internal 2025-06-02 17:49:53 +02:00
.gitignore
Cargo.lock Bump capstone from 0.12.0 to 0.13.0 in /yjit 2025-02-05 11:37:34 +09:00
Cargo.toml YJIT: ZJIT: Allow both JITs in the same build 2025-05-15 00:39:03 +09:00
not_gmake.mk Define ZJIT libs for non-gmake 2025-04-18 21:52:55 +09:00
yjit.mk YJIT: ZJIT: Allow both JITs in the same build 2025-05-15 00:39:03 +09:00