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 |