Index: runtime/vm/profiler_service.cc |
diff --git a/runtime/vm/profiler_service.cc b/runtime/vm/profiler_service.cc |
index 8eaf6c147e959a055631de5c01efa9f48bfbb984..35fd7712c23c8eaad2787d5ac4ac9e27140d0f3a 100644 |
--- a/runtime/vm/profiler_service.cc |
+++ b/runtime/vm/profiler_service.cc |
@@ -157,18 +157,38 @@ void ProfileFunction::Tick(bool exclusive, |
void ProfileFunction::TickSourcePosition(TokenPosition token_position, |
bool exclusive) { |
- for (intptr_t i = 0; i < source_position_ticks_.length(); i++) { |
+ intptr_t i = 0; |
+ for (; i < source_position_ticks_.length(); i++) { |
ProfileFunctionSourcePosition& position = source_position_ticks_[i]; |
- if (position.token_pos() == token_position) { |
+ if (position.token_pos().value() == token_position.value()) { |
+ if (FLAG_trace_profiler) { |
+ OS::Print("Ticking source position %s %s\n", |
+ exclusive ? "exclusive" : "inclusive", |
+ token_position.ToCString()); |
+ } |
// Found existing position, tick it. |
position.Tick(exclusive); |
return; |
} |
+ if (position.token_pos().value() > token_position.value()) { |
+ break; |
+ } |
} |
- // Add new one. |
+ |
+ // Add new one, sorted by token position value. |
ProfileFunctionSourcePosition pfsp(token_position); |
+ if (FLAG_trace_profiler) { |
+ OS::Print("Ticking source position %s %s\n", |
+ exclusive ? "exclusive" : "inclusive", |
+ token_position.ToCString()); |
+ } |
pfsp.Tick(exclusive); |
- source_position_ticks_.Add(pfsp); |
+ |
+ if (i < source_position_ticks_.length()) { |
+ source_position_ticks_.InsertAt(i, pfsp); |
+ } else { |
+ source_position_ticks_.Add(pfsp); |
+ } |
} |
@@ -1427,6 +1447,28 @@ class ProfileBuilder : public ValueObject { |
} |
} |
+ intptr_t OffsetForPC(uword pc, |
+ const Code& code, |
+ ProcessedSample* sample, |
+ intptr_t frame_index) { |
+ intptr_t offset = pc - code.EntryPoint(); |
+ if (frame_index != 0) { |
+ // The PC of frames below the top frame is a call's return address, |
+ // which can belong to a different inlining interval than the call. |
+ offset--; |
+ } else if (sample->IsAllocationSample()) { |
+ // Allocation samples skip the top frame, so the top frame's pc is |
+ // also a call's return address. |
+ offset--; |
+ } else if (!sample->first_frame_executing()) { |
+ // If the first frame wasn't executing code (i.e. we started to collect |
+ // the stack trace at an exit frame), the top frame's pc is also a |
+ // call's return address. |
+ offset--; |
+ } |
+ return offset; |
+ } |
+ |
ProfileFunctionTrieNode* ProcessFrame( |
ProfileFunctionTrieNode* current, |
intptr_t sample_index, |
@@ -1444,21 +1486,7 @@ class ProfileBuilder : public ValueObject { |
GrowableArray<TokenPosition> inlined_token_positions; |
TokenPosition token_position = TokenPosition::kNoSource; |
if (!code.IsNull()) { |
- intptr_t offset = pc - code.EntryPoint(); |
- if (frame_index != 0) { |
- // The PC of frames below the top frame is a call's return address, |
- // which can belong to a different inlining interval than the call. |
- offset--; |
- } else if (sample->IsAllocationSample()) { |
- // Allocation samples skip the top frame, so the top frame's pc is |
- // also a call's return address. |
- offset--; |
- } else if (!sample->first_frame_executing()) { |
- // If the first frame wasn't executing code (i.e. we started to collect |
- // the stack trace at an exit frame), the top frame's pc is also a |
- // call's return address. |
- offset--; |
- } |
+ const intptr_t offset = OffsetForPC(pc, code, sample, frame_index); |
code.GetInlinedFunctionsAt(offset, |
&inlined_functions, |
&inlined_token_positions); |
@@ -1587,13 +1615,15 @@ class ProfileBuilder : public ValueObject { |
ProfileFunction* function, |
TokenPosition token_position, |
intptr_t code_index) { |
- if (FLAG_trace_profiler) { |
- THR_Print("S[%" Pd "]F[%" Pd "] %s %s\n", |
- sample_index, |
- frame_index, |
- function->Name(), token_position.ToCString()); |
- } |
if (tick_functions_) { |
+ if (FLAG_trace_profiler) { |
+ THR_Print("S[%" Pd "]F[%" Pd "] %s %s 0x%" Px "\n", |
+ sample_index, |
+ frame_index, |
+ function->Name(), |
+ token_position.ToCString(), |
+ sample->At(frame_index)); |
+ } |
function->Tick(IsExecutingFrame(sample, frame_index), |
sample_index, |
token_position); |
@@ -2108,6 +2138,10 @@ void Profile::Build(Thread* thread, |
} |
+intptr_t Profile::NumFunctions() const { |
+ return functions_->length(); |
+} |
+ |
ProfileFunction* Profile::GetFunction(intptr_t index) { |
ASSERT(functions_ != NULL); |
return functions_->At(index); |
@@ -2224,6 +2258,15 @@ void Profile::PrintTimelineJSON(JSONStream* stream) { |
} |
+ProfileFunction* Profile::FindFunction(const Function& function) { |
+ const intptr_t index = functions_->LookupIndex(function); |
+ if (index < 0) { |
+ return NULL; |
+ } |
+ return functions_->At(index); |
+} |
+ |
+ |
void Profile::PrintProfileJSON(JSONStream* stream) { |
ScopeTimer sw("Profile::PrintProfileJSON", FLAG_trace_profiler); |
JSONObject obj(stream); |