Commit graph

93369 commits

Author SHA1 Message Date
Ethan
60ca525fce [DOC] Array#map! fix to indicate return is self 2025-08-09 11:10:51 +09:00
Ethan
4209ebb1e4 [DOC] Array#fill fix to indicate return is self
doc currently indicates the return value as `new_array` but then in the first sentence explains "always returns +self+ (never a new array)".
2025-08-09 11:10:51 +09:00
Carl Zulauf
22fe80f275 Fix Typo in Regular Expressions docs (_regexp.rdoc)
Small fix for a typo in the regular expression docs. The line of code above this change does not produce the output shown in the docs. With this change the docs will show the correct output for this example of using regex quantifiers.
2025-08-09 11:02:37 +09:00
John Hawthorn
d80c03d22a Fix id2ref table build when GC in progress
Previously, if GC was in progress when we're initially building the
id2ref table, it could see the empty table and then crash when trying to
remove ids from it. This commit fixes the bug by only publishing the
table after GC is done.

Co-authored-by: Aaron Patterson <tenderlove@ruby-lang.org>
2025-08-08 17:13:25 -07:00
Luke Gruber
07878ebe78 Fix lock ordering issue for rb_ractor_sched_wait() and rb_ractor_sched_wakeup()
In rb_ractor_sched_wait() (ex: Ractor.receive), we acquire
RACTOR_LOCK(cr) and then thread_sched_lock(cur_th). However, on wakeup
if we're a dnt, in thread_sched_wait_running_turn() we acquire
thread_sched_lock(cur_th) after condvar wakeup and then RACTOR_LOCK(cr).
This lock inversion can cause a deadlock with rb_ractor_wakeup_all()
(ex: port.send(obj)), where we acquire RACTOR_LOCK(other_r) and then
thread_sched_lock(other_th).

So, the error happens:

nt 1:   Ractor.receive
            rb_ractor_sched_wait() after condvar wakeup in thread_sched_wait_running_turn():
              - thread_sched_lock(cur_th) (condvar) # acquires lock
              - rb_ractor_lock_self(cr) # deadlock here: tries to acquire, HANGS

nt 2: port.send
            ractor_wakeup_all()
              - RACTOR_LOCK(port_r) # acquires lock
              - thread_sched_lock # tries to acquire, HANGS

To fix it, we now unlock the thread_sched_lock before acquiring the
ractor_lock in rb_ractor_sched_wait().

Script that reproduces issue:

```ruby
require "async"
class RactorWrapper
  def initialize
    @ractor = Ractor.new do
      Ractor.recv # Ractor doesn't start until explicitly told to
      # Do some calculations
      fib = ->(x) { x < 2 ? 1 : fib.call(x - 1) + fib.call(x - 2) }
      fib.call(20)
    end
  end

  def take_async
    @ractor.send(nil)
    Thread.new { @ractor.value }.value
  end
end

Async do |task|
  10_000.times do |i|
    task.async do
      RactorWrapper.new.take_async
      puts i
    end
  end
end
exit 0
```

Fixes [Bug #21398]

Co-authored-by: John Hawthorn <john.hawthorn@shopify.com>
2025-08-08 13:37:31 -07:00
Peter Zhu
e639e5fd1a Make rb_gc_impl_writebarrier_remember Ractor-safe
rb_gc_impl_writebarrier_remember is not Ractor safe because it writes to
bitmaps and also pushes onto the mark stack during incremental marking.
We should acquire the VM lock to prevent race conditions.

In the case that the object is not old, there is no performance impact.
However, we can see a performance impact in this microbenchmark where the
object is old:

    4.times.map do
      Ractor.new do
        ary = []

        3.times { GC.start }

        10_000_000.times do |i|
          ary.push(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17)
          ary.clear
        end
      end
    end.map(&:value)

Before:

    Time (mean ± σ):     682.4 ms ±   5.1 ms    [User: 2564.8 ms, System: 16.0 ms]

After:

    Time (mean ± σ):      5.522 s ±  0.096 s    [User: 8.237 s, System: 7.931 s]

Co-Authored-By: Luke Gruber <luke.gruber@shopify.com>
Co-Authored-By: John Hawthorn <john@hawthorn.email>
2025-08-08 16:04:11 -04:00
Alan Wu
0ba488d7f5
ZJIT: Avoid compiling and direct sends to forwardable ISEQs
These `...` ISEQs have a special calling convention in the interpreter
and our stubs and JIT calling convention don't deal well. Reject for now.
Debugged with help from `@tekknolagi` and `tool/zjit_bisect.rb`.

Merely avoiding direct sends is enough to pass the attached test, but also
avoid compiling ISEQs with `...` parameter to limit exposure for now.

`SendWithoutBlock`, which does dynamic dispatch using interpreter code,
seems to handle calling into forwardable ISEQs correctly, so they are
fine -- we can't predict where these dynamic sends land anyways.
2025-08-08 18:54:53 +00:00
Takashi Kokubun
eb931a09c5
ZJIT: Fix "memory operand with non-register base" (#14153) 2025-08-08 11:24:39 -07:00
Max Bernstein
8eb26ebf91
ZJIT: Add a graphviz dumper for HIR (#14117)
This is moderately useful just in stdout (copy and paste into a renderer) but potentially more useful alongside a tool that parses stdout looking for `digraph G { ... }` and renders those automatically.
2025-08-08 13:56:19 -04:00
Jean Boussier
057d7c1c58 object_id_to_ref: complete incremental GC before iterating
Otherwise dealing with garbage objects is tricky.
2025-08-08 19:06:59 +02:00
Nobuyoshi Nakada
e4b386e090
CI: Remove Strawberry Perl pkg-config 2025-08-09 01:02:34 +09:00
Nobuyoshi Nakada
7b5cd5ce15
Revert "Convert PKG_CONFIG_PATH to msys/cygwin path"
This reverts commit 8e9ea4c202.

The environment variable is converted internally.
2025-08-09 01:01:47 +09:00
Max Bernstein
c6a27a0253 ZJII: Address review feedback 2025-08-08 08:15:18 -07:00
Max Bernstein
180469a3a7 ZJIT: Actually kill timed-out process in bisect 2025-08-08 08:15:18 -07:00
Max Bernstein
0782bd2826 ZJIT: Use OptionParser in bisect script 2025-08-08 08:15:18 -07:00
Max Bernstein
fd6d6a45cd ZJIT: Use shellwords in bisect script 2025-08-08 08:15:18 -07:00
Max Bernstein
0b30cf3b40 ZJIT: Print out command to repro in bisect script 2025-08-08 08:15:18 -07:00
Nobuyoshi Nakada
a15cf61ba6
Revert "Check if the found pkg-config is usable actually"
This reverts commit 79d8a3159f.

The second argument of `find_executable0` in mkmf is `path`, not
arguments to the program like as `EnvUtil.find_executable`.
2025-08-08 20:17:58 +09:00
Nobuyoshi Nakada
f76ce9fd28 [ruby/optparse] Use ~/.config only if $XDG_CONFIG_HOME is unset or empty
2f9c7500a3
2025-08-08 10:39:20 +00:00
dependabot[bot]
3ad26d0501 Bump actions/cache in /.github/actions/setup/directories
Bumps [actions/cache](https://github.com/actions/cache) from 4.2.3 to 4.2.4.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](5a3ec84eff...0400d5f644)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-version: 4.2.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-08 11:57:23 +09:00
Takashi Kokubun
4fef87588a
ZJIT: Remove the need for unwrap() on with_num_bits() (#14144)
* ZJIT: Remove the need for unwrap() on with_num_bits()

* Fix arm64 tests

* Track the caller of with_num_bits

Co-authored-by: Alan Wu <XrXr@users.noreply.github.com>

---------

Co-authored-by: Alan Wu <XrXr@users.noreply.github.com>
2025-08-07 16:56:27 -07:00
Stan Lo
2edc944702
ZJIT: Implement defined? codegen for non-yield calls (#14101) 2025-08-07 15:41:05 -07:00
John Hawthorn
c41c323f1a
Invalidate CCs when cme is invalidated in marking
* Skip assertion when cc->klass is Qundef
* Invalidate CCs when cme is invalidated in marking
* Add additional assertions that CC references stay valid

Co-authored-by: Peter Zhu <peter@peterzhu.ca>
2025-08-07 15:39:45 -07:00
Stan Lo
d25eb1eb5c
ZJIT: Optimize class guards by directly reading klass field (#14136)
Replace `rb_yarv_class_of` call with:
- a constant check for special constants (nil, fixnums, symbols, etc)
- a check for false
- direct memory read at offset 8 for regular heap objects for the class check
2025-08-07 15:38:02 -07:00
Takashi Kokubun
96c9e1e93a
ZJIT: Remove GC offsets overwritten by invalidation (#14102)
ZJIT: Remove GC offsts overwritten by invalidation
2025-08-07 15:30:02 -07:00
Max Bernstein
363ad0ad17
ZJIT: Create HeapObject Type (#14140)
This is a counterpoint to the Immediate type and it represents all BasicObject subclasses except for the several immediate objects.

If we know something is a HeapObject, we know we can treat it as an RBasic pointer.
2025-08-07 15:11:55 -04:00
Jean Boussier
1aabd2cb36 Convert time to use rb_gc_mark_and_move
The `p->field = rb_gc_location(p->field)` isn't ideal because it means all
references are rewritten on compaction, regardless of whether the referenced
object has moved. This isn't good for caches nor for Copy-on-Write.

`rb_gc_mark_and_move` avoid needless writes, and most of the time allow to
have a single function for both marking and updating references.
2025-08-07 21:00:00 +02:00
Jean Boussier
1986d775cd symbol.c: use rb_gc_mark_and_move over rb_gc_location
The `p->field = rb_gc_location(p->field)` isn't ideal because it means all
references are rewritten on compaction, regardless of whether the referenced
object has moved. This isn't good for caches nor for Copy-on-Write.

`rb_gc_mark_and_move` avoid needless writes, and most of the time allow to
have a single function for both marking and updating references.
2025-08-07 21:00:00 +02:00
Jean Boussier
5bcfc53d6f set.c: use rb_gc_mark_and_move
The `p->field = rb_gc_location(p->field)` isn't ideal because it means all
references are rewritten on compaction, regardless of whether the referenced
object has moved. This isn't good for caches nor for Copy-on-Write.

`rb_gc_mark_and_move` avoid needless writes, and most of the time allow to
have a single function for both marking and updating references.
2025-08-07 21:00:00 +02:00
Jean Boussier
559d9e1f67 Convert VM/shape_tree to use rb_gc_mark_and_move
The `p->field = rb_gc_location(p->field)` isn't ideal because it means all
references are rewritten on compaction, regardless of whether the referenced
object has moved. This isn't good for caches nor for Copy-on-Write.

`rb_gc_mark_and_move` avoid needless writes, and most of the time allow to
have a single function for both marking and updating references.
2025-08-07 21:00:00 +02:00
Jean Boussier
bc9781c264 Convert name_err_mesg to use rb_gc_mark_and_move
The `p->field = rb_gc_location(p->field)` isn't ideal because it means all
references are rewritten on compaction, regardless of whether the referenced
object has moved. This isn't good for caches nor for Copy-on-Write.

`rb_gc_mark_and_move` avoid needless writes, and most of the time allow to
have a single function for both marking and updating references.
2025-08-07 21:00:00 +02:00
Jean Boussier
aee8e65c70 Convert Enumerator types to use rb_gc_mark_and_move
The `p->field = rb_gc_location(p->field)` isn't ideal because it means all
references are rewritten on compaction, regardless of whether the referenced
object has moved. This isn't good for caches nor for Copy-on-Write.

`rb_gc_mark_and_move` avoid needless writes, and most of the time allow to
have a single function for both marking and updating references.
2025-08-07 21:00:00 +02:00
Jean Boussier
846b5eec57 Convert marshal_compat_table to use rb_gc_mark_and_move
The `p->field = rb_gc_location(p->field)` isn't ideal because it means all
references are rewritten on compaction, regardless of whether the referenced
object has moved. This isn't good for caches nor for Copy-on-Write.

`rb_gc_mark_and_move` avoid needless writes, and most of the time allow to
have a single function for both marking and updating references.
2025-08-07 21:00:00 +02:00
Max Bernstein
a260bbc550
ZJIT: Set PC before StringCopy (#14141)
ZJIT: Set PC before StringCopy

This function allocates.
2025-08-07 18:28:10 +00:00
Peter Zhu
24d0b458cd Make Random write-barrier protected 2025-08-07 09:27:22 -04:00
John Hawthorn
fccd96cc6c Add stricter assertions on CC access 2025-08-06 15:57:13 -07:00
John Hawthorn
640a2f1dc7 Ensure ObjectSpace.dump won't call cc_cme on invalidated CC 2025-08-06 15:57:13 -07:00
John Hawthorn
a9f6fe0914 Avoid marking CC children after invalidation
Once klass becomes Qundef, it's disconnected and won't be invalidated
when the CME is. So once that happens we must not mark or attempt to
move the cme_ field.
2025-08-06 15:57:13 -07:00
Max Bernstein
ba4a36e226
ZJIT: Inline attr_reader/attr_accessor (#14126)
We can rewrite SendWithoutBlock to GetIvar.
2025-08-06 16:56:01 -04:00
Stan Lo
4a70f946a7
ZJIT: Implement SingleRactorMode invalidation (#14121)
* ZJIT: Implement SingleRactorMode invalidation

* ZJIT: Add macro for compiling jumps

* ZJIT: Fix typo in comment

* YJIT: Fix typo in comment

* ZJIT: Avoid using unexported types in zjit.h

`enum ruby_vminsn_type` is declared in `insns.inc` and is not exported.
Using it in `zjit.h` would cause build errors when the file including it
doesn't include `insns.inc`.
2025-08-06 13:51:41 -07:00
Alan Wu
e378a21a32 ZJIT: Run TestFixnum 2025-08-06 16:26:14 -04:00
Alan Wu
21cb1c9e92 ZJIT: x86: split: Fix live ranges index-out-of-range panic
Previously we crashed panicked due to index bounds check running
test_fixnum.rb.

On ARM and in other places in the x86 backend, this isn't a problem
because they inspect the output of instructions which is never replaced.
2025-08-06 16:26:14 -04:00
Peter Zhu
71b46938a7 Fix off-by-one in symbol next_id
Symbol last_id was changed to next_id, but it remained to be set to
tNEXT_ID - 1 initially, causing the initial static symbol to overlap with
the last built-in symbol in id.def.
2025-08-06 13:40:27 -04:00
Takashi Kokubun
ebb775be8d
ZJIT: Fix "immediate value too large" on cmp for x86_64 (#14125)
Co-authored-by: Alan Wu <alansi.xingwu@shopify.com>
2025-08-06 10:05:20 -07:00
S-H-GAMELINKS
bcd21053f7 Add MODULE NODE locations
Add `keyword_module` amd `keyword_end` locations to struct `RNode_MODULE`.

memo:
```
>ruby --dump=parsetree -e 'module A end'
@ ProgramNode (location: (1,0)-(1,12))
+-- locals: []
+-- statements:
    @ StatementsNode (location: (1,0)-(1,12))
    +-- body: (length: 1)
        +-- @ ModuleNode (location: (1,0)-(1,12))
            +-- locals: []
            +-- module_keyword_loc: (1,0)-(1,6) = "module"
            +-- constant_path:
            |   @ ConstantReadNode (location: (1,7)-(1,8))
            |   +-- name: :A
            +-- body: nil
            +-- end_keyword_loc: (1,9)-(1,12) = "end"
            +-- name: :A
```
2025-08-07 01:07:16 +09:00
ydah
7aa0e09bfe Fix typo in comment regarding symlink flags in autogen.sh 2025-08-07 01:06:50 +09:00
Jean Boussier
f3206cc79b Struct: keep direct reference to IMEMO/fields when space allows
It's not rare for structs to have additional ivars, hence are one
of the most common, if not the most common type in the `gen_fields_tbl`.

This can cause Ractor contention, but even in single ractor mode
means having to do a hash lookup to access the ivars, and increase
GC work.

Instead, unless the struct is perfectly right sized, we can store
a reference to the associated IMEMO/fields object right after the
last struct member.

```
compare-ruby: ruby 3.5.0dev (2025-08-06T12:50:36Z struct-ivar-fields-2 9a30d141a1) +PRISM [arm64-darwin24]
built-ruby: ruby 3.5.0dev (2025-08-06T12:57:59Z struct-ivar-fields-2 2ff3ec237f) +PRISM [arm64-darwin24]
warming up.....

|                      |compare-ruby|built-ruby|
|:---------------------|-----------:|---------:|
|member_reader         |    590.317k|  579.246k|
|                      |       1.02x|         -|
|member_writer         |    543.963k|  527.104k|
|                      |       1.03x|         -|
|member_reader_method  |    213.540k|  213.004k|
|                      |       1.00x|         -|
|member_writer_method  |    192.657k|  191.491k|
|                      |       1.01x|         -|
|ivar_reader           |    403.993k|  569.915k|
|                      |           -|     1.41x|
```

Co-Authored-By: Étienne Barrié <etienne.barrie@gmail.com>
2025-08-06 17:07:49 +02:00
Jean Boussier
9b3ad3449b Mark cross_ractor_require_data_type as embeddable
Nothing prevents it, so might as well.
2025-08-06 16:37:25 +02:00
Peter Zhu
06312377ad Make Ractor::Selector write-barrier protected 2025-08-06 09:02:30 -04:00
Jean Boussier
92688f7d57 variable.c: refactor accesses to the generic_fields_tbl
All accesses to `generic_fields_tbl_` are now encapsulated inside:

  - `rb_obj_fields`
  - `rb_obj_set_fields`
  - `rb_obj_replace_fields`
2025-08-06 12:33:44 +02:00