aboutsummaryrefslogtreecommitdiffstats
path: root/vm_backtrace.c
diff options
context:
space:
mode:
authorko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-10-07 07:21:11 +0000
committerko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-10-07 07:21:11 +0000
commit774bff0adb44eaf5c806afb1bf9eff65d26b2f1f (patch)
treece65433d0c9fff8d7c1003478966ada7344c0cb4 /vm_backtrace.c
parent6531e12e0beaf5e730592d7cd1bb9eab96140433 (diff)
downloadruby-774bff0adb44eaf5c806afb1bf9eff65d26b2f1f.tar.gz
* 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. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@43170 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'vm_backtrace.c')
-rw-r--r--vm_backtrace.c87
1 files changed, 87 insertions, 0 deletions
diff --git a/vm_backtrace.c b/vm_backtrace.c
index 3945993e42..b4f16f68fc 100644
--- a/vm_backtrace.c
+++ b/vm_backtrace.c
@@ -1200,3 +1200,90 @@ rb_debug_inspector_backtrace_locations(const rb_debug_inspector_t *dc)
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;
+ }
+}