Граф коммитов

545 Коммитов

Автор SHA1 Сообщение Дата
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",
813a5f4fc4.
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 10621f7cb9.

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 77d1b08247.
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
b00f280d4b.
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]:
* 8008fb7352
  "Update formatting per feedback"
* 8f6eaca2e1
  "Delete ID from constant cache table if it becomes empty on ISEQ free"
* 629908586b
  "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
Peter Zhu f38dcc78c4 Assume that klass of dummy head is NULL
klass of the dummy head of the subclass entries should always be NULL.
2022-03-16 15:19:30 -04:00
Peter Zhu 819f4f0e65 Always skip dummy head of subclass in rb_prepend_module
The first node of the subclass linked list of always a dummy head, so it
should be skipped.
2022-03-16 15:10:11 -04:00
John Hawthorn 19f331f588 Dedup superclass array in leaf sibling classes
Previously, we would build a new `superclasses` array for each class,
even though for all immediate subclasses of a class, the array is
identical.

This avoids duplicating the arrays on leaf classes (those without
subclasses) by calculating and storing a "superclasses including self"
array on a class when it's first inherited and sharing that among all
superclasses.

An additional trick used is that the "superclass array including self"
is valid as "self"'s superclass array. It just has it's own class at the
end. We can use this to avoid an extra pointer of storage and can use
one bit of a flag to track that we've "upgraded" the array.
2022-03-03 11:23:27 -08:00
John Hawthorn b13a7c8e36 Constant time class to class ancestor lookup
Previously when checking ancestors, we would walk all the way up the
ancestry chain checking each parent for a matching class or module.

I believe this was especially unfriendly to CPU cache since for each
step we need to check two cache lines (the class and class ext).

This check is used quite often in:
* case statements
* rescue statements
* Calling protected methods
* Class#is_a?
* Module#===
* Module#<=>

I believe it's most common to check a class against a parent class, to
this commit aims to improve that (unfortunately does not help checking
for an included Module).

This is done by storing on each class the number and an array of all
parent classes, in order (BasicObject is at index 0). Using this we can
check whether a class is a subclass of another in constant time since we
know the location to expect it in the hierarchy.
2022-02-23 19:57:42 -08:00
S-H-GAMELINKS 6e6ee1e6b3 Replace and Using METACLASS_OF macro 2022-02-19 23:18:51 +09:00
Nobuyoshi Nakada f3c77bd480 Fix the placeholder subclass entry skipping [Bug #18489] 2022-01-17 21:23:40 +09:00
Peter Zhu 6b7eff9086 Separately allocate class_serial on 32-bit systems
On 32-bit systems, VWA causes class_serial to not be aligned (it only
guarantees 4 byte alignment but class_serial is 8 bytes and requires 8
byte alignment). This commit uses a hack to allocate class_serial
through malloc. Once VWA allocates with 8 byte alignment in the future,
we will revert this commit.
2022-01-14 14:36:33 -05:00