Index: src/profiler/sampling-heap-profiler.cc |
diff --git a/src/profiler/sampling-heap-profiler.cc b/src/profiler/sampling-heap-profiler.cc |
index 16798a654b80dc07194ade88391227ad4dea836b..db9214d14d7f90f7d93dfad5e40c4febba893f10 100644 |
--- a/src/profiler/sampling-heap-profiler.cc |
+++ b/src/profiler/sampling-heap-profiler.cc |
@@ -125,8 +125,9 @@ void SamplingHeapProfiler::OnWeakCallback( |
while (node->allocations_.empty() && node->children_.empty() && |
node->parent_ && !node->parent_->pinned_) { |
AllocationNode* parent = node->parent_; |
- parent->children_.erase( |
- std::find(parent->children_.begin(), parent->children_.end(), node)); |
+ AllocationNode::FunctionId id = AllocationNode::function_id( |
+ node->script_id_, node->script_position_, node->name_); |
+ parent->children_.erase(id); |
delete node; |
node = parent; |
} |
@@ -135,19 +136,18 @@ void SamplingHeapProfiler::OnWeakCallback( |
delete sample; |
} |
-SamplingHeapProfiler::AllocationNode* SamplingHeapProfiler::FindOrAddChildNode( |
- AllocationNode* parent, const char* name, int script_id, |
- int start_position) { |
- for (AllocationNode* child : parent->children_) { |
- if (child->script_id_ == script_id && |
- child->script_position_ == start_position && |
- strcmp(child->name_, name) == 0) { |
- return child; |
- } |
+SamplingHeapProfiler::AllocationNode* |
+SamplingHeapProfiler::AllocationNode::FindOrAddChildNode(const char* name, |
+ int script_id, |
+ int start_position) { |
+ FunctionId id = function_id(script_id, start_position, name); |
+ auto it = children_.find(id); |
+ if (it != children_.end()) { |
+ DCHECK(strcmp(it->second->name_, name) == 0); |
+ return it->second; |
} |
- AllocationNode* child = |
- new AllocationNode(parent, name, script_id, start_position); |
- parent->children_.push_back(child); |
+ auto child = new AllocationNode(this, name, script_id, start_position); |
+ children_.insert(std::make_pair(id, child)); |
return child; |
} |
@@ -188,7 +188,7 @@ SamplingHeapProfiler::AllocationNode* SamplingHeapProfiler::AddStack() { |
name = "(JS)"; |
break; |
} |
- return FindOrAddChildNode(node, name, v8::UnboundScript::kNoScriptId, 0); |
+ return node->FindOrAddChildNode(name, v8::UnboundScript::kNoScriptId, 0); |
} |
// We need to process the stack in reverse order as the top of the stack is |
@@ -201,7 +201,7 @@ SamplingHeapProfiler::AllocationNode* SamplingHeapProfiler::AddStack() { |
Script* script = Script::cast(shared->script()); |
script_id = script->id(); |
} |
- node = FindOrAddChildNode(node, name, script_id, shared->start_position()); |
+ node = node->FindOrAddChildNode(name, script_id, shared->start_position()); |
} |
return node; |
} |
@@ -244,15 +244,13 @@ v8::AllocationProfile::Node* SamplingHeapProfiler::TranslateAllocationNode( |
script_name, node->script_id_, node->script_position_, line, column, |
std::vector<v8::AllocationProfile::Node*>(), allocations})); |
v8::AllocationProfile::Node* current = &profile->nodes().back(); |
- size_t child_len = node->children_.size(); |
- // The children vector may have nodes appended to it during translation |
+ // The children map may have nodes inserted into it during translation |
// because the translation may allocate strings on the JS heap that have |
- // the potential to be sampled. We cache the length of the vector before |
- // iteration so that nodes appended to the vector during iteration are |
- // not processed. |
- for (size_t i = 0; i < child_len; i++) { |
+ // the potential to be sampled. That's ok since map iterators are not |
+ // invalidated upon std::map insertion. |
+ for (auto it : node->children_) { |
current->children.push_back( |
- TranslateAllocationNode(profile, node->children_[i], scripts)); |
+ TranslateAllocationNode(profile, it.second, scripts)); |
} |
node->pinned_ = false; |
return current; |