| Index: runtime/vm/profiler.cc
|
| diff --git a/runtime/vm/profiler.cc b/runtime/vm/profiler.cc
|
| index 24d3da973f44574fe46971f0885cf3350147fb1e..acf90fc476e5b1c3f8db99edac71fe8032a3eafc 100644
|
| --- a/runtime/vm/profiler.cc
|
| +++ b/runtime/vm/profiler.cc
|
| @@ -564,9 +564,17 @@ class CodeRegion : public ZoneAllocated {
|
| PrintOverwrittenCode(&obj);
|
| } else if (kind() == kTagCode) {
|
| if (name() == NULL) {
|
| - const char* tag_name = start() == 0 ? "root" : VMTag::TagName(start());
|
| - ASSERT(tag_name != NULL);
|
| - SetName(tag_name);
|
| + if (VMTag::IsVMTag(start())) {
|
| + const char* tag_name = VMTag::TagName(start());
|
| + ASSERT(tag_name != NULL);
|
| + SetName(tag_name);
|
| + } else if (start() != 0) {
|
| + const char* tag_name = UserTagHelper::TagName(start());
|
| + ASSERT(tag_name != NULL);
|
| + SetName(tag_name);
|
| + } else {
|
| + SetName("root");
|
| + }
|
| }
|
| PrintTagCode(&obj);
|
| } else {
|
| @@ -927,6 +935,8 @@ class CodeRegionTableBuilder : public SampleVisitor {
|
| }
|
| // Make sure VM tag is created.
|
| CreateTag(sample->vm_tag());
|
| + // Make sure user tag is created.
|
| + CreateUserTag(sample->user_tag());
|
| // Exclusive tick for bottom frame.
|
| Tick(sample->At(0), true, timestamp);
|
| // Inclusive tick for all frames.
|
| @@ -962,6 +972,21 @@ class CodeRegionTableBuilder : public SampleVisitor {
|
| region->set_creation_serial(visited());
|
| }
|
|
|
| + void CreateUserTag(uword tag) {
|
| + intptr_t index = tag_code_table_->FindIndex(tag);
|
| + if (index >= 0) {
|
| + // Already created.
|
| + return;
|
| + }
|
| + CodeRegion* region = new CodeRegion(CodeRegion::kTagCode,
|
| + tag,
|
| + tag + 1,
|
| + 0);
|
| + index = tag_code_table_->InsertCodeRegion(region);
|
| + ASSERT(index >= 0);
|
| + region->set_creation_serial(visited());
|
| + }
|
| +
|
| void Tick(uword pc, bool exclusive, int64_t timestamp) {
|
| CodeRegionTable::TickResult r;
|
| intptr_t serial = exclusive ? -1 : visited();
|
| @@ -1101,8 +1126,14 @@ class CodeRegionExclusiveTrieBuilder : public SampleVisitor {
|
| root_->Tick();
|
| CodeRegionTrieNode* current = root_;
|
| if (use_tags()) {
|
| - intptr_t tag_index = FindTagIndex(sample->vm_tag());
|
| - current = current->GetChild(tag_index);
|
| + intptr_t user_tag_index = FindTagIndex(sample->user_tag());
|
| + if (user_tag_index >= 0) {
|
| + current = current->GetChild(user_tag_index);
|
| + // Give the tag a tick.
|
| + current->Tick();
|
| + }
|
| + intptr_t vm_tag_index = FindTagIndex(sample->vm_tag());
|
| + current = current->GetChild(vm_tag_index);
|
| // Give the tag a tick.
|
| current->Tick();
|
| }
|
| @@ -1132,6 +1163,9 @@ class CodeRegionExclusiveTrieBuilder : public SampleVisitor {
|
| private:
|
| intptr_t FindTagIndex(uword tag) const {
|
| intptr_t index = tag_code_table_->FindIndex(tag);
|
| + if (index <= 0) {
|
| + return -1;
|
| + }
|
| ASSERT(index >= 0);
|
| ASSERT((tag_code_table_->At(index))->contains(tag));
|
| return tag_code_table_offset_ + index;
|
| @@ -1431,13 +1465,15 @@ class ProfilerSampleStackWalker : public ValueObject {
|
| ASSERT(sample_ != NULL);
|
| }
|
|
|
| - int walk(Heap* heap, uword vm_tag) {
|
| + int walk(Heap* heap, uword vm_tag, uword user_tag) {
|
| 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);
|
| + // Always store the user tag.
|
| + sample_->set_user_tag(user_tag);
|
| if (!kWalkStack) {
|
| // Not walking the stack, only took exclusive sample.
|
| return 1;
|
| @@ -1466,6 +1502,9 @@ class ProfilerSampleStackWalker : public ValueObject {
|
| VerifyCodeAddress(heap, i, reinterpret_cast<uword>(pc));
|
| }
|
| sample_->SetAt(i, reinterpret_cast<uword>(pc));
|
| + if (fp == NULL) {
|
| + return i + 1;
|
| + }
|
| if (!ValidFramePointer(fp)) {
|
| return i + 1;
|
| }
|
| @@ -1473,9 +1512,18 @@ class ProfilerSampleStackWalker : public ValueObject {
|
| previous_fp = fp;
|
| fp = CallerFP(fp);
|
| intptr_t step = fp - previous_fp;
|
| - if ((step >= kMaxStep) || (fp <= previous_fp) || !ValidFramePointer(fp)) {
|
| + if (fp == NULL) {
|
| + return i + 1;
|
| + }
|
| + if ((step >= kMaxStep)) {
|
| // Frame pointer step is too large.
|
| + return i + 1;
|
| + }
|
| + if ((fp <= previous_fp)) {
|
| // Frame pointer did not move to a higher address.
|
| + return i + 1;
|
| + }
|
| + if (!ValidFramePointer(fp)) {
|
| // Frame pointer is outside of isolate stack bounds.
|
| return i + 1;
|
| }
|
| @@ -1559,7 +1607,7 @@ void Profiler::RecordSampleInterruptCallback(
|
| }
|
| ProfilerSampleStackWalker stackWalker(sample, stack_lower, stack_upper,
|
| state.pc, state.fp, state.sp);
|
| - stackWalker.walk(isolate->heap(), isolate->vm_tag());
|
| + stackWalker.walk(isolate->heap(), isolate->vm_tag(), isolate->user_tag());
|
| }
|
|
|
| } // namespace dart
|
|
|