[前][次][番号順一覧][スレッド一覧]

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/

[前][次][番号順一覧][スレッド一覧]