Age | Commit message (Collapse) | Author |
|
Notes:
Merged-By: ioquatix <[email protected]>
|
|
Originally, if a class was defined with the class keyword, the cref had a
const_added callback, and the superclass an inherited callback, const_added was
called first, and inherited second.
This was discussed in
https://bugs.ruby-lang.org/issues/21143
and an attempt at changing this order was made.
While both constant assignment and inheritance have happened before these
callbacks are invoked, it was deemed nice to have the same order as in
C = Class.new
This was mostly for alignment: In that last use case things happen at different
times and therefore the order of execution is kind of obvious, whereas when the
class keyword is involved, the order is opaque to the user and it is up to the
interpreter.
However, soon in
https://bugs.ruby-lang.org/issues/21193
Matz decided to play safe and keep the existing order.
This reverts commits:
de097fbe5f3df105bd2a26e72db06b0f5139bc1a
de48e47ddf78aba02fd9623bc7ce685540a10743
Notes:
Merged: https://github.com/ruby/ruby/pull/13085
|
|
Using `rb_obj_clone` introduce other problems, such as `initialize_*`
callbacks invocation in the context of the parent ractor.
So we can revert back to copy the content of the object slots,
but in a way that is aware of size pools.
Notes:
Merged: https://github.com/ruby/ruby/pull/13070
|
|
[Bug #20271]
[Bug #20267]
[Bug #20255]
`rb_obj_alloc(RBASIC_CLASS(obj))` will always allocate from the basic
40B pool, so if `obj` is larger than `40B`, we'll create a corrupted
object when we later copy the shape_id.
Instead we can use the same logic than ractor copy, which is
to use `rb_obj_clone`, and later ask the GC to free the original
object.
We then must turn it into a `T_OBJECT`, because otherwise
just changing its class to `RactorMoved` leaves a lot of
ways to keep using the object, e.g.:
```
a = [1, 2, 3]
Ractor.new{}.send(a, move: true)
[].concat(a) # Should raise, but wasn't.
```
If it turns out that `rb_obj_clone` isn't performant enough
for some uses, we can always have carefully crafted specialized
paths for the types that would benefit from it.
Notes:
Merged: https://github.com/ruby/ruby/pull/13008
|
|
[Feature #21109]
By always freezing when setting the global rb_rs variable, we can ensure
it is not modified and can be accessed from a ractor.
We're also making sure it's an instance of String and does not have any
instance variables.
Of course, if $/ is changed at runtime, it may cause surprising behavior
but doing so is deprecated already anyway.
Co-authored-by: Jean Boussier <[email protected]>
Notes:
Merged: https://github.com/ruby/ruby/pull/12975
|
|
[Misc #21143]
[Bug #21193]
The previous change caused a backward compatibility issue with code
that called `Object.const_source_location` from the `inherited` callback.
To fix this, the order is now:
- Define the constant
- Invoke `inherited`
- Invoke `const_set`
Notes:
Merged: https://github.com/ruby/ruby/pull/12956
|
|
The content depends on ruby internal, not responsibility of the
caller. Revive `RUBY_GLOBAL_SETUP` macro to define the hook function.
Notes:
Merged: https://github.com/ruby/ruby/pull/12933
|
|
In gsub is used with a string replacement or a map that doesn't
have a default proc, we know for sure no code can cause the MatchData
to escape the `gsub` call.
In such case, we still have to allocate a new MatchData because we
don't know what is the lifetime of the backref, but for any subsequent
match we can re-use the MatchData we allocated ourselves, reducing
allocations significantly.
This partially fixes [Misc #20652], except when a block is used,
and partially reduce the performance impact of
abc0304cb28cb9dcc3476993bc487884c139fd11 / [Bug #17507]
```
compare-ruby: ruby 3.5.0dev (2025-02-24T09:44:57Z master 5cf146399f) +PRISM [arm64-darwin24]
built-ruby: ruby 3.5.0dev (2025-02-24T10:58:27Z gsub-elude-match da966636e9) +PRISM [arm64-darwin24]
warming up....
| |compare-ruby|built-ruby|
|:----------------|-----------:|---------:|
|escape | 3.577k| 3.697k|
| | -| 1.03x|
|escape_bin | 5.869k| 6.743k|
| | -| 1.15x|
|escape_utf8 | 3.448k| 3.738k|
| | -| 1.08x|
|escape_utf8_bin | 6.361k| 7.267k|
| | -| 1.14x|
```
Co-Authored-By: Étienne Barrié <[email protected]>
|
|
This function replaces the internal rb_obj_gc_flags API. rb_gc_object_metadata
returns an array of name and value pairs, with the last element having
0 for the name.
Notes:
Merged: https://github.com/ruby/ruby/pull/12777
|
|
If the TZ environment variable is not set, the time zone names
retrieved from the system are localized for UI display and may vary
across editions and language packs for the same time zone.
Use the time zone IDs that are invariant across environments instead.
Notes:
Merged: https://github.com/ruby/ruby/pull/12765
|
|
The instruction counter is slowing multi-Ractor applications. I had
changed it to use a thread local, but using a thread local is slowing
single threaded applications. This commit only enables the instruction
counter in YJIT stats builds until we can figure out a way to gather the
information with lower overhead.
Co-authored-by: Randy Stauner <[email protected]>
Notes:
Merged: https://github.com/ruby/ruby/pull/12670
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/12740
|
|
If the provided Hash doesn't have a default proc, we know for
sure that we'll never call into user provided code, hence the
string we allocate to access the Hash can't possibly escape.
So we don't actually have to allocate it, we can use a fake_str,
AKA a stack allocated string.
```
compare-ruby: ruby 3.5.0dev (2025-02-10T13:47:44Z master 3fb455adab) +PRISM [arm64-darwin23]
built-ruby: ruby 3.5.0dev (2025-02-10T17:09:52Z opt-gsub-alloc ea5c28958f) +PRISM [arm64-darwin23]
warming up....
| |compare-ruby|built-ruby|
|:----------------|-----------:|---------:|
|escape | 3.374k| 3.722k|
| | -| 1.10x|
|escape_bin | 5.469k| 6.587k|
| | -| 1.20x|
|escape_utf8 | 3.465k| 3.734k|
| | -| 1.08x|
|escape_utf8_bin | 5.752k| 7.283k|
| | -| 1.27x|
```
Notes:
Merged: https://github.com/ruby/ruby/pull/12730
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/12711
|
|
The `ids` array and `dsymbol_fstr_hash` were pinned because they were
kept alive by rb_vm_register_global_object. This prevented the GC from
moving them even though there were reference updating code.
This commit changes it to be marked movable by marking it as a root object.
Notes:
Merged: https://github.com/ruby/ruby/pull/12711
|
|
We can use rb_gc_vm_weak_table_foreach for reference updating of weak tables
in the default GC.
Notes:
Merged: https://github.com/ruby/ruby/pull/12629
|
|
Previously, generic ivars worked differently than the other global tables
during compaction. The other global tables had their references updated
through iteration during rb_gc_update_vm_references. Generic ivars updated
the keys when the object moved and updated the values while reference
updating the object. This is inefficient as this required one lookup for
every moved object and one lookup for every object with generic ivars.
Instead, this commit changes it to iterate over the generic ivar table to
update both the keys and values.
Notes:
Merged: https://github.com/ruby/ruby/pull/12607
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/12566
|
|
`rb_vm_insns_count` is a global variable used for reporting YJIT
statistics. It is a counter that tallies the number of interpreter
instructions that have been executed, this way we can approximate how
much time we're spending in YJIT compared to the interpreter.
Unfortunately keeping this statistic means that every instruction
executed in the interpreter loop must increment the counter. Normally
this isn't a problem, but in multi-threaded situations (when Ractors are
used), incrementing this counter can become quite costly due to page
caching issues.
Additionally, since there is no locking when incrementing this global,
the count can't really make sense in a multi-threaded environment.
This commit changes `rb_vm_insns_count` to a thread local. That way each
Ractor has it's own copy of the counter and incrementing the counter
becomes quite cheap. Of course this means that in multi-threaded
situations, the value doesn't really make sense (but it didn't make
sense before because of the lack of locking).
The counter is used for YJIT statistics, and since YJIT is basically
disabled when Ractors are in use, I don't think we care about
inaccuracies (for the time being). We can revisit this counter when we
give YJIT multi-threading support, but for the time being this commit
restores multi-threaded performance.
To test this, I used the benchmark in [Bug #20489].
Here is the performance on Ruby 3.2:
```
$ time RUBY_MAX_CPU=12 ./miniruby -v ../test.rb 8 8
ruby 3.2.0 (2022-12-25 revision a528908271) [x86_64-linux]
[0...1, 1...2, 2...3, 3...4, 4...5, 5...6, 6...7, 7...8]
../test.rb:43: warning: Ractor is experimental, and the behavior may change in future versions of Ruby! Also there are many implementation issues.
________________________________________________________
Executed in 2.53 secs fish external
usr time 19.86 secs 370.00 micros 19.86 secs
sys time 0.02 secs 320.00 micros 0.02 secs
```
We can see the regression in performance on the master branch:
```
$ time RUBY_MAX_CPU=12 ./miniruby -v ../test.rb 8 8
ruby 3.5.0dev (2025-01-10T16:22:26Z master 4a2702dafb) +PRISM [x86_64-linux]
[0...1, 1...2, 2...3, 3...4, 4...5, 5...6, 6...7, 7...8]
../test.rb:43: warning: Ractor is experimental, and the behavior may change in future versions of Ruby! Also there are many implementation issues.
________________________________________________________
Executed in 24.87 secs fish external
usr time 195.55 secs 0.00 micros 195.55 secs
sys time 0.00 secs 716.00 micros 0.00 secs
```
Here are the stats after this commit:
```
$ time RUBY_MAX_CPU=12 ./miniruby -v ../test.rb 8 8
ruby 3.5.0dev (2025-01-10T20:37:06Z tl 3ef0432779) +PRISM [x86_64-linux]
[0...1, 1...2, 2...3, 3...4, 4...5, 5...6, 6...7, 7...8]
../test.rb:43: warning: Ractor is experimental, and the behavior may change in future versions of Ruby! Also there are many implementation issues.
________________________________________________________
Executed in 2.46 secs fish external
usr time 19.34 secs 381.00 micros 19.34 secs
sys time 0.01 secs 321.00 micros 0.01 secs
```
[Bug #20489]
Notes:
Merged: https://github.com/ruby/ruby/pull/12549
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/12546
|
|
This would allow imemo to take advantage of VWA and allocate sizes larger
than RVALUE (40 bytes).
Notes:
Merged: https://github.com/ruby/ruby/pull/12524
|
|
The code path hasn't compiled for almost a year, since 330830dd1a44b6e497250a14d93efae6fa363f82,
so probably nobody uses it.
Notes:
Merged: https://github.com/ruby/ruby/pull/12519
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/12502
|
|
For the universal parser, `rb_parser_reg_fragment_check` function is
shared between the parser and ripper. However `parser_params` struct
is partially different, and `compile_error` function depends on that
part indirectly.
Notes:
Merged: https://github.com/ruby/ruby/pull/12482
|
|
For the universal parser, `rb_reg_named_capture_assign_iter_impl`
function is shared between the parser and ripper. However
`parser_params` struct is partially different, and `assignable`
function depends on that part indirectly.
Notes:
Merged: https://github.com/ruby/ruby/pull/12400
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/12385
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/12385
|
|
This change poisons the whole slot of the object rather than just the flags.
This allows ASAN to find any reads/writes into the slot after it has been
freed.
Notes:
Merged: https://github.com/ruby/ruby/pull/12385
|
|
Newer GCCs have __has_feature and older ones have
__SANITIZE_ADDRESS__[1]. Relevant since ASAN with GCC 11 on the popular
Ubuntu Jammy failed to build previously.
[1]: https://gcc.gnu.org/onlinedocs/gcc-4.8.0/cpp/Common-Predefined-Macros.html
|
|
When reference updating ObjectSpace.trace_object_allocations, we need to
check whether the object is valid or not because it does not mark the
object so the object may be dead. This can cause a segmentation fault
if the object is on a free heap page.
For example, the following script crashes:
require "objspace"
objs = []
ObjectSpace.trace_object_allocations do
1_000_000.times do
objs << Object.new
end
end
objs = nil
# Free pages that the objs were on
GC.start
# Run compaction and check that it doesn't crash
GC.compact
Notes:
Merged: https://github.com/ruby/ruby/pull/12360
|
|
[Bug #20950]
ifunc proc has the ep allocated in the cfunc_proc_t which is the data of
the TypedData object. If an ifunc proc is duplicated, the ep points to
the ep of the source object. If the source object is freed, then the ep
of the duplicated object now points to a freed memory region. If we try
to use the ep we could crash.
For example, the following script crashes:
p = { a: 1 }.to_proc
100.times do
p = p.dup
GC.start
p.call
rescue ArgumentError
end
This commit changes ifunc proc to also duplicate the ep when it is duplicated.
Notes:
Merged: https://github.com/ruby/ruby/pull/12319
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/12309
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/12315
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/12271
|
|
We should use the rb_gc_enable/rb_gc_disable_no_rest APIs instead of
directly setting the ruby_disable_gc variable.
Notes:
Merged: https://github.com/ruby/ruby/pull/12264
|
|
We have name fragmentation for this feature, including "shared GC",
"modular GC", and "external GC". This commit standardizes the feature
name to "modular GC" and the implementation to "GC library".
Notes:
Merged: https://github.com/ruby/ruby/pull/12261
|
|
There's no case for when RUBY_MSAN_ENABLED, so the macro ends up doing
nothing when it should instead have __attribute__((__no_sanitize__("memory"))).
Notes:
Merged: https://github.com/ruby/ruby/pull/12219
|
|
* Add opt_duparray_send insn to skip the allocation on `#include?`
If the method isn't going to modify the array we don't need to copy it.
This avoids the allocation / array copy for things like `[:a, :b].include?(x)`.
This adds a BOP for include? and tracks redefinition for it on Array.
Co-authored-by: Andrew Novoselac <[email protected]>
* YJIT: Implement opt_duparray_send include_p
Co-authored-by: Andrew Novoselac <[email protected]>
* Update opt_newarray_send to support simple forms of include?(arg)
Similar to opt_duparray_send but for non-static arrays.
* YJIT: Implement opt_newarray_send include_p
---------
Co-authored-by: Andrew Novoselac <[email protected]>
Notes:
Merged-By: maximecb <[email protected]>
|
|
So that it doesn't get included in the generated binaries for builds
that don't support loading shared GC modules
Co-Authored-By: Peter Zhu <[email protected]>
Notes:
Merged: https://github.com/ruby/ruby/pull/12149
|
|
Use PR_SET_VMA_ANON_NAME to set human-readable names for anonymous
virtual memory areas mapped by `mmap()` when compiled and run on Linux
5.17 or higher. This makes it convenient for developers to debug mmap.
Notes:
Merged: https://github.com/ruby/ruby/pull/12119
|
|
Redirect `rb_nogvl` blocking operations to the fiber scheduler if possible
to prevent stalling the event loop.
[Feature #20876]
Notes:
Merged-By: ioquatix <[email protected]>
|
|
This will add +MOD_GC to the version string and Ruby description when
Ruby is compiled with shared gc support.
When shared GC support is compiled in and a GC module has been loaded
using RUBY_GC_LIBRARY, the version string will include the name of
the currently active GC as reported by the rb_gc_active_gc_name function
in the form
+MOD_GC[gc_name]
[Feature #20794]
Notes:
Merged: https://github.com/ruby/ruby/pull/11872
|
|
* YJIT: Specialize `String#[]` (`String#slice`) with fixnum arguments
String#[] is in the top few C calls of several YJIT benchmarks:
liquid-compile rubocop mail sudoku
This speeds up these benchmarks by 1-2%.
* YJIT: Try harder to get type info for `String#[]`
In the large generated code of the mail gem the context doesn't have
the type info. In that case if we peek at the stack and add a guard
we can still apply the specialization
and it speeds up the mail benchmark by 5%.
Co-authored-by: Maxime Chevalier-Boisvert <[email protected]>
Co-authored-by: Takashi Kokubun (k0kubun) <[email protected]>
---------
Co-authored-by: Maxime Chevalier-Boisvert <[email protected]>
Co-authored-by: Takashi Kokubun (k0kubun) <[email protected]>
Notes:
Merged-By: maximecb <[email protected]>
|
|
* Use FL_USER0 for ELTS_SHARED
This makes space in RString for two bits for chilled strings.
* Mark strings returned by `Symbol#to_s` as chilled
[Feature #20350]
`STR_CHILLED` now spans on two user flags. If one bit is set it
marks a chilled string literal, if it's the other it marks a
`Symbol#to_s` chilled string.
Since it's not possible, and doesn't make much sense to include
debug info when `--debug-frozen-string-literal` is set, we can't
include allocation source, but we can safely include the symbol
name in the warning message, making it much easier to find the source
of the issue.
Co-Authored-By: Étienne Barrié <[email protected]>
---------
Co-authored-by: Étienne Barrié <[email protected]>
Co-authored-by: Jean Boussier <[email protected]>
|
|
While profiling msgpack-ruby I noticed a very substantial amout of time
spent in `rb_enc_associate_index`, called by `rb_utf8_str_new`.
On that benchmark, `rb_utf8_str_new` is 33% of the total runtime,
in big part because it cause GC to trigger often, but even then
`5.3%` of the total runtime is spent in `rb_enc_associate_index`
called by `rb_utf8_str_new`.
After closer inspection, it appears that it's performing a lot of
safety check we can assert we don't need, and other extra useless
operations, because strings are first created and filled as ASCII-8BIT
and then later reassociated to the desired encoding.
By directly allocating the string with the right encoding, it allow
to skip a lot of duplicated and useless operations.
After this change, the time spent in `rb_utf8_str_new` is down
to `28.4%` of total runtime, and most of that is GC.
Notes:
Merged: https://github.com/ruby/ruby/pull/12076
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/12034
|
|
to avoid TLS issue with N:M threads.
Notes:
Merged: https://github.com/ruby/ruby/pull/11142
|
|
introduce
- rb_threadptr_interrupt_exec
- rb_ractor_interrupt_exec
to intercept the thread/ractor execution.
Notes:
Merged: https://github.com/ruby/ruby/pull/11142
|
|
RUBY_DEBUG enables ractor assertions, which sets up some space at the
end of each RVALUE to store the associated ractor ID. We need to make
sure the function that does this is visible to shared GC libraries.
Notes:
Merged: https://github.com/ruby/ruby/pull/11945
|
|
[Feature #20205]
The warning now suggests running with --debug-frozen-string-literal:
```
test.rb:3: warning: literal string will be frozen in the future (run with --debug-frozen-string-literal for more information)
```
When using --debug-frozen-string-literal, the location where the string
was created is shown:
```
test.rb:3: warning: literal string will be frozen in the future
test.rb:1: info: the string was created here
```
When resurrecting strings and debug mode is not enabled, the overhead is a simple FL_TEST_RAW.
When mutating chilled strings and deprecation warnings are not enabled,
the overhead is a simple warning category enabled check.
Co-authored-by: Jean Boussier <[email protected]>
Co-authored-by: Nobuyoshi Nakada <[email protected]>
Co-authored-by: Jean Boussier <[email protected]>
Notes:
Merged: https://github.com/ruby/ruby/pull/11893
|