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

ruby-changes:62411

From: Yusuke <ko1@a...>
Date: Tue, 28 Jul 2020 13:18:26 +0900 (JST)
Subject: [ruby-changes:62411] da31900d9d (master): vm_backtrace.c: let rb_profile_frames show cfunc frames

https://git.ruby-lang.org/ruby.git/commit/?id=da31900d9d

From da31900d9d9e4e9dcd6381a23dd863b18fe65e3d Mon Sep 17 00:00:00 2001
From: Yusuke Endoh <mame@r...>
Date: Wed, 8 Jul 2020 17:32:28 +0900
Subject: vm_backtrace.c: let rb_profile_frames show cfunc frames

... in addition to normal iseq frames.
It is sometimes useful to point the bottleneck more precisely.

diff --git a/test/-ext-/debug/test_profile_frames.rb b/test/-ext-/debug/test_profile_frames.rb
index 0335267..e015224 100644
--- a/test/-ext-/debug/test_profile_frames.rb
+++ b/test/-ext-/debug/test_profile_frames.rb
@@ -44,6 +44,7 @@ class TestProfileFrames < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/-ext-/debug/test_profile_frames.rb#L44
     }.resume
 
     labels = [
+      nil,
       "test_profile_frames",
       "zab",
       "baz",
@@ -54,6 +55,7 @@ class TestProfileFrames < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/-ext-/debug/test_profile_frames.rb#L55
       "test_profile_frames",
     ]
     base_labels = [
+      nil,
       "test_profile_frames",
       "zab",
       "baz",
@@ -64,6 +66,7 @@ class TestProfileFrames < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/-ext-/debug/test_profile_frames.rb#L66
       "test_profile_frames",
     ]
     full_labels = [
+      "Bug::Debug.profile_frames",
       "TestProfileFrames#test_profile_frames",
       "#{obj.inspect}.zab",
       "SampleClassForTestProfileFrames::Sample2#baz",
@@ -74,6 +77,7 @@ class TestProfileFrames < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/-ext-/debug/test_profile_frames.rb#L77
       "TestProfileFrames#test_profile_frames",
     ]
     classes = [
+      Bug::Debug,
       TestProfileFrames,
       obj,
       SampleClassForTestProfileFrames::Sample2,
@@ -84,9 +88,10 @@ class TestProfileFrames < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/-ext-/debug/test_profile_frames.rb#L88
       TestProfileFrames,
     ]
     singleton_method_p = [
-      false, true, false, true, true, true, false, false, false,
+      true, false, true, false, true, true, true, false, false, false,
     ]
     method_names = [
+      "profile_frames",
       "test_profile_frames",
       "zab",
       "baz",
@@ -97,6 +102,7 @@ class TestProfileFrames < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/-ext-/debug/test_profile_frames.rb#L102
       "test_profile_frames",
     ]
     qualified_method_names = [
+      "Bug::Debug.profile_frames",
       "TestProfileFrames#test_profile_frames",
       "#{obj.inspect}.zab",
       "SampleClassForTestProfileFrames::Sample2#baz",
@@ -106,8 +112,8 @@ class TestProfileFrames < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/-ext-/debug/test_profile_frames.rb#L112
       "SampleClassForTestProfileFrames#foo",
       "TestProfileFrames#test_profile_frames",
     ]
-    paths = [ file=__FILE__, "(eval)", file, file, file, file, file, file ]
-    absolute_paths = [ file, nil, file, file, file, file, file, file ]
+    paths = [ nil, file=__FILE__, "(eval)", file, file, file, file, file, file, nil ]
+    absolute_paths = [ "<cfunc>", file, nil, file, file, file, file, file, file, nil ]
 
     assert_equal(labels.size, frames.size)
 
@@ -120,8 +126,8 @@ class TestProfileFrames < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/-ext-/debug/test_profile_frames.rb#L126
       assert_equal(base_labels[i], base_label, err_msg)
       assert_equal(singleton_method_p[i], singleton_p, err_msg)
       assert_equal(method_names[i], method_name, err_msg)
-      assert_match(qualified_method_names[i], qualified_method_name, err_msg)
-      assert_match(full_labels[i], full_label, err_msg)
+      assert_equal(qualified_method_names[i], qualified_method_name, err_msg)
+      assert_equal(full_labels[i], full_label, err_msg)
       assert_match(classes[i].inspect, classpath, err_msg)
       if label == method_name
         c = classes[i]
diff --git a/vm_backtrace.c b/vm_backtrace.c
index ac77c6d..04b696c 100644
--- a/vm_backtrace.c
+++ b/vm_backtrace.c
@@ -1360,6 +1360,14 @@ rb_profile_frames(int start, int limit, VALUE *buff, int *lines) https://github.com/ruby/ruby/blob/trunk/vm_backtrace.c#L1360
 
 	    i++;
 	}
+        else {
+	    cme = rb_vm_frame_method_entry(cfp);
+	    if (cme && cme->def->type == VM_METHOD_TYPE_CFUNC) {
+		buff[i] = (VALUE)cme;
+                if (lines) lines[i] = 0;
+                i++;
+            }
+        }
 	cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
     }
 
@@ -1399,9 +1407,42 @@ rb_profile_frame_path(VALUE frame) https://github.com/ruby/ruby/blob/trunk/vm_backtrace.c#L1407
     return iseq ? rb_iseq_path(iseq) : Qnil;
 }
 
+static const rb_callable_method_entry_t *
+cframe(VALUE frame)
+{
+    if (frame == Qnil) return NULL;
+
+    if (RB_TYPE_P(frame, T_IMEMO)) {
+	switch (imemo_type(frame)) {
+	  case imemo_ment:
+            {
+		const rb_callable_method_entry_t *cme = (rb_callable_method_entry_t *)frame;
+		switch (cme->def->type) {
+		  case VM_METHOD_TYPE_CFUNC:
+		    return cme;
+		  default:
+		    return NULL;
+		}
+            }
+          default:
+            return NULL;
+        }
+    }
+
+    return NULL;
+}
+
 VALUE
 rb_profile_frame_absolute_path(VALUE frame)
 {
+    if (cframe(frame)) {
+        static VALUE cfunc_str = Qfalse;
+        if (!cfunc_str) {
+            cfunc_str = rb_str_new_literal("<cfunc>");
+            rb_gc_register_mark_object(cfunc_str);
+        }
+        return cfunc_str;
+    }
     const rb_iseq_t *iseq = frame2iseq(frame);
     return iseq ? rb_iseq_realpath(iseq) : Qnil;
 }
@@ -1479,15 +1520,18 @@ rb_profile_frame_singleton_method_p(VALUE frame) https://github.com/ruby/ruby/blob/trunk/vm_backtrace.c#L1520
 VALUE
 rb_profile_frame_method_name(VALUE frame)
 {
+    const rb_callable_method_entry_t *cme = cframe(frame);
+    if (cme) {
+        ID mid = cme->def->original_id;
+        return id2str(mid);
+    }
     const rb_iseq_t *iseq = frame2iseq(frame);
     return iseq ? rb_iseq_method_name(iseq) : Qnil;
 }
 
-VALUE
-rb_profile_frame_qualified_method_name(VALUE frame)
+static VALUE
+qualified_method_name(VALUE frame, VALUE method_name)
 {
-    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);
@@ -1506,8 +1550,23 @@ rb_profile_frame_qualified_method_name(VALUE frame) https://github.com/ruby/ruby/blob/trunk/vm_backtrace.c#L1550
 }
 
 VALUE
+rb_profile_frame_qualified_method_name(VALUE frame)
+{
+    VALUE method_name = rb_profile_frame_method_name(frame);
+
+    return qualified_method_name(frame, method_name);
+}
+
+VALUE
 rb_profile_frame_full_label(VALUE frame)
 {
+    const rb_callable_method_entry_t *cme = cframe(frame);
+    if (cme) {
+        ID mid = cme->def->original_id;
+        VALUE method_name = id2str(mid);
+        return qualified_method_name(frame, method_name);
+    }
+
     VALUE label = rb_profile_frame_label(frame);
     VALUE base_label = rb_profile_frame_base_label(frame);
     VALUE qualified_method_name = rb_profile_frame_qualified_method_name(frame);
-- 
cgit v0.10.2


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

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