summaryrefslogtreecommitdiff
path: root/class.c
AgeCommit message (Collapse)Author
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-11-10gc.h: move rb_objspace_garbage_object_p to internal/gc.hYusuke Endoh
... to allow class.c to use the function Notes: Merged: https://github.com/ruby/ruby/pull/5097
2021-11-10class.c: descendants must not cause GC until the result array is createdYusuke Endoh
Follow up of 428227472fc6563046d8138aab17f07bef6af753. The previous fix uses `rb_ary_new_from_values` to create the result array, but it may trigger the GC. This second try is to create the result array by `rb_ary_new_capa` before the second iteration, and assume that `rb_ary_push` does not trigger GC. This assumption is very fragile, so should be improved in future. [Bug #18282] [Feature #14394] Notes: Merged: https://github.com/ruby/ruby/pull/5097
2021-11-09Remove a redundant conditionYusuke Endoh
Notes: Merged: https://github.com/ruby/ruby/pull/5070
2021-11-09class.c (Class#descendants): Ingore subclasses created after estimationYusuke Endoh
It is theoretically possible if a finalizer creates a subclass. Notes: Merged: https://github.com/ruby/ruby/pull/5070
2021-11-09class.c: Use ALLOC_N instead of ALLOCA_NYusuke Endoh
Notes: Merged: https://github.com/ruby/ruby/pull/5070
2021-11-09class.c: calculate the length of Class.descendants in advanceYusuke Endoh
GC must not be triggered during callback of rb_class_foreach_subclass. To prevent GC, we can not use rb_ary_push. Instead, this changeset calls rb_class_foreach_subclass twice: first counts the subclasses, then allocates a buffer (which may cause GC and reduce subclasses, but not increase), and finally stores the subclasses to the buffer. [Bug #18282] [Feature #14394] Notes: Merged: https://github.com/ruby/ruby/pull/5070
2021-10-26Add Class#descendantsJeremy Evans
Doesn't include receiver or singleton classes. Implements [Feature #14394] Co-authored-by: fatkodima <fatkodima123@gmail.com> Co-authored-by: Benoit Daloze <eregontp@gmail.com> Notes: Merged: https://github.com/ruby/ruby/pull/4974 Merged-By: jeremyevans <code@jeremyevans.net>
2021-10-26Make the metaclass of Refinement explicitlyShugo Maeda
Otherwise, singleton methods of Module are not inherited unless Refinement.singleton_class is called.
2021-10-25[Feature #18239] Refactor RVARGC alloc functionsPeter Zhu
The allocation functions no longer assume that one RVALUE needs to be allocated. Notes: Merged: https://github.com/ruby/ruby/pull/4933
2021-10-21Deprecate include/prepend in refinements and add Refinement#import_methods ↵Shugo Maeda
instead Refinement#import_methods imports methods from modules. Unlike Module#include, it copies methods and adds them into the refinement, so the refinement is activated in the imported methods. [Bug #17429] [ruby-core:101639]
2021-09-24Use the flag for uninitialized module [Bug #18185]Nobuyoshi Nakada
Make `Module#ancestors` not to include `BasicObject`. Notes: Merged: https://github.com/ruby/ruby/pull/4883
2021-09-24Consider modified modules initialized [Bug #18185]Nobuyoshi Nakada
Notes: Merged: https://github.com/ruby/ruby/pull/4883
2021-09-20Allow to include uninitialized modules [Bug #18177]Nobuyoshi Nakada
The module that is about to be included is considered initialized. Notes: Merged: https://github.com/ruby/ruby/pull/4868
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-10include/ruby/internal/intern/class.h: add doxygen卜部昌平
Must not be a bad idea to improve documents. [ci skip] Notes: Merged: https://github.com/ruby/ruby/pull/4815
2021-09-10include/ruby/internal/method.h: add doxygen卜部昌平
Must not be a bad idea to improve documents. [ci skip] In fact many functions declared in the header file are already documented more or less. They were just copy & pasted, with applying some style updates. Notes: Merged: https://github.com/ruby/ruby/pull/4815
2021-09-10include/ruby/internal/module.h: add doxygen卜部昌平
Must not be a bad idea to improve documents. [ci skip] In fact many functions declared in the header file are already documented more or less. They were just copy & pasted, with applying some style updates. Notes: Merged: https://github.com/ruby/ruby/pull/4815
2021-09-10include/ruby/internal/newobj.h: add doxygen卜部昌平
Must not be a bad idea to improve documents. [ci skip] Notes: Merged: https://github.com/ruby/ruby/pull/4815
2021-09-01Assert not to be UNDEF visibilityNobuyoshi Nakada
Any defined methods, bound to any classes/modules and not being UNDEFINED_METHOD_ENTRY_P, should not be METHOD_VISI_UNDEF.
2021-08-25[Feature #18045] Implement size classes for GCPeter Zhu
This commits implements size classes in the GC for the Variable Width Allocation feature. Unless `USE_RVARGC` compile flag is set, only a single size class is created, maintaining current behaviour. See the redmine ticket for more details. Co-authored-by: Aaron Patterson <tenderlove@ruby-lang.org> Notes: Merged: https://github.com/ruby/ruby/pull/4773
2021-08-23Revert "[Feature #18045] Implement size classes for GC"Peter Zhu
This reverts commits 48ff7a9f3e47bffb3e4d067a12ba9b936261caa0 and b2e2cf2dedd104acad8610721db5e4d341f135ef because it is causing crashes in SPARC solaris and i386 debian. Notes: Merged: https://github.com/ruby/ruby/pull/4764
2021-08-23[Feature #18045] Implement size classes for GCPeter Zhu
This commits implements size classes in the GC for the Variable Width Allocation feature. Unless `USE_RVARGC` compile flag is set, only a single size class is created, maintaining current behaviour. See the redmine ticket for more details. Co-authored-by: Aaron Patterson <tenderlove@ruby-lang.org> Notes: Merged: https://github.com/ruby/ruby/pull/4680
2021-08-20Simplify repeated member access macrosNobuyoshi Nakada
2021-08-20Module#ancestors should not return superclasses of refinementsShugo Maeda
[ruby-core:86949] [Bug #14744] Reported by Eregon (Benoit Daloze). Thanks!
2021-08-19Remove old warning aged nearly 8 yearsNobuyoshi Nakada
2021-06-18Add a cache for class variableseileencodes
Redo of 34a2acdac788602c14bf05fb616215187badd504 and 931138b00696419945dc03e10f033b1f53cd50f3 which were reverted. GitHub PR #4340. This change implements a cache for class variables. Previously there was no cache for cvars. Cvar access is slow due to needing to travel all the way up th ancestor tree before returning the cvar value. The deeper the ancestor tree the slower cvar access will be. The benefits of the cache are more visible with a higher number of included modules due to the way Ruby looks up class variables. The benchmark here includes 26 modules and shows with the cache, this branch is 6.5x faster when accessing class variables. ``` compare-ruby: ruby 3.1.0dev (2021-03-15T06:22:34Z master 9e5105c) [x86_64-darwin19] built-ruby: ruby 3.1.0dev (2021-03-15T12:12:44Z add-cache-for-clas.. c6be009) [x86_64-darwin19] | |compare-ruby|built-ruby| |:--------|-----------:|---------:| |vm_cvar | 5.681M| 36.980M| | | -| 6.51x| ``` Benchmark.ips calling `ActiveRecord::Base.logger` from within a Rails application. ActiveRecord::Base.logger has 71 ancestors. The more ancestors a tree has, the more clear the speed increase. IE if Base had only one ancestor we'd see no improvement. This benchmark is run on a vanilla Rails application. Benchmark code: ```ruby require "benchmark/ips" require_relative "config/environment" Benchmark.ips do |x| x.report "logger" do ActiveRecord::Base.logger end end ``` Ruby 3.0 master / Rails 6.1: ``` Warming up -------------------------------------- logger 155.251k i/100ms Calculating ------------------------------------- ``` Ruby 3.0 with cvar cache / Rails 6.1: ``` Warming up -------------------------------------- logger 1.546M i/100ms Calculating ------------------------------------- logger 14.857M (± 4.8%) i/s - 74.198M in 5.006202s ``` Lastly we ran a benchmark to demonstate the difference between master and our cache when the number of modules increases. This benchmark measures 1 ancestor, 30 ancestors, and 100 ancestors. Ruby 3.0 master: ``` Warming up -------------------------------------- 1 module 1.231M i/100ms 30 modules 432.020k i/100ms 100 modules 145.399k i/100ms Calculating ------------------------------------- 1 module 12.210M (± 2.1%) i/s - 61.553M in 5.043400s 30 modules 4.354M (± 2.7%) i/s - 22.033M in 5.063839s 100 modules 1.434M (± 2.9%) i/s - 7.270M in 5.072531s Comparison: 1 module: 12209958.3 i/s 30 modules: 4354217.8 i/s - 2.80x (± 0.00) slower 100 modules: 1434447.3 i/s - 8.51x (± 0.00) slower ``` Ruby 3.0 with cvar cache: ``` Warming up -------------------------------------- 1 module 1.641M i/100ms 30 modules 1.655M i/100ms 100 modules 1.620M i/100ms Calculating ------------------------------------- 1 module 16.279M (± 3.8%) i/s - 82.038M in 5.046923s 30 modules 15.891M (± 3.9%) i/s - 79.459M in 5.007958s 100 modules 16.087M (± 3.6%) i/s - 81.005M in 5.041931s Comparison: 1 module: 16279458.0 i/s 100 modules: 16087484.6 i/s - same-ish: difference falls within error 30 modules: 15891406.2 i/s - same-ish: difference falls within error ``` Co-authored-by: Aaron Patterson <tenderlove@ruby-lang.org> Notes: Merged: https://github.com/ruby/ruby/pull/4544
2021-05-11Revert "Filling cache values on cvar write"Aaron Patterson
This reverts commit 08de37f9fa3469365e6b5c964689ae2bae0eb9f3. This reverts commit e8ae922b62adb00a80d3d4c49f7d7b0e6026eaba.
2021-05-11Filling cache values on cvar writeeileencodes
Instead of on read. Once it's in the inline cache we never have to make one again. We want to eventually put the value into the cache, and the best opportunity to do that is when you write the value. Notes: Merged: https://github.com/ruby/ruby/pull/4340
2021-05-11Add a cache for class variableseileencodes
This change implements a cache for class variables. Previously there was no cache for cvars. Cvar access is slow due to needing to travel all the way up th ancestor tree before returning the cvar value. The deeper the ancestor tree the slower cvar access will be. The benefits of the cache are more visible with a higher number of included modules due to the way Ruby looks up class variables. The benchmark here includes 26 modules and shows with the cache, this branch is 6.5x faster when accessing class variables. ``` compare-ruby: ruby 3.1.0dev (2021-03-15T06:22:34Z master 9e5105ca45) [x86_64-darwin19] built-ruby: ruby 3.1.0dev (2021-03-15T12:12:44Z add-cache-for-clas.. c6be0093ae) [x86_64-darwin19] | |compare-ruby|built-ruby| |:--------|-----------:|---------:| |vm_cvar | 5.681M| 36.980M| | | -| 6.51x| ``` Benchmark.ips calling `ActiveRecord::Base.logger` from within a Rails application. ActiveRecord::Base.logger has 71 ancestors. The more ancestors a tree has, the more clear the speed increase. IE if Base had only one ancestor we'd see no improvement. This benchmark is run on a vanilla Rails application. Benchmark code: ```ruby require "benchmark/ips" require_relative "config/environment" Benchmark.ips do |x| x.report "logger" do ActiveRecord::Base.logger end end ``` Ruby 3.0 master / Rails 6.1: ``` Warming up -------------------------------------- logger 155.251k i/100ms Calculating ------------------------------------- ``` Ruby 3.0 with cvar cache / Rails 6.1: ``` Warming up -------------------------------------- logger 1.546M i/100ms Calculating ------------------------------------- logger 14.857M (± 4.8%) i/s - 74.198M in 5.006202s ``` Lastly we ran a benchmark to demonstate the difference between master and our cache when the number of modules increases. This benchmark measures 1 ancestor, 30 ancestors, and 100 ancestors. Ruby 3.0 master: ``` Warming up -------------------------------------- 1 module 1.231M i/100ms 30 modules 432.020k i/100ms 100 modules 145.399k i/100ms Calculating ------------------------------------- 1 module 12.210M (± 2.1%) i/s - 61.553M in 5.043400s 30 modules 4.354M (± 2.7%) i/s - 22.033M in 5.063839s 100 modules 1.434M (± 2.9%) i/s - 7.270M in 5.072531s Comparison: 1 module: 12209958.3 i/s 30 modules: 4354217.8 i/s - 2.80x (± 0.00) slower 100 modules: 1434447.3 i/s - 8.51x (± 0.00) slower ``` Ruby 3.0 with cvar cache: ``` Warming up -------------------------------------- 1 module 1.641M i/100ms 30 modules 1.655M i/100ms 100 modules 1.620M i/100ms Calculating ------------------------------------- 1 module 16.279M (± 3.8%) i/s - 82.038M in 5.046923s 30 modules 15.891M (± 3.9%) i/s - 79.459M in 5.007958s 100 modules 16.087M (± 3.6%) i/s - 81.005M in 5.041931s Comparison: 1 module: 16279458.0 i/s 100 modules: 16087484.6 i/s - same-ish: difference falls within error 30 modules: 15891406.2 i/s - same-ish: difference falls within error ``` Co-authored-by: Aaron Patterson <tenderlove@ruby-lang.org> Notes: Merged: https://github.com/ruby/ruby/pull/4340
2021-05-11Method cache: fix refinement entry handlingAlan Wu
To invalidate some callable method entries, we replace the entry in the class. Most types of method entries are on the method table of the origin class, but refinement entries without an orig_me are housed in the method table of the class itself. They are there because refinements take priority over prepended methods. By unconditionally inserting a copy of the refinement entry into the origin class, clearing the method cache created situations where there are refinement entry duplicates in the lookup chain, leading to infinite loops and other problems. Update the replacement logic to use the right class that houses the method entry. Also, be more selective about cache invalidation when moving refinement entries for prepend. This avoids calling clear_method_cache_by_id_in_class() before refinement entries are in the place it expects. [Bug #17806] Notes: Merged: https://github.com/ruby/ruby/pull/4386 Merged-By: XrXr
2021-05-06Store rb_classext_t next to RClass slots on the heapMatt Valentine-House
Notes: Merged: https://github.com/ruby/ruby/pull/4391
2021-03-21Add ins_methods_type_i functionS.H
Notes: Merged: https://github.com/ruby/ruby/pull/4269 Merged-By: nobu <nobu@ruby-lang.org>
2021-03-10Refactor `rb_class_ivar_set`eileencodes
In every caller of `rb_class_ivar_set` it checks for the `RCLASS_IV_TBL` and then creates it if it doesn't exist. Instead of repeating this in every caller, this can be done once in `rb_class_ivar_set`. Notes: Merged: https://github.com/ruby/ruby/pull/4254
2021-02-22Check for cyclic prepend before making originAlan Wu
It's important to only make the origin when the prepend goes through, as the precense of the origin informs whether to do an origin backfill. This plus 2d877327e fix [Bug #17590]. Notes: Merged: https://github.com/ruby/ruby/pull/4181
2021-02-11Make a cyclic prepend not modify ancestors for the receiverJeremy Evans
Check for cyclic prepend before making any changes. This requires scanning the module ancestor chain twice, but in general modules do not have large numbers of ancestors. Notes: Merged: https://github.com/ruby/ruby/pull/4165
2021-02-01Add RCLASS_SUBCLASSES MacroMatt Valentine-House
Notes: Merged: https://github.com/ruby/ruby/pull/4124
2021-02-01Add RCLASS_ALLOCATOR MacroMatt Valentine-House
Notes: Merged: https://github.com/ruby/ruby/pull/4124
2021-02-01Add PARENT_MODULE_SUBCLASSES MacroMatt Valentine-House
Notes: Merged: https://github.com/ruby/ruby/pull/4124
2021-02-01Add RCLASS_PARENT_SUBMODULES MacroMatt Valentine-House
Notes: Merged: https://github.com/ruby/ruby/pull/4124
2021-01-26Add compaction notes for class/module creation C APIsAlan Wu
Notes: Merged: https://github.com/ruby/ruby/pull/3885
2021-01-26Make rb_define_module_id_under() pin existing modulesAlan Wu
Just like rb_define_class_id_under(). Also makes rb_define_module_under() consistent with rb_define_class_under() in the same regard. Notes: Merged: https://github.com/ruby/ruby/pull/3885
2021-01-14Make Module#prepend affect ancestor chain even if argument already included ↵Jeremy Evans
in receiver Previously, if a class included a module and then prepended the same module, the prepend had no effect. This changes the behavior so that the prepend has an effect unless the module is already prepended the receiver. While here, rename the origin_seen variable in include_modules_at, since it is misleading. The variable tracks whether c has been seen, not whether the origin of klass has been. Fixes [Bug #17423] Notes: Merged: https://github.com/ruby/ruby/pull/4072
2020-12-22reset cache before iteratingKoichi Sasada
cee02d754d76563635c1db90d2ab6c01f8492470 resets pCMC and `me` will be a invalidated and continuing the invalidated `me`, it will break the data structure. This patch tris to clear all methods of specified class before manipulating the `me`s. [Issue #17417] Notes: Merged: https://github.com/ruby/ruby/pull/3964
2020-12-21Fixed indefinite articles before "Integer" [ci skip]Nobuyoshi Nakada
2020-12-19fix refinements/prepend bugKoichi Sasada
replaced method entry should be invalidated. [Bug #17386]
2020-11-25Prefer rb_module_new() over rb_define_module_id()Alan Wu
rb_define_module_id() doesn't do anything with its parameter so it's a bit confusing.
2020-11-20Do not allow Module#include to insert modules before the origin in the ↵Jeremy Evans
lookup chain Module#include should only be able to insert modules after the origin, otherwise it ends up working like Module#prepend. This fixes the case where one of the modules in the included module chain is included in a module that is already prepended to the receiver. Fixes [Bug #7844] Notes: Merged: https://github.com/ruby/ruby/pull/3796
2020-11-16Fix singleton class cloningAlan Wu
Before this commit, `clone` gave different results depending on whether the original object had an attached singleton class or not. Consider the following setup: ``` class Foo; end Foo.singleton_class.define_method(:foo) {} obj = Foo.new obj.singleton_class if $call_singleton clone = obj.clone ``` When `$call_singleton = false`, neither `obj.singleton_class.singleton_class` nor `clone.singleton_class.singleton_class` own any methods. However, when `$call_singleton = true`, `clone.singleton_class.singleton_class` would own a copy of `foo` from `Foo.singleton_class`, even though `obj.singleton_class.singleton_class` does not. The latter case is unexpected and results in a visibly different clone, depending on if the original object had an attached class or not. Co-authored-by: Ufuk Kayserilioglu <ufuk.kayserilioglu@shopify.com> Notes: Merged: https://github.com/ruby/ruby/pull/3761