From ba11a74745e10fac88a74c2da2e0032ccf254265 Mon Sep 17 00:00:00 2001 From: 卜部昌平 Date: Mon, 16 Dec 2019 17:38:41 +0900 Subject: 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. --- vm_eval.c | 21 ++++++++++++--------- vm_insnhelper.c | 18 +++++++++--------- vm_insnhelper.h | 8 ++++++++ 3 files changed, 29 insertions(+), 18 deletions(-) diff --git a/vm_eval.c b/vm_eval.c index b0179423d8..cec1ea41f6 100644 --- a/vm_eval.c +++ b/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: { diff --git a/vm_insnhelper.c b/vm_insnhelper.c index 8487886886..e7e20ee3ca 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -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); } } diff --git a/vm_insnhelper.h b/vm_insnhelper.h index 99555fd4ed..c96522fc98 100644 --- a/vm_insnhelper.h +++ b/vm_insnhelper.h @@ -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]) /**********************************************************/ -- cgit v1.2.3