diff options
-rw-r--r-- | internal.h | 8 | ||||
-rw-r--r-- | vm_insnhelper.c | 16 | ||||
-rw-r--r-- | vm_method.c | 18 |
3 files changed, 37 insertions, 5 deletions
diff --git a/internal.h b/internal.h index 6c6e262f65..0c245c3d43 100644 --- a/internal.h +++ b/internal.h @@ -2389,6 +2389,8 @@ struct rb_call_data { }; RUBY_FUNC_EXPORTED RUBY_FUNC_NONNULL(1, VALUE rb_funcallv_with_cc(struct rb_call_data*, VALUE, ID, int, const VALUE*)); +RUBY_FUNC_EXPORTED +RUBY_FUNC_NONNULL(1, bool rb_method_basic_definition_p_with_cc(struct rb_call_data *, VALUE, ID)); #ifdef __GNUC__ # define rb_funcallv(recv, mid, argc, argv) \ @@ -2396,6 +2398,12 @@ RUBY_FUNC_NONNULL(1, VALUE rb_funcallv_with_cc(struct rb_call_data*, VALUE, ID, static struct rb_call_data rb_funcallv_data = { { 0, }, { 0, }, }; \ rb_funcallv_with_cc(&rb_funcallv_data, recv, mid, argc, argv); \ }) +# define rb_method_basic_definition_p(klass, mid) \ + __extension__({ \ + static struct rb_call_data rb_mbdp = { { 0, }, { 0, }, }; \ + (klass == Qfalse) ? /* hidden object cannot be overridden */ true : \ + rb_method_basic_definition_p_with_cc(&rb_mbdp, klass, mid); \ + }) #endif /* miniprelude.c, prelude.c */ diff --git a/vm_insnhelper.c b/vm_insnhelper.c index a4bc276f04..5e1cfccf3c 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -1433,13 +1433,9 @@ rb_vm_search_method_slowpath(struct rb_call_data *cd, VALUE klass) } static void -vm_search_method(struct rb_call_data *cd, VALUE recv) +vm_search_method_fastpath(struct rb_call_data *cd, VALUE klass) { struct rb_call_cache *cc = &cd->cc; - VALUE klass = CLASS_OF(recv); - - VM_ASSERT(klass != Qfalse); - VM_ASSERT(RBASIC_CLASS(klass) == 0 || rb_obj_is_kind_of(klass, rb_cClass)); #if OPT_INLINE_METHOD_CACHE if (LIKELY(RB_DEBUG_COUNTER_INC_UNLESS(mc_global_state_miss, @@ -1456,6 +1452,16 @@ vm_search_method(struct rb_call_data *cd, VALUE recv) rb_vm_search_method_slowpath(cd, klass); } +static void +vm_search_method(struct rb_call_data *cd, VALUE recv) +{ + VALUE klass = CLASS_OF(recv); + + VM_ASSERT(klass != Qfalse); + VM_ASSERT(RBASIC_CLASS(klass) == 0 || rb_obj_is_kind_of(klass, rb_cClass)); + vm_search_method_fastpath(cd, klass); +} + static inline int check_cfunc(const rb_callable_method_entry_t *me, VALUE (*func)()) { diff --git a/vm_method.c b/vm_method.c index 5ee1773fe2..311a66993a 100644 --- a/vm_method.c +++ b/vm_method.c @@ -2024,6 +2024,21 @@ rb_mod_modfunc(int argc, VALUE *argv, VALUE module) return module; } +bool +rb_method_basic_definition_p_with_cc(struct rb_call_data *cd, VALUE klass, ID mid) +{ + if (cd->ci.mid != mid) { + *cd = (struct rb_call_data) /* reset */ { .ci = { .mid = mid, }, }; + } + + vm_search_method_fastpath(cd, klass); + return cd->cc.me && METHOD_ENTRY_BASIC(cd->cc.me); +} + +#ifdef __GNUC__ +#pragma push_macro("rb_method_basic_definition_p") +#undef rb_method_basic_definition_p +#endif int rb_method_basic_definition_p(VALUE klass, ID id) { @@ -2032,6 +2047,9 @@ rb_method_basic_definition_p(VALUE klass, ID id) me = rb_method_entry(klass, id); return (me && METHOD_ENTRY_BASIC(me)) ? TRUE : FALSE; } +#ifdef __GNUC__ +#pragma pop_macro("rb_method_basic_definition_p") +#endif static VALUE call_method_entry(rb_execution_context_t *ec, VALUE defined_class, VALUE obj, ID id, |