e$B1sF#$G$9!#e(B
2010e$BG/e(B8e$B7ne(B25e$BF|e(B3:23 SASADA Koichi [email protected]:
e$B!!$G$-$l$P!$e(BVM_CALL_ARGS_BLOCKTRGH_BIT e$B$rA}$d$9$s$8$c$J$/e(B
e$B$F!$e(BVM_CALL_ARGS_BLOCKARG_BIT e$B$@$1$I!$e(Bblockiseqe$B!!$+$J$s$+$NCM$rFC<l$K$7e(B
e$B$F$*$/$H$+!$$=$&$$$&<BAu$K$7$F$b$i$($k$H$$$$$s$8$c$J$$$+$H;W$$$^$9!%e(B
e$B!JL?Na%*%Z%i%s%I$N%P%j%(!<%7%g%s$,8:$C$?J}$,?'!9$&$l$7$$!Ke(B
e$B%3%a%s%H$"$j$,$H$&$4$6$$$^$9!#$G$b!“8+$+$1>e%P%j%(!<%7%g%s$rA}$d$5$J$$e(B
e$B$H$3$m$G!“e(BVM_CALL_ARGS_BLOCKTRGH_BIT e$B$K7k9=0[$J$ke(B 2
e$B$D$N0UL#$rFM$C9~$`e(B
e$B$3$H$K$J$ke(B (e$B%9%?%C%/$Ke(B Proc
e$B$r:$;$k!&:$;$J$$$N0c$$$,$”$k$N$G!”:Y!9>re(B
e$B7oH=Dj$,I,MW$K$J$ke(B)
e$B$N$G!"Bg$7$F4r$7$/$J$$$H;W$$$^$9!#%a%s%F%J%s%9@-$be(B
e$B2<$,$j$^$9$N$G!"85$N%Q%C%A$NJ}$,$$$$$H;W$$$^$9!#e(B
e$B0l1~e(B blockiseq e$B$Ke(B -1 e$B$,F~$C$F$?$ie(B BLOCKTRGH
e$B07$$$K$9$k%Q%C%A$b=q$$$F$_e(B
e$B$^$7$?$,!"$+$J$jK<AE*$G$J$$%3!<%I$G$$$C$Q$$$K$J$j$^$7$?!#e(B
e$B:#e(B trunk e$B$,2u$l$F$k$h$&$J$N$G!"e(Btest-all
e$B$O$G$-$F$^$;$s!#e(B
diff --git a/compile.c b/compile.c
index 2fd804c…1c04640 100644
— a/compile.c
+++ b/compile.c
@@ -1411,11 +1411,18 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR
anchor)
case TS_ISEQ: / iseq */
{
VALUE v = operands[j];
-
if (v == Qundef) {
-
block = (VALUE)-1;
-
}
-
else {
-
rb_iseq_t *blk;
-
GetISeqPtr(v, blk);
-
block = (VALUE)blk;
-
}
}
@@ -2853,7 +2860,7 @@ add_ensure_iseq(LINK_ANCHOR *ret, rb_iseq_t
*iseq, int is_return)
}
static VALUE
-setup_args(rb_iseq_t *iseq, LINK_ANCHOR *args, NODE *argn, unsigned
long *flag)
+setup_args(rb_iseq_t *iseq, LINK_ANCHOR *args, NODE *argn, VALUE
*blockiseq, unsigned long *flag)
{
VALUE argc = INT2FIX(0);
int nsplat = 0;
@@ -2863,7 +2870,13 @@ setup_args(rb_iseq_t *iseq, LINK_ANCHOR *args,
NODE *argn, unsigned long *flag)
INIT_ANCHOR(arg_block);
INIT_ANCHOR(args_splat);
if (argn && nd_type(argn) == NODE_BLOCK_PASS) {
- COMPILE(arg_block, “block”, argn->nd_body);
- if ((VALUE)argn->nd_body != (VALUE)-1) {
-
COMPILE(arg_block, "block", argn->nd_body);
- }
- else {
-
arg_block = 0;
-
if (blockiseq) *blockiseq = Qundef;
- }
*flag |= VM_CALL_ARGS_BLOCKARG_BIT;
argn = argn->nd_head;
}
@@ -2932,7 +2945,7 @@ setup_args(rb_iseq_t *iseq, LINK_ANCHOR *args,
NODE *argn, unsigned long *flag)
ADD_SEQ(args, args_splat);
}
- if (*flag & VM_CALL_ARGS_BLOCKARG_BIT) {
- if ((*flag & VM_CALL_ARGS_BLOCKARG_BIT) && arg_block) {
ADD_SEQ(args, arg_block);
}
return argc;
@@ -3776,7 +3789,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR
*ret, NODE * node, int poped)
boff = 1;
default:
INIT_ANCHOR(args);
-
argc = setup_args(iseq, args, node->nd_args->nd_head, 0, &flag);
ADD_SEQ(ret, args);
}
ADD_INSN1(ret, nd_line(node), dupn, FIXNUM_INC(argc, 1 + boff));
@@ -4083,7 +4096,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR
*ret, NODE * node, int poped)
/* args */
if (nd_type(node) != NODE_VCALL) {
-
argc = setup_args(iseq, args, node->nd_args, &parent_block,
&flag);
}
else {
argc = INT2FIX(0);
@@ -4121,7 +4134,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR
*ret, NODE * node, int poped)
INIT_ANCHOR(args);
iseq->compile_data->current_block = Qfalse;
if (nd_type(node) == NODE_SUPER) {
-
argc = setup_args(iseq, args, node->nd_args, &parent_block,
&flag);
}
else {
/* NODE_ZSUPER */
@@ -4294,7 +4307,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR
*ret, NODE * node, int poped)
}
if (node->nd_head) {
-
argc = setup_args(iseq, args, node->nd_head, 0, &flag);
}
else {
argc = INT2FIX(0);
@@ -4906,7 +4919,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR
*ret, NODE * node, int poped)
INIT_ANCHOR(recv);
INIT_ANCHOR(args);
- argc = setup_args(iseq, args, node->nd_args, &flag);
-
argc = setup_args(iseq, args, node->nd_args, 0, &flag);
if (node->nd_recv == (NODE *) 1) {
flag |= VM_CALL_FCALL_BIT;
diff --git a/insns.def b/insns.def
index fcd97ae…10b99be 100644
— a/insns.def
+++ b/insns.def
@@ -989,7 +989,7 @@ DEFINE_INSN
send
(ID op_id, rb_num_t op_argc, ISEQ blockiseq, rb_num_t op_flag, IC ic)
(…)
-(VALUE val) // inc += - (int)(op_argc + ((op_flag &
VM_CALL_ARGS_BLOCKARG_BIT) ? 1 : 0));
+(VALUE val) // inc += - (int)(op_argc + (((op_flag &
VM_CALL_ARGS_BLOCKARG_BIT) && (VALUE)blockiseq != (VALUE)-1) ? 1 :
0));
{
const rb_method_entry_t *me;
VALUE recv, klass;
@@ -1017,7 +1017,7 @@ DEFINE_INSN
invokesuper
(rb_num_t op_argc, ISEQ blockiseq, rb_num_t op_flag)
(…)
-(VALUE val) // inc += - (int)(op_argc + ((op_flag &
VM_CALL_ARGS_BLOCKARG_BIT) ? 1 : 0));
+(VALUE val) // inc += - (int)(op_argc + (((op_flag &
VM_CALL_ARGS_BLOCKARG_BIT) && (VALUE)blockiseq != (VALUE)-1) ? 1 :
0));
{
rb_block_t *blockptr = !(op_flag & VM_CALL_ARGS_BLOCKARG_BIT) ?
GET_BLOCK_PTR() : 0;
int num = caller_setup_args(th, GET_CFP(), op_flag,
diff --git a/node.c b/node.c
index 65bc541…85574b4 100644
— a/node.c
+++ b/node.c
@@ -621,7 +621,12 @@ dump_node(VALUE buf, VALUE indent, int comment,
NODE *node)
ANN(“example: foo(x, &blk)”);
F_NODE(nd_head, “other arguments”);
LAST_NODE;
- F_NODE(nd_body, “block argument”);
-
if ((VALUE)node->nd_body != (VALUE)-1) {
-
F_NODE(nd_body, "block argument");
-
}
-
else {
-
F_MSG(nd_body, "block argument", "-1 (anonymous)");
-
}
break;
case NODE_DEFN:
diff --git a/parse.y b/parse.y
index e085088…b0b946b 100644
— a/parse.y
+++ b/parse.y
@@ -2459,6 +2459,14 @@ block_arg : tAMPER arg_value
$$ = $2;
%*/
}
opt_block_arg : ‘,’ block_arg
diff --git a/tool/instruction.rb b/tool/instruction.rb
index 4fd2127…4ce219f 100755
— a/tool/instruction.rb
+++ b/tool/instruction.rb
@@ -66,13 +66,12 @@ class RubyVM
ret = “int inc = 0;\n”
@opes.each_with_index{|(t, v), i|
re =~ val})
ret << " int #{v} = FIX2INT(opes[#{i}]);\n"
end
}
@defopes.each_with_index{|((t, var), val), i|
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index 985a2fb…f6418b7 100644
— a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -240,25 +240,31 @@ caller_setup_args(const rb_thread_t *th,
rb_control_frame_t *cfp, VALUE flag,
if (block) {
if (flag & VM_CALL_ARGS_BLOCKARG_BIT) {
“to_proc”);
-
if ((VALUE)blockiseq != (VALUE)-1) {
- rb_proc_t *po;
- VALUE proc;
-
- proc = *(–cfp->sp);
-
- if (proc != Qnil) {
-
if (!rb_obj_is_proc(proc)) {
-
VALUE b = rb_check_convert_type(proc, T_DATA, "Proc", "to_proc");
-
if (NIL_P(b) || !rb_obj_is_proc(b)) {
-
rb_raise(rb_eTypeError,
-
"wrong argument type %s (expected Proc)",
-
rb_obj_classname(proc));
-
}
-
proc = b;
}
- GetProcPtr(proc, po);
- blockptr = &po->block;
- RUBY_VM_GET_BLOCK_PTR_IN_CFP(cfp)->proc = proc;
- *block = blockptr;
-
}
-
else {
- rb_control_frame_t *reg_cfp = cfp;
- *block = GET_BLOCK_PTR();
}
}
else if (blockiseq) {