The equation shall hold for every call cache.  However prior to this
changeset cc->me could be updated without also updating cc->def.  Let's
make it sure by introducing new macro named CC_SET_ME which sets cc->me
and cc->def at once.
This commit is contained in:
卜部昌平 2019-12-16 17:38:41 +09:00
Родитель 6545d5bbb9
Коммит ba11a74745
3 изменённых файлов: 29 добавлений и 18 удалений

Просмотреть файл

@ -179,22 +179,25 @@ vm_call0_body(rb_execution_context_t *ec, struct rb_calling_info *calling, struc
super_class = RCLASS_ORIGIN(super_class);
}
else if (cc->me->def->body.refined.orig_me) {
cc->me = refined_method_callable_without_refinement(cc->me);
CC_SET_ME(cc, refined_method_callable_without_refinement(cc->me));
goto again;
}
super_class = RCLASS_SUPER(super_class);
if (super_class) {
CC_SET_ME(cc, rb_callable_method_entry(super_class, ci->mid));
if (cc->me) {
RUBY_VM_CHECK_INTS(ec);
goto again;
}
}
if (!super_class || !(cc->me = rb_callable_method_entry(super_class, ci->mid))) {
enum method_missing_reason ex = (type == VM_METHOD_TYPE_ZSUPER) ? MISSING_SUPER : 0;
ret = method_missing(calling->recv, ci->mid, calling->argc, argv, ex, calling->kw_splat);
goto success;
}
RUBY_VM_CHECK_INTS(ec);
goto again;
enum method_missing_reason ex = (type == VM_METHOD_TYPE_ZSUPER) ? MISSING_SUPER : 0;
ret = method_missing(calling->recv, ci->mid, calling->argc, argv, ex, calling->kw_splat);
goto success;
}
case VM_METHOD_TYPE_ALIAS:
cc->me = aliased_callable_method_entry(cc->me);
CC_SET_ME(cc, aliased_callable_method_entry(cc->me));
goto again;
case VM_METHOD_TYPE_MISSING:
{

Просмотреть файл

@ -2655,7 +2655,7 @@ vm_call_opt_send(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, struct
DEC_SP(1);
}
cc->me = rb_callable_method_entry_with_refinements(CLASS_OF(calling->recv), ci->mid, NULL);
CC_SET_ME(cc, rb_callable_method_entry_with_refinements(CLASS_OF(calling->recv), ci->mid, NULL));
ci->flag = VM_CALL_FCALL | VM_CALL_OPT_SEND | (calling->kw_splat ? VM_CALL_KW_SPLAT : 0);
return vm_call_method(ec, reg_cfp, calling, (CALL_DATA)&cd);
}
@ -2752,14 +2752,14 @@ vm_call_zsuper(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_ca
const struct rb_call_info *ci = &cd->ci;
struct rb_call_cache *cc = &cd->cc;
klass = RCLASS_SUPER(klass);
cc->me = klass ? rb_callable_method_entry(klass, ci->mid) : NULL;
CC_SET_ME(cc, klass ? rb_callable_method_entry(klass, ci->mid) : NULL);
if (!cc->me) {
return vm_call_method_nome(ec, cfp, calling, cd);
}
if (cc->me->def->type == VM_METHOD_TYPE_REFINED &&
cc->me->def->body.refined.orig_me) {
cc->me = refined_method_callable_without_refinement(cc->me);
CC_SET_ME(cc, refined_method_callable_without_refinement(cc->me));
}
return vm_call_method_each_type(ec, cfp, calling, cd);
}
@ -2885,24 +2885,24 @@ search_refined_method(rb_execution_context_t *ec, rb_control_frame_t *cfp, ID mi
}
if (cc->me->def->type != VM_METHOD_TYPE_REFINED ||
cc->me->def != ref_me->def) {
cc->me = ref_me;
CC_SET_ME(cc, ref_me);
}
if (ref_me->def->type != VM_METHOD_TYPE_REFINED) {
return TRUE;
}
}
else {
cc->me = NULL;
CC_SET_ME(cc, NULL);
return FALSE;
}
}
if (cc->me->def->body.refined.orig_me) {
cc->me = refined_method_callable_without_refinement(cc->me);
CC_SET_ME(cc, refined_method_callable_without_refinement(cc->me));
}
else {
VALUE klass = RCLASS_SUPER(cc->me->defined_class);
cc->me = klass ? rb_callable_method_entry(klass, mid) : NULL;
CC_SET_ME(cc, klass ? rb_callable_method_entry(klass, mid) : NULL);
}
return TRUE;
}
@ -2955,7 +2955,7 @@ vm_call_method_each_type(rb_execution_context_t *ec, rb_control_frame_t *cfp, st
return vm_call_bmethod(ec, cfp, calling, cd);
case VM_METHOD_TYPE_ALIAS:
cc->me = aliased_callable_method_entry(cc->me);
CC_SET_ME(cc, aliased_callable_method_entry(cc->me));
VM_ASSERT(cc->me != NULL);
return vm_call_method_each_type(ec, cfp, calling, cd);
@ -3156,7 +3156,7 @@ vm_search_super_method(const rb_control_frame_t *reg_cfp, struct rb_call_data *c
}
else {
/* TODO: use inline cache */
cc->me = rb_callable_method_entry(klass, ci->mid);
CC_SET_ME(cc, rb_callable_method_entry(klass, ci->mid));
CC_SET_FASTPATH(cc, vm_call_super_method, TRUE);
}
}

Просмотреть файл

@ -124,6 +124,14 @@ enum vm_regan_acttype {
if (LIKELY(enabled)) ((cc)->call = (func)); \
} while (0)
#define CC_SET_ME(cc, newme) do { \
CALL_CACHE ccx = (cc); \
const rb_callable_method_entry_t *mex = (newme); \
const rb_method_definition_t *defx = mex ? mex->def : NULL; \
ccx->me = mex; \
ccx->def = defx; \
} while (0)
#define GET_BLOCK_HANDLER() (GET_LEP()[VM_ENV_DATA_INDEX_SPECVAL])
/**********************************************************/