mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
68e02f2c2c
* vm_macro.def (macro_eval_invoke_func): fix to use callee_setup_arg. * compile.c (set_arguments): adjust for above changes. * compile.c (iseq_compile_each): ditto. * iseq.c (ruby_iseq_disasm): ditto. * yarvcore.h: add rb_iseq_t#post_arg_start and arg_size. * bootstraptest/test_method.rb: add post arg tests. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12594 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
232 lines
5.3 KiB
C
232 lines
5.3 KiB
C
/* -*- c -*- */
|
|
/* do not use C++ style comment */
|
|
/* */
|
|
|
|
MACRO macro_eval_setup_send_arguments(num, blockptr, flag, blockiseq)
|
|
{
|
|
if (flag & VM_CALL_ARGS_BLOCKARG_BIT) {
|
|
rb_proc_t *po;
|
|
VALUE proc;
|
|
|
|
proc = TOPN(0);
|
|
if (proc != Qnil) {
|
|
if (!rb_obj_is_proc(proc)) {
|
|
proc = rb_check_convert_type(proc, T_DATA, "Proc", "to_proc");
|
|
if (!rb_obj_is_proc(proc)) {
|
|
rb_raise(rb_eTypeError,
|
|
"wrong argument type %s (expected Proc)",
|
|
rb_obj_classname(proc));
|
|
}
|
|
}
|
|
GetProcPtr(proc, po);
|
|
blockptr = &po->block;
|
|
RUBY_VM_GET_BLOCK_PTR_IN_CFP(reg_cfp)->proc = proc;
|
|
}
|
|
INC_SP(-1);
|
|
}
|
|
else if (blockiseq) {
|
|
blockptr = RUBY_VM_GET_BLOCK_PTR_IN_CFP(reg_cfp);
|
|
blockptr->iseq = blockiseq;
|
|
blockptr->proc = 0;
|
|
}
|
|
|
|
/* expand top of stack? */
|
|
if (flag & VM_CALL_ARGS_SPLAT_BIT) {
|
|
VALUE ary = TOPN(0);
|
|
VALUE *ptr, *dst;
|
|
int i;
|
|
VALUE tmp = rb_check_convert_type(ary, T_ARRAY, "Array", "to_splat");
|
|
|
|
if (NIL_P(tmp)) {
|
|
tmp = rb_ary_new3(1, ary);
|
|
}
|
|
ary = tmp;
|
|
|
|
ptr = RARRAY_PTR(ary);
|
|
dst = GET_SP() - 1;
|
|
for (i = 0; i < RARRAY_LEN(ary); i++) {
|
|
dst[i] = ptr[i];
|
|
}
|
|
num += i - 1;
|
|
INC_SP(i - 1);
|
|
}
|
|
}
|
|
|
|
|
|
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 */
|
|
if (CHECK_STACK_OVERFLOW(th, GET_CFP(), niseq->stack_max + 0x100)) {
|
|
rb_exc_raise(sysstack_error);
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|