Index: src/profile-generator.cc |
diff --git a/src/profile-generator.cc b/src/profile-generator.cc |
index 29f9ab4d3536c4714639ce92caa65dcdb635bd0a..55ae56662796b92b28d16e0276fd22e8a6ab626d 100644 |
--- a/src/profile-generator.cc |
+++ b/src/profile-generator.cc |
@@ -829,7 +829,10 @@ void ProfileGenerator::RecordTickSample(const TickSample& sample) { |
void HeapGraphEdge::Init( |
int child_index, Type type, const char* name, HeapEntry* to) { |
- ASSERT(type == kContextVariable || type == kProperty || type == kInternal); |
+ ASSERT(type == kContextVariable |
+ || type == kProperty |
+ || type == kInternal |
+ || type == kShortcut); |
child_index_ = child_index; |
type_ = type; |
name_ = name; |
@@ -837,14 +840,20 @@ void HeapGraphEdge::Init( |
} |
-void HeapGraphEdge::Init(int child_index, int index, HeapEntry* to) { |
+void HeapGraphEdge::Init(int child_index, Type type, int index, HeapEntry* to) { |
+ ASSERT(type == kElement || type == kHidden); |
child_index_ = child_index; |
- type_ = kElement; |
+ type_ = type; |
index_ = index; |
to_ = to; |
} |
+void HeapGraphEdge::Init(int child_index, int index, HeapEntry* to) { |
+ Init(child_index, kElement, index, to); |
+} |
+ |
+ |
HeapEntry* HeapGraphEdge::From() { |
return reinterpret_cast<HeapEntry*>(this - child_index_) - 1; |
} |
@@ -879,9 +888,12 @@ void HeapEntry::SetNamedReference(HeapGraphEdge::Type type, |
} |
-void HeapEntry::SetElementReference( |
- int child_index, int index, HeapEntry* entry, int retainer_index) { |
- children_arr()[child_index].Init(child_index, index, entry); |
+void HeapEntry::SetIndexedReference(HeapGraphEdge::Type type, |
+ int child_index, |
+ int index, |
+ HeapEntry* entry, |
+ int retainer_index) { |
+ children_arr()[child_index].Init(child_index, type, index, entry); |
entry->retainers_arr()[retainer_index] = children_arr() + child_index; |
} |
@@ -929,6 +941,7 @@ void HeapEntry::ApplyAndPaintAllReachable(Visitor* visitor) { |
HeapEntry* entry = list.RemoveLast(); |
Vector<HeapGraphEdge> children = entry->children(); |
for (int i = 0; i < children.length(); ++i) { |
+ if (children[i].type() == HeapGraphEdge::kShortcut) continue; |
HeapEntry* child = children[i].to(); |
if (!child->painted_reachable()) { |
list.Add(child); |
@@ -985,6 +998,12 @@ void HeapEntry::Print(int max_depth, int indent) { |
case HeapGraphEdge::kProperty: |
OS::Print(" %*c %s: ", indent, ' ', edge.name()); |
break; |
+ case HeapGraphEdge::kHidden: |
+ OS::Print(" %*c $%d: ", indent, ' ', edge.index()); |
+ break; |
+ case HeapGraphEdge::kShortcut: |
+ OS::Print(" %*c ^%s: ", indent, ' ', edge.name()); |
+ break; |
default: |
OS::Print("!!! unknown edge type: %d ", edge.type()); |
} |
@@ -995,7 +1014,7 @@ void HeapEntry::Print(int max_depth, int indent) { |
const char* HeapEntry::TypeAsString() { |
switch (type()) { |
- case kInternal: return "/internal/"; |
+ case kHidden: return "/hidden/"; |
case kObject: return "/object/"; |
case kClosure: return "/closure/"; |
case kString: return "/string/"; |
@@ -1094,6 +1113,7 @@ void HeapEntryCalculatedData::CalculateSizes(HeapEntry* entry) { |
HeapEntry* curr = list.RemoveLast(); |
Vector<HeapGraphEdge> children = curr->children(); |
for (int i = 0; i < children.length(); ++i) { |
+ if (children[i].type() == HeapGraphEdge::kShortcut) continue; |
HeapEntry* child = children[i].to(); |
if (child != entry && child->not_painted_reachable_from_others()) { |
list.Add(child); |
@@ -1192,6 +1212,7 @@ void HeapGraphPath::Print() { |
OS::Print("[#%s] ", edge->name()); |
break; |
case HeapGraphEdge::kElement: |
+ case HeapGraphEdge::kHidden: |
OS::Print("[%d] ", edge->index()); |
break; |
case HeapGraphEdge::kInternal: |
@@ -1200,6 +1221,9 @@ void HeapGraphPath::Print() { |
case HeapGraphEdge::kProperty: |
OS::Print("[%s] ", edge->name()); |
break; |
+ case HeapGraphEdge::kShortcut: |
+ OS::Print("[^%s] ", edge->name()); |
+ break; |
default: |
OS::Print("!!! unknown edge type: %d ", edge->type()); |
} |
@@ -1211,6 +1235,8 @@ 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 |
@@ -1240,6 +1266,7 @@ HeapSnapshot::HeapSnapshot(HeapSnapshotsCollection* collection, |
title_(title), |
uid_(uid), |
root_entry_(NULL), |
+ gc_roots_entry_(NULL), |
raw_entries_(NULL), |
entries_sorted_(false) { |
STATIC_ASSERT( |
@@ -1280,9 +1307,20 @@ HeapEntry* HeapSnapshot::AddEntry(HeapObject* object, |
if (object == kInternalRootObject) { |
ASSERT(root_entry_ == NULL); |
ASSERT(retainers_count == 0); |
- root_entry_ = AddEntry( |
- HeapEntry::kInternal, "", 0, 0, children_count, retainers_count); |
- return root_entry_; |
+ return (root_entry_ = AddEntry(HeapEntry::kObject, |
+ "", |
+ HeapObjectsMap::kInternalRootObjectId, |
+ 0, |
+ children_count, |
+ retainers_count)); |
+ } else if (object == kGcRootsObject) { |
+ ASSERT(gc_roots_entry_ == NULL); |
+ return (gc_roots_entry_ = AddEntry(HeapEntry::kObject, |
+ "(GC roots)", |
+ HeapObjectsMap::kGcRootsObjectId, |
+ 0, |
+ children_count, |
+ retainers_count)); |
} else if (object->IsJSFunction()) { |
JSFunction* func = JSFunction::cast(object); |
SharedFunctionInfo* shared = func->shared(); |
@@ -1345,22 +1383,11 @@ HeapEntry* HeapSnapshot::AddEntry(HeapObject* object, |
children_count, |
retainers_count); |
} |
- // No interest in this object. |
- return NULL; |
-} |
- |
- |
-bool HeapSnapshot::WillAddEntry(HeapObject* object) { |
- return object == kInternalRootObject |
- || object->IsJSFunction() |
- || object->IsJSRegExp() |
- || object->IsJSObject() |
- || object->IsString() |
- || object->IsCode() |
- || object->IsSharedFunctionInfo() |
- || object->IsScript() |
- || object->IsFixedArray() |
- || object->IsHeapNumber(); |
+ return AddEntry(object, |
+ HeapEntry::kHidden, |
+ "system", |
+ children_count, |
+ retainers_count); |
} |
@@ -1387,7 +1414,7 @@ HeapEntry* HeapSnapshot::AddEntry(HeapObject* object, |
return AddEntry(type, |
name, |
collection_->GetObjectId(object->address()), |
- GetObjectSize(object), |
+ object->Size(), |
children_count, |
retainers_count); |
} |
@@ -1419,36 +1446,6 @@ HeapEntry* HeapSnapshot::GetNextEntryToInit() { |
} |
-int HeapSnapshot::GetObjectSize(HeapObject* obj) { |
- return obj->IsJSObject() ? |
- CalculateNetworkSize(JSObject::cast(obj)) : obj->Size(); |
-} |
- |
- |
-int HeapSnapshot::CalculateNetworkSize(JSObject* obj) { |
- int size = obj->Size(); |
- // If 'properties' and 'elements' are non-empty (thus, non-shared), |
- // take their size into account. |
- if (obj->properties() != Heap::empty_fixed_array()) { |
- size += obj->properties()->Size(); |
- } |
- if (obj->elements() != Heap::empty_fixed_array()) { |
- size += obj->elements()->Size(); |
- } |
- // For functions, also account non-empty context and literals sizes. |
- if (obj->IsJSFunction()) { |
- JSFunction* f = JSFunction::cast(obj); |
- if (f->unchecked_context()->IsContext()) { |
- size += f->context()->Size(); |
- } |
- if (f->literals()->length() != 0) { |
- size += f->literals()->Size(); |
- } |
- } |
- return size; |
-} |
- |
- |
HeapSnapshotsDiff* HeapSnapshot::CompareWith(HeapSnapshot* snapshot) { |
return collection_->CompareSnapshots(this, snapshot); |
} |
@@ -1475,9 +1472,12 @@ void HeapSnapshot::Print(int max_depth) { |
} |
+const uint64_t HeapObjectsMap::kInternalRootObjectId = 0; |
+const uint64_t HeapObjectsMap::kGcRootsObjectId = 1; |
Søren Thygesen Gjesse
2010/11/18 08:14:54
Please add kNumReservedObjectsIds = 2 (maybe you c
mnaganov (inactive)
2010/11/18 10:32:51
OK, I've introduced kFirstAvailableObjectId.
|
+ |
HeapObjectsMap::HeapObjectsMap() |
: initial_fill_mode_(true), |
- next_id_(1), |
+ next_id_(2), // Reserve 0..1 for internal root objects. |
entries_map_(AddressesMatch), |
entries_(new List<EntryInfo>()) { } |
@@ -1628,17 +1628,7 @@ HeapEntriesMap::HeapEntriesMap() |
HeapEntriesMap::~HeapEntriesMap() { |
for (HashMap::Entry* p = entries_.Start(); p != NULL; p = entries_.Next(p)) { |
- if (!IsAlias(p->value)) delete reinterpret_cast<EntryInfo*>(p->value); |
- } |
-} |
- |
- |
-void HeapEntriesMap::Alias(HeapObject* from, HeapObject* to) { |
- HashMap::Entry* from_cache_entry = entries_.Lookup(from, Hash(from), true); |
- HashMap::Entry* to_cache_entry = entries_.Lookup(to, Hash(to), false); |
- if (from_cache_entry->value == NULL) { |
- ASSERT(to_cache_entry != NULL); |
- from_cache_entry->value = MakeAlias(to_cache_entry->value); |
+ delete reinterpret_cast<EntryInfo*>(p->value); |
} |
} |
@@ -1646,8 +1636,7 @@ void HeapEntriesMap::Alias(HeapObject* from, HeapObject* to) { |
HeapEntry* HeapEntriesMap::Map(HeapObject* object) { |
HashMap::Entry* cache_entry = entries_.Lookup(object, Hash(object), false); |
if (cache_entry != NULL) { |
- EntryInfo* entry_info = |
- reinterpret_cast<EntryInfo*>(Unalias(cache_entry->value)); |
+ EntryInfo* entry_info = reinterpret_cast<EntryInfo*>(cache_entry->value); |
return entry_info->entry; |
} else { |
return NULL; |
@@ -1671,9 +1660,9 @@ void HeapEntriesMap::CountReference(HeapObject* from, HeapObject* to, |
ASSERT(from_cache_entry != NULL); |
ASSERT(to_cache_entry != NULL); |
EntryInfo* from_entry_info = |
- reinterpret_cast<EntryInfo*>(Unalias(from_cache_entry->value)); |
+ reinterpret_cast<EntryInfo*>(from_cache_entry->value); |
EntryInfo* to_entry_info = |
- reinterpret_cast<EntryInfo*>(Unalias(to_cache_entry->value)); |
+ reinterpret_cast<EntryInfo*>(to_cache_entry->value); |
if (prev_children_count) |
*prev_children_count = from_entry_info->children_count; |
if (prev_retainers_count) |
@@ -1685,6 +1674,36 @@ void HeapEntriesMap::CountReference(HeapObject* from, HeapObject* to, |
} |
+HeapObjectsSet::HeapObjectsSet() |
+ : entries_(HeapEntriesMap::HeapObjectsMatch) { |
+} |
+ |
+ |
+void HeapObjectsSet::Clear() { |
+ entries_.Clear(); |
+} |
+ |
+ |
+bool HeapObjectsSet::Contains(Object* obj) { |
+ if (!obj->IsHeapObject()) return false; |
+ HeapObject* object = HeapObject::cast(obj); |
+ HashMap::Entry* cache_entry = |
+ entries_.Lookup(object, HeapEntriesMap::Hash(object), false); |
+ return cache_entry != NULL; |
+} |
+ |
+ |
+void HeapObjectsSet::Insert(Object* obj) { |
+ if (!obj->IsHeapObject()) return; |
+ HeapObject* object = HeapObject::cast(obj); |
+ HashMap::Entry* cache_entry = |
+ entries_.Lookup(object, HeapEntriesMap::Hash(object), true); |
+ if (cache_entry->value == NULL) { |
+ cache_entry->value = HeapEntriesMap::kHeapEntryPlaceholder; |
+ } |
+} |
+ |
+ |
HeapSnapshotGenerator::HeapSnapshotGenerator(HeapSnapshot* snapshot) |
: snapshot_(snapshot), |
collection_(snapshot->collection()), |
@@ -1699,7 +1718,8 @@ class SnapshotCounter : public HeapSnapshotGenerator::SnapshotFillerInterface { |
entries_->Pair(obj, HeapEntriesMap::kHeapEntryPlaceholder); |
return HeapEntriesMap::kHeapEntryPlaceholder; |
} |
- void SetElementReference(HeapObject* parent_obj, |
+ void SetIndexedReference(HeapGraphEdge::Type, |
+ HeapObject* parent_obj, |
HeapEntry*, |
int, |
Object* child_obj, |
@@ -1714,10 +1734,18 @@ class SnapshotCounter : public HeapSnapshotGenerator::SnapshotFillerInterface { |
HeapEntry*) { |
entries_->CountReference(parent_obj, HeapObject::cast(child_obj)); |
} |
- void SetRootReference(Object* child_obj, HeapEntry*) { |
+ 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_; |
}; |
@@ -1733,16 +1761,19 @@ class SnapshotFiller : public HeapSnapshotGenerator::SnapshotFillerInterface { |
UNREACHABLE(); |
return NULL; |
} |
- void SetElementReference(HeapObject* parent_obj, |
+ 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->SetElementReference( |
- child_index, index, child_entry, 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, |
@@ -1759,13 +1790,43 @@ class SnapshotFiller : public HeapSnapshotGenerator::SnapshotFillerInterface { |
child_entry, |
retainer_index); |
} |
- void SetRootReference(Object* child_obj, HeapEntry* child_entry) { |
+ void SetRootGcRootsReference() { |
int child_index, retainer_index; |
- entries_->CountReference( |
- HeapSnapshot::kInternalRootObject, HeapObject::cast(child_obj), |
- &child_index, &retainer_index); |
- snapshot_->root()->SetElementReference( |
- child_index, child_index + 1, child_entry, 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_; |
@@ -1788,6 +1849,18 @@ class SnapshotAllocator { |
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_; |
+}; |
+ |
Søren Thygesen Gjesse
2010/11/18 08:14:54
Add empty line.
mnaganov (inactive)
2010/11/18 10:32:51
Done.
|
void HeapSnapshotGenerator::GenerateSnapshot() { |
AssertNoAllocation no_alloc; |
@@ -1795,12 +1868,14 @@ void HeapSnapshotGenerator::GenerateSnapshot() { |
SnapshotCounter counter(&entries_); |
filler_ = &counter; |
filler_->AddEntry(HeapSnapshot::kInternalRootObject); |
- HeapIterator iterator1; |
- for (HeapObject* obj = iterator1.next(); |
- obj != NULL; |
- obj = iterator1.next()) { |
+ filler_->AddEntry(HeapSnapshot::kGcRootsObject); |
+ HeapIterator iterator(HeapIterator::kPreciseFiltering); |
+ for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) { |
ExtractReferences(obj); |
} |
+ SetRootGcRootsReference(); |
+ RootsReferencesExtractor extractor(this); |
+ Heap::IterateRoots(&extractor, VISIT_ONLY_STRONG); |
// Allocate and fill entries in the snapshot, allocate references. |
snapshot_->AllocateEntries(entries_.entries_count(), |
@@ -1812,12 +1887,12 @@ void HeapSnapshotGenerator::GenerateSnapshot() { |
// Pass 2. Fill references. |
SnapshotFiller filler(snapshot_, &entries_); |
filler_ = &filler; |
- HeapIterator iterator2; |
- for (HeapObject* obj = iterator2.next(); |
- obj != NULL; |
- obj = iterator2.next()) { |
+ iterator.reset(); |
+ for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) { |
ExtractReferences(obj); |
} |
+ SetRootGcRootsReference(); |
+ Heap::IterateRoots(&extractor, VISIT_ONLY_STRONG); |
} |
@@ -1825,25 +1900,8 @@ 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) { |
- if (obj->IsJSGlobalPropertyCell()) { |
- Object* cell_target = JSGlobalPropertyCell::cast(obj)->value(); |
- entry = GetEntry(cell_target); |
- // If GPC references an object that we have interest in (see |
- // HeapSnapshot::AddEntry, WillAddEntry), add the object. We |
- // don't store HeapEntries for GPCs. Instead, we make our hash |
- // map to point to object's HeapEntry by GPCs address. |
- if (entry != NULL) { |
- entries_.Alias(object, HeapObject::cast(cell_target)); |
- } |
- return entry; |
- } |
- |
- if (snapshot_->WillAddEntry(object)) entry = filler_->AddEntry(object); |
- } |
- |
+ if (entry == NULL) entry = filler_->AddEntry(object); |
return entry; |
} |
@@ -1852,43 +1910,44 @@ class IndexedReferencesExtractor : public ObjectVisitor { |
public: |
IndexedReferencesExtractor(HeapSnapshotGenerator* generator, |
HeapObject* parent_obj, |
- HeapEntry* parent_entry) |
+ HeapEntry* parent_entry, |
+ HeapObjectsSet* knownReferences = NULL) |
Søren Thygesen Gjesse
2010/11/18 08:14:54
knownReferences -> known_references
mnaganov (inactive)
2010/11/18 10:32:51
Done.
|
: generator_(generator), |
parent_obj_(parent_obj), |
parent_(parent_entry), |
+ known_references_(knownReferences), |
next_index_(1) { |
} |
- |
- void VisitPointer(Object** o) { |
- generator_->SetElementReference(parent_obj_, parent_, next_index_++, *o); |
- } |
- |
void VisitPointers(Object** start, Object** end) { |
- for (Object** p = start; p < end; p++) VisitPointer(p); |
+ for (Object** p = start; p < end; p++) { |
+ if (!known_references_ || !known_references_->Contains(*p)) { |
+ generator_->SetHiddenReference(parent_obj_, parent_, next_index_++, *p); |
+ } |
+ } |
} |
- |
private: |
HeapSnapshotGenerator* generator_; |
HeapObject* parent_obj_; |
HeapEntry* parent_; |
+ HeapObjectsSet* known_references_; |
int next_index_; |
}; |
void HeapSnapshotGenerator::ExtractReferences(HeapObject* obj) { |
- // We need to reference JS global objects from snapshot's root. |
- // We use JSGlobalProxy because this is what embedder (e.g. browser) |
- // uses for the global object. |
- if (obj->IsJSGlobalProxy()) { |
- JSGlobalProxy* proxy = JSGlobalProxy::cast(obj); |
- SetRootReference(proxy->map()->prototype()); |
- return; |
- } |
- |
HeapEntry* entry = GetEntry(obj); |
if (entry == NULL) return; // No interest in this object. |
- if (obj->IsJSObject()) { |
+ known_references_.Clear(); |
+ if (obj->IsJSGlobalProxy()) { |
+ // We need to reference JS global objects from snapshot's root. |
+ // We use JSGlobalProxy because this is what embedder (e.g. browser) |
+ // uses for the global object. |
+ JSGlobalProxy* proxy = JSGlobalProxy::cast(obj); |
+ SetRootShortcutReference(proxy->map()->prototype()); |
+ IndexedReferencesExtractor refs_extractor(this, obj, entry); |
+ obj->Iterate(&refs_extractor); |
+ } else if (obj->IsJSObject()) { |
JSObject* js_obj = JSObject::cast(obj); |
ExtractClosureReferences(js_obj, entry); |
ExtractPropertyReferences(js_obj, entry); |
@@ -1903,16 +1962,16 @@ void HeapSnapshotGenerator::ExtractReferences(HeapObject* obj) { |
obj, entry, Heap::prototype_symbol(), js_fun->prototype()); |
} |
} |
+ IndexedReferencesExtractor refs_extractor( |
+ this, obj, entry, &known_references_); |
+ obj->Iterate(&refs_extractor); |
} else if (obj->IsString()) { |
if (obj->IsConsString()) { |
ConsString* cs = ConsString::cast(obj); |
- SetInternalReference(obj, entry, "1", cs->first()); |
- SetInternalReference(obj, entry, "2", cs->second()); |
+ SetInternalReference(obj, entry, 1, cs->first()); |
+ SetInternalReference(obj, entry, 2, cs->second()); |
} |
- } else if (obj->IsCode() || obj->IsSharedFunctionInfo() || obj->IsScript()) { |
- IndexedReferencesExtractor refs_extractor(this, obj, entry); |
- obj->Iterate(&refs_extractor); |
- } else if (obj->IsFixedArray()) { |
+ } else { |
IndexedReferencesExtractor refs_extractor(this, obj, entry); |
obj->Iterate(&refs_extractor); |
} |
@@ -1967,8 +2026,17 @@ void HeapSnapshotGenerator::ExtractPropertyReferences(JSObject* js_obj, |
for (int i = 0; i < length; ++i) { |
Object* k = dictionary->KeyAt(i); |
if (dictionary->IsKey(k)) { |
+ Object* target = dictionary->ValueAt(i); |
SetPropertyReference( |
- js_obj, entry, String::cast(k), dictionary->ValueAt(i)); |
+ js_obj, entry, String::cast(k), target); |
+ // We assume that global objects can only have slow properties. |
+ if (target->IsJSGlobalPropertyCell()) { |
+ SetPropertyShortcutReference(js_obj, |
+ entry, |
+ String::cast(k), |
+ JSGlobalPropertyCell::cast( |
+ target)->value()); |
+ } |
} |
} |
} |
@@ -2024,6 +2092,7 @@ void HeapSnapshotGenerator::SetClosureReference(HeapObject* parent_obj, |
collection_->GetName(reference_name), |
child_obj, |
child_entry); |
+ known_references_.Insert(child_obj); |
} |
} |
@@ -2034,8 +2103,13 @@ void HeapSnapshotGenerator::SetElementReference(HeapObject* parent_obj, |
Object* child_obj) { |
HeapEntry* child_entry = GetEntry(child_obj); |
if (child_entry != NULL) { |
- filler_->SetElementReference( |
- parent_obj, parent_entry, index, child_obj, child_entry); |
+ filler_->SetIndexedReference(HeapGraphEdge::kElement, |
+ parent_obj, |
+ parent_entry, |
+ index, |
+ child_obj, |
+ child_entry); |
+ known_references_.Insert(child_obj); |
} |
} |
@@ -2052,6 +2126,7 @@ void HeapSnapshotGenerator::SetInternalReference(HeapObject* parent_obj, |
reference_name, |
child_obj, |
child_entry); |
+ known_references_.Insert(child_obj); |
} |
} |
@@ -2068,6 +2143,23 @@ void HeapSnapshotGenerator::SetInternalReference(HeapObject* parent_obj, |
collection_->GetName(index), |
child_obj, |
child_entry); |
+ known_references_.Insert(child_obj); |
+ } |
+} |
+ |
+ |
+void HeapSnapshotGenerator::SetHiddenReference(HeapObject* parent_obj, |
+ HeapEntry* parent_entry, |
+ int index, |
+ Object* child_obj) { |
+ HeapEntry* child_entry = GetEntry(child_obj); |
+ if (child_entry != NULL) { |
+ filler_->SetIndexedReference(HeapGraphEdge::kHidden, |
+ parent_obj, |
+ parent_entry, |
+ index, |
+ child_obj, |
+ child_entry); |
} |
} |
@@ -2086,14 +2178,45 @@ void HeapSnapshotGenerator::SetPropertyReference(HeapObject* parent_obj, |
collection_->GetName(reference_name), |
child_obj, |
child_entry); |
+ known_references_.Insert(child_obj); |
} |
} |
-void HeapSnapshotGenerator::SetRootReference(Object* child_obj) { |
+void HeapSnapshotGenerator::SetPropertyShortcutReference( |
+ HeapObject* parent_obj, |
+ HeapEntry* parent_entry, |
+ String* reference_name, |
+ Object* child_obj) { |
+ HeapEntry* child_entry = GetEntry(child_obj); |
+ if (child_entry != NULL) { |
+ filler_->SetNamedReference(HeapGraphEdge::kShortcut, |
+ parent_obj, |
+ parent_entry, |
+ collection_->GetName(reference_name), |
+ child_obj, |
+ child_entry); |
+ } |
+} |
+ |
+ |
+void HeapSnapshotGenerator::SetRootGcRootsReference() { |
+ filler_->SetRootGcRootsReference(); |
+} |
+ |
+ |
+void HeapSnapshotGenerator::SetRootShortcutReference(Object* child_obj) { |
HeapEntry* child_entry = GetEntry(child_obj); |
ASSERT(child_entry != NULL); |
- filler_->SetRootReference(child_obj, child_entry); |
+ filler_->SetRootShortcutReference(child_obj, child_entry); |
+} |
+ |
+ |
+void HeapSnapshotGenerator::SetGcRootsReference(Object* child_obj) { |
+ HeapEntry* child_entry = GetEntry(child_obj); |
+ if (child_entry != NULL) { |
+ filler_->SetStrongRootReference(child_obj, child_entry); |
+ } |
} |
@@ -2101,11 +2224,11 @@ void HeapSnapshotsDiff::CreateRoots(int additions_count, int deletions_count) { |
raw_additions_root_ = |
NewArray<char>(HeapEntry::EntriesSize(1, additions_count, 0)); |
additions_root()->Init( |
- snapshot2_, HeapEntry::kInternal, "", 0, 0, additions_count, 0); |
+ snapshot2_, HeapEntry::kHidden, "", 0, 0, additions_count, 0); |
raw_deletions_root_ = |
NewArray<char>(HeapEntry::EntriesSize(1, deletions_count, 0)); |
deletions_root()->Init( |
- snapshot1_, HeapEntry::kInternal, "", 0, 0, deletions_count, 0); |
+ snapshot1_, HeapEntry::kHidden, "", 0, 0, deletions_count, 0); |
} |
@@ -2324,7 +2447,8 @@ void HeapSnapshotJSONSerializer::SerializeEdge(HeapGraphEdge* edge) { |
writer_->AddCharacter(','); |
writer_->AddNumber(edge->type()); |
writer_->AddCharacter(','); |
- if (edge->type() == HeapGraphEdge::kElement) { |
+ if (edge->type() == HeapGraphEdge::kElement |
+ || edge->type() == HeapGraphEdge::kHidden) { |
writer_->AddNumber(edge->index()); |
} else { |
writer_->AddNumber(GetStringId(edge->name())); |
@@ -2355,13 +2479,13 @@ void HeapSnapshotJSONSerializer::SerializeNode(HeapEntry* entry) { |
void HeapSnapshotJSONSerializer::SerializeNodes() { |
- // The first (zero) item of nodes array is a JSON-ified object |
- // describing node serialization layout. |
- // We use a set of macros to improve readability. |
+ // The first (zero) item of nodes array is an object describing node |
+ // serialization layout. We use a set of macros to improve |
+ // readability. |
#define JSON_A(s) "["s"]" |
#define JSON_O(s) "{"s"}" |
-#define JSON_S(s) "\\\""s"\\\"" |
- writer_->AddString("\"" JSON_O( |
+#define JSON_S(s) "\""s"\"" |
+ writer_->AddString(JSON_O( |
JSON_S("fields") ":" JSON_A( |
JSON_S("type") |
"," JSON_S("name") |
@@ -2371,7 +2495,7 @@ void HeapSnapshotJSONSerializer::SerializeNodes() { |
"," JSON_S("children")) |
"," JSON_S("types") ":" JSON_A( |
JSON_A( |
- JSON_S("internal") |
+ JSON_S("hidden") |
"," JSON_S("array") |
"," JSON_S("string") |
"," JSON_S("object") |
@@ -2393,9 +2517,11 @@ void HeapSnapshotJSONSerializer::SerializeNodes() { |
JSON_S("context") |
"," JSON_S("element") |
"," JSON_S("property") |
- "," JSON_S("internal")) |
+ "," JSON_S("internal") |
+ "," JSON_S("hidden") |
+ "," JSON_S("shortcut")) |
"," JSON_S("string_or_number") |
- "," JSON_S("node"))))) "\""); |
+ "," JSON_S("node")))))); |
#undef JSON_S |
#undef JSON_O |
#undef JSON_A |