summaryrefslogtreecommitdiff
path: root/class.c
Commit message (Collapse)AuthorAgeFilesLines
...
* Remove RCLASS(obj)->ptr when RVARGC is enabledMatt Valentine-House2021-11-111-3/+1
| | | | | | | 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
* gc.h: move rb_objspace_garbage_object_p to internal/gc.hYusuke Endoh2021-11-101-1/+0
| | | | ... to allow class.c to use the function
* class.c: descendants must not cause GC until the result array is createdYusuke Endoh2021-11-101-9/+13
| | | | | | | | | | | | | 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]
* Remove a redundant conditionYusuke Endoh2021-11-091-2/+2
|
* class.c (Class#descendants): Ingore subclasses created after estimationYusuke Endoh2021-11-091-2/+4
| | | | It is theoretically possible if a finalizer creates a subclass.
* class.c: Use ALLOC_N instead of ALLOCA_NYusuke Endoh2021-11-091-2/+6
|
* class.c: calculate the length of Class.descendants in advanceYusuke Endoh2021-11-091-6/+29
| | | | | | | | | | 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]
* Add Class#descendantsJeremy Evans2021-10-261-0/+35
| | | | | | | | 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>
* Make the metaclass of Refinement explicitlyShugo Maeda2021-10-261-0/+2
| | | | | Otherwise, singleton methods of Module are not inherited unless Refinement.singleton_class is called.
* [Feature #18239] Refactor RVARGC alloc functionsPeter Zhu2021-10-251-4/+4
| | | | | The allocation functions no longer assume that one RVALUE needs to be allocated.
* Deprecate include/prepend in refinements and add Refinement#import_methods ↵Shugo Maeda2021-10-211-3/+17
| | | | | | | | | | 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]
* Use the flag for uninitialized module [Bug #18185]Nobuyoshi Nakada2021-09-241-6/+9
| | | | Make `Module#ancestors` not to include `BasicObject`.
* Consider modified modules initialized [Bug #18185]Nobuyoshi Nakada2021-09-241-4/+10
|
* Allow to include uninitialized modules [Bug #18177]Nobuyoshi Nakada2021-09-201-1/+2
| | | | The module that is about to be included is considered initialized.
* Fix a typo [Bug #17048]Nobuyoshi Nakada2021-09-191-2/+2
|
* Already initialized modules cannot be replaced [Bug #17048]Nobuyoshi Nakada2021-09-171-1/+42
|
* include/ruby/internal/intern/class.h: add doxygen卜部昌平2021-09-101-67/+0
| | | | Must not be a bad idea to improve documents. [ci skip]
* include/ruby/internal/method.h: add doxygen卜部昌平2021-09-101-77/+1
| | | | | | | | 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.
* include/ruby/internal/module.h: add doxygen卜部昌平2021-09-101-51/+1
| | | | | | | | 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.
* include/ruby/internal/newobj.h: add doxygen卜部昌平2021-09-101-4/+0
| | | | Must not be a bad idea to improve documents. [ci skip]
* Assert not to be UNDEF visibilityNobuyoshi Nakada2021-09-011-0/+1
| | | | | Any defined methods, bound to any classes/modules and not being UNDEFINED_METHOD_ENTRY_P, should not be METHOD_VISI_UNDEF.
* [Feature #18045] Implement size classes for GCPeter Zhu2021-08-251-2/+1
| | | | | | | | | 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>
* Revert "[Feature #18045] Implement size classes for GC"Peter Zhu2021-08-231-1/+2
| | | | | | This reverts commits 48ff7a9f3e47bffb3e4d067a12ba9b936261caa0 and b2e2cf2dedd104acad8610721db5e4d341f135ef because it is causing crashes in SPARC solaris and i386 debian.
* [Feature #18045] Implement size classes for GCPeter Zhu2021-08-231-2/+1
| | | | | | | | | 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>
* Simplify repeated member access macrosNobuyoshi Nakada2021-08-201-14/+14
|
* Module#ancestors should not return superclasses of refinementsShugo Maeda2021-08-201-0/+5
| | | | | | [ruby-core:86949] [Bug #14744] Reported by Eregon (Benoit Daloze). Thanks!
* Remove old warning aged nearly 8 yearsNobuyoshi Nakada2021-08-191-6/+0
|
* Add a cache for class variableseileencodes2021-06-181-0/+6
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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>
* Revert "Filling cache values on cvar write"Aaron Patterson2021-05-111-6/+0
| | | | | This reverts commit 08de37f9fa3469365e6b5c964689ae2bae0eb9f3. This reverts commit e8ae922b62adb00a80d3d4c49f7d7b0e6026eaba.
* Filling cache values on cvar writeeileencodes2021-05-111-0/+1
| | | | | | 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.
* Add a cache for class variableseileencodes2021-05-111-0/+5
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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>
* Method cache: fix refinement entry handlingAlan Wu2021-05-111-1/+3
| | | | | | | | | | | | | | | | | | | | 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]
* Store rb_classext_t next to RClass slots on the heapMatt Valentine-House2021-05-061-1/+14
|
* Add ins_methods_type_i functionS.H2021-03-211-10/+10
|
* Refactor `rb_class_ivar_set`eileencodes2021-03-101-3/+0
| | | | | | 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`.
* Check for cyclic prepend before making originAlan Wu2021-02-221-21/+35
| | | | | | | | 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].
* Make a cyclic prepend not modify ancestors for the receiverJeremy Evans2021-02-111-2/+12
| | | | | | 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.
* Add RCLASS_SUBCLASSES MacroMatt Valentine-House2021-02-011-10/+10
|
* Add RCLASS_ALLOCATOR MacroMatt Valentine-House2021-02-011-4/+4
|
* Add PARENT_MODULE_SUBCLASSES MacroMatt Valentine-House2021-02-011-8/+8
|
* Add RCLASS_PARENT_SUBMODULES MacroMatt Valentine-House2021-02-011-8/+8
|
* Add compaction notes for class/module creation C APIsAlan Wu2021-01-261-0/+8
|
* Make rb_define_module_id_under() pin existing modulesAlan Wu2021-01-261-0/+2
| | | | | | Just like rb_define_class_id_under(). Also makes rb_define_module_under() consistent with rb_define_class_under() in the same regard.
* Make Module#prepend affect ancestor chain even if argument already included ↵Jeremy Evans2021-01-141-22/+29
| | | | | | | | | | | | | | | 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]
* reset cache before iteratingKoichi Sasada2020-12-221-4/+17
| | | | | | | | 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]
* Fixed indefinite articles before "Integer" [ci skip]Nobuyoshi Nakada2020-12-211-1/+1
|
* fix refinements/prepend bugKoichi Sasada2020-12-191-1/+3
| | | | | replaced method entry should be invalidated. [Bug #17386]
* Prefer rb_module_new() over rb_define_module_id()Alan Wu2020-11-251-2/+3
| | | | | rb_define_module_id() doesn't do anything with its parameter so it's a bit confusing.
* Do not allow Module#include to insert modules before the origin in the ↵Jeremy Evans2020-11-201-1/+6
| | | | | | | | | | | | 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]
* Fix singleton class cloningAlan Wu2020-11-161-9/+22
| | | | | | | | | | | | | | | | | | | | | | | | | | | | 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>