| 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; | 
| } | 
|  | 
|  | 
|  |