Commit 0352ea97 authored by Alexei Filippov's avatar Alexei Filippov Committed by Commit Bot

[heap profiler] Refactor: remove SnapshotFiller proxy

Long time ago there were two passes over heap. One was counting
objects and edge and another was filling them. Since then we have
just a single pass, but the filler object is still there.

Remove it for the sake of layering simplicity.

Change-Id: Ic873eb5ca616b9dcae17fe388197dde8f539026f
Reviewed-on: https://chromium-review.googlesource.com/1244380
Commit-Queue: Alexei Filippov <alph@chromium.org>
Reviewed-by: 's avatarUlan Degenbaev <ulan@chromium.org>
Reviewed-by: 's avatarMichael Lippautz <mlippautz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#56246}
parent 69a502ce
...@@ -82,6 +82,17 @@ void HeapEntry::SetIndexedReference(HeapGraphEdge::Type type, ...@@ -82,6 +82,17 @@ void HeapEntry::SetIndexedReference(HeapGraphEdge::Type type,
snapshot_->edges().emplace_back(type, index, this, entry); snapshot_->edges().emplace_back(type, index, this, entry);
} }
void HeapEntry::SetNamedAutoIndexReference(HeapGraphEdge::Type type,
const char* description,
HeapEntry* child,
StringsStorage* names) {
int index = children_count_ + 1;
const char* name = description
? names->GetFormatted("%d / %s", index, description)
: names->GetName(index);
SetNamedReference(type, name, child);
}
void HeapEntry::Print( void HeapEntry::Print(
const char* prefix, const char* edge_name, int max_depth, int indent) { const char* prefix, const char* edge_name, int max_depth, int indent) {
STATIC_ASSERT(sizeof(unsigned) == sizeof(id())); STATIC_ASSERT(sizeof(unsigned) == sizeof(id()));
...@@ -141,7 +152,6 @@ void HeapEntry::Print( ...@@ -141,7 +152,6 @@ void HeapEntry::Print(
} }
} }
const char* HeapEntry::TypeAsString() { const char* HeapEntry::TypeAsString() {
switch (type()) { switch (type()) {
case kHidden: return "/hidden/"; case kHidden: return "/hidden/";
...@@ -496,7 +506,7 @@ V8HeapExplorer::V8HeapExplorer(HeapSnapshot* snapshot, ...@@ -496,7 +506,7 @@ V8HeapExplorer::V8HeapExplorer(HeapSnapshot* snapshot,
names_(snapshot_->profiler()->names()), names_(snapshot_->profiler()->names()),
heap_object_map_(snapshot_->profiler()->heap_object_map()), heap_object_map_(snapshot_->profiler()->heap_object_map()),
progress_(progress), progress_(progress),
filler_(nullptr), generator_(nullptr),
global_object_name_resolver_(resolver) {} global_object_name_resolver_(resolver) {}
HeapEntry* V8HeapExplorer::AllocateEntry(HeapThing ptr) { HeapEntry* V8HeapExplorer::AllocateEntry(HeapThing ptr) {
...@@ -557,17 +567,14 @@ HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object) { ...@@ -557,17 +567,14 @@ HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object) {
return AddEntry(object, HeapEntry::kObject, name); return AddEntry(object, HeapEntry::kObject, name);
} else if (object->IsString()) { } else if (object->IsString()) {
String* string = String::cast(object); String* string = String::cast(object);
if (string->IsConsString()) if (string->IsConsString()) {
return AddEntry(object, return AddEntry(object, HeapEntry::kConsString, "(concatenated string)");
HeapEntry::kConsString, } else if (string->IsSlicedString()) {
"(concatenated string)"); return AddEntry(object, HeapEntry::kSlicedString, "(sliced string)");
if (string->IsSlicedString()) } else {
return AddEntry(object, return AddEntry(object, HeapEntry::kString,
HeapEntry::kSlicedString,
"(sliced string)");
return AddEntry(object,
HeapEntry::kString,
names_->GetName(String::cast(object))); names_->GetName(String::cast(object)));
}
} else if (object->IsSymbol()) { } else if (object->IsSymbol()) {
if (Symbol::cast(object)->is_private()) if (Symbol::cast(object)->is_private())
return AddEntry(object, HeapEntry::kHidden, "private symbol"); return AddEntry(object, HeapEntry::kHidden, "private symbol");
...@@ -579,16 +586,12 @@ HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object) { ...@@ -579,16 +586,12 @@ HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object) {
return AddEntry(object, HeapEntry::kCode, ""); return AddEntry(object, HeapEntry::kCode, "");
} else if (object->IsSharedFunctionInfo()) { } else if (object->IsSharedFunctionInfo()) {
String* name = SharedFunctionInfo::cast(object)->Name(); String* name = SharedFunctionInfo::cast(object)->Name();
return AddEntry(object, return AddEntry(object, HeapEntry::kCode, names_->GetName(name));
HeapEntry::kCode,
names_->GetName(name));
} else if (object->IsScript()) { } else if (object->IsScript()) {
Object* name = Script::cast(object)->name(); Object* name = Script::cast(object)->name();
return AddEntry(object, return AddEntry(
HeapEntry::kCode, object, HeapEntry::kCode,
name->IsString() name->IsString() ? names_->GetName(String::cast(name)) : "");
? names_->GetName(String::cast(name))
: "");
} else if (object->IsNativeContext()) { } else if (object->IsNativeContext()) {
return AddEntry(object, HeapEntry::kHidden, "system / NativeContext"); return AddEntry(object, HeapEntry::kHidden, "system / NativeContext");
} else if (object->IsContext()) { } else if (object->IsContext()) {
...@@ -602,14 +605,12 @@ HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object) { ...@@ -602,14 +605,12 @@ HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object) {
return AddEntry(object, HeapEntry::kHidden, GetSystemEntryName(object)); return AddEntry(object, HeapEntry::kHidden, GetSystemEntryName(object));
} }
HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object, HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object,
HeapEntry::Type type, HeapEntry::Type type,
const char* name) { const char* name) {
return AddEntry(object->address(), type, name, object->Size()); return AddEntry(object->address(), type, name, object->Size());
} }
HeapEntry* V8HeapExplorer::AddEntry(Address address, HeapEntry* V8HeapExplorer::AddEntry(Address address,
HeapEntry::Type type, HeapEntry::Type type,
const char* name, const char* name,
...@@ -625,57 +626,6 @@ HeapEntry* V8HeapExplorer::AddEntry(Address address, ...@@ -625,57 +626,6 @@ HeapEntry* V8HeapExplorer::AddEntry(Address address,
return snapshot_->AddEntry(type, name, object_id, size, trace_node_id); return snapshot_->AddEntry(type, name, object_id, size, trace_node_id);
} }
class SnapshotFiller {
public:
SnapshotFiller(HeapSnapshot* snapshot,
HeapSnapshotGenerator::HeapEntriesMap* entries_map)
: names_(snapshot->profiler()->names()), entries_map_(entries_map) {}
HeapEntry* AddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) {
return entries_map_->emplace(ptr, allocator->AllocateEntry(ptr))
.first->second;
}
HeapEntry* FindEntry(HeapThing ptr) {
auto it = entries_map_->find(ptr);
return it != entries_map_->end() ? it->second : nullptr;
}
HeapEntry* FindOrAddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) {
HeapEntry* entry = FindEntry(ptr);
return entry != nullptr ? entry : AddEntry(ptr, allocator);
}
void SetIndexedReference(HeapGraphEdge::Type type, HeapEntry* parent,
int index, HeapEntry* child) {
parent->SetIndexedReference(type, index, child);
}
void SetIndexedAutoIndexReference(HeapGraphEdge::Type type, HeapEntry* parent,
HeapEntry* child) {
int index = parent->children_count() + 1;
parent->SetIndexedReference(type, index, child);
}
void SetNamedReference(HeapGraphEdge::Type type, HeapEntry* parent,
const char* reference_name, HeapEntry* child) {
parent->SetNamedReference(type, reference_name, child);
}
void SetNamedAutoIndexReference(HeapGraphEdge::Type type, HeapEntry* parent,
const char* description, HeapEntry* child) {
int index = parent->children_count() + 1;
const char* name = description
? names_->GetFormatted("%d / %s", index, description)
: names_->GetName(index);
parent->SetNamedReference(type, name, child);
}
private:
StringsStorage* names_;
HeapSnapshotGenerator::HeapEntriesMap* entries_map_;
};
const char* V8HeapExplorer::GetSystemEntryName(HeapObject* object) { const char* V8HeapExplorer::GetSystemEntryName(HeapObject* object) {
switch (object->map()->instance_type()) { switch (object->map()->instance_type()) {
case MAP_TYPE: case MAP_TYPE:
...@@ -961,8 +911,8 @@ void V8HeapExplorer::ExtractEphemeronHashTableReferences( ...@@ -961,8 +911,8 @@ void V8HeapExplorer::ExtractEphemeronHashTableReferences(
if (key_entry && value_entry) { if (key_entry && value_entry) {
const char* edge_name = const char* edge_name =
names_->GetFormatted("key %s in WeakMap", key_entry->name()); names_->GetFormatted("key %s in WeakMap", key_entry->name());
filler_->SetNamedAutoIndexReference(HeapGraphEdge::kInternal, key_entry, key_entry->SetNamedAutoIndexReference(HeapGraphEdge::kInternal, edge_name,
edge_name, value_entry); value_entry, names_);
} }
} }
} }
...@@ -1244,9 +1194,9 @@ void V8HeapExplorer::ExtractJSArrayBufferReferences(HeapEntry* entry, ...@@ -1244,9 +1194,9 @@ void V8HeapExplorer::ExtractJSArrayBufferReferences(HeapEntry* entry,
size_t data_size = buffer->byte_length(); size_t data_size = buffer->byte_length();
JSArrayBufferDataEntryAllocator allocator(data_size, this); JSArrayBufferDataEntryAllocator allocator(data_size, this);
HeapEntry* data_entry = HeapEntry* data_entry =
filler_->FindOrAddEntry(buffer->backing_store(), &allocator); generator_->FindOrAddEntry(buffer->backing_store(), &allocator);
filler_->SetNamedReference(HeapGraphEdge::kInternal, entry->SetNamedReference(HeapGraphEdge::kInternal, "backing_store",
entry, "backing_store", data_entry); data_entry);
} }
void V8HeapExplorer::ExtractJSPromiseReferences(HeapEntry* entry, void V8HeapExplorer::ExtractJSPromiseReferences(HeapEntry* entry,
...@@ -1442,8 +1392,7 @@ String* V8HeapExplorer::GetConstructorName(JSObject* object) { ...@@ -1442,8 +1392,7 @@ String* V8HeapExplorer::GetConstructorName(JSObject* object) {
HeapEntry* V8HeapExplorer::GetEntry(Object* obj) { HeapEntry* V8HeapExplorer::GetEntry(Object* obj) {
if (!obj->IsHeapObject()) return nullptr; return obj->IsHeapObject() ? generator_->FindOrAddEntry(obj, this) : nullptr;
return filler_->FindOrAddEntry(obj, this);
} }
class RootsReferencesExtractor : public RootVisitor { class RootsReferencesExtractor : public RootVisitor {
...@@ -1473,8 +1422,9 @@ class RootsReferencesExtractor : public RootVisitor { ...@@ -1473,8 +1422,9 @@ class RootsReferencesExtractor : public RootVisitor {
bool visiting_weak_roots_; bool visiting_weak_roots_;
}; };
bool V8HeapExplorer::IterateAndExtractReferences(SnapshotFiller* filler) { bool V8HeapExplorer::IterateAndExtractReferences(
filler_ = filler; HeapSnapshotGenerator* generator) {
generator_ = generator;
// Create references to the synthetic roots. // Create references to the synthetic roots.
SetRootGcRootsReference(); SetRootGcRootsReference();
...@@ -1525,7 +1475,7 @@ bool V8HeapExplorer::IterateAndExtractReferences(SnapshotFiller* filler) { ...@@ -1525,7 +1475,7 @@ bool V8HeapExplorer::IterateAndExtractReferences(SnapshotFiller* filler) {
if (!progress_->ProgressReport(false)) interrupted = true; if (!progress_->ProgressReport(false)) interrupted = true;
} }
filler_ = nullptr; generator_ = nullptr;
return interrupted ? false : progress_->ProgressReport(true); return interrupted ? false : progress_->ProgressReport(true);
} }
...@@ -1566,7 +1516,7 @@ void V8HeapExplorer::SetContextReference(HeapObject* parent_obj, ...@@ -1566,7 +1516,7 @@ void V8HeapExplorer::SetContextReference(HeapObject* parent_obj,
DCHECK_EQ(parent_entry, GetEntry(parent_obj)); DCHECK_EQ(parent_entry, GetEntry(parent_obj));
HeapEntry* child_entry = GetEntry(child_obj); HeapEntry* child_entry = GetEntry(child_obj);
if (child_entry == nullptr) return; if (child_entry == nullptr) return;
filler_->SetNamedReference(HeapGraphEdge::kContextVariable, parent_entry, parent_entry->SetNamedReference(HeapGraphEdge::kContextVariable,
names_->GetName(reference_name), child_entry); names_->GetName(reference_name), child_entry);
MarkVisitedField(field_offset); MarkVisitedField(field_offset);
} }
...@@ -1585,8 +1535,8 @@ void V8HeapExplorer::SetNativeBindReference(HeapObject* parent_obj, ...@@ -1585,8 +1535,8 @@ void V8HeapExplorer::SetNativeBindReference(HeapObject* parent_obj,
DCHECK_EQ(parent_entry, GetEntry(parent_obj)); DCHECK_EQ(parent_entry, GetEntry(parent_obj));
HeapEntry* child_entry = GetEntry(child_obj); HeapEntry* child_entry = GetEntry(child_obj);
if (child_entry == nullptr) return; if (child_entry == nullptr) return;
filler_->SetNamedReference(HeapGraphEdge::kShortcut, parent_entry, parent_entry->SetNamedReference(HeapGraphEdge::kShortcut, reference_name,
reference_name, child_entry); child_entry);
} }
void V8HeapExplorer::SetElementReference(HeapObject* parent_obj, void V8HeapExplorer::SetElementReference(HeapObject* parent_obj,
...@@ -1595,7 +1545,7 @@ void V8HeapExplorer::SetElementReference(HeapObject* parent_obj, ...@@ -1595,7 +1545,7 @@ void V8HeapExplorer::SetElementReference(HeapObject* parent_obj,
DCHECK_EQ(parent_entry, GetEntry(parent_obj)); DCHECK_EQ(parent_entry, GetEntry(parent_obj));
HeapEntry* child_entry = GetEntry(child_obj); HeapEntry* child_entry = GetEntry(child_obj);
if (child_entry == nullptr) return; if (child_entry == nullptr) return;
filler_->SetIndexedReference(HeapGraphEdge::kElement, parent_entry, index, parent_entry->SetIndexedReference(HeapGraphEdge::kElement, index,
child_entry); child_entry);
} }
...@@ -1607,9 +1557,7 @@ void V8HeapExplorer::SetInternalReference(HeapObject* parent_obj, ...@@ -1607,9 +1557,7 @@ void V8HeapExplorer::SetInternalReference(HeapObject* parent_obj,
HeapEntry* child_entry = GetEntry(child_obj); HeapEntry* child_entry = GetEntry(child_obj);
if (child_entry == nullptr) return; if (child_entry == nullptr) return;
if (IsEssentialObject(child_obj)) { if (IsEssentialObject(child_obj)) {
filler_->SetNamedReference(HeapGraphEdge::kInternal, parent_entry->SetNamedReference(HeapGraphEdge::kInternal, reference_name,
parent_entry,
reference_name,
child_entry); child_entry);
} }
MarkVisitedField(field_offset); MarkVisitedField(field_offset);
...@@ -1622,10 +1570,8 @@ void V8HeapExplorer::SetInternalReference(HeapObject* parent_obj, ...@@ -1622,10 +1570,8 @@ void V8HeapExplorer::SetInternalReference(HeapObject* parent_obj,
HeapEntry* child_entry = GetEntry(child_obj); HeapEntry* child_entry = GetEntry(child_obj);
if (child_entry == nullptr) return; if (child_entry == nullptr) return;
if (IsEssentialObject(child_obj)) { if (IsEssentialObject(child_obj)) {
filler_->SetNamedReference(HeapGraphEdge::kInternal, parent_entry->SetNamedReference(HeapGraphEdge::kInternal,
parent_entry, names_->GetName(index), child_entry);
names_->GetName(index),
child_entry);
} }
MarkVisitedField(field_offset); MarkVisitedField(field_offset);
} }
...@@ -1637,7 +1583,7 @@ void V8HeapExplorer::SetHiddenReference(HeapObject* parent_obj, ...@@ -1637,7 +1583,7 @@ void V8HeapExplorer::SetHiddenReference(HeapObject* parent_obj,
HeapEntry* child_entry = GetEntry(child_obj); HeapEntry* child_entry = GetEntry(child_obj);
if (child_entry != nullptr && IsEssentialObject(child_obj) && if (child_entry != nullptr && IsEssentialObject(child_obj) &&
IsEssentialHiddenReference(parent_obj, field_offset)) { IsEssentialHiddenReference(parent_obj, field_offset)) {
filler_->SetIndexedReference(HeapGraphEdge::kHidden, parent_entry, index, parent_entry->SetIndexedReference(HeapGraphEdge::kHidden, index,
child_entry); child_entry);
} }
} }
...@@ -1650,9 +1596,7 @@ void V8HeapExplorer::SetWeakReference(HeapObject* parent_obj, ...@@ -1650,9 +1596,7 @@ void V8HeapExplorer::SetWeakReference(HeapObject* parent_obj,
HeapEntry* child_entry = GetEntry(child_obj); HeapEntry* child_entry = GetEntry(child_obj);
if (child_entry == nullptr) return; if (child_entry == nullptr) return;
if (IsEssentialObject(child_obj)) { if (IsEssentialObject(child_obj)) {
filler_->SetNamedReference(HeapGraphEdge::kWeak, parent_entry->SetNamedReference(HeapGraphEdge::kWeak, reference_name,
parent_entry,
reference_name,
child_entry); child_entry);
} }
MarkVisitedField(field_offset); MarkVisitedField(field_offset);
...@@ -1665,10 +1609,8 @@ void V8HeapExplorer::SetWeakReference(HeapObject* parent_obj, ...@@ -1665,10 +1609,8 @@ void V8HeapExplorer::SetWeakReference(HeapObject* parent_obj,
HeapEntry* child_entry = GetEntry(child_obj); HeapEntry* child_entry = GetEntry(child_obj);
if (child_entry == nullptr) return; if (child_entry == nullptr) return;
if (IsEssentialObject(child_obj)) { if (IsEssentialObject(child_obj)) {
filler_->SetNamedReference(HeapGraphEdge::kWeak, parent_entry->SetNamedReference(
parent_entry, HeapGraphEdge::kWeak, names_->GetFormatted("%d", index), child_entry);
names_->GetFormatted("%d", index),
child_entry);
} }
MarkVisitedField(field_offset); MarkVisitedField(field_offset);
} }
...@@ -1706,26 +1648,25 @@ void V8HeapExplorer::SetPropertyReference( ...@@ -1706,26 +1648,25 @@ void V8HeapExplorer::SetPropertyReference(
.get()) .get())
: names_->GetName(reference_name); : names_->GetName(reference_name);
filler_->SetNamedReference(type, parent_entry, name, child_entry); parent_entry->SetNamedReference(type, name, child_entry);
MarkVisitedField(field_offset); MarkVisitedField(field_offset);
} }
void V8HeapExplorer::SetRootGcRootsReference() { void V8HeapExplorer::SetRootGcRootsReference() {
filler_->SetIndexedAutoIndexReference( snapshot_->root()->SetIndexedAutoIndexReference(HeapGraphEdge::kElement,
HeapGraphEdge::kElement, snapshot_->root(), snapshot_->gc_roots()); snapshot_->gc_roots());
} }
void V8HeapExplorer::SetUserGlobalReference(Object* child_obj) { void V8HeapExplorer::SetUserGlobalReference(Object* child_obj) {
HeapEntry* child_entry = GetEntry(child_obj); HeapEntry* child_entry = GetEntry(child_obj);
DCHECK_NOT_NULL(child_entry); DCHECK_NOT_NULL(child_entry);
filler_->SetNamedAutoIndexReference(HeapGraphEdge::kShortcut, snapshot_->root()->SetNamedAutoIndexReference(HeapGraphEdge::kShortcut,
snapshot_->root(), nullptr, child_entry); nullptr, child_entry, names_);
} }
void V8HeapExplorer::SetGcRootsReference(Root root) { void V8HeapExplorer::SetGcRootsReference(Root root) {
filler_->SetIndexedAutoIndexReference(HeapGraphEdge::kElement, snapshot_->gc_roots()->SetIndexedAutoIndexReference(
snapshot_->gc_roots(), HeapGraphEdge::kElement, snapshot_->gc_subroot(root));
snapshot_->gc_subroot(root));
} }
void V8HeapExplorer::SetGcSubrootReference(Root root, const char* description, void V8HeapExplorer::SetGcSubrootReference(Root root, const char* description,
...@@ -1736,11 +1677,11 @@ void V8HeapExplorer::SetGcSubrootReference(Root root, const char* description, ...@@ -1736,11 +1677,11 @@ void V8HeapExplorer::SetGcSubrootReference(Root root, const char* description,
HeapGraphEdge::Type edge_type = HeapGraphEdge::Type edge_type =
is_weak ? HeapGraphEdge::kWeak : HeapGraphEdge::kInternal; is_weak ? HeapGraphEdge::kWeak : HeapGraphEdge::kInternal;
if (name != nullptr) { if (name != nullptr) {
filler_->SetNamedReference(edge_type, snapshot_->gc_subroot(root), name, snapshot_->gc_subroot(root)->SetNamedReference(edge_type, name,
child_entry); child_entry);
} else { } else {
filler_->SetNamedAutoIndexReference(edge_type, snapshot_->gc_subroot(root), snapshot_->gc_subroot(root)->SetNamedAutoIndexReference(
description, child_entry); edge_type, description, child_entry, names_);
} }
// Add a shortcut to JS global object reference at snapshot root. // Add a shortcut to JS global object reference at snapshot root.
...@@ -2017,8 +1958,7 @@ NativeObjectsExplorer::NativeObjectsExplorer( ...@@ -2017,8 +1958,7 @@ NativeObjectsExplorer::NativeObjectsExplorer(
native_entries_allocator_( native_entries_allocator_(
new BasicHeapEntriesAllocator(snapshot, HeapEntry::kNative)), new BasicHeapEntriesAllocator(snapshot, HeapEntry::kNative)),
embedder_graph_entries_allocator_( embedder_graph_entries_allocator_(
new EmbedderGraphEntriesAllocator(snapshot)), new EmbedderGraphEntriesAllocator(snapshot)) {}
filler_(nullptr) {}
NativeObjectsExplorer::~NativeObjectsExplorer() { NativeObjectsExplorer::~NativeObjectsExplorer() {
for (auto map_entry : objects_by_info_) { for (auto map_entry : objects_by_info_) {
...@@ -2077,14 +2017,14 @@ void NativeObjectsExplorer::FillEdges() { ...@@ -2077,14 +2017,14 @@ void NativeObjectsExplorer::FillEdges() {
*pair.first->Get(reinterpret_cast<v8::Isolate*>(isolate_))); *pair.first->Get(reinterpret_cast<v8::Isolate*>(isolate_)));
HeapObject* parent = HeapObject::cast(*parent_object); HeapObject* parent = HeapObject::cast(*parent_object);
HeapEntry* parent_entry = HeapEntry* parent_entry =
filler_->FindOrAddEntry(parent, native_entries_allocator_.get()); generator_->FindOrAddEntry(parent, native_entries_allocator_.get());
DCHECK_NOT_NULL(parent_entry); DCHECK_NOT_NULL(parent_entry);
Handle<Object> child_object = v8::Utils::OpenHandle( Handle<Object> child_object = v8::Utils::OpenHandle(
*pair.second->Get(reinterpret_cast<v8::Isolate*>(isolate_))); *pair.second->Get(reinterpret_cast<v8::Isolate*>(isolate_)));
HeapObject* child = HeapObject::cast(*child_object); HeapObject* child = HeapObject::cast(*child_object);
HeapEntry* child_entry = HeapEntry* child_entry =
filler_->FindOrAddEntry(child, native_entries_allocator_.get()); generator_->FindOrAddEntry(child, native_entries_allocator_.get());
filler_->SetNamedReference(HeapGraphEdge::kInternal, parent_entry, "native", parent_entry->SetNamedReference(HeapGraphEdge::kInternal, "native",
child_entry); child_entry);
} }
edges_.clear(); edges_.clear();
...@@ -2107,20 +2047,20 @@ HeapEntry* NativeObjectsExplorer::EntryForEmbedderGraphNode( ...@@ -2107,20 +2047,20 @@ HeapEntry* NativeObjectsExplorer::EntryForEmbedderGraphNode(
node = wrapper; node = wrapper;
} }
if (node->IsEmbedderNode()) { if (node->IsEmbedderNode()) {
return filler_->FindOrAddEntry(node, return generator_->FindOrAddEntry(node,
embedder_graph_entries_allocator_.get()); embedder_graph_entries_allocator_.get());
} else { } else {
EmbedderGraphImpl::V8NodeImpl* v8_node = EmbedderGraphImpl::V8NodeImpl* v8_node =
static_cast<EmbedderGraphImpl::V8NodeImpl*>(node); static_cast<EmbedderGraphImpl::V8NodeImpl*>(node);
Object* object = v8_node->GetObject(); Object* object = v8_node->GetObject();
if (object->IsSmi()) return nullptr; if (object->IsSmi()) return nullptr;
return filler_->FindEntry(HeapObject::cast(object)); return generator_->FindEntry(HeapObject::cast(object));
} }
} }
bool NativeObjectsExplorer::IterateAndExtractReferences( bool NativeObjectsExplorer::IterateAndExtractReferences(
SnapshotFiller* filler) { HeapSnapshotGenerator* generator) {
filler_ = filler; generator_ = generator;
if (FLAG_heap_profiler_use_embedder_graph && if (FLAG_heap_profiler_use_embedder_graph &&
snapshot_->profiler()->HasBuildEmbedderGraphCallback()) { snapshot_->profiler()->HasBuildEmbedderGraphCallback()) {
...@@ -2130,9 +2070,8 @@ bool NativeObjectsExplorer::IterateAndExtractReferences( ...@@ -2130,9 +2070,8 @@ bool NativeObjectsExplorer::IterateAndExtractReferences(
snapshot_->profiler()->BuildEmbedderGraph(isolate_, &graph); snapshot_->profiler()->BuildEmbedderGraph(isolate_, &graph);
for (const auto& node : graph.nodes()) { for (const auto& node : graph.nodes()) {
if (node->IsRootNode()) { if (node->IsRootNode()) {
filler_->SetIndexedAutoIndexReference( snapshot_->root()->SetIndexedAutoIndexReference(
HeapGraphEdge::kElement, snapshot_->root(), HeapGraphEdge::kElement, EntryForEmbedderGraphNode(node.get()));
EntryForEmbedderGraphNode(node.get()));
} }
// Adjust the name and the type of the V8 wrapper node. // Adjust the name and the type of the V8 wrapper node.
auto wrapper = node->WrapperNode(); auto wrapper = node->WrapperNode();
...@@ -2147,18 +2086,15 @@ bool NativeObjectsExplorer::IterateAndExtractReferences( ...@@ -2147,18 +2086,15 @@ bool NativeObjectsExplorer::IterateAndExtractReferences(
// Fill edges of the graph. // Fill edges of the graph.
for (const auto& edge : graph.edges()) { for (const auto& edge : graph.edges()) {
HeapEntry* from = EntryForEmbedderGraphNode(edge.from); HeapEntry* from = EntryForEmbedderGraphNode(edge.from);
// The |from| and |to| can nullptr if the corrsponding node is a V8 node // |from| and |to| can be nullptr if the corresponding node is a V8 node
// pointing to a Smi. // pointing to a Smi.
if (!from) continue; if (!from) continue;
HeapEntry* to = EntryForEmbedderGraphNode(edge.to); HeapEntry* to = EntryForEmbedderGraphNode(edge.to);
if (to) { if (!to) continue;
if (edge.name == nullptr) { if (edge.name == nullptr) {
filler_->SetIndexedAutoIndexReference(HeapGraphEdge::kElement, from, from->SetIndexedAutoIndexReference(HeapGraphEdge::kElement, to);
to);
} else { } else {
filler_->SetNamedReference(HeapGraphEdge::kInternal, from, edge.name, from->SetNamedReference(HeapGraphEdge::kInternal, edge.name, to);
to);
}
} }
} }
} else { } else {
...@@ -2176,7 +2112,7 @@ bool NativeObjectsExplorer::IterateAndExtractReferences( ...@@ -2176,7 +2112,7 @@ bool NativeObjectsExplorer::IterateAndExtractReferences(
SetRootNativeRootsReference(); SetRootNativeRootsReference();
} }
} }
filler_ = nullptr; generator_ = nullptr;
return true; return true;
} }
...@@ -2192,39 +2128,37 @@ NativeGroupRetainedObjectInfo* NativeObjectsExplorer::FindOrAddGroupInfo( ...@@ -2192,39 +2128,37 @@ NativeGroupRetainedObjectInfo* NativeObjectsExplorer::FindOrAddGroupInfo(
void NativeObjectsExplorer::SetNativeRootReference( void NativeObjectsExplorer::SetNativeRootReference(
v8::RetainedObjectInfo* info) { v8::RetainedObjectInfo* info) {
HeapEntry* child_entry = HeapEntry* child_entry =
filler_->FindOrAddEntry(info, native_entries_allocator_.get()); generator_->FindOrAddEntry(info, native_entries_allocator_.get());
DCHECK_NOT_NULL(child_entry); DCHECK_NOT_NULL(child_entry);
NativeGroupRetainedObjectInfo* group_info = NativeGroupRetainedObjectInfo* group_info =
FindOrAddGroupInfo(info->GetGroupLabel()); FindOrAddGroupInfo(info->GetGroupLabel());
HeapEntry* group_entry = HeapEntry* group_entry = generator_->FindOrAddEntry(
filler_->FindOrAddEntry(group_info, synthetic_entries_allocator_.get()); group_info, synthetic_entries_allocator_.get());
filler_->SetNamedAutoIndexReference(HeapGraphEdge::kInternal, group_entry, group_entry->SetNamedAutoIndexReference(HeapGraphEdge::kInternal, nullptr,
nullptr, child_entry); child_entry, names_);
} }
void NativeObjectsExplorer::SetWrapperNativeReferences( void NativeObjectsExplorer::SetWrapperNativeReferences(
HeapObject* wrapper, v8::RetainedObjectInfo* info) { HeapObject* wrapper, v8::RetainedObjectInfo* info) {
HeapEntry* wrapper_entry = filler_->FindEntry(wrapper); HeapEntry* wrapper_entry = generator_->FindEntry(wrapper);
DCHECK_NOT_NULL(wrapper_entry); DCHECK_NOT_NULL(wrapper_entry);
HeapEntry* info_entry = HeapEntry* info_entry =
filler_->FindOrAddEntry(info, native_entries_allocator_.get()); generator_->FindOrAddEntry(info, native_entries_allocator_.get());
DCHECK_NOT_NULL(info_entry); DCHECK_NOT_NULL(info_entry);
filler_->SetNamedReference(HeapGraphEdge::kInternal, wrapper_entry, "native", wrapper_entry->SetNamedReference(HeapGraphEdge::kInternal, "native",
info_entry); info_entry);
filler_->SetIndexedAutoIndexReference(HeapGraphEdge::kElement, info_entry, info_entry->SetIndexedAutoIndexReference(HeapGraphEdge::kElement,
wrapper_entry); wrapper_entry);
} }
void NativeObjectsExplorer::SetRootNativeRootsReference() { void NativeObjectsExplorer::SetRootNativeRootsReference() {
for (auto map_entry : native_groups_) { for (auto map_entry : native_groups_) {
NativeGroupRetainedObjectInfo* group_info = map_entry.second; NativeGroupRetainedObjectInfo* group_info = map_entry.second;
HeapEntry* group_entry = HeapEntry* group_entry =
filler_->FindOrAddEntry(group_info, native_entries_allocator_.get()); generator_->FindOrAddEntry(group_info, native_entries_allocator_.get());
DCHECK_NOT_NULL(group_entry); DCHECK_NOT_NULL(group_entry);
filler_->SetIndexedAutoIndexReference(HeapGraphEdge::kElement, snapshot_->root()->SetIndexedAutoIndexReference(HeapGraphEdge::kElement,
snapshot_->root(), group_entry); group_entry);
} }
} }
...@@ -2331,12 +2265,10 @@ void HeapSnapshotGenerator::InitProgressCounter() { ...@@ -2331,12 +2265,10 @@ void HeapSnapshotGenerator::InitProgressCounter() {
} }
bool HeapSnapshotGenerator::FillReferences() { bool HeapSnapshotGenerator::FillReferences() {
SnapshotFiller filler(snapshot_, &entries_map_); return v8_heap_explorer_.IterateAndExtractReferences(this) &&
return v8_heap_explorer_.IterateAndExtractReferences(&filler) && dom_explorer_.IterateAndExtractReferences(this);
dom_explorer_.IterateAndExtractReferences(&filler);
} }
template<int bytes> struct MaxDecimalDigitsIn; template<int bytes> struct MaxDecimalDigitsIn;
template<> struct MaxDecimalDigitsIn<4> { template<> struct MaxDecimalDigitsIn<4> {
static const int kSigned = 11; static const int kSigned = 11;
...@@ -2347,7 +2279,6 @@ template<> struct MaxDecimalDigitsIn<8> { ...@@ -2347,7 +2279,6 @@ template<> struct MaxDecimalDigitsIn<8> {
static const int kUnsigned = 20; static const int kUnsigned = 20;
}; };
class OutputStreamWriter { class OutputStreamWriter {
public: public:
explicit OutputStreamWriter(v8::OutputStream* stream) explicit OutputStreamWriter(v8::OutputStream* stream)
......
...@@ -29,6 +29,7 @@ class HeapEntry; ...@@ -29,6 +29,7 @@ class HeapEntry;
class HeapIterator; class HeapIterator;
class HeapProfiler; class HeapProfiler;
class HeapSnapshot; class HeapSnapshot;
class HeapSnapshotGenerator;
class JSArrayBuffer; class JSArrayBuffer;
class JSCollection; class JSCollection;
class JSGeneratorObject; class JSGeneratorObject;
...@@ -36,7 +37,6 @@ class JSGlobalObject; ...@@ -36,7 +37,6 @@ class JSGlobalObject;
class JSGlobalProxy; class JSGlobalProxy;
class JSPromise; class JSPromise;
class JSWeakCollection; class JSWeakCollection;
class SnapshotFiller;
struct SourceLocation { struct SourceLocation {
SourceLocation(int entry_index, int scriptId, int line, int col) SourceLocation(int entry_index, int scriptId, int line, int col)
...@@ -136,6 +136,13 @@ class HeapEntry { ...@@ -136,6 +136,13 @@ class HeapEntry {
HeapGraphEdge::Type type, int index, HeapEntry* entry); HeapGraphEdge::Type type, int index, HeapEntry* entry);
void SetNamedReference( void SetNamedReference(
HeapGraphEdge::Type type, const char* name, HeapEntry* entry); HeapGraphEdge::Type type, const char* name, HeapEntry* entry);
void SetIndexedAutoIndexReference(HeapGraphEdge::Type type,
HeapEntry* child) {
SetIndexedReference(type, children_count_ + 1, child);
}
void SetNamedAutoIndexReference(HeapGraphEdge::Type type,
const char* description, HeapEntry* child,
StringsStorage* strings);
void Print( void Print(
const char* prefix, const char* edge_name, int max_depth, int indent); const char* prefix, const char* edge_name, int max_depth, int indent);
...@@ -310,9 +317,10 @@ class V8HeapExplorer : public HeapEntriesAllocator { ...@@ -310,9 +317,10 @@ class V8HeapExplorer : public HeapEntriesAllocator {
SnapshottingProgressReportingInterface* progress, SnapshottingProgressReportingInterface* progress,
v8::HeapProfiler::ObjectNameResolver* resolver); v8::HeapProfiler::ObjectNameResolver* resolver);
~V8HeapExplorer() override = default; ~V8HeapExplorer() override = default;
HeapEntry* AllocateEntry(HeapThing ptr) override; HeapEntry* AllocateEntry(HeapThing ptr) override;
int EstimateObjectsCount(); int EstimateObjectsCount();
bool IterateAndExtractReferences(SnapshotFiller* filler); bool IterateAndExtractReferences(HeapSnapshotGenerator* generator);
void TagGlobalObjects(); void TagGlobalObjects();
void TagCodeObject(Code* code); void TagCodeObject(Code* code);
void TagBuiltinCodeObject(Code* code, const char* name); void TagBuiltinCodeObject(Code* code, const char* name);
...@@ -425,7 +433,7 @@ class V8HeapExplorer : public HeapEntriesAllocator { ...@@ -425,7 +433,7 @@ class V8HeapExplorer : public HeapEntriesAllocator {
StringsStorage* names_; StringsStorage* names_;
HeapObjectsMap* heap_object_map_; HeapObjectsMap* heap_object_map_;
SnapshottingProgressReportingInterface* progress_; SnapshottingProgressReportingInterface* progress_;
SnapshotFiller* filler_; HeapSnapshotGenerator* generator_ = nullptr;
std::unordered_map<JSGlobalObject*, const char*> objects_tags_; std::unordered_map<JSGlobalObject*, const char*> objects_tags_;
std::unordered_map<Object*, const char*> strong_gc_subroot_names_; std::unordered_map<Object*, const char*> strong_gc_subroot_names_;
std::unordered_set<JSGlobalObject*> user_roots_; std::unordered_set<JSGlobalObject*> user_roots_;
...@@ -450,7 +458,7 @@ class NativeObjectsExplorer { ...@@ -450,7 +458,7 @@ class NativeObjectsExplorer {
SnapshottingProgressReportingInterface* progress); SnapshottingProgressReportingInterface* progress);
virtual ~NativeObjectsExplorer(); virtual ~NativeObjectsExplorer();
int EstimateObjectsCount(); int EstimateObjectsCount();
bool IterateAndExtractReferences(SnapshotFiller* filler); bool IterateAndExtractReferences(HeapSnapshotGenerator* generator);
private: private:
void FillRetainedObjects(); void FillRetainedObjects();
...@@ -494,7 +502,7 @@ class NativeObjectsExplorer { ...@@ -494,7 +502,7 @@ class NativeObjectsExplorer {
std::unique_ptr<HeapEntriesAllocator> native_entries_allocator_; std::unique_ptr<HeapEntriesAllocator> native_entries_allocator_;
std::unique_ptr<HeapEntriesAllocator> embedder_graph_entries_allocator_; std::unique_ptr<HeapEntriesAllocator> embedder_graph_entries_allocator_;
// Used during references extraction. // Used during references extraction.
SnapshotFiller* filler_; HeapSnapshotGenerator* generator_ = nullptr;
v8::HeapProfiler::RetainerEdges edges_; v8::HeapProfiler::RetainerEdges edges_;
static HeapThing const kNativesRootObject; static HeapThing const kNativesRootObject;
...@@ -504,7 +512,6 @@ class NativeObjectsExplorer { ...@@ -504,7 +512,6 @@ class NativeObjectsExplorer {
DISALLOW_COPY_AND_ASSIGN(NativeObjectsExplorer); DISALLOW_COPY_AND_ASSIGN(NativeObjectsExplorer);
}; };
class HeapSnapshotGenerator : public SnapshottingProgressReportingInterface { class HeapSnapshotGenerator : public SnapshottingProgressReportingInterface {
public: public:
// The HeapEntriesMap instance is used to track a mapping between // The HeapEntriesMap instance is used to track a mapping between
...@@ -517,6 +524,21 @@ class HeapSnapshotGenerator : public SnapshottingProgressReportingInterface { ...@@ -517,6 +524,21 @@ class HeapSnapshotGenerator : public SnapshottingProgressReportingInterface {
Heap* heap); Heap* heap);
bool GenerateSnapshot(); bool GenerateSnapshot();
HeapEntry* FindEntry(HeapThing ptr) {
auto it = entries_map_.find(ptr);
return it != entries_map_.end() ? it->second : nullptr;
}
HeapEntry* AddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) {
return entries_map_.emplace(ptr, allocator->AllocateEntry(ptr))
.first->second;
}
HeapEntry* FindOrAddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) {
HeapEntry* entry = FindEntry(ptr);
return entry != nullptr ? entry : AddEntry(ptr, allocator);
}
private: private:
bool FillReferences(); bool FillReferences();
void ProgressStep() override; void ProgressStep() override;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment