summaryrefslogtreecommitdiff
path: root/imemo.c
AgeCommit message (Collapse)Author
2025-12-29Add rb_gc_register_pinning_objPeter Zhu
2025-12-29Move MEMO_NEW to imemo.c and rename to rb_imemo_memo_newPeter Zhu
2025-12-25Implement callcache using declare weak referencesPeter Zhu
2025-12-16Make tracepoints with set_trace_func or TracePoint.new ractor local (#15468)Luke Gruber
Before this change, GC'ing any Ractor object caused you to lose all enabled tracepoints across all ractors (even main). Now tracepoints are ractor-local and this doesn't happen. Internal events are still global. Fixes [Bug #19112]
2025-11-26Revert miscommit at "Reset the cache variable before retrying"Nobuyoshi Nakada
This reverts commit 26a9e0b4e31f7b5a9cbd755e0a15823a8fa51bae partially.
2025-11-26Reset the cache variable before retryingNobuyoshi Nakada
2025-11-26Box: mark/move Box object referred via ENV/rb_env_tSatoshi Tagomori
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-09-21Fix memory leak in cloning complex imemo_fieldsPeter Zhu
When we clone a complex imemo_fields, it calls creates the imemo_fields using rb_imemo_fields_new_complex, which allocates and initializes a new st_table. However, st_replace will directly replace any exisiting fields in the st_table, causing it to leak. For example, this script demonstrates the leak: obj = Class.new 8.times do |i| obj.instance_variable_set(:"@test#{i}", nil) obj.remove_instance_variable(:"@test#{i}") end obj.instance_variable_set(:"@test", 1) 10.times do 100_000.times do obj.dup end puts `ps -o rss= -p #{$$}` end Before: 26320 39296 52320 63136 75520 87008 97856 114800 120864 133504 After: 16288 20112 20416 20720 20800 20864 21184 21424 21904 21904
2025-09-19Fix capacity of imemo_fields objects created from ↵Peter Zhu
rb_imemo_fields_new_complex_tbl The imemo_fields_new function takes a capacity in the number of fields to preallocate. rb_imemo_fields_new_complex_tbl is using it incorrectly because it is preallocating sizeof(struct rb_fields) number of fields.
2025-09-19Directly use rb_imemo_new in imemo_fields_new_complexPeter Zhu
We should not assume that a complex imemo_field takes only one additional VALUE space. This is fragile as it will break if we add additional fields to complex imemo_field.
2025-09-17Clear out memory for newly allocated tmpbufPeter Zhu
2025-09-15Remove next field and unused method from tmpbufJohn Hawthorn
These used to be used by the parser
2025-09-15Make imemo_tmpbuf not write-barrier protectedPeter Zhu
imemo_tmpbuf is not write-barrier protected and uses mark maybe to mark the buffer it holds. The normal rb_imemo_new creates a write-barrier protected object which can make the tmpbuf miss marking references.
2025-09-15Move rb_imemo_tmpbuf_new to imemo.cPeter Zhu
2025-09-15Combine rb_imemo_tmpbuf_auto_free_pointer and rb_imemo_tmpbuf_newPeter Zhu
2025-09-12Use IMEMO_NEW in rb_imemo_tmpbuf_newPeter Zhu
2025-08-27Don't pin method hooks of bmethodsPeter Zhu
2025-08-27Replace ROBJECT_EMBED by ROBJECT_HEAPJean Boussier
The embed layout is way more common than the heap one, especially since WVA. I think it makes for more readable code to inverse the flag.
2025-08-26Ensure T_OBJECT and T_IMEMO/fields have identical layoutJean Boussier
2025-08-21variable.c: handle cleared fields_obj in genfields cacheJean Boussier
[Bug #21547] Followup: https://github.com/ruby/ruby/pull/14201 When adding an instance variable and the IMEMO/fields need to be larger, we allocate a new one and clear the old one. Since the old one may still be in other ec's cache, on a hit we must check the IMEMO/fields isn't a stale one.
2025-08-13imemo_fields: store owner object in RBasic.klassJean Boussier
It is much more convenient than storing the klass, especially when dealing with `object_id` as it allows to update the id2ref table without having to dereference the owner, which may be garbage at that point.
2025-08-07Invalidate CCs when cme is invalidated in markingJohn Hawthorn
* Skip assertion when cc->klass is Qundef * Invalidate CCs when cme is invalidated in marking * Add additional assertions that CC references stay valid Co-authored-by: Peter Zhu <peter@peterzhu.ca>
2025-08-06Avoid marking CC children after invalidationJohn Hawthorn
Once klass becomes Qundef, it's disconnected and won't be invalidated when the CME is. So once that happens we must not mark or attempt to move the cme_ field.
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-08-01Use `rb_gc_mark_weak` for `cc->klass`.Jean Boussier
One of the biggest remaining contention point is `RClass.cc_table`. The logical solution would be to turn it into a managed object, so we can use an RCU strategy, given it's read heavy. However, that's not currently possible because the table can't be freed before the owning class, given the class free function MUST go over all the CC entries to invalidate them. However if the `CC->klass` reference is weak marked, then the GC will take care of setting the reference to `Qundef`.
2025-07-29Get rid of imemo_astJean Boussier
It has been marked as obsolete for a while and I see no reason to keep it.
2025-07-24Remove unused imemo_parser_strtermPeter Zhu
2025-07-14Remove dead rb_cc_table_freePeter Zhu
2025-07-14Remove dead rb_cc_table_markPeter Zhu
2025-06-17Add missing write barriers in `rb_imemo_fields_clone`.Jean Boussier
Notes: Merged: https://github.com/ruby/ruby/pull/13626
2025-06-17Refactor generic fields to use `T_IMEMO/fields` objects.Jean Boussier
Followup: https://github.com/ruby/ruby/pull/13589 This simplify a lot of things, as we no longer need to manually manage the memory, we can use the Read-Copy-Update pattern and avoid numerous race conditions. Co-Authored-By: Étienne Barrié <etienne.barrie@gmail.com> Notes: Merged: https://github.com/ruby/ruby/pull/13626
2025-06-17Refactor `rb_imemo_fields_new` to not assume T_CLASSJean Boussier
Notes: Merged: https://github.com/ruby/ruby/pull/13626
2025-06-17Rename `imemo_class_fields` -> `imemo_fields`Jean Boussier
Notes: Merged: https://github.com/ruby/ruby/pull/13626
2025-06-12Make setting and accessing class ivars lock-freeJean Boussier
Now that class fields have been deletated to a T_IMEMO/class_fields when we're in multi-ractor mode, we can read and write class instance variable in an atomic way using Read-Copy-Update (RCU). Note when in multi-ractor mode, we always use RCU. In theory we don't need to, instead if we ensured the field is written before the shape is updated it would be safe. Benchmark: ```ruby Warning[:experimental] = false class Foo @foo = 1 @bar = 2 @baz = 3 @egg = 4 @spam = 5 class << self attr_reader :foo, :bar, :baz, :egg, :spam end end ractors = 8.times.map do Ractor.new do 1_000_000.times do Foo.bar + Foo.baz * Foo.egg - Foo.spam end end end if Ractor.method_defined?(:value) ractors.each(&:value) else ractors.each(&:take) end ``` This branch vs Ruby 3.4: ```bash $ hyperfine -w 1 'ruby --disable-all ../test.rb' './miniruby ../test.rb' Benchmark 1: ruby --disable-all ../test.rb Time (mean ± σ): 3.162 s ± 0.071 s [User: 2.783 s, System: 10.809 s] Range (min … max): 3.093 s … 3.337 s 10 runs Benchmark 2: ./miniruby ../test.rb Time (mean ± σ): 208.7 ms ± 4.6 ms [User: 889.7 ms, System: 6.9 ms] Range (min … max): 202.8 ms … 222.0 ms 14 runs Summary ./miniruby ../test.rb ran 15.15 ± 0.47 times faster than ruby --disable-all ../test.rb ``` Notes: Merged: https://github.com/ruby/ruby/pull/13594
2025-06-12Fix class instance variable inside namespacesJean Boussier
Now that classes fields are delegated to an object with its own shape_id, we no longer need to mark all classes as TOO_COMPLEX. Notes: Merged: https://github.com/ruby/ruby/pull/13595
2025-06-12Turn `rb_classext_t.fields` into a T_IMEMO/class_fieldsJean Boussier
This behave almost exactly as a T_OBJECT, the layout is entirely compatible. This aims to solve two problems. First, it solves the problem of namspaced classes having a single `shape_id`. Now each namespaced classext has an object that can hold the namespace specific shape. Second, it open the door to later make class instance variable writes atomics, hence be able to read class variables without locking the VM. In the future, in multi-ractor mode, we can do the write on a copy of the `fields_obj` and then atomically swap it. Considerations: - Right now the `RClass` shape_id is always synchronized, but with namespace we should likely mark classes that have multiple namespace with a specific shape flag. Notes: Merged: https://github.com/ruby/ruby/pull/13411
2025-05-11namespace on readSatoshi Tagomori
2025-03-16Only mark `cc->cme_` on valid imemo_callcacheAlan Wu
We observed T_NONE on `cc->cme_` on a --repeat-count=50 run a compaction test on CI: http://ci.rvm.jp/results/trunk-repeat50@ruby-sp2-noble-docker/5654900 During reference updating for imemo_callcache in rb_imemo_mark_and_move(), if `cc->klass` is not live, but `cc->_cme` is live and moved, we go to the vm_cc_invalidate() path which leaves `cc->_cme` not updated and stale. In the next marking run after compaction, CME would've become a T_NONE. So to quote the comment above "... cc is invalidated by `vm_cc_invalidate()` and cc->cme is not be accessed." Notes: Merged: https://github.com/ruby/ruby/pull/12936 Merged-By: XrXr
2025-01-08Pass allocation size to rb_imemo_newPeter Zhu
This would allow imemo to take advantage of VWA and allocate sizes larger than RVALUE (40 bytes). Notes: Merged: https://github.com/ruby/ruby/pull/12524
2025-01-07Remove IMEMO_DEBUGPeter Zhu
The code path hasn't compiled for almost a year, since 330830dd1a44b6e497250a14d93efae6fa363f82, so probably nobody uses it. Notes: Merged: https://github.com/ruby/ruby/pull/12519
2024-12-19Don't unpoison the CC in vm_ccs_freePeter Zhu
The poison status is maintained by the GC, so don't unpoison it in vm_ccs_free. If the object is not a garbage object, then it should not be poisoned. Notes: Merged: https://github.com/ruby/ruby/pull/12402
2024-12-19Fix use-after-free in vm_ccs_free()Alan Wu
`struct rb_callcache *` point to an imemo object on the GC heap when pushed into `struct rb_class_cc_entries`, but by the time vm_ccs_free() runs, the entire GC page the imemo was on could already be deallocated. With the right conditions, vm_ccs_free() wrote to freed memory. rb_objspace_garbage_object_p() by itself is not enough to determine liveness. I conjectured this situation to be possible in <https://github.com/ruby/ruby/pull/11995> using hints from crashes in the wild. With c37bdfa5311be0aa8503b995299fb9547cede0a6 ("Make asan_poison_object poison the whole slot"), the in-tree test suite now recreates this scenario[^1][^2][^3]. Use rb_gc_pointer_to_heap_p(). Other uses of rb_objspace_garbage_object_p() could be making the same mistake, but correcting them might introduce serious performance regressions, so leave them alone for now. [^1]: http://ci.rvm.jp/results/trunk_asan@ruby-sp1/5477412 [^2]: http://ci.rvm.jp/results/trunk_asan@ruby-sp1/5477445 [^3]: http://ci.rvm.jp/results/trunk_asan@ruby-sp1/5477448 Notes: Merged: https://github.com/ruby/ruby/pull/12401 Merged-By: XrXr
2024-12-19Prefix asan_poison_object with rbPeter Zhu
Notes: Merged: https://github.com/ruby/ruby/pull/12385
2024-11-25Place all non-default GC API behind USE_SHARED_GCMatt Valentine-House
So that it doesn't get included in the generated binaries for builds that don't support loading shared GC modules Co-Authored-By: Peter Zhu <peter@peterzhu.ca> Notes: Merged: https://github.com/ruby/ruby/pull/12149
2024-09-10Use rb_id_table_foreach_values for marking CC tablePeter Zhu
We don't use the key, so we can speed it up by not needing to convert the key to ID in the iterator. Notes: Merged: https://github.com/ruby/ruby/pull/11580
2024-07-03[Feature #20470] Split GC into gc_impl.cPeter Zhu
This commit splits gc.c into two files: - gc.c now only contains code not specific to Ruby GC. This includes code to mark objects (which the GC implementation may choose not to use) and wrappers for internal APIs that the implementation may need to use (e.g. locking the VM). - gc_impl.c now contains the implementation of Ruby's GC. This includes marking, sweeping, compaction, and statistics. Most importantly, gc_impl.c only uses public APIs in Ruby and a limited set of functions exposed in gc.c. This allows us to build gc_impl.c independently of Ruby and plug Ruby's GC into itself.
2024-06-18Mark the class on orphan call cachesAaron Patterson
"super" CC's are "orphans", meaning there is no class CC table that points at them. Since they are orphans, we should mark the class reference so that if the cache happens to be used, the class will still be alive
2024-06-03Avoid unnecessary writes to imemo_env during GCJohn Hawthorn
Similar to the previous commit, to avoid unnecessary Copy-on-Write memory use we should only set this flag when it has not previously been set.