From df48db987da2bd623d29d06419f2fbc8b7ecb38a Mon Sep 17 00:00:00 2001 From: Koichi Sasada Date: Tue, 21 Dec 2021 06:03:51 +0900 Subject: `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. --- vm_callinfo.h | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'vm_callinfo.h') diff --git a/vm_callinfo.h b/vm_callinfo.h index 700fd3dc6c..09f755c818 100644 --- a/vm_callinfo.h +++ b/vm_callinfo.h @@ -449,6 +449,10 @@ struct rb_class_cc_entries { }; #if VM_CHECK_MODE > 0 + +const rb_callable_method_entry_t *rb_vm_lookup_overloaded_cme(const rb_callable_method_entry_t *cme); +void rb_vm_dump_overloaded_cme_table(void); + static inline bool vm_ccs_p(const struct rb_class_cc_entries *ccs) { @@ -459,15 +463,17 @@ static inline bool vm_cc_check_cme(const struct rb_callcache *cc, const rb_callable_method_entry_t *cme) { if (vm_cc_cme(cc) == cme || - (cme->def->iseq_overload && vm_cc_cme(cc) == cme->def->body.iseq.mandatory_only_cme)) { + (cme->def->iseq_overload && vm_cc_cme(cc) == rb_vm_lookup_overloaded_cme(cme))) { return true; } else { #if 1 - fprintf(stderr, "iseq_overload:%d mandatory_only_cme:%p eq:%d\n", - (int)cme->def->iseq_overload, - (void *)cme->def->body.iseq.mandatory_only_cme, - vm_cc_cme(cc) == cme->def->body.iseq.mandatory_only_cme); + // debug print + + fprintf(stderr, "iseq_overload:%d\n", (int)cme->def->iseq_overload); + rp(cme); + rp(vm_cc_cme(cc)); + rb_vm_lookup_overloaded_cme(cme); #endif return false; } -- cgit v1.2.3