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

ruby-changes:40557

From: ko1 <ko1@a...>
Date: Wed, 18 Nov 2015 17:16:02 +0900 (JST)
Subject: [ruby-changes:40557] ko1:r52636 (trunk): * method.h: introduce the folliwing field and macros.

ko1	2015-11-18 17:15:51 +0900 (Wed, 18 Nov 2015)

  New Revision: 52636

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

  Log:
    * method.h: introduce the folliwing field and macros.
    
      * rb_method_definition_t::complemented_count to count shared method
        entries because of complemented method entries and separate from
        alias_count.
    
        Shared `def' only by complemented method entries should not prevent
        method re-definition warning.
    
      * METHOD_ENTRY_COMPLEMENTED(me) to represent complemented method entry.
      * METHOD_ENTRY_COMPLEMENTED_SET(me) to check it as  complemented me.
    
    * vm_insnhelper.c (aliased_callable_method_entry): should also
      check me->def->complemented_count.
    
    * vm_method.c (method_definition_addref_complement): add to count
      complemented method entries number.
    
    * vm_method.c (rb_method_definition_release): release `def' iff
      alias_count == 0 and complemented_count == 0.
    
    * test/ruby/test_module.rb: add a test.

  Modified files:
    trunk/ChangeLog
    trunk/method.h
    trunk/test/ruby/test_module.rb
    trunk/vm_insnhelper.c
    trunk/vm_method.c
Index: method.h
===================================================================
--- method.h	(revision 52635)
+++ method.h	(revision 52636)
@@ -65,6 +65,8 @@ typedef struct rb_callable_method_entry_ https://github.com/ruby/ruby/blob/trunk/method.h#L65
 
 #define METHOD_ENTRY_VISI(me)  (rb_method_visibility_t)(((me)->flags & (IMEMO_FL_USER0 | IMEMO_FL_USER1)) >> (IMEMO_FL_USHIFT+0))
 #define METHOD_ENTRY_BASIC(me) (int)                   (((me)->flags & (IMEMO_FL_USER2                 )) >> (IMEMO_FL_USHIFT+2))
+#define METHOD_ENTRY_COMPLEMENTED(me)     ((me)->flags & IMEMO_FL_USER3)
+#define METHOD_ENTRY_COMPLEMENTED_SET(me) ((me)->flags = (me)->flags | IMEMO_FL_USER3)
 
 static inline void
 METHOD_ENTRY_VISI_SET(rb_method_entry_t *me, rb_method_visibility_t visi)
@@ -143,8 +145,9 @@ typedef struct rb_method_refined_struct https://github.com/ruby/ruby/blob/trunk/method.h#L145
 } rb_method_refined_t;
 
 typedef struct rb_method_definition_struct {
-    rb_method_type_t type; /* method type */
-    int alias_count;
+    rb_method_type_t type :  8; /* method type */
+    int alias_count       : 28;
+    int complemented_count: 28;
 
     union {
 	rb_method_iseq_t iseq;
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 52635)
+++ ChangeLog	(revision 52636)
@@ -1,3 +1,28 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Wed Nov 18 17:08:18 2015  Koichi Sasada  <ko1@a...>
+
+	* method.h: introduce the folliwing field and macros.
+
+	  * rb_method_definition_t::complemented_count to count shared method
+	    entries because of complemented method entries and separate from
+	    alias_count.
+
+	    Shared `def' only by complemented method entries should not prevent
+	    method re-definition warning.
+
+	  * METHOD_ENTRY_COMPLEMENTED(me) to represent complemented method entry.
+	  * METHOD_ENTRY_COMPLEMENTED_SET(me) to check it as  complemented me.
+
+	* vm_insnhelper.c (aliased_callable_method_entry): should also
+	  check me->def->complemented_count.
+
+	* vm_method.c (method_definition_addref_complement): add to count
+	  complemented method entries number.
+
+	* vm_method.c (rb_method_definition_release): release `def' iff
+	  alias_count == 0 and complemented_count == 0.
+
+	* test/ruby/test_module.rb: add a test.
+
 Wed Nov 18 17:06:19 2015  Koichi Sasada  <ko1@a...>
 
 	* gc.c (rb_raw_obj_info): fix trivial issues.
Index: vm_method.c
===================================================================
--- vm_method.c	(revision 52635)
+++ vm_method.c	(revision 52636)
@@ -135,19 +135,24 @@ rb_add_method_cfunc(VALUE klass, ID mid, https://github.com/ruby/ruby/blob/trunk/vm_method.c#L135
 }
 
 static void
-rb_method_definition_release(rb_method_definition_t *def)
+rb_method_definition_release(rb_method_definition_t *def, int complemented)
 {
     if (def != NULL) {
-	const int count = def->alias_count;
-	VM_ASSERT(count >= 0);
+	const int alias_count = def->alias_count;
+	const int complemented_count = def->complemented_count;
+	VM_ASSERT(alias_count >= 0);
+	VM_ASSERT(complemented_count >= 0);
 
-	if (count == 0) {
-	    if (METHOD_DEBUG) fprintf(stderr, "-%p-%s:%d\n", def, rb_id2name(def->original_id), count);
+	if (alias_count + complemented_count == 0) {
+	    if (METHOD_DEBUG) fprintf(stderr, "-%p-%s:%d,%d (remove)\n", def, rb_id2name(def->original_id), alias_count, complemented_count);
 	    xfree(def);
 	}
 	else {
-	    if (METHOD_DEBUG) fprintf(stderr, "-%p-%s:%d->%d\n", def, rb_id2name(def->original_id), count, count-1);
-	    def->alias_count--;
+	    if (complemented) def->complemented_count--;
+	    else if (def->alias_count > 0) def->alias_count--;
+
+	    if (METHOD_DEBUG) fprintf(stderr, "-%p-%s:%d->%d,%d->%d (dec)\n", def, rb_id2name(def->original_id),
+				      alias_count, def->alias_count, complemented_count, def->complemented_count);
 	}
     }
 }
@@ -155,7 +160,7 @@ rb_method_definition_release(rb_method_d https://github.com/ruby/ruby/blob/trunk/vm_method.c#L160
 void
 rb_free_method_entry(const rb_method_entry_t *me)
 {
-    rb_method_definition_release(me->def);
+    rb_method_definition_release(me->def, METHOD_ENTRY_COMPLEMENTED(me));
 }
 
 static inline rb_method_entry_t *search_method(VALUE klass, ID id, VALUE *defined_class_ptr);
@@ -342,6 +347,14 @@ method_definition_addref(rb_method_defin https://github.com/ruby/ruby/blob/trunk/vm_method.c#L347
     return def;
 }
 
+static rb_method_definition_t *
+method_definition_addref_complement(rb_method_definition_t *def)
+{
+    def->complemented_count++;
+    if (METHOD_DEBUG) fprintf(stderr, "+%p-%s:%d\n", def, rb_id2name(def->original_id), def->alias_count);
+    return def;
+}
+
 static rb_method_entry_t *
 rb_method_entry_alloc(ID called_id, VALUE owner, VALUE defined_class, const rb_method_definition_t *def)
 {
@@ -385,8 +398,12 @@ const rb_callable_method_entry_t * https://github.com/ruby/ruby/blob/trunk/vm_method.c#L398
 rb_method_entry_complement_defined_class(const rb_method_entry_t *src_me, VALUE defined_class)
 {
     rb_method_entry_t *me = rb_method_entry_alloc(src_me->called_id, src_me->owner, defined_class,
-						  method_definition_addref(src_me->def));
+						  method_definition_addref_complement(src_me->def));
     METHOD_ENTRY_FLAGS_COPY(me, src_me);
+    METHOD_ENTRY_COMPLEMENTED_SET(me);
+
+    VM_ASSERT(RB_TYPE_P(me->owner, T_MODULE));
+
     return (rb_callable_method_entry_t *)me;
 }
 
Index: vm_insnhelper.c
===================================================================
--- vm_insnhelper.c	(revision 52635)
+++ vm_insnhelper.c	(revision 52636)
@@ -1990,7 +1990,7 @@ aliased_callable_method_entry(const rb_c https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L1990
 	VM_ASSERT(RB_TYPE_P(orig_me->owner, T_MODULE));
 	cme = rb_method_entry_complement_defined_class(orig_me, defined_class);
 
-	if (me->def->alias_count == 0) {
+	if (me->def->alias_count + me->def->complemented_count == 0) {
 	    RB_OBJ_WRITE(me, &me->def->body.alias.original_me, cme);
 	}
 	else {
Index: test/ruby/test_module.rb
===================================================================
--- test/ruby/test_module.rb	(revision 52635)
+++ test/ruby/test_module.rb	(revision 52636)
@@ -1280,6 +1280,20 @@ class TestModule < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_module.rb#L1280
         undef foo
       end
     end
+
+    stderr = EnvUtil.verbose_warning do
+      Module.new do
+        def foo; end
+        mod = self
+        c = Class.new do
+          include mod
+        end
+        c.new.foo
+        def foo; end
+      end
+    end
+    assert_match(/: warning: method redefined; discarding old foo/, stderr)
+    assert_match(/: warning: previous definition of foo/, stderr)
   end
 
   def test_protected_singleton_method

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

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