Chromium Code Reviews| Index: src/profile-generator.cc |
| diff --git a/src/profile-generator.cc b/src/profile-generator.cc |
| index dd2f7014dbd4ae1a36ae8f74bdeb53c27a7b58fd..12e48e48071c8ca211fea85355c289833177c6e4 100644 |
| --- a/src/profile-generator.cc |
| +++ b/src/profile-generator.cc |
| @@ -992,8 +992,8 @@ void HeapEntry::SetNamedReference(HeapGraphEdge::Type type, |
| const char* name, |
| HeapEntry* entry, |
| int retainer_index) { |
| - children_arr()[child_index].Init(child_index, type, name, entry); |
| - entry->retainers_arr()[retainer_index] = children_arr() + child_index; |
| + children()[child_index].Init(child_index, type, name, entry); |
| + entry->retainers()[retainer_index] = children_arr() + child_index; |
| } |
| @@ -1002,14 +1002,14 @@ void HeapEntry::SetIndexedReference(HeapGraphEdge::Type type, |
| 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; |
| + children()[child_index].Init(child_index, type, index, entry); |
| + entry->retainers()[retainer_index] = children_arr() + child_index; |
| } |
| void HeapEntry::SetUnidirElementReference( |
| int child_index, int index, HeapEntry* entry) { |
| - children_arr()[child_index].Init(child_index, index, entry); |
| + children()[child_index].Init(child_index, index, entry); |
| } |
| @@ -1671,18 +1671,6 @@ HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object, |
| GetGcSubrootOrder(object), |
| children_count, |
| retainers_count); |
| - } else if (object->IsJSGlobalObject()) { |
|
mnaganov (inactive)
2012/03/05 16:21:58
Will this fall through down to the generic case th
alexeif
2012/03/05 17:35:31
It should fall into JSObject at 1703 which is the
|
| - const char* tag = objects_tags_.GetTag(object); |
| - const char* name = collection_->names()->GetName( |
| - GetConstructorName(JSObject::cast(object))); |
| - if (tag != NULL) { |
| - name = collection_->names()->GetFormatted("%s / %s", name, tag); |
| - } |
| - return AddEntry(object, |
| - HeapEntry::kObject, |
| - name, |
| - children_count, |
| - retainers_count); |
| } else if (object->IsJSFunction()) { |
| JSFunction* func = JSFunction::cast(object); |
| SharedFunctionInfo* shared = func->shared(); |
| @@ -1703,8 +1691,7 @@ HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object, |
| } else if (object->IsJSObject()) { |
| return AddEntry(object, |
| HeapEntry::kObject, |
| - collection_->names()->GetName( |
| - GetConstructorName(JSObject::cast(object))), |
| + "", |
| children_count, |
| retainers_count); |
| } else if (object->IsString()) { |
| @@ -2349,6 +2336,32 @@ bool V8HeapExplorer::IterateAndExtractReferences( |
| } |
| +bool V8HeapExplorer::IterateAndSetObjectNames(SnapshotFillerInterface* filler) { |
| + HeapIterator iterator(HeapIterator::kFilterUnreachable); |
| + filler_ = filler; |
| + for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) { |
| + SetObjectName(obj); |
| + } |
| + return true; |
| +} |
| + |
| + |
| +void V8HeapExplorer::SetObjectName(HeapObject* object) { |
| + if (!object->IsJSObject() || object->IsJSRegExp() || object->IsJSFunction()) { |
| + return; |
| + } |
| + const char* name = collection_->names()->GetName( |
| + GetConstructorName(JSObject::cast(object))); |
| + if (object->IsJSGlobalObject()) { |
| + const char* tag = objects_tags_.GetTag(object); |
| + if (tag != NULL) { |
| + name = collection_->names()->GetFormatted("%s / %s", name, tag); |
| + } |
| + } |
| + GetEntry(object)->set_name(name); |
| +} |
| + |
| + |
| void V8HeapExplorer::SetClosureReference(HeapObject* parent_obj, |
| HeapEntry* parent_entry, |
| String* reference_name, |
| @@ -2907,15 +2920,6 @@ void NativeObjectsExplorer::VisitSubtreeWrapper(Object** p, uint16_t class_id) { |
| } |
| -HeapSnapshotGenerator::HeapSnapshotGenerator(HeapSnapshot* snapshot, |
| - v8::ActivityControl* control) |
| - : snapshot_(snapshot), |
| - control_(control), |
| - v8_heap_explorer_(snapshot_, this), |
| - dom_explorer_(snapshot_, this) { |
| -} |
| - |
| - |
| class SnapshotCounter : public SnapshotFillerInterface { |
| public: |
| explicit SnapshotCounter(HeapEntriesMap* entries) : entries_(entries) { } |
| @@ -3040,6 +3044,15 @@ class SnapshotFiller : public SnapshotFillerInterface { |
| }; |
| +HeapSnapshotGenerator::HeapSnapshotGenerator(HeapSnapshot* snapshot, |
| + v8::ActivityControl* control) |
| + : snapshot_(snapshot), |
| + control_(control), |
| + v8_heap_explorer_(snapshot_, this), |
| + dom_explorer_(snapshot_, this) { |
| +} |
| + |
| + |
| bool HeapSnapshotGenerator::GenerateSnapshot() { |
| v8_heap_explorer_.TagGlobalObjects(); |
| @@ -3084,10 +3097,12 @@ bool HeapSnapshotGenerator::GenerateSnapshot() { |
| debug_heap->Verify(); |
| #endif |
| - // Allocate and fill entries in the snapshot, allocate references. |
| + // Allocate memory for entries and references. |
| snapshot_->AllocateEntries(entries_.entries_count(), |
| entries_.total_children_count(), |
| entries_.total_retainers_count()); |
| + |
| + // Allocate heap objects to entries hash map. |
| entries_.AllocateEntries(); |
| // Pass 2. Fill references. |
| @@ -3132,17 +3147,22 @@ void HeapSnapshotGenerator::SetProgressTotal(int iterations_count) { |
| bool HeapSnapshotGenerator::CountEntriesAndReferences() { |
| SnapshotCounter counter(&entries_); |
| v8_heap_explorer_.AddRootEntries(&counter); |
| - return |
| - v8_heap_explorer_.IterateAndExtractReferences(&counter) && |
| - dom_explorer_.IterateAndExtractReferences(&counter); |
| + return v8_heap_explorer_.IterateAndExtractReferences(&counter) |
| + && dom_explorer_.IterateAndExtractReferences(&counter); |
| } |
| bool HeapSnapshotGenerator::FillReferences() { |
| SnapshotFiller filler(snapshot_, &entries_); |
| - return |
| - v8_heap_explorer_.IterateAndExtractReferences(&filler) && |
| - dom_explorer_.IterateAndExtractReferences(&filler); |
| + // IterateAndExtractReferences cannot set object names because |
| + // it makes call to JSObject::LocalLookupRealNamedProperty which |
| + // in turn may relocate objects in property maps thus changing the heap |
| + // layout and affecting retainer counts. This is not acceptable because |
| + // number of retainers must not change between count and fill passes. |
| + // To avoid this there's a separate postpass that set object names. |
| + return v8_heap_explorer_.IterateAndExtractReferences(&filler) |
| + && dom_explorer_.IterateAndExtractReferences(&filler) |
| + && v8_heap_explorer_.IterateAndSetObjectNames(&filler); |
|
mnaganov (inactive)
2012/03/05 16:21:58
As we have discussed offline, please split Generat
alexeif
2012/03/05 17:35:31
I checked the AssertNoAllocation class and it does
|
| } |
| @@ -3198,26 +3218,28 @@ bool HeapSnapshotGenerator::BuildDominatorTree( |
| for (int i = 0; i < root_index; ++i) (*dominators)[i] = kNoDominator; |
| (*dominators)[root_index] = root_index; |
| - // The painted flag is used to mark entries that need to be recalculated |
| - // because of dominators change among their retainers. |
| - for (int i = 0; i < entries_length; ++i) entries[i]->clear_paint(); |
| - |
| + // The affected array is used to mark entries which dominators |
| + // have to be racalculated because of changes in their retainers. |
| + ScopedVector<bool> affected(entries_length); |
| + for (int i = 0; i < affected.length(); ++i) affected[i] = false; |
| // Mark the root direct children as affected. |
| Vector<HeapGraphEdge> children = entries[root_index]->children(); |
| - for (int i = 0; i < children.length(); ++i) children[i].to()->paint(); |
| + for (int i = 0; i < children.length(); ++i) { |
| + affected[children[i].to()->ordered_index()] = true; |
| + } |
| bool changed = true; |
| while (changed) { |
| changed = false; |
| + if (!ProgressReport(true)) return false; |
| for (int i = root_index - 1; i >= 0; --i) { |
| + if (!affected[i]) continue; |
| + affected[i] = false; |
| // If dominator of the entry has already been set to root, |
| // then it can't propagate any further. |
| if ((*dominators)[i] == root_index) continue; |
| - HeapEntry* entry = entries[i]; |
| - if (!entry->painted()) continue; |
| - entry->clear_paint(); |
| int new_idom_index = kNoDominator; |
| - Vector<HeapGraphEdge*> rets = entry->retainers(); |
| + Vector<HeapGraphEdge*> rets = entries[i]->retainers(); |
| for (int j = 0; j < rets.length(); ++j) { |
| if (rets[j]->type() == HeapGraphEdge::kShortcut) continue; |
| int ret_index = rets[j]->From()->ordered_index(); |
| @@ -3235,7 +3257,9 @@ bool HeapSnapshotGenerator::BuildDominatorTree( |
| (*dominators)[i] = new_idom_index; |
| changed = true; |
| Vector<HeapGraphEdge> children = entries[i]->children(); |
| - for (int j = 0; j < children.length(); ++j) children[j].to()->paint(); |
| + for (int j = 0; j < children.length(); ++j) { |
| + affected[children[j].to()->ordered_index()] = true; |
| + } |
| } |
| } |
| } |