aboutsummaryrefslogtreecommitdiffstats
path: root/vm_method.c
diff options
context:
space:
mode:
authorKoichi Sasada <ko1@atdot.net>2020-12-13 05:55:18 +0900
committerKoichi Sasada <ko1@atdot.net>2020-12-14 11:57:46 +0900
commit967040ba59799e6b7891168ffbf37cc646988d84 (patch)
tree2f36f519d5c753ccd68dc08c8e6c65ea375ffcc6 /vm_method.c
parentfa63052be19b26d39b22689ad9969aa83909809e (diff)
downloadruby-967040ba59799e6b7891168ffbf37cc646988d84.tar.gz
Introduce negative method cache
pCMC doesn't have negative method cache so this patch implements it.
Diffstat (limited to 'vm_method.c')
-rw-r--r--vm_method.c42
1 files changed, 36 insertions, 6 deletions
diff --git a/vm_method.c b/vm_method.c
index 6845ad44f0..f87c52fc54 100644
--- a/vm_method.c
+++ b/vm_method.c
@@ -164,7 +164,6 @@ clear_method_cache_by_id_in_class(VALUE klass, ID mid)
if (cme) {
// invalidate cme if found to invalidate the inline method cache.
-
if (METHOD_ENTRY_CACHED(cme)) {
if (METHOD_ENTRY_COMPLEMENTED(cme)) {
// do nothing
@@ -177,6 +176,7 @@ clear_method_cache_by_id_in_class(VALUE klass, ID mid)
VALUE origin = RCLASS_ORIGIN(owner);
rb_method_table_insert(origin, RCLASS_M_TBL(origin), mid, new_cme);
}
+
vm_me_invalidate_cache((rb_callable_method_entry_t *)cme);
RB_DEBUG_COUNTER_INC(cc_invalidate_tree_cme);
}
@@ -193,6 +193,13 @@ clear_method_cache_by_id_in_class(VALUE klass, ID mid)
RB_DEBUG_COUNTER_INC(cc_invalidate_tree);
}
+ else {
+ rb_vm_t *vm = GET_VM();
+ if (rb_id_table_lookup(vm->negative_cme_table, mid, (VALUE *)&cme)) {
+ rb_id_table_delete(vm->negative_cme_table, mid);
+ vm_me_invalidate_cache((rb_callable_method_entry_t *)cme);
+ }
+ }
}
}
@@ -1038,7 +1045,7 @@ static const rb_callable_method_entry_t *
complemented_callable_method_entry(VALUE klass, ID id)
{
VALUE defined_class;
- rb_method_entry_t *me = search_method_protect(klass, id, &defined_class);
+ rb_method_entry_t *me = search_method(klass, id, &defined_class);
return prepare_callable_method_entry(defined_class, id, me, FALSE);
}
@@ -1070,6 +1077,7 @@ static void
cache_callable_method_entry(VALUE klass, ID mid, const rb_callable_method_entry_t *cme)
{
ASSERT_vm_locking();
+ VM_ASSERT(cme != NULL);
struct rb_id_table *cc_tbl = RCLASS_CC_TBL(klass);
struct rb_class_cc_entries *ccs;
@@ -1088,6 +1096,21 @@ cache_callable_method_entry(VALUE klass, ID mid, const rb_callable_method_entry_
}
static const rb_callable_method_entry_t *
+negative_cme(ID mid)
+{
+ rb_vm_t *vm = GET_VM();
+ const rb_callable_method_entry_t *cme;
+
+ if (!rb_id_table_lookup(vm->negative_cme_table, mid, (VALUE *)&cme)) {
+ cme = (rb_callable_method_entry_t *)rb_method_entry_alloc(mid, Qnil, Qnil, NULL);
+ rb_id_table_insert(vm->negative_cme_table, mid, (VALUE)cme);
+ }
+
+ VM_ASSERT(cme != NULL);
+ return cme;
+}
+
+static const rb_callable_method_entry_t *
callable_method_entry(VALUE klass, ID mid, VALUE *defined_class_ptr)
{
const rb_callable_method_entry_t *cme;
@@ -1102,15 +1125,22 @@ callable_method_entry(VALUE klass, ID mid, VALUE *defined_class_ptr)
}
else {
VALUE defined_class;
- rb_method_entry_t *me = search_method_protect(klass, mid, &defined_class);
+ rb_method_entry_t *me = search_method(klass, mid, &defined_class);
if (defined_class_ptr) *defined_class_ptr = defined_class;
- cme = prepare_callable_method_entry(defined_class, mid, me, TRUE);
- if (cme) cache_callable_method_entry(klass, mid, cme);
+
+ if (me != NULL) {
+ cme = prepare_callable_method_entry(defined_class, mid, me, TRUE);
+ }
+ else {
+ cme = negative_cme(mid);
+ }
+
+ cache_callable_method_entry(klass, mid, cme);
}
}
RB_VM_LOCK_LEAVE();
- return cme;
+ return !UNDEFINED_METHOD_ENTRY_P(cme) ? cme : NULL;
}
MJIT_FUNC_EXPORTED const rb_callable_method_entry_t *