591 Commits
Author SHA1 Message Date
John HawthornandLuke Gruber f3a72fe0a6 [Bug #22242] Invalidate CCs on cc_table_dup
When a Ractor is started, rather than modifying the cc table in place we
make a copy and CAS the table. When making the copy we previously
skipped cc_entries with an invalidated CME. However, that left the CCs
associated with that entry orphaned. CCs do not mark their CME, and the
CAS removed the table from the live set, so nothing invalidated the CC
and it ended up pointing at a garbage object.

Co-authored-by: Luke Gruber <luke.gru@gmail.com>
2026-08-26 14:27:32 -07:00
Satoshi Tagomori b23f46c1fa [Box] make the tmp array safe
* Using rb_ary_hidden_new() to hide this array
  from ObjectSpace.each_object
* Call RB_GC_GUARD to not collect this value in GC
2026-06-22 09:57:10 -07:00
Satoshi Tagomori a700301788 [Box] Invalidate callable me on per-box origin IClasses 2026-06-22 09:57:10 -07:00
Satoshi Tagomori 6765a5f646 [Box] Invalidate the method cache of the owner too
The owner could be different from the housing class when the housing
module is prepended.
2026-06-22 09:57:10 -07:00
John Hawthorn a08f356063 Use atomics for kwargs reference count
Fixes [Bug #22075]
2026-05-21 11:17:29 -07:00
John Hawthorn 0e9a0ad996 Fix missing writebarrier on refined orig_me
Caught by wbcheck. The same field is written with RB_OBJ_WRITE
in rb_method_definition_set.
2026-05-05 13:27:43 -07:00
John Hawthorn 2b22593ac1 Simplify subclasses list, remove from Box
Currently we maintain the subclasses list for two separate purposes (we essentially have to different relationships we're putting into the same list):

1. On a T_MODULE, we track the T_ICLASSes created to include it into
   other classes. Used for method invalidation and propagating includes
   on the module that happen after it's been used
2. On a T_CLASS/T_ICLASS, we track the T_CLASS/T_ICLASS which are the
   immediate children of the class. We use this for method invalidation,
   some cvar things, and to iterate through subclasses.

Purpose 1 does not have any issues with box, the T_ICLASS always belongs
to one specific module and that's immutable. This list can be box-global
(always use the prime classext or hoist it out) and only needs to be
pruned during free. If we care about behaviour under a particular box
(ie. the propagating includes), we should look up the current box being
modified on the ICLASS itself.

Purpose 2 is more complicated. It currently tracks the immediate
children, the T_CLASS or T_ICLASS whose super points back. Because super
is per-box and is mutable (include/prepend insert ICLASSes into the
chain) we need to update the list on include/prepend, entries must be
per-box, and we can have multiple entries per-box. *I propose we
simplify this by no longer tracking the immediate subclass*, but instead
tracking the T_CLASS -> ... -> T_CLASS relationship, ie. the inverse of
rb_class_superclass. That relationship is the same across all boxes and
immutable after Class creation.

As a special case the ICLASS for refinements are also added to the
purpose 2 list (on T_CLASS). As those ICLASS do not chain to an eventual
leaf T_CLASS.

When we need to find the classes which have included a module, we can
use the module subclasses list to find the ICLASS and then use
RCLASS_INCLUDER. If we needed to iterate all T_ICLASS, we could then
walk up the CLASS_SUPER chain, but I didn't find anywhere we needed to
do that.
2026-03-19 17:57:58 -07:00
John Hawthorn d9c0d4c71c Don't copy invalidated CME in rb_vm_cc_table_dup
The cc_entries list associated with the invalidated CME can be deleted
from the table during GC, so it isn't safe to copy (and we shouldn't
copy it anyways, it's stale data).
2025-12-19 12:06:29 -08:00
John HawthornandLuke Gruber 63b082cf0e Store ractor_id directly on EC
This is easier to access as ec->ractor_id instead of pointer-chasing through
ec->thread->ractor->ractor_id

Co-authored-by: Luke Gruber <luke.gru@gmail.com>
2025-12-18 13:43:45 -08:00
Luke Gruber 4fb537b1ee Make tracepoints with set_trace_func or TracePoint.new ractor local (#15468)
Before this change, GC'ing any Ractor object caused you to lose all
enabled tracepoints across all ractors (even main). Now tracepoints are
ractor-local and this doesn't happen. Internal events are still global.

Fixes [Bug #19112]
2025-12-16 14:06:55 -05:00
John Hawthorn 32e6dc0f31 Speed up class allocator search
This rewrites the class allocator search to be faster. Instead of using
RCLASS_SUPER, which is now even slower due to Box, we can scan the
superclasses list to find a class where the allocator is defined.

This also disallows allocating from an ICLASS. Previously I believe that
was only done for FrozenCore, and that was changed in
e596cf6e93.
2025-12-11 09:53:10 -08:00
Jeremy Evans 1e7cf7b2bc Fix refinement modification of method visibility in superclass
Previously, this didn't work correctly, resulting in a
SystemStackError. This fixes the issue by finding the related
superclass method entry, and updating the orig_me in the
refinement method to point to the superclass method.

Fixes [Bug #21446]
2025-12-10 06:19:52 +09:00
John HawthornandLuke Gruber 1d3fe2c382 Change bmethod defined_ractor to use id instead
When defining a bmethod, we recorded the current Ractor's object in the
method. However that was never marked and so could be GC'd and reused by
a future Ractor. Instead we can use the Ractor's id, which we expect to
be unique forever.

Co-authored-by: Luke Gruber <luke.gru@gmail.com>
2025-12-04 13:25:45 -08:00
Peter Zhu bcfcfedc30 Fix memory leak in invalidate_ccs_in_iclass_cc_tbl
invalidate_ccs_in_iclass_cc_tbl deletes the ccs from the table but never
frees it, causing memory to leak.
2025-11-12 03:48:59 -08:00
Nobuyoshi Nakada a4dff09be7 [Bug #21673] Fix resolving refined module-defined method
A method defined in a module has no `defined_class`, use the ICLASS
for it as the `defined_class`.
2025-11-09 16:39:38 +09:00
Satoshi Tagomori d2a587c791 renaming internal data structures and functions from namespace to box 2025-11-07 13:14:54 +09:00
Peter Zhu b66fbd59ae Make rb_vm_ccs_invalidate_and_free static 2025-10-26 15:27:14 -04:00
Koichi Sasada bc00c4468e use SET_SHAREABLE
to adopt strict shareable rule.

* (basically) shareable objects only refer shareable objects
* (exception) shareable objects can refere unshareable objects
  but should not leak reference to unshareable objects to Ruby world
2025-10-23 13:08:26 +09:00
Peter Zhu 14cdd88970 [Bug #21620] Fix strict aliasing in rb_managed_id_table_lookup
We cannot pass &ccs into rb_managed_id_table_lookup because rb_managed_id_table_lookup
takes in a VALUE*, so it violates strict aliasing in C. This causes segfaults
when compiling with LTO enabled.
2025-10-03 09:20:53 -04:00
Alan Wu 328d2037a6 ZJIT: Remove dead CMEs from Invariants 2025-09-25 18:36:58 -04:00
John Hawthorn 4afc6370cb Add missing locks to method table 2025-09-22 09:59:35 -07:00
Takashi Kokubun 51cd877636 ZJIT: Add missing rb_zjit_cme_invalidate 2025-08-28 15:46:16 -07:00
John Hawthorn 823d55a827 Add lock-free fastpath to callable_method_entry... 2025-08-21 15:42:14 -07:00
Jeremy Evans acb29f7fa1 Do not respect ruby2_keywords on method/proc with post arguments
Previously, ruby2_keywords could be used on a method or proc with
post arguments, but I don't think the behavior is desired:

```ruby
def a(*c, **kw) [c, kw] end
def b(*a, b) a(*a, b) end
ruby2_keywords(:b)

b({foo: 1}, bar: 1)
```

This changes ruby2_keywords to emit a warning and not set the
flag on a method/proc with post arguments.

While here, fix the ruby2_keywords specs for warnings, since they
weren't testing what they should be testing.  They all warned
because the method didn't accept a rest argument, not because it
accepted a keyword or keyword rest argument.
2025-08-22 00:46:57 +09:00
John Hawthorn feb8331673 Atomic CC table set in cache_callable_method_entry 2025-08-21 09:17:31 +02:00
Peter Zhu 2c7ec3d155 Fix race condition in method invalidation for Ractors
We lock the VM to invalidate method entries. However, we do not lock the
VM to call methods, so it's possible that during a method call the method
entry gets invalidated. We only check that the method entry in the callcache
is not invalidated at the beginning of the method call, which makes it
possible to have race conditions. This causes crashes like:

    vm_callinfo.h:421: Assertion Failed: vm_cc_cme:cc->klass != Qundef || !vm_cc_markable(cc)
    vm_insnhelper.c:2200: Assertion Failed: vm_lookup_cc:!METHOD_ENTRY_INVALIDATED(vm_cc_cme(ccs_cc))

This commit adds a VM barrier to method cache invalidation to ensure that
other Ractors are stopped at a safe-point before invalidating the method
entry.
2025-08-20 15:53:00 -04:00
Peter Zhu 9d484e3412 Fix indentation in clear_method_cache_by_id_in_class [ci skip] 2025-08-20 10:57:47 -04:00
John HawthornandPeter Zhu 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
John Hawthorn faa67506e5 Ensure CC entries always marked, add missing WB
Previously we were issuing writebarriers for each cc, but were missing
the cme.

We also need to avoid it being possible to run GC after we've copied the
values into the allocated array, but before they're visible in the
object.
2025-08-01 13:45:29 -07:00
Jean BoussierandÉtienne Barrié bc789ca804 Convert rb_class_cc_entries.entries in a flexible array member
`rb_class_cc_entries` is little more than a `len` and `capa`.
Hence embedding the entries doesn't cost much extra copying and
saves a bit of memory and some pointer chasing.

Co-Authored-By: Étienne Barrié <etienne.barrie@gmail.com>
2025-08-01 19:49:38 +02:00
Jean Boussier 547f111b5b Refactor vm_lookup_cc to allow lock-free lookups in RClass.cc_tbl
In multi-ractor mode, the `cc_tbl` mutations use the RCU pattern,
which allow lock-less reads.

Based on the assumption that invalidations and misses should be
increasingly rare as the process ages, locking on modification
isn't a big concern.
2025-08-01 10:42:04 +02:00
Jean Boussier f2a7e48dea Make RClass.cc_table a managed object
For now this doesn't change anything, but now that the table
is managed by GC, it opens the door to use RCU when in multi-ractor
mode, hence allow unsynchornized reads.
2025-08-01 10:42:04 +02:00
Jean Boussier fc5e1541e4 Use rb_gc_mark_weak for cc->klass.
One of the biggest remaining contention point is `RClass.cc_table`.
The logical solution would be to turn it into a managed object, so
we can use an RCU strategy, given it's read heavy.

However, that's not currently possible because the table can't
be freed before the owning class, given the class free function
MUST go over all the CC entries to invalidate them.

However if the `CC->klass` reference is weak marked, then the
GC will take care of setting the reference to `Qundef`.
2025-08-01 10:42:04 +02:00
Takashi Kokubun 2cd10de330 ZJIT: Prepare for sharing JIT hooks with ZJIT (#14044) 2025-07-30 10:11:10 -07:00
Stan Lo a0d0b84bad ZJIT: Support invalidating constant patch points (#13998) 2025-07-28 14:48:41 -07:00
Stan Lo 8df61bfc92 ZJIT: Support invalidating on method redefinition (#13875)
ZJIT: Support invalidating method redefinition

This commit adds support for the MethodRedefined invariant to be invalidated
when a method is redefined.

Changes:
- Added CME pointer to the MethodRedefined invariant in HIR
- Updated all places where MethodRedefined invariants are created to
    include the CME pointer
- Added handling for MethodRedefined invariants in gen_patch_point to
    call track_cme_assumption, which registers the patch point for
    invalidation when rb_zjit_cme_invalidate is called

This ensures that when a method is redefined, all JIT code that
depends on that method will be properly invalidated.
2025-07-18 15:36:51 +00:00
Vinicius Stock d1f38ce4ac Make protected documentation more explicit about differences (#13849)
[DOC] Make protected documentation more explicit about differences

Protected is a common source of confusion for devs
coming from different languages to Ruby. This
commit makes the documentation more explicit about
the differences, so that the use case for
protected is clearer.
2025-07-17 12:19:51 -07:00
Jeremy Evans 08d4f7893e Rename some set_* functions to set_table_*
These functions conflict with the planned C-API functions. Since they
deal with the underlying set_table pointers and not Set instances,
this seems like a more accurate name as well.
2025-07-11 15:24:23 +09:00
John Hawthorn 581da51cb5 Fix whitespace on some RB_VM_LOCKING calls 2025-07-09 17:28:47 -07:00
Luke Gruber 3c66eb3358 Change def->method_serial to be atomic
`rb_method_definition_create` can be called across different ractors at the same time, so `def->method_serial` should be atomic.
2025-06-25 15:43:57 -07:00
alpaca-tc c8ddc0a843 Optimize callcache invalidation for refinements
Fixes [Bug #21201]

This change addresses a performance regression where defining methods
inside `refine` blocks caused severe slowdowns. The issue was due to
`rb_clear_all_refinement_method_cache()` triggering a full object
space scan via `rb_objspace_each_objects` to find and invalidate
affected callcaches, which is very inefficient.

To fix this, I introduce `vm->cc_refinement_table` to track
callcaches related to refinements. This allows us to invalidate
only the necessary callcaches without scanning the entire heap,
resulting in significant performance improvement.
2025-06-09 12:33:35 +09:00
git aa00a2d07b * remove trailing spaces. [ci skip] 2025-05-26 02:44:58 +00:00
Nobuyoshi Nakada aad9fa2853 Use RB_VM_LOCKING 2025-05-25 15:22:43 +09:00
Satoshi Tagomori 382645d440 namespace on read 2025-05-11 23:32:50 +09:00
Alan Wu dd0e0eb4ac Delete always true assert [ci skip] 2025-05-02 21:06:11 +09:00
Jean Boussier c0417bd094 Use set_table to track const caches
Now that we have a `set_table` implementation, we can
use it to track const caches and save some memory.

We could even save some more memory if `numtable` didn't
store a copy of the `hash` and instead recomputed it every
time, but this is a quick win.
2025-04-26 12:10:32 +02:00
Nobuyoshi Nakada c218862d3c Fix style [ci skip] 2025-04-19 22:02:10 +09:00
John Hawthornandwanabe bfe6068417 Use atomic for method reference count [Bug #20934]
This changes reference_count on rb_method_definition_struct into an
atomic.

Ractors can create additional references as part of `bind_call` or
(presumably) similar. Because this can be done inside Ractors, we should
use a lock or atomics so that we don't race and avoid incrementing.

Co-authored-by: wanabe <s.wanabe@gmail.com>
2025-03-20 13:09:40 -07:00
Nobuyoshi Nakada 4a67ef09cc [Feature #21116] Extract RJIT as a third-party gem 2025-02-13 18:01:03 +09:00
Fabio Sangiovanni f0dc9dcdc7 rb_alias: improve "undefined method" error message by invoking
`rb_print_undef` with `target_klass` as argument.
2025-01-31 00:20:47 +09:00