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

ruby-changes:24685

From: nobu <ko1@a...>
Date: Mon, 20 Aug 2012 20:36:51 +0900 (JST)
Subject: [ruby-changes:24685] nobu:r36736 (trunk): vm_insnhelper.c: iclass as klass in cfp

nobu	2012-08-20 20:36:34 +0900 (Mon, 20 Aug 2012)

  New Revision: 36736

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=36736

  Log:
    vm_insnhelper.c: iclass as klass in cfp
    
    * vm_insnhelper.c (vm_call_method): follow iclasses as klass in cfp
      but not included modules.  [ruby-core:47241] [Bug #6891]
    * vm_insnhelper.c (vm_call_bmethod): pass defined_class to follow
      proper ancestors.  [ruby-core:47241] [Bug #6891]

  Modified files:
    trunk/ChangeLog
    trunk/cont.c
    trunk/proc.c
    trunk/test/ruby/test_module.rb
    trunk/thread.c
    trunk/vm.c
    trunk/vm_core.h
    trunk/vm_eval.c
    trunk/vm_insnhelper.c

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 36735)
+++ ChangeLog	(revision 36736)
@@ -1,3 +1,19 @@
+Mon Aug 20 20:36:30 2012  Nobuyoshi Nakada  <nobu@r...>
+
+	* vm_insnhelper.c (vm_call_method): follow iclasses as klass in cfp
+	  but not included modules.  [ruby-core:47241] [Bug #6891]
+
+	* vm_insnhelper.c (vm_call_bmethod): pass defined_class to follow
+	  proper ancestors.  [ruby-core:47241] [Bug #6891]
+
+Mon Aug 20 20:36:13 2012  Nobuyoshi Nakada  <nobu@r...>
+
+	* vm_insnhelper.c (vm_call_method): follow iclasses as klass in cfp
+	  but not included modules.  [ruby-core:47241] [Bug #6891]
+
+	* vm_insnhelper.c (vm_call_bmethod): pass defined_class to follow
+	  proper ancestors.  [ruby-core:47241] [Bug #6891]
+
 Mon Aug 20 11:40:27 2012  Kazuhiro NISHIYAMA  <zn@m...>
 
 	* common.mk: fix failed to make with -j2.
Index: vm_core.h
===================================================================
--- vm_core.h	(revision 36735)
+++ vm_core.h	(revision 36736)
@@ -731,7 +731,7 @@
 #endif
 int rb_thread_method_id_and_class(rb_thread_t *th, ID *idp, VALUE *klassp);
 
-VALUE rb_vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc, VALUE self,
+VALUE rb_vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc,
 			int argc, const VALUE *argv, const rb_block_t *blockptr);
 VALUE rb_vm_make_proc(rb_thread_t *th, const rb_block_t *block, VALUE klass);
 VALUE rb_vm_make_env_object(rb_thread_t *th, rb_control_frame_t *cfp);
Index: vm_eval.c
===================================================================
--- vm_eval.c	(revision 36735)
+++ vm_eval.c	(revision 36736)
@@ -126,7 +126,7 @@
 	  case OPTIMIZED_METHOD_TYPE_CALL: {
 	    rb_proc_t *proc;
 	    GetProcPtr(recv, proc);
-	    val = rb_vm_invoke_proc(th, proc, proc->block.self, argc, argv, blockptr);
+	    val = rb_vm_invoke_proc(th, proc, argc, argv, blockptr);
 	    break;
 	  }
 	  default:
Index: proc.c
===================================================================
--- proc.c	(revision 36735)
+++ proc.c	(revision 36736)
@@ -558,8 +558,7 @@
 	}
     }
 
-    vret = rb_vm_invoke_proc(GET_THREAD(), proc, proc->block.self,
-			     argc, argv, blockptr);
+    vret = rb_vm_invoke_proc(GET_THREAD(), proc, argc, argv, blockptr);
     RB_GC_GUARD(procval);
     return vret;
 }
@@ -584,7 +583,7 @@
     VALUE vret;
     rb_proc_t *proc;
     GetProcPtr(self, proc);
-    vret = rb_vm_invoke_proc(GET_THREAD(), proc, proc->block.self,
+    vret = rb_vm_invoke_proc(GET_THREAD(), proc,
 			     check_argc(RARRAY_LEN(args)), RARRAY_PTR(args), 0);
     RB_GC_GUARD(self);
     RB_GC_GUARD(args);
@@ -605,8 +604,7 @@
 	block = &pass_proc->block;
     }
 
-    vret = rb_vm_invoke_proc(GET_THREAD(), proc, proc->block.self,
-			     argc, argv, block);
+    vret = rb_vm_invoke_proc(GET_THREAD(), proc, argc, argv, block);
     RB_GC_GUARD(self);
     RB_GC_GUARD(pass_procval);
     return vret;
Index: thread.c
===================================================================
--- thread.c	(revision 36735)
+++ thread.c	(revision 36736)
@@ -455,7 +455,7 @@
 		    th->errinfo = Qnil;
 		    th->root_lep = rb_vm_ep_local_ep(proc->block.ep);
 		    th->root_svar = Qnil;
-		    th->value = rb_vm_invoke_proc(th, proc, proc->block.self,
+		    th->value = rb_vm_invoke_proc(th, proc,
 						  (int)RARRAY_LEN(args), RARRAY_PTR(args), 0);
 		}
 		else {
Index: cont.c
===================================================================
--- cont.c	(revision 36735)
+++ cont.c	(revision 36736)
@@ -1161,7 +1161,7 @@
 	th->root_svar = Qnil;
 
 	fib->status = RUNNING;
-	cont->value = rb_vm_invoke_proc(th, proc, proc->block.self, argc, argv, 0);
+	cont->value = rb_vm_invoke_proc(th, proc, argc, argv, 0);
     }
     TH_POP_TAG();
 
Index: vm.c
===================================================================
--- vm.c	(revision 36735)
+++ vm.c	(revision 36736)
@@ -61,6 +61,10 @@
     return VM_CF_BLOCK_PTR(cfp);
 }
 
+static VALUE
+vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc, VALUE self, VALUE defined_class,
+	       int argc, const VALUE *argv, const rb_block_t *blockptr);
+
 #include "vm_insnhelper.h"
 #include "vm_insnhelper.c"
 #include "vm_exec.h"
@@ -577,7 +581,8 @@
 static inline VALUE
 invoke_block_from_c(rb_thread_t *th, const rb_block_t *block,
 		    VALUE self, int argc, const VALUE *argv,
-		    const rb_block_t *blockptr, const NODE *cref)
+		    const rb_block_t *blockptr, const NODE *cref,
+		    VALUE defined_class)
 {
     if (SPECIAL_CONST_P(block->iseq))
 	return Qnil;
@@ -599,7 +604,7 @@
 				     type == VM_FRAME_MAGIC_LAMBDA);
 
 	vm_push_frame(th, iseq, type | VM_FRAME_FLAG_FINISH,
-		      self, block->klass, /* th->passed_defined_class, */
+		      self, defined_class,
 		      VM_ENVVAL_PREV_EP_PTR(block->ep),
 		      iseq->iseq_encoded + opt_pc,
 		      cfp->sp + arg_size, iseq->local_size - arg_size,
@@ -633,19 +638,21 @@
 vm_yield_with_cref(rb_thread_t *th, int argc, const VALUE *argv, const NODE *cref)
 {
     const rb_block_t *blockptr = check_block(th);
-    return invoke_block_from_c(th, blockptr, blockptr->self, argc, argv, 0, cref);
+    return invoke_block_from_c(th, blockptr, blockptr->self, argc, argv, 0, cref,
+			       blockptr->klass);
 }
 
 static inline VALUE
 vm_yield(rb_thread_t *th, int argc, const VALUE *argv)
 {
     const rb_block_t *blockptr = check_block(th);
-    return invoke_block_from_c(th, blockptr, blockptr->self, argc, argv, 0, 0);
+    return invoke_block_from_c(th, blockptr, blockptr->self, argc, argv, 0, 0,
+			       blockptr->klass);
 }
 
-VALUE
-rb_vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc, VALUE self,
-		  int argc, const VALUE *argv, const rb_block_t * blockptr)
+static VALUE
+vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc, VALUE self, VALUE defined_class,
+	       int argc, const VALUE *argv, const rb_block_t *blockptr)
 {
     VALUE val = Qundef;
     int state;
@@ -656,7 +663,8 @@
 	if (!proc->is_from_method) {
 	    th->safe_level = proc->safe_level;
 	}
-	val = invoke_block_from_c(th, &proc->block, self, argc, argv, blockptr, 0);
+	val = invoke_block_from_c(th, &proc->block, self, argc, argv, blockptr, 0,
+				  defined_class);
     }
     TH_POP_TAG();
 
@@ -670,6 +678,14 @@
     return val;
 }
 
+VALUE
+rb_vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc,
+		  int argc, const VALUE *argv, const rb_block_t *blockptr)
+{
+    return vm_invoke_proc(th, proc, proc->block.self, proc->block.klass,
+			  argc, argv, blockptr);
+}
+
 /* special variable */
 
 static rb_control_frame_t *
Index: vm_insnhelper.c
===================================================================
--- vm_insnhelper.c	(revision 36735)
+++ vm_insnhelper.c	(revision 36736)
@@ -466,7 +466,7 @@
     /* control block frame */
     th->passed_me = me;
     GetProcPtr(me->def->body.proc, proc);
-    val = rb_vm_invoke_proc(th, proc, recv, argc, argv, blockptr);
+    val = vm_invoke_proc(th, proc, recv, defined_class, argc, argv, blockptr);
 
     EXEC_EVENT_HOOK(th, RUBY_EVENT_RETURN, recv, me->called_id, me->klass);
 
@@ -655,7 +655,7 @@
 		    MEMCPY(argv, cfp->sp - num, VALUE, num);
 		    cfp->sp -= num + 1;
 
-		    val = rb_vm_invoke_proc(th, proc, proc->block.self, argc, argv, blockptr);
+		    val = rb_vm_invoke_proc(th, proc, argc, argv, blockptr);
 		    break;
 		  }
 		  default:
@@ -683,10 +683,6 @@
 		val = vm_method_missing(th, id, recv, num, blockptr, stat);
 	    }
 	    else if (!(flag & VM_CALL_OPT_SEND_BIT) && (me->flag & NOEX_MASK) & NOEX_PROTECTED) {
-		if (RB_TYPE_P(defined_class, T_ICLASS)) {
-		    defined_class = RBASIC(defined_class)->klass;
-		}
-
 		if (!rb_obj_is_kind_of(cfp->self, defined_class)) {
 		    val = vm_method_missing(th, id, recv, num, blockptr, NOEX_PROTECTED);
 		}
Index: test/ruby/test_module.rb
===================================================================
--- test/ruby/test_module.rb	(revision 36735)
+++ test/ruby/test_module.rb	(revision 36736)
@@ -1398,4 +1398,58 @@
     assert_equal([:@@bar, :@@foo], m2.class_variables(true))
     assert_equal([:@@bar], m2.class_variables(false))
   end
+
+  Bug6891 = '[ruby-core:47241]'
+
+  def test_extend_module_with_protected_method
+    list = []
+
+    x = Class.new {
+      @list = list
+
+      extend Module.new {
+        protected
+
+        def inherited(klass)
+          @list << "protected"
+          super(klass)
+        end
+      }
+
+      extend Module.new {
+        def inherited(klass)
+          @list << "public"
+          super(klass)
+        end
+      }
+    }
+
+    assert_nothing_raised(NoMethodError, Bug6891) {Class.new(x)}
+    assert_equal(['public', 'protected'], list)
+  end
+
+  def test_extend_module_with_protected_bmethod
+    list = []
+
+    x = Class.new {
+      extend Module.new {
+        protected
+
+        define_method(:inherited) do |klass|
+          list << "protected"
+          super(klass)
+        end
+      }
+
+      extend Module.new {
+        define_method(:inherited) do |klass|
+          list << "public"
+          super(klass)
+        end
+      }
+    }
+
+    assert_nothing_raised(NoMethodError, Bug6891) {Class.new(x)}
+    assert_equal(['public', 'protected'], list)
+  end
 end

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

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