rb_method_basic_definition_p with CC
Noticed that rb_method_basic_definition_p is frequently called. Its callers include vm_caller_setup_args_block(), rb_hash_default_value(), rb_num_neative_int_p(), and a lot more. It seems worth caching the method resolution part. Majority of rb_method_basic_definion_p() usages take fixed class and fixed method id combinations. Calculating ------------------------------------- ours trunk so_matrix 2.379 2.115 i/s - 1.000 times in 0.420409s 0.472879s Comparison: so_matrix ours: 2.4 i/s trunk: 2.1 i/s - 1.12x slower
This commit is contained in:
parent
1390d56ecf
commit
6ff1250739
Notes:
git
2019-11-05 11:40:01 +09:00
@ -2389,6 +2389,8 @@ struct rb_call_data {
|
|||||||
};
|
};
|
||||||
RUBY_FUNC_EXPORTED
|
RUBY_FUNC_EXPORTED
|
||||||
RUBY_FUNC_NONNULL(1, VALUE rb_funcallv_with_cc(struct rb_call_data*, VALUE, ID, int, const VALUE*));
|
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__
|
#ifdef __GNUC__
|
||||||
# define rb_funcallv(recv, mid, argc, argv) \
|
# 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, }, }; \
|
static struct rb_call_data rb_funcallv_data = { { 0, }, { 0, }, }; \
|
||||||
rb_funcallv_with_cc(&rb_funcallv_data, recv, mid, argc, argv); \
|
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
|
#endif
|
||||||
|
|
||||||
/* miniprelude.c, prelude.c */
|
/* miniprelude.c, prelude.c */
|
||||||
|
@ -1433,13 +1433,9 @@ rb_vm_search_method_slowpath(struct rb_call_data *cd, VALUE klass)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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;
|
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 OPT_INLINE_METHOD_CACHE
|
||||||
if (LIKELY(RB_DEBUG_COUNTER_INC_UNLESS(mc_global_state_miss,
|
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);
|
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
|
static inline int
|
||||||
check_cfunc(const rb_callable_method_entry_t *me, VALUE (*func)())
|
check_cfunc(const rb_callable_method_entry_t *me, VALUE (*func)())
|
||||||
{
|
{
|
||||||
|
18
vm_method.c
18
vm_method.c
@ -2024,6 +2024,21 @@ rb_mod_modfunc(int argc, VALUE *argv, VALUE module)
|
|||||||
return 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
|
int
|
||||||
rb_method_basic_definition_p(VALUE klass, ID id)
|
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);
|
me = rb_method_entry(klass, id);
|
||||||
return (me && METHOD_ENTRY_BASIC(me)) ? TRUE : FALSE;
|
return (me && METHOD_ENTRY_BASIC(me)) ? TRUE : FALSE;
|
||||||
}
|
}
|
||||||
|
#ifdef __GNUC__
|
||||||
|
#pragma pop_macro("rb_method_basic_definition_p")
|
||||||
|
#endif
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
call_method_entry(rb_execution_context_t *ec, VALUE defined_class, VALUE obj, ID id,
|
call_method_entry(rb_execution_context_t *ec, VALUE defined_class, VALUE obj, ID id,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user