summaryrefslogtreecommitdiff
path: root/internal/class.h
AgeCommit message (Collapse)Author
2024-10-03Rename size_pool -> heapMatt Valentine-House
Now that we've inlined the eden_heap into the size_pool, we should rename the size_pool to heap. So that Ruby contains multiple heaps, with different sized objects. The term heap as a collection of memory pages is more in memory management nomenclature, whereas size_pool was a name chosen out of necessity during the development of the Variable Width Allocation features of Ruby. The concept of size pools was introduced in order to facilitate different sized objects (other than the default 40 bytes). They wrapped the eden heap and the tomb heap, and some related state, and provided a reasonably simple way of duplicating all related concerns, to provide multiple pools that all shared the same structure but held different objects. Since then various changes have happend in Ruby's memory layout: * The concept of tomb heaps has been replaced by a global free pages list, with each page having it's slot size reconfigured at the point when it is resurrected * the eden heap has been inlined into the size pool itself, so that now the size pool directly controls the free_pages list, the sweeping page, the compaction cursor and the other state that was previously being managed by the eden heap. Now that there is no need for a heap wrapper, we should refer to the collection of pages containing Ruby objects as a heap again rather than a size pool Notes: Merged: https://github.com/ruby/ruby/pull/11771
2024-03-06Refactor VM root modulesJean Boussier
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-06Move FL_SINGLETON to FL_USER1Jean Boussier
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-01Don't pin named structs defined in RubyJean Boussier
[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-02-20De-dup identical callinfo objectsJohn Hawthorn
Previously every call to vm_ci_new (when the CI was not packable) would result in a different callinfo being returned this meant that every kwarg callsite had its own CI. When calling, different CIs result in different CCs. These CIs and CCs both end up persisted on the T_CLASS inside cc_tbl. So in an eval loop this resulted in a memory leak of both types of object. This also likely resulted in extra memory used, and extra time searching, in non-eval cases. For simplicity in this commit I always allocate a CI object inside rb_vm_ci_lookup, but ideally we would lazily allocate it only when needed. I hope to do that as a follow up in the future.
2023-12-19Set m_tbl right after allocationPeter Zhu
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 <[email protected]>
2023-11-20Don't try compacting ivars on Classes that are "too complex"Aaron Patterson
Too complex classes use a hash table to store ivs, and should always pin their IVs. We shouldn't touch those classes in compaction.
2023-10-15Avoid the pointer hack in RCLASS_EXTYusuke Endoh
... because GCC 13 warns it. ``` In file included from class.c:24: In function ‘RCLASS_SET_ALLOCATOR’, inlined from ‘class_alloc’ at class.c:251:5, inlined from ‘rb_module_s_alloc’ at class.c:1045:17: internal/class.h:159:43: warning: array subscript 0 is outside array bounds of ‘rb_classext_t[0]’ {aka ‘struct rb_classext_struct[]’} [-Warray-bounds=] 159 | RCLASS_EXT(klass)->as.class.allocator = allocator; | ^ ``` https://rubyci.s3.amazonaws.com/arch/ruby-master/log/20231015T030003Z.log.html.gz
2023-09-19Stop exposing FrozenCore in headersNobuyoshi Nakada
Revert commit "Directly allocate FrozenCore as an ICLASS", 813a5f4fc46a24ca1695d23c159250b9e1080ac7.
2023-06-23Prefer `0` over `NULL` as function pointersNobuyoshi Nakada
SunC warns use of `NULL`, pointer to data as function pointers. Notes: Merged: https://github.com/ruby/ruby/pull/7972 Merged-By: nobu <[email protected]>
2023-06-14Directly allocate FrozenCore as an ICLASSPeter Zhu
It's a bad idea to overwrite the flags as the garbage collector may have set other flags. Notes: Merged: https://github.com/ruby/ruby/pull/7940
2023-06-05Revert "Revert "Fix cvar caching when class is cloned""eileencodes
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 <[email protected]> Notes: Merged: https://github.com/ruby/ruby/pull/7900
2023-06-01Revert "Fix cvar caching when class is cloned"Aaron Patterson
This reverts commit 77d1b082470790c17c24a2f406b4fec5d522636b.
2023-06-01Fix cvar caching when class is clonedeileencodes
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 <[email protected]> Notes: Merged: https://github.com/ruby/ruby/pull/7265
2023-04-16Make classes embedded on 32 bitPeter Zhu
Classes are now exactly 80 bytes when embedded, which perfectly fits the 3rd size pool on 32 bit systems. Notes: Merged: https://github.com/ruby/ruby/pull/7719
2023-04-16Move shape ID to flags for classes on 32 bitPeter Zhu
Moves shape ID to FL_USER4 to FL_USER19 for the shape ID on 32 bit systems. This makes the rb_classext_struct smaller so that it can be embedded. Notes: Merged: https://github.com/ruby/ruby/pull/7719
2023-04-16Move RCLASS_CLONED to rb_classext_structPeter Zhu
This commit moves RCLASS_CLONED from the flags to the rb_classext_struct. This frees the FL_USER1 bit. Notes: Merged: https://github.com/ruby/ruby/pull/7719
2023-04-11Change max_iv_count to type attr_index_tPeter Zhu
max_iv_count is calculated from next_iv_index of the shape, which is of type attr_index_t, so we can also make max_iv_count of type attr_index_t. Notes: Merged: https://github.com/ruby/ruby/pull/7689
2023-03-10Revert "Allow classes and modules to become too complex"Aaron Patterson
This reverts commit 69465df4242f3b2d8e55fbe18d7c45b47b40a626.
2023-03-09Allow classes and modules to become too complexHParker
This makes the behavior of classes and modules when there are too many instance variables match the behavior of objects with too many instance variables. Notes: Merged: https://github.com/ruby/ruby/pull/7349
2023-03-06Stop exporting symbols for MJITTakashi Kokubun
Notes: Merged: https://github.com/ruby/ruby/pull/7459
2023-02-16Move `attached_object` into `rb_classext_struct`Jean Boussier
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. Notes: Merged: https://github.com/ruby/ruby/pull/7309
2023-02-15Encapsulate RCLASS_ATTACHED_OBJECTJean Boussier
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. Notes: Merged: https://github.com/ruby/ruby/pull/7308
2023-02-15Check !RCLASS_EXT_EMBEDDED instead of SIZE_POOL_COUNT == 1Jean Boussier
It's much more self documenting and consistent Notes: Merged: https://github.com/ruby/ruby/pull/7307
2023-01-18Don't redefine RB_OBJ_WRITEPeter Zhu
RB_OBJ_WRITE already exists in rgengc.h, so we shouldn't redefine it in gc.h. Notes: Merged: https://github.com/ruby/ruby/pull/7131
2023-01-11Move classpath to rb_classext_tPeter Zhu
This commit moves the classpath (and tmp_classpath) from instance variables to the rb_classext_t. This improves performance as we no longer need to set an instance variable when assigning a classpath to a class. I benchmarked with the following script: ```ruby name = :MyClass puts(Benchmark.measure do 10_000_000.times do |i| Object.const_set(name, Class.new) Object.send(:remove_const, name) end end) ``` Before this patch: ``` 5.440119 0.025264 5.465383 ( 5.467105) ``` After this patch: ``` 4.889646 0.028325 4.917971 ( 4.942678) ``` Notes: Merged: https://github.com/ruby/ruby/pull/7096
2023-01-11Make variation_count an unsigned charPeter Zhu
Since SHAPE_MAX_VARIATIONS is 8, it can easily fit inside an unsigned char. Notes: Merged: https://github.com/ruby/ruby/pull/7096
2022-12-15Add variation_count on classesJemma Issroff
Count how many "variations" each class creates. A "variation" is a a unique ordering of instance variables on a particular class. This can also be thought of as a branch in the shape tree. For example, the following Foo class will have 2 variations: ```ruby class Foo ; end Foo.new.instance_variable_set(:@a, 1) # case 1: creates one variation Foo.new.instance_variable_set(:@b, 1) # case 2: creates another variation foo = Foo.new foo.instance_variable_set(:@a, 1) # does not create a new variation foo.instance_variable_set(:@b, 1) # does not create a new variation (a continuation of the variation in case 1) ``` We will use this number to limit the amount of shapes that a class can create and fallback to using a hash iv lookup. Co-Authored-By: Aaron Patterson <[email protected]> Notes: Merged: https://github.com/ruby/ruby/pull/6931
2022-11-10Transition shape when object's capacity changesJemma Issroff
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 <[email protected]> Notes: Merged: https://github.com/ruby/ruby/pull/6699
2022-10-31Implement object shapes for T_CLASS and T_MODULE (#6637)John Hawthorn
* 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 Notes: Merged-By: jhawthorn <[email protected]>
2022-10-24Remove iv_index_tbl_entryJohn Hawthorn
Notes: Merged: https://github.com/ruby/ruby/pull/6610
2022-10-21Remove unused class serialJemma Issroff
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 <[email protected]> Notes: Merged: https://github.com/ruby/ruby/pull/6605
2022-10-11Revert "Revert "This commit implements the Object Shapes technique in CRuby.""Jemma Issroff
This reverts commit 9a6803c90b817f70389cae10d60b50ad752da48f.
2022-09-30Revert "This commit implements the Object Shapes technique in CRuby."Aaron Patterson
This reverts commit 68bc9e2e97d12f80df0d113e284864e225f771c2.
2022-09-28This commit implements the Object Shapes technique in CRuby.Jemma Issroff
Object Shapes is used for accessing instance variables and representing the "frozenness" of objects. Object instances have a "shape" and the shape represents some attributes of the object (currently which instance variables are set and the "frozenness"). Shapes form a tree data structure, and when a new instance variable is set on an object, that object "transitions" to a new shape in the shape tree. Each shape has an ID that is used for caching. The shape structure is independent of class, so objects of different types can have the same shape. For example: ```ruby class Foo def initialize # Starts with shape id 0 @a = 1 # transitions to shape id 1 @b = 1 # transitions to shape id 2 end end class Bar def initialize # Starts with shape id 0 @a = 1 # transitions to shape id 1 @b = 1 # transitions to shape id 2 end end foo = Foo.new # `foo` has shape id 2 bar = Bar.new # `bar` has shape id 2 ``` Both `foo` and `bar` instances have the same shape because they both set instance variables of the same name in the same order. This technique can help to improve inline cache hits as well as generate more efficient machine code in JIT compilers. This commit also adds some methods for debugging shapes on objects. See `RubyVM::Shape` for more details. For more context on Object Shapes, see [Feature: #18776] Co-Authored-By: Aaron Patterson <[email protected]> Co-Authored-By: Eileen M. Uchitelle <[email protected]> Co-Authored-By: John Hawthorn <[email protected]>
2022-09-26Revert this until we can figure out WB issues or remove shapes from GCAaron Patterson
Revert "* expand tabs. [ci skip]" This reverts commit 830b5b5c351c5c6efa5ad461ae4ec5085e5f0275. Revert "This commit implements the Object Shapes technique in CRuby." This reverts commit 9ddfd2ca004d1952be79cf1b84c52c79a55978f4.
2022-09-26This commit implements the Object Shapes technique in CRuby.Jemma Issroff
Object Shapes is used for accessing instance variables and representing the "frozenness" of objects. Object instances have a "shape" and the shape represents some attributes of the object (currently which instance variables are set and the "frozenness"). Shapes form a tree data structure, and when a new instance variable is set on an object, that object "transitions" to a new shape in the shape tree. Each shape has an ID that is used for caching. The shape structure is independent of class, so objects of different types can have the same shape. For example: ```ruby class Foo def initialize # Starts with shape id 0 @a = 1 # transitions to shape id 1 @b = 1 # transitions to shape id 2 end end class Bar def initialize # Starts with shape id 0 @a = 1 # transitions to shape id 1 @b = 1 # transitions to shape id 2 end end foo = Foo.new # `foo` has shape id 2 bar = Bar.new # `bar` has shape id 2 ``` Both `foo` and `bar` instances have the same shape because they both set instance variables of the same name in the same order. This technique can help to improve inline cache hits as well as generate more efficient machine code in JIT compilers. This commit also adds some methods for debugging shapes on objects. See `RubyVM::Shape` for more details. For more context on Object Shapes, see [Feature: #18776] Co-Authored-By: Aaron Patterson <[email protected]> Co-Authored-By: Eileen M. Uchitelle <[email protected]> Co-Authored-By: John Hawthorn <[email protected]> Notes: Merged: https://github.com/ruby/ruby/pull/6386
2022-06-06Add Module#undefined_instance_methodsJeremy Evans
Implements [Feature #12655] Co-authored-by: Nobuyoshi Nakada <[email protected]> Notes: Merged: https://github.com/ruby/ruby/pull/5733 Merged-By: jeremyevans <[email protected]>
2022-05-27RCLASS uses FLUSER bits 0 through 3Jemma Issroff
Notes: Merged: https://github.com/ruby/ruby/pull/5955
2022-03-03Dedup superclass array in leaf sibling classesJohn Hawthorn
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. Notes: Merged: https://github.com/ruby/ruby/pull/5604
2022-02-23Constant time class to class ancestor lookupJohn Hawthorn
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. Notes: Merged: https://github.com/ruby/ruby/pull/5568
2022-01-17Parenthesize the macro argumentNobuyoshi Nakada
2022-01-14Separately allocate class_serial on 32-bit systemsPeter Zhu
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. Notes: Merged: https://github.com/ruby/ruby/pull/5442
2021-11-22Make RCLASS_EXT(c)->subclasses a doubly linked listMatt Valentine-House
Updating RCLASS_PARENT_SUBCLASSES and RCLASS_MODULE_SUBCLASSES while compacting can trigger the read barrier. This commit makes RCLASS_SUBCLASSES a doubly linked list with a dedicated head object so that we can add and remove entries from the list without having to touch an object in the Ruby heap Notes: Merged: https://github.com/ruby/ruby/pull/5125
2021-11-11Remove RCLASS(obj)->ptr when RVARGC is enabledMatt Valentine-House
With RVARGC we always store the rb_classext_t in the same slot as the RClass struct that refers to it. So we don't need to store the pointer or access through the pointer anymore and can switch the RCLASS_EXT macro to use an offset Notes: Merged: https://github.com/ruby/ruby/pull/5101
2021-09-24Consider modified modules initialized [Bug #18185]Nobuyoshi Nakada
Notes: Merged: https://github.com/ruby/ruby/pull/4883
2021-09-19Fix a typo [Bug #17048]Nobuyoshi Nakada
2021-09-17Already initialized modules cannot be replaced [Bug #17048]Nobuyoshi Nakada
Notes: Merged: https://github.com/ruby/ruby/pull/4858
2021-09-10internal/*.h: skip doxygen卜部昌平
These contents are purely implementation details, not worth appearing in CAPI documents. [ci skip] Notes: Merged: https://github.com/ruby/ruby/pull/4815
2021-08-19Remove old warning aged nearly 8 yearsNobuyoshi Nakada