Revision: 10528
Author: [email protected]
Date: Fri Jan 27 04:02:57 2012
Log: Detailed heap snapshot usability improvement.
The detailed heap snapshot has two groups of nodes. The first one
is the group for v8 heap nodes and the second one is the group for
native objects. At the moment we have two different sets of native
objects. There are 'Detached DOM trees' and 'Document DOM trees' type of
objects.
I think it'd be nice to replace one group containing all native objects with
separate groups for different types of native objects.
BUG=none
TEST=HeapSnapshotRetainedObjectInfo
Review URL: https://chromiumcodereview.appspot.com/9223009
http://code.google.com/p/v8/source/detail?r=10528
Modified:
/branches/bleeding_edge/include/v8-profiler.h
/branches/bleeding_edge/src/profile-generator.cc
/branches/bleeding_edge/src/profile-generator.h
/branches/bleeding_edge/test/cctest/test-heap-profiler.cc
=======================================
--- /branches/bleeding_edge/include/v8-profiler.h Tue Dec 6 09:41:47 2011
+++ /branches/bleeding_edge/include/v8-profiler.h Fri Jan 27 04:02:57 2012
@@ -476,10 +476,21 @@
virtual intptr_t GetHash() = 0;
/**
- * Returns human-readable label. It must be a NUL-terminated UTF-8
+ * Returns human-readable label. It must be a null-terminated UTF-8
* encoded string. V8 copies its contents during a call to GetLabel.
*/
virtual const char* GetLabel() = 0;
+
+ /**
+ * Returns human-readable group label. It must be a null-terminated UTF-8
+ * encoded string. V8 copies its contents during a call to GetGroupLabel.
+ * Heap snapshot generator will collect all the group names, create
+ * top level entries with these names and attach the objects to the
+ * corresponding top level group objects. There is a default
+ * implementation which is required because embedders don't have their
+ * own implementation yet.
+ */
+ virtual const char* GetGroupLabel() { return GetLabel(); }
/**
* Returns element count in case if a global handle retains
=======================================
--- /branches/bleeding_edge/src/profile-generator.cc Mon Jan 16 01:44:35
2012
+++ /branches/bleeding_edge/src/profile-generator.cc Fri Jan 27 04:02:57
2012
@@ -1306,19 +1306,6 @@
children_count,
retainers_count));
}
-
-
-HeapEntry* HeapSnapshot::AddNativesRootEntry(int children_count,
- int retainers_count) {
- ASSERT(natives_root_entry_ == NULL);
- return (natives_root_entry_ = AddEntry(
- HeapEntry::kObject,
- "(Native objects)",
- HeapObjectsMap::kNativesRootObjectId,
- 0,
- children_count,
- retainers_count));
-}
HeapEntry* HeapSnapshot::AddEntry(HeapEntry::Type type,
@@ -1402,10 +1389,8 @@
const uint64_t HeapObjectsMap::kInternalRootObjectId = 1;
const uint64_t HeapObjectsMap::kGcRootsObjectId =
HeapObjectsMap::kInternalRootObjectId + HeapObjectsMap::kObjectIdStep;
-const uint64_t HeapObjectsMap::kNativesRootObjectId =
- HeapObjectsMap::kGcRootsObjectId + HeapObjectsMap::kObjectIdStep;
const uint64_t HeapObjectsMap::kGcRootsFirstSubrootId =
- HeapObjectsMap::kNativesRootObjectId + HeapObjectsMap::kObjectIdStep;
+ HeapObjectsMap::kGcRootsObjectId + HeapObjectsMap::kObjectIdStep;
const uint64_t HeapObjectsMap::kFirstAvailableObjectId =
HeapObjectsMap::kGcRootsFirstSubrootId +
VisitorSynchronization::kNumberOfSyncTags *
HeapObjectsMap::kObjectIdStep;
@@ -2712,11 +2697,6 @@
NativeObjectsExplorer* explorer_;
};
-HeapThing const NativeObjectsExplorer::kNativesRootObject =
- reinterpret_cast<HeapThing>(
- static_cast<intptr_t>(HeapObjectsMap::kNativesRootObjectId));
-
-
NativeObjectsExplorer::NativeObjectsExplorer(
HeapSnapshot* snapshot, SnapshottingProgressReportingInterface*
progress)
: snapshot_(snapshot),
@@ -2724,6 +2704,7 @@
progress_(progress),
embedder_queried_(false),
objects_by_info_(RetainedInfosMatch),
+ native_groups_(StringsMatch),
filler_(NULL) {
}
@@ -2744,32 +2725,22 @@
HeapEntry* NativeObjectsExplorer::AllocateEntry(
HeapThing ptr, int children_count, int retainers_count) {
- if (ptr == kNativesRootObject) {
- return snapshot_->AddNativesRootEntry(children_count, retainers_count);
- } else {
- v8::RetainedObjectInfo* info =
- reinterpret_cast<v8::RetainedObjectInfo*>(ptr);
- intptr_t elements = info->GetElementCount();
- intptr_t size = info->GetSizeInBytes();
- return snapshot_->AddEntry(
- HeapEntry::kNative,
- elements != -1 ?
- collection_->names()->GetFormatted(
- "%s / %" V8_PTR_PREFIX "d entries",
- info->GetLabel(),
- info->GetElementCount()) :
- collection_->names()->GetCopy(info->GetLabel()),
- HeapObjectsMap::GenerateId(info),
- size != -1 ? static_cast<int>(size) : 0,
- children_count,
- retainers_count);
- }
-}
-
-
-void NativeObjectsExplorer::AddRootEntries(SnapshotFillerInterface*
filler) {
- if (EstimateObjectsCount() <= 0) return;
- filler->AddEntry(kNativesRootObject, this);
+ v8::RetainedObjectInfo* info =
+ reinterpret_cast<v8::RetainedObjectInfo*>(ptr);
+ intptr_t elements = info->GetElementCount();
+ intptr_t size = info->GetSizeInBytes();
+ return snapshot_->AddEntry(
+ HeapEntry::kNative,
+ elements != -1 ?
+ collection_->names()->GetFormatted(
+ "%s / %" V8_PTR_PREFIX "d entries",
+ info->GetLabel(),
+ info->GetElementCount()) :
+ collection_->names()->GetCopy(info->GetLabel()),
+ HeapObjectsMap::GenerateId(info),
+ size != -1 ? static_cast<int>(size) : 0,
+ children_count,
+ retainers_count);
}
@@ -2835,19 +2806,61 @@
SetWrapperNativeReferences(objects->at(i), info);
}
}
- SetRootNativesRootReference();
+ SetRootNativeRootsReference();
filler_ = NULL;
return true;
}
+
+
+class NativeGroupRetainedObjectInfo : public v8::RetainedObjectInfo {
+ public:
+ explicit NativeGroupRetainedObjectInfo(const char* label)
+ : disposed_(false),
+ hash_(reinterpret_cast<intptr_t>(label)),
+ label_(label) {
+ }
+
+ virtual ~NativeGroupRetainedObjectInfo() {}
+ virtual void Dispose() {
+ CHECK(!disposed_);
+ disposed_ = true;
+ }
+ virtual bool IsEquivalent(RetainedObjectInfo* other) {
+ return hash_ == other->GetHash() && !strcmp(label_, other->GetLabel());
+ }
+ virtual intptr_t GetHash() { return hash_; }
+ virtual const char* GetLabel() { return label_; }
+
+ private:
+ bool disposed_;
+ int hash_;
+ const char* label_;
+};
+
+
+NativeGroupRetainedObjectInfo* NativeObjectsExplorer::FindOrAddGroupInfo(
+ const char* label) {
+ const char* label_copy = collection_->names()->GetCopy(label);
+ intptr_t hash = HashSequentialString(label_copy, strlen(label_copy),
+ HEAP->HashSeed());
+ HashMap::Entry* entry =
native_groups_.Lookup(const_cast<char*>(label_copy),
+ hash, true);
+ if (entry->value == NULL)
+ entry->value = new NativeGroupRetainedObjectInfo(label);
+ return static_cast<NativeGroupRetainedObjectInfo*>(entry->value);
+}
void NativeObjectsExplorer::SetNativeRootReference(
v8::RetainedObjectInfo* info) {
HeapEntry* child_entry = filler_->FindOrAddEntry(info, this);
ASSERT(child_entry != NULL);
- filler_->SetIndexedAutoIndexReference(
- HeapGraphEdge::kElement,
- kNativesRootObject, snapshot_->natives_root(),
+ NativeGroupRetainedObjectInfo* group_info =
+ FindOrAddGroupInfo(info->GetGroupLabel());
+ HeapEntry* group_entry = filler_->FindOrAddEntry(group_info, this);
+ filler_->SetNamedAutoIndexReference(
+ HeapGraphEdge::kInternal,
+ group_info, group_entry,
info, child_entry);
}
@@ -2868,11 +2881,19 @@
}
-void NativeObjectsExplorer::SetRootNativesRootReference() {
- filler_->SetIndexedAutoIndexReference(
- HeapGraphEdge::kElement,
- V8HeapExplorer::kInternalRootObject, snapshot_->root(),
- kNativesRootObject, snapshot_->natives_root());
+void NativeObjectsExplorer::SetRootNativeRootsReference() {
+ for (HashMap::Entry* entry = native_groups_.Start();
+ entry;
+ entry = native_groups_.Next(entry)) {
+ NativeGroupRetainedObjectInfo* group_info =
+ static_cast<NativeGroupRetainedObjectInfo*>(entry->value);
+ HeapEntry* group_entry = filler_->FindOrAddEntry(group_info, this);
+ ASSERT(group_entry != NULL);
+ filler_->SetIndexedAutoIndexReference(
+ HeapGraphEdge::kElement,
+ V8HeapExplorer::kInternalRootObject, snapshot_->root(),
+ group_info, group_entry);
+ }
}
@@ -3107,7 +3128,6 @@
bool HeapSnapshotGenerator::CountEntriesAndReferences() {
SnapshotCounter counter(&entries_);
v8_heap_explorer_.AddRootEntries(&counter);
- dom_explorer_.AddRootEntries(&counter);
return
v8_heap_explorer_.IterateAndExtractReferences(&counter) &&
dom_explorer_.IterateAndExtractReferences(&counter);
=======================================
--- /branches/bleeding_edge/src/profile-generator.h Fri Jan 13 05:09:52 2012
+++ /branches/bleeding_edge/src/profile-generator.h Fri Jan 27 04:02:57 2012
@@ -1026,6 +1026,7 @@
DISALLOW_COPY_AND_ASSIGN(V8HeapExplorer);
};
+class NativeGroupRetainedObjectInfo;
// An implementation of retained native objects extractor.
class NativeObjectsExplorer : public HeapEntriesAllocator {
@@ -1043,7 +1044,7 @@
void FillRetainedObjects();
List<HeapObject*>* GetListMaybeDisposeInfo(v8::RetainedObjectInfo* info);
void SetNativeRootReference(v8::RetainedObjectInfo* info);
- void SetRootNativesRootReference();
+ void SetRootNativeRootsReference();
void SetWrapperNativeReferences(HeapObject* wrapper,
v8::RetainedObjectInfo* info);
void VisitSubtreeWrapper(Object** p, uint16_t class_id);
@@ -1057,6 +1058,12 @@
(reinterpret_cast<v8::RetainedObjectInfo*>(key1))->IsEquivalent(
reinterpret_cast<v8::RetainedObjectInfo*>(key2));
}
+ INLINE(static bool StringsMatch(void* key1, void* key2)) {
+ return strcmp(reinterpret_cast<char*>(key1),
+ reinterpret_cast<char*>(key2)) == 0;
+ }
+
+ NativeGroupRetainedObjectInfo* FindOrAddGroupInfo(const char* label);
HeapSnapshot* snapshot_;
HeapSnapshotsCollection* collection_;
@@ -1065,6 +1072,7 @@
HeapObjectsSet in_groups_;
// RetainedObjectInfo* -> List<HeapObject*>*
HashMap objects_by_info_;
+ HashMap native_groups_;
// Used during references extraction.
SnapshotFillerInterface* filler_;
=======================================
--- /branches/bleeding_edge/test/cctest/test-heap-profiler.cc Tue Dec 6
09:41:47 2011
+++ /branches/bleeding_edge/test/cctest/test-heap-profiler.cc Fri Jan 27
04:02:57 2012
@@ -666,11 +666,13 @@
class TestRetainedObjectInfo : public v8::RetainedObjectInfo {
public:
TestRetainedObjectInfo(int hash,
+ const char* group_label,
const char* label,
intptr_t element_count = -1,
intptr_t size = -1)
: disposed_(false),
hash_(hash),
+ group_label_(group_label),
label_(label),
element_count_(element_count),
size_(size) {
@@ -685,6 +687,7 @@
return GetHash() == other->GetHash();
}
virtual intptr_t GetHash() { return hash_; }
+ virtual const char* GetGroupLabel() { return group_label_; }
virtual const char* GetLabel() { return label_; }
virtual intptr_t GetElementCount() { return element_count_; }
virtual intptr_t GetSizeInBytes() { return size_; }
@@ -696,15 +699,15 @@
if (wrapper->IsString()) {
v8::String::AsciiValue ascii(wrapper);
if (strcmp(*ascii, "AAA") == 0)
- return new TestRetainedObjectInfo(1, "aaa", 100);
+ return new TestRetainedObjectInfo(1, "aaa-group", "aaa", 100);
else if (strcmp(*ascii, "BBB") == 0)
- return new TestRetainedObjectInfo(1, "aaa", 100);
+ return new TestRetainedObjectInfo(1, "aaa-group", "aaa", 100);
}
} else if (class_id == 2) {
if (wrapper->IsString()) {
v8::String::AsciiValue ascii(wrapper);
if (strcmp(*ascii, "CCC") == 0)
- return new TestRetainedObjectInfo(2, "ccc");
+ return new TestRetainedObjectInfo(2, "ccc-group", "ccc");
}
}
CHECK(false);
@@ -717,6 +720,7 @@
bool disposed_;
int category_;
int hash_;
+ const char* group_label_;
const char* label_;
intptr_t element_count_;
intptr_t size_;
@@ -769,18 +773,21 @@
delete TestRetainedObjectInfo::instances[i];
}
- const v8::HeapGraphNode* natives = GetNode(
- snapshot->GetRoot(), v8::HeapGraphNode::kObject, "(Native objects)");
- CHECK_NE(NULL, natives);
- CHECK_EQ(2, natives->GetChildrenCount());
+ const v8::HeapGraphNode* native_group_aaa = GetNode(
+ snapshot->GetRoot(), v8::HeapGraphNode::kNative, "aaa-group");
+ CHECK_NE(NULL, native_group_aaa);
+ CHECK_EQ(1, native_group_aaa->GetChildrenCount());
const v8::HeapGraphNode* aaa = GetNode(
- natives, v8::HeapGraphNode::kNative, "aaa / 100 entries");
+ native_group_aaa, v8::HeapGraphNode::kNative, "aaa / 100 entries");
CHECK_NE(NULL, aaa);
+ CHECK_EQ(2, aaa->GetChildrenCount());
+
+ const v8::HeapGraphNode* native_group_ccc = GetNode(
+ snapshot->GetRoot(), v8::HeapGraphNode::kNative, "ccc-group");
const v8::HeapGraphNode* ccc = GetNode(
- natives, v8::HeapGraphNode::kNative, "ccc");
+ native_group_ccc, v8::HeapGraphNode::kNative, "ccc");
CHECK_NE(NULL, ccc);
- CHECK_EQ(2, aaa->GetChildrenCount());
const v8::HeapGraphNode* n_AAA = GetNode(
aaa, v8::HeapGraphNode::kString, "AAA");
CHECK_NE(NULL, n_AAA);
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev