Chromium Code Reviews| Index: runtime/vm/profiler.cc |
| diff --git a/runtime/vm/profiler.cc b/runtime/vm/profiler.cc |
| index 2f1ae378005907a8bb16aa5418f4c3c9a08c7313..2b63d94aa0c9079e067e6c06a0be18696cd28be6 100644 |
| --- a/runtime/vm/profiler.cc |
| +++ b/runtime/vm/profiler.cc |
| @@ -328,6 +328,32 @@ void ClearProfileVisitor::VisitSample(Sample* sample) { |
| } |
| +static void DumpStackFrame(intptr_t frame, uword pc) { |
|
srdjan
2016/04/25 20:05:55
maybe s/frame/frame_index/ ... also below
Cutch
2016/04/25 20:14:54
Done.
|
| + uintptr_t start = 0; |
| + char* native_symbol_name = |
| + NativeSymbolResolver::LookupSymbolName(pc, &start); |
| + if (native_symbol_name == NULL) { |
| + OS::Print("Frame[%" Pd "] = `unknown symbol` [0x%" Px "]\n", frame, pc); |
| + } else { |
| + OS::Print("Frame[%" Pd "] = `%s` [0x%" Px "]\n", |
| + frame, native_symbol_name, pc); |
| + free(native_symbol_name); |
| + } |
| +} |
| + |
| + |
| +static void DumpStackFrame(intptr_t frame, |
| + uword pc, |
| + const Code& code) { |
| + if (code.IsNull()) { |
| + DumpStackFrame(frame, pc); |
| + } else { |
| + OS::Print("Frame[%" Pd "] = Dart:`%s` [0x%" Px "]\n", |
| + frame, code.ToCString(), pc); |
| + } |
| +} |
| + |
| + |
| class ProfilerStackWalker : public ValueObject { |
| public: |
| ProfilerStackWalker(Isolate* isolate, |
| @@ -339,12 +365,31 @@ class ProfilerStackWalker : public ValueObject { |
| frame_index_(0), |
| total_frames_(0) { |
| ASSERT(isolate_ != NULL); |
| - ASSERT(sample_ != NULL); |
| - ASSERT(sample_buffer_ != NULL); |
| - ASSERT(sample_->head_sample()); |
| + if (sample_ != NULL) { |
|
srdjan
2016/04/25 20:05:55
I find using positive test (in most cases) to be m
Cutch
2016/04/25 20:14:54
Done.
|
| + ASSERT(sample_buffer_ != NULL); |
| + ASSERT(sample_->head_sample()); |
| + } else { |
| + ASSERT(sample_buffer_ == NULL); |
| + } |
| + } |
| + |
| + bool Append(uword pc, const Code& code) { |
| + if (sample_ == NULL) { |
| + DumpStackFrame(frame_index_, pc, code); |
| + frame_index_++; |
| + total_frames_++; |
| + return true; |
| + } |
| + return Append(pc); |
| } |
| bool Append(uword pc) { |
| + if (sample_ == NULL) { |
| + DumpStackFrame(frame_index_, pc); |
| + frame_index_++; |
| + total_frames_++; |
| + return true; |
| + } |
| if (total_frames_ >= FLAG_max_profile_depth) { |
| sample_->set_truncated_trace(true); |
| return false; |
| @@ -392,8 +437,10 @@ class ProfilerDartExitStackWalker : public ProfilerStackWalker { |
| sample_->set_exit_frame_sample(true); |
| StackFrame* frame = frame_iterator_.NextFrame(); |
| + Code& code = Code::Handle(); |
|
srdjan
2016/04/25 20:05:55
Can you use zone here (from frame_iterator_ or Pro
Cutch
2016/04/25 20:14:54
I've actually re-worked this code here. It was uns
|
| while (frame != NULL) { |
| - if (!Append(frame->pc())) { |
| + code ^= frame->LookupDartCode(); |
| + if (!Append(frame->pc(), code)) { |
| return; |
| } |
| frame = frame_iterator_.NextFrame(); |
| @@ -581,7 +628,6 @@ class ProfilerNativeStackWalker : public ProfilerStackWalker { |
| void walk() { |
| const uword kMaxStep = VirtualMemory::PageSize(); |
| - |
| Append(original_pc_); |
| uword* pc = reinterpret_cast<uword*>(original_pc_); |
| @@ -881,6 +927,77 @@ static uintptr_t __attribute__((noinline)) GetProgramCounter() { |
| } |
| #endif |
| + |
| +void Profiler::DumpStackTrace(bool native_stack_trace) { |
| + Thread* thread = Thread::Current(); |
| + ASSERT(thread != NULL); |
| + OSThread* os_thread = thread->os_thread(); |
| + ASSERT(os_thread != NULL); |
| + Isolate* isolate = thread->isolate(); |
| + if (!CheckIsolate(isolate)) { |
| + return; |
| + } |
| + |
| + const bool exited_dart_code = thread->HasExitedDartCode(); |
| + |
| + OS::Print("Dumping %s stack trace for thread %" Px "\n", |
| + native_stack_trace ? "native" : "dart-only", |
| + static_cast<uintptr_t>(os_thread->trace_id())); |
| + |
| + uintptr_t sp = Thread::GetCurrentStackPointer(); |
| + uintptr_t fp = 0; |
| + uintptr_t pc = GetProgramCounter(); |
| + |
| + COPY_FP_REGISTER(fp); |
| + |
| + uword stack_lower = 0; |
| + uword stack_upper = 0; |
| + |
| + if (!InitialRegisterCheck(pc, fp, sp)) { |
| + OS::Print( |
| + "Stack dump aborted because InitialRegisterCheck.\n"); |
| + return; |
| + } |
| + |
| + if (!GetAndValidateIsolateStackBounds(thread, |
| + fp, |
| + sp, |
| + &stack_lower, |
| + &stack_upper)) { |
| + OS::Print( |
| + "Stack dump aborted because GetAndValidateIsolateStackBounds.\n"); |
| + return; |
| + } |
| + |
| + if (native_stack_trace) { |
| + ProfilerNativeStackWalker native_stack_walker(isolate, |
| + NULL, |
| + NULL, |
| + stack_lower, |
| + stack_upper, |
| + pc, |
| + fp, |
| + sp); |
| + native_stack_walker.walk(); |
| + } else if (exited_dart_code) { |
| + ProfilerDartExitStackWalker dart_exit_stack_walker(thread, |
| + isolate, |
| + NULL, |
| + NULL); |
| + dart_exit_stack_walker.walk(); |
| + } else { |
| + ProfilerDartStackWalker dart_stack_walker(isolate, |
| + NULL, |
| + NULL, |
| + stack_lower, |
| + stack_upper, |
| + pc, |
| + fp, |
| + sp); |
| + } |
| +} |
| + |
| + |
| void Profiler::SampleAllocation(Thread* thread, intptr_t cid) { |
| ASSERT(thread != NULL); |
| OSThread* os_thread = thread->os_thread(); |