summaryrefslogtreecommitdiff
path: root/id_table.c
AgeCommit message (Collapse)Author
2025-12-18Check for NULL fields in TYPEDDATA memsize functions (#15633)Luke Gruber
Some TYPEDDATA objects allocate struct fields using the GC right after they get created, and in that case the VM can try to perform a GC and join a barrier if another ractor started one. If we're dumping the heap in another ractor, this acquires a barrier and it will call the `rb_obj_memsize` function on this object. We can't assume these struct fields are non-null. This also goes for C extensions, which may cause problems with heap dumping from a ractor if their memsize functions aren't coded correctly to check for NULL fields. Because dumping the heap from a ractor is likely a rare scenario and it has only recently been introduced, we'll have to see how this works in practice and if it causes bugs.
2025-11-11Remove useless cast in rb_managed_id_table_typePeter Zhu
2025-10-23use `SET_SHAREABLE`Koichi Sasada
to adopt strict shareable rule. * (basically) shareable objects only refer shareable objects * (exception) shareable objects can refere unshareable objects but should not leak reference to unshareable objects to Ruby world
2025-08-01Refactor `vm_lookup_cc` to allow lock-free lookups in `RClass.cc_tbl`Jean Boussier
In multi-ractor mode, the `cc_tbl` mutations use the RCU pattern, which allow lock-less reads. Based on the assumption that invalidations and misses should be increasingly rare as the process ages, locking on modification isn't a big concern.
2025-08-01Make `RClass.cc_table` a managed objectJean Boussier
For now this doesn't change anything, but now that the table is managed by GC, it opens the door to use RCU when in multi-ractor mode, hence allow unsynchornized reads.
2025-07-15id_table.c: reduce duplication in managed_id_table methodsJean Boussier
2025-06-04shape.c: fix off by one error in `shape_tree_mark`Jean Boussier
Notes: Merged: https://github.com/ruby/ruby/pull/13289
2025-06-02shape.c: Implement a lock-free version of get_next_shape_internalJean Boussier
Whenever we run into an inline cache miss when we try to set an ivar, we may need to take the global lock, just to be able to lookup inside `shape->edges`. To solve that, when we're in multi-ractor mode, we can treat the `shape->edges` as immutable. When we need to add a new edge, we first copy the table, and then replace it with CAS. This increases memory allocations, however we expect that creating new transitions becomes increasingly rare over time. ```ruby class A def initialize(bool) @a = 1 if bool @b = 2 else @c = 3 end end def test @d = 4 end end def bench(iterations) i = iterations while i > 0 A.new(true).test A.new(false).test i -= 1 end end if ARGV.first == "ractor" ractors = 8.times.map do Ractor.new do bench(20_000_000 / 8) end end ractors.each(&:take) else bench(20_000_000) end ``` The above benchmark takes 27 seconds in Ractor mode on Ruby 3.4, and only 1.7s with this branch. Co-Authored-By: Étienne Barrié <etienne.barrie@gmail.com> Notes: Merged: https://github.com/ruby/ruby/pull/13441
2024-02-12Replace assert with RUBY_ASSERT in id_table.cPeter Zhu
assert does not print the bug report, only the file and line number of the assertion that failed. RUBY_ASSERT prints the full bug report, which makes it much easier to debug.
2023-03-06Stop exporting symbols for MJITTakashi Kokubun
Notes: Merged: https://github.com/ruby/ruby/pull/7459
2022-07-21Expand tabs [ci skip]Takashi Kokubun
[Misc #18891] Notes: Merged: https://github.com/ruby/ruby/pull/6094
2022-01-25Support ID_TABLE_STOP for replace functionPeter Zhu
Iteration should top if the replace function returns ID_TABLE_STOP. Notes: Merged: https://github.com/ruby/ruby/pull/5486
2022-01-25Rename rb_id_table_foreach_with_replacePeter Zhu
Renames rb_id_table_foreach_with_replace to rb_id_table_foreach_values_with_replace and passes only the value to the callback. We can use this in GC compaction when we cannot access the global symbol array. Notes: Merged: https://github.com/ruby/ruby/pull/5486
2022-01-26Revert "`ID` in `rb_id_table_foreach_with_replace` [Feature #18253]"Nobuyoshi Nakada
This reverts commit 530e485265dac6e2aea1d587a4a79a314cc772cf. `rb_id_table_foreach_with_replace` is used during GC compaction, and the global symbols array can have been moved at that time.
2022-01-24`ID` in `rb_id_table_foreach_with_replace` [Feature #18253]Nobuyoshi Nakada
Pass the `ID` from `rb_id_table_foreach_with_replace` to callback functions. Notes: Merged: https://github.com/ruby/ruby/pull/5458
2021-10-13Qundef is not for IDNobuyoshi 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-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
2020-08-10Suppress unused-variable warningNobuyoshi Nakada
`key` is not used outside this assertion.
2020-04-21reroute redefinition of NDEBUG卜部昌平
NDEBUG can be defined via a command-line argument. Should take care of such situations.
2020-02-22Introduce disposable call-cache.Koichi Sasada
This patch contains several ideas: (1) Disposable inline method cache (IMC) for race-free inline method cache * Making call-cache (CC) as a RVALUE (GC target object) and allocate new CC on cache miss. * This technique allows race-free access from parallel processing elements like RCU. (2) Introduce per-Class method cache (pCMC) * Instead of fixed-size global method cache (GMC), pCMC allows flexible cache size. * Caching CCs reduces CC allocation and allow sharing CC's fast-path between same call-info (CI) call-sites. (3) Invalidate an inline method cache by invalidating corresponding method entries (MEs) * Instead of using class serials, we set "invalidated" flag for method entry itself to represent cache invalidation. * Compare with using class serials, the impact of method modification (add/overwrite/delete) is small. * Updating class serials invalidate all method caches of the class and sub-classes. * Proposed approach only invalidate the method cache of only one ME. See [Feature #16614] for more details. Notes: Merged: https://github.com/ruby/ruby/pull/2888
2019-10-03Revert https://github.com/ruby/ruby/pull/2486卜部昌平
This reverts commits: 10d6a3aca7 8ba48c1b85 fba8627dc1 dd883de5ba 6c6a25feca 167e6b48f1 7cb96d41a5 3207979278 595b3c4fdd 1521f7cf89 c11c5e69ac cf33608203 3632a812c0 f56506be0d 86427a3219 . The reason for the revert is that we observe ABA problem around inline method cache. When a cache misshits, we search for a method entry. And if the entry is identical to what was cached before, we reuse the cache. But the commits we are reverting here introduced situations where a method entry is freed, then the identical memory region is used for another method entry. An inline method cache cannot detect that ABA. Here is a code that reproduce such situation: ```ruby require 'prime' class << Integer alias org_sqrt sqrt def sqrt(n) raise end GC.stress = true Prime.each(7*37){} rescue nil # <- Here we populate CC class << Object.new; end # These adjacent remove-then-alias maneuver # frees a method entry, then immediately # reuses it for another. remove_method :sqrt alias sqrt org_sqrt end Prime.each(7*37).to_a # <- SEGV ```
2019-09-30refactor add rb_id_table_foreach_with_replace_with_key卜部昌平
This is a pure refactoring to reduce copy & paste. Also the new function is made visible from other parts of the interpreter, to be used later. Notes: Merged: https://github.com/ruby/ruby/pull/2486
2019-04-20Add `GC.compact` again.tenderlove
🙏 git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67620 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2019-04-17Reverting compaction for nowtenderlove
For some reason symbols (or classes) are being overridden in trunk git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67598 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2019-04-17Adding `GC.compact` and compacting GC support.tenderlove
This commit adds the new method `GC.compact` and compacting GC support. Please see this issue for caveats: https://bugs.ruby-lang.org/issues/15626 [Feature #15626] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2019-04-10Reverting all commits from r67479 to r67496 because of CI failureskazu
Because hard to specify commits related to r67479 only. So please commit again. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67499 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2019-04-10id_table.c: use NULL as ID* instead of Qundefnobu
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67495 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2019-04-10Adjusted stylesnobu
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67493 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2019-04-09Adding `GC.compact` and compacting GC support.tenderlove
This commit adds the new method `GC.compact` and compacting GC support. Please see this issue for caveats: https://bugs.ruby-lang.org/issues/15626 [Feature #15626] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67479 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2017-05-10adjust styles [ci skip]nobu
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@58646 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2017-01-25swithc id_table data structure.ko1
* id_table.c: swtich to "simple open addressing with quadratic probing" by Yura Sokolov. For more detail measurements, see [Feature #12180] * id_table.c: remove other algorithms to simplify the source code. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@57416 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2017-01-19id_table.c: fix typonobu
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@57369 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2016-08-14id_table.c: extend, don't shrinknobu
* id_table.c (hash_table_extend): should not shrink the table than the previous capacity. [ruby-core:76534] [Bug #12614] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55896 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2016-08-06id_table.h: dummy sentinelnobu
* id_table.h (rb_id_table_iterator_result): add dummy sentinel member because C standard prohibits a trailing comma. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55821 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2016-05-20capa should be even number on 64-bit SPARC for 8-byte word alignmentngoto
* id_table.c (list_id_table_init): When unaligned word access is prohibited and sizeof(VALUE) is 8 (64-bit machines), capa should always be even number for 8-byte word alignment of the values of a table. This code assumes that sizeof(ID) is 4, sizeof(VALUE) is 8, and xmalloc() returns 8-byte aligned memory. This fixes bus error on 64-bit SPARC Solaris 10. [Bug #12406][ruby-dev:49631] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55086 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2016-01-22RUBY_ASSERTnobu
* error.c (rb_assert_failure): assertion with stack dump. * ruby_assert.h (RUBY_ASSERT): new header for the assertion. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@53615 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-11-02id_table: const correctness for _size and _memsizenormal
This allows us to swap in rb_id_table_memsize for st_memsize (which takes a "const st_table *") more easily. It also makes sense to do the same for rb_id_table_size, too; as the table cannot be altered when accessing size. * id_table.h (rb_id_table_size): const arg (rb_id_table_memsize): ditto * id_table.c (st_id_table_size): ditto (st_id_table_memsize): ditto (list_id_table_size): ditto (list_id_table_memsize): ditto (hash_id_table_size): ditto (hash_id_table_memsize): ditto (mix_id_table_size): ditto (mix_id_table_memsize): ditto git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52428 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-11-01* id_table.c (mix_id_table_insert): do not touch list duringko1
list->hash transition because GC can run during transition. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52421 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-09-27id_table.c: fix prototype namesnobu
* id_table.c: fix prototype names, missing underscore prefixes. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@51950 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-09-27id_table.c: fix prototype namesnobu
* id_table.c: fix prototype names, missing underscore prefixes. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@51949 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-09-27id_table.c: suppress warningsnobu
* id_table.c (UNUSED): mark implementation functions maybe-unused to suppress warnings by old gcc. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@51948 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-09-25* id_table.c: fix typo. [ci skip][fix GH-1031] Patch @davydovantonhsbt
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@51932 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-09-17id_table.c: fix typesnobu
* id_table.c (insert_into_chain, insert_into_main): fix argument types in prototype declarations. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@51884 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-08-26id_table.c: aliasesnobu
* id_table.c (IMPL_TYPE, IMPL_VOID): make aliases if supported on the platform. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@51683 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-08-26id_table.h: callback function typesnobu
* id_table.h (rb_id_table_foreach_func_t): define callback function type for rb_id_table_foreach(). * id_table.h (rb_id_table_foreach_values_func_t): ditto for rb_id_table_foreach_values(). git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@51682 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-08-26id_table.c: adjust indentnobu
* id_table.c (list_table_extend, fix_empty): adjust indent. (hash_id_table_foreach_values): ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@51681 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-08-26id_table.c: constifynobu
* id_table.c (find_empty): constify static data. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@51680 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-08-26id_table.c: fix for C89 compilersnobu
* id_table.c (list_table_extend, hash_table_extend): remove C99 features. [ruby-dev:49239] [Bug #11487] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@51678 b2dd03c8-39d4-4d8f-98ff-823fe69b080e