| Age | Commit message (Collapse) | Author |
|
Notes:
Merged: https://github.com/ruby/ruby/pull/11987
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/13617
|
|
[Bug #21438]
Previously GC could trigger a table rebuild of the generic fields
st_table in the middle of calling the st_update callback. This could
cause entries to be reallocated or rearranged and the update to be for
the wrong entry.
This commit adds an assertion to make that case easier to detect, and
replaces the st_update with a separate st_lookup and st_insert.
Co-authored-by: Aaron Patterson <tenderlove@ruby-lang.org>
Co-authored-by: Jean Boussier <byroot@ruby-lang.org>
Notes:
Merged: https://github.com/ruby/ruby/pull/13589
|
|
This test was written for another implementation of `#object_id`
which had complex interations with GC, that's not the case of
the implementation that was actually merged.
|
|
If an object is shareable and has no capacity left, it isn't
safe to store the object ID in fields as it requires an object
resize which can't be done unless all field reads are synchronized.
In this very specific case we create the object_id in advance,
before the object is made shareable.
Notes:
Merged: https://github.com/ruby/ruby/pull/13609
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/13611
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/13603
|
|
Co-authored-by: Max Bernstein <tekknolagi@gmail.com>
Notes:
Merged-By: k0kubun <takashikkbn@gmail.com>
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/13531
|
|
[Bug #21439] Fix PM_SPLAT_NODE compilation error in for loops
This commit fixes a crash that occurred when using splat nodes (*) as
the index variable in for loops. The error "Unexpected node type for
index in for node: PM_SPLAT_NODE" was thrown because the compiler
didn't know how to handle splat nodes in this context.
The fix allows code like `for *x in [[1,2], [3,4]]` to compile and
execute correctly, where the splat collects each sub-array.
Notes:
Merged-By: eileencodes <eileencodes@gmail.com>
|
|
Now that class fields have been deletated to a T_IMEMO/class_fields
when we're in multi-ractor mode, we can read and write class instance
variable in an atomic way using Read-Copy-Update (RCU).
Note when in multi-ractor mode, we always use RCU. In theory
we don't need to, instead if we ensured the field is written
before the shape is updated it would be safe.
Benchmark:
```ruby
Warning[:experimental] = false
class Foo
@foo = 1
@bar = 2
@baz = 3
@egg = 4
@spam = 5
class << self
attr_reader :foo, :bar, :baz, :egg, :spam
end
end
ractors = 8.times.map do
Ractor.new do
1_000_000.times do
Foo.bar + Foo.baz * Foo.egg - Foo.spam
end
end
end
if Ractor.method_defined?(:value)
ractors.each(&:value)
else
ractors.each(&:take)
end
```
This branch vs Ruby 3.4:
```bash
$ hyperfine -w 1 'ruby --disable-all ../test.rb' './miniruby ../test.rb'
Benchmark 1: ruby --disable-all ../test.rb
Time (mean ± σ): 3.162 s ± 0.071 s [User: 2.783 s, System: 10.809 s]
Range (min … max): 3.093 s … 3.337 s 10 runs
Benchmark 2: ./miniruby ../test.rb
Time (mean ± σ): 208.7 ms ± 4.6 ms [User: 889.7 ms, System: 6.9 ms]
Range (min … max): 202.8 ms … 222.0 ms 14 runs
Summary
./miniruby ../test.rb ran
15.15 ± 0.47 times faster than ruby --disable-all ../test.rb
```
Notes:
Merged: https://github.com/ruby/ruby/pull/13594
|
|
Now that classes fields are delegated to an object with its own
shape_id, we no longer need to mark all classes as TOO_COMPLEX.
Notes:
Merged: https://github.com/ruby/ruby/pull/13595
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/13581
|
|
When we copy the table from one set to another we need to run write
barriers.
Notes:
Merged: https://github.com/ruby/ruby/pull/13558
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/13549
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/13549
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/13549
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/13549
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/13549
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/13549
|
|
Make Kernel#inspect ask which instance variables should be dumped by
the result of `#instance_variables_to_inspect`.
Co-Authored-By: Jean Boussier <byroot@ruby-lang.org>
Notes:
Merged: https://github.com/ruby/ruby/pull/13555
|
|
On a high load machine, the following test can fail.
This patch simply records the load average with `uptime`.
```
1) Failure:
TestThreadQueue#test_thr_kill [/tmp/ruby/src/trunk_gcc10/test/ruby/test_thread_queue.rb:239]:
only 165/250 done in 60 seconds.
```
|
|
I can reproduce timeout failure with the high load machine:
```
$ RUBY_MAX_CPU=100 ruby -e '100.times{Ractor.new{loop{}}}; sleep' &
$ while make test-all -o exts -o encs TESTS='ruby/gc -n /test_interrupt_in_finalizer/ --repeat-count=100'; do date; done
....
Finished(93/100) tests in 0.653434s, 1.5304 tests/s, 7.6519 assertions/s.
Finished(94/100) tests in 0.614422s, 1.6275 tests/s, 8.1377 assertions/s.
[1/1] TestGc#test_interrupt_in_finalizer = 11.08 s
1) Timeout:
TestGc#test_interrupt_in_finalizer
```
|
|
Now that we have the `heap_index` in shape flags we no longer
need `T_OBJECT` shapes.
Notes:
Merged: https://github.com/ruby/ruby/pull/13556
|
|
This is preparation to getting rid of `T_OBJECT` transitions.
By first only replicating the information it's easier to ensure
consistency.
Notes:
Merged: https://github.com/ruby/ruby/pull/13556
|
|
This helps with getting with of `SHAPE_T_OBJECT`, by ensuring
that transitions will have capacities that match the next embed size.
Notes:
Merged: https://github.com/ruby/ruby/pull/13548
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/13527
|
|
I didn't know `rb_ivar_get` existed until @Xrxr pointed me to it.
Thanks, Alan!
Notes:
Merged: https://github.com/ruby/ruby/pull/13527
|
|
* 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>
Notes:
Merged-By: k0kubun <takashikkbn@gmail.com>
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/13524
|
|
To debug flaky failures on i686 that look like:
1) Failure:
TestGc#test_heaps_grow_independently [test/ruby/test_gc.rb:704]:
Expected 2061929 to be < 2000000.
Notes:
Merged: https://github.com/ruby/ruby/pull/13140
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/13470
Merged-By: XrXr
|
|
Now all flags are only in the `shape_id_t`, and can all be checked
without needing to dereference a pointer.
Notes:
Merged: https://github.com/ruby/ruby/pull/13515
|
|
* Add newrange support to zjit
* Add RangeType enum for Range insn's flag
* Address other feedback
Notes:
Merged-By: k0kubun <takashikkbn@gmail.com>
|
|
`RUBY_DEBUG=gc_stress ./miniruby -e0` crashes because of this
marking miss.
BTW, to use `RUBY_DEBUG=gc_stress` we need to specify
`--enable-debug-env` configure option. This is why I couldn't repro
on my environments.
see c0c94ab183d0d428595ccb74ae71ee945f1afd45
Notes:
Merged: https://github.com/ruby/ruby/pull/13506
|
|
Co-authored-by: Max Bernstein <tekknolagi@gmail.com>
Co-authored-by: Alan Wu <alansi.xingwu@shopify.com>
Notes:
Merged-By: k0kubun <takashikkbn@gmail.com>
|
|
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.
Notes:
Merged: https://github.com/ruby/ruby/pull/13468
|
|
Instead `shape_id_t` higher bits contain flags, and the first one
tells whether the shape is frozen.
This has multiple benefits:
- Can check if a shape is frozen with a single bit check instead of
dereferencing a pointer.
- Guarantees it is always possible to transition to frozen.
- This allow reclaiming `FL_FREEZE` (not done yet).
The downside is you have to be careful to preserve these flags
when transitioning.
Notes:
Merged: https://github.com/ruby/ruby/pull/13289
|
|
[Bug #21394]
There are two ways to make RubyVM::InstructionSequence.new raise which
would cause the options->scopes to leak memory:
1. Passing in any (non T_FILE) object where the to_str raises.
2. Passing in a T_FILE object where String#initialize_dup raises. This is
because rb_io_path dups the string.
Example 1:
10.times do
100_000.times do
RubyVM::InstructionSequence.new(nil)
rescue TypeError
end
puts `ps -o rss= -p #{$$}`
end
Before:
13392
17104
20256
23920
27264
30432
33584
36752
40032
43232
After:
9392
11072
11648
11648
11648
11712
11712
11712
11744
11744
Example 2:
require "tempfile"
MyError = Class.new(StandardError)
String.prepend(Module.new do
def initialize_dup(_)
if $raise_on_dup
raise MyError
else
super
end
end
end)
Tempfile.create do |f|
10.times do
100_000.times do
$raise_on_dup = true
RubyVM::InstructionSequence.new(f)
rescue MyError
else
raise "MyError was not raised during RubyVM::InstructionSequence.new"
end
puts `ps -o rss= -p #{$$}`
ensure
$raise_on_dup = false
end
end
Before:
14080
18512
22000
25184
28320
31600
34736
37904
41088
44256
After:
12016
12464
12880
12880
12880
12912
12912
12912
12912
12912
Notes:
Merged: https://github.com/ruby/ruby/pull/13496
|
|
The test fails with:
TestISeq#test_loading_kwargs_memory_leak [test/ruby/test_iseq.rb:882]:
pid 18222 exit 1
| -:2:in '<main>': undefined method 'iseq_to_binary' for main (NoMethodError)
Notes:
Merged: https://github.com/ruby/ruby/pull/13494
|
|
[Bug #21370]
Notes:
Merged: https://github.com/ruby/ruby/pull/13436
|
|
```
1) Failure:
TestGc#test_gc_stress_at_startup [/home/chkbuild/chkbuild/tmp/build/20250530T213003Z/ruby/test/ruby/test_gc.rb:799]:
[Bug #15784]
pid 1748790 killed by SIGSEGV (signal 11) (core dumped).
1. [3/3] Assertion for "success?"
| Expected #<Process::Status: pid 1748790 SIGSEGV (signal 11) (core dumped)> to be success?.
```
|
|
```
1) Failure:
TestProcess#test_warmup_frees_pages [/tmp/ruby/src/trunk-random1/test/ruby/test_process.rb:2772]:
<164348> expected but was
<165985>.
```
can someone investigate it?
Notes:
Merged: https://github.com/ruby/ruby/pull/13478
|
|
* Added `Ractor::Port`
* `Ractor::Port#receive` (support multi-threads)
* `Rcator::Port#close`
* `Ractor::Port#closed?`
* Added some methods
* `Ractor#join`
* `Ractor#value`
* `Ractor#monitor`
* `Ractor#unmonitor`
* Removed some methods
* `Ractor#take`
* `Ractor.yield`
* Change the spec
* `Racotr.select`
You can wait for multiple sequences of messages with `Ractor::Port`.
```ruby
ports = 3.times.map{ Ractor::Port.new }
ports.map.with_index do |port, ri|
Ractor.new port,ri do |port, ri|
3.times{|i| port << "r#{ri}-#{i}"}
end
end
p ports.each{|port| pp 3.times.map{port.receive}}
```
In this example, we use 3 ports, and 3 Ractors send messages to them respectively.
We can receive a series of messages from each port.
You can use `Ractor#value` to get the last value of a Ractor's block:
```ruby
result = Ractor.new do
heavy_task()
end.value
```
You can wait for the termination of a Ractor with `Ractor#join` like this:
```ruby
Ractor.new do
some_task()
end.join
```
`#value` and `#join` are similar to `Thread#value` and `Thread#join`.
To implement `#join`, `Ractor#monitor` (and `Ractor#unmonitor`) is introduced.
This commit changes `Ractor.select()` method.
It now only accepts ports or Ractors, and returns when a port receives a message or a Ractor terminates.
We removes `Ractor.yield` and `Ractor#take` because:
* `Ractor::Port` supports most of similar use cases in a simpler manner.
* Removing them significantly simplifies the code.
We also change the internal thread scheduler code (thread_pthread.c):
* During barrier synchronization, we keep the `ractor_sched` lock to avoid deadlocks.
This lock is released by `rb_ractor_sched_barrier_end()`
which is called at the end of operations that require the barrier.
* fix potential deadlock issues by checking interrupts just before setting UBF.
https://bugs.ruby-lang.org/issues/21262
Notes:
Merged: https://github.com/ruby/ruby/pull/13445
|
|
[Bug #21383]
The following script leaks memory:
10.times do
20_000.times do
eval("class C; yield; end")
rescue SyntaxError
end
puts `ps -o rss= -p #{$$}`
end
Before:
16464
25536
29424
35904
39552
44576
46736
51600
56096
59824
After:
13488
16160
18240
20528
19760
21808
21680
22272
22064
22336
Notes:
Merged: https://github.com/ruby/ruby/pull/13464
|
|
Reported at https://hackerone.com/reports/3163876
Notes:
Merged: https://github.com/ruby/ruby/pull/13462
|
|
When using MN threads (such as running the test in a ractor), this test
failed because it was raising a SystemStackError: stack level too deep.
This is because the machine stack is smaller under MN threads than on
the native main thread.
Notes:
Merged: https://github.com/ruby/ruby/pull/13427
|
|
If you catch an error that was raised from a file you required in
a ractor, that error did not have its belonging reset from the main
ractor to the current ractor, so you hit assertion errors in debug
mode.
Notes:
Merged: https://github.com/ruby/ruby/pull/13428
|
|
The following error is reported repeatedly on my riscv64-linux machine, so just skipt it.
I hope someone investigate it.
```
1) Error:
TestStruct::SubStruct#test_named_structs_are_not_rooted:
Test::Unit::ProxyError: execution of Test::Unit::CoreAssertions#assert_no_memory_leak expired timeout (10 sec)
pid 1113858 killed by SIGTERM (signal 15)
| ruby 3.5.0dev (2025-05-22T21:05:12Z master 9583b7af8f) +PRISM [riscv64-linux]
|
| [7;1m1096282:1747967727.622:d70f:[mSTART={peak:453828608,size:453763072,lck:0,pin:0,hwm:9601024,rss:9601024,data:445943808,stk:135168,exe:4096,lib:7450624,pte:77824,swap:0}
| [7;1m1096282:1747967727.622:d70f:[mFINAL={peak:457502720,size:457498624,lck:0,pin:0,hwm:13312000,rss:13312000,data:449679360,stk:135168,exe:4096,lib:7450624,pte:86016,swap:0}
```
Notes:
Merged: https://github.com/ruby/ruby/pull/13422
|
|
Prior to https://github.com/ruby/ruby/commit/49b306ecb9e2e9e06e0b1590bacc5f4b38169c3c
the `optional_arg` passed from `rb_hash_update_block_i` to `tbl_update`
was a hash value (i.e. a VALUE). After that commit it changed to an
`update_call_args`.
If the block sets or changes the value, `tbl_update_modify` will set the
`arg.value` back to an actual value and we won't crash. But in the case
where the block returns the original value we end up calling
`RB_OBJ_WRITTEN` with the `update_call_args` which is not expected and
may crash.
`arg.value` appears to only be used to pass to `RB_OBJ_WRITTEN` (others
who need the `update_call_args` get it from `arg.arg`), so I don't think
it needs to be set to anything upfront. And `tbl_update_modify` will set
the `arg.value` in the cases we need the write barrier.
Notes:
Merged: https://github.com/ruby/ruby/pull/13404
|