[前][次][番号順一覧][スレッド一覧]

ruby-changes:64133

From: Koichi <ko1@a...>
Date: Mon, 14 Dec 2020 11:58:09 +0900 (JST)
Subject: [ruby-changes:64133] 967040ba59 (master): Introduce negative method cache

https://git.ruby-lang.org/ruby.git/commit/?id=967040ba59

From 967040ba59799e6b7891168ffbf37cc646988d84 Mon Sep 17 00:00:00 2001
From: Koichi Sasada <ko1@a...>
Date: Sun, 13 Dec 2020 05:55:18 +0900
Subject: Introduce negative method cache

pCMC doesn't have negative method cache so this patch  implements it.

diff --git a/thread.c b/thread.c
index e910615..e60d71f 100644
--- a/thread.c
+++ b/thread.c
@@ -5671,6 +5671,8 @@ rb_resolve_me_location(const rb_method_entry_t *me, VALUE resolved_location[5]) https://github.com/ruby/ruby/blob/trunk/thread.c#L5671
 {
     VALUE path, beg_pos_lineno, beg_pos_column, end_pos_lineno, end_pos_column;
 
+    if (!me->def) return NULL; // negative cme
+
   retry:
     switch (me->def->type) {
       case VM_METHOD_TYPE_ISEQ: {
diff --git a/vm.c b/vm.c
index 6573925..c6f3344 100644
--- a/vm.c
+++ b/vm.c
@@ -2530,6 +2530,13 @@ rb_vm_each_stack_value(void *ptr, void (*cb)(VALUE, void*), void *ctx) https://github.com/ruby/ruby/blob/trunk/vm.c#L2530
     }
 }
 
+static enum rb_id_table_iterator_result
+vm_mark_negative_cme(VALUE val, void *dmy)
+{
+    rb_gc_mark(val);
+    return ID_TABLE_CONTINUE;
+}
+
 void
 rb_vm_mark(void *ptr)
 {
@@ -2585,6 +2592,8 @@ rb_vm_mark(void *ptr) https://github.com/ruby/ruby/blob/trunk/vm.c#L2592
 
 	rb_gc_mark_values(RUBY_NSIG, vm->trap_list.cmd);
 
+        rb_id_table_foreach_values(vm->negative_cme_table, vm_mark_negative_cme, NULL);
+
         mjit_mark();
     }
 
@@ -3660,6 +3669,7 @@ Init_BareVM(void) https://github.com/ruby/ruby/blob/trunk/vm.c#L3669
 
     vm->objspace = rb_objspace_alloc();
     ruby_current_vm_ptr = vm;
+    vm->negative_cme_table = rb_id_table_create(16);
 
     Init_native_thread(th);
     th->vm = vm;
diff --git a/vm_core.h b/vm_core.h
index a4c0e87..117671b 100644
--- a/vm_core.h
+++ b/vm_core.h
@@ -649,6 +649,8 @@ typedef struct rb_vm_struct { https://github.com/ruby/ruby/blob/trunk/vm_core.h#L649
     const struct rb_builtin_function *builtin_function_table;
     int builtin_inline_index;
 
+    struct rb_id_table *negative_cme_table;
+
 #if USE_VM_CLOCK
     uint32_t clock;
 #endif
diff --git a/vm_method.c b/vm_method.c
index 6845ad4..f87c52f 100644
--- a/vm_method.c
+++ b/vm_method.c
@@ -164,7 +164,6 @@ clear_method_cache_by_id_in_class(VALUE klass, ID mid) https://github.com/ruby/ruby/blob/trunk/vm_method.c#L164
 
         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) https://github.com/ruby/ruby/blob/trunk/vm_method.c#L176
                     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) https://github.com/ruby/ruby/blob/trunk/vm_method.c#L193
 
             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 * https://github.com/ruby/ruby/blob/trunk/vm_method.c#L1045
 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 https://github.com/ruby/ruby/blob/trunk/vm_method.c#L1077
 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_ https://github.com/ruby/ruby/blob/trunk/vm_method.c#L1096
 }
 
 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) https://github.com/ruby/ruby/blob/trunk/vm_method.c#L1125
         }
         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 *
-- 
cgit v0.10.2


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]