| Index: src/profiler/sampling-heap-profiler.cc
|
| diff --git a/src/profiler/sampling-heap-profiler.cc b/src/profiler/sampling-heap-profiler.cc
|
| index 6c6e0e597b7e0b6b781881806acd6b09b10dacaa..be691fdb515dbb32e1342b10b34221f6cb7f788d 100644
|
| --- a/src/profiler/sampling-heap-profiler.cc
|
| +++ b/src/profiler/sampling-heap-profiler.cc
|
| @@ -58,14 +58,14 @@ SamplingHeapProfiler::SamplingHeapProfiler(Heap* heap, StringsStorage* names,
|
| heap_, static_cast<intptr_t>(rate), rate, this,
|
| heap->isolate()->random_number_generator())),
|
| names_(names),
|
| - profile_root_("(root)", v8::UnboundScript::kNoScriptId, 0),
|
| + profile_root_(nullptr, "(root)", v8::UnboundScript::kNoScriptId, 0),
|
| samples_(),
|
| stack_depth_(stack_depth),
|
| rate_(rate) {
|
| CHECK_GT(rate_, 0);
|
| heap->new_space()->AddAllocationObserver(new_space_observer_.get());
|
| AllSpaces spaces(heap);
|
| - for (Space* space = spaces.next(); space != NULL; space = spaces.next()) {
|
| + for (Space* space = spaces.next(); space != nullptr; space = spaces.next()) {
|
| if (space != heap->new_space()) {
|
| space->AddAllocationObserver(other_spaces_observer_.get());
|
| }
|
| @@ -76,7 +76,7 @@ SamplingHeapProfiler::SamplingHeapProfiler(Heap* heap, StringsStorage* names,
|
| SamplingHeapProfiler::~SamplingHeapProfiler() {
|
| heap_->new_space()->RemoveAllocationObserver(new_space_observer_.get());
|
| AllSpaces spaces(heap_);
|
| - for (Space* space = spaces.next(); space != NULL; space = spaces.next()) {
|
| + for (Space* space = spaces.next(); space != nullptr; space = spaces.next()) {
|
| if (space != heap_->new_space()) {
|
| space->RemoveAllocationObserver(other_spaces_observer_.get());
|
| }
|
| @@ -119,6 +119,14 @@ void SamplingHeapProfiler::OnWeakCallback(
|
| node->allocations_[sample->size]--;
|
| if (node->allocations_[sample->size] == 0) {
|
| node->allocations_.erase(sample->size);
|
| + 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));
|
| + delete node;
|
| + node = parent;
|
| + }
|
| }
|
| sample->profiler->samples_.erase(sample);
|
| delete sample;
|
| @@ -134,7 +142,8 @@ SamplingHeapProfiler::AllocationNode* SamplingHeapProfiler::FindOrAddChildNode(
|
| return child;
|
| }
|
| }
|
| - AllocationNode* child = new AllocationNode(name, script_id, start_position);
|
| + AllocationNode* child =
|
| + new AllocationNode(parent, name, script_id, start_position);
|
| parent->children_.push_back(child);
|
| return child;
|
| }
|
| @@ -197,6 +206,9 @@ SamplingHeapProfiler::AllocationNode* SamplingHeapProfiler::AddStack() {
|
| v8::AllocationProfile::Node* SamplingHeapProfiler::TranslateAllocationNode(
|
| AllocationProfile* profile, SamplingHeapProfiler::AllocationNode* node,
|
| const std::map<int, Handle<Script>>& scripts) {
|
| + // By pinning the node we make sure its children won't get disposed if
|
| + // a GC kicks in during the tree retrieval.
|
| + node->pinned_ = true;
|
| Local<v8::String> script_name =
|
| ToApiHandle<v8::String>(isolate_->factory()->InternalizeUtf8String(""));
|
| int line = v8::AllocationProfile::kNoLineNumberInfo;
|
| @@ -239,6 +251,7 @@ v8::AllocationProfile::Node* SamplingHeapProfiler::TranslateAllocationNode(
|
| current->children.push_back(
|
| TranslateAllocationNode(profile, node->children_[i], scripts));
|
| }
|
| + node->pinned_ = false;
|
| return current;
|
| }
|
|
|
|
|