diff --git a/internal.h b/internal.h index 3bd95c2c25..fe2b028f47 100644 --- a/internal.h +++ b/internal.h @@ -2282,6 +2282,7 @@ const char *rb_source_location_cstr(int *pline); MJIT_STATIC void rb_vm_pop_cfunc_frame(void); int rb_vm_add_root_module(ID id, VALUE module); void rb_vm_check_redefinition_by_prepend(VALUE klass); +int rb_vm_check_optimizable_mid(VALUE mid); VALUE rb_yield_refine_block(VALUE refinement, VALUE refinements); MJIT_STATIC VALUE ruby_vm_special_exception_copy(VALUE); PUREFUNC(st_table *rb_vm_fstring_table(void)); diff --git a/vm.c b/vm.c index 9a4147aba6..8c0f05b0a9 100644 --- a/vm.c +++ b/vm.c @@ -1557,6 +1557,7 @@ rb_iter_break_value(VALUE val) /* optimization: redefine management */ static st_table *vm_opt_method_table = 0; +static st_table *vm_opt_mid_table = 0; static int vm_redefinition_check_flag(VALUE klass) @@ -1576,6 +1577,16 @@ vm_redefinition_check_flag(VALUE klass) return 0; } +int +rb_vm_check_optimizable_mid(VALUE mid) +{ + if (!vm_opt_mid_table) { + return FALSE; + } + + return st_lookup(vm_opt_mid_table, mid, NULL); +} + static int vm_redefinition_check_method_type(const rb_method_definition_t *def) { @@ -1630,6 +1641,7 @@ add_opt_method(VALUE klass, ID mid, VALUE bop) if (me && vm_redefinition_check_method_type(me->def)) { st_insert(vm_opt_method_table, (st_data_t)me, (st_data_t)bop); + st_insert(vm_opt_mid_table, (st_data_t)mid, (st_data_t)Qtrue); } else { rb_bug("undefined optimized method: %s", rb_id2name(mid)); @@ -1643,6 +1655,7 @@ vm_init_redefined_flag(void) VALUE bop; vm_opt_method_table = st_init_numtable(); + vm_opt_mid_table = st_init_numtable(); #define OP(mid_, bop_) (mid = id##mid_, bop = BOP_##bop_, ruby_vm_redefined_flag[bop] = 0) #define C(k) add_opt_method(rb_c##k, mid, bop) diff --git a/vm_method.c b/vm_method.c index bcf6b0b8c0..d2bd677e6a 100644 --- a/vm_method.c +++ b/vm_method.c @@ -500,7 +500,7 @@ rb_add_refined_method_entry(VALUE refined_class, ID mid) } static void -check_override_opt_method(VALUE klass, VALUE arg) +check_override_opt_method_i(VALUE klass, VALUE arg) { ID mid = (ID)arg; const rb_method_entry_t *me, *newme; @@ -512,7 +512,15 @@ check_override_opt_method(VALUE klass, VALUE arg) if (newme != me) rb_vm_check_redefinition_opt_method(me, me->owner); } } - rb_class_foreach_subclass(klass, check_override_opt_method, (VALUE)mid); + rb_class_foreach_subclass(klass, check_override_opt_method_i, (VALUE)mid); +} + +static void +check_override_opt_method(VALUE klass, VALUE mid) +{ + if (rb_vm_check_optimizable_mid(mid)) { + check_override_opt_method_i(klass, mid); + } } /*