Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(128)

Unified Diff: src/profiler/profile-generator.cc

Issue 1740073002: Make CPU profiler unwind the inlined functions stack. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: rebaseline Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/profiler/profile-generator.h ('k') | test/cctest/test-cpu-profiler.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/profiler/profile-generator.cc
diff --git a/src/profiler/profile-generator.cc b/src/profiler/profile-generator.cc
index e9465ba5427ea4082ffee230d5409f9455876edc..70a5a4c423ba0beddd6b3a52293045a44e4e3dad 100644
--- a/src/profiler/profile-generator.cc
+++ b/src/profiler/profile-generator.cc
@@ -50,6 +50,11 @@ const char* const CodeEntry::kNoDeoptReason = "";
CodeEntry::~CodeEntry() {
delete line_info_;
+ for (auto location : inline_locations_) {
+ for (auto entry : location.second) {
+ delete entry;
+ }
+ }
}
@@ -100,6 +105,18 @@ int CodeEntry::GetSourceLine(int pc_offset) const {
return v8::CpuProfileNode::kNoLineNumberInfo;
}
+void CodeEntry::AddInlineStack(int pc_offset,
+ std::vector<CodeEntry*>& inline_stack) {
+ // It's better to use std::move to place the vector into the map,
+ // but it's not supported by the current stdlibc++ on MacOS.
+ inline_locations_.insert(std::make_pair(pc_offset, std::vector<CodeEntry*>()))
+ .first->second.swap(inline_stack);
+}
+
+const std::vector<CodeEntry*>* CodeEntry::GetInlineStack(int pc_offset) const {
+ auto it = inline_locations_.find(pc_offset);
+ return it != inline_locations_.end() ? &it->second : NULL;
+}
void CodeEntry::FillFunctionInfo(SharedFunctionInfo* shared) {
if (!shared->script()->IsScript()) return;
@@ -109,7 +126,6 @@ void CodeEntry::FillFunctionInfo(SharedFunctionInfo* shared) {
set_bailout_reason(GetBailoutReason(shared->disable_optimization_reason()));
}
-
CpuProfileDeoptInfo CodeEntry::GetDeoptInfo() {
DCHECK(has_deopt_info());
@@ -274,17 +290,14 @@ unsigned ProfileTree::GetFunctionId(const ProfileNode* node) {
return static_cast<unsigned>(reinterpret_cast<uintptr_t>(entry->value));
}
-ProfileNode* ProfileTree::AddPathFromEnd(const Vector<CodeEntry*>& path,
+ProfileNode* ProfileTree::AddPathFromEnd(const std::vector<CodeEntry*>& path,
int src_line, bool update_stats) {
ProfileNode* node = root_;
CodeEntry* last_entry = NULL;
- for (CodeEntry** entry = path.start() + path.length() - 1;
- entry != path.start() - 1;
- --entry) {
- if (*entry != NULL) {
- node = node->FindOrAddChild(*entry);
- last_entry = *entry;
- }
+ for (auto it = path.rbegin(); it != path.rend(); ++it) {
+ if (*it == NULL) continue;
+ last_entry = *it;
+ node = node->FindOrAddChild(*it);
}
if (last_entry && last_entry->has_deopt_info()) {
node->CollectDeoptInfo(last_entry);
@@ -356,7 +369,7 @@ CpuProfile::CpuProfile(Isolate* isolate, const char* title, bool record_samples)
top_down_(isolate) {}
void CpuProfile::AddPath(base::TimeTicks timestamp,
- const Vector<CodeEntry*>& path, int src_line,
+ const std::vector<CodeEntry*>& path, int src_line,
bool update_stats) {
ProfileNode* top_frame_node =
top_down_.AddPathFromEnd(path, src_line, update_stats);
@@ -525,8 +538,8 @@ void CpuProfilesCollection::RemoveProfile(CpuProfile* profile) {
}
void CpuProfilesCollection::AddPathToCurrentProfiles(
- base::TimeTicks timestamp, const Vector<CodeEntry*>& path, int src_line,
- bool update_stats) {
+ base::TimeTicks timestamp, const std::vector<CodeEntry*>& path,
+ int src_line, bool update_stats) {
// As starting / stopping profiles is rare relatively to this
// method, we don't bother minimizing the duration of lock holding,
// e.g. copying contents of the list to a local vector.
@@ -576,12 +589,10 @@ ProfileGenerator::ProfileGenerator(CpuProfilesCollection* profiles)
void ProfileGenerator::RecordTickSample(const TickSample& sample) {
- // Allocate space for stack frames + pc + function + vm-state.
- ScopedVector<CodeEntry*> entries(sample.frames_count + 3);
- // As actual number of decoded code entries may vary, initialize
- // entries vector with NULL values.
- CodeEntry** entry = entries.start();
- memset(entry, 0, entries.length() * sizeof(*entry));
+ std::vector<CodeEntry*> entries;
+ // Conservatively reserve space for stack frames + pc + function + vm-state.
+ // There could in fact be more of them because of inlined entries.
+ entries.reserve(sample.frames_count + 3);
// The ProfileNode knows nothing about all versions of generated code for
// the same JS function. The line number information associated with
@@ -597,7 +608,7 @@ void ProfileGenerator::RecordTickSample(const TickSample& sample) {
// Don't use PC when in external callback code, as it can point
// inside callback's code, and we will erroneously report
// that a callback calls itself.
- *entry++ = code_map_.FindEntry(sample.external_callback);
+ entries.push_back(code_map_.FindEntry(sample.external_callback));
} else {
CodeEntry* pc_entry = code_map_.FindEntry(sample.pc);
// If there is no pc_entry we're likely in native code.
@@ -620,7 +631,7 @@ void ProfileGenerator::RecordTickSample(const TickSample& sample) {
src_line = pc_entry->line_number();
}
src_line_not_found = false;
- *entry++ = pc_entry;
+ entries.push_back(pc_entry);
if (pc_entry->builtin_id() == Builtins::kFunctionPrototypeApply ||
pc_entry->builtin_id() == Builtins::kFunctionPrototypeCall) {
@@ -631,7 +642,7 @@ void ProfileGenerator::RecordTickSample(const TickSample& sample) {
// former case we don't so we simply replace the frame with
// 'unresolved' entry.
if (sample.top_frame_type == StackFrame::JAVA_SCRIPT) {
- *entry++ = unresolved_entry_;
+ entries.push_back(unresolved_entry_);
}
}
}
@@ -640,35 +651,43 @@ void ProfileGenerator::RecordTickSample(const TickSample& sample) {
for (const Address *stack_pos = sample.stack,
*stack_end = stack_pos + sample.frames_count;
stack_pos != stack_end; ++stack_pos) {
- *entry = code_map_.FindEntry(*stack_pos);
+ CodeEntry* entry = code_map_.FindEntry(*stack_pos);
- // Skip unresolved frames (e.g. internal frame) and get source line of
- // the first JS caller.
- if (src_line_not_found && *entry) {
+ if (entry) {
+ // Find out if the entry has an inlining stack associated.
int pc_offset =
- static_cast<int>(*stack_pos - (*entry)->instruction_start());
- src_line = (*entry)->GetSourceLine(pc_offset);
- if (src_line == v8::CpuProfileNode::kNoLineNumberInfo) {
- src_line = (*entry)->line_number();
+ static_cast<int>(*stack_pos - entry->instruction_start());
+ const std::vector<CodeEntry*>* inline_stack =
+ entry->GetInlineStack(pc_offset);
+ if (inline_stack) {
+ entries.insert(entries.end(), inline_stack->rbegin(),
+ inline_stack->rend());
+ }
+ // Skip unresolved frames (e.g. internal frame) and get source line of
+ // the first JS caller.
+ if (src_line_not_found) {
+ src_line = entry->GetSourceLine(pc_offset);
+ if (src_line == v8::CpuProfileNode::kNoLineNumberInfo) {
+ src_line = entry->line_number();
+ }
+ src_line_not_found = false;
}
- src_line_not_found = false;
}
-
- entry++;
+ entries.push_back(entry);
}
}
if (FLAG_prof_browser_mode) {
bool no_symbolized_entries = true;
- for (CodeEntry** e = entries.start(); e != entry; ++e) {
- if (*e != NULL) {
+ for (auto e : entries) {
+ if (e != NULL) {
no_symbolized_entries = false;
break;
}
}
// If no frames were symbolized, put the VM state entry in.
if (no_symbolized_entries) {
- *entry++ = EntryForVMState(sample.state);
+ entries.push_back(EntryForVMState(sample.state));
}
}
« no previous file with comments | « src/profiler/profile-generator.h ('k') | test/cctest/test-cpu-profiler.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698