From a7e1820a9f9c0b6c84c281c171c105a34aa16738 Mon Sep 17 00:00:00 2001 From: nobu Date: Wed, 4 Jul 2012 02:11:37 +0000 Subject: __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. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@36301 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 7 +++++ eval.c | 68 ++++++++++++++++++++++++++++++++++++++++++------ insns.def | 2 +- test/ruby/test_method.rb | 14 ++++++++++ vm.c | 15 ++++++----- vm_eval.c | 2 +- vm_insnhelper.c | 16 ++++++------ 7 files changed, 99 insertions(+), 25 deletions(-) diff --git a/ChangeLog b/ChangeLog index f629e0f88b..51a6690d13 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +Wed Jul 4 11:11:28 2012 Nobuyoshi Nakada + + * 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 * array.c (rb_ary_aref): Updated documentation to indicate the diff --git a/eval.c b/eval.c index 37bb35a148..2c82d4f2b8 100644 --- a/eval.c +++ b/eval.c @@ -874,27 +874,66 @@ frame_func_id(rb_control_frame_t *cfp) return 0; } -ID -rb_frame_this_func(void) +static ID +frame_called_id(rb_control_frame_t *cfp) { - return frame_func_id(GET_THREAD()->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(""); + } + 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_callee(void) +rb_frame_this_func(void) { return frame_func_id(GET_THREAD()->cfp); } -static ID -rb_frame_caller(void) +static rb_control_frame_t * +previous_frame(rb_thread_t *th) { - 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; } + return prev_cfp; +} + +ID +rb_frame_callee(void) +{ + 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_control_frame_t *prev_cfp = previous_frame(GET_THREAD()); + if (!prev_cfp) return 0; return frame_func_id(prev_cfp); } @@ -1248,6 +1287,19 @@ rb_f_method_name(void) } } +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 @@ Init_eval(void) 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); diff --git a/insns.def b/insns.def index e256a83758..ab40d30634 100644 --- a/insns.def +++ b/insns.def @@ -974,7 +974,7 @@ defineclass 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(); diff --git a/test/ruby/test_method.rb b/test/ruby/test_method.rb index e299b722ee..6a5a75cf20 100644 --- a/test/ruby/test_method.rb +++ b/test/ruby/test_method.rb @@ -90,6 +90,20 @@ class TestMethod < Test::Unit::TestCase 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 diff --git a/vm.c b/vm.c index 06d2db3ddd..0a85e0fced 100644 --- a/vm.c +++ b/vm.c @@ -137,7 +137,7 @@ vm_set_top_stack(rb_thread_t * th, VALUE iseqval) 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 @@ vm_set_eval_stack(rb_thread_t * th, VALUE iseqval, const NODE *cref, rb_block_t 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 @@ invoke_block_from_c(rb_thread_t *th, const rb_block_t *block, 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 @@ vm_exec(rb_thread_t *th) 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 @@ rb_vm_call_cfunc(VALUE recv, VALUE (*func)(VALUE), VALUE arg, 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_init(rb_thread_t *th, VALUE self) 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; diff --git a/vm_eval.c b/vm_eval.c index 7ec768f7f6..bb9ac8d8f6 100644 --- a/vm_eval.c +++ b/vm_eval.c @@ -71,7 +71,7 @@ vm_call0(rb_thread_t* th, VALUE recv, VALUE id, int argc, const VALUE *argv, 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); diff --git a/vm_insnhelper.c b/vm_insnhelper.c index 6544ed89fc..22e903ad80 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -30,7 +30,8 @@ vm_push_frame(rb_thread_t *th, 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 @@ vm_push_frame(rb_thread_t *th, cfp->self = self; cfp->block_iseq = 0; cfp->proc = 0; - cfp->me = 0; + cfp->me = me; if (VMDEBUG == 2) { SDR(); @@ -423,9 +424,8 @@ vm_call_cfunc(rb_thread_t *th, rb_control_frame_t *reg_cfp, 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_setup_method(rb_thread_t *th, rb_control_frame_t *cfp, 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_setup_method(rb_thread_t *th, rb_control_frame_t *cfp, 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 @@ vm_yield_with_cfunc(rb_thread_t *th, const rb_block_t *block, } 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_invoke_block(rb_thread_t *th, rb_control_frame_t *reg_cfp, rb_num_t num, rb_n 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; } -- cgit v1.2.3