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

ruby-changes:26042

From: tenderlove <ko1@a...>
Date: Sat, 1 Dec 2012 11:25:50 +0900 (JST)
Subject: [ruby-changes:26042] tenderlove:r38099 (trunk): * variable.c (rb_class_path_no_cache): add a function to get the class

tenderlove	2012-12-01 11:13:06 +0900 (Sat, 01 Dec 2012)

  New Revision: 38099

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

  Log:
    * variable.c (rb_class_path_no_cache): add a function to get the class
      path without caching the computed path. Some classes are frozen, and
      will raise an exception without this.
    
    * probes.d (cmethod-entry, cmethod-return): separate cmethods from
      regular methods to match set trace func.
    
    * probes_helper.h: refactor macros.  Fix probes to avoid calling
      #inspect when profiling.
    
    * insns.def: update for use with new macros.
    
    * vm_eval.c: ditto
    
    * vm_insnhelper.c: ditto
    
    * test/dtrace/test_singleton_function.rb: fix test for new output.
    
    * test/dtrace/test_cmethod.rb: test the cmethod probes.

  Added files:
    trunk/test/dtrace/test_cmethod.rb
  Modified files:
    trunk/ChangeLog
    trunk/insns.def
    trunk/probes.d
    trunk/probes_helper.h
    trunk/test/dtrace/test_singleton_function.rb
    trunk/variable.c
    trunk/vm_eval.c
    trunk/vm_insnhelper.c

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 38098)
+++ ChangeLog	(revision 38099)
@@ -1,3 +1,25 @@
+Sat Dec  1 11:09:12 2012  Aaron Patterson <aaron@t...>
+
+	* variable.c (rb_class_path_no_cache): add a function to get the class
+	  path without caching the computed path. Some classes are frozen, and
+	  will raise an exception without this.
+	
+	* probes.d (cmethod-entry, cmethod-return): separate cmethods from
+	  regular methods to match set trace func.
+	
+	* probes_helper.h: refactor macros.  Fix probes to avoid calling
+	  #inspect when profiling.
+
+	* insns.def: update for use with new macros.
+
+	* vm_eval.c: ditto
+
+	* vm_insnhelper.c: ditto
+
+	* test/dtrace/test_singleton_function.rb: fix test for new output.
+
+	* test/dtrace/test_cmethod.rb: test the cmethod probes.
+
 Sat Dec  1 09:44:16 2012  Eric Hodel  <drbrain@s...>
 
 	* test/rdoc/test_rdoc_options.rb:  Windows drive letters are
Index: insns.def
===================================================================
--- insns.def	(revision 38098)
+++ insns.def	(revision 38099)
@@ -843,35 +843,27 @@
 {
     rb_event_flag_t flag = (rb_event_flag_t)nf;
 
-    if (RUBY_DTRACE_METHOD_ENTRY_ENABLED()) {
-        if (flag == RUBY_EVENT_CALL || flag == RUBY_EVENT_C_CALL) {
-          VALUE klass;
-          ID called_id;
+    if (RUBY_DTRACE_METHOD_ENTRY_ENABLED() ||
+        RUBY_DTRACE_METHOD_RETURN_ENABLED() ||
+        RUBY_DTRACE_CMETHOD_ENTRY_ENABLED() ||
+        RUBY_DTRACE_CMETHOD_RETURN_ENABLED()) {
 
-          rb_thread_method_id_and_class(th, &called_id, &klass);
-
-          RUBY_DTRACE_METHOD_ENTRY(
-                  RSTRING_PTR(rb_inspect(klass)),
-                  rb_id2name(called_id),
-                  rb_sourcefile(),
-                  rb_sourceline());
+        switch(flag) {
+          case RUBY_EVENT_CALL:
+            RUBY_DTRACE_METHOD_ENTRY_HOOK(th, 0, 0);
+            break;
+          case RUBY_EVENT_C_CALL:
+            RUBY_DTRACE_CMETHOD_ENTRY_HOOK(th, 0, 0);
+            break;
+          case RUBY_EVENT_RETURN:
+            RUBY_DTRACE_METHOD_RETURN_HOOK(th, 0, 0);
+            break;
+          case RUBY_EVENT_C_RETURN:
+            RUBY_DTRACE_CMETHOD_RETURN_HOOK(th, 0, 0);
+            break;
         }
     }
-    if (RUBY_DTRACE_METHOD_RETURN_ENABLED()) {
-        if (flag == RUBY_EVENT_RETURN || flag == RUBY_EVENT_C_RETURN) {
-          VALUE klass;
-          ID called_id;
 
-          rb_thread_method_id_and_class(th, &called_id, &klass);
-
-          RUBY_DTRACE_METHOD_RETURN(
-                  RSTRING_PTR(rb_inspect(klass)),
-                  rb_id2name(called_id),
-                  rb_sourcefile(),
-                  rb_sourceline());
-        }
-    }
-
     EXEC_EVENT_HOOK(th, flag, GET_SELF(), 0, 0 /* id and klass are resolved at callee */,
 		    (flag & RUBY_EVENT_RETURN | RUBY_EVENT_B_RETURN) ? TOPN(0) : Qundef);
 }
Index: variable.c
===================================================================
--- variable.c	(revision 38098)
+++ variable.c	(revision 38099)
@@ -211,8 +211,10 @@
     return path;
 }
 
+typedef VALUE (*path_cache_func)(VALUE obj, ID id, VALUE val);
+
 static VALUE
-rb_tmp_class_path(VALUE klass, int *permanent)
+rb_tmp_class_path(VALUE klass, int *permanent, path_cache_func cache_path)
 {
     VALUE path = classname(klass, permanent);
     st_data_t n = (st_data_t)path;
@@ -233,12 +235,17 @@
 		s = "Module";
 	    }
 	    else {
-		s = rb_class2name(RBASIC(klass)->klass);
+		int perm;
+		VALUE path;
+
+		path = rb_tmp_class_path(RBASIC(klass)->klass, &perm, cache_path);
+		s = RSTRING_PTR(path);
 	    }
 	}
 	path = rb_sprintf("#<%s:%p>", s, (void*)klass);
 	OBJ_FREEZE(path);
-	rb_ivar_set(klass, tmp_classpath, path);
+
+	cache_path(klass, tmp_classpath, path);
 	*permanent = 0;
 
 	return path;
@@ -249,11 +256,26 @@
 rb_class_path(VALUE klass)
 {
     int permanent;
-    VALUE path = rb_tmp_class_path(klass, &permanent);
+    VALUE path = rb_tmp_class_path(klass, &permanent, rb_ivar_set);
     if (!NIL_P(path)) path = rb_str_dup(path);
     return path;
 }
 
+static VALUE
+null_cache(VALUE obj, ID id, VALUE val)
+{
+    return Qnil;
+}
+
+VALUE
+rb_class_path_no_cache(VALUE klass)
+{
+    int permanent;
+    VALUE path = rb_tmp_class_path(klass, &permanent, null_cache);
+    if (!NIL_P(path)) path = rb_str_dup(path);
+    return path;
+}
+
 void
 rb_set_class_path_string(VALUE klass, VALUE under, VALUE name)
 {
@@ -265,7 +287,7 @@
     }
     else {
 	int permanent;
-	str = rb_str_dup(rb_tmp_class_path(under, &permanent));
+	str = rb_str_dup(rb_tmp_class_path(under, &permanent, rb_ivar_set));
 	rb_str_cat2(str, "::");
 	rb_str_append(str, name);
 	OBJ_FREEZE(str);
@@ -288,7 +310,7 @@
     }
     else {
 	int permanent;
-	str = rb_str_dup(rb_tmp_class_path(under, &permanent));
+	str = rb_str_dup(rb_tmp_class_path(under, &permanent, rb_ivar_set));
 	rb_str_cat2(str, "::");
 	rb_str_cat2(str, name);
 	if (!permanent) {
Index: vm_eval.c
===================================================================
--- vm_eval.c	(revision 38098)
+++ vm_eval.c	(revision 38099)
@@ -55,7 +55,7 @@
 {
     VALUE val;
 
-    RUBY_DTRACE_METHOD_ENTRY_HOOK(ci->defined_class, ci->mid);
+    RUBY_DTRACE_CMETHOD_ENTRY_HOOK(th, ci->defined_class, ci->mid);
     EXEC_EVENT_HOOK(th, RUBY_EVENT_C_CALL, ci->recv, ci->mid, ci->defined_class, Qnil);
     {
 	rb_control_frame_t *reg_cfp = th->cfp;
@@ -85,7 +85,7 @@
 	}
     }
     EXEC_EVENT_HOOK(th, RUBY_EVENT_C_RETURN, ci->recv, ci->mid, ci->defined_class, val);
-    RUBY_DTRACE_METHOD_RETURN_HOOK(th, ci->defined_class, ci->mid);
+    RUBY_DTRACE_CMETHOD_RETURN_HOOK(th, ci->defined_class, ci->mid);
 
     return val;
 }
@@ -103,7 +103,7 @@
     ID mid = ci->mid;
     rb_block_t *blockptr = ci->blockptr;
 
-    RUBY_DTRACE_METHOD_ENTRY_HOOK(defined_class, mid);
+    RUBY_DTRACE_CMETHOD_ENTRY_HOOK(th, defined_class, mid);
     EXEC_EVENT_HOOK(th, RUBY_EVENT_C_CALL, recv, mid, defined_class, Qnil);
     {
 	rb_control_frame_t *reg_cfp = th->cfp;
@@ -123,7 +123,7 @@
 	vm_pop_frame(th);
     }
     EXEC_EVENT_HOOK(th, RUBY_EVENT_C_RETURN, recv, mid, defined_class, val);
-    RUBY_DTRACE_METHOD_RETURN_HOOK(th, defined_class, mid);
+    RUBY_DTRACE_CMETHOD_RETURN_HOOK(th, defined_class, mid);
 
     return val;
 }
@@ -1015,7 +1015,7 @@
 		    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_METHOD_RETURN_HOOK(th, me->klass, me->called_id);
+			RUBY_DTRACE_CMETHOD_RETURN_HOOK(th, me->klass, me->called_id);
 		    }
 
 		    th->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp);
Index: probes.d
===================================================================
--- probes.d	(revision 38098)
+++ probes.d	(revision 38099)
@@ -4,6 +4,9 @@
   probe method__entry(const char *, const char *, const char *, int);
   probe method__return(const char *, const char *, const char *, int);
 
+  probe cmethod__entry(const char *, const char *, const char *, int);
+  probe cmethod__return(const char *, const char *, const char *, int);
+
   probe require__entry(const char *, const char *, int);
   probe require__return(const char *);
 
Index: probes_helper.h
===================================================================
--- probes_helper.h	(revision 38098)
+++ probes_helper.h	(revision 38099)
@@ -4,23 +4,11 @@
 #include "ruby/ruby.h"
 #include "probes.h"
 
-#define RUBY_DTRACE_METHOD_ENTRY_HOOK(klass, id) \
-    if (RUBY_DTRACE_METHOD_ENTRY_ENABLED()) { \
-	const char * classname  = rb_class2name((klass)); \
-	const char * methodname = rb_id2name((id)); \
-	const char * filename   = rb_sourcefile(); \
-	if (classname && methodname && filename) { \
-	    RUBY_DTRACE_METHOD_ENTRY( \
-		    classname, \
-		    methodname, \
-		    filename, \
-		    rb_sourceline()); \
-	} \
-    } \
+VALUE rb_class_path_no_cache(VALUE _klass);
 
-#define RUBY_DTRACE_METHOD_RETURN_HOOK(th, klass, id) \
-    if (RUBY_DTRACE_METHOD_RETURN_ENABLED()) { \
-	VALUE _klass = (klass); \
+#define RUBY_DTRACE_HOOK(name, th, klazz, id) \
+    if (RUBY_DTRACE_##name##_ENABLED()) { \
+	VALUE _klass = (klazz); \
 	VALUE _id = (id); \
 	const char * classname; \
 	const char * methodname; \
@@ -28,16 +16,49 @@
 	if (!_klass) { \
 	    rb_thread_method_id_and_class((th), &_id, &_klass); \
 	} \
-	classname  = rb_class2name(_klass); \
-	methodname = rb_id2name(_id); \
-	filename   = rb_sourcefile(); \
-	if (classname && methodname && filename) { \
-	    RUBY_DTRACE_METHOD_RETURN( \
-		    classname, \
-		    methodname, \
-		    filename, \
-		    rb_sourceline()); \
+	if (_klass) { \
+	    if (RB_TYPE_P(_klass, T_ICLASS)) { \
+		_klass = RBASIC(_klass)->klass; \
+	    } \
+	    else if (FL_TEST(_klass, FL_SINGLETON)) { \
+		_klass = rb_iv_get(_klass, "__attached__"); \
+	    } \
+	    switch(TYPE(_klass)) { \
+		case T_CLASS: \
+		case T_ICLASS: \
+		case T_MODULE: \
+		{ \
+		    VALUE _name = rb_class_path_no_cache(_klass); \
+		    if (!NIL_P(_name)) { \
+		        classname = StringValuePtr(_name); \
+		    } else { \
+		        classname = "<unknown>"; \
+		    } \
+		    methodname = rb_id2name(_id); \
+		    filename   = rb_sourcefile(); \
+		    if (classname && methodname && filename) { \
+		        RUBY_DTRACE_##name( \
+				classname, \
+				methodname, \
+				filename, \
+				rb_sourceline()); \
+		    } \
+		    break; \
+		} \
+	    } \
 	} \
     } \
 
+#define RUBY_DTRACE_METHOD_ENTRY_HOOK(th, klass, id) \
+    RUBY_DTRACE_HOOK(METHOD_ENTRY, th, klass, id)
+
+#define RUBY_DTRACE_METHOD_RETURN_HOOK(th, klass, id) \
+    RUBY_DTRACE_HOOK(METHOD_RETURN, th, klass, id)
+
+#define RUBY_DTRACE_CMETHOD_ENTRY_HOOK(th, klass, id) \
+    RUBY_DTRACE_HOOK(CMETHOD_ENTRY, th, klass, id)
+
+#define RUBY_DTRACE_CMETHOD_RETURN_HOOK(th, klass, id) \
+    RUBY_DTRACE_HOOK(CMETHOD_RETURN, th, klass, id)
+
 #endif /* RUBY_PROBES_HELPER_H */
Index: vm_insnhelper.c
===================================================================
--- vm_insnhelper.c	(revision 38098)
+++ vm_insnhelper.c	(revision 38099)
@@ -1449,7 +1449,7 @@
     rb_block_t *blockptr = ci->blockptr;
     int argc = ci->argc;
 
-    RUBY_DTRACE_METHOD_ENTRY_HOOK(me->klass, me->called_id);
+    RUBY_DTRACE_CMETHOD_ENTRY_HOOK(th, me->klass, me->called_id);
     EXEC_EVENT_HOOK(th, RUBY_EVENT_C_CALL, recv, me->called_id, me->klass, Qundef);
 
     vm_push_frame(th, 0, VM_FRAME_MAGIC_CFUNC, recv, defined_class,
@@ -1468,7 +1468,7 @@
     vm_pop_frame(th);
 
     EXEC_EVENT_HOOK(th, RUBY_EVENT_C_RETURN, recv, me->called_id, me->klass, val);
-    RUBY_DTRACE_METHOD_RETURN_HOOK(th, me->klass, me->called_id);
+    RUBY_DTRACE_CMETHOD_RETURN_HOOK(th, me->klass, me->called_id);
 
     return val;
 }
@@ -1516,7 +1516,7 @@
 
     if (len >= 0) rb_check_arity(ci->argc, len, len);
 
-    RUBY_DTRACE_METHOD_ENTRY_HOOK(me->klass, me->called_id);
+    RUBY_DTRACE_CMETHOD_ENTRY_HOOK(th, me->klass, me->called_id);
     EXEC_EVENT_HOOK(th, RUBY_EVENT_C_CALL, recv, me->called_id, me->klass, Qnil);
 
     if (!(ci->me->flag & NOEX_PROTECTED) &&
@@ -1526,7 +1526,7 @@
     val = vm_call_cfunc_latter(th, reg_cfp, ci);
 
     EXEC_EVENT_HOOK(th, RUBY_EVENT_C_RETURN, recv, me->called_id, me->klass, val);
-    RUBY_DTRACE_METHOD_RETURN_HOOK(th, me->klass, me->called_id);
+    RUBY_DTRACE_CMETHOD_RETURN_HOOK(th, me->klass, me->called_id);
 
     return val;
 }
@@ -1575,7 +1575,7 @@
     rb_proc_t *proc;
     VALUE val;
 
-    RUBY_DTRACE_METHOD_ENTRY_HOOK(ci->me->klass, ci->me->called_id);
+    RUBY_DTRACE_METHOD_ENTRY_HOOK(th, ci->me->klass, ci->me->called_id);
     EXEC_EVENT_HOOK(th, RUBY_EVENT_CALL, ci->recv, ci->me->called_id, ci->me->klass, Qnil);
 
     /* control block frame */
Index: test/dtrace/test_cmethod.rb
===================================================================
--- test/dtrace/test_cmethod.rb	(revision 0)
+++ test/dtrace/test_cmethod.rb	(revision 38099)
@@ -0,0 +1,49 @@
+require 'dtrace/helper'
+
+module DTrace
+  class TestCMethod < TestCase
+    def test_entry
+      probe = <<-eoprobe
+ruby$target:::cmethod-entry
+{
+  printf("%s %s %s %d\\n", copyinstr(arg0), copyinstr(arg1), copyinstr(arg2), arg3);
+}
+      eoprobe
+
+      trap_probe(probe, ruby_program) { |d_file, rb_file, probes|
+	foo_calls = probes.map { |line| line.split }.find_all { |row|
+	  row[1] == 'times'
+	}
+
+	assert_equal 1, foo_calls.length
+      }
+    end
+
+    def test_exit
+      probe = <<-eoprobe
+ruby$target:::cmethod-return
+{
+  printf("%s %s %s %d\\n", copyinstr(arg0), copyinstr(arg1), copyinstr(arg2), arg3);
+}
+      eoprobe
+
+      trap_probe(probe, ruby_program) { |d_file, rb_file, probes|
+	foo_calls = probes.map { |line| line.split }.find_all { |row|
+	  row[1] == 'times'
+	}
+
+	assert_equal 1, foo_calls.length
+      }
+    end
+
+    def ruby_program
+      <<-eoruby
+      class Foo
+	def self.foo; end
+      end
+      10.times { Foo.foo }
+      eoruby
+    end
+  end
+end if defined?(DTrace::TestCase)
+

Property changes on: test/dtrace/test_cmethod.rb
___________________________________________________________________
Added: svn:eol-style
   + LF

Index: test/dtrace/test_singleton_function.rb
===================================================================
--- test/dtrace/test_singleton_function.rb	(revision 38098)
+++ test/dtrace/test_singleton_function.rb	(revision 38099)
@@ -13,7 +13,7 @@
 
       trap_probe(probe, ruby_program) { |d_file, rb_file, probes|
 	foo_calls = probes.map { |line| line.split }.find_all { |row|
-	  row.first == '#<Class:Foo>'  && row[1] == 'foo'
+	  row.first == 'Foo'  && row[1] == 'foo'
 	}
 
 	assert_equal 10, foo_calls.length
@@ -33,7 +33,7 @@
 
       trap_probe(probe, ruby_program) { |d_file, rb_file, probes|
 	foo_calls = probes.map { |line| line.split }.find_all { |row|
-	  row.first == '#<Class:Foo>'  && row[1] == 'foo'
+	  row.first == 'Foo'  && row[1] == 'foo'
 	}
 
 	assert_equal 10, foo_calls.length

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

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