OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 974 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
985 } id_adaptor = {id}; | 985 } id_adaptor = {id}; |
986 id_ = id_adaptor.stored_id; | 986 id_ = id_adaptor.stored_id; |
987 } | 987 } |
988 | 988 |
989 | 989 |
990 void HeapEntry::SetNamedReference(HeapGraphEdge::Type type, | 990 void HeapEntry::SetNamedReference(HeapGraphEdge::Type type, |
991 int child_index, | 991 int child_index, |
992 const char* name, | 992 const char* name, |
993 HeapEntry* entry, | 993 HeapEntry* entry, |
994 int retainer_index) { | 994 int retainer_index) { |
995 children_arr()[child_index].Init(child_index, type, name, entry); | 995 children()[child_index].Init(child_index, type, name, entry); |
996 entry->retainers_arr()[retainer_index] = children_arr() + child_index; | 996 entry->retainers()[retainer_index] = children_arr() + child_index; |
997 } | 997 } |
998 | 998 |
999 | 999 |
1000 void HeapEntry::SetIndexedReference(HeapGraphEdge::Type type, | 1000 void HeapEntry::SetIndexedReference(HeapGraphEdge::Type type, |
1001 int child_index, | 1001 int child_index, |
1002 int index, | 1002 int index, |
1003 HeapEntry* entry, | 1003 HeapEntry* entry, |
1004 int retainer_index) { | 1004 int retainer_index) { |
1005 children_arr()[child_index].Init(child_index, type, index, entry); | 1005 children()[child_index].Init(child_index, type, index, entry); |
1006 entry->retainers_arr()[retainer_index] = children_arr() + child_index; | 1006 entry->retainers()[retainer_index] = children_arr() + child_index; |
1007 } | 1007 } |
1008 | 1008 |
1009 | 1009 |
1010 void HeapEntry::SetUnidirElementReference( | 1010 void HeapEntry::SetUnidirElementReference( |
1011 int child_index, int index, HeapEntry* entry) { | 1011 int child_index, int index, HeapEntry* entry) { |
1012 children_arr()[child_index].Init(child_index, index, entry); | 1012 children()[child_index].Init(child_index, index, entry); |
1013 } | 1013 } |
1014 | 1014 |
1015 | 1015 |
1016 Handle<HeapObject> HeapEntry::GetHeapObject() { | 1016 Handle<HeapObject> HeapEntry::GetHeapObject() { |
1017 return snapshot_->collection()->FindHeapObjectById(id()); | 1017 return snapshot_->collection()->FindHeapObjectById(id()); |
1018 } | 1018 } |
1019 | 1019 |
1020 | 1020 |
1021 void HeapEntry::Print( | 1021 void HeapEntry::Print( |
1022 const char* prefix, const char* edge_name, int max_depth, int indent) { | 1022 const char* prefix, const char* edge_name, int max_depth, int indent) { |
(...skipping 641 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1664 if (object == kInternalRootObject) { | 1664 if (object == kInternalRootObject) { |
1665 ASSERT(retainers_count == 0); | 1665 ASSERT(retainers_count == 0); |
1666 return snapshot_->AddRootEntry(children_count); | 1666 return snapshot_->AddRootEntry(children_count); |
1667 } else if (object == kGcRootsObject) { | 1667 } else if (object == kGcRootsObject) { |
1668 return snapshot_->AddGcRootsEntry(children_count, retainers_count); | 1668 return snapshot_->AddGcRootsEntry(children_count, retainers_count); |
1669 } else if (object >= kFirstGcSubrootObject && object < kLastGcSubrootObject) { | 1669 } else if (object >= kFirstGcSubrootObject && object < kLastGcSubrootObject) { |
1670 return snapshot_->AddGcSubrootEntry( | 1670 return snapshot_->AddGcSubrootEntry( |
1671 GetGcSubrootOrder(object), | 1671 GetGcSubrootOrder(object), |
1672 children_count, | 1672 children_count, |
1673 retainers_count); | 1673 retainers_count); |
1674 } 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
| |
1675 const char* tag = objects_tags_.GetTag(object); | |
1676 const char* name = collection_->names()->GetName( | |
1677 GetConstructorName(JSObject::cast(object))); | |
1678 if (tag != NULL) { | |
1679 name = collection_->names()->GetFormatted("%s / %s", name, tag); | |
1680 } | |
1681 return AddEntry(object, | |
1682 HeapEntry::kObject, | |
1683 name, | |
1684 children_count, | |
1685 retainers_count); | |
1686 } else if (object->IsJSFunction()) { | 1674 } else if (object->IsJSFunction()) { |
1687 JSFunction* func = JSFunction::cast(object); | 1675 JSFunction* func = JSFunction::cast(object); |
1688 SharedFunctionInfo* shared = func->shared(); | 1676 SharedFunctionInfo* shared = func->shared(); |
1689 const char* name = shared->bound() ? "native_bind" : | 1677 const char* name = shared->bound() ? "native_bind" : |
1690 collection_->names()->GetName(String::cast(shared->name())); | 1678 collection_->names()->GetName(String::cast(shared->name())); |
1691 return AddEntry(object, | 1679 return AddEntry(object, |
1692 HeapEntry::kClosure, | 1680 HeapEntry::kClosure, |
1693 name, | 1681 name, |
1694 children_count, | 1682 children_count, |
1695 retainers_count); | 1683 retainers_count); |
1696 } else if (object->IsJSRegExp()) { | 1684 } else if (object->IsJSRegExp()) { |
1697 JSRegExp* re = JSRegExp::cast(object); | 1685 JSRegExp* re = JSRegExp::cast(object); |
1698 return AddEntry(object, | 1686 return AddEntry(object, |
1699 HeapEntry::kRegExp, | 1687 HeapEntry::kRegExp, |
1700 collection_->names()->GetName(re->Pattern()), | 1688 collection_->names()->GetName(re->Pattern()), |
1701 children_count, | 1689 children_count, |
1702 retainers_count); | 1690 retainers_count); |
1703 } else if (object->IsJSObject()) { | 1691 } else if (object->IsJSObject()) { |
1704 return AddEntry(object, | 1692 return AddEntry(object, |
1705 HeapEntry::kObject, | 1693 HeapEntry::kObject, |
1706 collection_->names()->GetName( | 1694 "", |
1707 GetConstructorName(JSObject::cast(object))), | |
1708 children_count, | 1695 children_count, |
1709 retainers_count); | 1696 retainers_count); |
1710 } else if (object->IsString()) { | 1697 } else if (object->IsString()) { |
1711 return AddEntry(object, | 1698 return AddEntry(object, |
1712 HeapEntry::kString, | 1699 HeapEntry::kString, |
1713 collection_->names()->GetName(String::cast(object)), | 1700 collection_->names()->GetName(String::cast(object)), |
1714 children_count, | 1701 children_count, |
1715 retainers_count); | 1702 retainers_count); |
1716 } else if (object->IsCode()) { | 1703 } else if (object->IsCode()) { |
1717 return AddEntry(object, | 1704 return AddEntry(object, |
(...skipping 624 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2342 RootsReferencesExtractor extractor; | 2329 RootsReferencesExtractor extractor; |
2343 heap_->IterateRoots(&extractor, VISIT_ONLY_STRONG); | 2330 heap_->IterateRoots(&extractor, VISIT_ONLY_STRONG); |
2344 extractor.SetCollectingAllReferences(); | 2331 extractor.SetCollectingAllReferences(); |
2345 heap_->IterateRoots(&extractor, VISIT_ALL); | 2332 heap_->IterateRoots(&extractor, VISIT_ALL); |
2346 extractor.FillReferences(this); | 2333 extractor.FillReferences(this); |
2347 filler_ = NULL; | 2334 filler_ = NULL; |
2348 return progress_->ProgressReport(false); | 2335 return progress_->ProgressReport(false); |
2349 } | 2336 } |
2350 | 2337 |
2351 | 2338 |
2339 bool V8HeapExplorer::IterateAndSetObjectNames(SnapshotFillerInterface* filler) { | |
2340 HeapIterator iterator(HeapIterator::kFilterUnreachable); | |
2341 filler_ = filler; | |
2342 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) { | |
2343 SetObjectName(obj); | |
2344 } | |
2345 return true; | |
2346 } | |
2347 | |
2348 | |
2349 void V8HeapExplorer::SetObjectName(HeapObject* object) { | |
2350 if (!object->IsJSObject() || object->IsJSRegExp() || object->IsJSFunction()) { | |
2351 return; | |
2352 } | |
2353 const char* name = collection_->names()->GetName( | |
2354 GetConstructorName(JSObject::cast(object))); | |
2355 if (object->IsJSGlobalObject()) { | |
2356 const char* tag = objects_tags_.GetTag(object); | |
2357 if (tag != NULL) { | |
2358 name = collection_->names()->GetFormatted("%s / %s", name, tag); | |
2359 } | |
2360 } | |
2361 GetEntry(object)->set_name(name); | |
2362 } | |
2363 | |
2364 | |
2352 void V8HeapExplorer::SetClosureReference(HeapObject* parent_obj, | 2365 void V8HeapExplorer::SetClosureReference(HeapObject* parent_obj, |
2353 HeapEntry* parent_entry, | 2366 HeapEntry* parent_entry, |
2354 String* reference_name, | 2367 String* reference_name, |
2355 Object* child_obj) { | 2368 Object* child_obj) { |
2356 HeapEntry* child_entry = GetEntry(child_obj); | 2369 HeapEntry* child_entry = GetEntry(child_obj); |
2357 if (child_entry != NULL) { | 2370 if (child_entry != NULL) { |
2358 filler_->SetNamedReference(HeapGraphEdge::kContextVariable, | 2371 filler_->SetNamedReference(HeapGraphEdge::kContextVariable, |
2359 parent_obj, | 2372 parent_obj, |
2360 parent_entry, | 2373 parent_entry, |
2361 collection_->names()->GetName(reference_name), | 2374 collection_->names()->GetName(reference_name), |
(...skipping 538 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2900 void NativeObjectsExplorer::VisitSubtreeWrapper(Object** p, uint16_t class_id) { | 2913 void NativeObjectsExplorer::VisitSubtreeWrapper(Object** p, uint16_t class_id) { |
2901 if (in_groups_.Contains(*p)) return; | 2914 if (in_groups_.Contains(*p)) return; |
2902 Isolate* isolate = Isolate::Current(); | 2915 Isolate* isolate = Isolate::Current(); |
2903 v8::RetainedObjectInfo* info = | 2916 v8::RetainedObjectInfo* info = |
2904 isolate->heap_profiler()->ExecuteWrapperClassCallback(class_id, p); | 2917 isolate->heap_profiler()->ExecuteWrapperClassCallback(class_id, p); |
2905 if (info == NULL) return; | 2918 if (info == NULL) return; |
2906 GetListMaybeDisposeInfo(info)->Add(HeapObject::cast(*p)); | 2919 GetListMaybeDisposeInfo(info)->Add(HeapObject::cast(*p)); |
2907 } | 2920 } |
2908 | 2921 |
2909 | 2922 |
2910 HeapSnapshotGenerator::HeapSnapshotGenerator(HeapSnapshot* snapshot, | |
2911 v8::ActivityControl* control) | |
2912 : snapshot_(snapshot), | |
2913 control_(control), | |
2914 v8_heap_explorer_(snapshot_, this), | |
2915 dom_explorer_(snapshot_, this) { | |
2916 } | |
2917 | |
2918 | |
2919 class SnapshotCounter : public SnapshotFillerInterface { | 2923 class SnapshotCounter : public SnapshotFillerInterface { |
2920 public: | 2924 public: |
2921 explicit SnapshotCounter(HeapEntriesMap* entries) : entries_(entries) { } | 2925 explicit SnapshotCounter(HeapEntriesMap* entries) : entries_(entries) { } |
2922 HeapEntry* AddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) { | 2926 HeapEntry* AddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) { |
2923 entries_->Pair(ptr, allocator, HeapEntriesMap::kHeapEntryPlaceholder); | 2927 entries_->Pair(ptr, allocator, HeapEntriesMap::kHeapEntryPlaceholder); |
2924 return HeapEntriesMap::kHeapEntryPlaceholder; | 2928 return HeapEntriesMap::kHeapEntryPlaceholder; |
2925 } | 2929 } |
2926 HeapEntry* FindEntry(HeapThing ptr) { | 2930 HeapEntry* FindEntry(HeapThing ptr) { |
2927 return entries_->Map(ptr); | 2931 return entries_->Map(ptr); |
2928 } | 2932 } |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3033 retainer_index); | 3037 retainer_index); |
3034 } | 3038 } |
3035 | 3039 |
3036 private: | 3040 private: |
3037 HeapSnapshot* snapshot_; | 3041 HeapSnapshot* snapshot_; |
3038 HeapSnapshotsCollection* collection_; | 3042 HeapSnapshotsCollection* collection_; |
3039 HeapEntriesMap* entries_; | 3043 HeapEntriesMap* entries_; |
3040 }; | 3044 }; |
3041 | 3045 |
3042 | 3046 |
3047 HeapSnapshotGenerator::HeapSnapshotGenerator(HeapSnapshot* snapshot, | |
3048 v8::ActivityControl* control) | |
3049 : snapshot_(snapshot), | |
3050 control_(control), | |
3051 v8_heap_explorer_(snapshot_, this), | |
3052 dom_explorer_(snapshot_, this) { | |
3053 } | |
3054 | |
3055 | |
3043 bool HeapSnapshotGenerator::GenerateSnapshot() { | 3056 bool HeapSnapshotGenerator::GenerateSnapshot() { |
3044 v8_heap_explorer_.TagGlobalObjects(); | 3057 v8_heap_explorer_.TagGlobalObjects(); |
3045 | 3058 |
3046 // TODO(1562) Profiler assumes that any object that is in the heap after | 3059 // TODO(1562) Profiler assumes that any object that is in the heap after |
3047 // full GC is reachable from the root when computing dominators. | 3060 // full GC is reachable from the root when computing dominators. |
3048 // This is not true for weakly reachable objects. | 3061 // This is not true for weakly reachable objects. |
3049 // As a temporary solution we call GC twice. | 3062 // As a temporary solution we call GC twice. |
3050 Isolate::Current()->heap()->CollectAllGarbage( | 3063 Isolate::Current()->heap()->CollectAllGarbage( |
3051 Heap::kMakeHeapIterableMask, | 3064 Heap::kMakeHeapIterableMask, |
3052 "HeapSnapshotGenerator::GenerateSnapshot"); | 3065 "HeapSnapshotGenerator::GenerateSnapshot"); |
(...skipping 24 matching lines...) Expand all Loading... | |
3077 debug_heap->Verify(); | 3090 debug_heap->Verify(); |
3078 #endif | 3091 #endif |
3079 | 3092 |
3080 // Pass 1. Iterate heap contents to count entries and references. | 3093 // Pass 1. Iterate heap contents to count entries and references. |
3081 if (!CountEntriesAndReferences()) return false; | 3094 if (!CountEntriesAndReferences()) return false; |
3082 | 3095 |
3083 #ifdef DEBUG | 3096 #ifdef DEBUG |
3084 debug_heap->Verify(); | 3097 debug_heap->Verify(); |
3085 #endif | 3098 #endif |
3086 | 3099 |
3087 // Allocate and fill entries in the snapshot, allocate references. | 3100 // Allocate memory for entries and references. |
3088 snapshot_->AllocateEntries(entries_.entries_count(), | 3101 snapshot_->AllocateEntries(entries_.entries_count(), |
3089 entries_.total_children_count(), | 3102 entries_.total_children_count(), |
3090 entries_.total_retainers_count()); | 3103 entries_.total_retainers_count()); |
3104 | |
3105 // Allocate heap objects to entries hash map. | |
3091 entries_.AllocateEntries(); | 3106 entries_.AllocateEntries(); |
3092 | 3107 |
3093 // Pass 2. Fill references. | 3108 // Pass 2. Fill references. |
3094 if (!FillReferences()) return false; | 3109 if (!FillReferences()) return false; |
3095 | 3110 |
3096 if (!SetEntriesDominators()) return false; | 3111 if (!SetEntriesDominators()) return false; |
3097 if (!CalculateRetainedSizes()) return false; | 3112 if (!CalculateRetainedSizes()) return false; |
3098 | 3113 |
3099 progress_counter_ = progress_total_; | 3114 progress_counter_ = progress_total_; |
3100 if (!ProgressReport(true)) return false; | 3115 if (!ProgressReport(true)) return false; |
(...skipping 24 matching lines...) Expand all Loading... | |
3125 progress_total_ = ( | 3140 progress_total_ = ( |
3126 v8_heap_explorer_.EstimateObjectsCount(&iterator) + | 3141 v8_heap_explorer_.EstimateObjectsCount(&iterator) + |
3127 dom_explorer_.EstimateObjectsCount()) * iterations_count; | 3142 dom_explorer_.EstimateObjectsCount()) * iterations_count; |
3128 progress_counter_ = 0; | 3143 progress_counter_ = 0; |
3129 } | 3144 } |
3130 | 3145 |
3131 | 3146 |
3132 bool HeapSnapshotGenerator::CountEntriesAndReferences() { | 3147 bool HeapSnapshotGenerator::CountEntriesAndReferences() { |
3133 SnapshotCounter counter(&entries_); | 3148 SnapshotCounter counter(&entries_); |
3134 v8_heap_explorer_.AddRootEntries(&counter); | 3149 v8_heap_explorer_.AddRootEntries(&counter); |
3135 return | 3150 return v8_heap_explorer_.IterateAndExtractReferences(&counter) |
3136 v8_heap_explorer_.IterateAndExtractReferences(&counter) && | 3151 && dom_explorer_.IterateAndExtractReferences(&counter); |
3137 dom_explorer_.IterateAndExtractReferences(&counter); | |
3138 } | 3152 } |
3139 | 3153 |
3140 | 3154 |
3141 bool HeapSnapshotGenerator::FillReferences() { | 3155 bool HeapSnapshotGenerator::FillReferences() { |
3142 SnapshotFiller filler(snapshot_, &entries_); | 3156 SnapshotFiller filler(snapshot_, &entries_); |
3143 return | 3157 // IterateAndExtractReferences cannot set object names because |
3144 v8_heap_explorer_.IterateAndExtractReferences(&filler) && | 3158 // it makes call to JSObject::LocalLookupRealNamedProperty which |
3145 dom_explorer_.IterateAndExtractReferences(&filler); | 3159 // in turn may relocate objects in property maps thus changing the heap |
3160 // layout and affecting retainer counts. This is not acceptable because | |
3161 // number of retainers must not change between count and fill passes. | |
3162 // To avoid this there's a separate postpass that set object names. | |
3163 return v8_heap_explorer_.IterateAndExtractReferences(&filler) | |
3164 && dom_explorer_.IterateAndExtractReferences(&filler) | |
3165 && 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
| |
3146 } | 3166 } |
3147 | 3167 |
3148 | 3168 |
3149 void HeapSnapshotGenerator::FillReversePostorderIndexes( | 3169 void HeapSnapshotGenerator::FillReversePostorderIndexes( |
3150 Vector<HeapEntry*>* entries) { | 3170 Vector<HeapEntry*>* entries) { |
3151 snapshot_->ClearPaint(); | 3171 snapshot_->ClearPaint(); |
3152 int current_entry = 0; | 3172 int current_entry = 0; |
3153 List<HeapEntry*> nodes_to_visit; | 3173 List<HeapEntry*> nodes_to_visit; |
3154 nodes_to_visit.Add(snapshot_->root()); | 3174 nodes_to_visit.Add(snapshot_->root()); |
3155 snapshot_->root()->paint(); | 3175 snapshot_->root()->paint(); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3191 // Softw. Pract. Exper. 4 (2001), pp. 1-10. | 3211 // Softw. Pract. Exper. 4 (2001), pp. 1-10. |
3192 bool HeapSnapshotGenerator::BuildDominatorTree( | 3212 bool HeapSnapshotGenerator::BuildDominatorTree( |
3193 const Vector<HeapEntry*>& entries, | 3213 const Vector<HeapEntry*>& entries, |
3194 Vector<int>* dominators) { | 3214 Vector<int>* dominators) { |
3195 if (entries.length() == 0) return true; | 3215 if (entries.length() == 0) return true; |
3196 const int entries_length = entries.length(), root_index = entries_length - 1; | 3216 const int entries_length = entries.length(), root_index = entries_length - 1; |
3197 static const int kNoDominator = -1; | 3217 static const int kNoDominator = -1; |
3198 for (int i = 0; i < root_index; ++i) (*dominators)[i] = kNoDominator; | 3218 for (int i = 0; i < root_index; ++i) (*dominators)[i] = kNoDominator; |
3199 (*dominators)[root_index] = root_index; | 3219 (*dominators)[root_index] = root_index; |
3200 | 3220 |
3201 // The painted flag is used to mark entries that need to be recalculated | 3221 // The affected array is used to mark entries which dominators |
3202 // because of dominators change among their retainers. | 3222 // have to be racalculated because of changes in their retainers. |
3203 for (int i = 0; i < entries_length; ++i) entries[i]->clear_paint(); | 3223 ScopedVector<bool> affected(entries_length); |
3204 | 3224 for (int i = 0; i < affected.length(); ++i) affected[i] = false; |
3205 // Mark the root direct children as affected. | 3225 // Mark the root direct children as affected. |
3206 Vector<HeapGraphEdge> children = entries[root_index]->children(); | 3226 Vector<HeapGraphEdge> children = entries[root_index]->children(); |
3207 for (int i = 0; i < children.length(); ++i) children[i].to()->paint(); | 3227 for (int i = 0; i < children.length(); ++i) { |
3228 affected[children[i].to()->ordered_index()] = true; | |
3229 } | |
3208 | 3230 |
3209 bool changed = true; | 3231 bool changed = true; |
3210 while (changed) { | 3232 while (changed) { |
3211 changed = false; | 3233 changed = false; |
3234 if (!ProgressReport(true)) return false; | |
3212 for (int i = root_index - 1; i >= 0; --i) { | 3235 for (int i = root_index - 1; i >= 0; --i) { |
3236 if (!affected[i]) continue; | |
3237 affected[i] = false; | |
3213 // If dominator of the entry has already been set to root, | 3238 // If dominator of the entry has already been set to root, |
3214 // then it can't propagate any further. | 3239 // then it can't propagate any further. |
3215 if ((*dominators)[i] == root_index) continue; | 3240 if ((*dominators)[i] == root_index) continue; |
3216 HeapEntry* entry = entries[i]; | |
3217 if (!entry->painted()) continue; | |
3218 entry->clear_paint(); | |
3219 int new_idom_index = kNoDominator; | 3241 int new_idom_index = kNoDominator; |
3220 Vector<HeapGraphEdge*> rets = entry->retainers(); | 3242 Vector<HeapGraphEdge*> rets = entries[i]->retainers(); |
3221 for (int j = 0; j < rets.length(); ++j) { | 3243 for (int j = 0; j < rets.length(); ++j) { |
3222 if (rets[j]->type() == HeapGraphEdge::kShortcut) continue; | 3244 if (rets[j]->type() == HeapGraphEdge::kShortcut) continue; |
3223 int ret_index = rets[j]->From()->ordered_index(); | 3245 int ret_index = rets[j]->From()->ordered_index(); |
3224 if (dominators->at(ret_index) != kNoDominator) { | 3246 if (dominators->at(ret_index) != kNoDominator) { |
3225 new_idom_index = new_idom_index == kNoDominator | 3247 new_idom_index = new_idom_index == kNoDominator |
3226 ? ret_index | 3248 ? ret_index |
3227 : Intersect(ret_index, new_idom_index, *dominators); | 3249 : Intersect(ret_index, new_idom_index, *dominators); |
3228 // If idom has already reached the root, it doesn't make sense | 3250 // If idom has already reached the root, it doesn't make sense |
3229 // to check other retainers. | 3251 // to check other retainers. |
3230 if (new_idom_index == root_index) break; | 3252 if (new_idom_index == root_index) break; |
3231 } | 3253 } |
3232 } | 3254 } |
3233 if (new_idom_index != kNoDominator | 3255 if (new_idom_index != kNoDominator |
3234 && dominators->at(i) != new_idom_index) { | 3256 && dominators->at(i) != new_idom_index) { |
3235 (*dominators)[i] = new_idom_index; | 3257 (*dominators)[i] = new_idom_index; |
3236 changed = true; | 3258 changed = true; |
3237 Vector<HeapGraphEdge> children = entries[i]->children(); | 3259 Vector<HeapGraphEdge> children = entries[i]->children(); |
3238 for (int j = 0; j < children.length(); ++j) children[j].to()->paint(); | 3260 for (int j = 0; j < children.length(); ++j) { |
3261 affected[children[j].to()->ordered_index()] = true; | |
3262 } | |
3239 } | 3263 } |
3240 } | 3264 } |
3241 } | 3265 } |
3242 return true; | 3266 return true; |
3243 } | 3267 } |
3244 | 3268 |
3245 | 3269 |
3246 bool HeapSnapshotGenerator::SetEntriesDominators() { | 3270 bool HeapSnapshotGenerator::SetEntriesDominators() { |
3247 // This array is used for maintaining reverse postorder of nodes. | 3271 // This array is used for maintaining reverse postorder of nodes. |
3248 ScopedVector<HeapEntry*> ordered_entries(snapshot_->entries()->length()); | 3272 ScopedVector<HeapEntry*> ordered_entries(snapshot_->entries()->length()); |
(...skipping 449 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3698 | 3722 |
3699 | 3723 |
3700 void HeapSnapshotJSONSerializer::SortHashMap( | 3724 void HeapSnapshotJSONSerializer::SortHashMap( |
3701 HashMap* map, List<HashMap::Entry*>* sorted_entries) { | 3725 HashMap* map, List<HashMap::Entry*>* sorted_entries) { |
3702 for (HashMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) | 3726 for (HashMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) |
3703 sorted_entries->Add(p); | 3727 sorted_entries->Add(p); |
3704 sorted_entries->Sort(SortUsingEntryValue); | 3728 sorted_entries->Sort(SortUsingEntryValue); |
3705 } | 3729 } |
3706 | 3730 |
3707 } } // namespace v8::internal | 3731 } } // namespace v8::internal |
OLD | NEW |