ruby-changes:25584
From: ko1 <ko1@a...>
Date: Tue, 13 Nov 2012 17:36:42 +0900 (JST)
Subject: [ruby-changes:25584] ko1:r37641 (trunk): * vm_insnhelper.c (vm_caller_setup_args): save and restore
ko1 2012-11-13 17:34:43 +0900 (Tue, 13 Nov 2012) New Revision: 37641 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=37641 Log: * vm_insnhelper.c (vm_caller_setup_args): save and restore ci->argc and ci->blockptr before and after method invocations because these method dispatches override call_info. * bootstraptest/test_method.rb: add tests for this fix. Modified files: trunk/ChangeLog trunk/bootstraptest/test_method.rb trunk/vm_insnhelper.c Index: ChangeLog =================================================================== --- ChangeLog (revision 37640) +++ ChangeLog (revision 37641) @@ -1,3 +1,11 @@ +Tue Nov 13 17:28:47 2012 Koichi Sasada <ko1@a...> + + * vm_insnhelper.c (vm_caller_setup_args): save and restore + ci->argc and ci->blockptr before and after method invocations + because these method dispatches override call_info. + + * bootstraptest/test_method.rb: add tests for this fix. + Tue Nov 13 16:38:02 2012 NARUSE, Yui <naruse@r...> * common.mk (dmyprobes.h): always create for make dist. Index: bootstraptest/test_method.rb =================================================================== --- bootstraptest/test_method.rb (revision 37640) +++ bootstraptest/test_method.rb (revision 37641) @@ -1204,3 +1204,61 @@ 'ok' end } + +assert_equal 'DC', %q{ + $result = [] + + class C + def foo *args + $result << 'C' + end + end + class D + def foo *args + $result << 'D' + end + end + + o1 = $o1 = C.new + o2 = $o2 = D.new + + args = Object.new + def args.to_a + test1 $o2, nil + [] + end + def test1 o, args + o.foo(*args) + end + test1 o1, args + $result.join +} + +assert_equal 'DC', %q{ + $result = [] + + class C + def foo *args + $result << 'C' + end + end + class D + def foo *args + $result << 'D' + end + end + + o1 = $o1 = C.new + o2 = $o2 = D.new + + block = Object.new + def block.to_proc + test2 $o2, %w(a, b, c), nil + Proc.new{} + end + def test2 o, args, block + o.foo(*args, &block) + end + test2 o1, [], block + $result.join +} Index: vm_insnhelper.c =================================================================== --- vm_insnhelper.c (revision 37640) +++ vm_insnhelper.c (revision 37641) @@ -1036,6 +1036,12 @@ static void vm_caller_setup_args(const rb_thread_t *th, rb_control_frame_t *cfp, rb_call_info_t *ci) { +#define SAVE_RESTORE_CI(expr, ci) do { \ + int saved_argc = (ci)->argc; rb_block_t *saved_blockptr = (ci)->blockptr; /* save */ \ + expr; \ + (ci)->argc = saved_argc; (ci)->blockptr = saved_blockptr; /* restore */ \ +} while (0) + if (UNLIKELY(ci->flag & VM_CALL_ARGS_BLOCKARG)) { rb_proc_t *po; VALUE proc; @@ -1044,7 +1050,10 @@ if (proc != Qnil) { if (!rb_obj_is_proc(proc)) { - VALUE b = rb_check_convert_type(proc, T_DATA, "Proc", "to_proc"); + VALUE b; + + SAVE_RESTORE_CI(b = rb_check_convert_type(proc, T_DATA, "Proc", "to_proc"), ci); + if (NIL_P(b) || !rb_obj_is_proc(b)) { rb_raise(rb_eTypeError, "wrong argument type %s (expected Proc)", @@ -1069,8 +1078,10 @@ VALUE ary = *(cfp->sp - 1); VALUE *ptr; int i; - VALUE tmp = rb_check_convert_type(ary, T_ARRAY, "Array", "to_a"); + VALUE tmp; + SAVE_RESTORE_CI(tmp = rb_check_convert_type(ary, T_ARRAY, "Array", "to_a"), ci); + if (NIL_P(tmp)) { /* do nothing */ } -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/