1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00
ruby--ruby/vm_macro.def
ko1 adc677eb5c * insnhelper.h: change CHECK_STACK_OVERFLOW() to throw exception.
* vm.c (caller_setup_arg), vm_macro.def: remove
  macro_eval_setup_send_arguments and add caller_setup_arg().
* insns.def: ditto.
* bootstraptest/test_method.rb: add splat arg tests.



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

179 lines
4.1 KiB
C

/* -*- c -*- */
/* do not use C++ style comment */
/* */
MACRO macro_eval_invoke_cfunc(num, id, recv, klass, mn, blockptr)
{
EXEC_EVENT_HOOK(th, RUBY_EVENT_C_CALL, recv, id, klass);
{
rb_control_frame_t *cfp =
push_frame(th, 0, FRAME_MAGIC_CFUNC,
recv, (VALUE) blockptr, 0, GET_SP(), 0, 1);
cfp->method_id = id;
cfp->method_klass = klass;
reg_cfp->sp -= num + 1;
val = call_cfunc(mn->nd_cfnc, recv, mn->nd_argc, num, reg_cfp->sp + 1);
if (reg_cfp != th->cfp + 1) {
SDR2(reg_cfp);
SDR2(th->cfp-5);
rb_bug("cfp consistency error - send");
th->cfp = reg_cfp;
}
pop_frame(th);
}
EXEC_EVENT_HOOK(th, RUBY_EVENT_C_RETURN, recv, id, klass);
}
MACRO macro_eval_invoke_func(niseqval, recv, klass, blockptr, num)
{
rb_iseq_t *niseq;
int opt_pc, i;
VALUE *rsp = GET_SP() - num;
VALUE *sp;
/* TODO: eliminate it */
GetISeqPtr(niseqval, niseq);
opt_pc = callee_setup_arg(th, niseq, num, rsp, &blockptr);
sp = rsp + niseq->arg_size;
/* stack overflow check */
CHECK_STACK_OVERFLOW(GET_CFP(), niseq->stack_max + 0x10);
if (flag & VM_CALL_TAILCALL_BIT) {
/* copy arguments */
VALUE *p_rsp, *p_sp;
reg_cfp = ++th->cfp;
p_rsp = th->cfp->sp;
for (i=0; i < (sp - rsp); i++) {
p_rsp[i] = rsp[i];
}
sp -= rsp - p_rsp;
for (i = 0; i < niseq->local_size - niseq->arg_size; i++) {
*sp++ = Qnil;
}
push_frame(th, niseq,
FRAME_MAGIC_METHOD, recv, (VALUE) blockptr,
niseq->iseq_encoded + opt_pc, sp, 0, 0);
}
else {
if (0) printf("local_size: %d, arg_size: %d\n",
niseq->local_size, niseq->arg_size);
for (i = 0; i < niseq->local_size - niseq->arg_size; i++) {
*sp++ = Qnil;
}
push_frame(th, niseq,
FRAME_MAGIC_METHOD, recv, (VALUE) blockptr,
niseq->iseq_encoded + opt_pc, sp, 0, 0);
reg_cfp->sp = rsp - 1 /* recv */;
}
RESTORE_REGS();
}
MACRO macro_eval_invoke_method(recv, klass, id, num, mn, blockptr)
{
/* 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:{
macro_eval_invoke_func(node->nd_body, recv, klass,
blockptr, num);
NEXT_INSN();
}
case NODE_CFUNC:{
macro_eval_invoke_cfunc(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;
}
}
}
}