зеркало из https://github.com/github/ruby.git
ensure cc->def == cc->me->def
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:
Родитель
6545d5bbb9
Коммит
ba11a74745
21
vm_eval.c
21
vm_eval.c
|
@ -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])
|
||||
|
||||
/**********************************************************/
|
||||
|
|
Загрузка…
Ссылка в новой задаче