summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog7
-rw-r--r--eval.c68
-rw-r--r--insns.def2
-rw-r--r--test/ruby/test_method.rb14
-rw-r--r--vm.c15
-rw-r--r--vm_eval.c2
-rw-r--r--vm_insnhelper.c16
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 <nobu@ruby-lang.org>
+
+ * 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@segment7.net>
* 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("<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_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;
}