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
parent 63beeed3
......@@ -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 RetainersIterator>
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<HeapObject*>(ptr);
JSObjectsCluster cluster = HeapObjectAsCluster(obj);
const char* name = cluster.GetSpecialCaseName();
if (name == NULL) {
......@@ -1018,12 +1028,13 @@ class AggregatedRetainerTreeAllocator {
template<class Iterator>
void AggregatedHeapSnapshotGenerator::IterateRetainers(
HeapEntriesMap* entries_map) {
HeapEntriesAllocator* allocator, HeapEntriesMap* entries_map) {
RetainerHeapProfile* p = agg_snapshot_->js_retainer_profile();
AggregatingRetainerTreeIterator<Iterator> agg_ret_iter_1(
p->coarser(), entries_map);
p->coarser(), allocator, entries_map);
p->retainers_tree()->ForEach(&agg_ret_iter_1);
AggregatingRetainerTreeIterator<Iterator> agg_ret_iter_2(NULL, entries_map);
AggregatingRetainerTreeIterator<Iterator> 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<CountingRetainersIterator>(&entries_map);
int root_child_index = 0;
AggregatedRetainerTreeAllocator allocator(snapshot, &root_child_index);
IterateRetainers<CountingRetainersIterator>(&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<AllocatingRetainersIterator>(&entries_map);
IterateRetainers<AllocatingRetainersIterator>(&allocator, &entries_map);
snapshot->SetDominatorsToSelf();
}
......
......@@ -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<class Iterator>
void IterateRetainers(HeapEntriesMap* entries_map);
void IterateRetainers(
HeapEntriesAllocator* allocator, HeapEntriesMap* entries_map);
AggregatedHeapSnapshot* agg_snapshot_;
};
......
......@@ -121,34 +121,6 @@ uint64_t HeapEntry::id() {
return id_adaptor.returned_id;
}
template<class Visitor>
void HeapEntriesMap::UpdateEntries(Visitor* visitor) {
for (HashMap::Entry* p = entries_.Start();
p != NULL;
p = entries_.Next(p)) {
EntryInfo* entry_info = reinterpret_cast<EntryInfo*>(p->value);
entry_info->entry = visitor->GetEntry(
reinterpret_cast<HeapObject*>(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
......
......@@ -1177,12 +1177,6 @@ void HeapGraphPath::Print() {
}
HeapObject *const HeapSnapshot::kInternalRootObject =
reinterpret_cast<HeapObject*>(1);
HeapObject *const HeapSnapshot::kGcRootsObject =
reinterpret_cast<HeapObject*>(2);
// It is very important to keep objects that form a heap snapshot
// as small as possible.
namespace { // Avoid littering the global namespace.
......@@ -1253,19 +1247,28 @@ void HeapSnapshot::AllocateEntries(int entries_count,
}
HeapEntry* HeapSnapshot::AddEntry(HeapObject* object,
int children_count,
int retainers_count) {
if (object == kInternalRootObject) {
static void HeapEntryClearPaint(HeapEntry** entry_ptr) {
(*entry_ptr)->clear_paint();
}
void HeapSnapshot::ClearPaint() {
entries_.Iterate(HeapEntryClearPaint);
}
HeapEntry* HeapSnapshot::AddRootEntry(int children_count) {
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) {
0));
}
HeapEntry* HeapSnapshot::AddGcRootsEntry(int children_count,
int retainers_count) {
ASSERT(gc_roots_entry_ == NULL);
return (gc_roots_entry_ = AddEntry(HeapEntry::kObject,
"(GC roots)",
......@@ -1273,96 +1276,6 @@ HeapEntry* HeapSnapshot::AddEntry(HeapObject* object,
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();
}
void HeapSnapshot::ClearPaint() {
entries_.Iterate(HeapEntryClearPaint);
}
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);
}
......@@ -1615,7 +1528,7 @@ HeapEntry *const HeapEntriesMap::kHeapEntryPlaceholder =
reinterpret_cast<HeapEntry*>(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<EntryInfo*>(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<EntryInfo*>(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)
: snapshot_(snapshot),
control_(control),
collection_(snapshot->collection()),
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_;
};
HeapObject *const V8HeapExplorer::kInternalRootObject =
reinterpret_cast<HeapObject*>(1);
HeapObject *const V8HeapExplorer::kGcRootsObject =
reinterpret_cast<HeapObject*>(2);
class SnapshotFiller : public HeapSnapshotGenerator::SnapshotFillerInterface {
public:
explicit SnapshotFiller(HeapSnapshot* snapshot, HeapEntriesMap* entries)
V8HeapExplorer::V8HeapExplorer(
HeapSnapshot* snapshot,
SnapshottingProgressReportingInterface* progress)
: 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_;
};
collection_(snapshot_->collection()),
progress_(progress),
filler_(NULL) {
}
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<HeapObject*>(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,7 +1836,7 @@ void HeapSnapshotGenerator::ExtractReferences(HeapObject* obj) {
}
void HeapSnapshotGenerator::ExtractClosureReferences(JSObject* js_obj,
void V8HeapExplorer::ExtractClosureReferences(JSObject* js_obj,
HeapEntry* entry) {
if (js_obj->IsJSFunction()) {
HandleScope hs;
......@@ -1992,7 +1859,7 @@ void HeapSnapshotGenerator::ExtractClosureReferences(JSObject* js_obj,
}
void HeapSnapshotGenerator::ExtractPropertyReferences(JSObject* js_obj,
void V8HeapExplorer::ExtractPropertyReferences(JSObject* js_obj,
HeapEntry* entry) {
if (js_obj->HasFastProperties()) {
DescriptorArray* descs = js_obj->map()->instance_descriptors();
......@@ -2034,7 +1901,7 @@ void HeapSnapshotGenerator::ExtractPropertyReferences(JSObject* js_obj,
}
void HeapSnapshotGenerator::ExtractElementReferences(JSObject* js_obj,
void V8HeapExplorer::ExtractElementReferences(JSObject* js_obj,
HeapEntry* entry) {
if (js_obj->HasFastElements()) {
FixedArray* elements = FixedArray::cast(js_obj->elements());
......@@ -2061,7 +1928,7 @@ void HeapSnapshotGenerator::ExtractElementReferences(JSObject* js_obj,
}
void HeapSnapshotGenerator::ExtractInternalReferences(JSObject* js_obj,
void V8HeapExplorer::ExtractInternalReferences(JSObject* js_obj,
HeapEntry* entry) {
int length = js_obj->GetInternalFieldCount();
for (int i = 0; i < length; ++i) {
......@@ -2071,7 +1938,52 @@ void HeapSnapshotGenerator::ExtractInternalReferences(JSObject* js_obj,
}
void HeapSnapshotGenerator::SetClosureReference(HeapObject* parent_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) {
......@@ -2088,7 +2000,7 @@ void HeapSnapshotGenerator::SetClosureReference(HeapObject* parent_obj,
}
void HeapSnapshotGenerator::SetElementReference(HeapObject* parent_obj,
void V8HeapExplorer::SetElementReference(HeapObject* parent_obj,
HeapEntry* parent_entry,
int index,
Object* child_obj) {
......@@ -2105,7 +2017,7 @@ void HeapSnapshotGenerator::SetElementReference(HeapObject* parent_obj,
}
void HeapSnapshotGenerator::SetInternalReference(HeapObject* parent_obj,
void V8HeapExplorer::SetInternalReference(HeapObject* parent_obj,
HeapEntry* parent_entry,
const char* reference_name,
Object* child_obj) {
......@@ -2122,7 +2034,7 @@ void HeapSnapshotGenerator::SetInternalReference(HeapObject* parent_obj,
}
void HeapSnapshotGenerator::SetInternalReference(HeapObject* parent_obj,
void V8HeapExplorer::SetInternalReference(HeapObject* parent_obj,
HeapEntry* parent_entry,
int index,
Object* child_obj) {
......@@ -2139,7 +2051,7 @@ void HeapSnapshotGenerator::SetInternalReference(HeapObject* parent_obj,
}
void HeapSnapshotGenerator::SetHiddenReference(HeapObject* parent_obj,
void V8HeapExplorer::SetHiddenReference(HeapObject* parent_obj,
HeapEntry* parent_entry,
int index,
Object* child_obj) {
......@@ -2155,7 +2067,7 @@ void HeapSnapshotGenerator::SetHiddenReference(HeapObject* parent_obj,
}
void HeapSnapshotGenerator::SetPropertyReference(HeapObject* parent_obj,
void V8HeapExplorer::SetPropertyReference(HeapObject* parent_obj,
HeapEntry* parent_entry,
String* reference_name,
Object* child_obj) {
......@@ -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<char>(HeapEntry::EntriesSize(1, additions_count, 0));
......
......@@ -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<class Visitor>
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<uint32_t>(reinterpret_cast<uintptr_t>(object)));
static_cast<uint32_t>(reinterpret_cast<uintptr_t>(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 {
public:
class SnapshotFillerInterface {
// An interface used to populate a snapshot with nodes and edges.
class SnapshotFillerInterface {
public:
virtual ~SnapshotFillerInterface() { }
virtual HeapEntry* AddEntry(HeapObject* obj) = 0;
virtual HeapEntry* AddEntry(HeapThing ptr) = 0;
virtual HeapEntry* FindOrAddEntry(HeapThing ptr) = 0;
virtual void SetIndexedReference(HeapGraphEdge::Type type,
HeapObject* parent_obj,
HeapThing parent_ptr,
HeapEntry* parent_entry,
int index,
Object* child_obj,
HeapThing child_ptr,
HeapEntry* child_entry) = 0;
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,
HeapObject* parent_obj,
HeapThing parent_ptr,
HeapEntry* parent_entry,
const char* reference_name,
Object* child_obj,
HeapThing child_ptr,
HeapEntry* child_entry) = 0;
virtual void SetRootGcRootsReference() = 0;
virtual void SetRootShortcutReference(Object* child_obj,
HeapEntry* child_entry) = 0;
virtual void SetStrongRootReference(Object* child_obj,
virtual void SetNamedAutoIndexReference(HeapGraphEdge::Type type,
HeapThing parent_ptr,
HeapEntry* parent_entry,
HeapThing child_ptr,
HeapEntry* child_entry) = 0;
};
};
class SnapshottingProgressReportingInterface {
public:
virtual ~SnapshottingProgressReportingInterface() { }
virtual void ProgressStep() = 0;
virtual bool ProgressReport(bool force) = 0;
};
HeapSnapshotGenerator(HeapSnapshot* snapshot,
v8::ActivityControl* control);
bool GenerateSnapshot();
// 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<HeapEntry*>& entries,
Vector<HeapEntry*>* 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<HeapEntry*>* 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<HeapEntry*>& entries,
Vector<HeapEntry*>* dominators);
bool CountEntriesAndReferences();
bool FillReferences();
void FillReversePostorderIndexes(Vector<HeapEntry*>* 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);
};
......
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