Reuse slow path method search for gccct
This way all code paths use the same search code for finding call caches for a particular method.
This commit is contained in:
parent
9bba999be7
commit
853c0b1a77
86
vm_eval.c
86
vm_eval.c
@ -29,15 +29,6 @@ static VALUE rb_eUncaughtThrow;
|
||||
static ID id_result, id_tag, id_value;
|
||||
#define id_mesg idMesg
|
||||
|
||||
typedef enum call_type {
|
||||
CALL_PUBLIC,
|
||||
CALL_FCALL,
|
||||
CALL_VCALL,
|
||||
CALL_PUBLIC_KW,
|
||||
CALL_FCALL_KW,
|
||||
CALL_TYPE_MAX
|
||||
} call_type;
|
||||
|
||||
static VALUE send_internal(int argc, const VALUE *argv, VALUE recv, call_type scope);
|
||||
static VALUE vm_call0_body(rb_execution_context_t* ec, struct rb_calling_info *calling, const VALUE *argv);
|
||||
|
||||
@ -403,61 +394,46 @@ NORETURN(static void uncallable_object(VALUE recv, ID mid));
|
||||
static inline const rb_callable_method_entry_t *rb_search_method_entry(VALUE recv, ID mid);
|
||||
static inline enum method_missing_reason rb_method_call_status(rb_execution_context_t *ec, const rb_callable_method_entry_t *me, call_type scope, VALUE self);
|
||||
|
||||
static const struct rb_callcache *
|
||||
cc_new(VALUE klass, ID mid, int argc, const rb_callable_method_entry_t *cme)
|
||||
{
|
||||
const struct rb_callcache *cc = NULL;
|
||||
|
||||
RB_VM_LOCK_ENTER();
|
||||
{
|
||||
struct rb_class_cc_entries *ccs;
|
||||
struct rb_id_table *cc_tbl = RCLASS_CC_TBL(klass);
|
||||
VALUE ccs_data;
|
||||
|
||||
if (rb_id_table_lookup(cc_tbl, mid, &ccs_data)) {
|
||||
// ok
|
||||
ccs = (struct rb_class_cc_entries *)ccs_data;
|
||||
}
|
||||
else {
|
||||
ccs = vm_ccs_create(klass, cc_tbl, mid, cme);
|
||||
}
|
||||
|
||||
for (int i=0; i<ccs->len; i++) {
|
||||
cc = ccs->entries[i].cc;
|
||||
if (vm_cc_cme(cc) == cme) {
|
||||
break;
|
||||
}
|
||||
cc = NULL;
|
||||
}
|
||||
|
||||
if (cc == NULL) {
|
||||
const struct rb_callinfo *ci = vm_ci_new(mid, 0, argc, NULL); // TODO: proper ci
|
||||
cc = vm_cc_new(klass, cme, vm_call_general, cc_type_normal);
|
||||
METHOD_ENTRY_CACHED_SET((struct rb_callable_method_entry_struct *)cme);
|
||||
vm_ccs_push(klass, ccs, ci, cc);
|
||||
}
|
||||
}
|
||||
RB_VM_LOCK_LEAVE();
|
||||
|
||||
return cc;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
gccct_hash(VALUE klass, ID mid)
|
||||
{
|
||||
return (klass >> 3) ^ (VALUE)mid;
|
||||
}
|
||||
|
||||
NOINLINE(static const struct rb_callcache *gccct_method_search_slowpath(rb_vm_t *vm, VALUE klass, ID mid, int argc, unsigned int index));
|
||||
NOINLINE(static const struct rb_callcache *gccct_method_search_slowpath(rb_vm_t *vm, VALUE klass, ID mid, int argc, unsigned int index, call_type scope));
|
||||
|
||||
static const struct rb_callcache *
|
||||
gccct_method_search_slowpath(rb_vm_t *vm, VALUE klass, ID mid, int argc, unsigned int index)
|
||||
gccct_method_search_slowpath(rb_vm_t *vm, VALUE klass, ID mid, int argc, unsigned int index, call_type scope)
|
||||
{
|
||||
const rb_callable_method_entry_t *cme = rb_callable_method_entry(klass, mid);
|
||||
const struct rb_callcache *cc;
|
||||
int flags = 0;
|
||||
|
||||
switch(scope) {
|
||||
case CALL_PUBLIC:
|
||||
break;
|
||||
case CALL_FCALL:
|
||||
flags |= VM_CALL_FCALL;
|
||||
break;
|
||||
case CALL_VCALL:
|
||||
flags |= VM_CALL_VCALL;
|
||||
break;
|
||||
case CALL_PUBLIC_KW:
|
||||
flags |= VM_CALL_KWARG;
|
||||
break;
|
||||
case CALL_FCALL_KW:
|
||||
flags |= (VM_CALL_KWARG | VM_CALL_FCALL);
|
||||
break;
|
||||
}
|
||||
|
||||
struct rb_call_data cd = {
|
||||
.ci = &VM_CI_ON_STACK(mid, flags, argc, NULL),
|
||||
.cc = NULL
|
||||
};
|
||||
|
||||
if (cme != NULL) {
|
||||
cc = cc_new(klass, mid, argc, cme);
|
||||
vm_search_method_slowpath0(vm->self, &cd, klass);
|
||||
cc = cd.cc;
|
||||
}
|
||||
else {
|
||||
cc = NULL;
|
||||
@ -467,7 +443,7 @@ gccct_method_search_slowpath(rb_vm_t *vm, VALUE klass, ID mid, int argc, unsigne
|
||||
}
|
||||
|
||||
static inline const struct rb_callcache *
|
||||
gccct_method_search(rb_execution_context_t *ec, VALUE recv, ID mid, int argc)
|
||||
gccct_method_search(rb_execution_context_t *ec, VALUE recv, ID mid, int argc, call_type call_scope)
|
||||
{
|
||||
VALUE klass;
|
||||
|
||||
@ -502,7 +478,7 @@ gccct_method_search(rb_execution_context_t *ec, VALUE recv, ID mid, int argc)
|
||||
}
|
||||
|
||||
RB_DEBUG_COUNTER_INC(gccct_miss);
|
||||
return gccct_method_search_slowpath(vm, klass, mid, argc, index);
|
||||
return gccct_method_search_slowpath(vm, klass, mid, argc, index, call_scope);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -543,7 +519,7 @@ rb_call0(rb_execution_context_t *ec,
|
||||
break;
|
||||
}
|
||||
|
||||
const struct rb_callcache *cc = gccct_method_search(ec, recv, mid, argc);
|
||||
const struct rb_callcache *cc = gccct_method_search(ec, recv, mid, argc, scope);
|
||||
|
||||
if (scope == CALL_PUBLIC) {
|
||||
RB_DEBUG_COUNTER_INC(call0_public);
|
||||
@ -1060,7 +1036,7 @@ static inline VALUE
|
||||
rb_funcallv_scope(VALUE recv, ID mid, int argc, const VALUE *argv, call_type scope)
|
||||
{
|
||||
rb_execution_context_t *ec = GET_EC();
|
||||
const struct rb_callcache *cc = gccct_method_search(ec, recv, mid, argc);
|
||||
const struct rb_callcache *cc = gccct_method_search(ec, recv, mid, argc, scope);
|
||||
VALUE self = ec->cfp->self;
|
||||
|
||||
if (LIKELY(cc) &&
|
||||
|
@ -2421,13 +2421,13 @@ opt_equality(const rb_iseq_t *cd_owner, VALUE recv, VALUE obj, CALL_DATA cd)
|
||||
|
||||
#undef EQ_UNREDEFINED_P
|
||||
|
||||
static inline const struct rb_callcache *gccct_method_search(rb_execution_context_t *ec, VALUE recv, ID mid, int argc); // vm_eval.c
|
||||
static inline const struct rb_callcache *gccct_method_search(rb_execution_context_t *ec, VALUE recv, ID mid, int argc, call_type scope); // vm_eval.c
|
||||
NOINLINE(static VALUE opt_equality_by_mid_slowpath(VALUE recv, VALUE obj, ID mid));
|
||||
|
||||
static VALUE
|
||||
opt_equality_by_mid_slowpath(VALUE recv, VALUE obj, ID mid)
|
||||
{
|
||||
const struct rb_callcache *cc = gccct_method_search(GET_EC(), recv, mid, 1);
|
||||
const struct rb_callcache *cc = gccct_method_search(GET_EC(), recv, mid, 1, CALL_PUBLIC);
|
||||
|
||||
if (cc && check_cfunc(vm_cc_cme(cc), rb_obj_equal)) {
|
||||
return RBOOL(recv == obj);
|
||||
|
@ -58,6 +58,14 @@ RUBY_EXTERN rb_serial_t ruby_vm_global_cvar_state;
|
||||
VM_REG_CFP = ec->cfp; \
|
||||
} while (0)
|
||||
|
||||
typedef enum call_type {
|
||||
CALL_PUBLIC,
|
||||
CALL_FCALL,
|
||||
CALL_VCALL,
|
||||
CALL_PUBLIC_KW,
|
||||
CALL_FCALL_KW
|
||||
} call_type;
|
||||
|
||||
#if VM_COLLECT_USAGE_DETAILS
|
||||
enum vm_regan_regtype {
|
||||
VM_REGAN_PC = 0,
|
||||
|
Loading…
x
Reference in New Issue
Block a user