summaryrefslogtreecommitdiff
path: root/imemo.c
diff options
context:
space:
mode:
authorJean Boussier <jean.boussier@gmail.com>2025-07-29 15:13:01 +0200
committerJean Boussier <jean.boussier@gmail.com>2025-08-01 10:42:04 +0200
commitfc5e1541e4bb4b7995b6acc1ea6121b60fc64e7a (patch)
tree502509a59f9433d205a27b0875f30a3648d83569 /imemo.c
parent1055e04e28a66b82d8c2118bb61763961ed4d1c9 (diff)
Use `rb_gc_mark_weak` for `cc->klass`.
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`.
Diffstat (limited to 'imemo.c')
-rw-r--r--imemo.c24
1 files changed, 9 insertions, 15 deletions
diff --git a/imemo.c b/imemo.c
index 7153689030..985ab9aa5d 100644
--- a/imemo.c
+++ b/imemo.c
@@ -273,7 +273,7 @@ rb_imemo_memsize(VALUE obj)
static bool
moved_or_living_object_strictly_p(VALUE obj)
{
- return obj && (!rb_objspace_garbage_object_p(obj) || BUILTIN_TYPE(obj) == T_MOVED);
+ return !SPECIAL_CONST_P(obj) && (!rb_objspace_garbage_object_p(obj) || BUILTIN_TYPE(obj) == T_MOVED);
}
static void
@@ -353,25 +353,19 @@ rb_imemo_mark_and_move(VALUE obj, bool reference_updating)
*/
struct rb_callcache *cc = (struct rb_callcache *)obj;
if (reference_updating) {
- if (!cc->klass) {
- // already invalidated
+ if (moved_or_living_object_strictly_p((VALUE)cc->cme_)) {
+ *((VALUE *)&cc->klass) = rb_gc_location(cc->klass);
+ *((struct rb_callable_method_entry_struct **)&cc->cme_) =
+ (struct rb_callable_method_entry_struct *)rb_gc_location((VALUE)cc->cme_);
}
- else {
- if (moved_or_living_object_strictly_p(cc->klass) &&
- moved_or_living_object_strictly_p((VALUE)cc->cme_)) {
- *((VALUE *)&cc->klass) = rb_gc_location(cc->klass);
- *((struct rb_callable_method_entry_struct **)&cc->cme_) =
- (struct rb_callable_method_entry_struct *)rb_gc_location((VALUE)cc->cme_);
- }
- else {
- vm_cc_invalidate(cc);
- }
+ else if (vm_cc_valid(cc)) {
+ vm_cc_invalidate(cc);
}
}
else {
- if (cc->klass && (vm_cc_super_p(cc) || vm_cc_refinement_p(cc))) {
+ rb_gc_mark_weak((VALUE *)&cc->klass);
+ if ((vm_cc_super_p(cc) || vm_cc_refinement_p(cc))) {
rb_gc_mark_movable((VALUE)cc->cme_);
- rb_gc_mark_movable((VALUE)cc->klass);
}
}