* 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
This commit is contained in:
nobu 2012-07-04 02:11:37 +00:00
Родитель 07132e0675
Коммит a7e1820a9f
7 изменённых файлов: 101 добавлений и 27 удалений

Просмотреть файл

@ -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

72
eval.c
Просмотреть файл

@ -874,27 +874,66 @@ frame_func_id(rb_control_frame_t *cfp)
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);
}
ID
rb_frame_callee(void)
static rb_control_frame_t *
previous_frame(rb_thread_t *th)
{
return frame_func_id(GET_THREAD()->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;
}
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);

Просмотреть файл

@ -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();

Просмотреть файл

@ -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

15
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;

Просмотреть файл

@ -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);

Просмотреть файл

@ -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;
}