summaryrefslogtreecommitdiff
path: root/gc.c
diff options
context:
space:
mode:
authorKoichi Sasada <ko1@atdot.net>2021-12-21 06:03:51 +0900
committerKoichi Sasada <ko1@atdot.net>2021-12-21 11:03:09 +0900
commitdf48db987da2bd623d29d06419f2fbc8b7ecb38a (patch)
treeed86fd0472dd5885581e21c7947afafff4eef483 /gc.c
parent711342d93565092a8348ac5538bc4b4288d384ba (diff)
`mandatory_only_cme` should not be in `def`
`def` (`rb_method_definition_t`) is shared by multiple callable method entries (cme, `rb_callable_method_entry_t`). There are two issues: * old -> young reference: `cme1->def->mandatory_only_cme = monly_cme` if `cme1` is young and `monly_cme` is young, there is no problem. Howevr, another old `cme2` can refer `def`, in this case, old `cme2` points young `monly_cme` and it violates gengc assumption. * cme can have different `defined_class` but `monly_cme` only has one `defined_class`. It does not make sense and `monly_cme` should be created for a cme (not `def`). To solve these issues, this patch allocates `monly_cme` per `cme`. `cme` does not have another room to store a pointer to the `monly_cme`, so this patch introduces `overloaded_cme_table`, which is weak key map `[cme] -> [monly_cme]`. `def::body::iseqptr::monly_cme` is deleted. The first issue is reported by Alan Wu.
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/5311
Diffstat (limited to 'gc.c')
-rw-r--r--gc.c17
1 files changed, 13 insertions, 4 deletions
diff --git a/gc.c b/gc.c
index 5a723762ad..5fd46defb4 100644
--- a/gc.c
+++ b/gc.c
@@ -6363,6 +6363,8 @@ rb_mark_hash(st_table *tbl)
mark_st(&rb_objspace, tbl);
}
+const rb_callable_method_entry_t *rb_vm_lookup_overloaded_cme(const rb_callable_method_entry_t *cme);
+
static void
mark_method_entry(rb_objspace_t *objspace, const rb_method_entry_t *me)
{
@@ -6376,7 +6378,13 @@ mark_method_entry(rb_objspace_t *objspace, const rb_method_entry_t *me)
case VM_METHOD_TYPE_ISEQ:
if (def->body.iseq.iseqptr) gc_mark(objspace, (VALUE)def->body.iseq.iseqptr);
gc_mark(objspace, (VALUE)def->body.iseq.cref);
- if (def->body.iseq.mandatory_only_cme) gc_mark(objspace, (VALUE)def->body.iseq.mandatory_only_cme);
+ if (def->iseq_overload && me->defined_class) { // cme
+ const rb_callable_method_entry_t *monly_cme = rb_vm_lookup_overloaded_cme((const rb_callable_method_entry_t *)me);
+ if (monly_cme) {
+ gc_mark(objspace, (VALUE)monly_cme);
+ gc_mark_and_pin(objspace, (VALUE)me);
+ }
+ }
break;
case VM_METHOD_TYPE_ATTRSET:
case VM_METHOD_TYPE_IVAR:
@@ -9599,9 +9607,6 @@ gc_ref_update_method_entry(rb_objspace_t *objspace, rb_method_entry_t *me)
TYPED_UPDATE_IF_MOVED(objspace, rb_iseq_t *, def->body.iseq.iseqptr);
}
TYPED_UPDATE_IF_MOVED(objspace, rb_cref_t *, def->body.iseq.cref);
- if (def->body.iseq.mandatory_only_cme) {
- TYPED_UPDATE_IF_MOVED(objspace, rb_callable_method_entry_t *, def->body.iseq.mandatory_only_cme);
- }
break;
case VM_METHOD_TYPE_ATTRSET:
case VM_METHOD_TYPE_IVAR:
@@ -10108,6 +10113,9 @@ gc_ref_update(void *vstart, void *vend, size_t stride, rb_objspace_t * objspace,
extern rb_symbols_t ruby_global_symbols;
#define global_symbols ruby_global_symbols
+
+st_table *rb_vm_overloaded_cme_table(void);
+
static void
gc_update_references(rb_objspace_t *objspace)
{
@@ -10143,6 +10151,7 @@ gc_update_references(rb_objspace_t *objspace)
gc_update_table_refs(objspace, objspace->id_to_obj_tbl);
gc_update_table_refs(objspace, global_symbols.str_sym);
gc_update_table_refs(objspace, finalizer_table);
+ gc_update_table_refs(objspace, rb_vm_overloaded_cme_table());
}
static VALUE