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

ruby-changes:39085

From: ko1 <ko1@a...>
Date: Tue, 7 Jul 2015 03:45:16 +0900 (JST)
Subject: [ruby-changes:39085] ko1:r51166 (trunk): * vm_core.h: remove rb_iseq_t::klass to reduce dynamic data.

ko1	2015-07-07 03:44:54 +0900 (Tue, 07 Jul 2015)

  New Revision: 51166

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

  Log:
    * vm_core.h: remove rb_iseq_t::klass to reduce dynamic data.
    * internal.h, iseq.c (rb_iseq_klass): remove it because
      rb_iseq_t::klass is removed.
    * vm_insnhelper.c (vm_super_outside): do not see cfp->iseq, but
      check callable method entry on a frame.
      This fix simplify the logic to search super class.
    * test/ruby/test_method.rb: support super() from Proc.
      Now, [Bug #4881] and [Bug #3136] was solved.
    * proc.c (rb_mod_define_method): catch up this change.
    * vm.c (vm_define_method): ditto.
    * vm_backtrace.c (rb_profile_frames): now, each `frame' objects
      are rb_callable_method_entry_t data or iseq VALUEs.
      This fix introduce minor compatibility issue that
      rb_profile_frame_label() always returns
      rb_profile_frame_base_label().
    * test/-ext-/debug/test_profile_frames.rb: catch up this change.

  Modified files:
    trunk/ChangeLog
    trunk/internal.h
    trunk/iseq.c
    trunk/proc.c
    trunk/test/-ext-/debug/test_profile_frames.rb
    trunk/test/ruby/test_method.rb
    trunk/vm.c
    trunk/vm_backtrace.c
    trunk/vm_core.h
    trunk/vm_insnhelper.c
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 51165)
+++ ChangeLog	(revision 51166)
@@ -1,3 +1,30 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Tue Jul  7 03:33:20 2015  Koichi Sasada  <ko1@a...>
+
+	* vm_core.h: remove rb_iseq_t::klass to reduce dynamic data.
+
+	* internal.h, iseq.c (rb_iseq_klass): remove it because
+	  rb_iseq_t::klass is removed.
+
+	* vm_insnhelper.c (vm_super_outside): do not see cfp->iseq, but
+	  check callable method entry on a frame.
+	  This fix simplify the logic to search super class.
+
+	* test/ruby/test_method.rb: support super() from Proc.
+	  Now, [Bug #4881] and [Bug #3136] was solved.
+
+	* proc.c (rb_mod_define_method): catch up this change.
+
+	* vm.c (vm_define_method): ditto.
+
+	* vm_backtrace.c (rb_profile_frames): now, each `frame' objects
+	  are rb_callable_method_entry_t data or iseq VALUEs.
+
+	  This fix introduce minor compatibility issue that
+	  rb_profile_frame_label() always returns
+	  rb_profile_frame_base_label().
+
+	* test/-ext-/debug/test_profile_frames.rb: catch up this change.
+
 Tue Jul  7 01:52:14 2015  Koichi Sasada  <ko1@a...>
 
 	* cont.c (fiber_init): initialize control frame correctly.
Index: vm_core.h
===================================================================
--- vm_core.h	(revision 51165)
+++ vm_core.h	(revision 51166)
@@ -348,7 +348,6 @@ struct rb_iseq_struct { https://github.com/ruby/ruby/blob/trunk/vm_core.h#L348
 
     VALUE self;
     const VALUE orig;			/* non-NULL if its data have origin */
-    const VALUE klass;
 
     /* misc */
     ID defined_method_id;	/* for define_method */
Index: iseq.c
===================================================================
--- iseq.c	(revision 51165)
+++ iseq.c	(revision 51166)
@@ -127,8 +127,6 @@ iseq_mark(void *ptr) https://github.com/ruby/ruby/blob/trunk/iseq.c#L127
 	    RUBY_MARK_UNLESS_NULL(iseq->orig);
 	}
 
-	RUBY_MARK_UNLESS_NULL(iseq->klass);
-
 	if (iseq->compile_data != 0) {
 	    struct iseq_compile_data *const compile_data = iseq->compile_data;
 	    RUBY_MARK_UNLESS_NULL(compile_data->mark_ary);
@@ -261,7 +259,6 @@ prepare_iseq_build(rb_iseq_t *iseq, https://github.com/ruby/ruby/blob/trunk/iseq.c#L259
 		   const rb_compile_option_t *option)
 {
     iseq->type = type;
-    RB_OBJ_WRITE(iseq->self, &iseq->klass, 0);
     set_relation(iseq, parent);
 
     name = rb_fstring(name);
@@ -939,14 +936,6 @@ rb_iseq_first_lineno(VALUE self) https://github.com/ruby/ruby/blob/trunk/iseq.c#L936
 }
 
 VALUE
-rb_iseq_klass(VALUE self)
-{
-    rb_iseq_t *iseq;
-    GetISeqPtr(self, iseq);
-    return iseq->local_iseq->klass;
-}
-
-VALUE
 rb_iseq_method_name(VALUE self)
 {
     rb_iseq_t *iseq, *local_iseq;
@@ -1961,13 +1950,6 @@ rb_iseq_clone(VALUE iseqval, VALUE newcb https://github.com/ruby/ruby/blob/trunk/iseq.c#L1950
 	iseq1->local_iseq = iseq1;
     }
 
-    if (newcbase) {
-	RB_OBJ_WRITE(iseq1->self, &iseq1->klass, newcbase);
-    }
-    else {
-	RB_OBJ_WRITTEN(iseq1->self, Qundef, iseq1->klass);
-    }
-
     RB_GC_GUARD(iseqval); /* seems necessary iff RGenGC is disabled */
 
     return newiseq;
Index: proc.c
===================================================================
--- proc.c	(revision 51165)
+++ proc.c	(revision 51166)
@@ -1725,7 +1725,6 @@ rb_mod_define_method(int argc, VALUE *ar https://github.com/ruby/ruby/blob/trunk/proc.c#L1725
 	GetProcPtr(body, proc);
 	if (!RUBY_VM_IFUNC_P(proc->block.iseq)) {
 	    proc->block.iseq->defined_method_id = id;
-	    RB_OBJ_WRITE(proc->block.iseq->self, &proc->block.iseq->klass, mod);
 	    proc->is_lambda = TRUE;
 	    proc->is_from_method = TRUE;
 	}
Index: vm_backtrace.c
===================================================================
--- vm_backtrace.c	(revision 51165)
+++ vm_backtrace.c	(revision 51166)
@@ -9,6 +9,8 @@ https://github.com/ruby/ruby/blob/trunk/vm_backtrace.c#L9
 
 **********************************************************************/
 
+#define VM_CHECK_MODE 2
+
 #include "internal.h"
 #include "ruby/debug.h"
 
@@ -1248,15 +1250,24 @@ rb_profile_frames(int start, int limit, https://github.com/ruby/ruby/blob/trunk/vm_backtrace.c#L1250
     rb_control_frame_t *cfp = th->cfp, *end_cfp = RUBY_VM_END_CONTROL_FRAME(th);
 
     for (i=0; i<limit && cfp != end_cfp;) {
-	if (cfp->iseq && cfp->pc) { /* should be NORMAL_ISEQ */
+	const rb_callable_method_entry_t *cme = rb_vm_frame_method_entry(cfp);
+
+	if ((cme && cme->def->type == VM_METHOD_TYPE_ISEQ) || (cfp->iseq && cfp->pc)) {
 	    if (start > 0) {
 		start--;
 		continue;
 	    }
 
 	    /* record frame info */
-	    buff[i] = cfp->iseq->self;
-	    if (lines) lines[i] = calc_lineno(cfp->iseq, cfp->pc);
+	    if (cme) {
+		buff[i] = (VALUE)cme;
+	    }
+	    else {
+		buff[i] = cfp->iseq->self;
+	    }
+
+	    if (cfp->iseq && lines) lines[i] = calc_lineno(cfp->iseq, cfp->pc);
+
 	    i++;
 	}
 	cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
@@ -1265,42 +1276,83 @@ rb_profile_frames(int start, int limit, https://github.com/ruby/ruby/blob/trunk/vm_backtrace.c#L1276
     return i;
 }
 
-#define frame2iseq(frame) frame
+static VALUE
+frame2iseq(VALUE frame)
+{
+    if (frame == Qnil) return Qnil;
+
+    if (RB_TYPE_P(frame, T_DATA)) {
+	VM_ASSERT(strcmp(rb_objspace_data_type_name(frame), "iseq") == 0);
+	return frame;
+    }
+
+    if (RB_TYPE_P(frame, T_IMEMO)) {
+	const rb_callable_method_entry_t *cme = (rb_callable_method_entry_t *)frame;
+	VM_ASSERT(imemo_type(frame) == imemo_ment);
+	switch (cme->def->type) {
+	  case VM_METHOD_TYPE_ISEQ:
+	    return cme->def->body.iseq.iseqptr->self;
+	  default:
+	    return Qnil;
+	}
+    }
+    rb_bug("frame2iseq: unreachable");
+}
 
 VALUE
 rb_profile_frame_path(VALUE frame)
 {
-    return rb_iseq_path(frame2iseq(frame));
+    VALUE iseqv = frame2iseq(frame);
+    return NIL_P(iseqv) ? Qnil : rb_iseq_path(iseqv);
 }
 
 VALUE
 rb_profile_frame_absolute_path(VALUE frame)
 {
-    return rb_iseq_absolute_path(frame2iseq(frame));
+    VALUE iseqv = frame2iseq(frame);
+    return NIL_P(iseqv) ? Qnil : rb_iseq_absolute_path(iseqv);
 }
 
 VALUE
 rb_profile_frame_label(VALUE frame)
 {
-    return rb_iseq_label(frame2iseq(frame));
+    VALUE iseqv = frame2iseq(frame);
+    return NIL_P(iseqv) ? Qnil : rb_iseq_label(iseqv);
 }
 
 VALUE
 rb_profile_frame_base_label(VALUE frame)
 {
-    return rb_iseq_base_label(frame2iseq(frame));
+    VALUE iseqv = frame2iseq(frame);
+    return NIL_P(iseqv) ? Qnil : rb_iseq_base_label(iseqv);
 }
 
 VALUE
 rb_profile_frame_first_lineno(VALUE frame)
 {
-    return rb_iseq_first_lineno(frame2iseq(frame));
+    VALUE iseqv = frame2iseq(frame);
+    return NIL_P(iseqv) ? Qnil : rb_iseq_first_lineno(iseqv);
+}
+
+static VALUE
+frame2klass(VALUE frame)
+{
+    if (frame == Qnil) return Qnil;
+
+    if (RB_TYPE_P(frame, T_IMEMO)) {
+	const rb_callable_method_entry_t *cme = (rb_callable_method_entry_t *)frame;
+	VM_ASSERT(imemo_type(frame) == imemo_ment);
+	return cme->defined_class;
+    }
+    else {
+	return Qnil;
+    }
 }
 
 VALUE
 rb_profile_frame_classpath(VALUE frame)
 {
-    VALUE klass = rb_iseq_klass(frame2iseq(frame));
+    VALUE klass = frame2klass(frame);
 
     if (klass && !NIL_P(klass)) {
 	if (RB_TYPE_P(klass, T_ICLASS)) {
@@ -1321,7 +1373,8 @@ rb_profile_frame_classpath(VALUE frame) https://github.com/ruby/ruby/blob/trunk/vm_backtrace.c#L1373
 VALUE
 rb_profile_frame_singleton_method_p(VALUE frame)
 {
-    VALUE klass = rb_iseq_klass(frame2iseq(frame));
+    VALUE klass = frame2klass(frame);
+
     if (klass && !NIL_P(klass) && FL_TEST(klass, FL_SINGLETON)) {
 	return Qtrue;
     }
@@ -1333,13 +1386,15 @@ rb_profile_frame_singleton_method_p(VALU https://github.com/ruby/ruby/blob/trunk/vm_backtrace.c#L1386
 VALUE
 rb_profile_frame_method_name(VALUE frame)
 {
-    return rb_iseq_method_name(frame2iseq(frame));
+    VALUE iseqv = frame2iseq(frame);
+    return NIL_P(iseqv) ? Qnil : rb_iseq_method_name(iseqv);
 }
 
 VALUE
 rb_profile_frame_qualified_method_name(VALUE frame)
 {
-    VALUE method_name = rb_iseq_method_name(frame2iseq(frame));
+    VALUE method_name = rb_profile_frame_method_name(frame);
+
     if (method_name != Qnil) {
 	VALUE classpath = rb_profile_frame_classpath(frame);
 	VALUE singleton_p = rb_profile_frame_singleton_method_p(frame);
Index: internal.h
===================================================================
--- internal.h	(revision 51165)
+++ internal.h	(revision 51166)
@@ -853,7 +853,6 @@ VALUE rb_iseq_absolute_path(VALUE iseqva https://github.com/ruby/ruby/blob/trunk/internal.h#L853
 VALUE rb_iseq_label(VALUE iseqval);
 VALUE rb_iseq_base_label(VALUE iseqval);
 VALUE rb_iseq_first_lineno(VALUE iseqval);
-VALUE rb_iseq_klass(VALUE iseqval); /* completely temporary function */
 VALUE rb_iseq_method_name(VALUE self);
 
 /* load.c */
Index: vm.c
===================================================================
--- vm.c	(revision 51165)
+++ vm.c	(revision 51166)
@@ -2278,11 +2278,6 @@ vm_define_method(rb_thread_t *th, VALUE https://github.com/ruby/ruby/blob/trunk/vm.c#L2278
     rb_iseq_t *miseq;
     GetISeqPtr(iseqval, miseq);
 
-    if (miseq->klass) {
-	iseqval = rb_iseq_clone(iseqval, 0);
-	GetISeqPtr(iseqval, miseq);
-    }
-
     if (NIL_P(klass)) {
 	rb_raise(rb_eTypeError, "no class/module to add method");
     }
@@ -2293,7 +2288,6 @@ vm_define_method(rb_thread_t *th, VALUE https://github.com/ruby/ruby/blob/trunk/vm.c#L2288
     }
 
     /* dup */
-    RB_OBJ_WRITE(miseq->self, &miseq->klass, klass);
     miseq->defined_method_id = id;
     rb_add_method_iseq(klass, id, iseqval, cref, visi);
 
Index: vm_insnhelper.c
===================================================================
--- vm_insnhelper.c	(revision 51165)
+++ vm_insnhelper.c	(revision 51166)
@@ -2173,58 +2173,19 @@ vm_super_outside(void) https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L2173
 static int
 vm_search_superclass(rb_control_frame_t *reg_cfp, rb_iseq_t *iseq, VALUE sigval, rb_call_info_t *ci)
 {
-    const rb_callable_method_entry_t *me;
+    const rb_callable_method_entry_t *me = rb_vm_frame_method_entry(reg_cfp);
 
-    while (iseq && !iseq->klass) {
-	iseq = iseq->parent_iseq;
-    }
-
-    if (iseq == 0) {
+    if (me == NULL) {
 	return -1;
     }
-
-    ci->mid = iseq->defined_method_id;
-
-    if (iseq != iseq->local_iseq) {
-	/* defined by Module#define_method() */
-	rb_control_frame_t *lcfp = GET_CFP();
-
-	if (!sigval) {
-	    /* zsuper */
-	    return -2;
-	}
-
-	while (lcfp->iseq != iseq) {
-	    rb_thread_t *th = GET_THREAD();
-	    VALUE *tep = VM_EP_PREV_EP(lcfp->ep);
-	    while (1) {
-		lcfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(lcfp);
-		if (RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(th, lcfp)) {
-		    return -1;
-		}
-		if (lcfp->ep == tep) {
-		    break;
-		}
-	    }
-	}
-
-	me = rb_vm_frame_method_entry(lcfp);
-
-	/* temporary measure for [Bug #2420] [Bug #3136] */
-	if (!me) {
-	    fprintf(stderr, "kore?\n");
-	    return -1;
-	}
-
-	ci->mid = me->def->original_id;
-	ci->klass = vm_search_normal_superclass(me->defined_class);
+    else if (me->def->type == VM_METHOD_TYPE_BMETHOD && !sigval) {
+	return -2;
     }
     else {
-	me = rb_vm_frame_method_entry(reg_cfp);
+	ci->mid = me->def->original_id;
 	ci->klass = vm_search_normal_superclass(me->defined_class);
+	return 0;
     }
-
-    return 0;
 }
 
 static void
Index: test/ruby/test_method.rb
===================================================================
--- test/ruby/test_method.rb	(revision 51165)
+++ test/ruby/test_method.rb	(revision 51166)
@@ -405,11 +405,7 @@ class TestMethod < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_method.rb#L405
       end
     }
     c2 = Class.new(c1) { define_method(:m) { Proc.new { super() } } }
-    # c2.new.m.call should return :m1, but currently it raise NoMethodError.
-    # see [Bug #4881] and [Bug #3136]
-    assert_raise(NoMethodError) {
-      c2.new.m.call
-    }
+    assert_equal(:m1, c2.new.m.call, 'see [Bug #4881] and [Bug #3136]')
   end
 
   def test_clone
Index: test/-ext-/debug/test_profile_frames.rb
===================================================================
--- test/-ext-/debug/test_profile_frames.rb	(revision 51165)
+++ test/-ext-/debug/test_profile_frames.rb	(revision 51166)
@@ -25,12 +25,12 @@ class TestProfileFrames < Test::Unit::Te https://github.com/ruby/ruby/blob/trunk/test/-ext-/debug/test_profile_frames.rb#L25
     }.resume
 
     labels = [
-      "block (2 levels) in test_profile_frames",
+      "test_profile_frames",
       "zab",
       "baz",
       "bar",
       "foo",
-      "block in test_profile_frames",
+      "test_profile_frames",
     ]
     base_labels = [
       "test_profile_frames",
@@ -41,12 +41,12 @@ class TestProfileFrames < Test::Unit::Te https://github.com/ruby/ruby/blob/trunk/test/-ext-/debug/test_profile_frames.rb#L41
       "test_profile_frames",
     ]
     full_labels = [
-      "block (2 levels) in TestProfileFrames#test_profile_frames",
+      "TestProfileFrames#test_profile_frames",
       "#{obj.inspect}.zab",
       "SampleClassForTestProfileFrames::Sample2#baz",
       "SampleClassForTestProfileFrames.bar",
       "SampleClassForTestProfileFrames#foo",
-      "block in TestProfileFrames#test_profile_frames",
+      "TestProfileFrames#test_profile_frames",
     ]
     classes = [
       TestProfileFrames,

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

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