From 72a9e445e5be0aa2ef26f5c10152986ca348675a Mon Sep 17 00:00:00 2001 From: "alexeif@chromium.org" Date: Thu, 19 Apr 2012 15:58:42 +0000 Subject: [PATCH] Show names for the strong roots in heap snapshot. Review URL: https://chromiumcodereview.appspot.com/10128006 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@11392 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/profile-generator.cc | 36 +++++++++++++++++++++++++++---- src/profile-generator.h | 3 +++ test/cctest/test-heap-profiler.cc | 24 +++++++++++++++++++++ 3 files changed, 59 insertions(+), 4 deletions(-) diff --git a/src/profile-generator.cc b/src/profile-generator.cc index c7ddd16b59..256136d9f1 100644 --- a/src/profile-generator.cc +++ b/src/profile-generator.cc @@ -2655,14 +2655,42 @@ 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 = GetStrongGcSubrootName(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::GetStrongGcSubrootName(Object* object) { + if (strong_gc_subroot_names_.is_empty()) { +#define NAME_ENTRY(name) strong_gc_subroot_names_.SetTag(heap_->name(), #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(!strong_gc_subroot_names_.is_empty()); + } + return strong_gc_subroot_names_.GetTag(object); +} + + void V8HeapExplorer::TagObject(Object* obj, const char* tag) { if (obj->IsHeapObject() && !obj->IsOddball() && diff --git a/src/profile-generator.h b/src/profile-generator.h index 961cc8d1fc..aee741f1d2 100644 --- a/src/profile-generator.h +++ b/src/profile-generator.h @@ -897,6 +897,7 @@ class HeapObjectsSet { void Insert(Object* obj); const char* GetTag(Object* obj); void SetTag(Object* obj, const char* tag); + bool is_empty() const { return entries_.occupancy() == 0; } private: HashMap entries_; @@ -1025,6 +1026,7 @@ class V8HeapExplorer : public HeapEntriesAllocator { void SetGcRootsReference(VisitorSynchronization::SyncTag tag); void SetGcSubrootReference( VisitorSynchronization::SyncTag tag, bool is_weak, Object* child); + const char* GetStrongGcSubrootName(Object* object); void SetObjectName(HeapObject* object); void TagObject(Object* obj, const char* tag); @@ -1039,6 +1041,7 @@ class V8HeapExplorer : public HeapEntriesAllocator { SnapshottingProgressReportingInterface* progress_; SnapshotFillerInterface* filler_; HeapObjectsSet objects_tags_; + HeapObjectsSet strong_gc_subroot_names_; static HeapObject* const kGcRootsObject; static HeapObject* const kFirstGcSubrootObject; diff --git a/test/cctest/test-heap-profiler.cc b/test/cctest/test-heap-profiler.cc index 53b4f7e118..4724d6d82a 100644 --- a/test/cctest/test-heap-profiler.cc +++ b/test/cctest/test-heap-profiler.cc @@ -4,6 +4,8 @@ #include "v8.h" +#include + #include "cctest.h" #include "heap-profiler.h" #include "snapshot.h" @@ -1621,3 +1623,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)); + } +}