Reviewers: Mikhail Naganov (Chromium), Yury Semikhatsky, loislo,

Description:
Show names for the strong roots in heap snapshot.


Please review this at https://chromiumcodereview.appspot.com/10128006/

SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge

Affected files:
  M src/profile-generator.h
  M src/profile-generator.cc
  M test/cctest/test-heap-profiler.cc


Index: src/profile-generator.cc
diff --git a/src/profile-generator.cc b/src/profile-generator.cc
index 5d74c42ac1e0a6ec1310734bd5816a7203da29b6..ddc42f9763b774050c7d0e89f0118d96e0a1e282 100644
--- a/src/profile-generator.cc
+++ b/src/profile-generator.cc
@@ -1736,7 +1736,8 @@ V8HeapExplorer::V8HeapExplorer(
       snapshot_(snapshot),
       collection_(snapshot_->collection()),
       progress_(progress),
-      filler_(NULL) {
+      filler_(NULL),
+      gc_subroot_names_(HeapEntriesMap::HeapThingsMatch) {
 }


@@ -2653,11 +2654,49 @@ void V8HeapExplorer::SetGcSubrootReference(
     VisitorSynchronization::SyncTag tag, bool is_weak, Object* child_obj) {
   HeapEntry* child_entry = GetEntry(child_obj);
   if (child_entry != NULL) {
-    filler_->SetIndexedAutoIndexReference(
-        is_weak ? HeapGraphEdge::kWeak : HeapGraphEdge::kElement,
-        GetNthGcSubrootObject(tag), snapshot_->gc_subroot(tag),
-        child_obj, child_entry);
-  }
+    const char* name = GetGcSubrootName(child_obj);
+    if (name != NULL) {
+      filler_->SetNamedReference(
+          HeapGraphEdge::kInternal,
+          GetNthGcSubrootObject(tag), snapshot_->gc_subroot(tag),
+          name,
+          child_obj, child_entry);
+    } else {
+      filler_->SetIndexedAutoIndexReference(
+          is_weak ? HeapGraphEdge::kWeak : HeapGraphEdge::kElement,
+          GetNthGcSubrootObject(tag), snapshot_->gc_subroot(tag),
+          child_obj, child_entry);
+    }
+  }
+}
+
+
+const char* V8HeapExplorer::GetGcSubrootName(Object* object) {
+  if (gc_subroot_names_.occupancy() == 0) {
+    HashMap::Entry* entry;
+    Object* obj;
+#define NAME_ENTRY(name) \
+    obj = heap_->name(); \
+    if (obj != NULL) { \
+ entry = gc_subroot_names_.Lookup(obj, HeapEntriesMap::Hash(obj), true); \
+      entry->value = const_cast<char*>(#name); \
+    }
+#define ROOT_NAME(type, name, camel_name) NAME_ENTRY(name)
+    STRONG_ROOT_LIST(ROOT_NAME)
+#undef ROOT_NAME
+#define STRUCT_MAP_NAME(NAME, Name, name) NAME_ENTRY(name##_map)
+    STRUCT_LIST(STRUCT_MAP_NAME)
+#undef STRUCT_MAP_NAME
+#define SYMBOL_NAME(name, str) NAME_ENTRY(name)
+    SYMBOL_LIST(SYMBOL_NAME)
+#undef SYMBOL_NAME
+#undef NAME_ENTRY
+    CHECK(gc_subroot_names_.occupancy() > 0);
+    CHECK(gc_subroot_names_.occupancy() <= Heap::kStrongRootListLength);
+  }
+  HashMap::Entry* entry = gc_subroot_names_.Lookup(
+      object, HeapEntriesMap::Hash(object), false);
+ return entry != NULL ? reinterpret_cast<const char*>(entry->value) : NULL;
 }


Index: src/profile-generator.h
diff --git a/src/profile-generator.h b/src/profile-generator.h
index 961cc8d1fcb61f2c9e4a0cf103f82d131219ad9f..13f3f17d70ada856e9dd2f7ee23a6aea8a3613aa 100644
--- a/src/profile-generator.h
+++ b/src/profile-generator.h
@@ -853,6 +853,15 @@ class HeapEntriesMap {

   static HeapEntry* const kHeapEntryPlaceholder;

+  static uint32_t Hash(HeapThing thing) {
+    return ComputeIntegerHash(
+        static_cast<uint32_t>(reinterpret_cast<uintptr_t>(thing)),
+        v8::internal::kZeroHashSeed);
+  }
+  static bool HeapThingsMatch(HeapThing key1, HeapThing key2) {
+    return key1 == key2;
+  }
+
  private:
   struct EntryInfo {
     EntryInfo(HeapEntry* entry, HeapEntriesAllocator* allocator)
@@ -869,15 +878,6 @@ class HeapEntriesMap {

static inline void AllocateHeapEntryForMapEntry(HashMap::Entry* map_entry);

-  static uint32_t Hash(HeapThing thing) {
-    return ComputeIntegerHash(
-        static_cast<uint32_t>(reinterpret_cast<uintptr_t>(thing)),
-        v8::internal::kZeroHashSeed);
-  }
-  static bool HeapThingsMatch(HeapThing key1, HeapThing key2) {
-    return key1 == key2;
-  }
-
   HashMap entries_;
   int entries_count_;
   int total_children_count_;
@@ -1025,6 +1025,7 @@ class V8HeapExplorer : public HeapEntriesAllocator {
   void SetGcRootsReference(VisitorSynchronization::SyncTag tag);
   void SetGcSubrootReference(
       VisitorSynchronization::SyncTag tag, bool is_weak, Object* child);
+  const char* GetGcSubrootName(Object* object);
   void SetObjectName(HeapObject* object);
   void TagObject(Object* obj, const char* tag);

@@ -1039,6 +1040,7 @@ class V8HeapExplorer : public HeapEntriesAllocator {
   SnapshottingProgressReportingInterface* progress_;
   SnapshotFillerInterface* filler_;
   HeapObjectsSet objects_tags_;
+  HashMap gc_subroot_names_;

   static HeapObject* const kGcRootsObject;
   static HeapObject* const kFirstGcSubrootObject;
Index: test/cctest/test-heap-profiler.cc
diff --git a/test/cctest/test-heap-profiler.cc b/test/cctest/test-heap-profiler.cc index 53b4f7e118351fa1a850a45c80074c4551e74f6d..85caa3f957d42c5f5f9bdd446e455a9fa9dfadb9 100644
--- a/test/cctest/test-heap-profiler.cc
+++ b/test/cctest/test-heap-profiler.cc
@@ -10,6 +10,7 @@
 #include "debug.h"
 #include "utils-inl.h"
 #include "../include/v8-profiler.h"
+#include <ctype.h>

 namespace {

@@ -1621,3 +1622,25 @@ TEST(PersistentHandleCount) {
   p_BBB.Dispose();
CHECK_EQ(global_handle_count, v8::HeapProfiler::GetPersistentHandleCount());
 }
+
+
+TEST(AllStrongGcRootsHaveNames) {
+  v8::HandleScope scope;
+  LocalContext env;
+
+  CompileRun("foo = {};");
+  const v8::HeapSnapshot* snapshot =
+      v8::HeapProfiler::TakeSnapshot(v8_str("snapshot"));
+  const v8::HeapGraphNode* gc_roots = GetNode(
+      snapshot->GetRoot(), v8::HeapGraphNode::kObject, "(GC roots)");
+  CHECK_NE(NULL, gc_roots);
+  const v8::HeapGraphNode* strong_roots = GetNode(
+      gc_roots, v8::HeapGraphNode::kObject, "(Strong roots)");
+  CHECK_NE(NULL, strong_roots);
+  for (int i = 0; i < strong_roots->GetChildrenCount(); ++i) {
+    const v8::HeapGraphEdge* edge = strong_roots->GetChild(i);
+    CHECK_EQ(v8::HeapGraphEdge::kInternal, edge->GetType());
+    v8::String::AsciiValue name(edge->GetName());
+    CHECK(isalpha(**name));
+  }
+}


--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to