Skip to content

Commit f6e1e52

Browse files
committed
Make frames with different files distinct for Firefox profiler categories
1 parent 154737b commit f6e1e52

File tree

2 files changed

+49
-27
lines changed

2 files changed

+49
-27
lines changed

ext/vernier/vernier.cc

Lines changed: 49 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -83,27 +83,35 @@ struct FuncInfo {
8383
return StringValueCStr(label);
8484
}
8585

86-
static const char *file_cstr(VALUE frame) {
87-
VALUE file = rb_profile_frame_absolute_path(frame);
88-
if (NIL_P(file))
89-
file = rb_profile_frame_path(frame);
86+
static const char *file_cstr(VALUE file) {
9087
if (NIL_P(file)) {
9188
return "(nil)";
9289
} else {
9390
return StringValueCStr(file);
9491
}
9592
}
9693

94+
static VALUE get_frame_file(VALUE frame) {
95+
VALUE file = rb_profile_frame_absolute_path(frame);
96+
if (NIL_P(file)) file = rb_profile_frame_path(frame);
97+
return file;
98+
}
99+
97100
static int first_lineno_int(VALUE frame) {
98101
VALUE first_lineno = rb_profile_frame_first_lineno(frame);
99102
return NIL_P(first_lineno) ? 0 : FIX2INT(first_lineno);
100103
}
101104

102105
FuncInfo(VALUE frame) :
103106
label(label_cstr(frame)),
104-
file(file_cstr(frame)),
107+
file(file_cstr(is_refined_frame(frame) ? Qnil : get_frame_file(frame))),
105108
first_lineno(first_lineno_int(frame)) { }
106109

110+
static bool is_refined_frame(VALUE frame) {
111+
VALUE label = rb_profile_frame_full_label(frame);
112+
return NIL_P(label);
113+
}
114+
107115
std::string label;
108116
std::string file;
109117
int first_lineno;
@@ -116,13 +124,25 @@ bool operator==(const FuncInfo& lhs, const FuncInfo& rhs) noexcept {
116124
lhs.first_lineno == rhs.first_lineno;
117125
}
118126

127+
bool operator!=(const FuncInfo& lhs, const FuncInfo& rhs) noexcept {
128+
return !(lhs == rhs);
129+
}
130+
119131
struct Frame {
120132
VALUE frame;
133+
VALUE file;
121134
int line;
135+
136+
Frame() : frame(Qnil), file(Qnil), line(-1) { }
137+
138+
Frame(VALUE frame, int line) :
139+
frame(frame),
140+
file(Qnil),
141+
line(line) { }
122142
};
123143

124144
bool operator==(const Frame& lhs, const Frame& rhs) noexcept {
125-
return lhs.frame == rhs.frame && lhs.line == rhs.line;
145+
return lhs.frame == rhs.frame && lhs.file == rhs.file && lhs.line == rhs.line;
126146
}
127147

128148
bool operator!=(const Frame& lhs, const Frame& rhs) noexcept {
@@ -135,7 +155,7 @@ namespace std {
135155
{
136156
std::size_t operator()(Frame const& s) const noexcept
137157
{
138-
return s.frame ^ s.line;
158+
return s.frame ^ s.file ^ s.line;
139159
}
140160
};
141161
}
@@ -164,7 +184,7 @@ class RawSample {
164184
Frame frame(int i) const {
165185
int idx = len - i - 1;
166186
if (idx < 0) throw std::out_of_range("VERNIER BUG: index out of range");
167-
const Frame frame = {frames[idx], lines[idx]};
187+
const Frame frame = Frame(frames[idx], lines[idx]);
168188
return frame;
169189
}
170190

@@ -279,10 +299,10 @@ struct StackTable {
279299
int parent;
280300
int index;
281301

282-
StackNode(Frame frame, int index, int parent) : frame(frame), index(index), parent(parent) {}
302+
StackNode(Frame frame, int index, int parent) : frame(frame), index(index), parent(parent) { }
283303

284304
// root
285-
StackNode() : frame(Frame{0, 0}), index(-1), parent(-1) {}
305+
StackNode() : frame(Frame(0, 0)), index(-1), parent(-1) { }
286306
};
287307

288308
// This mutex guards the StackNodes only. The rest of the maps and vectors
@@ -349,20 +369,29 @@ struct StackTable {
349369
// Converts Frames from stacks other tables. "Symbolicates" the frames
350370
// which allocates.
351371
void finalize() {
372+
std::unordered_map<VALUE, Frame> frames_by_func;
373+
352374
{
353375
const std::lock_guard<std::mutex> lock(stack_mutex);
354376
for (int i = stack_node_list_finalized_idx; i < stack_node_list.size(); i++) {
355-
const auto &stack_node = stack_node_list[i];
377+
auto &stack_node = stack_node_list[i];
378+
if (NIL_P(stack_node.frame.file) && stack_node.frame.frame != 0) {
379+
VALUE file = rb_profile_frame_absolute_path(stack_node.frame.frame);
380+
if (NIL_P(file)) file = rb_profile_frame_path(stack_node.frame.frame);
381+
stack_node.frame.file = file;
382+
}
356383
frame_map.index(stack_node.frame);
357384
func_map.index(stack_node.frame.frame);
385+
frames_by_func.emplace(stack_node.frame.frame, stack_node.frame);
358386
stack_node_list_finalized_idx = i;
359387
}
360388
}
361389

362390
for (int i = func_info_list.size(); i < func_map.size(); i++) {
363391
const auto &func = func_map[i];
392+
const auto &frame = frames_by_func[func];
364393
// must not hold a mutex here
365-
func_info_list.push_back(FuncInfo(func));
394+
func_info_list.push_back(FuncInfo(frame.frame));
366395
}
367396
}
368397

@@ -371,6 +400,7 @@ struct StackTable {
371400

372401
for (auto stack_node: stack_node_list) {
373402
rb_gc_mark(stack_node.frame.frame);
403+
rb_gc_mark(stack_node.frame.file);
374404
}
375405
}
376406

@@ -1177,9 +1207,10 @@ class BaseCollector {
11771207
VALUE start_thread;
11781208
TimeStamp started_at;
11791209

1180-
BaseCollector(VALUE stack_table_value) : stack_table_value(stack_table_value), stack_table(get_stack_table(stack_table_value)) {
1181-
}
1182-
virtual ~BaseCollector() {}
1210+
BaseCollector(VALUE stack_table_value) :
1211+
stack_table_value(stack_table_value),
1212+
stack_table(get_stack_table(stack_table_value)) { }
1213+
virtual ~BaseCollector() { }
11831214

11841215
virtual bool start() {
11851216
if (running) {
@@ -1421,15 +1452,15 @@ class RetainedCollector : public BaseCollector {
14211452
RetainedCollector *collector = this;
14221453
for (auto& obj: collector->object_list) {
14231454
VALUE reloc_obj = rb_gc_location(obj);
1424-
1455+
14251456
const auto search = collector->object_frames.find(obj);
14261457
if (search != collector->object_frames.end()) {
14271458
int stack_index = search->second;
1428-
1459+
14291460
collector->object_frames.erase(search);
14301461
collector->object_frames.emplace(reloc_obj, stack_index);
14311462
}
1432-
1463+
14331464
obj = reloc_obj;
14341465
}
14351466
}

test/test_stack_table.rb

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -56,15 +56,6 @@ def test_current_sample
5656
assert_equal hash[:func_table][:name].uniq, hash[:func_table][:name]
5757
end
5858

59-
def test_calling_to_h_multiple_times
60-
stack_table = Vernier::StackTable.new
61-
stack_table.current_stack
62-
63-
first = stack_table.to_h
64-
second = stack_table.to_h
65-
assert_equal first, second
66-
end
67-
6859
def test_current_sample_with_offset
6960
stack_table = Vernier::StackTable.new
7061

0 commit comments

Comments
 (0)