From 60711c074fc66fe6b6cd2284fb11466218ebf6fe Mon Sep 17 00:00:00 2001 From: "mikhail.naganov@gmail.com" Date: Tue, 1 Mar 2011 17:38:49 +0000 Subject: [PATCH] Refactor heap profiler's code to make possible including into heap snapshots non-HeapObjects. This is needed as a preparation for adding DOM subtrees tracking. BUG=none TEST=none Review URL: http://codereview.chromium.org/6596073 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@7004 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/heap-profiler.cc | 45 ++- src/heap-profiler.h | 4 +- src/profile-generator-inl.h | 28 -- src/profile-generator.cc | 805 ++++++++++++++++++++++++-------------------- src/profile-generator.h | 184 ++++++---- 5 files changed, 585 insertions(+), 481 deletions(-) diff --git a/src/heap-profiler.cc b/src/heap-profiler.cc index 732d2f4..07b631f 100644 --- a/src/heap-profiler.cc +++ b/src/heap-profiler.cc @@ -911,22 +911,27 @@ static JSObjectsCluster HeapObjectAsCluster(HeapObject* object) { class CountingRetainersIterator { public: CountingRetainersIterator(const JSObjectsCluster& child_cluster, + HeapEntriesAllocator* allocator, HeapEntriesMap* map) - : child_(ClusterAsHeapObject(child_cluster)), map_(map) { + : child_(ClusterAsHeapObject(child_cluster)), + allocator_(allocator), + map_(map) { if (map_->Map(child_) == NULL) - map_->Pair(child_, HeapEntriesMap::kHeapEntryPlaceholder); + map_->Pair(child_, allocator_, HeapEntriesMap::kHeapEntryPlaceholder); } void Call(const JSObjectsCluster& cluster, const NumberAndSizeInfo& number_and_size) { if (map_->Map(ClusterAsHeapObject(cluster)) == NULL) map_->Pair(ClusterAsHeapObject(cluster), + allocator_, HeapEntriesMap::kHeapEntryPlaceholder); map_->CountReference(ClusterAsHeapObject(cluster), child_); } private: HeapObject* child_; + HeapEntriesAllocator* allocator_; HeapEntriesMap* map_; }; @@ -934,6 +939,7 @@ class CountingRetainersIterator { class AllocatingRetainersIterator { public: AllocatingRetainersIterator(const JSObjectsCluster& child_cluster, + HeapEntriesAllocator*, HeapEntriesMap* map) : child_(ClusterAsHeapObject(child_cluster)), map_(map) { child_entry_ = map_->Map(child_); @@ -966,8 +972,9 @@ template class AggregatingRetainerTreeIterator { public: explicit AggregatingRetainerTreeIterator(ClustersCoarser* coarser, + HeapEntriesAllocator* allocator, HeapEntriesMap* map) - : coarser_(coarser), map_(map) { + : coarser_(coarser), allocator_(allocator), map_(map) { } void Call(const JSObjectsCluster& cluster, JSObjectsClusterTree* tree) { @@ -981,25 +988,28 @@ class AggregatingRetainerTreeIterator { tree->ForEach(&retainers_aggregator); tree_to_iterate = &dest_tree_; } - RetainersIterator iterator(cluster, map_); + RetainersIterator iterator(cluster, allocator_, map_); tree_to_iterate->ForEach(&iterator); } private: ClustersCoarser* coarser_; + HeapEntriesAllocator* allocator_; HeapEntriesMap* map_; }; -class AggregatedRetainerTreeAllocator { +class AggregatedRetainerTreeAllocator : public HeapEntriesAllocator { public: AggregatedRetainerTreeAllocator(HeapSnapshot* snapshot, int* root_child_index) : snapshot_(snapshot), root_child_index_(root_child_index) { } + ~AggregatedRetainerTreeAllocator() { } - HeapEntry* GetEntry( - HeapObject* obj, int children_count, int retainers_count) { + HeapEntry* AllocateEntry( + HeapThing ptr, int children_count, int retainers_count) { + HeapObject* obj = reinterpret_cast(ptr); JSObjectsCluster cluster = HeapObjectAsCluster(obj); const char* name = cluster.GetSpecialCaseName(); if (name == NULL) { @@ -1018,12 +1028,13 @@ class AggregatedRetainerTreeAllocator { template void AggregatedHeapSnapshotGenerator::IterateRetainers( - HeapEntriesMap* entries_map) { + HeapEntriesAllocator* allocator, HeapEntriesMap* entries_map) { RetainerHeapProfile* p = agg_snapshot_->js_retainer_profile(); AggregatingRetainerTreeIterator agg_ret_iter_1( - p->coarser(), entries_map); + p->coarser(), allocator, entries_map); p->retainers_tree()->ForEach(&agg_ret_iter_1); - AggregatingRetainerTreeIterator agg_ret_iter_2(NULL, entries_map); + AggregatingRetainerTreeIterator agg_ret_iter_2( + NULL, allocator, entries_map); p->aggregator()->output_tree().ForEach(&agg_ret_iter_2); } @@ -1042,7 +1053,9 @@ void AggregatedHeapSnapshotGenerator::FillHeapSnapshot(HeapSnapshot* snapshot) { agg_snapshot_->js_cons_profile()->ForEach(&counting_cons_iter); histogram_entities_count += counting_cons_iter.entities_count(); HeapEntriesMap entries_map; - IterateRetainers(&entries_map); + int root_child_index = 0; + AggregatedRetainerTreeAllocator allocator(snapshot, &root_child_index); + IterateRetainers(&allocator, &entries_map); histogram_entities_count += entries_map.entries_count(); histogram_children_count += entries_map.total_children_count(); histogram_retainers_count += entries_map.total_retainers_count(); @@ -1056,10 +1069,7 @@ void AggregatedHeapSnapshotGenerator::FillHeapSnapshot(HeapSnapshot* snapshot) { snapshot->AllocateEntries(histogram_entities_count, histogram_children_count, histogram_retainers_count); - snapshot->AddEntry(HeapSnapshot::kInternalRootObject, - root_children_count, - 0); - int root_child_index = 0; + snapshot->AddRootEntry(root_children_count); for (int i = FIRST_NONSTRING_TYPE; i <= kAllStringsType; ++i) { if (agg_snapshot_->info()[i].bytes() > 0) { AddEntryFromAggregatedSnapshot(snapshot, @@ -1075,11 +1085,10 @@ void AggregatedHeapSnapshotGenerator::FillHeapSnapshot(HeapSnapshot* snapshot) { AllocatingConstructorHeapProfileIterator alloc_cons_iter( snapshot, &root_child_index); agg_snapshot_->js_cons_profile()->ForEach(&alloc_cons_iter); - AggregatedRetainerTreeAllocator allocator(snapshot, &root_child_index); - entries_map.UpdateEntries(&allocator); + entries_map.AllocateEntries(); // Fill up references. - IterateRetainers(&entries_map); + IterateRetainers(&allocator, &entries_map); snapshot->SetDominatorsToSelf(); } diff --git a/src/heap-profiler.h b/src/heap-profiler.h index 90c664e..20ba457 100644 --- a/src/heap-profiler.h +++ b/src/heap-profiler.h @@ -340,6 +340,7 @@ class AggregatedHeapSnapshot { class HeapEntriesMap; +class HeapEntriesAllocator; class HeapSnapshot; class AggregatedHeapSnapshotGenerator { @@ -354,7 +355,8 @@ class AggregatedHeapSnapshotGenerator { void CalculateStringsStats(); void CollectStats(HeapObject* obj); template - void IterateRetainers(HeapEntriesMap* entries_map); + void IterateRetainers( + HeapEntriesAllocator* allocator, HeapEntriesMap* entries_map); AggregatedHeapSnapshot* agg_snapshot_; }; diff --git a/src/profile-generator-inl.h b/src/profile-generator-inl.h index 4bcfa9b..747e5c7 100644 --- a/src/profile-generator-inl.h +++ b/src/profile-generator-inl.h @@ -121,34 +121,6 @@ uint64_t HeapEntry::id() { return id_adaptor.returned_id; } - -template -void HeapEntriesMap::UpdateEntries(Visitor* visitor) { - for (HashMap::Entry* p = entries_.Start(); - p != NULL; - p = entries_.Next(p)) { - EntryInfo* entry_info = reinterpret_cast(p->value); - entry_info->entry = visitor->GetEntry( - reinterpret_cast(p->key), - entry_info->children_count, - entry_info->retainers_count); - entry_info->children_count = 0; - entry_info->retainers_count = 0; - } -} - - -bool HeapSnapshotGenerator::ReportProgress(bool force) { - const int kProgressReportGranularity = 10000; - if (control_ != NULL - && (force || progress_counter_ % kProgressReportGranularity == 0)) { - return - control_->ReportProgressValue(progress_counter_, progress_total_) == - v8::ActivityControl::kContinue; - } - return true; -} - } } // namespace v8::internal #endif // ENABLE_LOGGING_AND_PROFILING diff --git a/src/profile-generator.cc b/src/profile-generator.cc index 261b3d6..7612eab 100644 --- a/src/profile-generator.cc +++ b/src/profile-generator.cc @@ -1177,12 +1177,6 @@ void HeapGraphPath::Print() { } -HeapObject *const HeapSnapshot::kInternalRootObject = - reinterpret_cast(1); -HeapObject *const HeapSnapshot::kGcRootsObject = - reinterpret_cast(2); - - // It is very important to keep objects that form a heap snapshot // as small as possible. namespace { // Avoid littering the global namespace. @@ -1253,96 +1247,6 @@ void HeapSnapshot::AllocateEntries(int entries_count, } -HeapEntry* HeapSnapshot::AddEntry(HeapObject* object, - int children_count, - int retainers_count) { - if (object == kInternalRootObject) { - ASSERT(root_entry_ == NULL); - ASSERT(retainers_count == 0); - return (root_entry_ = AddEntry(HeapEntry::kObject, - "", - HeapObjectsMap::kInternalRootObjectId, - 0, - children_count, - retainers_count)); - } else if (object == kGcRootsObject) { - ASSERT(gc_roots_entry_ == NULL); - return (gc_roots_entry_ = AddEntry(HeapEntry::kObject, - "(GC roots)", - HeapObjectsMap::kGcRootsObjectId, - 0, - children_count, - retainers_count)); - } else if (object->IsJSFunction()) { - JSFunction* func = JSFunction::cast(object); - SharedFunctionInfo* shared = func->shared(); - return AddEntry(object, - HeapEntry::kClosure, - collection_->GetName(String::cast(shared->name())), - children_count, - retainers_count); - } else if (object->IsJSRegExp()) { - JSRegExp* re = JSRegExp::cast(object); - return AddEntry(object, - HeapEntry::kRegExp, - collection_->GetName(re->Pattern()), - children_count, - retainers_count); - } else if (object->IsJSObject()) { - return AddEntry(object, - HeapEntry::kObject, - collection_->GetName(GetConstructorNameForHeapProfile( - JSObject::cast(object))), - children_count, - retainers_count); - } else if (object->IsString()) { - return AddEntry(object, - HeapEntry::kString, - collection_->GetName(String::cast(object)), - children_count, - retainers_count); - } else if (object->IsCode()) { - return AddEntry(object, - HeapEntry::kCode, - "", - children_count, - retainers_count); - } else if (object->IsSharedFunctionInfo()) { - SharedFunctionInfo* shared = SharedFunctionInfo::cast(object); - return AddEntry(object, - HeapEntry::kCode, - collection_->GetName(String::cast(shared->name())), - children_count, - retainers_count); - } else if (object->IsScript()) { - Script* script = Script::cast(object); - return AddEntry(object, - HeapEntry::kCode, - script->name()->IsString() ? - collection_->GetName(String::cast(script->name())) : "", - children_count, - retainers_count); - } else if (object->IsFixedArray()) { - return AddEntry(object, - HeapEntry::kArray, - "", - children_count, - retainers_count); - } else if (object->IsHeapNumber()) { - return AddEntry(object, - HeapEntry::kHeapNumber, - "number", - children_count, - retainers_count); - } - return AddEntry(object, - HeapEntry::kHidden, - "system", - children_count, - retainers_count); -} - - static void HeapEntryClearPaint(HeapEntry** entry_ptr) { (*entry_ptr)->clear_paint(); } @@ -1352,17 +1256,26 @@ void HeapSnapshot::ClearPaint() { } -HeapEntry* HeapSnapshot::AddEntry(HeapObject* object, - HeapEntry::Type type, - const char* name, - int children_count, - int retainers_count) { - return AddEntry(type, - name, - collection_->GetObjectId(object->address()), - object->Size(), - children_count, - retainers_count); +HeapEntry* HeapSnapshot::AddRootEntry(int children_count) { + ASSERT(root_entry_ == NULL); + return (root_entry_ = AddEntry(HeapEntry::kObject, + "", + HeapObjectsMap::kInternalRootObjectId, + 0, + children_count, + 0)); +} + + +HeapEntry* HeapSnapshot::AddGcRootsEntry(int children_count, + int retainers_count) { + ASSERT(gc_roots_entry_ == NULL); + return (gc_roots_entry_ = AddEntry(HeapEntry::kObject, + "(GC roots)", + HeapObjectsMap::kGcRootsObjectId, + 0, + children_count, + retainers_count)); } @@ -1615,7 +1528,7 @@ HeapEntry *const HeapEntriesMap::kHeapEntryPlaceholder = reinterpret_cast(1); HeapEntriesMap::HeapEntriesMap() - : entries_(HeapObjectsMatch), + : entries_(HeapThingsMatch), entries_count_(0), total_children_count_(0), total_retainers_count_(0) { @@ -1629,8 +1542,23 @@ HeapEntriesMap::~HeapEntriesMap() { } -HeapEntry* HeapEntriesMap::Map(HeapObject* object) { - HashMap::Entry* cache_entry = entries_.Lookup(object, Hash(object), false); +void HeapEntriesMap::AllocateEntries() { + for (HashMap::Entry* p = entries_.Start(); + p != NULL; + p = entries_.Next(p)) { + EntryInfo* entry_info = reinterpret_cast(p->value); + entry_info->entry = entry_info->allocator->AllocateEntry( + p->key, + entry_info->children_count, + entry_info->retainers_count); + entry_info->children_count = 0; + entry_info->retainers_count = 0; + } +} + + +HeapEntry* HeapEntriesMap::Map(HeapThing thing) { + HashMap::Entry* cache_entry = entries_.Lookup(thing, Hash(thing), false); if (cache_entry != NULL) { EntryInfo* entry_info = reinterpret_cast(cache_entry->value); return entry_info->entry; @@ -1640,15 +1568,16 @@ HeapEntry* HeapEntriesMap::Map(HeapObject* object) { } -void HeapEntriesMap::Pair(HeapObject* object, HeapEntry* entry) { - HashMap::Entry* cache_entry = entries_.Lookup(object, Hash(object), true); +void HeapEntriesMap::Pair( + HeapThing thing, HeapEntriesAllocator* allocator, HeapEntry* entry) { + HashMap::Entry* cache_entry = entries_.Lookup(thing, Hash(thing), true); ASSERT(cache_entry->value == NULL); - cache_entry->value = new EntryInfo(entry); + cache_entry->value = new EntryInfo(entry, allocator); ++entries_count_; } -void HeapEntriesMap::CountReference(HeapObject* from, HeapObject* to, +void HeapEntriesMap::CountReference(HeapThing from, HeapThing to, int* prev_children_count, int* prev_retainers_count) { HashMap::Entry* from_cache_entry = entries_.Lookup(from, Hash(from), false); @@ -1671,7 +1600,7 @@ void HeapEntriesMap::CountReference(HeapObject* from, HeapObject* to, HeapObjectsSet::HeapObjectsSet() - : entries_(HeapEntriesMap::HeapObjectsMatch) { + : entries_(HeapEntriesMap::HeapThingsMatch) { } @@ -1700,206 +1629,144 @@ void HeapObjectsSet::Insert(Object* obj) { } -HeapSnapshotGenerator::HeapSnapshotGenerator(HeapSnapshot* snapshot, - v8::ActivityControl* control) +HeapObject *const V8HeapExplorer::kInternalRootObject = + reinterpret_cast(1); +HeapObject *const V8HeapExplorer::kGcRootsObject = + reinterpret_cast(2); + + +V8HeapExplorer::V8HeapExplorer( + HeapSnapshot* snapshot, + SnapshottingProgressReportingInterface* progress) : snapshot_(snapshot), - control_(control), - collection_(snapshot->collection()), + collection_(snapshot_->collection()), + progress_(progress), filler_(NULL) { } -class SnapshotCounter : public HeapSnapshotGenerator::SnapshotFillerInterface { - public: - explicit SnapshotCounter(HeapEntriesMap* entries) - : entries_(entries) { } - HeapEntry* AddEntry(HeapObject* obj) { - entries_->Pair(obj, HeapEntriesMap::kHeapEntryPlaceholder); - return HeapEntriesMap::kHeapEntryPlaceholder; - } - void SetIndexedReference(HeapGraphEdge::Type, - HeapObject* parent_obj, - HeapEntry*, - int, - Object* child_obj, - HeapEntry*) { - entries_->CountReference(parent_obj, HeapObject::cast(child_obj)); - } - void SetNamedReference(HeapGraphEdge::Type, - HeapObject* parent_obj, - HeapEntry*, - const char*, - Object* child_obj, - HeapEntry*) { - entries_->CountReference(parent_obj, HeapObject::cast(child_obj)); - } - void SetRootShortcutReference(Object* child_obj, HeapEntry*) { - entries_->CountReference( - HeapSnapshot::kInternalRootObject, HeapObject::cast(child_obj)); - } - void SetRootGcRootsReference() { - entries_->CountReference( - HeapSnapshot::kInternalRootObject, HeapSnapshot::kGcRootsObject); - } - void SetStrongRootReference(Object* child_obj, HeapEntry*) { - entries_->CountReference( - HeapSnapshot::kGcRootsObject, HeapObject::cast(child_obj)); - } - private: - HeapEntriesMap* entries_; -}; - - -class SnapshotFiller : public HeapSnapshotGenerator::SnapshotFillerInterface { - public: - explicit SnapshotFiller(HeapSnapshot* snapshot, HeapEntriesMap* entries) - : snapshot_(snapshot), - collection_(snapshot->collection()), - entries_(entries) { } - HeapEntry* AddEntry(HeapObject* obj) { - UNREACHABLE(); - return NULL; - } - void SetIndexedReference(HeapGraphEdge::Type type, - HeapObject* parent_obj, - HeapEntry* parent_entry, - int index, - Object* child_obj, - HeapEntry* child_entry) { - int child_index, retainer_index; - entries_->CountReference(parent_obj, - HeapObject::cast(child_obj), - &child_index, - &retainer_index); - parent_entry->SetIndexedReference( - type, child_index, index, child_entry, retainer_index); - } - void SetNamedReference(HeapGraphEdge::Type type, - HeapObject* parent_obj, - HeapEntry* parent_entry, - const char* reference_name, - Object* child_obj, - HeapEntry* child_entry) { - int child_index, retainer_index; - entries_->CountReference(parent_obj, HeapObject::cast(child_obj), - &child_index, &retainer_index); - parent_entry->SetNamedReference(type, - child_index, - reference_name, - child_entry, - retainer_index); - } - void SetRootGcRootsReference() { - int child_index, retainer_index; - entries_->CountReference(HeapSnapshot::kInternalRootObject, - HeapSnapshot::kGcRootsObject, - &child_index, - &retainer_index); - snapshot_->root()->SetIndexedReference(HeapGraphEdge::kElement, - child_index, - child_index + 1, - snapshot_->gc_roots(), - retainer_index); - } - void SetRootShortcutReference(Object* child_obj, - HeapEntry* child_entry) { - int child_index, retainer_index; - entries_->CountReference(HeapSnapshot::kInternalRootObject, - HeapObject::cast(child_obj), - &child_index, - &retainer_index); - snapshot_->root()->SetNamedReference(HeapGraphEdge::kShortcut, - child_index, - collection_->GetName(child_index + 1), - child_entry, - retainer_index); - } - void SetStrongRootReference(Object* child_obj, - HeapEntry* child_entry) { - int child_index, retainer_index; - entries_->CountReference(HeapSnapshot::kGcRootsObject, - HeapObject::cast(child_obj), - &child_index, - &retainer_index); - snapshot_->gc_roots()->SetIndexedReference(HeapGraphEdge::kElement, - child_index, - child_index + 1, - child_entry, - retainer_index); - } - private: - HeapSnapshot* snapshot_; - HeapSnapshotsCollection* collection_; - HeapEntriesMap* entries_; -}; -class SnapshotAllocator { - public: - explicit SnapshotAllocator(HeapSnapshot* snapshot) - : snapshot_(snapshot) { } - HeapEntry* GetEntry( - HeapObject* obj, int children_count, int retainers_count) { - HeapEntry* entry = - snapshot_->AddEntry(obj, children_count, retainers_count); - ASSERT(entry != NULL); - return entry; - } - private: - HeapSnapshot* snapshot_; -}; - -class RootsReferencesExtractor : public ObjectVisitor { - public: - explicit RootsReferencesExtractor(HeapSnapshotGenerator* generator) - : generator_(generator) { - } - void VisitPointers(Object** start, Object** end) { - for (Object** p = start; p < end; p++) generator_->SetGcRootsReference(*p); - } - private: - HeapSnapshotGenerator* generator_; -}; +V8HeapExplorer::~V8HeapExplorer() { +} -bool HeapSnapshotGenerator::GenerateSnapshot() { - AssertNoAllocation no_alloc; +HeapEntry* V8HeapExplorer::AllocateEntry( + HeapThing ptr, int children_count, int retainers_count) { + return AddEntry( + reinterpret_cast(ptr), children_count, retainers_count); +} - SetProgressTotal(4); // 2 passes + dominators + sizes. - // Pass 1. Iterate heap contents to count entries and references. - if (!CountEntriesAndReferences()) return false; +HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object, + int children_count, + int retainers_count) { + if (object == kInternalRootObject) { + ASSERT(retainers_count == 0); + return snapshot_->AddRootEntry(children_count); + } else if (object == kGcRootsObject) { + return snapshot_->AddGcRootsEntry(children_count, retainers_count); + } else if (object->IsJSFunction()) { + JSFunction* func = JSFunction::cast(object); + SharedFunctionInfo* shared = func->shared(); + return AddEntry(object, + HeapEntry::kClosure, + collection_->GetName(String::cast(shared->name())), + children_count, + retainers_count); + } else if (object->IsJSRegExp()) { + JSRegExp* re = JSRegExp::cast(object); + return AddEntry(object, + HeapEntry::kRegExp, + collection_->GetName(re->Pattern()), + children_count, + retainers_count); + } else if (object->IsJSObject()) { + return AddEntry(object, + HeapEntry::kObject, + collection_->GetName(GetConstructorNameForHeapProfile( + JSObject::cast(object))), + children_count, + retainers_count); + } else if (object->IsString()) { + return AddEntry(object, + HeapEntry::kString, + collection_->GetName(String::cast(object)), + children_count, + retainers_count); + } else if (object->IsCode()) { + return AddEntry(object, + HeapEntry::kCode, + "", + children_count, + retainers_count); + } else if (object->IsSharedFunctionInfo()) { + SharedFunctionInfo* shared = SharedFunctionInfo::cast(object); + return AddEntry(object, + HeapEntry::kCode, + collection_->GetName(String::cast(shared->name())), + children_count, + retainers_count); + } else if (object->IsScript()) { + Script* script = Script::cast(object); + return AddEntry(object, + HeapEntry::kCode, + script->name()->IsString() ? + collection_->GetName(String::cast(script->name())) : "", + children_count, + retainers_count); + } else if (object->IsFixedArray()) { + return AddEntry(object, + HeapEntry::kArray, + "", + children_count, + retainers_count); + } else if (object->IsHeapNumber()) { + return AddEntry(object, + HeapEntry::kHeapNumber, + "number", + children_count, + retainers_count); + } + return AddEntry(object, + HeapEntry::kHidden, + "system", + children_count, + retainers_count); +} - // Allocate and fill entries in the snapshot, allocate references. - snapshot_->AllocateEntries(entries_.entries_count(), - entries_.total_children_count(), - entries_.total_retainers_count()); - SnapshotAllocator allocator(snapshot_); - entries_.UpdateEntries(&allocator); - // Pass 2. Fill references. - if (!FillReferences()) return false; +HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object, + HeapEntry::Type type, + const char* name, + int children_count, + int retainers_count) { + return snapshot_->AddEntry(type, + name, + collection_->GetObjectId(object->address()), + object->Size(), + children_count, + retainers_count); +} - if (!SetEntriesDominators()) return false; - if (!ApproximateRetainedSizes()) return false; - progress_counter_ = progress_total_; - if (!ReportProgress(true)) return false; - return true; +void V8HeapExplorer::AddRootEntries(SnapshotFillerInterface* filler) { + filler->AddEntry(kInternalRootObject); + filler->AddEntry(kGcRootsObject); } -HeapEntry* HeapSnapshotGenerator::GetEntry(Object* obj) { - if (!obj->IsHeapObject()) return NULL; - HeapObject* object = HeapObject::cast(obj); - HeapEntry* entry = entries_.Map(object); - // A new entry. - if (entry == NULL) entry = filler_->AddEntry(object); - return entry; +int V8HeapExplorer::EstimateObjectsCount() { + HeapIterator iterator(HeapIterator::kFilterUnreachable); + int objects_count = 0; + for (HeapObject* obj = iterator.next(); + obj != NULL; + obj = iterator.next(), ++objects_count) {} + return objects_count; } class IndexedReferencesExtractor : public ObjectVisitor { public: - IndexedReferencesExtractor(HeapSnapshotGenerator* generator, + IndexedReferencesExtractor(V8HeapExplorer* generator, HeapObject* parent_obj, HeapEntry* parent_entry, HeapObjectsSet* known_references = NULL) @@ -1917,7 +1784,7 @@ class IndexedReferencesExtractor : public ObjectVisitor { } } private: - HeapSnapshotGenerator* generator_; + V8HeapExplorer* generator_; HeapObject* parent_obj_; HeapEntry* parent_; HeapObjectsSet* known_references_; @@ -1925,7 +1792,7 @@ class IndexedReferencesExtractor : public ObjectVisitor { }; -void HeapSnapshotGenerator::ExtractReferences(HeapObject* obj) { +void V8HeapExplorer::ExtractReferences(HeapObject* obj) { HeapEntry* entry = GetEntry(obj); if (entry == NULL) return; // No interest in this object. @@ -1969,8 +1836,8 @@ void HeapSnapshotGenerator::ExtractReferences(HeapObject* obj) { } -void HeapSnapshotGenerator::ExtractClosureReferences(JSObject* js_obj, - HeapEntry* entry) { +void V8HeapExplorer::ExtractClosureReferences(JSObject* js_obj, + HeapEntry* entry) { if (js_obj->IsJSFunction()) { HandleScope hs; JSFunction* func = JSFunction::cast(js_obj); @@ -1992,8 +1859,8 @@ void HeapSnapshotGenerator::ExtractClosureReferences(JSObject* js_obj, } -void HeapSnapshotGenerator::ExtractPropertyReferences(JSObject* js_obj, - HeapEntry* entry) { +void V8HeapExplorer::ExtractPropertyReferences(JSObject* js_obj, + HeapEntry* entry) { if (js_obj->HasFastProperties()) { DescriptorArray* descs = js_obj->map()->instance_descriptors(); for (int i = 0; i < descs->number_of_descriptors(); i++) { @@ -2034,8 +1901,8 @@ void HeapSnapshotGenerator::ExtractPropertyReferences(JSObject* js_obj, } -void HeapSnapshotGenerator::ExtractElementReferences(JSObject* js_obj, - HeapEntry* entry) { +void V8HeapExplorer::ExtractElementReferences(JSObject* js_obj, + HeapEntry* entry) { if (js_obj->HasFastElements()) { FixedArray* elements = FixedArray::cast(js_obj->elements()); int length = js_obj->IsJSArray() ? @@ -2061,8 +1928,8 @@ void HeapSnapshotGenerator::ExtractElementReferences(JSObject* js_obj, } -void HeapSnapshotGenerator::ExtractInternalReferences(JSObject* js_obj, - HeapEntry* entry) { +void V8HeapExplorer::ExtractInternalReferences(JSObject* js_obj, + HeapEntry* entry) { int length = js_obj->GetInternalFieldCount(); for (int i = 0; i < length; ++i) { Object* o = js_obj->GetInternalField(i); @@ -2071,10 +1938,55 @@ void HeapSnapshotGenerator::ExtractInternalReferences(JSObject* js_obj, } -void HeapSnapshotGenerator::SetClosureReference(HeapObject* parent_obj, - HeapEntry* parent_entry, - String* reference_name, - Object* child_obj) { +HeapEntry* V8HeapExplorer::GetEntry(Object* obj) { + if (!obj->IsHeapObject()) return NULL; + return filler_->FindOrAddEntry(obj); +} + + +class RootsReferencesExtractor : public ObjectVisitor { + public: + explicit RootsReferencesExtractor(V8HeapExplorer* explorer) + : explorer_(explorer) { + } + void VisitPointers(Object** start, Object** end) { + for (Object** p = start; p < end; p++) explorer_->SetGcRootsReference(*p); + } + private: + V8HeapExplorer* explorer_; +}; + + +bool V8HeapExplorer::IterateAndExtractReferences( + SnapshotFillerInterface* filler) { + filler_ = filler; + HeapIterator iterator(HeapIterator::kFilterUnreachable); + bool interrupted = false; + // Heap iteration with filtering must be finished in any case. + for (HeapObject* obj = iterator.next(); + obj != NULL; + obj = iterator.next(), progress_->ProgressStep()) { + if (!interrupted) { + ExtractReferences(obj); + if (!progress_->ProgressReport(false)) interrupted = true; + } + } + if (interrupted) { + filler_ = NULL; + return false; + } + SetRootGcRootsReference(); + RootsReferencesExtractor extractor(this); + Heap::IterateRoots(&extractor, VISIT_ALL); + filler_ = NULL; + return progress_->ProgressReport(false); +} + + +void V8HeapExplorer::SetClosureReference(HeapObject* parent_obj, + HeapEntry* parent_entry, + String* reference_name, + Object* child_obj) { HeapEntry* child_entry = GetEntry(child_obj); if (child_entry != NULL) { filler_->SetNamedReference(HeapGraphEdge::kContextVariable, @@ -2088,10 +2000,10 @@ void HeapSnapshotGenerator::SetClosureReference(HeapObject* parent_obj, } -void HeapSnapshotGenerator::SetElementReference(HeapObject* parent_obj, - HeapEntry* parent_entry, - int index, - Object* child_obj) { +void V8HeapExplorer::SetElementReference(HeapObject* parent_obj, + HeapEntry* parent_entry, + int index, + Object* child_obj) { HeapEntry* child_entry = GetEntry(child_obj); if (child_entry != NULL) { filler_->SetIndexedReference(HeapGraphEdge::kElement, @@ -2105,10 +2017,10 @@ void HeapSnapshotGenerator::SetElementReference(HeapObject* parent_obj, } -void HeapSnapshotGenerator::SetInternalReference(HeapObject* parent_obj, - HeapEntry* parent_entry, - const char* reference_name, - Object* child_obj) { +void V8HeapExplorer::SetInternalReference(HeapObject* parent_obj, + HeapEntry* parent_entry, + const char* reference_name, + Object* child_obj) { HeapEntry* child_entry = GetEntry(child_obj); if (child_entry != NULL) { filler_->SetNamedReference(HeapGraphEdge::kInternal, @@ -2122,10 +2034,10 @@ void HeapSnapshotGenerator::SetInternalReference(HeapObject* parent_obj, } -void HeapSnapshotGenerator::SetInternalReference(HeapObject* parent_obj, - HeapEntry* parent_entry, - int index, - Object* child_obj) { +void V8HeapExplorer::SetInternalReference(HeapObject* parent_obj, + HeapEntry* parent_entry, + int index, + Object* child_obj) { HeapEntry* child_entry = GetEntry(child_obj); if (child_entry != NULL) { filler_->SetNamedReference(HeapGraphEdge::kInternal, @@ -2139,10 +2051,10 @@ void HeapSnapshotGenerator::SetInternalReference(HeapObject* parent_obj, } -void HeapSnapshotGenerator::SetHiddenReference(HeapObject* parent_obj, - HeapEntry* parent_entry, - int index, - Object* child_obj) { +void V8HeapExplorer::SetHiddenReference(HeapObject* parent_obj, + HeapEntry* parent_entry, + int index, + Object* child_obj) { HeapEntry* child_entry = GetEntry(child_obj); if (child_entry != NULL) { filler_->SetIndexedReference(HeapGraphEdge::kHidden, @@ -2155,10 +2067,10 @@ void HeapSnapshotGenerator::SetHiddenReference(HeapObject* parent_obj, } -void HeapSnapshotGenerator::SetPropertyReference(HeapObject* parent_obj, - HeapEntry* parent_entry, - String* reference_name, - Object* child_obj) { +void V8HeapExplorer::SetPropertyReference(HeapObject* parent_obj, + HeapEntry* parent_entry, + String* reference_name, + Object* child_obj) { HeapEntry* child_entry = GetEntry(child_obj); if (child_entry != NULL) { HeapGraphEdge::Type type = reference_name->length() > 0 ? @@ -2174,7 +2086,7 @@ void HeapSnapshotGenerator::SetPropertyReference(HeapObject* parent_obj, } -void HeapSnapshotGenerator::SetPropertyShortcutReference( +void V8HeapExplorer::SetPropertyShortcutReference( HeapObject* parent_obj, HeapEntry* parent_entry, String* reference_name, @@ -2191,52 +2103,221 @@ void HeapSnapshotGenerator::SetPropertyShortcutReference( } -void HeapSnapshotGenerator::SetRootGcRootsReference() { - filler_->SetRootGcRootsReference(); +void V8HeapExplorer::SetRootGcRootsReference() { + filler_->SetIndexedAutoIndexReference( + HeapGraphEdge::kElement, + kInternalRootObject, snapshot_->root(), + kGcRootsObject, snapshot_->gc_roots()); } -void HeapSnapshotGenerator::SetRootShortcutReference(Object* child_obj) { +void V8HeapExplorer::SetRootShortcutReference(Object* child_obj) { HeapEntry* child_entry = GetEntry(child_obj); ASSERT(child_entry != NULL); - filler_->SetRootShortcutReference(child_obj, child_entry); + filler_->SetNamedAutoIndexReference( + HeapGraphEdge::kShortcut, + kInternalRootObject, snapshot_->root(), + child_obj, child_entry); } -void HeapSnapshotGenerator::SetGcRootsReference(Object* child_obj) { +void V8HeapExplorer::SetGcRootsReference(Object* child_obj) { HeapEntry* child_entry = GetEntry(child_obj); if (child_entry != NULL) { - filler_->SetStrongRootReference(child_obj, child_entry); + filler_->SetIndexedAutoIndexReference( + HeapGraphEdge::kElement, + kGcRootsObject, snapshot_->gc_roots(), + child_obj, child_entry); } } +HeapSnapshotGenerator::HeapSnapshotGenerator(HeapSnapshot* snapshot, + v8::ActivityControl* control) + : snapshot_(snapshot), + control_(control), + v8_heap_explorer_(snapshot_, this) { +} + + +class SnapshotCounter : public SnapshotFillerInterface { + public: + SnapshotCounter(HeapEntriesAllocator* allocator, HeapEntriesMap* entries) + : allocator_(allocator), entries_(entries) { } + HeapEntry* AddEntry(HeapThing ptr) { + entries_->Pair(ptr, allocator_, HeapEntriesMap::kHeapEntryPlaceholder); + return HeapEntriesMap::kHeapEntryPlaceholder; + } + HeapEntry* FindOrAddEntry(HeapThing ptr) { + HeapEntry* entry = entries_->Map(ptr); + return entry != NULL ? entry : AddEntry(ptr); + } + void SetIndexedReference(HeapGraphEdge::Type, + HeapThing parent_ptr, + HeapEntry*, + int, + HeapThing child_ptr, + HeapEntry*) { + entries_->CountReference(parent_ptr, child_ptr); + } + void SetIndexedAutoIndexReference(HeapGraphEdge::Type, + HeapThing parent_ptr, + HeapEntry*, + HeapThing child_ptr, + HeapEntry*) { + entries_->CountReference(parent_ptr, child_ptr); + } + void SetNamedReference(HeapGraphEdge::Type, + HeapThing parent_ptr, + HeapEntry*, + const char*, + HeapThing child_ptr, + HeapEntry*) { + entries_->CountReference(parent_ptr, child_ptr); + } + void SetNamedAutoIndexReference(HeapGraphEdge::Type, + HeapThing parent_ptr, + HeapEntry*, + HeapThing child_ptr, + HeapEntry*) { + entries_->CountReference(parent_ptr, child_ptr); + } + private: + HeapEntriesAllocator* allocator_; + HeapEntriesMap* entries_; +}; + + +class SnapshotFiller : public SnapshotFillerInterface { + public: + explicit SnapshotFiller(HeapSnapshot* snapshot, HeapEntriesMap* entries) + : snapshot_(snapshot), + collection_(snapshot->collection()), + entries_(entries) { } + HeapEntry* AddEntry(HeapThing ptr) { + UNREACHABLE(); + return NULL; + } + HeapEntry* FindOrAddEntry(HeapThing ptr) { + HeapEntry* entry = entries_->Map(ptr); + return entry != NULL ? entry : AddEntry(ptr); + } + void SetIndexedReference(HeapGraphEdge::Type type, + HeapThing parent_ptr, + HeapEntry* parent_entry, + int index, + HeapThing child_ptr, + HeapEntry* child_entry) { + int child_index, retainer_index; + entries_->CountReference( + parent_ptr, child_ptr, &child_index, &retainer_index); + parent_entry->SetIndexedReference( + type, child_index, index, child_entry, retainer_index); + } + void SetIndexedAutoIndexReference(HeapGraphEdge::Type type, + HeapThing parent_ptr, + HeapEntry* parent_entry, + HeapThing child_ptr, + HeapEntry* child_entry) { + int child_index, retainer_index; + entries_->CountReference( + parent_ptr, child_ptr, &child_index, &retainer_index); + parent_entry->SetIndexedReference( + type, child_index, child_index + 1, child_entry, retainer_index); + } + void SetNamedReference(HeapGraphEdge::Type type, + HeapThing parent_ptr, + HeapEntry* parent_entry, + const char* reference_name, + HeapThing child_ptr, + HeapEntry* child_entry) { + int child_index, retainer_index; + entries_->CountReference( + parent_ptr, child_ptr, &child_index, &retainer_index); + parent_entry->SetNamedReference( + type, child_index, reference_name, child_entry, retainer_index); + } + void SetNamedAutoIndexReference(HeapGraphEdge::Type type, + HeapThing parent_ptr, + HeapEntry* parent_entry, + HeapThing child_ptr, + HeapEntry* child_entry) { + int child_index, retainer_index; + entries_->CountReference( + parent_ptr, child_ptr, &child_index, &retainer_index); + parent_entry->SetNamedReference(type, + child_index, + collection_->GetName(child_index + 1), + child_entry, + retainer_index); + } + private: + HeapSnapshot* snapshot_; + HeapSnapshotsCollection* collection_; + HeapEntriesMap* entries_; +}; + + +bool HeapSnapshotGenerator::GenerateSnapshot() { + AssertNoAllocation no_alloc; + + SetProgressTotal(4); // 2 passes + dominators + sizes. + + // Pass 1. Iterate heap contents to count entries and references. + if (!CountEntriesAndReferences()) return false; + + // Allocate and fill entries in the snapshot, allocate references. + snapshot_->AllocateEntries(entries_.entries_count(), + entries_.total_children_count(), + entries_.total_retainers_count()); + entries_.AllocateEntries(); + + // Pass 2. Fill references. + if (!FillReferences()) return false; + + if (!SetEntriesDominators()) return false; + if (!ApproximateRetainedSizes()) return false; + + progress_counter_ = progress_total_; + if (!ProgressReport(true)) return false; + return true; +} + + +void HeapSnapshotGenerator::ProgressStep() { + ++progress_counter_; +} + + +bool HeapSnapshotGenerator::ProgressReport(bool force) { + const int kProgressReportGranularity = 10000; + if (control_ != NULL + && (force || progress_counter_ % kProgressReportGranularity == 0)) { + return + control_->ReportProgressValue(progress_counter_, progress_total_) == + v8::ActivityControl::kContinue; + } + return true; +} + + void HeapSnapshotGenerator::SetProgressTotal(int iterations_count) { if (control_ == NULL) return; - - HeapIterator iterator(HeapIterator::kFilterUnreachable); - int objects_count = 0; - for (HeapObject* obj = iterator.next(); - obj != NULL; - obj = iterator.next(), ++objects_count) {} - progress_total_ = objects_count * iterations_count; + progress_total_ = v8_heap_explorer_.EstimateObjectsCount() * iterations_count; progress_counter_ = 0; } bool HeapSnapshotGenerator::CountEntriesAndReferences() { - SnapshotCounter counter(&entries_); - filler_ = &counter; - filler_->AddEntry(HeapSnapshot::kInternalRootObject); - filler_->AddEntry(HeapSnapshot::kGcRootsObject); - return IterateAndExtractReferences(); + SnapshotCounter counter(&v8_heap_explorer_, &entries_); + v8_heap_explorer_.AddRootEntries(&counter); + return v8_heap_explorer_.IterateAndExtractReferences(&counter); } bool HeapSnapshotGenerator::FillReferences() { SnapshotFiller filler(snapshot_, &entries_); - filler_ = &filler; - return IterateAndExtractReferences(); + return v8_heap_explorer_.IterateAndExtractReferences(&filler); } @@ -2322,7 +2403,7 @@ bool HeapSnapshotGenerator::BuildDominatorTree( int remaining = entries_length - changed; if (remaining < 0) remaining = 0; progress_counter_ = base_progress_counter + remaining; - if (!ReportProgress(true)) return false; + if (!ProgressReport(true)) return false; } return true; } @@ -2352,7 +2433,7 @@ bool HeapSnapshotGenerator::ApproximateRetainedSizes() { } for (int i = 0; i < snapshot_->entries()->length(); - ++i, IncProgressCounter()) { + ++i, ProgressStep()) { HeapEntry* entry = snapshot_->entries()->at(i); int entry_size = entry->self_size(); for (HeapEntry* dominator = entry->dominator(); @@ -2360,32 +2441,12 @@ bool HeapSnapshotGenerator::ApproximateRetainedSizes() { entry = dominator, dominator = entry->dominator()) { dominator->add_retained_size(entry_size); } - if (!ReportProgress()) return false; + if (!ProgressReport()) return false; } return true; } -bool HeapSnapshotGenerator::IterateAndExtractReferences() { - HeapIterator iterator(HeapIterator::kFilterUnreachable); - bool interrupted = false; - // Heap iteration with filtering must be finished in any case. - for (HeapObject* obj = iterator.next(); - obj != NULL; - obj = iterator.next(), IncProgressCounter()) { - if (!interrupted) { - ExtractReferences(obj); - if (!ReportProgress()) interrupted = true; - } - } - if (interrupted) return false; - SetRootGcRootsReference(); - RootsReferencesExtractor extractor(this); - Heap::IterateRoots(&extractor, VISIT_ALL); - return ReportProgress(); -} - - void HeapSnapshotsDiff::CreateRoots(int additions_count, int deletions_count) { raw_additions_root_ = NewArray(HeapEntry::EntriesSize(1, additions_count, 0)); diff --git a/src/profile-generator.h b/src/profile-generator.h index 748714d..4762eb6 100644 --- a/src/profile-generator.h +++ b/src/profile-generator.h @@ -681,14 +681,14 @@ class HeapSnapshot { void AllocateEntries( int entries_count, int children_count, int retainers_count); - HeapEntry* AddEntry( - HeapObject* object, int children_count, int retainers_count); HeapEntry* AddEntry(HeapEntry::Type type, const char* name, uint64_t id, int size, int children_count, int retainers_count); + HeapEntry* AddRootEntry(int children_count); + HeapEntry* AddGcRootsEntry(int children_count, int retainers_count); void ClearPaint(); HeapSnapshotsDiff* CompareWith(HeapSnapshot* snapshot); HeapEntry* GetEntryById(uint64_t id); @@ -701,15 +701,7 @@ class HeapSnapshot { void Print(int max_depth); void PrintEntriesSize(); - static HeapObject* const kInternalRootObject; - static HeapObject* const kGcRootsObject; - private: - HeapEntry* AddEntry(HeapObject* object, - HeapEntry::Type type, - const char* name, - int children_count, - int retainers_count); HeapEntry* GetNextEntryToInit(); HeapSnapshotsCollection* collection_; @@ -873,6 +865,20 @@ class HeapSnapshotsCollection { }; +// A typedef for referencing anything that can be snapshotted living +// in any kind of heap memory. +typedef void* HeapThing; + + +// An interface that creates HeapEntries by HeapThings. +class HeapEntriesAllocator { + public: + virtual ~HeapEntriesAllocator() { } + virtual HeapEntry* AllocateEntry( + HeapThing ptr, int children_count, int retainers_count) = 0; +}; + + // The HeapEntriesMap instance is used to track a mapping between // real heap objects and their representations in heap snapshots. class HeapEntriesMap { @@ -880,13 +886,12 @@ class HeapEntriesMap { HeapEntriesMap(); ~HeapEntriesMap(); - HeapEntry* Map(HeapObject* object); - void Pair(HeapObject* object, HeapEntry* entry); - void CountReference(HeapObject* from, HeapObject* to, + void AllocateEntries(); + HeapEntry* Map(HeapThing thing); + void Pair(HeapThing thing, HeapEntriesAllocator* allocator, HeapEntry* entry); + void CountReference(HeapThing from, HeapThing to, int* prev_children_count = NULL, int* prev_retainers_count = NULL); - template - void UpdateEntries(Visitor* visitor); int entries_count() { return entries_count_; } int total_children_count() { return total_children_count_; } @@ -896,18 +901,25 @@ class HeapEntriesMap { private: struct EntryInfo { - explicit EntryInfo(HeapEntry* entry) - : entry(entry), children_count(0), retainers_count(0) { } + EntryInfo(HeapEntry* entry, HeapEntriesAllocator* allocator) + : entry(entry), + allocator(allocator), + children_count(0), + retainers_count(0) { + } HeapEntry* entry; + HeapEntriesAllocator* allocator; int children_count; int retainers_count; }; - static uint32_t Hash(HeapObject* object) { + static uint32_t Hash(HeapThing thing) { return ComputeIntegerHash( - static_cast(reinterpret_cast(object))); + static_cast(reinterpret_cast(thing))); + } + static bool HeapThingsMatch(HeapThing key1, HeapThing key2) { + return key1 == key2; } - static bool HeapObjectsMatch(void* key1, void* key2) { return key1 == key2; } HashMap entries_; int entries_count_; @@ -934,52 +946,70 @@ class HeapObjectsSet { }; -class HeapSnapshotGenerator { +// An interface used to populate a snapshot with nodes and edges. +class SnapshotFillerInterface { public: - class SnapshotFillerInterface { - public: - virtual ~SnapshotFillerInterface() { } - virtual HeapEntry* AddEntry(HeapObject* obj) = 0; - virtual void SetIndexedReference(HeapGraphEdge::Type type, - HeapObject* parent_obj, - HeapEntry* parent_entry, - int index, - Object* child_obj, - HeapEntry* child_entry) = 0; - virtual void SetNamedReference(HeapGraphEdge::Type type, - HeapObject* parent_obj, + virtual ~SnapshotFillerInterface() { } + virtual HeapEntry* AddEntry(HeapThing ptr) = 0; + virtual HeapEntry* FindOrAddEntry(HeapThing ptr) = 0; + virtual void SetIndexedReference(HeapGraphEdge::Type type, + HeapThing parent_ptr, HeapEntry* parent_entry, - const char* reference_name, - Object* child_obj, + int index, + HeapThing child_ptr, HeapEntry* child_entry) = 0; - virtual void SetRootGcRootsReference() = 0; - virtual void SetRootShortcutReference(Object* child_obj, + virtual void SetIndexedAutoIndexReference(HeapGraphEdge::Type type, + HeapThing parent_ptr, + HeapEntry* parent_entry, + HeapThing child_ptr, + HeapEntry* child_entry) = 0; + virtual void SetNamedReference(HeapGraphEdge::Type type, + HeapThing parent_ptr, + HeapEntry* parent_entry, + const char* reference_name, + HeapThing child_ptr, + HeapEntry* child_entry) = 0; + virtual void SetNamedAutoIndexReference(HeapGraphEdge::Type type, + HeapThing parent_ptr, + HeapEntry* parent_entry, + HeapThing child_ptr, HeapEntry* child_entry) = 0; - virtual void SetStrongRootReference(Object* child_obj, - HeapEntry* child_entry) = 0; - }; +}; - HeapSnapshotGenerator(HeapSnapshot* snapshot, - v8::ActivityControl* control); - bool GenerateSnapshot(); + +class SnapshottingProgressReportingInterface { + public: + virtual ~SnapshottingProgressReportingInterface() { } + virtual void ProgressStep() = 0; + virtual bool ProgressReport(bool force) = 0; +}; + + +// An implementation of V8 heap graph extractor. +class V8HeapExplorer : public HeapEntriesAllocator { + public: + V8HeapExplorer(HeapSnapshot* snapshot, + SnapshottingProgressReportingInterface* progress); + ~V8HeapExplorer(); + virtual HeapEntry* AllocateEntry( + HeapThing ptr, int children_count, int retainers_count); + void AddRootEntries(SnapshotFillerInterface* filler); + int EstimateObjectsCount(); + bool IterateAndExtractReferences(SnapshotFillerInterface* filler); private: - bool ApproximateRetainedSizes(); - bool BuildDominatorTree(const Vector& entries, - Vector* dominators); - bool CountEntriesAndReferences(); - HeapEntry* GetEntry(Object* obj); - void IncProgressCounter() { ++progress_counter_; } + HeapEntry* AddEntry( + HeapObject* object, int children_count, int retainers_count); + HeapEntry* AddEntry(HeapObject* object, + HeapEntry::Type type, + const char* name, + int children_count, + int retainers_count); void ExtractReferences(HeapObject* obj); void ExtractClosureReferences(JSObject* js_obj, HeapEntry* entry); void ExtractPropertyReferences(JSObject* js_obj, HeapEntry* entry); void ExtractElementReferences(JSObject* js_obj, HeapEntry* entry); void ExtractInternalReferences(JSObject* js_obj, HeapEntry* entry); - bool FillReferences(); - void FillReversePostorderIndexes(Vector* entries); - bool IterateAndExtractReferences(); - inline bool ReportProgress(bool force = false); - bool SetEntriesDominators(); void SetClosureReference(HeapObject* parent_obj, HeapEntry* parent, String* reference_name, @@ -1011,24 +1041,54 @@ class HeapSnapshotGenerator { void SetRootShortcutReference(Object* child); void SetRootGcRootsReference(); void SetGcRootsReference(Object* child); - void SetProgressTotal(int iterations_count); + + HeapEntry* GetEntry(Object* obj); HeapSnapshot* snapshot_; - v8::ActivityControl* control_; HeapSnapshotsCollection* collection_; - // Mapping from HeapObject* pointers to HeapEntry* pointers. - HeapEntriesMap entries_; - SnapshotFillerInterface* filler_; + SnapshottingProgressReportingInterface* progress_; // Used during references extraction to mark heap objects that // are references via non-hidden properties. HeapObjectsSet known_references_; - // Used during snapshot generation. - int progress_counter_; - int progress_total_; + SnapshotFillerInterface* filler_; + + static HeapObject* const kInternalRootObject; + static HeapObject* const kGcRootsObject; friend class IndexedReferencesExtractor; friend class RootsReferencesExtractor; + DISALLOW_COPY_AND_ASSIGN(V8HeapExplorer); +}; + + +class HeapSnapshotGenerator : public SnapshottingProgressReportingInterface { + public: + HeapSnapshotGenerator(HeapSnapshot* snapshot, + v8::ActivityControl* control); + bool GenerateSnapshot(); + + private: + bool ApproximateRetainedSizes(); + bool BuildDominatorTree(const Vector& entries, + Vector* dominators); + bool CountEntriesAndReferences(); + bool FillReferences(); + void FillReversePostorderIndexes(Vector* entries); + void ProgressStep(); + bool ProgressReport(bool force = false); + bool SetEntriesDominators(); + void SetProgressTotal(int iterations_count); + + HeapSnapshot* snapshot_; + v8::ActivityControl* control_; + V8HeapExplorer v8_heap_explorer_; + // Mapping from HeapThing pointers to HeapEntry* pointers. + HeapEntriesMap entries_; + // Used during snapshot generation. + int progress_counter_; + int progress_total_; + DISALLOW_COPY_AND_ASSIGN(HeapSnapshotGenerator); }; -- 2.7.4