1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

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.
This commit is contained in:
Yusuke Endoh 2020-07-08 17:32:28 +09:00
parent e4b63202eb
commit da31900d9d
Notes: git 2020-07-28 13:18:35 +09:00
2 changed files with 74 additions and 9 deletions

View file

@ -44,6 +44,7 @@ class TestProfileFrames < Test::Unit::TestCase
}.resume
labels = [
nil,
"test_profile_frames",
"zab",
"baz",
@ -54,6 +55,7 @@ class TestProfileFrames < Test::Unit::TestCase
"test_profile_frames",
]
base_labels = [
nil,
"test_profile_frames",
"zab",
"baz",
@ -64,6 +66,7 @@ class TestProfileFrames < Test::Unit::TestCase
"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
"TestProfileFrames#test_profile_frames",
]
classes = [
Bug::Debug,
TestProfileFrames,
obj,
SampleClassForTestProfileFrames::Sample2,
@ -84,9 +88,10 @@ class TestProfileFrames < Test::Unit::TestCase
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
"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
"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
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]

View file

@ -1360,6 +1360,14 @@ rb_profile_frames(int start, int limit, VALUE *buff, int *lines)
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)
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)
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);
@ -1505,9 +1549,24 @@ rb_profile_frame_qualified_method_name(VALUE frame)
}
}
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);