1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00
ruby--ruby/insn_send.ci
ko1 904b9e5d54 * vm_macro.def: removed.
* insn_send.ci: added.  this file includes send instruction body.
* common.mk: ditto.
* insns.def: ditto.
* tool/insns2vm.rb: ditto.
* vm.c: ditto.



git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12600 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-06-24 11:02:40 +00:00

226 lines
5.1 KiB
C

/* -*-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();
}