Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(115)

Unified Diff: src/profile-generator.cc

Issue 5139002: New heap profiler: include all heap objects and refs into snapshot. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 10 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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

Powered by Google App Engine
This is Rietveld 408576698