summaryrefslogtreecommitdiff
path: root/vm_insnhelper.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 /vm_insnhelper.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 'vm_insnhelper.c')
-rw-r--r--vm_insnhelper.c16
1 files changed, 5 insertions, 11 deletions
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index c6b079e7d5..37229b5dc0 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -1766,7 +1766,7 @@ vm_ccs_verify(struct rb_class_cc_entries *ccs, ID mid, VALUE klass)
#ifndef MJIT_HEADER
-static const rb_callable_method_entry_t *overloaded_cme(const rb_callable_method_entry_t *cme);
+static const rb_callable_method_entry_t *check_overloaded_cme(const rb_callable_method_entry_t *cme, const struct rb_callinfo * const ci);
static const struct rb_callcache *
vm_search_cc(const VALUE klass, const struct rb_callinfo * const ci)
@@ -1780,7 +1780,6 @@ vm_search_cc(const VALUE klass, const struct rb_callinfo * const ci)
if (rb_id_table_lookup(cc_tbl, mid, &ccs_data)) {
ccs = (struct rb_class_cc_entries *)ccs_data;
const int ccs_len = ccs->len;
- VM_ASSERT(vm_ccs_verify(ccs, mid, klass));
if (UNLIKELY(METHOD_ENTRY_INVALIDATED(ccs->cme))) {
rb_vm_ccs_free(ccs);
@@ -1788,6 +1787,8 @@ vm_search_cc(const VALUE klass, const struct rb_callinfo * const ci)
ccs = NULL;
}
else {
+ VM_ASSERT(vm_ccs_verify(ccs, mid, klass));
+
for (int i=0; i<ccs_len; i++) {
const struct rb_callinfo *ccs_ci = ccs->entries[i].ci;
const struct rb_callcache *ccs_cc = ccs->entries[i].cc;
@@ -1852,15 +1853,8 @@ vm_search_cc(const VALUE klass, const struct rb_callinfo * const ci)
}
}
- if (cme->def->iseq_overload &&
- (vm_ci_flag(ci) & (VM_CALL_ARGS_SIMPLE)) &&
- (int)vm_ci_argc(ci) == method_entry_iseqptr(cme)->body->param.lead_num
- ) {
- // use alternative
- cme = overloaded_cme(cme);
- METHOD_ENTRY_CACHED_SET((struct rb_callable_method_entry_struct *)cme);
- // rp(cme);
- }
+ cme = check_overloaded_cme(cme, ci);
+
const struct rb_callcache *cc = vm_cc_new(klass, cme, vm_call_general);
vm_ccs_push(klass, ccs, ci, cc);