ruby-changes:29308
From: ktsj <ko1@a...>
Date: Mon, 17 Jun 2013 21:47:38 +0900 (JST)
Subject: [ruby-changes:29308] ktsj:r41360 (trunk): * include/ruby/ruby.h, vm_eval.c (rb_funcall_with_block):
ktsj 2013-06-17 21:47:26 +0900 (Mon, 17 Jun 2013) New Revision: 41360 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=41360 Log: * include/ruby/ruby.h, vm_eval.c (rb_funcall_with_block): new function to invoke a method with a block passed as an argument. * string.c (sym_call): use the above function to avoid a block sharing. [ruby-dev:47438] [Bug #8531] * vm_insnhelper.c (vm_yield_with_cfunc): don't set block in the frame. * test/ruby/test_symbol.rb (TestSymbol#test_block_given_to_proc): run related tests. Modified files: trunk/ChangeLog trunk/include/ruby/ruby.h trunk/string.c trunk/test/ruby/test_symbol.rb trunk/vm_eval.c trunk/vm_insnhelper.c Index: include/ruby/ruby.h =================================================================== --- include/ruby/ruby.h (revision 41359) +++ include/ruby/ruby.h (revision 41360) @@ -1480,6 +1480,7 @@ VALUE rb_funcallv_public(VALUE, ID, int, https://github.com/ruby/ruby/blob/trunk/include/ruby/ruby.h#L1480 #define rb_funcall2 rb_funcallv #define rb_funcall3 rb_funcallv_public VALUE rb_funcall_passing_block(VALUE, ID, int, const VALUE*); +VALUE rb_funcall_with_block(VALUE, ID, int, const VALUE*, VALUE); int rb_scan_args(int, const VALUE*, const char*, ...); VALUE rb_call_super(int, const VALUE*); Index: ChangeLog =================================================================== --- ChangeLog (revision 41359) +++ ChangeLog (revision 41360) @@ -1,3 +1,18 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Mon Jun 17 21:42:18 2013 Kazuki Tsujimoto <kazuki@c...> + + * include/ruby/ruby.h, vm_eval.c (rb_funcall_with_block): + new function to invoke a method with a block passed + as an argument. + + * string.c (sym_call): use the above function to avoid + a block sharing. [ruby-dev:47438] [Bug #8531] + + * vm_insnhelper.c (vm_yield_with_cfunc): don't set block + in the frame. + + * test/ruby/test_symbol.rb (TestSymbol#test_block_given_to_proc): + run related tests. + Mon Jun 17 21:33:27 2013 Kazuki Tsujimoto <kazuki@c...> * include/ruby/intern.h, proc.c (rb_method_call_with_block): Index: string.c =================================================================== --- string.c (revision 41359) +++ string.c (revision 41360) @@ -8213,7 +8213,7 @@ sym_to_sym(VALUE sym) https://github.com/ruby/ruby/blob/trunk/string.c#L8213 } static VALUE -sym_call(VALUE args, VALUE sym, int argc, VALUE *argv) +sym_call(VALUE args, VALUE sym, int argc, VALUE *argv, VALUE passed_proc) { VALUE obj; @@ -8221,7 +8221,7 @@ sym_call(VALUE args, VALUE sym, int argc https://github.com/ruby/ruby/blob/trunk/string.c#L8221 rb_raise(rb_eArgError, "no receiver given"); } obj = argv[0]; - return rb_funcall_passing_block(obj, (ID)sym, argc - 1, argv + 1); + return rb_funcall_with_block(obj, (ID)sym, argc - 1, argv + 1, passed_proc); } /* Index: vm_eval.c =================================================================== --- vm_eval.c (revision 41359) +++ vm_eval.c (revision 41360) @@ -830,6 +830,23 @@ rb_funcall_passing_block(VALUE recv, ID https://github.com/ruby/ruby/blob/trunk/vm_eval.c#L830 return rb_call(recv, mid, argc, argv, CALL_PUBLIC); } +VALUE +rb_funcall_with_block(VALUE recv, ID mid, int argc, const VALUE *argv, VALUE pass_procval) +{ + if (!NIL_P(pass_procval)) { + rb_thread_t *th = GET_THREAD(); + rb_block_t *block = 0; + + rb_proc_t *pass_proc; + GetProcPtr(pass_procval, pass_proc); + block = &pass_proc->block; + + th->passed_block = block; + } + + return rb_call(recv, mid, argc, argv, CALL_PUBLIC); +} + static VALUE send_internal(int argc, const VALUE *argv, VALUE recv, call_type scope) { Index: vm_insnhelper.c =================================================================== --- vm_insnhelper.c (revision 41359) +++ vm_insnhelper.c (revision 41360) @@ -2076,7 +2076,6 @@ vm_yield_with_cfunc(rb_thread_t *th, con https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L2076 NODE *ifunc = (NODE *) block->iseq; VALUE val, arg, blockarg; int lambda = block_proc_is_lambda(block->proc); - rb_control_frame_t *cfp; if (lambda) { arg = rb_ary_new4(argc, argv); @@ -2100,13 +2099,10 @@ vm_yield_with_cfunc(rb_thread_t *th, con https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L2099 blockarg = Qnil; } - cfp = vm_push_frame(th, (rb_iseq_t *)ifunc, VM_FRAME_MAGIC_IFUNC, self, - 0, VM_ENVVAL_PREV_EP_PTR(block->ep), 0, - th->cfp->sp, 1, 0); + vm_push_frame(th, (rb_iseq_t *)ifunc, VM_FRAME_MAGIC_IFUNC, self, + 0, VM_ENVVAL_PREV_EP_PTR(block->ep), 0, + th->cfp->sp, 1, 0); - if (blockargptr) { - VM_CF_LEP(cfp)[0] = VM_ENVVAL_BLOCK_PTR(blockargptr); - } val = (*ifunc->nd_cfnc) (arg, ifunc->nd_tval, argc, argv, blockarg); th->cfp++; Index: test/ruby/test_symbol.rb =================================================================== --- test/ruby/test_symbol.rb (revision 41359) +++ test/ruby/test_symbol.rb (revision 41360) @@ -128,7 +128,6 @@ class TestSymbol < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_symbol.rb#L128 def test_block_given_to_proc bug8531 = '[Bug #8531]' - skip bug8531 m = :m_block_given?.to_proc assert(!m.call(self), "#{bug8531} without block") assert(m.call(self) {}, "#{bug8531} with block") -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/