<feed xmlns='http://www.w3.org/2005/Atom'>
<title>ruby.git/vm_core.h, branch v4.0.3</title>
<subtitle>The Ruby Programming Language</subtitle>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/'/>
<entry>
<title>YJIT: Support calling bmethods in Ractors</title>
<updated>2025-12-18T21:43:45+00:00</updated>
<author>
<name>John Hawthorn</name>
<email>john@hawthorn.email</email>
</author>
<published>2025-12-17T20:08:43+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=345ea0c8e18d3ce8fed332137d225769df619f2b'/>
<id>345ea0c8e18d3ce8fed332137d225769df619f2b</id>
<content type='text'>
Co-authored-by: Luke Gruber &lt;luke.gru@gmail.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Co-authored-by: Luke Gruber &lt;luke.gru@gmail.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>Store ractor_id directly on EC</title>
<updated>2025-12-18T21:43:45+00:00</updated>
<author>
<name>John Hawthorn</name>
<email>john@hawthorn.email</email>
</author>
<published>2025-12-17T20:12:17+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=63b082cf0e87942dcea28cbdeb1c8a9e616e903a'/>
<id>63b082cf0e87942dcea28cbdeb1c8a9e616e903a</id>
<content type='text'>
This is easier to access as ec-&gt;ractor_id instead of pointer-chasing through
ec-&gt;thread-&gt;ractor-&gt;ractor_id

Co-authored-by: Luke Gruber &lt;luke.gru@gmail.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
This is easier to access as ec-&gt;ractor_id instead of pointer-chasing through
ec-&gt;thread-&gt;ractor-&gt;ractor_id

Co-authored-by: Luke Gruber &lt;luke.gru@gmail.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>Make tracepoints with set_trace_func or TracePoint.new ractor local (#15468)</title>
<updated>2025-12-16T19:06:55+00:00</updated>
<author>
<name>Luke Gruber</name>
<email>luke.gruber@shopify.com</email>
</author>
<published>2025-12-16T19:06:55+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=4fb537b1ee28bb37dbe551ac65c279d436c756bc'/>
<id>4fb537b1ee28bb37dbe551ac65c279d436c756bc</id>
<content type='text'>
Before this change, GC'ing any Ractor object caused you to lose all
enabled tracepoints across all ractors (even main). Now tracepoints are
ractor-local and this doesn't happen. Internal events are still global.

Fixes [Bug #19112]</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Before this change, GC'ing any Ractor object caused you to lose all
enabled tracepoints across all ractors (even main). Now tracepoints are
ractor-local and this doesn't happen. Internal events are still global.

Fixes [Bug #19112]</pre>
</div>
</content>
</entry>
<entry>
<title>Rename fiber_serial into ec_serial</title>
<updated>2025-12-16T08:51:07+00:00</updated>
<author>
<name>Jean Boussier</name>
<email>jean.boussier@gmail.com</email>
</author>
<published>2025-12-15T23:43:41+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=e42bcd7ce76e75601ef3adf35467edf277471af2'/>
<id>e42bcd7ce76e75601ef3adf35467edf277471af2</id>
<content type='text'>
Since it now live in the EC.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Since it now live in the EC.
</pre>
</div>
</content>
</entry>
<entry>
<title>Store the fiber_serial in the EC to allow inlining</title>
<updated>2025-12-16T08:51:07+00:00</updated>
<author>
<name>Jean Boussier</name>
<email>jean.boussier@gmail.com</email>
</author>
<published>2025-12-14T09:46:52+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=28b195fc67788c03be59c2a4cbf0cad52ac3b90f'/>
<id>28b195fc67788c03be59c2a4cbf0cad52ac3b90f</id>
<content type='text'>
Mutexes spend a significant amount of time in `rb_fiber_serial`
because it can't be inlined (except with LTO).
The fiber struct is opaque the so function can't be defined as inlineable.

Ideally the while fiber struct would not be opaque to the rest of
Ruby core, but it's tricky to do.

Instead we can store the fiber serial in the execution context
itself, and make its access cheaper:

```
$ hyperfine './miniruby-baseline --yjit /tmp/mut.rb' './miniruby-inline-serial --yjit /tmp/mut.rb'
Benchmark 1: ./miniruby-baseline --yjit /tmp/mut.rb
  Time (mean ± σ):      4.011 s ±  0.084 s    [User: 3.977 s, System: 0.011 s]
  Range (min … max):    3.950 s …  4.245 s    10 runs

Benchmark 2: ./miniruby-inline-serial --yjit /tmp/mut.rb
  Time (mean ± σ):      3.495 s ±  0.150 s    [User: 3.448 s, System: 0.009 s]
  Range (min … max):    3.340 s …  3.869 s    10 runs

Summary
  ./miniruby-inline-serial --yjit /tmp/mut.rb ran
    1.15 ± 0.05 times faster than ./miniruby-baseline --yjit /tmp/mut.rb
```

```ruby
i = 10_000_000
mut = Mutex.new
while i &gt; 0
  i -= 1
  mut.synchronize { }
  mut.synchronize { }
  mut.synchronize { }
  mut.synchronize { }
  mut.synchronize { }
  mut.synchronize { }
  mut.synchronize { }
  mut.synchronize { }
  mut.synchronize { }
  mut.synchronize { }
end
```
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Mutexes spend a significant amount of time in `rb_fiber_serial`
because it can't be inlined (except with LTO).
The fiber struct is opaque the so function can't be defined as inlineable.

Ideally the while fiber struct would not be opaque to the rest of
Ruby core, but it's tricky to do.

Instead we can store the fiber serial in the execution context
itself, and make its access cheaper:

```
$ hyperfine './miniruby-baseline --yjit /tmp/mut.rb' './miniruby-inline-serial --yjit /tmp/mut.rb'
Benchmark 1: ./miniruby-baseline --yjit /tmp/mut.rb
  Time (mean ± σ):      4.011 s ±  0.084 s    [User: 3.977 s, System: 0.011 s]
  Range (min … max):    3.950 s …  4.245 s    10 runs

Benchmark 2: ./miniruby-inline-serial --yjit /tmp/mut.rb
  Time (mean ± σ):      3.495 s ±  0.150 s    [User: 3.448 s, System: 0.009 s]
  Range (min … max):    3.340 s …  3.869 s    10 runs

Summary
  ./miniruby-inline-serial --yjit /tmp/mut.rb ran
    1.15 ± 0.05 times faster than ./miniruby-baseline --yjit /tmp/mut.rb
```

```ruby
i = 10_000_000
mut = Mutex.new
while i &gt; 0
  i -= 1
  mut.synchronize { }
  mut.synchronize { }
  mut.synchronize { }
  mut.synchronize { }
  mut.synchronize { }
  mut.synchronize { }
  mut.synchronize { }
  mut.synchronize { }
  mut.synchronize { }
  mut.synchronize { }
end
```
</pre>
</div>
</content>
</entry>
<entry>
<title>move th-&gt;event_serial to rb_thread_sched_item (#15500)</title>
<updated>2025-12-12T19:24:40+00:00</updated>
<author>
<name>Luke Gruber</name>
<email>luke.gruber@shopify.com</email>
</author>
<published>2025-12-12T19:24:40+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=7909ce2a839ba1c3e134239189e6aa2de3b6b630'/>
<id>7909ce2a839ba1c3e134239189e6aa2de3b6b630</id>
<content type='text'>
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
</pre>
</div>
</content>
</entry>
<entry>
<title>Fix typos in comment of rb_current_execution_context()</title>
<updated>2025-12-10T11:42:33+00:00</updated>
<author>
<name>Benoit Daloze</name>
<email>eregontp@gmail.com</email>
</author>
<published>2025-12-10T11:42:33+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=2b66fc763a6657c9a25719c5f70ae7b66abc2232'/>
<id>2b66fc763a6657c9a25719c5f70ae7b66abc2232</id>
<content type='text'>
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
</pre>
</div>
</content>
</entry>
<entry>
<title>Register internal tracepoints globally</title>
<updated>2025-12-09T00:38:45+00:00</updated>
<author>
<name>John Hawthorn</name>
<email>john@hawthorn.email</email>
</author>
<published>2025-12-03T08:06:03+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=de94f88c6820c94b69df3343c6050cdb8cc0610e'/>
<id>de94f88c6820c94b69df3343c6050cdb8cc0610e</id>
<content type='text'>
Internal tracepoints only make sense to run globally, and they already
took completely different paths.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Internal tracepoints only make sense to run globally, and they already
took completely different paths.
</pre>
</div>
</content>
</entry>
<entry>
<title>Fix thread scheduler issue with thread_sched_wait_events (#15392)</title>
<updated>2025-12-04T21:51:11+00:00</updated>
<author>
<name>Luke Gruber</name>
<email>luke.gruber@shopify.com</email>
</author>
<published>2025-12-04T21:51:11+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=8d8159e7d87e4fd1594ce2fad3d2653e47fb1026'/>
<id>8d8159e7d87e4fd1594ce2fad3d2653e47fb1026</id>
<content type='text'>
Fix race between timer thread dequeuing waiting thread and thread
skipping sleeping due to being dequeued. We now use `th-&gt;event_serial` which
is protected by `thread_sched_lock`. When a thread is put on timer thread's waiting
list, the event serial is saved on the item. The timer thread checks
that the saved serial is the same as current thread's serial before
calling `thread_sched_to_ready`.

The following script (taken from a test in `test_thread.rb` used to crash on
scheduler debug assertions. It would likely crash in non-debug mode as well.

```ruby
def assert_nil(val)
  if val != nil
    raise "Expected #{val} to be nil"
  end
end

def assert_equal(expected, actual)
  if expected != actual
    raise "Expected #{expected} to be #{actual}"
  end
end

def test_join2
  ok = false
  t1 = Thread.new { ok = true; sleep }
  Thread.pass until ok
  Thread.pass until t1.stop?
  t2 = Thread.new do
    Thread.pass while ok
    t1.join(0.01)
  end
  t3 = Thread.new do
    ok = false
    t1.join
  end
  assert_nil(t2.value)
  t1.wakeup
  assert_equal(t1, t3.value)
ensure
  t1&amp;.kill&amp;.join
  t2&amp;.kill&amp;.join
  t3&amp;.kill&amp;.join
end

rs = 30.times.map do
  Ractor.new do
    test_join2
  end
end
rs.each(&amp;:join)
```</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Fix race between timer thread dequeuing waiting thread and thread
skipping sleeping due to being dequeued. We now use `th-&gt;event_serial` which
is protected by `thread_sched_lock`. When a thread is put on timer thread's waiting
list, the event serial is saved on the item. The timer thread checks
that the saved serial is the same as current thread's serial before
calling `thread_sched_to_ready`.

The following script (taken from a test in `test_thread.rb` used to crash on
scheduler debug assertions. It would likely crash in non-debug mode as well.

```ruby
def assert_nil(val)
  if val != nil
    raise "Expected #{val} to be nil"
  end
end

def assert_equal(expected, actual)
  if expected != actual
    raise "Expected #{expected} to be #{actual}"
  end
end

def test_join2
  ok = false
  t1 = Thread.new { ok = true; sleep }
  Thread.pass until ok
  Thread.pass until t1.stop?
  t2 = Thread.new do
    Thread.pass while ok
    t1.join(0.01)
  end
  t3 = Thread.new do
    ok = false
    t1.join
  end
  assert_nil(t2.value)
  t1.wakeup
  assert_equal(t1, t3.value)
ensure
  t1&amp;.kill&amp;.join
  t2&amp;.kill&amp;.join
  t3&amp;.kill&amp;.join
end

rs = 30.times.map do
  Ractor.new do
    test_join2
  end
end
rs.each(&amp;:join)
```</pre>
</div>
</content>
</entry>
<entry>
<title>Add `rb_ec_close` function to manage execution context cleanup. (#15253)</title>
<updated>2025-12-01T04:49:31+00:00</updated>
<author>
<name>Samuel Williams</name>
<email>samuel.williams@shopify.com</email>
</author>
<published>2025-12-01T04:49:31+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=bc9ea585bee075480b4f12f84c8ab99315766595'/>
<id>bc9ea585bee075480b4f12f84c8ab99315766595</id>
<content type='text'>
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
</pre>
</div>
</content>
</entry>
</feed>
