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:
parent
e4b63202eb
commit
da31900d9d
Notes:
git
2020-07-28 13:18:35 +09:00
2 changed files with 74 additions and 9 deletions
|
@ -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]
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue