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

ruby-changes:31091

From: ko1 <ko1@a...>
Date: Mon, 7 Oct 2013 16:21:18 +0900 (JST)
Subject: [ruby-changes:31091] ko1:r43170 (trunk): * include/ruby/debug.h: add backtrace collecting APIs for profiler.

ko1	2013-10-07 16:21:11 +0900 (Mon, 07 Oct 2013)

  New Revision: 43170

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

  Log:
    * include/ruby/debug.h: add backtrace collecting APIs for profiler.
    * int rb_profile_frames(int start, int limit, VALUE *buff, int *lines);
      Collect information of frame information.
    * VALUE rb_profile_frame_path(VALUE frame);
    * VALUE rb_profile_frame_absolute_path(VALUE frame);
    * VALUE rb_profile_frame_label(VALUE frame);
    * VALUE rb_profile_frame_base_label(VALUE frame);
    * VALUE rb_profile_frame_first_lineno(VALUE frame);
    * VALUE rb_profile_frame_classpath(VALUE frame);
    * VALUE rb_profile_frame_singleton_method_p(VALUE frame);
      Get information about each frame.
      These APIs are designed for profilers, for example, no objectallocation,
      and enough information for profilers.
      In this version, this API collects only collect Ruby level frames.
      This issue will be fixed after Ruby 2.1.
    * vm_backtrace.c: implement above APIs.
    * iseq.c (rb_iseq_klass): return local_iseq's class.

  Modified files:
    trunk/ChangeLog
    trunk/include/ruby/debug.h
    trunk/iseq.c
    trunk/vm_backtrace.c
Index: include/ruby/debug.h
===================================================================
--- include/ruby/debug.h	(revision 43169)
+++ include/ruby/debug.h	(revision 43170)
@@ -24,6 +24,17 @@ RUBY_SYMBOL_EXPORT_BEGIN https://github.com/ruby/ruby/blob/trunk/include/ruby/debug.h#L24
 /* Note: This file contains experimental APIs. */
 /* APIs can be replaced at Ruby 2.0.1 or later */
 
+
+/* profile frames APIs */
+int rb_profile_frames(int start, int limit, VALUE *buff, int *lines);
+VALUE rb_profile_frame_path(VALUE frame);
+VALUE rb_profile_frame_absolute_path(VALUE frame);
+VALUE rb_profile_frame_label(VALUE frame);
+VALUE rb_profile_frame_base_label(VALUE frame);
+VALUE rb_profile_frame_first_lineno(VALUE frame);
+VALUE rb_profile_frame_classpath(VALUE frame);
+VALUE rb_profile_frame_singleton_method_p(VALUE frame);
+
 /* debug inspector APIs */
 typedef struct rb_debug_inspector_struct rb_debug_inspector_t;
 typedef VALUE (*rb_debug_inspector_func_t)(const rb_debug_inspector_t *, void *);
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 43169)
+++ ChangeLog	(revision 43170)
@@ -1,7 +1,31 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Mon Oct  7 16:12:36 2013  Koichi Sasada  <ko1@a...>
+
+	* include/ruby/debug.h: add backtrace collecting APIs for profiler.
+	  * int rb_profile_frames(int start, int limit, VALUE *buff, int *lines);
+	    Collect information of frame information.
+
+	  * VALUE rb_profile_frame_path(VALUE frame);
+	  * VALUE rb_profile_frame_absolute_path(VALUE frame);
+	  * VALUE rb_profile_frame_label(VALUE frame);
+	  * VALUE rb_profile_frame_base_label(VALUE frame);
+	  * VALUE rb_profile_frame_first_lineno(VALUE frame);
+	  * VALUE rb_profile_frame_classpath(VALUE frame);
+	  * VALUE rb_profile_frame_singleton_method_p(VALUE frame);
+	    Get information about each frame.
+
+	  These APIs are designed for profilers, for example, no objectallocation,
+	  and enough information for profilers.
+	  In this version, this API collects only collect Ruby level frames.
+	  This issue will be fixed after Ruby 2.1.
+
+	* vm_backtrace.c: implement above APIs.
+
+	* iseq.c (rb_iseq_klass): return local_iseq's class.
+
 Mon Oct  7 14:26:01 2013  Koichi Sasada  <ko1@a...>
 
 	* proc.c: catch up last commit.
-	  Type of return value of rb_iseq_first_lineno() is now VALUE.
+	  Type of return value of rb_iseq_first_lioneno() is now VALUE.
 
 	* vm_insnhelper.c (argument_error): ditto.
 
Index: iseq.c
===================================================================
--- iseq.c	(revision 43169)
+++ iseq.c	(revision 43170)
@@ -956,7 +956,7 @@ rb_iseq_klass(VALUE self) https://github.com/ruby/ruby/blob/trunk/iseq.c#L956
 {
     rb_iseq_t *iseq;
     GetISeqPtr(self, iseq);
-    return iseq->klass;
+    return iseq->local_iseq->klass;
 }
 
 static
Index: vm_backtrace.c
===================================================================
--- vm_backtrace.c	(revision 43169)
+++ vm_backtrace.c	(revision 43170)
@@ -1200,3 +1200,90 @@ rb_debug_inspector_backtrace_locations(c https://github.com/ruby/ruby/blob/trunk/vm_backtrace.c#L1200
     return dc->backtrace;
 }
 
+int
+rb_profile_frames(int start, int limit, VALUE *buff, int *lines)
+{
+    int i;
+    rb_thread_t *th = GET_THREAD();
+    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 */
+	    if (start > 0) {
+		start--;
+		continue;
+	    }
+
+	    /* record frame info */
+	    buff[i] = cfp->iseq->self;
+	    if (lines) lines[i] = calc_lineno(cfp->iseq, cfp->pc);
+	    i++;
+	}
+	cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
+    }
+
+    return i;
+}
+
+#define frame2iseq(frame) frame
+
+VALUE
+rb_profile_frame_path(VALUE frame)
+{
+    return rb_iseq_path(frame2iseq(frame));
+}
+
+VALUE
+rb_profile_frame_absolute_path(VALUE frame)
+{
+    return rb_iseq_absolute_path(frame2iseq(frame));
+}
+
+VALUE
+rb_profile_frame_label(VALUE frame)
+{
+    return rb_iseq_label(frame2iseq(frame));
+}
+
+VALUE
+rb_profile_frame_base_label(VALUE frame)
+{
+    return rb_iseq_base_label(frame2iseq(frame));
+}
+
+VALUE
+rb_profile_frame_first_lineno(VALUE frame)
+{
+    return rb_iseq_first_lineno(frame2iseq(frame));
+}
+
+VALUE
+rb_profile_frame_classpath(VALUE frame)
+{
+    VALUE klass = rb_iseq_klass(frame2iseq(frame));
+
+    if (klass && !NIL_P(klass)) {
+	if (RB_TYPE_P(klass, T_ICLASS)) {
+	    klass = RBASIC(klass)->klass;
+	}
+	else if (FL_TEST(klass, FL_SINGLETON)) {
+	    klass = rb_ivar_get(klass, id__attached__);
+	}
+	return rb_class_path(klass);
+    }
+    else {
+	return Qnil;
+    }
+}
+
+VALUE
+rb_profile_frame_singleton_method_p(VALUE frame)
+{
+    VALUE klass = rb_iseq_klass(frame2iseq(frame));
+    if (klass && !NIL_P(klass) && FL_TEST(klass, FL_SINGLETON)) {
+	return Qtrue;
+    }
+    else {
+	return Qfalse;
+    }
+}

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

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