92218 Commits

Author SHA1 Message Date
John Hawthorn
ef9301a6b7 Ensure crr->feature is an fstring 2025-06-12 13:13:55 -07:00
John Hawthorn
b28f344312 Use a T_DATA for cross_ractor_require
[Bug #21090]

The struct was previously allocated on the stack, which could be freed
if the Thread is terminated. Moving this to a T_DATA on the heap should
mean this is no longer an issue.

1000.times { Ractor.new { th = Thread.new { require "rbconfig" }; Thread.pass }.take }

Co-authored-by: Luke Gruber <luke.gruber@shopify.com>
2025-06-12 13:13:55 -07:00
John Hawthorn
a34fcf401b Add a new_thread flag to rb_interrupt_exec
Previously rb_ractor_interrupt_exec would use an intermediate function
to create a new thread with the actual target function, replacing the
data being passed in with a piece of malloc memory holding the "next"
function and the original data.

Because of this, passing rb_interrupt_exec_flag_value_data to
rb_ractor_interrupt_exec didn't have the intended effect of allowing
data to be passed in and marked.

This commit adds a rb_interrupt_exec_flag_new_thread flag, which
both simplifies the implementation and allows the original data to be
marked.
2025-06-12 13:13:55 -07:00
Luke Gruber
97994c77fb Only use regex internal reg_cache when in main ractor
Using this `reg_cache` is racy across ractors, so don't use it when in a
ractor. Also, its use across ractors can cause a regular expression created
in 1 ractor to be used in another ractor (an isolation bug).
2025-06-12 13:13:18 -07:00
Peter Zhu
6e36841dbd Free rb_native_thread memory at fork
We never freed any resources of rb_native_thread at fork because it would
cause it to hang. This is because it called rb_native_cond_destroy for
condition variables.  We can't call rb_native_cond_destroy here because
according to the specs of pthread_cond_destroy:

    Attempting to destroy a condition variable upon which other threads
    are currently blocked results in undefined behavior.

Specifically, glibc's pthread_cond_destroy waits on all the other listeners.
Since after forking all the threads are dead, the condition variable's
listeners will never wake up, so it will hang forever.

This commit changes it to only free the memory and none of the condition
variables.
2025-06-12 15:23:50 -04:00
Ufuk Kayserilioglu
5ec9a392cd
[Bug #21439] Fix PM_SPLAT_NODE compilation error in for loops (#13597)
[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.
2025-06-12 11:33:10 -04:00
Jean Boussier
7c22330cd2 Allocate rb_shape_tree statically
There is no point allocating it during init, it adds
a useless indirection.
2025-06-12 17:08:22 +02:00
Jean Boussier
de4b910381 Get rid of GET_SHAPE_TREE()
It's a useless indirection.
2025-06-12 17:08:22 +02:00
Jean Boussier
e070d93573 Get rid of rb_shape_lookup 2025-06-12 17:08:22 +02:00
Jean Boussier
0292b702c4 shape.h: make RSHAPE static inline
Since the shape_tree_ptr is `extern` it should be possible to
fully inline `RSHAPE`.
2025-06-12 17:08:22 +02:00
Peter Zhu
d55c463d56 Fix memory leak of Ractor basket when sending to closed Ractor
The following script leaks memory:

    r = Ractor.new { }
    r.value

    10.times do
      100_000.times do
        r.send(123)
      rescue Ractor::ClosedError
      end

      puts `ps -o rss= -p #{$$}`
    end

Before:

    18508
    25420
    32460
    40012
    47308
    54092
    61132
    68300
    75724
    83020

After:

    11432
    11432
    11432
    11432
    11432
    11432
    11432
    11432
    11432
    11688
2025-06-12 10:02:44 -04:00
Jean Boussier
a74c385208 Make setting and accessing class ivars lock-free
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
```
2025-06-12 14:55:13 +02:00
Jean Boussier
8b5ac5abf2 Fix class instance variable inside namespaces
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.
2025-06-12 13:43:29 +02:00
Hartley McGuire
8120971932 Move more NilClass methods to ruby
```
$ make benchmark ITEM=nilclass COMPARE_RUBY="/opt/rubies/ruby-master/bin/ruby"
/opt/rubies/3.4.2/bin/ruby --disable=gems -rrubygems -I../benchmark/lib ../benchmark/benchmark-driver/exe/benchmark-driver \
                    --executables="compare-ruby::/opt/rubies/ruby-master/bin/ruby -I.ext/common --disable-gem" \
                    --executables="built-ruby::./miniruby -I../lib -I. -I.ext/common  ../tool/runruby.rb --extout=.ext  -- --disable-gems --disable-gem" \
                    --output=markdown --output-compare -v $(find ../benchmark -maxdepth 1 -name 'nilclass' -o -name '*nilclass*.yml' -o -name '*nilclass*.rb' | sort)
compare-ruby: ruby 3.5.0dev (2025-06-02T13:52:25Z master cbd49ecbbe) +PRISM [arm64-darwin24]
built-ruby: ruby 3.5.0dev (2025-06-02T22:47:21Z hm-ruby-nilclass 3e7f1f0466) +PRISM [arm64-darwin24]

|             |compare-ruby|built-ruby|
|:------------|-----------:|---------:|
|rationalize  |     24.056M|   53.908M|
|             |           -|     2.24x|
|to_c         |     23.652M|   82.781M|
|             |           -|     3.50x|
|to_i         |     89.526M|   84.388M|
|             |       1.06x|         -|
|to_f         |     84.746M|   96.899M|
|             |           -|     1.14x|
|to_r         |     25.107M|   83.472M|
|             |           -|     3.32x|
|splat        |     42.772M|   42.717M|
|             |       1.00x|         -|
```

This makes them much faster
2025-06-12 09:30:09 +02:00
Jean Boussier
3abdd4241f Turn rb_classext_t.fields into a T_IMEMO/class_fields
This behave almost exactly as a T_OBJECT, the layout is entirely
compatible.

This aims to solve two problems.

First, it solves the problem of namspaced classes having
a single `shape_id`. Now each namespaced classext
has an object that can hold the namespace specific
shape.

Second, it open the door to later make class instance variable
writes atomics, hence be able to read class variables
without locking the VM.
In the future, in multi-ractor mode, we can do the write
on a copy of the `fields_obj` and then atomically swap it.

Considerations:

  - Right now the `RClass` shape_id is always synchronized,
    but with namespace we should likely mark classes that have
    multiple namespace with a specific shape flag.
2025-06-12 07:58:16 +02:00
Hiroshi SHIBATA
166ff187bd [rubygems/rubygems] Removed ccache or sccache from args of Rust builder
```
 "  = note: some arguments are omitted. use `--verbose` to show all linker arguments\n" +
 "  = note: error: unexpected argument '-W' found\n" +
 "          \n" +
 "            tip: to pass '-W' as a value, use '-- -W'\n" +
 "          \n" +
 "          Usage: sccache [OPTIONS] <--dist-auth|--debug-preprocessor-cache|--dist-status|--show-stats|--show-adv-stats|--start-server|--stop-server|--zero-stats|--package-toolchain <EXE> <OUT>|CMD>\n" +
 "          \n" +
 "          For more information, try '--help'.\n" +
 "          \n" +
```

https://github.com/rubygems/rubygems/commit/45e688ae62
2025-06-12 14:28:43 +09:00
Nobuyoshi Nakada
4585ccd90f [ruby/strscan] Update extconf.rb
(https://github.com/ruby/strscan/pull/158)

- `have_func` includes "ruby.h" by default.
- include "ruby/re.h" where `rb_reg_onig_match` is declared.

https://github.com/ruby/strscan/commit/1ac96f47e9
2025-06-12 10:34:31 +09:00
John Hawthorn
7854b71e7f Supress a few more tsan errors 2025-06-11 18:11:36 -07:00
John Hawthorn
f91c80836a gdbinit: fix printing of T_DATA 2025-06-11 18:11:36 -07:00
David Rodríguez
3a6844a692
Tweak to spec setup so that rspec instead of our bin/rspec binstub still works 2025-06-12 08:45:02 +09:00
Joshua Young
8abb87b9c7 [rubygems/rubygems] Remove duplicate documentation for --changelog flag
https://github.com/rubygems/rubygems/commit/9f1d07685f
2025-06-12 08:40:51 +09:00
David Rodríguez
3fdaa6a19c [rubygems/rubygems] Fix typos in some documentation lists making them render incorrectly
https://github.com/rubygems/rubygems/commit/19739ba71c
2025-06-12 08:40:50 +09:00
David Rodríguez
ca7bd59794 [rubygems/rubygems] Update man pages month
https://github.com/rubygems/rubygems/commit/3e4687616a
2025-06-12 08:40:50 +09:00
Earlopain
970813d982 [ruby/prism] Fix parser translator during string escaping with invalid utf-8
Instead, prefer `scan_byte` over `get_byte` since that already returns the byte as an integer, sidestepping conversion issues.

Fixes https://github.com/ruby/prism/issues/3582

https://github.com/ruby/prism/commit/7f3008b2b5
2025-06-11 18:07:43 +00:00
Jean Boussier
95201299fd Refactor the last references to rb_shape_t
The type isn't opaque because Ruby isn't often compiled with LTO,
so for optimization purpose it's better to allow as much inlining
as possible.

However ideally only `shape.c` and `shape.h` should deal with
the actual struct, and everything else should just deal with opaque
`shape_id_t`.
2025-06-11 16:38:38 +02:00
Jean Boussier
4463ac264d shape.h: remove YJIT workaround
YJIT x86 backend would crahs if the shape_id top bit was set.
This should have been fixed now.
2025-06-11 14:21:43 +02:00
Alan Wu
59fad961b8 ZJIT: x86: Fix panic writing 32-bit number with top bit set
Previously, `asm.mov(m32, imm32)` panicked when `imm32 > 0x80000000`. It
attempted to split imm32 into a register before doing the store, but
then the register size didn't match the destination size.

Instead of splitting, use the `MOV r/m32, imm32` form which works for
all 32-bit values. Adjust asserts that assumed that all forms undergo
sign extension, which is not true for this case.

See: 54edc930f9f0a658da45cfcef46648d1b6f82467
2025-06-11 19:49:49 +09:00
Alan Wu
e5c7f1695e YJIT: x86: Fix panic writing 32-bit number with top bit set
Previously, `asm.mov(m32, imm32)` panicked when `imm32 > 0x80000000`. It
attempted to split imm32 into a register before doing the store, but
then the register size didn't match the destination size.

Instead of splitting, use the `MOV r/m32, imm32` form which works for
all 32-bit values. Adjust asserts that assumed that all forms undergo
sign extension, which is not true for this case.

See: 54edc930f9f0a658da45cfcef46648d1b6f82467
2025-06-11 19:49:49 +09:00
Alan Wu
4ebe0a1ba5 ZJIT: Restore x86 assembler tests 2025-06-11 19:49:49 +09:00
Alan Wu
c489020cab ZJIT: Restore some A64 backend tests to fix unused warning 2025-06-11 19:49:49 +09:00
Alan Wu
0bc24353d3 ZJIT: Restore most x64 backend tests 2025-06-11 19:49:49 +09:00
Nobuyoshi Nakada
f45aa1505f [ruby/date] Update zonetab.h at 2025-06-11
https://github.com/ruby/date/commit/b28617cde0
2025-06-11 10:05:39 +00:00
Jean Boussier
c2f2ac7db3 shape.c: Fix rb_bug call to use correct format for size_t 2025-06-11 10:10:04 +02:00
Hiroshi SHIBATA
fd7e56a831 Use artifacts built by vcpkg manifest mode
I'm not sure why vcpkg cache is not using while recent weeks.
2025-06-11 17:04:18 +09:00
Hiroshi SHIBATA
255e6e6197 Try to run ignored tests with macOS 15 2025-06-11 15:40:52 +09:00
Nobuyoshi Nakada
51118fa2da [ruby/net-http] Support pretty_print
https://github.com/ruby/net-http/commit/bfc60454f6
2025-06-11 05:04:16 +00:00
Hiroshi SHIBATA
a976fa1bb7 Followed up https://github.com/ruby/net-http/commit/002441da1e for ruby/spec 2025-06-11 13:57:08 +09:00
Hiroshi SHIBATA
82e3312493 [ruby/net-http] Fixed test case for default content-type.
I changed content-type of request to "application/octet-stream" if request didn't have
content-type.

https://github.com/ruby/net-http/commit/fc5870d2ac
2025-06-11 03:35:12 +00:00
Hiroshi SHIBATA
51b70d106a [ruby/net-http] Don't set content type by default
Fixes https://github.com/ruby/net-http/issues/205

https://github.com/ruby/net-http/commit/002441da1e
2025-06-11 03:35:11 +00:00
David Rodríguez
9b09c68032 Simplify make test-bundler 2025-06-11 09:38:56 +09:00
David Rodríguez
ec897fd204 Fix make test-bundler 2025-06-11 09:38:56 +09:00
David Rodríguez
dba72134de [rubygems/rubygems] Fix gem pristine sometimes not resetting extensions
If `gem pristine foo` is run, and there's a default copy of foo, only
executables for it are reset. However, that was causing other copies of
`foo` to only reset executables, which is unexpected.

We should not modify `options[:only_executables]`, but respect its value
for every gem, and make sure special handling for default gems does not
leak to other gems.

https://github.com/rubygems/rubygems/commit/2c3039f1b0
2025-06-11 08:48:57 +09:00
David Rodríguez
6560083c39 [rubygems/rubygems] Normalize file existence helpers usage
https://github.com/rubygems/rubygems/commit/a61cc97cd4
2025-06-11 08:48:57 +09:00
Samuel Giddins
7e3d271f76 [rubygems/rubygems] Install the best matching gem for the current platform in gem install
Instead of picking essentially a random matching platform

Signed-off-by: Samuel Giddins <segiddins@segiddins.me>

https://github.com/rubygems/rubygems/commit/3727096297
2025-06-11 08:48:56 +09:00
Randy Stauner
b5beb19825 [rubygems/rubygems] Validate dependencies when doing bundle install
https://github.com/rubygems/rubygems/commit/b0983f392f
2025-06-11 08:48:55 +09:00
Jean Boussier
35fc19f5d4 enumerator.c: Remove unused IDs 2025-06-10 21:13:37 +02:00
Aaron Patterson
0f922edca0 ZJIT: Support get/set on global variables
Adds support for code like:

```ruby
$foo
$foo = x
```
2025-06-10 10:42:01 -07:00
Étienne Barrié
c54e96d651 Fix RubyVM::Shape.transition_tree 2025-06-10 19:37:03 +02:00
Jean Boussier
bcb4fbe2eb Refactor Enumerator::ArithmeticSequence to not use ivars
It's an embedded TypedData, it can much more efficiently store
the references it need without using ivars.
2025-06-10 19:26:37 +02:00
Luke Gruber
585dcffff1 Fix regular expressions across ractors that match different encodings
In commit d42b9ffb206, an optimization was introduced that can speed up
Regexp#match by 15% when it matches with strings of different encodings.
This optimization, however, does not work across ractors. To fix this,
we only use the optimization if no ractors have been started. In the
future, we could use atomics for the reference counting if we find it's
needed and if it's more performant.

The backtrace of the misbehaving native thread:

```
  * frame #0: 0x0000000189c94388 libsystem_kernel.dylib`__pthread_kill + 8
    frame #1: 0x0000000189ccd88c libsystem_pthread.dylib`pthread_kill + 296
    frame #2: 0x0000000189bd6c60 libsystem_c.dylib`abort + 124
    frame #3: 0x0000000189adb174 libsystem_malloc.dylib`malloc_vreport + 892
    frame #4: 0x0000000189adec90 libsystem_malloc.dylib`malloc_report + 64
    frame #5: 0x0000000189ae321c libsystem_malloc.dylib`___BUG_IN_CLIENT_OF_LIBMALLOC_POINTER_BEING_FREED_WAS_NOT_ALLOCATED + 32
    frame #6: 0x00000001001c3be4 ruby`onig_free_body(reg=0x000000012d84b660) at regcomp.c:5663:5
    frame #7: 0x00000001001ba828 ruby`rb_reg_prepare_re(re=4748462304, str=4748451168) at re.c:1680:13
    frame #8: 0x00000001001bac58 ruby`rb_reg_onig_match(re=4748462304, str=4748451168, match=(ruby`reg_onig_search [inlined] rbimpl_RB_TYPE_P_fastpath at value_type.h:349:14
ruby`reg_onig_search [inlined] rbimpl_rstring_getmem at rstring.h:391:5
ruby`reg_onig_search at re.c:1781:5), args=0x000000013824b168, regs=0x000000013824b150) at re.c:1708:20
    frame #9: 0x00000001001baefc ruby`rb_reg_search_set_match(re=4748462304, str=4748451168, pos=<unavailable>, reverse=0, set_backref_str=1, set_match=0x0000000000000000) at re.c:1809:27
    frame #10: 0x00000001001bae80 ruby`rb_reg_search0(re=<unavailable>, str=<unavailable>, pos=<unavailable>, reverse=<unavailable>, set_backref_str=<unavailable>, match=<unavailable>) at re.c:1861:12 [artificial]
    frame #11: 0x0000000100230b90 ruby`rb_pat_search0(pat=<unavailable>, str=<unavailable>, pos=<unavailable>, set_backref_str=<unavailable>, match=<unavailable>) at string.c:6619:16 [artificial]
    frame #12: 0x00000001002287f4 ruby`rb_str_sub_bang [inlined] rb_pat_search(pat=4748462304, str=4748451168, pos=0, set_backref_str=1) at string.c:6626:12
    frame #13: 0x00000001002287dc ruby`rb_str_sub_bang(argc=1, argv=0x00000001381280d0, str=4748451168) at string.c:6668:11
    frame #14: 0x000000010022826c ruby`rb_str_sub
```

You can reproduce this by running:
```
RUBY_TESTOPTS="--name=/test_str_capitalize/" make test-all TESTS=test/ruby/test_m17n.comb
```

However, you need to run it with multiple ractors at once.

Co-authored-by: jhawthorn <john@hawthorn.email>
2025-06-10 09:00:17 -07:00