Commit graph

234 commits

Author SHA1 Message Date
Jean Boussier
62a7f17157 Update RB_GC_OBJECT_METADATA_ENTRY_COUNT
In cb1ea54bbf I added one more
metadata flag, but didn't notice `RB_GC_OBJECT_METADATA_ENTRY_COUNT`
had to be incremented.

This should fix ASAN builds.

Interestingly, bdb25959fb already
caused the count to be off by one, so I had to increment it by
2.
2025-04-25 11:17:31 +02:00
Jean Boussier
cb1ea54bbf objspace_dump: Include shareable flag
Given that the currently planned ractor local GC implementation
performance will heavilly be influenced by the number of shareable
objects it would be valuable to be able to know how many of them
are in the heap.
2025-04-24 10:14:29 +02:00
Jean Boussier
1048b162de Eagerly store a copy of object_id in finalizer table.
This makes the finalizer table fully self contained, so GC no
longer need to delay cleaning the `obj_to_id_tbl`.
2025-04-23 11:54:29 +02:00
Jean Boussier
6d0dd7d863 rb_gc_impl_define_finalizer: unlock on early return 2025-04-23 07:04:41 +02:00
Jean Boussier
7c30bd50df Add missing lock in rb_gc_impl_define_finalizer
`objspace->finalizer_table` must be synchronized,
otherwise concurrent insertion from multiple ractors
will cause a crash.

Repro:

```ruby
ractors = 5.times.map do |i|
  Ractor.new do
    100_000.times.map do
      o = Object.new
      ObjectSpace.define_finalizer(o, ->(id) {})
      o
    end
  end
end

ractors.each(&:take)
```
2025-04-22 23:23:35 +02:00
dependabot[bot]
f6fddbd337 Bump crossbeam-channel from 0.5.13 to 0.5.15 in /gc/mmtk
Bumps [crossbeam-channel](https://github.com/crossbeam-rs/crossbeam) from 0.5.13 to 0.5.15.
- [Release notes](https://github.com/crossbeam-rs/crossbeam/releases)
- [Changelog](https://github.com/crossbeam-rs/crossbeam/blob/master/CHANGELOG.md)
- [Commits](https://github.com/crossbeam-rs/crossbeam/compare/crossbeam-channel-0.5.13...crossbeam-channel-0.5.15)

---
updated-dependencies:
- dependency-name: crossbeam-channel
  dependency-version: 0.5.15
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-15 17:14:26 +09:00
Jean Boussier
0606046c1a Lazily create objspace->id_to_obj_tbl
This inverse table is only useful if `ObjectSpace._id2ref` is used,
which is extremely rare. The only notable exception is the `drb` gem
and even then it has an option not to rely on `_id2ref`.

So if we assume this table will never be looked up, we can just
not maintain it, and if it turns out `_id2ref` is called, we
can lock the VM and re-build it.

```
compare-ruby: ruby 3.5.0dev (2025-04-10T09:44:40Z master 684cfa42d7) +YJIT +PRISM [arm64-darwin24]
built-ruby: ruby 3.5.0dev (2025-04-10T10:13:43Z lazy-id-to-obj d3aa9626cc) +YJIT +PRISM [arm64-darwin24]
warming up..

|           |compare-ruby|built-ruby|
|:----------|-----------:|---------:|
|baseline   |     26.364M|   25.974M|
|           |       1.01x|         -|
|object_id  |     10.293M|   14.202M|
|           |           -|     1.38x|
```
2025-04-15 07:57:39 +09:00
Kunshan Wang
d17ab5a430 [ruby/mmtk] Do root scanning in scan_vm_specific_roots
We rely on scan_vm_specific_roots to reach all stacks via the following
path:

    VM -> ractors -> threads -> fibers -> stacks

0a6a835aaa
2025-04-08 03:12:50 +00:00
Peter Zhu
d4406f0627 Grow GC heaps independently
[Bug #21214]

If we allocate objects where one heap holds transient objects and another
holds long lived objects, then the heap with transient objects will grow
along the heap with long lived objects, causing higher memory usage.

For example, we can see this issue in this script:

    def allocate_small_object = []
    def allocate_large_object = Array.new(10)

    arys = Array.new(1_000_000) do
      # Allocate 10 small transient objects
      10.times { allocate_small_object }
      # Allocate 1 large object that is persistent
      allocate_large_object
    end

    pp GC.stat
    pp GC.stat_heap

Before this change:

    heap_live_slots: 2837243
    {0 =>
      {slot_size: 40,
       heap_eden_pages: 1123,
       heap_eden_slots: 1838807},
     2 =>
      {slot_size: 160,
       heap_eden_pages: 2449,
       heap_eden_slots: 1001149},
    }

After this change:

    heap_live_slots: 1094474
    {0 =>
      {slot_size: 40,
       heap_eden_pages: 58,
       heap_eden_slots: 94973},
     2 =>
      {slot_size: 160,
       heap_eden_pages: 2449,
       heap_eden_slots: 1001149},
    }
2025-04-07 09:41:11 -04:00
Matt Valentine-House
e4020133c8 Remove incorrect assertion
ractor_cache will always be NULL in this context
2025-04-01 21:45:08 +01:00
Jean Boussier
7db0e07134 Don't preserve object_id when moving object to another Ractor
That seemed like the logical thing to do to me, but ko1 disagree.
2025-03-31 12:01:55 +02:00
Jean Boussier
0350290262 Ractor: Fix moving embedded objects
[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.
2025-03-31 12:01:55 +02:00
Alan Wu
c576e83a24
Prefer FL_TEST_RAW() in GC on known on-heap objects
Was reading some assembly and noticed the dead branches generated for
FL_TEST(). Just a quick basic pass to change the obvious places; there
may be other opportunities.
2025-03-25 18:16:31 -04:00
Peter Zhu
6bb35a1de4 Make ruby_autocompact_compare_func static
It's not used outside of default.c.
2025-03-25 16:19:32 -04:00
Peter Zhu
e4c7eb1152 Make ruby_enable_autocompact static
It's not used outside of defaut.c
2025-03-25 16:19:32 -04:00
Peter Zhu
eb3f73ae9c [DOC] Use install-modular-gc in gc/README.md 2025-03-25 08:49:31 -04:00
Peter Zhu
319fcca656 Move rb_gc_impl_ractor_cache_free to shutdown section 2025-03-24 08:49:30 -04:00
Peter Zhu
a572ec1ba0 Move rb_gc_impl_objspace_free to shutdown section 2025-03-24 08:49:30 -04:00
Peter Zhu
31cf2684b0 Output object_id in object metadata for MMTk 2025-03-13 10:12:24 -04:00
Peter Zhu
bdb25959fb Move object_id to flags for ObjectSpace dumps
Moving object_id dumping from ObjectSpace to the GC flags allows ObjectSpace
to not assume the FL_SEEN_OBJ_ID flag and instead move it to the responsibility
of the GC.
2025-03-13 10:12:24 -04:00
Kunshan Wang
aa7b5e2df4 [ruby/mmtk] Trigger forced GC in GC.start
We now use `MMTK::handle_user_collection_request(true, ...)` to force
triggering a GC instead of enabling GC temporarily.

02ef47f818
2025-02-24 23:30:00 +00:00
Peter Zhu
0f1cb92345 [ruby/mmtk] Fix compatibility for Rust 1.85
9da566e26a
2025-02-20 19:35:38 +00:00
Peter Zhu
49e229b3fc Fix value of RB_GC_OBJECT_METADATA_ENTRY_COUNT
There are 7 entries in RB_GC_OBJECT_METADATA_ENTRY_COUNT.
2025-02-19 09:56:17 -05:00
Peter Zhu
5e45f2a0bc Add age to rb_gc_object_metadata
This will allow ObjectSpace.dump to output the age of the object.
2025-02-19 09:47:28 -05:00
Peter Zhu
5acfe30880 Implement rb_gc_object_metadata for MMTk 2025-02-19 09:47:28 -05:00
Peter Zhu
7b6e07ea93 Add rb_gc_object_metadata API
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.
2025-02-19 09:47:28 -05:00
Yuta Saito
eac35edfd1 [wasm] Stop using mprotect(PROT_NONE) on WASI
we had been using a stub weak definition of `mprotect` in wasm/missing.c
so far, but wasi-sdk 23 added mprotect emulation to wasi-libc[^1], so the
emulation is now linked instead. However, the emulation doesn't support
PROT_NONE and fails with ENOSYS, so we need to avoid calling mprotect
completely on WASI.

[^1]: 7528b13170
2025-02-19 11:46:12 +09:00
Peter Zhu
b74077c19e [ruby/mmtk] Set Immix as the default plan
e52b973611
2025-02-10 20:37:10 +00:00
Daisuke Aritomo
c7e35e5534 gc.c: Remove no-op code
In this context, `vm_locked` is a argument variable, and is not used
later in the function.
2025-02-10 14:21:10 -05:00
Peter Zhu
de45755de8 Use an identity hash instead of array for stress_to_class 2025-01-29 13:22:04 -05:00
Peter Zhu
5e644e80e9 Fix GC.add_stress_to_class and GC.remove_stress_to_class
These methods were accidentally removed in [Feature #20470]. This commit
adds them back.
2025-01-29 13:22:04 -05:00
Nobuyoshi Nakada
be44d5677d
Suppress unused-value warnings 2025-01-29 16:57:16 +09:00
Peter Zhu
cb9aeb283b Fix gc_update_references_weak_table_i for ASAN
If the object is a T_MOVED, then it is poisoned in ASAN, so we need to
unpoison it before checking the type.
2025-01-27 13:26:26 -05:00
Peter Zhu
feec48ae2b Fix rb_gc_vm_weak_table_foreach compatibility for MMTK 2025-01-27 10:28:36 -05:00
Peter Zhu
98b36f6f36 Use rb_gc_vm_weak_table_foreach for reference updating
We can use rb_gc_vm_weak_table_foreach for reference updating of weak tables
in the default GC.
2025-01-27 10:28:36 -05:00
Peter Zhu
9e5ff79c5b Optionally traverse non-weak references in rb_gc_vm_weak_table_foreach
For moving garbage collectors, we may want to combine liveliness checking
with reference updating for performance. This commit allows for non-weak
references to be passed into the callback function when weak_only is false.
2025-01-27 10:28:36 -05:00
Peter Zhu
4df16051be [ruby/mmtk] Remove unused lazy_static dependency
f47a1e2d17
2025-01-22 16:07:04 +00:00
Peter Zhu
89240eb2fb Add generic ivar reference updating step
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.
2025-01-22 08:54:52 -05:00
Peter Zhu
be66448311 [ruby/mmtk] Bump mmtk-core
Fixes a bug where there is an infinite loop when MMTK_HEAP_MIN is small.

12c7ede20b
2025-01-21 17:02:18 +00:00
Peter Zhu
5fceba6614 [ruby/mmtk] Add mmtk_heap_max to GC.config
6a78ffaf16
2025-01-17 15:44:24 +00:00
Peter Zhu
179899c616 [ruby/mmtk] Add mmtk_heap_min to GC.config
5bbac70c69
2025-01-16 21:40:31 +00:00
Peter Zhu
d1a30359b1 [ruby/mmtk] Bump mmtk-core
52b857ea04
2025-01-16 16:20:05 +00:00
Peter Zhu
2538f4d521 [ruby/mmtk] Add mmtk_heap_mode to GC.config
810f897603
2025-01-16 16:20:04 +00:00
Peter Zhu
ab1565ebe3 [ruby/mmtk] Add mmtk_plan to GC.config
67da9ea5b8
2025-01-15 18:08:03 +00:00
Peter Zhu
e02c7491e9 [ruby/mmtk] Fix mmtk.h
dbb4036be9
2025-01-15 17:55:32 +00:00
Peter Zhu
cb6476a34e [ruby/mmtk] Bump mmtk-core
https://github.com/mmtk/mmtk-core/pull/1261 fixes an issue where the following
script causes a Rust panic:

    GC.disable
    10_000.times { Object.new }
    puts GC.stat

6191ee994a
2025-01-15 15:13:36 +00:00
Peter Zhu
f1e32914eb [ruby/mmtk] Add mmtk_worker_count to GC.config
836a9059cb
2025-01-14 20:59:39 +00:00
Peter Zhu
f5fa1ee5f6 [ruby/mmtk] Exit with error message if MMTK_PLAN is invalid
79ce2008a3
2025-01-14 17:17:44 +00:00
Peter Zhu
2bcbc80fa2 [ruby/mmtk] Exit with error message if MMTK_HEAP_MODE is invalid
c8b1f4c156
2025-01-14 17:07:21 +00:00
Nobuyoshi Nakada
1758137ead Simplify gc/mmtk/extconf.rb
- Split static recipes to depend file.
- Modify makefile configurations in the block to `create_makefile`.
- Expand rust sources in extconf.rb instead of GNU make extension.

TODO: pass `CARGO_TARGET_DIR` without shell syntax.
2025-01-14 10:21:57 -05:00