Chromium Code Reviews| Index: runtime/vm/profiler.cc |
| diff --git a/runtime/vm/profiler.cc b/runtime/vm/profiler.cc |
| index 24d3da973f44574fe46971f0885cf3350147fb1e..b10396e9c0f9be3af6aa2661ab5c294f76576333 100644 |
| --- a/runtime/vm/profiler.cc |
| +++ b/runtime/vm/profiler.cc |
| @@ -35,6 +35,8 @@ DEFINE_FLAG(int, profile_depth, 8, |
| "Maximum number stack frames walked. Minimum 1. Maximum 255."); |
| DEFINE_FLAG(bool, profile_verify_stack_walk, false, |
| "Verify instruction addresses while walking the stack."); |
| +DEFINE_FLAG(bool, profile_native_stack, true, |
| + "Use native stack in profiler."); |
| bool Profiler::initialized_ = false; |
| SampleBuffer* Profiler::sample_buffer_ = NULL; |
| @@ -926,6 +928,11 @@ class CodeRegionTableBuilder : public SampleVisitor { |
| min_time_ = timestamp; |
| } |
| // Make sure VM tag is created. |
| + if (VMTag::IsNativeEntryTag(sample->vm_tag())) { |
| + CreateTag(VMTag::kNativeTagId); |
| + } else if (VMTag::IsRuntimeEntryTag(sample->vm_tag())) { |
| + CreateTag(VMTag::kRuntimeTagId); |
| + } |
| CreateTag(sample->vm_tag()); |
| // Exclusive tick for bottom frame. |
| Tick(sample->At(0), true, timestamp); |
| @@ -1101,6 +1108,19 @@ class CodeRegionExclusiveTrieBuilder : public SampleVisitor { |
| root_->Tick(); |
| CodeRegionTrieNode* current = root_; |
| if (use_tags()) { |
| + if (VMTag::IsNativeEntryTag(sample->vm_tag())) { |
| + // Insert a dummy kNativeTagId node. |
| + intptr_t tag_index = FindTagIndex(VMTag::kNativeTagId); |
| + current = current->GetChild(tag_index); |
| + // Give the tag a tick. |
| + current->Tick(); |
| + } else if (VMTag::IsRuntimeEntryTag(sample->vm_tag())) { |
| + // Insert a dummy kRuntimeTagId node. |
| + intptr_t tag_index = FindTagIndex(VMTag::kRuntimeTagId); |
| + current = current->GetChild(tag_index); |
| + // Give the tag a tick. |
| + current->Tick(); |
| + } |
| intptr_t tag_index = FindTagIndex(sample->vm_tag()); |
| current = current->GetChild(tag_index); |
| // Give the tag a tick. |
| @@ -1406,6 +1426,45 @@ Sample* SampleBuffer::ReserveSample() { |
| return At(cursor); |
| } |
| +class ProfilerDartStackWalker : public ValueObject { |
| + public: |
| + explicit ProfilerDartStackWalker(Sample* sample) |
| + : sample_(sample), |
| + frame_iterator_() { |
| + ASSERT(sample_ != NULL); |
| + } |
| + |
| + ProfilerDartStackWalker(Sample* sample, uword pc, uword fp, uword sp) |
| + : sample_(sample), |
| + frame_iterator_(fp, sp, pc) { |
| + ASSERT(sample_ != NULL); |
| + } |
| + |
| + ProfilerDartStackWalker(Sample* sample, uword fp) |
| + : sample_(sample), |
| + frame_iterator_(fp) { |
| + ASSERT(sample_ != NULL); |
| + } |
| + |
| + int walk() { |
| + intptr_t frame_index = 0; |
| + StackFrame* frame = frame_iterator_.NextFrame(); |
| + while (frame != NULL) { |
| + sample_->SetAt(frame_index, frame->pc()); |
| + frame_index++; |
| + if (frame_index >= FLAG_profile_depth) { |
| + break; |
| + } |
| + frame = frame_iterator_.NextFrame(); |
| + } |
| + return frame_index; |
| + } |
| + |
| + private: |
| + Sample* sample_; |
| + DartFrameIterator frame_iterator_; |
| +}; |
| + |
| // Notes on stack frame walking: |
| // |
| // The sampling profiler will collect up to Sample::kNumStackFrames stack frames |
| @@ -1414,9 +1473,9 @@ Sample* SampleBuffer::ReserveSample() { |
| // recent GCC versions with optimizing enabled) the stack walking code may |
| // fail (sometimes leading to a crash). |
| // |
| -class ProfilerSampleStackWalker : public ValueObject { |
| +class ProfilerNativeStackWalker : public ValueObject { |
| public: |
| - ProfilerSampleStackWalker(Sample* sample, |
| + ProfilerNativeStackWalker(Sample* sample, |
| uword stack_lower, |
| uword stack_upper, |
| uword pc, |
| @@ -1431,13 +1490,11 @@ class ProfilerSampleStackWalker : public ValueObject { |
| ASSERT(sample_ != NULL); |
| } |
| - int walk(Heap* heap, uword vm_tag) { |
| + int walk(Heap* heap) { |
| const intptr_t kMaxStep = 0x1000; // 4K. |
| const bool kWalkStack = true; // Walk the stack. |
| // Always store the exclusive PC. |
| sample_->SetAt(0, original_pc_); |
| - // Always store the vm tag. |
| - sample_->set_vm_tag(vm_tag); |
| if (!kWalkStack) { |
| // Not walking the stack, only took exclusive sample. |
| return 1; |
| @@ -1534,7 +1591,15 @@ void Profiler::RecordSampleInterruptCallback( |
| const InterruptedThreadState& state, |
| void* data) { |
| Isolate* isolate = reinterpret_cast<Isolate*>(data); |
| - if (isolate == NULL) { |
| + if ((isolate == NULL) || (Dart::vm_isolate() == NULL)) { |
| + return; |
| + } |
| + if (isolate == Dart::vm_isolate()) { |
| + // Never sample the vm_isolate. |
| + return; |
| + } |
|
siva
2014/04/08 16:27:54
Does it make sense to start the profiler before th
Cutch
2014/04/09 17:40:59
Isolate::SetCurrent expects the profiler to have b
siva
2014/04/09 23:28:11
I agree we don't want to make Isolate::SetCurrent
Cutch
2014/04/10 15:30:27
Done.
|
| + if (!FLAG_profile_native_stack && (isolate->stub_code() == NULL)) { |
| + // ProfilerDartStackWalker requires stub code setup to be completed. |
| return; |
| } |
|
siva
2014/04/08 16:27:54
Instead of checking like this wouldn't it be more
Cutch
2014/04/09 17:40:59
See above.
|
| VMTagCounters* counters = isolate->vm_tag_counters(); |
| @@ -1550,16 +1615,28 @@ void Profiler::RecordSampleInterruptCallback( |
| } |
| Sample* sample = sample_buffer->ReserveSample(); |
| sample->Init(isolate, OS::GetCurrentTimeMicros(), state.tid); |
| - uword stack_lower = 0; |
| - uword stack_upper = 0; |
| - isolate->GetStackBounds(&stack_lower, &stack_upper); |
| - if ((stack_lower == 0) || (stack_upper == 0)) { |
| - stack_lower = 0; |
| - stack_upper = 0; |
| - } |
| - ProfilerSampleStackWalker stackWalker(sample, stack_lower, stack_upper, |
| - state.pc, state.fp, state.sp); |
| - stackWalker.walk(isolate->heap(), isolate->vm_tag()); |
| + sample->set_vm_tag(isolate->vm_tag()); |
| + if (FLAG_profile_native_stack) { |
| + // Collect native and Dart frames. |
| + uword stack_lower = 0; |
| + uword stack_upper = 0; |
| + isolate->GetStackBounds(&stack_lower, &stack_upper); |
| + if ((stack_lower == 0) || (stack_upper == 0)) { |
| + stack_lower = 0; |
| + stack_upper = 0; |
| + } |
| + ProfilerNativeStackWalker stackWalker(sample, stack_lower, stack_upper, |
| + state.pc, state.fp, state.sp); |
| + stackWalker.walk(isolate->heap()); |
| + } else { |
| + if (isolate->top_exit_frame_info() != 0) { |
| + ProfilerDartStackWalker stackWalker(sample); |
| + stackWalker.walk(); |
| + } else { |
| + // TODO(johnmccutchan): StackFrameIterator that is resilient to native |
| + // frames. |
|
siva
2014/04/08 16:27:54
what does this TODO mean (for pure Dart frame walk
Cutch
2014/04/09 17:40:59
Slightly misworded but I want to support only coll
|
| + } |
| + } |
| } |
| } // namespace dart |