summaryrefslogtreecommitdiff
path: root/bootstraptest
AgeCommit message (Collapse)Author
6 hoursYJIT: Fix local register mapping overflowIbrahim Awwal
Previously, local indices greater than 255 were truncated when converted to RegOpnd::Local. This could make a high-index local alias a tracked low-index local in the register mapping and produce incorrect values after compilation. Cap overflowing indices to MAX_CTX_LOCALS. RegMapping treats that index as untrackable because it is just outside the tracked local range. Fixes [Bug #22074]. Co-authored-by: Codex <199175422+chatgpt-connector[bot]@users.noreply.github.com>
34 hoursUse atomics for kwargs reference countJohn Hawthorn
Fixes [Bug #22075]
2026-05-06shapes: Rename `TOO_COMPLEX` in just `COMPLEX`Jean Boussier
The `too_` prefix wasn't consistently used and just make the thing longer for no benefit.
2026-04-30Rename `putstring` instruction as `dupstring`Jean Boussier
As well as `putchilledstring` as `dupchilledstring`. This is more consistent with similar `duparray` and `duphash` instructions and better reflect it's behavior.
2026-04-01Fix sending backtraces across ractorsJean Boussier
[Bug #21818] Currently exceptions can be sent across ractors, but because of a limitation in the TypedData API, the exception backtrace is duped as an empty backtrace. The problem is that backtraces are embedded objects, hence the classic `rb_class_alloc(klass)` API is insufficient because we need to know the size of the Backtrace object we're duping to instantiate the copy. This is worked around by changing Ractors to call `#clone` on objects rather than use `rb_obj_clone`, and to implement `Thread::Backtrace#clone` to properly clone the variable size object.
2026-03-25Revert "Skip initializing optional arguments to `nil`" and add testAlan Wu
This reverts commit 1596853428393136ee9964ad4c11b0120ed648d1. Expressions that run when the local is not given can observe the initial state of the optional parameter locals.
2026-03-19Allow reading cvars from non-main Ractors (#16308)Aaron Patterson
Today you can read instance variables from non-main Ractors, but many Rails applications use cvars, and we cannot read them. For example: ```ruby class Foo # This is NOT allowed to be read in non-main Ractors @@bar = 123 def self.bar; @@bar; end # This is allowed to be read in non-main Ractors @baz = 123 def self.baz; @baz; end end # This is OK Ractor.new { p Foo.baz }.value # Exception here Ractor.new { p Foo.bar }.value ``` This commit changes the semantics of cvars to be the same as instance variables: * It's ok to read Ractor shareable objects from the non-main Ractor * It's NOT ok to write from the non-main Ractor [Feature #21942]
2026-02-24Improve error message failing to copy procJohn Hawthorn
Previously, when passing an unshareable proc to a Ractor we would get the message: 'Ractor.new': allocator undefined for Proc (TypeError) With this change we get: 'Ractor.new': can not copy unshareable object #<Proc:0x00007f1b31713600 test.rb:2> (Ractor::Error) Which should hopefully be a little clearer about the problem and make it simpler to debug.
2026-02-20YJIT: Fix version_map use-after-free from mutable aliasing UBRandy Stauner
Multiple YJIT functions created overlapping `&'static mut IseqPayload` references by calling `get_iseq_payload()` multiple times for the same iseq. Overlapping &mut is UB in rust's aliasing model, and as consequence, we trigered use-after-free on the `version_map` Vec header due to false claims of LLVM `noalias`. This manifested as crashes in various YJIT operations (block lookup, GC marking, block removal) that dereference the stale pointer. Fix by moving `delayed_deallocation` and `get_or_create_version_list` from free functions (which each call `get_iseq_payload()` internally) to methods on `IseqPayload` that operate through `&mut self`. This lets callers obtain a single payload reference and use it for all operations without creating overlapping mutable borrows. The three fixed call sites: 1. `rb_yjit_tracing_invalidate_all` (invariants.rs): The loop called `delayed_deallocation()` which internally called `get_iseq_payload()`, creating a second `&mut` overlapping with the outer `payload` reference. Fix: call `payload.delayed_deallocation()` method instead. 2. `add_block_version` (core.rs): Called `get_or_create_version_list()` then later `get_iseq_payload()` for pages, creating two references. Fix: use a single `get_or_create_iseq_payload()` call then call the `get_or_create_version_list()` method on it for both version_map and pages access. Also adds regression tests exercising tracing invalidation with on-stack methods and suspended fibers. [alan: edited commit message] Reviewed-by: Alan Wu <alanwu@ruby-lang.org>
2026-02-18YJIT: Fix always-failing guard for `super()` in BMETHODsAlan Wu
Previously, when dealing with a `super()` nested in a block that runs as a method (through e.g. `define_method`), YJIT generated a guard that never passes leading to a misidentification of the callsite as megamorphic and an unconditional interpreter fallback. The issue was in the subroutine to find the currently running method entry. In the interpreter, this is rb_vm_frame_method_entry(). YJIT used `gen_get_lep()` to find the EP with `VM_ENV_FLAG_LOCAL`, but in case of BMETHODs, the corresponding CME is never at an EP level with `VM_ENV_FLAG_LOCAL` set. Because each block nesting level can dynamically run as either a BMETHOD or not, starting at a block and finding the first EP that has a method entry ultimately requires a search loop such as the one in rb_vm_frame_method_entry(). This patch introduces such a loop. Because `invokesuper` in a block can now work end-to-end, add check for the previously masked "implicit argument passing of super from method defined by define_method() is not supported..." condition.
2026-02-13[Bug #21551] changing the exception to be isolationerror rather than ↵Nery Campusano
argument error
2026-02-03[Bug #21669] Thoroughly implement void value expression check (prism)Earlopain
2026-01-13Add pushtoarray insn to fix segfault with forwarding + splatRandy Stauner
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
2025-12-19Extract `Test::JobServer` moduleNobuyoshi Nakada
A placeholder to handle GNU make jobserver option. spec/default.mspec didn't handle the jobserver using a FIFO.
2025-12-18Update ArgumentError message for Ractor.selectJohn Hawthorn
2025-12-16Let Ractor::IsolationError report correct constant pathDaisuke Aritomo
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-16Add the instance variable name and the module in Ractor::IsolationError (#15563)Étienne Barrié
2025-12-16Add the class variable and the class itself in Ractor::IsolationError (#15562)Étienne Barrié
2025-12-15YJIT: Bail out if proc would be stored above stack topRandy Stauner
Fixes [Bug #21266].
2025-12-12YJIT: Fix panic from overly loose filtering in identity method inliningAlan Wu
Credits to @rwstauner for noticing this issue in GH-15533.
2025-12-12YJIT: Add missing local variable type update for fallback setlocal blocksAlan Wu
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-11test_ractor.rb: old object while calling _id2refJean Boussier
2025-12-10Update Ractor warning messageJohn Hawthorn
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-09Use continuation bit in concurrent setJohn Hawthorn
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-09Test that Ractor.make_shareable mutates the original ProcBenoit Daloze
2025-12-09Fix Ractor test to not depend on the previous testBenoit Daloze
2025-12-09Fix some descriptions in bootstraptest/test_ractor.rbBenoit Daloze
2025-12-09Test that Ractor.shareable_proc keeps the original Proc intactBenoit Daloze
2025-12-08ignore Thread creation errorKoichi Sasada
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-06Fix id2ref for multi-RactorPeter Zhu
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-05Ractor.shareable_proc(&pr) should copy prKoichi Sasada
`pr` should not change on this method.
2025-12-04Adjust test to avoid bugJohn Hawthorn
2025-12-04Change bmethod defined_ractor to use id insteadJohn Hawthorn
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-05fix typo s/sharable/shareable/Koichi Sasada
2025-12-05Method and UnboundMethod can be sharableKoichi Sasada
with `RUBY_TYPED_FROZEN_SHAREABLE_NO_REC`, if the receiver object is shareable on Method objects.
2025-11-26YJIT: Abort expandarray optimization if method_missing is definedRandy Stauner
Fixes: [Bug #21707] [AW: rewrote comments] Co-authored-by: Alan Wu <alanwu@ruby-lang.org>
2025-11-25Fix live object count for multi-Ractor forkingPeter Zhu
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-20Add a Ractor test case that causes MMTk to deadlockPeter Zhu
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-18YJIT: omit single ractor mode assumption for `proc#call` (#15092)Luke Gruber
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-14YJIT: Fix stack handling in rb_str_dupJohn Hawthorn
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-10Fix bootstraptest runner driver message (#15072)Randy Stauner
This was a mistake; the code tested for RUBY_PATCHLEVEL but then instead of using it used RUBY_PLATFORM twice.
2025-11-05Skip an unstable IO test for mswinTakashi Kokubun
https://github.com/ruby/ruby/actions/runs/19107764906/job/54596244201
2025-11-05Fix ractor move of object with generic ivars (#15056)Luke Gruber
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-01Fix rescue in test_ractor.rbBenoit Daloze
2025-11-01Make the expectation more precise in Ractor.make_shareable(Proc) testBenoit Daloze
2025-11-01Fix the description and logic for the Ractor.make_shareable(Proc) testBenoit Daloze
2025-10-30Fixes [Bug #21522] eval isolation in Ractors for PrismAndre Muta
2025-10-23NameError (NoMethodError) is copyableKoichi Sasada
because ISeq is shareable now.
2025-09-24Ractor.shareable_procKoichi Sasada
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-02ZJIT: Unskip a Ractor bootstrap test (#14421)Stan Lo
ZJIT: Unskip Ractor bootstrap test