579 Commits

Author SHA1 Message Date
John Hawthorn
f483befd90 Add shape_id to RBasic under 32 bit
This makes `RBobject` `4B` larger on 32 bit systems
but simplifies the implementation a lot.

[Feature #21353]

Co-authored-by: Jean Boussier <byroot@ruby-lang.org>
2025-05-26 10:31:54 +02:00
Nobuyoshi Nakada
aad9fa2853
Use RB_VM_LOCKING 2025-05-25 15:22:43 +09:00
John Hawthorn
05cdcfcefd Only call RCLASS_SET_ALLOCATOR on T_CLASS objects
It's invalid to set an allocator on a T_ICLASS or T_MODULE, as those use
the other fields from the union.
2025-05-23 10:33:48 -07:00
John Hawthorn
11ad7f5f47 Don't use namespaced classext for superclasses
Superclasses can't be modified by user code, so do not need namespace
indirection. For example Object.superclass is always BasicObject, no
matter what modules are included onto it.
2025-05-23 10:22:24 -07:00
Aaron Patterson
e32054736f Remove assertion on field in class_duplicate_iclass_classext
`ext` is newly allocated so it shouldn't need an assertion. The class
ext (which is always from the module) that we're passing to
`class_duplicate_iclass_classext` could legitimately have instance
variables on it.  We just want to avoid copying them.

The assertion was making this crash:

```
$ RUBY_NAMESPACE=1 ./miniruby -e1
```
2025-05-22 22:12:42 -07:00
Jean Boussier
f18883b295 Namespaces: Don't initialize fields for T_ICLASS
ICLASS don't have instance variables or anything like that.

`gc_mark_classext_iclass` didn't mark it, and `classext_iclass_free`
wasn't freeing it.
2025-05-22 12:10:10 +02:00
Aaron Patterson
6df6aaa036 Update class.c
Co-authored-by: Satoshi Tagomori <tagomoris@gmail.com>
2025-05-21 09:51:32 -07:00
Aaron Patterson
6ea893f376 Add assertion for RCLASS_SET_PRIME_CLASSEXT_WRITABLE
When classes are booted, they should all be writeable unless namespaces
are enabled.  This commit adds an assertion to ensure that classes are
writable.
2025-05-21 09:51:32 -07:00
Jean Boussier
130d6aaef2 Reclaim one VALUE from rb_classext_t by shrinking super_classdepth
By making `super_classdepth` `uint16_t`, classes and modules can
now fit in 160B slots again.

The downside of course is that before `super_classdepth` was large
enough we never had to care about overflow, as you couldn't
realistically create enough classes to ever go over it.

With this change, while it is stupid, you could realistically
create an ancestor chain containing 65k classes and modules.
2025-05-14 10:17:03 +02:00
Satoshi Tagomori
8ecc04dc04 Delete code for debugging namespace 2025-05-11 23:32:50 +09:00
Satoshi Tagomori
294b52fb9b Follow the code style about else 2025-05-11 23:32:50 +09:00
Satoshi Tagomori
90e5ce6132 Rename RCLASS_EXT() macro to RCLASS_EXT_PRIME() to prevent using it wrongly
The macro RCLASS_EXT() accesses the prime classext directly, but it can be
valid only in a limited situation when namespace is enabled.
So, to prevent using RCLASS_EXT() in the wrong way, rename the macro and
let the developer check it is ok to access the prime classext or not.
2025-05-11 23:32:50 +09:00
Satoshi Tagomori
ff790c759e Compact prime classext readable/writable flags
To make RClass size smaller, move flags of prime classext readable/writable to:
 readable - use ns_classext_tbl is NULL or not (if NULL, it's readable)
 writable - use FL_USER2 of RBasic flags
2025-05-11 23:32:50 +09:00
Satoshi Tagomori
5ee1ec313a initialize method tables before any GC chance 2025-05-11 23:32:50 +09:00
Satoshi Tagomori
f24ba27d6d avoid calling ZALLOC after NEWOBJ_OF for RClass: need to return RClass not promoted 2025-05-11 23:32:50 +09:00
Satoshi Tagomori
382645d440 namespace on read 2025-05-11 23:32:50 +09:00
Peter Zhu
f30f0f0a22 Fix crash when instantiating classes in Ractors
[Bug #18119]

When we create classes, it pushes the class to the subclass list of the
superclass. This access needs to be synchronized because multiple Ractors
may be creating classes with the same superclass, which would cause race
conditions and cause the linked list to be corrupted.

For example, we can reproduce with this script crashing:

    workers = (0...8).map do
      Ractor.new do
        loop do
          100.times.map { Class.new }
          Ractor.yield nil
        end
      end
    end

    100.times { Ractor.select(*workers) }

With ASAN enabled, we can see that there are use-after-free errors:

    ==176013==ERROR: AddressSanitizer: heap-use-after-free on address 0x5030000974f0 at pc 0x62f9e56f892d bp 0x7a503f1ffd90 sp 0x7a503f1ffd88
    WRITE of size 8 at 0x5030000974f0 thread T4
        #0 0x62f9e56f892c in rb_class_remove_from_super_subclasses class.c:149:24
        #1 0x62f9e58c9dd2 in rb_gc_obj_free gc.c:1262:9
        #2 0x62f9e58f6e19 in gc_sweep_plane gc/default/default.c:3450:21
        #3 0x62f9e58f686a in gc_sweep_page gc/default/default.c:3535:13
        #4 0x62f9e58f12b4 in gc_sweep_step gc/default/default.c:3810:9
        #5 0x62f9e58ed2a7 in gc_sweep gc/default/default.c:4058:13
        #6 0x62f9e58fac93 in gc_start gc/default/default.c:6402:13
        #7 0x62f9e58e8b69 in heap_prepare gc/default/default.c:2032:13
        #8 0x62f9e58e8b69 in heap_next_free_page gc/default/default.c:2255:9
        #9 0x62f9e58e8b69 in newobj_cache_miss gc/default/default.c:2362:38
    ...
    0x5030000974f0 is located 16 bytes inside of 24-byte region [0x5030000974e0,0x5030000974f8)
    freed by thread T4 here:
        #0 0x62f9e562f28a in free (miniruby+0x1fd28a) (BuildId: 5ad6d9e7cec8318df6726ea5ce34d3c76d0d0233)
        #1 0x62f9e58ca2ab in rb_gc_impl_free gc/default/default.c:8102:9
        #2 0x62f9e58ca2ab in ruby_sized_xfree gc.c:5029:13
        #3 0x62f9e58ca2ab in ruby_xfree gc.c:5040:5
        #4 0x62f9e56f88e6 in rb_class_remove_from_super_subclasses class.c:152:9
        #5 0x62f9e58c9dd2 in rb_gc_obj_free gc.c:1262:9
        #6 0x62f9e58f6e19 in gc_sweep_plane gc/default/default.c:3450:21
        #7 0x62f9e58f686a in gc_sweep_page gc/default/default.c:3535:13
        #8 0x62f9e58f12b4 in gc_sweep_step gc/default/default.c:3810:9
        #9 0x62f9e58ed2a7 in gc_sweep gc/default/default.c:4058:13
    ...
    previously allocated by thread T5 here:
        #0 0x62f9e562f70d in calloc (miniruby+0x1fd70d) (BuildId: 5ad6d9e7cec8318df6726ea5ce34d3c76d0d0233)
        #1 0x62f9e58c8e1a in calloc1 gc/default/default.c:1472:12
        #2 0x62f9e58c8e1a in rb_gc_impl_calloc gc/default/default.c:8138:5
        #3 0x62f9e58c8e1a in ruby_xcalloc_body gc.c:4964:12
        #4 0x62f9e58c8e1a in ruby_xcalloc gc.c:4958:34
        #5 0x62f9e56f906e in push_subclass_entry_to_list class.c:88:13
        #6 0x62f9e56f906e in rb_class_subclass_add class.c:111:38
        #7 0x62f9e56f906e in RCLASS_SET_SUPER internal/class.h:257:9
        #8 0x62f9e56fca7a in make_metaclass class.c:786:5
        #9 0x62f9e59db982 in rb_class_initialize object.c:2101:5
2025-05-09 10:24:38 -04:00
Jean Boussier
0ea210d1ea Rename ivptr -> fields, next_iv_index -> next_field_index
Ivars will longer be the only thing stored inline
via shapes, so keeping the `iv_index` and `ivptr` names
would be confusing.

Instance variables won't be the only thing stored inline
via shapes, so keeping the `ivptr` name would be confusing.

`field` encompass anything that can be stored in a VALUE array.

Similarly, `gen_ivtbl` becomes `gen_fields_tbl`.
2025-05-08 07:58:05 +02:00
Xavier Noria
c5c0bb5afc Restore the original order of const_added and inherited callbacks
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
2025-04-10 10:20:31 +02:00
Jean Boussier
de097fbe5f Trigger inherited and const_set callbacks after const has been defined
[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`
2025-03-20 18:18:11 +01:00
Jean Boussier
de48e47ddf Invoke inherited callbacks before const_added
[Misc #21143]

Conceptually this makes sense and is more consistent with using
the `Name = Class.new(Superclass)` alternative method.

However the new class is still named before `inherited` is called.
2025-03-14 09:51:57 +01:00
Jeremy Evans
3b7892b6e4 Fix a bug in rb_include_module that stops nested inclusion into module subclasses
This bug was present since the code was originally added by me
in 3556a834a2847e52162d1d3302d4c64390df1694.

Fixes [Bug #20871]
2024-11-20 07:59:31 -08:00
Takashi Kokubun
dc64448202 Remove an unused variable 2024-09-19 10:14:17 -07:00
Jeremy Evans
6118e8a473 Fix method caching bug when including/prepend module A that prepends module B
Fix by always adding the generated iclass to the subclasses list,
otherwise the method cache for the iclass is not cleared when
the method in the module is overwritten.

Fixes [Bug #20716]
2024-09-19 07:34:01 -07:00
Jean Boussier
f06670c5a2 Eliminate usage of OBJ_FREEZE_RAW
Previously it would bypass the `FL_ABLE` check, but
since shapes introduction, it started having a different
behavior than `OBJ_FREEZE`, as it would onyl set the `FL_FREEZE`
flag, but not update the shape.

I have no indication of this causing a bug yet, but it seems
like a trap waiting to happen.
2024-04-16 17:20:35 +02:00
Takashi Kokubun
46bf6ae886
YJIT: Propagate Array, Hash, and String classes (#10323) 2024-03-25 12:06:47 -04:00
Takashi Kokubun
cbcb2d46fc
[DOC] Unify Doxygen formats (#10285) 2024-03-19 10:59:25 -07:00
Étienne Barrié
12be40ae6b Implement chilled strings
[Feature #20205]

As a path toward enabling frozen string literals by default in the future,
this commit introduce "chilled strings". From a user perspective chilled
strings pretend to be frozen, but on the first attempt to mutate them,
they lose their frozen status and emit a warning rather than to raise a
`FrozenError`.

Implementation wise, `rb_compile_option_struct.frozen_string_literal` is
no longer a boolean but a tri-state of `enabled/disabled/unset`.

When code is compiled with frozen string literals neither explictly enabled
or disabled, string literals are compiled with a new `putchilledstring`
instruction. This instruction is identical to `putstring` except it marks
the String with the `STR_CHILLED (FL_USER3)` and `FL_FREEZE` flags.

Chilled strings have the `FL_FREEZE` flag as to minimize the need to check
for chilled strings across the codebase, and to improve compatibility with
C extensions.

Notes:
  - `String#freeze`: clears the chilled flag.
  - `String#-@`: acts as if the string was mutable.
  - `String#+@`: acts as if the string was mutable.
  - `String#clone`: copies the chilled flag.

Co-authored-by: Jean Boussier <byroot@ruby-lang.org>
2024-03-19 09:26:49 +01:00
Jean Boussier
d4f3dcf4df Refactor VM root modules
This `st_table` is used to both mark and pin classes
defined from the C API. But `vm->mark_object_ary` already
does both much more efficiently.

Currently a Ruby process starts with 252 rooted classes,
which uses `7224B` in an `st_table` or `2016B` in an `RArray`.

So a baseline of 5kB saved, but since `mark_object_ary` is
preallocated with `1024` slots but only use `405` of them,
it's a net `7kB` save.

`vm->mark_object_ary` is also being refactored.

Prior to this changes, `mark_object_ary` was a regular `RArray`, but
since this allows for references to be moved, it was marked a second
time from `rb_vm_mark()` to pin these objects.

This has the detrimental effect of marking these references on every
minors even though it's a mostly append only list.

But using a custom TypedData we can save from having to mark
all the references on minor GC runs.

Addtionally, immediate values are now ignored and not appended
to `vm->mark_object_ary` as it's just wasted space.
2024-03-06 15:33:43 -05:00
Jean Boussier
b4a69351ec Move FL_SINGLETON to FL_USER1
This frees FL_USER0 on both T_MODULE and T_CLASS.

Note: prior to this, FL_SINGLETON was never set on T_MODULE,
so checking for `FL_SINGLETON` without first checking that
`FL_TYPE` was `T_CLASS` was valid. That's no longer the case.
2024-03-06 13:11:41 -05:00
Peter Zhu
476cd2b251 [DOC] Add comment about RUBY_FL_SINGLETON 2024-03-06 10:37:57 -05:00
Peter Zhu
7e44440774 [DOC] Fix indentation in comment in class.c 2024-03-06 10:36:46 -05:00
Jean Boussier
e626da82ea Don't pin named structs defined in Ruby
[Bug #20311]

`rb_define_class_under` assumes it's called from C and that the
reference might be held in a C global variable, so it adds the
class to the VM root.

In the case of `Struct.new('Name')` it's wasteful and make
the struct immortal.
2024-03-01 08:23:38 +01:00
Yusuke Endoh
25d74b9527 Do not include a backtick in error messages and backtraces
[Feature #16495]
2024-02-15 18:42:31 +09:00
Peter Zhu
28a6e4ea9d Set m_tbl right after allocation
We should set the m_tbl right after allocation before anything that can
trigger GC to avoid clone_p from becoming old and needing to fire write
barriers.

Co-authored-by: Aaron Patterson <tenderlove@ruby-lang.org>
2023-12-19 13:09:36 -08:00
Adam Hess
c42261059d [Bug #19901]
fix leak in module clone

Co-authored-by: Peter Zhu <peter@peterzhu.ca>
2023-09-23 23:10:46 +02:00
Nobuyoshi Nakada
4634405f7c
Stop exposing FrozenCore in headers
Revert commit "Directly allocate FrozenCore as an ICLASS",
813a5f4fc46a24ca1695d23c159250b9e1080ac7.
2023-09-19 14:08:05 +09:00
Matt Valentine-House
d426343418 Store object age in a bitmap
Closes [Feature #19729]

Previously 2 bits of the flags on each RVALUE are reserved to store the
number of GC cycles that each object has survived. This commit
introduces a new bit array on the heap page, called age_bits, to store
that information instead.

This patch still reserves one of the age bits in the flags (the old
FL_PROMOTED0 bit, now renamed FL_PROMOTED).

This is set to 0 for young objects and 1 for old objects, and is used as
a performance optimisation for the write barrier. Fetching the age_bits
from the heap page and doing the required math to calculate if the
object was old or not would slow down the write barrier. So we keep this
bit synced in the flags for fast access.
2023-07-13 09:21:36 +01:00
Nobuyoshi Nakada
b934976024
Prefer 0 over NULL as function pointers
SunC warns use of `NULL`, pointer to data as function pointers.
2023-06-23 03:15:55 +09:00
Peter Zhu
813a5f4fc4 Directly allocate FrozenCore as an ICLASS
It's a bad idea to overwrite the flags as the garbage collector may have
set other flags.
2023-06-14 10:42:40 -04:00
eileencodes
40f090f433 Revert "Revert "Fix cvar caching when class is cloned""
This reverts commit 10621f7cb9a0c70e568f89cce47a02e878af6778.

This was reverted because the gc integrity build started failing. We
have figured out a fix so I'm reopening the PR.

Original commit message:

Fix cvar caching when class is cloned

The class variable cache that was added in
ruby#4544 changed the behavior of class
variables on cloned classes. As reported when a class is cloned AND a
class variable was set, and the class variable was read from the
original class, reading a class variable from the cloned class would
return the value from the original class.

This was happening because the IC (inline cache) is stored on the ISEQ
which is shared between the original and cloned class, therefore they
share the cache too.

To fix this we are now storing the `cref` in the cache so that we can
check if it's equal to the current `cref`. If it's different we don't
want to read from the cache. If it's the same we do. Cloned classes
don't share the same cref with their original class.

This will need to be backported to 3.1 in addition to 3.2 since the bug
exists in both versions.

We also added a marking function which was missing.

Fixes [Bug #19379]

Co-authored-by: Aaron Patterson <tenderlove@ruby-lang.org>
2023-06-05 11:11:12 -07:00
Aaron Patterson
10621f7cb9
Revert "Fix cvar caching when class is cloned"
This reverts commit 77d1b082470790c17c24a2f406b4fec5d522636b.
2023-06-01 14:55:36 -07:00
eileencodes
77d1b08247 Fix cvar caching when class is cloned
The class variable cache that was added in
https://github.com/ruby/ruby/pull/4544 changed the behavior of class
variables on cloned classes. As reported when a class is cloned AND a
class variable was set, and the class variable was read from the
original class, reading a class variable from the cloned class would
return the value from the original class.

This was happening because the IC (inline cache) is stored on the ISEQ
which is shared between the original and cloned class, therefore they
share the cache too.

To fix this we are now storing the `cref` in the cache so that we can
check if it's equal to the current `cref`. If it's different we don't
want to read from the cache. If it's the same we do. Cloned classes
don't share the same cref with their original class.

This will need to be backported to 3.1 in addition to 3.2 since the bug
exists in both versions.

We also added a marking function which was missing.

Fixes [Bug #19379]

Co-authored-by: Aaron Patterson <tenderlove@ruby-lang.org>
2023-06-01 08:52:48 -07:00
Peter Zhu
ae90fa981a [DOC] Documentation for flags of RClass 2023-04-20 16:53:13 -04:00
Peter Zhu
a0d1069e03 Make classes embedded on 32 bit
Classes are now exactly 80 bytes when embedded, which perfectly fits the
3rd size pool on 32 bit systems.
2023-04-16 11:06:31 -04:00
Peter Zhu
d7bb7e70cc Change RMODULE_ALLOCATED_BUT_NOT_INITIALIZED
RCLASS_CLONED no longer uses FL_USER1, so we can make
RMODULE_ALLOCATED_BUT_NOT_INITIALIZED use FL_USER1.
2023-04-16 11:06:31 -04:00
Peter Zhu
ad3d4e87d7 Move RCLASS_CLONED to rb_classext_struct
This commit moves RCLASS_CLONED from the flags to the
rb_classext_struct. This frees the FL_USER1 bit.
2023-04-16 11:06:31 -04:00
Matt Valentine-House
026321c5b9 [Feature #19474] Refactor NEWOBJ macros
NEWOBJ_OF is now our canonical newobj macro. It takes an optional ec
2023-04-06 11:07:16 +01:00
Nobuyoshi Nakada
00d6772e40
Adjust styles [ci skip] 2023-03-08 14:02:46 +09:00
Takashi Kokubun
233ddfac54 Stop exporting symbols for MJIT 2023-03-06 21:59:23 -08:00