summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--internal.h8
-rw-r--r--vm_insnhelper.c16
-rw-r--r--vm_method.c18
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,