| Index: runtime/vm/profiler.cc
|
| diff --git a/runtime/vm/profiler.cc b/runtime/vm/profiler.cc
|
| index 24d3da973f44574fe46971f0885cf3350147fb1e..9398bbba7528c845e6f4ebf5a163c0bf9a54514b 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,9 +1591,11 @@ 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;
|
| }
|
| + ASSERT(isolate != Dart::vm_isolate());
|
| + ASSERT(isolate->stub_code() != NULL);
|
| VMTagCounters* counters = isolate->vm_tag_counters();
|
| ASSERT(counters != NULL);
|
| counters->Increment(isolate->vm_tag());
|
| @@ -1550,16 +1609,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): Support collecting only Dart frames with
|
| + // ProfilerNativeStackWalker.
|
| + }
|
| + }
|
| }
|
|
|
| } // namespace dart
|
|
|