1068 Commits

Author SHA1 Message Date
Randy Stauner
1a0b356d40 Add pushtoarray insn to fix segfault with forwarding + splat
Example insns diff for `def x = [3]; def a(...) = b(*x, 2, 3, ...)`

     == disasm: #<ISeq:a@-e:1 (1,13)-(1,42)>
     local table (size: 1, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1])
     [ 1] "..."@0
     0000 putself                                                          (   1)[Ca]
     0000 putself
     0000 opt_send_without_block                 <calldata!mid:x, argc:0, FCALL|VCALL|ARGS_SIMPLE>
     0000 splatarray                             true
     0000 putobject                              2
     0000 putobject                              3
    +0000 pushtoarray                            2
     0000 getlocal_WC_0                          "..."@0
     0000 sendforward                            <calldata!mid:b, argc:1, ARGS_SPLAT|ARGS_SPLAT_MUT|FCALL|FORWARDING>, nil
     0000 leave                                  [Re]

This matches the insns produced by parse.y
2026-01-13 11:18:19 -08:00
Nobuyoshi Nakada
bfba65d8c1
Extract Test::JobServer module
A placeholder to handle GNU make jobserver option.
spec/default.mspec didn't handle the jobserver using a FIFO.
2025-12-19 13:36:42 +09:00
John Hawthorn
0c4fcdff32 Update ArgumentError message for Ractor.select 2025-12-18 16:47:35 -08:00
Daisuke Aritomo
cbcbbb2fbe Let Ractor::IsolationError report correct constant path
Before this patch, Ractor::IsolationError reported an incorrect constant
path when constant was found through `rb_const_get_0()`.

In this code, Ractor::IsolationError reported illegal access against
`M::TOPLEVEL`, where it should be `Object::TOPLEVEL`.

```ruby
TOPLEVEL = [1]

module M
  def self.f
    TOPLEVEL
  end
end

Ractor.new { M.f }.value
```

This was because `rb_const_get_0()` built the "path" part referring to
the module/class passed to it in the first place. When a constant was
found through recursive search upwards, the module/class which the
constant was found should be reported.

This patch fixes this issue by modifying rb_const_search() to take a
VALUE pointer to be filled with the module/class where the constant was
found.

[Bug #21782]
2025-12-16 17:15:59 -08:00
Étienne Barrié
aab4f6287d
Add the instance variable name and the module in Ractor::IsolationError (#15563) 2025-12-16 11:47:13 -05:00
Étienne Barrié
09a29e1312
Add the class variable and the class itself in Ractor::IsolationError (#15562) 2025-12-16 11:06:33 -05:00
Randy Stauner
9168cad4d6 YJIT: Bail out if proc would be stored above stack top
Fixes [Bug #21266].
2025-12-15 23:05:27 -05:00
Alan Wu
e1f5e61d6b YJIT: Fix panic from overly loose filtering in identity method inlining
Credits to @rwstauner for noticing this issue in GH-15533.
2025-12-12 21:23:24 -05:00
Alan Wu
2884f53519 YJIT: Add missing local variable type update for fallback setlocal blocks
Previously, the chain_depth>0 version of setlocal blocks did not
update the type of the local variable in the context. This can leave
the context with stale type information and trigger panics like in
[Bug #21772] or lead to miscompilation.

To trigger the issue, YJIT needs to see the same ISEQ before and after
environment escape and have tracked type info before the escape. To
trigger in ISEQs that do not send with a block, it probably requires
Kernel#binding or the use of include/ruby/debug.h APIs.
2025-12-12 15:29:04 -05:00
Jean Boussier
8210a11781 test_ractor.rb: old object while calling _id2ref 2025-12-11 23:25:57 +01:00
John Hawthorn
5828872ec4 Update Ractor warning message
Although the Ractor API is still experimental and may change, and there
may be some implementation issues, we should no longer say that there
are many.

Hopefully we can remove this warning entirely for Ruby 4.1
2025-12-10 16:01:27 -08:00
John Hawthorn
81fbdff8fd Use continuation bit in concurrent set
This refactors the concurrent set to examine and reserve a slot via CAS
with the hash, before then doing the same with the key.

This allows us to use an extra bit from the hash as a "continuation bit"
which marks whether we have ever probed past this key while inserting.
When that bit isn't set on deletion we can clear the field instead of
placing a tombstone.
2025-12-09 22:48:06 -08:00
Benoit Daloze
007a70a15c Test that Ractor.make_shareable mutates the original Proc 2025-12-09 00:54:24 +01:00
Benoit Daloze
4cb3a61b5e Fix Ractor test to not depend on the previous test 2025-12-09 00:54:24 +01:00
Benoit Daloze
39a3b88659 Fix some descriptions in bootstraptest/test_ractor.rb 2025-12-09 00:54:24 +01:00
Benoit Daloze
09f8b8e3ad Test that Ractor.shareable_proc keeps the original Proc intact 2025-12-09 00:54:24 +01:00
Koichi Sasada
159430e8b6 ignore Thread creation error
on resource limited environment.

```
stderr output is not empty
   bootstraptest.test_ractor.rb_2446_1412.rb:23:in 'Ractor.new': can't create Thread: Cannot allocate memory (ThreadError)
```
2025-12-08 18:41:06 +09:00
Peter Zhu
588347a088 Fix id2ref for multi-Ractor
The id2ref table needs to be under a VM lock to ensure there are no race
conditions. The following script crashes:

    o = Object.new

    ObjectSpace._id2ref(o.object_id)

    10.times.map do
      Ractor.new do
        10_000.times do
          a = Object.new
          a.object_id
        end
      end
    end.map(&:value)

With:

    [BUG] Object ID seen, but not in _id2ref table: object_id=2800 object=T_OBJECT
    ruby 4.0.0dev (2025-12-06T15:15:43Z ractor-id2ref-fix e7f9abdc91) +PRISM [x86_64-linux]

    -- Control frame information -----------------------------------------------
    c:0001 p:---- s:0003 e:000002 l:y b:---- DUMMY  [FINISH]

    -- Threading information ---------------------------------------------------
    Total ractor count: 5
    Ruby thread count for this ractor: 1

    -- C level backtrace information -------------------------------------------
    miniruby(rb_print_backtrace+0x14) [0x6047d09b2dff] vm_dump.c:1105
    miniruby(rb_vm_bugreport) vm_dump.c:1450
    miniruby(rb_bug_without_die_internal+0x5f) [0x6047d066bf57] error.c:1098
    miniruby(rb_bug) error.c:1116
    miniruby(rb_gc_get_ractor_newobj_cache+0x0) [0x6047d066c8dd] gc.c:2052
    miniruby(gc_sweep_plane+0xad) [0x6047d079276d] gc/default/default.c:3513
    miniruby(gc_sweep_page) gc/default/default.c:3605
    miniruby(gc_sweep_step) gc/default/default.c:3886
    miniruby(gc_sweep+0x1ba) [0x6047d0794cfa] gc/default/default.c:4154
    miniruby(gc_start+0xbf2) [0x6047d0796742] gc/default/default.c:6519
    miniruby(heap_prepare+0xcc) [0x6047d079748c] gc/default/default.c:2090
    miniruby(heap_next_free_page) gc/default/default.c:2305
    miniruby(newobj_cache_miss) gc/default/default.c:2412
    miniruby(newobj_alloc+0xd) [0x6047d0798ff5] gc/default/default.c:2436
    miniruby(rb_gc_impl_new_obj) gc/default/default.c:2515
    miniruby(newobj_of) gc.c:996
    miniruby(rb_wb_protected_newobj_of) gc.c:1046
    miniruby(str_alloc_embed+0x28) [0x6047d08fda18] string.c:1019
    miniruby(str_enc_new) string.c:1069
    miniruby(prep_io+0x5) [0x6047d07cda14] io.c:9305
    miniruby(prep_stdio) io.c:9347
    miniruby(rb_io_prep_stdin) io.c:9365
    miniruby(thread_start_func_2+0x77c) [0x6047d093a55c] thread.c:679
    miniruby(thread_sched_lock_+0x0) [0x6047d093aacd] thread_pthread.c:2241
    miniruby(co_start) thread_pthread_mn.c:469
2025-12-06 10:08:24 -08:00
Koichi Sasada
02cddcc2be Ractor.shareable_proc(&pr) should copy pr
`pr` should not change on this method.
2025-12-05 10:45:03 +09:00
John Hawthorn
7d9558f99b Adjust test to avoid bug 2025-12-04 13:25:45 -08:00
John Hawthorn
1d3fe2c382 Change bmethod defined_ractor to use id instead
When defining a bmethod, we recorded the current Ractor's object in the
method. However that was never marked and so could be GC'd and reused by
a future Ractor. Instead we can use the Ractor's id, which we expect to
be unique forever.

Co-authored-by: Luke Gruber <luke.gru@gmail.com>
2025-12-04 13:25:45 -08:00
Koichi Sasada
2aaea665bb fix typo s/sharable/shareable/ 2025-12-05 03:10:50 +09:00
Koichi Sasada
4c893e2ff1 Method and UnboundMethod can be sharable
with `RUBY_TYPED_FROZEN_SHAREABLE_NO_REC`,
if the receiver object is shareable on Method objects.
2025-12-05 02:28:30 +09:00
Randy Stauner
5f55c9c8fb YJIT: Abort expandarray optimization if method_missing is defined
Fixes: [Bug #21707]
[AW: rewrote comments]
Co-authored-by: Alan Wu <alanwu@ruby-lang.org>
2025-11-26 15:56:27 -05:00
Peter Zhu
8bf333a199 Fix live object count for multi-Ractor forking
Since we do not run a Ractor barrier before forking, it's possible that
another other Ractor is halfway through allocating an object during forking.
This may lead to allocated_objects_count being off by one.

For example, the following script reproduces the bug:

    100.times do |i|
      Ractor.new(i) do |j|
        10000.times do |i|
          "#{j}-#{i}"
        end
        Ractor.receive
      end
      pid = fork { GC.verify_internal_consistency }
      _, status = Process.waitpid2 pid
      raise unless status.success?
    end

We need to run with `taskset -c 1` to force it to use a single CPU core
to more consistenly reproduce the bug:

    heap_pages_final_slots: 1, total_freed_objects: 16628
    test.rb:8: [BUG] inconsistent live slot number: expect 19589, but 19588.
    ruby 4.0.0dev (2025-11-25T03:06:55Z master 55892f5994) +PRISM [x86_64-linux]

    -- Control frame information -----------------------------------------------
    c:0007 p:---- s:0029 e:000028 l:y b:---- CFUNC  :verify_internal_consistency
    c:0006 p:0004 s:0025 e:000024 l:n b:---- BLOCK  test.rb:8 [FINISH]
    c:0005 p:---- s:0022 e:000021 l:y b:---- CFUNC  :fork
    c:0004 p:0012 s:0018 E:0014c0 l:n b:---- BLOCK  test.rb:8
    c:0003 p:0024 s:0011 e:000010 l:y b:0001 METHOD <internal:numeric>:257
    c:0002 p:0005 s:0006 E:001730 l:n b:---- EVAL   test.rb:1 [FINISH]
    c:0001 p:0000 s:0003 E:001d20 l:y b:---- DUMMY  [FINISH]

    -- Ruby level backtrace information ----------------------------------------
    test.rb:1:in '<main>'
    <internal:numeric>:257:in 'times'
    test.rb:8:in 'block in <main>'
    test.rb:8:in 'fork'
    test.rb:8:in 'block (2 levels) in <main>'
    test.rb:8:in 'verify_internal_consistency'

    -- Threading information ---------------------------------------------------
    Total ractor count: 1
    Ruby thread count for this ractor: 1

    -- C level backtrace information -------------------------------------------
    ruby(rb_print_backtrace+0x14) [0x61b67ac48b60] vm_dump.c:1105
    ruby(rb_vm_bugreport) vm_dump.c:1450
    ruby(rb_bug_without_die_internal+0x5f) [0x61b67a818a28] error.c:1098
    ruby(rb_bug) error.c:1116
    ruby(gc_verify_internal_consistency_+0xbdd) [0x61b67a83d8ed] gc/default/default.c:5186
    ruby(gc_verify_internal_consistency+0x2d) [0x61b67a83d960] gc/default/default.c:5241
    ruby(rb_gc_verify_internal_consistency) gc/default/default.c:8950
    ruby(gc_verify_internal_consistency_m) gc/default/default.c:8966
    ruby(vm_call_cfunc_with_frame_+0x10d) [0x61b67a9e50fd] vm_insnhelper.c:3902
    ruby(vm_sendish+0x111) [0x61b67a9eeaf1] vm_insnhelper.c:6124
    ruby(vm_exec_core+0x84) [0x61b67aa07434] insns.def:903
    ruby(vm_exec_loop+0xa) [0x61b67a9f8155] vm.c:2811
    ruby(rb_vm_exec) vm.c:2787
    ruby(vm_yield_with_cref+0x90) [0x61b67a9fd2ea] vm.c:1865
    ruby(vm_yield) vm.c:1873
    ruby(rb_yield) vm_eval.c:1362
    ruby(rb_protect+0xef) [0x61b67a81fe6f] eval.c:1154
    ruby(rb_f_fork+0x16) [0x61b67a8e98ab] process.c:4293
    ruby(rb_f_fork) process.c:4284
2025-11-25 14:19:30 -08:00
Peter Zhu
3ec44a9995 Add a Ractor test case that causes MMTk to deadlock
This was a test case for Ractors discovered that causes MMTk to deadlock.
There is a fix for it in https://github.com/ruby/mmtk/pull/49.
2025-11-20 15:10:19 -08:00
Luke Gruber
ff2d2fc1bd
YJIT: omit single ractor mode assumption for proc#call (#15092)
The comptime receiver, which is a proc, is either shareable or from this
ractor so we don't need to assume single-ractor mode. We should never get
the "defined with an un-shareable Proc in a different ractor" error.
2025-11-18 14:24:49 -05:00
John Hawthorn
e4295bc3f7 YJIT: Fix stack handling in rb_str_dup
Previously because we did a stack_push before ccall, in some cases we
could end up pushing an uninitialized value to the VM stack when
spilling regs as part of the ccall.

Co-authored-by: Luke Gruber <luke.gru@gmail.com>
2025-11-14 09:29:09 -08:00
Randy Stauner
ddaa56d549
Fix bootstraptest runner driver message (#15072)
This was a mistake;
the code tested for RUBY_PATCHLEVEL but then
instead of using it used RUBY_PLATFORM twice.
2025-11-10 21:41:35 -08:00
Takashi Kokubun
df290e11d9 Skip an unstable IO test for mswin
https://github.com/ruby/ruby/actions/runs/19107764906/job/54596244201
2025-11-05 10:28:19 -08:00
Luke Gruber
54907db8f3
Fix ractor move of object with generic ivars (#15056)
This bug was happening only when the `id2ref` table exists. We need
to replace the generic fields before replacing the object id of the
newly moved object.

Fixes [Bug #21664]
2025-11-05 12:42:08 -05:00
Benoit Daloze
48c7f349f6 Fix rescue in test_ractor.rb 2025-11-01 20:14:42 +01:00
Benoit Daloze
94287b1e18 Make the expectation more precise in Ractor.make_shareable(Proc) test 2025-11-01 12:16:04 +01:00
Benoit Daloze
33a026fedd Fix the description and logic for the Ractor.make_shareable(Proc) test 2025-11-01 12:16:04 +01:00
Andre Muta
244a37bd53 Fixes [Bug #21522] eval isolation in Ractors for Prism 2025-10-30 09:17:58 -04:00
Koichi Sasada
024bbf5401 NameError (NoMethodError) is copyable
because ISeq is shareable now.
2025-10-23 13:08:26 +09:00
Koichi Sasada
55b1ba3bf2 Ractor.shareable_proc
call-seq:
  Ractor.sharable_proc(self: nil){} -> sharable proc

It returns shareable Proc object. The Proc object is
shareable and the self in a block will be replaced with
the value passed via `self:` keyword.

In a shareable Proc, the outer variables should
* (1) refer shareable objects
* (2) be not be overwritten

```ruby
  a = 42
  Ractor.shareable_proc{ p a }
  #=> OK

  b = 43
  Ractor.shareable_proc{ p b; b = 44 }
  #=> Ractor::IsolationError because 'b' is reassigned in the block.

  c = 44
  Ractor.shareable_proc{ p c }
  #=> Ractor::IsolationError because 'c' will be reassigned outside of the block.
  c = 45

  d = 45
  d = 46 if cond
  Ractor.shareable_proc{ p d }
  #=> Ractor::IsolationError because 'd' was reassigned outside of the block.
```

The last `d`'s case can be relaxed in a future version.

The above check will be done in a static analysis at compile time,
so the reflection feature such as `Binding#local_varaible_set`
can not be detected.

```ruby
  e = 42
  shpr = Ractor.shareable_proc{ p e } #=> OK
  binding.local_variable_set(:e, 43)
  shpr.call #=> 42 (returns captured timing value)
```

Ractor.sharaeble_lambda is also introduced.
[Feature #21550]
[Feature #21557]
2025-09-24 03:59:03 +09:00
Stan Lo
a8df3f664f
ZJIT: Unskip a Ractor bootstrap test (#14421)
ZJIT: Unskip Ractor bootstrap test
2025-09-02 10:04:37 -07:00
Koichi Sasada
f9bffff3d4 remove Ractor#take
[Feature #21262]
2025-09-01 17:34:41 +09:00
Stan Lo
c7ef8df851 Follow up cleanup for opt_(aref|aset)_with removal
Just removing some unneeded tests, outdated comments...etc.
2025-08-26 15:03:47 -07:00
Peter Zhu
fca258f97f Fix deadlock when malloc in Ractor lock
If we malloc when the current Ractor is locked, we can deadlock because
GC requires VM lock and Ractor barrier. If another Ractor is waiting on
this Ractor lock, then it will deadlock because the other Ractor will
never join the barrier.

For example, this script deadlocks:

    r = Ractor.new do
      loop do
        Ractor::Port.new
      end
    end

    100000.times do |i|
      r.send(nil)
      puts i
    end

On debug builds, it fails with this assertion error:

    vm_sync.c:75: Assertion Failed: vm_lock_enter:cr->sync.locked_by != rb_ractor_self(cr)

On non-debug builds, we can see that it deadlocks in the debugger:

    Main Ractor:
    frame #3: 0x000000010021fdc4 miniruby`rb_native_mutex_lock(lock=<unavailable>) at thread_pthread.c:115:14
    frame #4: 0x0000000100193eb8 miniruby`ractor_send0 [inlined] ractor_lock(r=<unavailable>, file=<unavailable>, line=1180) at ractor.c:73:5
    frame #5: 0x0000000100193eb0 miniruby`ractor_send0 [inlined] ractor_send_basket(ec=<unavailable>, rp=0x0000000131092840, b=0x000000011c63de80, raise_on_error=true) at ractor_sync.c:1180:5
    frame #6: 0x0000000100193eac miniruby`ractor_send0(ec=<unavailable>, rp=0x0000000131092840, obj=4, move=<unavailable>, raise_on_error=true) at ractor_sync.c:1211:5

    Second Ractor:
    frame #2: 0x00000001002208d0 miniruby`rb_ractor_sched_barrier_start [inlined] rb_native_cond_wait(cond=<unavailable>, mutex=<unavailable>) at thread_pthread.c:221:13
    frame #3: 0x00000001002208cc miniruby`rb_ractor_sched_barrier_start(vm=0x000000013180d600, cr=0x0000000131093460) at thread_pthread.c:1438:13
    frame #4: 0x000000010028a328 miniruby`rb_vm_barrier at vm_sync.c:262:13 [artificial]
    frame #5: 0x00000001000dfa6c miniruby`gc_start [inlined] rb_gc_vm_barrier at gc.c:179:5
    frame #6: 0x00000001000dfa68 miniruby`gc_start [inlined] gc_enter(objspace=0x000000013180fc00, event=gc_enter_event_start, lock_lev=<unavailable>) at default.c:6636:9
    frame #7: 0x00000001000dfa48 miniruby`gc_start(objspace=0x000000013180fc00, reason=<unavailable>) at default.c:6361:5
    frame #8: 0x00000001000e3fd8 miniruby`objspace_malloc_increase_body [inlined] garbage_collect(objspace=0x000000013180fc00, reason=512) at default.c:6341:15
    frame #9: 0x00000001000e3fa4 miniruby`objspace_malloc_increase_body [inlined] garbage_collect_with_gvl(objspace=0x000000013180fc00, reason=512) at default.c:6741:16
    frame #10: 0x00000001000e3f88 miniruby`objspace_malloc_increase_body(objspace=0x000000013180fc00, mem=<unavailable>, new_size=<unavailable>, old_size=<unavailable>, type=<unavailable>) at default.c:8007:13
    frame #11: 0x00000001000e3c44 miniruby`rb_gc_impl_malloc [inlined] objspace_malloc_fixup(objspace=0x000000013180fc00, mem=0x000000011c700000, size=12582912) at default.c:8085:5
    frame #12: 0x00000001000e3c30 miniruby`rb_gc_impl_malloc(objspace_ptr=0x000000013180fc00, size=12582912) at default.c:8182:12
    frame #13: 0x00000001000d4584 miniruby`ruby_xmalloc [inlined] ruby_xmalloc_body(size=<unavailable>) at gc.c:5128:12
    frame #14: 0x00000001000d4568 miniruby`ruby_xmalloc(size=<unavailable>) at gc.c:5118:34
    frame #15: 0x00000001001eb184 miniruby`rb_st_init_existing_table_with_size(tab=0x000000011c2b4b40, type=<unavailable>, size=<unavailable>) at st.c:559:39
    frame #16: 0x00000001001ebc74 miniruby`rebuild_table_if_necessary [inlined] rb_st_init_table_with_size(type=0x00000001004f4a78, size=524287) at st.c:585:5
    frame #17: 0x00000001001ebc5c miniruby`rebuild_table_if_necessary [inlined] rebuild_table(tab=0x000000013108e2f0) at st.c:753:19
    frame #18: 0x00000001001ebbfc miniruby`rebuild_table_if_necessary(tab=0x000000013108e2f0) at st.c:1125:9
    frame #19: 0x00000001001eba08 miniruby`rb_st_insert(tab=0x000000013108e2f0, key=262144, value=4767566624) at st.c:1143:5
    frame #20: 0x0000000100194b84 miniruby`ractor_port_initialzie [inlined] ractor_add_port(r=0x0000000131093460, id=262144) at ractor_sync.c:399:9
    frame #21: 0x0000000100194b58 miniruby`ractor_port_initialzie [inlined] ractor_port_init(rpv=4750065560, r=0x0000000131093460) at ractor_sync.c:87:5
    frame #22: 0x0000000100194b34 miniruby`ractor_port_initialzie(self=4750065560) at ractor_sync.c:103:12
2025-08-25 15:43:01 -04:00
Peter Zhu
2c7ec3d155 Fix race condition in method invalidation for Ractors
We lock the VM to invalidate method entries. However, we do not lock the
VM to call methods, so it's possible that during a method call the method
entry gets invalidated. We only check that the method entry in the callcache
is not invalidated at the beginning of the method call, which makes it
possible to have race conditions. This causes crashes like:

    vm_callinfo.h:421: Assertion Failed: vm_cc_cme:cc->klass != Qundef || !vm_cc_markable(cc)
    vm_insnhelper.c:2200: Assertion Failed: vm_lookup_cc:!METHOD_ENTRY_INVALIDATED(vm_cc_cme(ccs_cc))

This commit adds a VM barrier to method cache invalidation to ensure that
other Ractors are stopped at a safe-point before invalidating the method
entry.
2025-08-20 15:53:00 -04:00
Alan Wu
38558dd95e YJIT: Fix defined?(yield) and block_given? at top level
Previously, YJIT returned truthy for the block given query at the top
level. That's incorrect because the top level script never receives a
block, and `yield` is a syntax error there.

Inside methods, the number of hops to get from `iseq` to
`iseq->body->local_iseq` is the same as the number of
`VM_ENV_PREV_EP(ep)` hops to get to an environment with
`VM_ENV_FLAG_LOCAL`. YJIT and the interpreter both rely on this as can
be seen in get_lvar_level(). However, this identity does not hold for
the top level frame because of vm_set_eval_stack(), which sets up
`TOPLEVEL_BINDING`.

Since only methods can take a block that `yield` goes to, have ISEQs
that are the child of a non-method ISEQ return falsy for the block given
query. This fixes the issue for the top level script and is an
optimization for non-method contexts such as inside `ISEQ_TYPE_CLASS`.
2025-08-14 17:01:11 -04:00
Jean Boussier
547f111b5b Refactor vm_lookup_cc to allow lock-free lookups in RClass.cc_tbl
In multi-ractor mode, the `cc_tbl` mutations use the RCU pattern,
which allow lock-less reads.

Based on the assumption that invalidations and misses should be
increasingly rare as the process ages, locking on modification
isn't a big concern.
2025-08-01 10:42:04 +02:00
Stan Lo
4263c49d1c
YJIT: Remove a dead test for getinlinecaches (#14033)
The test was added in #5221 4 years ago but:

1. The insn it targets was removed in 2022 in #6187
2. The YJIT API `blocks_for` seems to be dropped in 2022 when it switched
   to use Rust in #5826

So this test has not been run in more than 3 years and can't be run
anymore. I think we can remove it.
2025-07-30 09:33:25 -07:00
Luke Gruber
be58cd4d7d Ractor: lock around global variable get/set
There's a global id_table `rb_global_tbl` that needs a lock (I used VM lock). In the future, we might use a lock-free rb_id_table if we create such a data structure.

Reproduction script that might crash or behave strangely:

```ruby
100.times do
  Ractor.new do
    1_000_000.times do
      $stderr
      $stdout
      $stdin
      $VERBOSE
      $stderr
      $stdout
      $stdin
      $VERBOSE
      $stderr
      $stdout
      $stdin
      $VERBOSE
    end
  end
end

$myglobal0 = nil;
$myglobal1 = nil;
  # ... vim macros to the rescue
$myglobal100000 = nil;
```
2025-07-21 15:57:44 +02:00
Luke Gruber
815eb58fce Fix btest in ractor_test.rb that can lead timeout of the test
It could also potentially lead to an out of memory error.
2025-07-17 11:21:01 -07:00
John Hawthorn
1582bd9382 Add Timeout message when bootstraptest times out 2025-07-11 10:20:50 -07:00
John Hawthorn
6c66458070 Fix rb_eSystemExit raised in Ractor
[Bug #21505]

Previously `Ractor.new { exit }.join` would hang because SystemExit was
special cased.

This commit updates this to take the same path as other exceptions,
which wraps the exception in a Ractor::RemoteError and does not end up
exiting the main Ractor. I don't know if that's what this should do, but
I think it's a reasonable behaviour as calling exit() in a Ractor is
odd.

    in 'Ractor#join': thrown by remote Ractor. (Ractor::RemoteError)
       from -e:1:in '<main>'
    in 'Kernel#exit': exit (SystemExit)
            from -e:1:in 'block in <main>'
2025-07-10 15:57:08 -07:00
John Hawthorn
365317f6ba Fix wrong GENIV WB on too_complex Ractor traversal
WBCHECK ERROR: Missed write barrier detected!
      Parent object: 0x7c4a5f1f66c0 (wb_protected: true)
        rb_obj_info_dump: 0x00007c4a5f1f66c0 T_IMEMO/<fields>
      Reference counts - snapshot: 2, writebarrier: 0, current: 2, missed: 1
      Missing reference to: 0x7b6a5f2f7010
        rb_obj_info_dump: 0x00007b6a5f2f7010 T_ARRAY/Array [E ] len: 1 (embed)
2025-07-04 14:54:49 -07:00