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

ruby-changes:32456

From: ko1 <ko1@a...>
Date: Thu, 9 Jan 2014 19:13:10 +0900 (JST)
Subject: [ruby-changes:32456] ko1:r44535 (trunk): * vm.c (rb_vm_pop_cfunc_frame): added. It cares c_return event.

ko1	2014-01-09 19:12:59 +0900 (Thu, 09 Jan 2014)

  New Revision: 44535

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

  Log:
    * vm.c (rb_vm_pop_cfunc_frame): added.  It cares c_return event.
      The patch base by drkaes (Stefan Kaes).
      [Bug #9321]
    * variable.c (rb_mod_const_missing): use rb_vm_pop_cfunc_frame()
      instead of rb_frame_pop().
    * vm_eval.c (raise_method_missing): ditto.
    * vm_eval.c (rb_iterate): ditto.
    * internal.h (rb_vm_pop_cfunc_frame): add decl.
    * test/ruby/test_settracefunc.rb: add tests.
      provided by drkaes (Stefan Kaes).
    * vm.c, eval.c, include/ruby/intern.h (rb_frame_pop):
      move definition of rb_frame_pop() and deprecate it.
      It doesn't care about `return' events.

  Modified files:
    trunk/ChangeLog
    trunk/eval.c
    trunk/include/ruby/intern.h
    trunk/internal.h
    trunk/test/ruby/test_settracefunc.rb
    trunk/variable.c
    trunk/vm.c
    trunk/vm_eval.c
Index: include/ruby/intern.h
===================================================================
--- include/ruby/intern.h	(revision 44534)
+++ include/ruby/intern.h	(revision 44535)
@@ -939,11 +939,14 @@ VALUE rb_mod_remove_cvar(VALUE, VALUE); https://github.com/ruby/ruby/blob/trunk/include/ruby/intern.h#L939
 ID rb_frame_callee(void);
 VALUE rb_str_succ(VALUE);
 VALUE rb_time_succ(VALUE);
-void rb_frame_pop(void);
 int rb_frame_method_id_and_class(ID *idp, VALUE *klassp);
 VALUE rb_make_backtrace(void);
 VALUE rb_make_exception(int, VALUE*);
 
+/* deprecated */
+DEPRECATED(void rb_frame_pop(void));
+
+
 RUBY_SYMBOL_EXPORT_END
 
 #if defined(__cplusplus)
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 44534)
+++ ChangeLog	(revision 44535)
@@ -1,3 +1,25 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Thu Jan  9 19:12:37 2014  Koichi Sasada  <ko1@a...>
+
+	* vm.c (rb_vm_pop_cfunc_frame): added.  It cares c_return event.
+	  The patch base by drkaes (Stefan Kaes).
+	  [Bug #9321]
+
+	* variable.c (rb_mod_const_missing): use rb_vm_pop_cfunc_frame()
+	  instead of rb_frame_pop().
+
+	* vm_eval.c (raise_method_missing): ditto.
+
+	* vm_eval.c (rb_iterate): ditto.
+
+	* internal.h (rb_vm_pop_cfunc_frame): add decl.
+
+	* test/ruby/test_settracefunc.rb: add tests.
+	  provided by drkaes (Stefan Kaes).
+
+	* vm.c, eval.c, include/ruby/intern.h (rb_frame_pop): 
+	  move definition of rb_frame_pop() and deprecate it.
+	  It doesn't care about `return' events.
+
 Thu Jan  9 17:40:28 2014  NAKAMURA Usaku  <usa@r...>
 
 	* hash.c (rb_any_hash): should treat the return value of rb_objid_hash()
Index: variable.c
===================================================================
--- variable.c	(revision 44534)
+++ variable.c	(revision 44535)
@@ -1518,7 +1518,7 @@ const_missing(VALUE klass, ID id) https://github.com/ruby/ruby/blob/trunk/variable.c#L1518
 VALUE
 rb_mod_const_missing(VALUE klass, VALUE name)
 {
-    rb_frame_pop(); /* pop frame for "const_missing" */
+    rb_vm_pop_cfunc_frame();
     uninitialized_constant(klass, rb_to_id(name));
 
     UNREACHABLE;
Index: vm_eval.c
===================================================================
--- vm_eval.c	(revision 44534)
+++ vm_eval.c	(revision 44535)
@@ -686,7 +686,7 @@ raise_method_missing(rb_thread_t *th, in https://github.com/ruby/ruby/blob/trunk/vm_eval.c#L686
     {
 	exc = make_no_method_exception(exc, format, obj, argc, argv);
 	if (!(last_call_status & NOEX_MISSING)) {
-	    th->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp);
+	    rb_vm_pop_cfunc_frame();
 	}
 	rb_exc_raise(exc);
     }
@@ -1087,13 +1087,12 @@ rb_iterate(VALUE (* it_proc) (VALUE), VA https://github.com/ruby/ruby/blob/trunk/vm_eval.c#L1087
 #if VMDEBUG
 		    printf("skipped frame: %s\n", vm_frametype_name(th->cfp));
 #endif
-		    if (UNLIKELY(VM_FRAME_TYPE(th->cfp) == VM_FRAME_MAGIC_CFUNC)) {
-			const rb_method_entry_t *me = th->cfp->me;
-			EXEC_EVENT_HOOK(th, RUBY_EVENT_C_RETURN, th->cfp->self, me->called_id, me->klass, Qnil);
-			RUBY_DTRACE_CMETHOD_RETURN_HOOK(th, me->klass, me->called_id);
+		    if (VM_FRAME_TYPE(th->cfp) != VM_FRAME_MAGIC_CFUNC) {
+			vm_pop_frame(th);
+		    }
+		    else { /* unlikely path */
+			rb_vm_pop_cfunc_frame();
 		    }
-
-		    th->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp);
 		}
 	    }
 	    else{
Index: eval.c
===================================================================
--- eval.c	(revision 44534)
+++ eval.c	(revision 44535)
@@ -1010,13 +1010,6 @@ prev_frame_func(void) https://github.com/ruby/ruby/blob/trunk/eval.c#L1010
     return frame_func_id(prev_cfp);
 }
 
-void
-rb_frame_pop(void)
-{
-    rb_thread_t *th = GET_THREAD();
-    th->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp);
-}
-
 /*
  *  call-seq:
  *     append_features(mod)   -> mod
Index: internal.h
===================================================================
--- internal.h	(revision 44534)
+++ internal.h	(revision 44535)
@@ -764,6 +764,7 @@ void rb_vm_inc_const_missing_count(void) https://github.com/ruby/ruby/blob/trunk/internal.h#L764
 void rb_thread_mark(void *th);
 const void **rb_vm_get_insns_address_table(void);
 VALUE rb_sourcefilename(void);
+void rb_vm_pop_cfunc_frame(void);
 
 /* vm_dump.c */
 void rb_vm_bugreport(void);
Index: vm.c
===================================================================
--- vm.c	(revision 44534)
+++ vm.c	(revision 44535)
@@ -277,6 +277,24 @@ vm_get_ruby_level_caller_cfp(rb_thread_t https://github.com/ruby/ruby/blob/trunk/vm.c#L277
     return 0;
 }
 
+void
+rb_vm_pop_cfunc_frame(void)
+{
+    rb_thread_t *th = GET_THREAD();
+    const rb_method_entry_t *me = th->cfp->me;
+    EXEC_EVENT_HOOK(th, RUBY_EVENT_C_RETURN, th->cfp->self, me->called_id, me->klass, Qnil);
+    RUBY_DTRACE_CMETHOD_RETURN_HOOK(th, me->klass, me->called_id);
+    vm_pop_frame(th);
+}
+
+/* obsolete */
+void
+rb_frame_pop(void)
+{
+    rb_thread_t *th = GET_THREAD();
+    vm_pop_frame(th);
+}
+
 /* at exit */
 
 void
Index: test/ruby/test_settracefunc.rb
===================================================================
--- test/ruby/test_settracefunc.rb	(revision 44534)
+++ test/ruby/test_settracefunc.rb	(revision 44535)
@@ -1066,4 +1066,88 @@ class TestSetTraceFunc < Test::Unit::Tes https://github.com/ruby/ruby/blob/trunk/test/ruby/test_settracefunc.rb#L1066
       :b_return
     ], events)
   end
+
+  def test_const_missing
+    bug59398 = '[ruby-core:59398]'
+    events = []
+    assert !defined?(MISSING_CONSTANT_59398)
+    TracePoint.new(:c_call, :c_return, :call, :return){|tp|
+      next unless tp.defined_class == Module
+      # rake/ext/module.rb aliases :const_missing and Ruby uses the aliased name
+      # but this only happens when running the full test suite
+      events << [tp.event,tp.method_id] if tp.method_id == :const_missing || tp.method_id == :rake_original_const_missing
+    }.enable{
+      MISSING_CONSTANT_59398 rescue nil
+    }
+    if events.map{|e|e[1]}.include?(:rake_original_const_missing)
+      assert_equal([
+        [:call, :const_missing],
+        [:c_call, :rake_original_const_missing],
+        [:c_return, :rake_original_const_missing],
+        [:return, :const_missing],
+      ], events, bug59398)
+    else
+      assert_equal([
+        [:c_call, :const_missing],
+        [:c_return, :const_missing]
+      ], events, bug59398)
+    end
+  end
+
+  class AliasedRubyMethod
+    def foo; 1; end;
+    alias bar foo
+  end
+  def test_aliased_ruby_method
+    events = []
+    aliased = AliasedRubyMethod.new
+    TracePoint.new(:call, :return){|tp|
+      events << [tp.event, tp.method_id]
+    }.enable{
+      aliased.bar
+    }
+    assert_equal([
+      [:call, :foo],
+      [:return, :foo]
+    ], events, "should use original method name for tracing ruby methods")
+  end
+  class AliasedCMethod < Hash
+    alias original_size size
+    def size; original_size; end
+  end
+
+  def test_aliased_c_method
+    events = []
+    aliased = AliasedCMethod.new
+    TracePoint.new(:call, :return, :c_call, :c_return){|tp|
+      events << [tp.event, tp.method_id]
+    }.enable{
+      aliased.size
+    }
+    assert_equal([
+      [:call, :size],
+      [:c_call, :original_size],
+      [:c_return, :original_size],
+      [:return, :size]
+    ], events, "should use alias method name for tracing c methods")
+  end
+
+  def test_method_missing
+    bug59398 = '[ruby-core:59398]'
+    events = []
+    assert !respond_to?(:missing_method_59398)
+    TracePoint.new(:c_call, :c_return, :call, :return){|tp|
+      next unless tp.defined_class == BasicObject
+      # rake/ext/module.rb aliases :const_missing and Ruby uses the aliased name
+      # but this only happens when running the full test suite
+      events << [tp.event,tp.method_id] if tp.method_id == :method_missing
+    }.enable{
+      missing_method_59398 rescue nil
+    }
+    assert_equal([
+      [:c_call, :method_missing],
+      [:c_return, :method_missing]
+    ], events, bug59398)
+  end
+
 end

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

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