diff --git a/ChangeLog b/ChangeLog index 4649ed6f15..d1dc7117dc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +Thu Dec 20 16:04:17 2007 Koichi Sasada + + * insnhelper.ci, vm.c, vm_core.h: change interface of + vm_invoke_block() to specify block ptr. [ruby-talk:266422] + + * cont.c, eval_jump.ci, insns.def, proc.c, signal.c, thread.c: + apply above change. + + * bootstraptest/test_knownbug.rb: move fixed bug. + + * bootstraptest/test_block.rb: ditto. and add a test. + Thu Dec 20 15:47:13 2007 Nobuyoshi Nakada * enc/iso_8859_{1..16}.c: renamed. diff --git a/bootstraptest/test_block.rb b/bootstraptest/test_block.rb index 97fcdd4bef..f139c21d15 100644 --- a/bootstraptest/test_block.rb +++ b/bootstraptest/test_block.rb @@ -472,3 +472,28 @@ assert_equal '[nil, []]', %q{ GC.stress=false r.inspect }, '[ruby-dev:32567]' + +assert_equal NilClass.to_s, %q{ + r = false; 1.times{|&b| r = b}; r.class +} + +assert_equal 'ok', %q{ + class C + define_method(:foo) do |arg, &block| + if block then block.call else arg end + end + end + C.new.foo("ng") {"ok"} +}, '[ruby-talk:266422]' + +assert_equal 'ok', %q{ + STDERR.reopen(STDOUT) + class C + define_method(:foo) do |&block| + block.call if block + end + result = "ng" + new.foo() {result = "ok"} + result + end +} diff --git a/bootstraptest/test_knownbug.rb b/bootstraptest/test_knownbug.rb index 2108a59168..c9711d642f 100644 --- a/bootstraptest/test_knownbug.rb +++ b/bootstraptest/test_knownbug.rb @@ -10,27 +10,6 @@ assert_equal '0', %q{ $?.to_i }, '[ruby-dev:32404]' -assert_equal 'ok', %q{ - class C - define_method(:foo) do |arg, &block| - if block then block.call else arg end - end - end - C.new.foo("ng") {"ok"} -}, '[ruby-talk:266422]' - -assert_equal 'ok', %q{ - STDERR.reopen(STDOUT) - class C - define_method(:foo) do |&block| - block.call if block - end - result = "ng" - new.foo() {result = "ok"} - result - end -} - assert_equal 'ok', %q{ 1.times{ eval("break") diff --git a/cont.c b/cont.c index 14c1f497f3..39c8cfd33d 100644 --- a/cont.c +++ b/cont.c @@ -596,7 +596,7 @@ rb_fiber_start(void) th->local_lfp = proc->block.lfp; th->local_svar = Qnil; - cont->value = vm_invoke_proc(th, proc, proc->block.self, 1, &args); + cont->value = vm_invoke_proc(th, proc, proc->block.self, 1, &args, 0); } TH_POP_TAG(); diff --git a/eval_jump.ci b/eval_jump.ci index db32bba8f5..948ac635be 100644 --- a/eval_jump.ci +++ b/eval_jump.ci @@ -159,13 +159,10 @@ rb_catch_obj(VALUE tag, VALUE (*func)(), VALUE data) /* exit */ -static void call_end_proc _((VALUE data)); - -static void -call_end_proc(VALUE data) +void +rb_call_end_proc(VALUE data) { - /* TODO: fix me */ - proc_invoke(data, rb_ary_new2(0), Qundef, 0); + rb_proc_call(data, rb_ary_new()); } /* @@ -198,7 +195,7 @@ rb_f_at_exit(void) rb_raise(rb_eArgError, "called without a block"); } proc = rb_block_proc(); - rb_set_end_proc(call_end_proc, proc); + rb_set_end_proc(rb_call_end_proc, proc); return proc; } diff --git a/insnhelper.ci b/insnhelper.ci index 7544345a73..ba390c3aed 100644 --- a/insnhelper.ci +++ b/insnhelper.ci @@ -391,7 +391,7 @@ vm_cfunc_flags(rb_control_frame_t *cfp) static inline VALUE vm_call_bmethod(rb_thread_t *th, ID id, VALUE procval, VALUE recv, - VALUE klass, int argc, VALUE *argv) + VALUE klass, int argc, VALUE *argv, rb_block_t *blockptr) { rb_control_frame_t *cfp = th->cfp; rb_proc_t *proc; @@ -402,7 +402,7 @@ vm_call_bmethod(rb_thread_t *th, ID id, VALUE procval, VALUE recv, (cfp-2)->method_class = klass; GetProcPtr(procval, proc); - val = vm_invoke_proc(th, proc, recv, argc, argv); + val = vm_invoke_proc(th, proc, recv, argc, argv, blockptr); return val; } @@ -516,7 +516,7 @@ vm_call_method(rb_thread_t *th, rb_control_frame_t *cfp, } case NODE_BMETHOD:{ VALUE *argv = cfp->sp - num; - val = vm_call_bmethod(th, id, node->nd_cval, recv, klass, num, argv); + val = vm_call_bmethod(th, id, node->nd_cval, recv, klass, num, argv, blockptr); cfp->sp += - num - 1; break; } @@ -1392,12 +1392,6 @@ vm_expandarray(rb_control_frame_t *cfp, VALUE ary, int num, int flag) } } -static void -call_end_proc(VALUE data) -{ - rb_proc_call(data, rb_ary_new2(0)); -} - static inline int check_cfunc(NODE *mn, void *func) { diff --git a/insns.def b/insns.def index 7cfa15a13f..e0d997b834 100644 --- a/insns.def +++ b/insns.def @@ -879,13 +879,14 @@ postexe { rb_block_t *blockptr; VALUE proc; + extern void rb_call_end_proc(VALUE data); blockptr = RUBY_VM_GET_BLOCK_PTR_IN_CFP(GET_CFP()); blockptr->iseq = blockiseq; blockptr->proc = 0; proc = vm_make_proc(th, GET_CFP(), blockptr); - rb_set_end_proc(call_end_proc, proc); + rb_set_end_proc(rb_call_end_proc, proc); } /** diff --git a/proc.c b/proc.c index 0bc3e99963..e75a90706c 100644 --- a/proc.c +++ b/proc.c @@ -352,17 +352,6 @@ proc_lambda(void) return rb_block_lambda(); } -VALUE -proc_invoke(VALUE self, VALUE args, VALUE alt_self, VALUE alt_class) -{ - rb_proc_t *proc; - GetProcPtr(self, proc); - - /* ignore self and klass */ - return vm_invoke_proc(GET_THREAD(), proc, proc->block.self, - RARRAY_LEN(args), RARRAY_PTR(args)); -} - /* CHECKME: are the argument checking semantics correct? */ /* @@ -401,23 +390,32 @@ static VALUE proc_call(int argc, VALUE *argv, VALUE procval) { rb_proc_t *proc; + rb_block_t *blockptr = 0; GetProcPtr(procval, proc); - return vm_invoke_proc(GET_THREAD(), proc, proc->block.self, argc, argv); -} + if (BUILTIN_TYPE(proc->block.iseq) != T_NODE && + proc->block.iseq->arg_block != -1) { -static VALUE -proc_yield(int argc, VALUE *argv, VALUE procval) -{ - rb_proc_t *proc; - GetProcPtr(procval, proc); - return vm_invoke_proc(GET_THREAD(), proc, proc->block.self, argc, argv); + if (rb_block_given_p()) { + rb_proc_t *proc; + VALUE procval; + procval = rb_block_proc(); + GetProcPtr(procval, proc); + blockptr = &proc->block; + } + } + + return vm_invoke_proc(GET_THREAD(), proc, proc->block.self, + argc, argv, blockptr); } VALUE -rb_proc_call(VALUE proc, VALUE args) +rb_proc_call(VALUE self, VALUE args) { - return proc_invoke(proc, args, Qundef, 0); + rb_proc_t *proc; + GetProcPtr(self, proc); + return vm_invoke_proc(GET_THREAD(), proc, proc->block.self, + RARRAY_LEN(args), RARRAY_PTR(args), 0); } /* @@ -1489,7 +1487,7 @@ Init_Proc(void) rb_define_singleton_method(rb_cProc, "new", rb_proc_s_new, -1); rb_define_method(rb_cProc, "call", proc_call, -1); rb_define_method(rb_cProc, "[]", proc_call, -1); - rb_define_method(rb_cProc, "yield", proc_yield, -1); + rb_define_method(rb_cProc, "yield", proc_call, -1); rb_define_method(rb_cProc, "to_proc", proc_to_proc, 0); rb_define_method(rb_cProc, "arity", proc_arity, 0); rb_define_method(rb_cProc, "clone", proc_clone, 0); diff --git a/signal.c b/signal.c index f83d166e43..9e0316d2d6 100644 --- a/signal.c +++ b/signal.c @@ -557,7 +557,7 @@ signal_exec(VALUE cmd, int sig) rb_proc_t *proc; VALUE signum = INT2FIX(sig); GetProcPtr(cmd, proc); - vm_invoke_proc(GET_THREAD(), proc, proc->block.self, 1, &signum); + vm_invoke_proc(GET_THREAD(), proc, proc->block.self, 1, &signum, 0); } void diff --git a/thread.c b/thread.c index 94d2ae5f49..63f161cc5e 100644 --- a/thread.c +++ b/thread.c @@ -321,7 +321,7 @@ thread_start_func_2(rb_thread_t *th, VALUE *stack_start, VALUE *register_stack_s th->local_lfp = proc->block.lfp; th->local_svar = Qnil; th->value = vm_invoke_proc(th, proc, proc->block.self, - RARRAY_LEN(args), RARRAY_PTR(args)); + RARRAY_LEN(args), RARRAY_PTR(args), 0); } else { th->value = (*th->first_func)((void *)th->first_args); diff --git a/vm.c b/vm.c index 75f2629bb7..7818acadf2 100644 --- a/vm.c +++ b/vm.c @@ -465,8 +465,7 @@ vm_call0(rb_thread_t *th, VALUE klass, VALUE recv, } case NODE_ATTRSET:{ if (argc != 1) { - rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", - argc); + rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", argc); } val = rb_ivar_set(recv, body->nd_vid, argv[0]); break; @@ -481,7 +480,7 @@ vm_call0(rb_thread_t *th, VALUE klass, VALUE recv, } case NODE_BMETHOD:{ val = vm_call_bmethod(th, id, body->nd_cval, - recv, klass, argc, (VALUE *)argv); + recv, klass, argc, (VALUE *)argv, blockptr); break; } default: @@ -539,15 +538,16 @@ rb_call_super(int argc, const VALUE *argv) /* C -> Ruby: block */ static VALUE -invoke_block(rb_thread_t *th, rb_block_t *block, VALUE self, int argc, VALUE *argv) +invoke_block(rb_thread_t *th, rb_block_t *block, VALUE self, + int argc, VALUE *argv, rb_block_t *blockptr) { VALUE val; if (BUILTIN_TYPE(block->iseq) != T_NODE) { rb_iseq_t *iseq = block->iseq; rb_control_frame_t *cfp = th->cfp; + int i, opt_pc; const int arg_size = iseq->arg_size; const int type = block_proc_is_lambda(block->proc) ? FRAME_MAGIC_LAMBDA : FRAME_MAGIC_BLOCK; - int i, opt_pc; rb_vm_set_finish_env(th); @@ -557,22 +557,8 @@ invoke_block(rb_thread_t *th, rb_block_t *block, VALUE self, int argc, VALUE *ar cfp->sp[i] = argv[i]; } - if (iseq->arg_block == -1) { - opt_pc = vm_yield_setup_args(th, iseq, argc, cfp->sp, 0, - type == FRAME_MAGIC_LAMBDA); - } - else { - rb_block_t *blockptr = 0; - if (rb_block_given_p()) { - rb_proc_t *proc; - VALUE procval; - procval = rb_block_proc(); - GetProcPtr(procval, proc); - blockptr = &proc->block; - } - opt_pc = vm_yield_setup_args(th, iseq, argc, cfp->sp, - blockptr, type == FRAME_MAGIC_LAMBDA); - } + opt_pc = vm_yield_setup_args(th, iseq, argc, cfp->sp, blockptr, + type == FRAME_MAGIC_LAMBDA); vm_push_frame(th, iseq, type, self, GC_GUARDED_PTR(block->dfp), @@ -587,7 +573,7 @@ invoke_block(rb_thread_t *th, rb_block_t *block, VALUE self, int argc, VALUE *ar argc = 1; argv = &args; } - val = vm_yield_with_cfunc(th, block, block->self, argc, argv); + val = vm_yield_with_cfunc(th, block, self, argc, argv); } return val; } @@ -601,12 +587,12 @@ vm_yield(rb_thread_t *th, int argc, VALUE *argv) vm_localjump_error("no block given", Qnil, 0); } - return invoke_block(th, block, block->self, argc, argv); + return invoke_block(th, block, block->self, argc, argv, 0); } VALUE vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc, - VALUE self, int argc, VALUE *argv) + VALUE self, int argc, VALUE *argv, rb_block_t *blockptr) { VALUE val = Qundef; int state; @@ -618,7 +604,7 @@ vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc, TH_PUSH_TAG(th); if ((state = EXEC_TAG()) == 0) { th->safe_level = proc->safe_level; - val = invoke_block(th, &proc->block, self, argc, argv); + val = invoke_block(th, &proc->block, self, argc, argv, blockptr); } TH_POP_TAG(); diff --git a/vm_core.h b/vm_core.h index 8f8079e31d..c6b909a90a 100644 --- a/vm_core.h +++ b/vm_core.h @@ -599,7 +599,8 @@ void rb_disable_interrupt(void); int rb_thread_method_id_and_class(rb_thread_t *th, ID *idp, VALUE *klassp); VALUE vm_eval_body(rb_thread_t *th); -VALUE vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc, VALUE self, int argc, VALUE *argv); +VALUE vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc, VALUE self, + int argc, VALUE *argv, rb_block_t *blockptr); VALUE vm_make_proc(rb_thread_t *th, rb_control_frame_t *cfp, rb_block_t *block); VALUE vm_make_env_object(rb_thread_t *th, rb_control_frame_t *cfp); VALUE vm_backtrace(rb_thread_t *, int);