552 Commits

Author SHA1 Message Date
É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
Jean Boussier
1a4b4cd7f8 Move attached_object into rb_classext_struct
Given that signleton classes don't have an allocator,
we can re-use these bytes to store the attached object
in `rb_classext_struct` without making it larger.
2023-02-16 08:14:44 +01:00
Jean Boussier
7413079dae Encapsulate RCLASS_ATTACHED_OBJECT
Right now the attached object is stored as an instance variable
and all the call sites that either get or set it have to know how it's
stored.

It's preferable to hide this implementation detail behind accessors
so that it is easier to change how it's stored.
2023-02-15 15:24:22 +01:00
eileencodes
b9e6580135 Copy cvar table on clone
When a class with a class variable is cloned we need to also copy the
cvar cache table from the original table to the clone. I found this bug
while working on fixing [Bug #19379]. While this does not fix that bug
directly it is still a required change to fix another bug revealed by
the fix in https://github.com/ruby/ruby/pull/7265

This needs to be backported to 3.2.x and 3.1.x.

Co-authored-by: Aaron Patterson <tenderlove@ruby-lang.org>
2023-02-09 11:24:32 -08:00
Nobuyoshi Nakada
1bb0749c5b [DOC] Move the internal document for Init_class_hierarchy
It has hidden the document for `Object` class.
2023-01-04 01:18:24 +09:00
zverok
f07897fd7b [DOC] Clarify Class#subclases behavior quirks
As per discussion in [Feature #18273], explain the
non-deterministic nature of the method.
2022-12-11 18:43:44 +02:00
Alan Wu
bb8afd7265 Freeze singleton class, not its origin
Previously, when we froze an object, we froze
`RCLASS_ORIGIN(object.singleton_class)`, which didn't freeze
`object.singleton_class` when it has some prepended modules.

Origin iclass are internal objects and users can't interact with
them through Kernel#freeze?, Kernel#freeze, or any mutation method
that checks the frozen status. So we shouldn't touch the origin
iclasses when the frozen status should be visible.

[Bug #19169]
2022-12-08 15:58:26 -05:00
John Hawthorn
da204d2eee Inherit max_iv_count from superclass
In 274870bd5434ab64ac3a3c9db9aa27d262c1d6d6 we gained the ability to
make an educated guess at the max_iv_count of a class based on its
initialize method. This commit makes subclasses inherit their super's
max_iv_count, which makes the estimate work in cases that the subclass
does not have an initialize method.
2022-12-01 15:37:15 -08:00
S-H-GAMELINKS
1f4f6c9832 Using UNDEF_P macro 2022-11-16 18:58:33 +09:00
Jemma Issroff
5246f4027e Transition shape when object's capacity changes
This commit adds a `capacity` field to shapes, and adds shape
transitions whenever an object's capacity changes. Objects which are
allocated out of a bigger size pool will also make a transition from the
root shape to the shape with the correct capacity for their size pool
when they are allocated.

This commit will allow us to remove numiv from objects completely, and
will also mean we can guarantee that if two objects share shapes, their
IVs are in the same positions (an embedded and extended object cannot
share shapes). This will enable us to implement ivar sets in YJIT using
object shapes.

Co-Authored-By: Aaron Patterson <tenderlove@ruby-lang.org>
2022-11-10 10:11:34 -05:00
John Hawthorn
02f1554224
Implement object shapes for T_CLASS and T_MODULE (#6637)
* Avoid RCLASS_IV_TBL in marshal.c
* Avoid RCLASS_IV_TBL for class names
* Avoid RCLASS_IV_TBL for autoload
* Avoid RCLASS_IV_TBL for class variables
* Avoid copying RCLASS_IV_TBL onto ICLASSes
* Use object shapes for Class and Module IVs
2022-10-31 14:05:37 -07:00
Jemma Issroff
13bd617ea6 Remove unused class serial
Before object shapes, we were using class serial to invalidate
inline caches. Now that we use shape_id for inline cache keys,
the class serial is unnecessary.

Co-Authored-By: Aaron Patterson <tenderlove@ruby-lang.org>
2022-10-21 14:56:48 -07:00
Ufuk Kayserilioglu
0378e2f4a8 Add Class#attached_object
Implements [Feature #12084]

Returns the object for which the receiver is the singleton class, or
raises TypeError if the receiver is not a singleton class.
2022-10-20 17:30:17 +02:00
S-H-GAMELINKS
ee8bcbf405 Reuse ins_methods_type_i function 2022-10-14 18:31:15 +09:00
John Hawthorn
a74f4cded2 Remove reference to __classid__
This used to be used for module names but its uses were removed in
b00f280d4b9569e7153365d7e1c522b3d6b3c6cf.
2022-09-23 15:57:02 -07:00
Jeremy Evans
f5f81bb777 Update Module#instance_methods documentation for visibility changes/aliases
Requested by matz in comment on #18435.
2022-08-24 14:15:41 -07:00
Peter Zhu
efb91ff19b Rename rb_ary_tmp_new to rb_ary_hidden_new
rb_ary_tmp_new suggests that the array is temporary in some way, but
that's not true, it just creates an array that's hidden and not on the
transient heap. This commit renames it to rb_ary_hidden_new.
2022-07-26 09:12:09 -04:00
Takashi Kokubun
5b21e94beb Expand tabs [ci skip]
[Misc #18891]
2022-07-21 09:42:04 -07:00
Jeremy Evans
7cda7fbbdc
Add Module#undefined_instance_methods
Implements [Feature #12655]

Co-authored-by: Nobuyoshi Nakada <nobu@ruby-lang.org>
2022-06-06 09:57:32 -07:00
Jemma Issroff
33fdff3c30 Remove unused RMODULE_INCLUDED_INTO_REFINEMENT flag 2022-05-26 12:09:04 -07:00
Jemma Issroff
80ad0e751f Remove unnecessary module flag, add module assertions to other module flags 2022-05-23 11:04:34 -07:00
Alan Wu
7448afccb3 Fix potential GC issue while iterating over weak refs
While walking over the list of subclasses for `include` and friends, we
check whether the subclass is a garbage object. After the check, we
allocate objects which might trigger GC and make the subclass garbage,
even though before the allocation the subclass was not garbage. This is
a sort of time-of-check-time-of-use issue.

Fix this by saving the weak reference to a local variable, upgrading it
to a strong reference while we do the allocation. It makes the code look
slightly nicer even if it doesn't fix any runtime issues.
2022-05-05 17:37:07 -04:00
John Hawthorn
7950c4eb2d Fix class ancestry checks for duped classes
Previously in some when classes were duped (specifically those with a
prepended module), they would not correctly have their "superclasses"
array or depth filled in.

This could cause ancestry checks (like is_a? and Module comparisons) to
return incorrect results.

This happened because rb_mod_init_copy builds origin classes in an order
that doesn't have the super linked list fully connected until it's
finished. This commit fixes the previous issue by calling
rb_class_update_superclasses before returning the cloned class. This is
similar to what's already done in make_metaclass.
2022-04-16 11:40:56 -07:00
Kevin Newton
6068da8937 Finer-grained constant cache invalidation (take 2)
This commit reintroduces finer-grained constant cache invalidation.
After 8008fb7 got merged, it was causing issues on token-threaded
builds (such as on Windows).

The issue was that when you're iterating through instruction sequences
and using the translator functions to get back the instruction structs,
you're either using `rb_vm_insn_null_translator` or
`rb_vm_insn_addr2insn2` depending if it's a direct-threading build.
`rb_vm_insn_addr2insn2` does some normalization to always return to
you the non-trace version of whatever instruction you're looking at.
`rb_vm_insn_null_translator` does not do that normalization.

This means that when you're looping through the instructions if you're
trying to do an opcode comparison, it can change depending on the type
of threading that you're using. This can be very confusing. So, this
commit creates a new translator function
`rb_vm_insn_normalizing_translator` to always return the non-trace
version so that opcode comparisons don't have to worry about different
configurations.

[Feature #18589]
2022-04-01 14:48:22 -04:00
Nobuyoshi Nakada
69967ee64e
Revert "Finer-grained inline constant cache invalidation"
This reverts commits for [Feature #18589]:
* 8008fb7352abc6fba433b99bf20763cf0d4adb38
  "Update formatting per feedback"
* 8f6eaca2e19828e92ecdb28b0fe693d606a03f96
  "Delete ID from constant cache table if it becomes empty on ISEQ free"
* 629908586b4bead1103267652f8b96b1083573a8
  "Finer-grained inline constant cache invalidation"

MSWin builds on AppVeyor have been crashing since the merger.
2022-03-25 20:29:09 +09:00
Kevin Newton
8008fb7352 Update formatting per feedback
Co-authored-by: Nobuyoshi Nakada <nobu@ruby-lang.org>
2022-03-24 09:14:38 -07:00
Kevin Newton
629908586b Finer-grained inline constant cache invalidation
Current behavior - caches depend on a global counter. All constant mutations cause caches to be invalidated.

```ruby
class A
  B = 1
end

def foo
  A::B # inline cache depends on global counter
end

foo # populate inline cache
foo # hit inline cache

C = 1 # global counter increments, all caches are invalidated

foo # misses inline cache due to `C = 1`
```

Proposed behavior - caches depend on name components. Only constant mutations with corresponding names will invalidate the cache.

```ruby
class A
  B = 1
end

def foo
  A::B # inline cache depends constants named "A" and "B"
end

foo # populate inline cache
foo # hit inline cache

C = 1 # caches that depend on the name "C" are invalidated

foo # hits inline cache because IC only depends on "A" and "B"
```

Examples of breaking the new cache:

```ruby
module C
  # Breaks `foo` cache because "A" constant is set and the cache in foo depends
  # on "A" and "B"
  class A; end
end

B = 1
```

We expect the new cache scheme to be invalidated less often because names aren't frequently reused. With the cache being invalidated less, we can rely on its stability more to keep our constant references fast and reduce the need to throw away generated code in YJIT.
2022-03-24 09:14:38 -07:00
Peter Zhu
97426e15d7 [Bug #18627] Fix crash when including module
During lazy sweeping, the iclass could be a dead object that has not yet
been swept. However, the chain of superclasses of the iclass could
already have been swept (and become a new object), which would cause a
crash when trying to read the object.
2022-03-18 09:19:11 -04:00