From f4ce78d5c139a8825ee2d09f39aef03ef762dfc6 Mon Sep 17 00:00:00 2001 From: Koichi Sasada Date: Wed, 13 Jan 2021 17:33:53 +0900 Subject: delete negative cache from the table correctly negative cache entry should be removed from vm->negative_cme_table even if the redefined class has no subclasses. --- vm_method.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) (limited to 'vm_method.c') diff --git a/vm_method.c b/vm_method.c index 61b27da513..287d4aee6d 100644 --- a/vm_method.c +++ b/vm_method.c @@ -114,7 +114,7 @@ rb_vm_mtbl_dump(const char *msg, VALUE klass, ID target_mid) } static inline void -vm_me_invalidate_cache(rb_callable_method_entry_t *cme) +vm_cme_invalidate(rb_callable_method_entry_t *cme) { VM_ASSERT(IMEMO_TYPE_P(cme, imemo_ment)); VM_ASSERT(callable_method_entry_p(cme)); @@ -128,6 +128,21 @@ rb_clear_constant_cache(void) INC_GLOBAL_CONSTANT_STATE(); } +static void +invaldate_negative_cache(ID mid, bool invalidate_cme) +{ + const rb_callable_method_entry_t *cme; + 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); + if (invalidate_cme) { + vm_cme_invalidate((rb_callable_method_entry_t *)cme); + RB_DEBUG_COUNTER_INC(cc_invalidate_negative); + } + } +} + static rb_method_entry_t *rb_method_entry_alloc(ID called_id, VALUE owner, VALUE defined_class, const rb_method_definition_t *def); const rb_method_entry_t * rb_method_entry_clone(const rb_method_entry_t *src_me); static const rb_callable_method_entry_t *complemented_callable_method_entry(VALUE klass, ID id); @@ -146,6 +161,7 @@ clear_method_cache_by_id_in_class(VALUE klass, ID mid) // invalidate CCs if (cc_tbl && rb_id_table_lookup(cc_tbl, mid, (VALUE *)&ccs)) { + if (NIL_P(ccs->cme->owner)) invaldate_negative_cache(mid, false); rb_vm_ccs_free(ccs); rb_id_table_delete(cc_tbl, mid); RB_DEBUG_COUNTER_INC(cc_invalidate_leaf_ccs); @@ -177,7 +193,7 @@ clear_method_cache_by_id_in_class(VALUE klass, ID mid) rb_method_table_insert(origin, RCLASS_M_TBL(origin), mid, new_cme); } - vm_me_invalidate_cache((rb_callable_method_entry_t *)cme); + vm_cme_invalidate((rb_callable_method_entry_t *)cme); RB_DEBUG_COUNTER_INC(cc_invalidate_tree_cme); } @@ -194,13 +210,7 @@ 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); - - RB_DEBUG_COUNTER_INC(cc_invalidate_negative); - } + invaldate_negative_cache(mid, true); } } } -- cgit v1.2.3