* common.mk: ditto.
* vm.c (vm_call_bmethod), isnsn.def: added.  fix to use this
  function instead of using goto.
* vm.c (vm_call_bmethod): renamed from th_invoke_bmethod().
* vm.c (vm_method_missing): renamed from eval_methdo_missing().
* vm_evalbody.ci: remove tmp_* variables.
* insnhelper.h: add some macros.
* insns.def: forbid zsuper from method defined by define_method().
* test/ruby/test_super.rb: ditto.



git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12601 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
ko1 2007-06-24 13:05:51 +00:00
Родитель 904b9e5d54
Коммит 62deb7dbbd
8 изменённых файлов: 300 добавлений и 384 удалений

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

@ -1,3 +1,24 @@
Sun Jun 24 22:00:17 2007 Koichi Sasada <ko1@atdot.net>
* insn_send.ci: removed.
* common.mk: ditto.
* vm.c (vm_call_bmethod), isnsn.def: added. fix to use this
function instead of using goto.
* vm.c (vm_call_bmethod): renamed from th_invoke_bmethod().
* vm.c (vm_method_missing): renamed from eval_methdo_missing().
* vm_evalbody.ci: remove tmp_* variables.
* insnhelper.h: add some macros.
* insns.def: forbid zsuper from method defined by define_method().
* test/ruby/test_super.rb: ditto.
Sun Jun 24 20:01:08 2007 Koichi Sasada <ko1@atdot.net>
* vm_macro.def: removed.

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

@ -552,21 +552,20 @@ compile.$(OBJEXT): {$(VPATH)}compile.c {$(VPATH)}yarvcore.h \
{$(VPATH)}compile.h {$(VPATH)}debug.h {$(VPATH)}ruby.h {$(VPATH)}config.h \
{$(VPATH)}defines.h {$(VPATH)}missing.h {$(VPATH)}intern.h \
{$(VPATH)}st.h {$(VPATH)}node.h {$(VPATH)}signal.h \
{$(VPATH)}insns.inc {$(VPATH)}insns_info.inc {$(VPATH)}optinsn.inc \
{$(VPATH)}insns_info.inc {$(VPATH)}optinsn.inc \
{$(VPATH)}opt_sc.inc {$(VPATH)}optunifs.inc {$(VPATH)}vm_opts.h \
{$(VPATH)}thread_$(THREAD_MODEL).h
iseq.$(OBJEXT): {$(VPATH)}iseq.c {$(VPATH)}yarvcore.h {$(VPATH)}debug.h \
{$(VPATH)}ruby.h {$(VPATH)}defines.h {$(VPATH)}missing.h \
{$(VPATH)}intern.h {$(VPATH)}st.h {$(VPATH)}signal.h \
{$(VPATH)}gc.h {$(VPATH)}vm_opts.h {$(VPATH)}config.h {$(VPATH)}node.h \
{$(VPATH)}thread_$(THREAD_MODEL).h\
{$(VPATH)}insns.inc {$(VPATH)}insns_info.inc
{$(VPATH)}thread_$(THREAD_MODEL).h {$(VPATH)}insns_info.inc
vm.$(OBJEXT): {$(VPATH)}vm.c {$(VPATH)}vm.h {$(VPATH)}insnhelper.h \
{$(VPATH)}yarvcore.h {$(VPATH)}debug.h {$(VPATH)}ruby.h {$(VPATH)}config.h\
{$(VPATH)}node.h {$(VPATH)}util.h {$(VPATH)}signal.h {$(VPATH)}dln.h \
{$(VPATH)}vm_evalbody.ci {$(VPATH)}call_cfunc.ci \
{$(VPATH)}insns.inc {$(VPATH)}vm.inc {$(VPATH)}vmtc.inc \
{$(VPATH)}insn_send.ci {$(VPATH)}vm_opts.h {$(VPATH)}eval_intern.h \
{$(VPATH)}vm_opts.h {$(VPATH)}eval_intern.h \
{$(VPATH)}defines.h {$(VPATH)}missing.h {$(VPATH)}intern.h \
{$(VPATH)}gc.h {$(VPATH)}thread_$(THREAD_MODEL).h
vm_dump.$(OBJEXT): {$(VPATH)}vm_dump.c {$(VPATH)}yarvcore.h {$(VPATH)}vm.h \

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

@ -1,226 +0,0 @@
/* -*-c-*- */
/* send instruction body */
{
NODE *mn;
VALUE recv;
VALUE klass;
rb_block_t *blockptr = 0;
rb_num_t num;
rb_num_t flag = op_flag;
ID id = op_id;
num = caller_setup_args(th, GET_CFP(), flag, op_argc, blockiseq, &blockptr);
if (flag & VM_CALL_FCALL_BIT) {
/* method(...) */
recv = GET_SELF();
}
else {
/* recv.method(...) */
recv = TOPN(num);
}
klass = CLASS_OF(recv);
mn = eval_method_search(id, klass, ic);
if ((flag & VM_CALL_SEND_BIT) && mn && nd_type(mn->nd_body) == NODE_CFUNC) {
NODE *node = mn->nd_body;
extern VALUE rb_f_funcall(int argc, VALUE *argv, VALUE recv);
extern VALUE rb_f_send(int argc, VALUE *argv, VALUE recv);
if (node->nd_cfnc == rb_f_funcall || node->nd_cfnc == rb_f_send) {
int i;
VALUE sym = TOPN(num - 1);
id = SYMBOL_P(sym) ? SYM2ID(sym) : rb_to_id(sym);
/* shift arguments */
for (i=num-1; i>0; i--) {
TOPN(i) = TOPN(i-1);
}
mn = rb_method_node(klass, id);
num -= 1;
DEC_SP(1);
}
if (node->nd_cfnc == rb_f_funcall) {
flag |= VM_CALL_FCALL_BIT;
}
}
#if CURRENT_INSN_send || CURRENT_INSN_send_SC_xx_ax
#if !YARV_AOT_COMPILED
if (0) {
if (0) {
LABEL_IS_SC(start_init_in_send_for_opt_1):
num = 1;
recv = TOPN(1);
}
else if (0) {
LABEL_IS_SC(start_init_in_send_for_opt_2):
num = 2;
recv = TOPN(2);
}
flag = 0;
id = tmp_id;
klass = CLASS_OF(recv);
blockptr = 0;
mn = rb_method_node(klass, id);
}
if (0) {
LABEL_IS_SC(start_init_in_super):
{
rb_iseq_t *iseq = GET_ISEQ();
rb_iseq_t *ip = iseq;
num = tmp_num;
flag = VM_CALL_FCALL_BIT;
recv = GET_SELF();
while (ip && !ip->klass) {
ip = ip->parent_iseq;
}
if (ip == 0) {
rb_raise(rb_eNoMethodError, "super called outside of method");
}
id = ip->defined_method_id;
if (ip != ip->local_iseq) {
/* defined by Module#define_method() */
rb_control_frame_t *lcfp = GET_CFP();
while (lcfp->iseq != ip) {
VALUE *tdfp = GET_PREV_DFP(lcfp->dfp);
while (1) {
lcfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(lcfp);
if (lcfp->dfp == tdfp) {
break;
}
}
}
id = lcfp->method_id;
klass = search_super_klass(lcfp->method_klass, recv);
if (TOPN(num) == Qfalse) {
/* for ZSUPER */
int i;
POPN(num);
num = ip->argc;
for (i = 0; i < ip->argc; i++) {
PUSH(lcfp->dfp[i - ip->local_size]);
}
}
}
else {
klass = search_super_klass(ip->klass, recv);
}
flag = VM_CALL_SUPER_BIT | VM_CALL_FCALL_BIT;
blockptr = tmp_blockptr;
mn = rb_method_node(klass, id);
}
}
LABEL_IS_SC(start_method_dispatch):
#endif
#endif
/* method missing */
if (mn == 0) {
/* temporarily */
if (id == idMethodMissing) {
rb_bug("method missing");
}
else {
int stat = 0;
if (flag & VM_CALL_VCALL_BIT) {
stat |= NOEX_VCALL;
}
if (flag & VM_CALL_SUPER_BIT) {
stat |= NOEX_SUPER;
}
val = eval_method_missing(th, id, recv, num, blockptr, stat);
}
}
else if (!(flag & VM_CALL_FCALL_BIT) &&
(mn->nd_noex & NOEX_MASK) & NOEX_PRIVATE) {
int stat = NOEX_PRIVATE;
if (flag & VM_CALL_VCALL_BIT) {
stat |= NOEX_VCALL;
}
val = eval_method_missing(th, id, recv, num, blockptr, stat);
}
else if ((mn->nd_noex & NOEX_MASK) & NOEX_PROTECTED) {
VALUE defined_class = mn->nd_clss;
if (TYPE(defined_class) == T_ICLASS) {
defined_class = RBASIC(defined_class)->klass;
}
if (!rb_obj_is_kind_of(GET_SELF(), rb_class_real(defined_class))) {
val =
eval_method_missing(th, id, recv, num, blockptr,
NOEX_PROTECTED);
}
else {
goto INSN_LABEL(normal_method_dispatch);
}
}
else {
NODE *node;
INSN_LABEL(normal_method_dispatch):
node = mn->nd_body;
switch (nd_type(node)) {
case RUBY_VM_METHOD_NODE:{
vm_setup_method(th, GET_CFP(), num, blockptr, flag, (VALUE)node->nd_body, recv, klass);
RESTORE_REGS();
NEXT_INSN();
}
case NODE_CFUNC:{
val = vm_call_cfunc(th, GET_CFP(), num, id, recv, klass, node, blockptr);
break;
}
case NODE_ATTRSET:{
val = rb_ivar_set(recv, node->nd_vid, TOPN(0));
POPN(2);
break;
}
case NODE_IVAR:{
val = rb_ivar_get(recv, node->nd_vid);
POP();
break;
}
case NODE_BMETHOD:{
VALUE *argv = GET_SP() - num;
val = th_invoke_bmethod(th, id, node->nd_cval,
recv, klass, num, argv);
INC_SP(-num-1);
break;
}
case NODE_ZSUPER:{
klass = RCLASS(mn->nd_clss)->super;
mn = rb_method_node(klass, id);
if (mn != 0) {
goto INSN_LABEL(normal_method_dispatch);
}
else {
goto LABEL_IS_SC(start_method_dispatch);
}
}
default:{
printf("node: %s\n", ruby_node_name(nd_type(node)));
rb_bug("eval_invoke_method: unreachable");
/* unreachable */
break;
}
}
}
RUBY_VM_CHECK_INTS();
}

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

@ -146,4 +146,20 @@ while (0)
#define BASIC_OP_UNREDEFINED_P(op) ((yarv_redefined_flag & (op)) == 0)
#define HEAP_CLASS_OF(obj) RBASIC(obj)->klass
#define CALL_METHOD(num, blockptr, flag, id, mn, recv, klass) do { \
VALUE v = vm_call_method(th, GET_CFP(), num, blockptr, flag, id, mn, recv, klass); \
if (v == Qundef) { \
RESTORE_REGS(); \
NEXT_INSN(); \
} \
else { \
val = v; \
} \
} while (0)
#define CALL_SIMPLE_METHOD(num, id, recv) do { \
VALUE klass = CLASS_OF(recv); \
CALL_METHOD(num, 0, 0, id, rb_method_node(klass, id), recv, CLASS_OF(recv)); \
} while (0)
#endif /* _INSNHELPER_H_INCLUDED_ */

236
insns.def
Просмотреть файл

@ -1152,7 +1152,55 @@ send
(...)
(VALUE val) // inc += - (op_argc + ((op_flag & VM_CALL_ARGS_BLOCKARG_BIT) ? 1 : 0));
{
#include "insn_send.ci"
NODE *mn;
VALUE recv, klass, v;
rb_block_t *blockptr = 0;
rb_num_t num = caller_setup_args(th, GET_CFP(), op_flag, op_argc, blockiseq, &blockptr);
rb_num_t flag = op_flag;
ID id = op_id;
/* get receiver */
if (flag & VM_CALL_FCALL_BIT) {
/* method(...) */
recv = GET_SELF();
}
else {
/* recv.method(...) */
recv = TOPN(num);
}
klass = CLASS_OF(recv);
mn = eval_method_search(id, klass, ic);
/* send/funcall optimization */
if ((flag & VM_CALL_SEND_BIT) && mn && nd_type(mn->nd_body) == NODE_CFUNC) {
NODE *node = mn->nd_body;
extern VALUE rb_f_funcall(int argc, VALUE *argv, VALUE recv);
extern VALUE rb_f_send(int argc, VALUE *argv, VALUE recv);
if (node->nd_cfnc == rb_f_funcall || node->nd_cfnc == rb_f_send) {
int i;
VALUE sym = TOPN(num - 1);
id = SYMBOL_P(sym) ? SYM2ID(sym) : rb_to_id(sym);
/* shift arguments */
for (i=num-1; i>0; i--) {
TOPN(i) = TOPN(i-1);
}
mn = rb_method_node(klass, id);
num -= 1;
DEC_SP(1);
}
if (node->nd_cfnc == rb_f_funcall) {
flag |= VM_CALL_FCALL_BIT;
}
}
CALL_METHOD(num, blockptr, flag, id, mn, recv, klass);
}
/**
@ -1162,21 +1210,65 @@ send
*/
DEFINE_INSN
invokesuper
(rb_num_t op_argc, ISEQ blockiseq, rb_num_t flag)
(rb_num_t op_argc, ISEQ blockiseq, rb_num_t op_flag)
(...)
(VALUE val) // inc += - op_argc;
{
#if YARV_AOT_COMPILED
/* TODO: */
rb_bug("...");
#else
tmp_blockptr = 0;
tmp_num = caller_setup_args(th, GET_CFP(), flag, op_argc, blockiseq, &tmp_blockptr);
if (!tmp_blockptr && !(flag & VM_CALL_ARGS_BLOCKARG_BIT)) {
tmp_blockptr = GET_BLOCK_PTR();
rb_block_t *blockptr = 0;
VALUE flag = op_flag;
int num = caller_setup_args(th, GET_CFP(), flag, op_argc, blockiseq, &blockptr);
rb_iseq_t *iseq = GET_ISEQ();
rb_iseq_t *ip = iseq;
VALUE recv, klass;
ID id;
NODE *mn;
if (!blockptr && !(flag & VM_CALL_ARGS_BLOCKARG_BIT)) {
blockptr = GET_BLOCK_PTR();
}
goto LABEL_IS_SC(start_init_in_super);
#endif
recv = GET_SELF();
while (ip && !ip->klass) {
ip = ip->parent_iseq;
}
if (ip == 0) {
rb_raise(rb_eNoMethodError, "super called outside of method");
}
id = ip->defined_method_id;
if (ip != ip->local_iseq) {
/* defined by Module#define_method() */
rb_control_frame_t *lcfp = GET_CFP();
while (lcfp->iseq != ip) {
VALUE *tdfp = GET_PREV_DFP(lcfp->dfp);
while (1) {
lcfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(lcfp);
if (lcfp->dfp == tdfp) {
break;
}
}
}
id = lcfp->method_id;
klass = search_super_klass(lcfp->method_klass, recv);
if (TOPN(num) == Qfalse) {
/* zsuper */
rb_raise(rb_eRuntimeError, "zsuper from method defined by define_method() is not supported. Specify all arguments.");
}
}
else {
klass = search_super_klass(ip->klass, recv);
}
flag = VM_CALL_SUPER_BIT | VM_CALL_FCALL_BIT;
mn = rb_method_node(klass, id);
CALL_METHOD(num, blockptr, flag, id, mn, recv, klass);
}
/**
@ -1581,15 +1673,9 @@ opt_plus
}
else {
INSN_LABEL(normal_dispatch):
#ifdef YARV_AOT_COMPILED
val = rb_funcall(recv, idPLUS, 1, obj);
#else
PUSH(recv);
PUSH(obj);
tmp_id = idPLUS;
goto LABEL_IS_SC(start_init_in_send_for_opt_1);
#endif
CALL_SIMPLE_METHOD(1, idPLUS, recv);
}
}
@ -1619,14 +1705,9 @@ opt_minus
}
else {
/* other */
#ifdef YARV_AOT_COMPILED
val = rb_funcall(recv, idMINUS, 1, obj);
#else
PUSH(recv);
PUSH(obj);
tmp_id = idMINUS;
goto LABEL_IS_SC(start_init_in_send_for_opt_1);
#endif
CALL_SIMPLE_METHOD(1, idMINUS, recv);
}
}
@ -1675,16 +1756,9 @@ opt_mult
}
else {
INSN_LABEL(normal_dispatch):
/* other */
#ifdef YARV_AOT_COMPILED
val = rb_funcall(recv, idMULT, 1, obj);
#else
PUSH(recv);
PUSH(obj);
tmp_id = idMULT;
goto LABEL_IS_SC(start_init_in_send_for_opt_1);
#endif
CALL_SIMPLE_METHOD(1, idMULT, recv);
}
}
@ -1746,16 +1820,9 @@ opt_div
}
else {
INSN_LABEL(normal_dispatch):
/* other */
#ifdef YARV_AOT_COMPILED
val = rb_funcall(recv, idDIV, 1, obj);
#else
PUSH(recv);
PUSH(obj);
tmp_id = idDIV;
goto LABEL_IS_SC(start_init_in_send_for_opt_1);
#endif
CALL_SIMPLE_METHOD(1, idDIV, recv);
}
}
@ -1837,16 +1904,9 @@ opt_mod
}
else {
INSN_LABEL(normal_dispatch):
/* other */
#ifdef YARV_AOT_COMPILED
val = rb_funcall(recv, idMOD, 1, obj);
#else
PUSH(recv);
PUSH(obj);
tmp_id = idMOD;
goto LABEL_IS_SC(start_init_in_send_for_opt_1);
#endif
CALL_SIMPLE_METHOD(1, idMOD, recv);
}
}
@ -1916,14 +1976,9 @@ opt_eq
else {
INSN_LABEL(normal_dispatch):
/* other */
#ifdef YARV_AOT_COMPILED
val = rb_funcall(recv, idEq, 1, obj);
#else
PUSH(recv);
PUSH(obj);
tmp_id = idEq;
goto LABEL_IS_SC(start_init_in_send_for_opt_1);
#endif
CALL_SIMPLE_METHOD(1, idEq, recv);
}
}
@ -1951,15 +2006,9 @@ opt_lt
}
}
else {
/* other */
#ifdef YARV_AOT_COMPILED
val = rb_funcall(recv, idLT, 1, obj);
#else
PUSH(recv);
PUSH(obj);
tmp_id = idLT;
goto LABEL_IS_SC(start_init_in_send_for_opt_1);
#endif
CALL_SIMPLE_METHOD(1, idLT, recv);
}
}
@ -1987,14 +2036,9 @@ opt_le
}
else {
/* other */
#ifdef YARV_AOT_COMPILED
val = rb_funcall(recv, idLE, 1, obj);
#else
PUSH(recv);
PUSH(obj);
tmp_id = idLE;
goto LABEL_IS_SC(start_init_in_send_for_opt_1);
#endif
CALL_SIMPLE_METHOD(1, idLE, recv);
}
}
@ -2021,15 +2065,9 @@ opt_gt
}
}
else {
/* other */
#ifdef YARV_AOT_COMPILED
val = rb_funcall(recv, idGT, 1, obj);
#else
PUSH(recv);
PUSH(obj);
tmp_id = idGT;
goto LABEL_IS_SC(start_init_in_send_for_opt_1);
#endif
CALL_SIMPLE_METHOD(1, idGT, recv);
}
}
@ -2056,15 +2094,9 @@ opt_ge
}
}
else {
/* other */
#ifdef YARV_AOT_COMPILED
val = rb_funcall(recv, idGE, 1, obj);
#else
PUSH(recv);
PUSH(obj);
tmp_id = idGE;
goto LABEL_IS_SC(start_init_in_send_for_opt_1);
#endif
CALL_SIMPLE_METHOD(1, idGE, recv);
}
}
@ -2096,15 +2128,9 @@ opt_ltlt
}
else {
INSN_LABEL(normal_dispatch):
/* other */
#ifdef YARV_AOT_COMPILED
val = rb_funcall(recv, idLTLT, 1, obj);
#else
PUSH(recv);
PUSH(obj);
tmp_id = idLTLT;
goto LABEL_IS_SC(start_init_in_send_for_opt_1);
#endif
CALL_SIMPLE_METHOD(1, idLTLT, recv);
}
}
@ -2132,15 +2158,9 @@ opt_aref
}
else {
INSN_LABEL(normal_dispatch):
/* other */
#ifdef YARV_AOT_COMPILED
val = rb_funcall(recv, idAREF, 1, obj);
#else
PUSH(recv);
PUSH(obj);
tmp_id = idAREF;
goto LABEL_IS_SC(start_init_in_send_for_opt_1);
#endif
CALL_SIMPLE_METHOD(1, idAREF, recv);
}
}
@ -2171,16 +2191,10 @@ opt_aset
}
else {
INSN_LABEL(normal_dispatch):
/* other */
#ifdef YARV_AOT_COMPILED
val = rb_funcall(recv, idASET, 2, obj, set);
#else
PUSH(recv);
PUSH(obj);
PUSH(set);
tmp_id = idASET;
goto LABEL_IS_SC(start_init_in_send_for_opt_2);
#endif
CALL_SIMPLE_METHOD(2, idASET, recv);
}
}
@ -2212,12 +2226,8 @@ opt_length
}
else {
INSN_LABEL(normal_dispatch):
/* other */
#ifdef YARV_AOT_COMPILED
val = rb_funcall(recv, idLength, 0);
#else
val = rb_funcall(recv, idLength, 0);
#endif
PUSH(recv);
CALL_SIMPLE_METHOD(0, idLength, recv);
}
}
@ -2262,12 +2272,8 @@ opt_succ
}
if (0) {
INSN_LABEL(normal_dispatch):
/* other */
#ifdef YARV_AOT_COMPILED
val = rb_funcall(recv, idSucc, 0);
#else
val = rb_funcall(recv, idSucc, 0);
#endif
PUSH(recv);
CALL_SIMPLE_METHOD(0, idSucc, recv);
}
}

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

@ -120,7 +120,7 @@ class TestSuper < Test::Unit::TestCase
def uu(a)
class << self
define_method(:tt) do |sym|
super
super(sym)
end
end
end

172
vm.c
Просмотреть файл

@ -371,6 +371,38 @@ vm_call_cfunc(rb_thread_t *th, rb_control_frame_t *reg_cfp, int num,
return val;
}
static inline VALUE
vm_call_bmethod(rb_thread_t *th, ID id, VALUE procval, VALUE recv,
VALUE klass, int argc, VALUE *argv)
{
rb_control_frame_t *cfp = th->cfp;
rb_proc_t *proc;
VALUE val;
/* control block frame */
(cfp-2)->method_id = id;
(cfp-2)->method_klass = klass;
GetProcPtr(procval, proc);
val = th_invoke_proc(th, proc, recv, argc, argv);
return val;
}
static inline VALUE
vm_method_missing(rb_thread_t *th, ID id, VALUE recv, int num,
rb_block_t *blockptr, int opt)
{
rb_control_frame_t *reg_cfp = th->cfp;
VALUE *argv = STACK_ADDR_FROM_TOP(num + 1);
VALUE val;
argv[0] = ID2SYM(id);
th->method_missing_reason = opt;
th->passed_block = blockptr;
val = rb_funcall2(recv, idMethodMissing, num + 1, argv);
POPN(num + 1);
return val;
}
static inline void
vm_setup_method(rb_thread_t *th, rb_control_frame_t *cfp,
int argc, rb_block_t *blockptr, VALUE flag,
@ -428,6 +460,110 @@ vm_setup_method(rb_thread_t *th, rb_control_frame_t *cfp,
}
}
static inline VALUE
vm_call_method(rb_thread_t *th, rb_control_frame_t *cfp,
int num, rb_block_t *blockptr, VALUE flag,
ID id, NODE *mn, VALUE recv, VALUE klass)
{
VALUE val;
start_method_dispatch:
/* method missing */
if (mn == 0) {
if (id == idMethodMissing) {
rb_bug("method missing");
}
else {
int stat = 0;
if (flag & VM_CALL_VCALL_BIT) {
stat |= NOEX_VCALL;
}
if (flag & VM_CALL_SUPER_BIT) {
stat |= NOEX_SUPER;
}
val = vm_method_missing(th, id, recv, num, blockptr, stat);
}
}
else if (!(flag & VM_CALL_FCALL_BIT) &&
(mn->nd_noex & NOEX_MASK) & NOEX_PRIVATE) {
int stat = NOEX_PRIVATE;
if (flag & VM_CALL_VCALL_BIT) {
stat |= NOEX_VCALL;
}
val = vm_method_missing(th, id, recv, num, blockptr, stat);
}
else if ((mn->nd_noex & NOEX_MASK) & NOEX_PROTECTED) {
VALUE defined_class = mn->nd_clss;
if (TYPE(defined_class) == T_ICLASS) {
defined_class = RBASIC(defined_class)->klass;
}
if (!rb_obj_is_kind_of(cfp->self, rb_class_real(defined_class))) {
val = vm_method_missing(th, id, recv, num, blockptr, NOEX_PROTECTED);
}
else {
goto normal_method_dispatch;
}
}
/* dispatch method */
else {
NODE *node;
normal_method_dispatch:
node = mn->nd_body;
switch (nd_type(node)) {
case RUBY_VM_METHOD_NODE:{
vm_setup_method(th, cfp, num, blockptr, flag, (VALUE)node->nd_body, recv, klass);
return Qundef;
}
case NODE_CFUNC:{
val = vm_call_cfunc(th, cfp, num, id, recv, klass, node, blockptr);
break;
}
case NODE_ATTRSET:{
val = rb_ivar_set(recv, node->nd_vid, *(cfp->sp - 1));
cfp->sp -= 2;
break;
}
case NODE_IVAR:{
val = rb_ivar_get(recv, node->nd_vid);
cfp->sp -= 1;
break;
}
case NODE_BMETHOD:{
VALUE *argv = cfp->sp - num;
val = vm_call_bmethod(th, id, node->nd_cval, recv, klass, num, argv);
cfp->sp += - num - 1;
break;
}
case NODE_ZSUPER:{
klass = RCLASS(mn->nd_clss)->super;
mn = rb_method_node(klass, id);
if (mn != 0) {
goto normal_method_dispatch;
}
else {
goto start_method_dispatch;
}
}
default:{
printf("node: %s\n", ruby_node_name(nd_type(node)));
rb_bug("eval_invoke_method: unreachable");
/* unreachable */
break;
}
}
}
RUBY_VM_CHECK_INTS();
return val;
}
/* Env */
static void
@ -735,23 +871,6 @@ th_make_proc(rb_thread_t *th,
return procval;
}
static inline VALUE
th_invoke_bmethod(rb_thread_t *th, ID id, VALUE procval, VALUE recv,
VALUE klass, int argc, VALUE *argv)
{
rb_control_frame_t *cfp = th->cfp;
rb_proc_t *proc;
VALUE val;
/* control block frame */
(cfp-2)->method_id = id;
(cfp-2)->method_klass = klass;
GetProcPtr(procval, proc);
val = th_invoke_proc(th, proc, recv, argc, argv);
return val;
}
VALUE
th_call0(rb_thread_t *th, VALUE klass, VALUE recv,
VALUE id, ID oid, int argc, const VALUE *argv,
@ -829,8 +948,8 @@ th_call0(rb_thread_t *th, VALUE klass, VALUE recv,
break;
}
case NODE_BMETHOD:{
val = th_invoke_bmethod(th, id, body->nd_cval,
recv, klass, argc, (VALUE *)argv);
val = vm_call_bmethod(th, id, body->nd_cval,
recv, klass, argc, (VALUE *)argv);
break;
}
default:
@ -1555,21 +1674,6 @@ eval_define_method(rb_thread_t *th, VALUE obj,
INC_VM_STATE_VERSION();
}
EVALBODY_HELPER_FUNCTION VALUE
eval_method_missing(rb_thread_t *th, ID id, VALUE recv, int num,
rb_block_t *blockptr, int opt)
{
rb_control_frame_t *reg_cfp = th->cfp;
VALUE *argv = STACK_ADDR_FROM_TOP(num + 1);
VALUE val;
argv[0] = ID2SYM(id);
th->method_missing_reason = opt;
th->passed_block = blockptr;
val = rb_funcall2(recv, idMethodMissing, num + 1, argv);
POPN(num + 1);
return val;
}
EVALBODY_HELPER_FUNCTION NODE *
eval_method_search(VALUE id, VALUE klass, IC ic)
{

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

@ -76,10 +76,6 @@ th_eval(rb_thread_t *th, VALUE initial)
#define SET_PC(x) (reg_cfp->pc = REG_PC = (x))
#endif
ID tmp_id;
rb_block_t *tmp_blockptr;
rb_num_t tmp_num;
#if OPT_TOKEN_THREADED_CODE || OPT_DIRECT_THREADED_CODE
#include "vmtc.inc"
if (th == 0) {