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

ruby-changes:24250

From: nobu <ko1@a...>
Date: Wed, 4 Jul 2012 11:11:50 +0900 (JST)
Subject: [ruby-changes:24250] nobu:r36301 (trunk): __callee__ fix

nobu	2012-07-04 11:11:37 +0900 (Wed, 04 Jul 2012)

  New Revision: 36301

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=36301

  Log:
    __callee__ fix
    
    * eval.c (rb_frame_callee, rb_f_callee_name): fix to return the called
      id.
    * vm_insnhelper.c (vm_push_frame): set proper method entry.

  Modified files:
    trunk/ChangeLog
    trunk/eval.c
    trunk/insns.def
    trunk/test/ruby/test_method.rb
    trunk/vm.c
    trunk/vm_eval.c
    trunk/vm_insnhelper.c

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 36300)
+++ ChangeLog	(revision 36301)
@@ -1,3 +1,10 @@
+Wed Jul  4 11:11:28 2012  Nobuyoshi Nakada  <nobu@r...>
+
+	* eval.c (rb_frame_callee, rb_f_callee_name): fix to return the called
+	  id.
+
+	* vm_insnhelper.c (vm_push_frame): set proper method entry.
+
 Wed Jul  4 08:29:31 2012  Eric Hodel  <drbrain@s...>
 
 	* array.c (rb_ary_aref):  Updated documentation to indicate the
Index: insns.def
===================================================================
--- insns.def	(revision 36300)
+++ insns.def	(revision 36301)
@@ -974,7 +974,7 @@
     vm_push_frame(th, class_iseq, VM_FRAME_MAGIC_CLASS,
 		  klass, VM_ENVVAL_BLOCK_PTR(GET_BLOCK_PTR()),
 		  class_iseq->iseq_encoded, GET_SP(),
-		  class_iseq->local_size);
+		  class_iseq->local_size, 0);
     RESTORE_REGS();
 
     INC_VM_STATE_VERSION();
Index: vm_eval.c
===================================================================
--- vm_eval.c	(revision 36300)
+++ vm_eval.c	(revision 36301)
@@ -71,7 +71,7 @@
 	    rb_control_frame_t *reg_cfp = th->cfp;
 	    rb_control_frame_t *cfp =
 		vm_push_frame(th, 0, VM_FRAME_MAGIC_CFUNC,
-			      recv, VM_ENVVAL_BLOCK_PTR(blockptr), 0, reg_cfp->sp, 1);
+			      recv, VM_ENVVAL_BLOCK_PTR(blockptr), 0, reg_cfp->sp, 1, me);
 
 	    cfp->me = me;
 	    val = call_cfunc(def->body.cfunc.func, recv, def->body.cfunc.argc, argc, argv);
Index: eval.c
===================================================================
--- eval.c	(revision 36300)
+++ eval.c	(revision 36301)
@@ -874,27 +874,66 @@
     return 0;
 }
 
+static ID
+frame_called_id(rb_control_frame_t *cfp)
+{
+    const rb_method_entry_t *me_local;
+    rb_iseq_t *iseq = cfp->iseq;
+    if (cfp->me) {
+	return cfp->me->called_id;
+    }
+    while (iseq) {
+	if (RUBY_VM_IFUNC_P(iseq)) {
+	    NODE *ifunc = (NODE *)iseq;
+	    if (ifunc->nd_aid) return ifunc->nd_aid;
+	    return rb_intern("<ifunc>");
+	}
+	me_local = method_entry_of_iseq(cfp, iseq);
+	if (me_local) {
+	    cfp->me = me_local;
+	    return me_local->called_id;
+	}
+	if (iseq->defined_method_id) {
+	    return iseq->defined_method_id;
+	}
+	if (iseq->local_iseq == iseq) {
+	    break;
+	}
+	iseq = iseq->parent_iseq;
+    }
+    return 0;
+}
+
 ID
 rb_frame_this_func(void)
 {
     return frame_func_id(GET_THREAD()->cfp);
 }
 
+static rb_control_frame_t *
+previous_frame(rb_thread_t *th)
+{
+    rb_control_frame_t *prev_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp);
+    /* check if prev_cfp can be accessible */
+    if ((void *)(th->stack + th->stack_size) == (void *)(prev_cfp)) {
+        return 0;
+    }
+    return prev_cfp;
+}
+
 ID
 rb_frame_callee(void)
 {
-    return frame_func_id(GET_THREAD()->cfp);
+    rb_control_frame_t *prev_cfp = previous_frame(GET_THREAD());
+    if (!prev_cfp) return 0;
+    return frame_called_id(prev_cfp);
 }
 
 static ID
 rb_frame_caller(void)
 {
-    rb_thread_t *th = GET_THREAD();
-    rb_control_frame_t *prev_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp);
-    /* check if prev_cfp can be accessible */
-    if ((void *)(th->stack + th->stack_size) == (void *)(prev_cfp)) {
-        return 0;
-    }
+    rb_control_frame_t *prev_cfp = previous_frame(GET_THREAD());
+    if (!prev_cfp) return 0;
     return frame_func_id(prev_cfp);
 }
 
@@ -1248,6 +1287,19 @@
     }
 }
 
+static VALUE
+rb_f_callee_name(void)
+{
+    ID fname = rb_frame_callee(); /* need *callee* ID */
+
+    if (fname) {
+	return ID2SYM(fname);
+    }
+    else {
+	return Qnil;
+    }
+}
+
 void
 Init_eval(void)
 {
@@ -1260,7 +1312,7 @@
     rb_define_global_function("global_variables", rb_f_global_variables, 0);	/* in variable.c */
 
     rb_define_global_function("__method__", rb_f_method_name, 0);
-    rb_define_global_function("__callee__", rb_f_method_name, 0);
+    rb_define_global_function("__callee__", rb_f_callee_name, 0);
 
     rb_define_private_method(rb_cModule, "append_features", rb_mod_append_features, 1);
     rb_define_private_method(rb_cModule, "extend_object", rb_mod_extend_object, 1);
Index: vm.c
===================================================================
--- vm.c	(revision 36300)
+++ vm.c	(revision 36301)
@@ -137,7 +137,7 @@
     CHECK_STACK_OVERFLOW(th->cfp, iseq->local_size + iseq->stack_max);
     vm_push_frame(th, iseq, VM_FRAME_MAGIC_TOP | VM_FRAME_FLAG_FINISH,
 		  th->top_self, VM_ENVVAL_BLOCK_PTR(0), iseq->iseq_encoded,
-		  th->cfp->sp, iseq->local_size);
+		  th->cfp->sp, iseq->local_size, 0);
 }
 
 static void
@@ -149,7 +149,7 @@
     CHECK_STACK_OVERFLOW(th->cfp, iseq->local_size + iseq->stack_max);
     vm_push_frame(th, iseq, VM_FRAME_MAGIC_EVAL | VM_FRAME_FLAG_FINISH, base_block->self,
 		  VM_ENVVAL_PREV_EP_PTR(base_block->ep), iseq->iseq_encoded,
-		  th->cfp->sp, iseq->local_size);
+		  th->cfp->sp, iseq->local_size, 0);
 
     if (cref) {
 	th->cfp->ep[-1] = (VALUE)cref;
@@ -598,8 +598,8 @@
 
 	ncfp = vm_push_frame(th, iseq, type | VM_FRAME_FLAG_FINISH,
 			     self, VM_ENVVAL_PREV_EP_PTR(block->ep),
-			     iseq->iseq_encoded + opt_pc, cfp->sp + arg_size, iseq->local_size - arg_size);
-	ncfp->me = th->passed_me;
+			     iseq->iseq_encoded + opt_pc, cfp->sp + arg_size, iseq->local_size - arg_size,
+			     th->passed_me);
 	th->passed_me = 0;
 	th->passed_block = blockptr;
 
@@ -1304,7 +1304,8 @@
 	    cfp->sp[0] = err;
 	    vm_push_frame(th, catch_iseq, VM_FRAME_MAGIC_BLOCK,
 			  cfp->self, VM_ENVVAL_PREV_EP_PTR(cfp->ep), catch_iseq->iseq_encoded,
-			  cfp->sp + 1 /* push value */, catch_iseq->local_size - 1);
+			  cfp->sp + 1 /* push value */, catch_iseq->local_size - 1,
+			  cfp->me);
 
 	    state = 0;
 	    th->state = 0;
@@ -1438,7 +1439,7 @@
     VALUE val;
 
     vm_push_frame(th, DATA_PTR(iseqval), VM_FRAME_MAGIC_TOP | VM_FRAME_FLAG_FINISH,
-		  recv, VM_ENVVAL_BLOCK_PTR(blockptr), 0, reg_cfp->sp, 1);
+		  recv, VM_ENVVAL_BLOCK_PTR(blockptr), 0, reg_cfp->sp, 1, 0);
 
     val = (*func)(arg);
 
@@ -1782,7 +1783,7 @@
     th->cfp = (void *)(th->stack + th->stack_size);
 
     vm_push_frame(th, 0 /* dummy iseq */, VM_FRAME_MAGIC_TOP | VM_FRAME_FLAG_FINISH,
-		  Qnil /* dummy self */, VM_ENVVAL_BLOCK_PTR(0), 0 /* dummy pc */, th->stack, 1);
+		  Qnil /* dummy self */, VM_ENVVAL_BLOCK_PTR(0), 0 /* dummy pc */, th->stack, 1, 0);
 
     th->status = THREAD_RUNNABLE;
     th->errinfo = Qnil;
Index: vm_insnhelper.c
===================================================================
--- vm_insnhelper.c	(revision 36300)
+++ vm_insnhelper.c	(revision 36301)
@@ -30,7 +30,8 @@
 	      VALUE specval,
 	      const VALUE *pc,
 	      VALUE *sp,
-	      int local_size)
+	      int local_size,
+	      const rb_method_entry_t *me)
 {
     rb_control_frame_t *const cfp = th->cfp - 1;
     int i;
@@ -62,7 +63,7 @@
     cfp->self = self;
     cfp->block_iseq = 0;
     cfp->proc = 0;
-    cfp->me = 0;
+    cfp->me = me;
 
     if (VMDEBUG == 2) {
 	SDR();
@@ -423,9 +424,8 @@
     EXEC_EVENT_HOOK(th, RUBY_EVENT_C_CALL, recv, me->called_id, me->klass);
 
     cfp = vm_push_frame(th, 0, VM_FRAME_MAGIC_CFUNC, recv,
-			VM_ENVVAL_BLOCK_PTR(blockptr), 0, th->cfp->sp, 1);
+			VM_ENVVAL_BLOCK_PTR(blockptr), 0, th->cfp->sp, 1, me);
 
-    cfp->me = me;
     reg_cfp->sp -= num + 1;
 
     val = call_cfunc(def->body.cfunc.func, recv, (int)def->body.cfunc.argc, num, reg_cfp->sp + 1);
@@ -508,7 +508,7 @@
 
 	vm_push_frame(th, iseq, VM_FRAME_MAGIC_METHOD, recv,
 		      VM_ENVVAL_BLOCK_PTR(blockptr),
-		      iseq->iseq_encoded + opt_pc, sp, 0);
+		      iseq->iseq_encoded + opt_pc, sp, 0, me);
 
 	cfp->sp = rsp - 1 /* recv */;
     }
@@ -531,7 +531,7 @@
 
 	vm_push_frame(th, iseq, VM_FRAME_MAGIC_METHOD, recv,
 		      VM_ENVVAL_BLOCK_PTR(blockptr),
-		      iseq->iseq_encoded + opt_pc, sp, 0);
+		      iseq->iseq_encoded + opt_pc, sp, 0, me);
     }
 }
 
@@ -760,7 +760,7 @@
     }
 
     cfp = vm_push_frame(th, (rb_iseq_t *)ifunc, VM_FRAME_MAGIC_IFUNC, self,
-			VM_ENVVAL_PREV_EP_PTR(block->ep), 0, th->cfp->sp, 1);
+			VM_ENVVAL_PREV_EP_PTR(block->ep), 0, th->cfp->sp, 1, 0);
 
     if (blockargptr) {
 	VM_CF_LEP(cfp)[0] = VM_ENVVAL_BLOCK_PTR(blockargptr);
@@ -980,7 +980,7 @@
 		      VM_ENVVAL_PREV_EP_PTR(block->ep),
 		      iseq->iseq_encoded + opt_pc,
 		      rsp + arg_size,
-		      iseq->local_size - arg_size);
+		      iseq->local_size - arg_size, 0);
 
 	return Qundef;
     }
Index: test/ruby/test_method.rb
===================================================================
--- test/ruby/test_method.rb	(revision 36300)
+++ test/ruby/test_method.rb	(revision 36301)
@@ -90,6 +90,20 @@
     assert_equal(:m, Class.new {define_method(:m) {__method__}}.new.m)
     assert_equal(:m, Class.new {define_method(:m) {tap{return __method__}}}.new.m)
     assert_nil(eval("class TestCallee; __method__; end"))
+
+    assert_equal(:test_callee, __callee__)
+    [
+      ["method",              Class.new {def m; __callee__; end},],
+      ["block",               Class.new {def m; tap{return __callee__}; end},],
+      ["define_method",       Class.new {define_method(:m) {__callee__}}],
+      ["define_method block", Class.new {define_method(:m) {tap{return __callee__}}}],
+    ].each do |mesg, c|
+      c.class_eval {alias m2 m}
+      o = c.new
+      assert_equal(:m, o.m, mesg)
+      assert_equal(:m2, o.m2, mesg)
+    end
+    assert_nil(eval("class TestCallee; __callee__; end"))
   end
 
   def test_method_in_define_method_block

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

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