[前][次][番号順一覧][スレッド一覧]

ruby-changes:59273

From: =E5=8D=9C=E9=83=A8=E6=98=8C=E5=B9=B3 <ko1@a...>
Date: Mon, 16 Dec 2019 17:52:38 +0900 (JST)
Subject: [ruby-changes:59273] ba11a74745 (master): ensure cc->def == cc->me->def

https://git.ruby-lang.org/ruby.git/commit/?id=ba11a74745

From ba11a74745e10fac88a74c2da2e0032ccf254265 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=8D=9C=E9=83=A8=E6=98=8C=E5=B9=B3?=
 <shyouhei@r...>
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.

diff --git a/vm_eval.c b/vm_eval.c
index b017942..cec1ea4 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 https://github.com/ruby/ruby/blob/trunk/vm_eval.c#L179
 		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 8487886..e7e20ee 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 https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L2655
 	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 https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L2752
     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 https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L2885
             }
             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 https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L2955
         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 https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L3156
     }
     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 99555fd..c96522f 100644
--- a/vm_insnhelper.h
+++ b/vm_insnhelper.h
@@ -124,6 +124,14 @@ enum vm_regan_acttype { https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.h#L124
     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 v0.10.2


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]