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 3253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3264 if (!has_new_edges) { | 3264 if (!has_new_edges) { |
3265 entry->set_ordered_index(current_entry); | 3265 entry->set_ordered_index(current_entry); |
3266 (*entries)[current_entry++] = entry; | 3266 (*entries)[current_entry++] = entry; |
3267 nodes_to_visit.RemoveLast(); | 3267 nodes_to_visit.RemoveLast(); |
3268 } | 3268 } |
3269 } | 3269 } |
3270 ASSERT_EQ(current_entry, entries->length()); | 3270 ASSERT_EQ(current_entry, entries->length()); |
3271 } | 3271 } |
3272 | 3272 |
3273 | 3273 |
3274 static int Intersect(int i1, int i2, const Vector<HeapEntry*>& dominators) { | 3274 static int Intersect(int i1, int i2, const Vector<int>& dominators) { |
3275 int finger1 = i1, finger2 = i2; | 3275 int finger1 = i1, finger2 = i2; |
3276 while (finger1 != finger2) { | 3276 while (finger1 != finger2) { |
3277 while (finger1 < finger2) finger1 = dominators[finger1]->ordered_index(); | 3277 while (finger1 < finger2) finger1 = dominators[finger1]; |
3278 while (finger2 < finger1) finger2 = dominators[finger2]->ordered_index(); | 3278 while (finger2 < finger1) finger2 = dominators[finger2]; |
3279 } | 3279 } |
3280 return finger1; | 3280 return finger1; |
3281 } | 3281 } |
3282 | 3282 |
| 3283 |
3283 // The algorithm is based on the article: | 3284 // The algorithm is based on the article: |
3284 // K. Cooper, T. Harvey and K. Kennedy "A Simple, Fast Dominance Algorithm" | 3285 // K. Cooper, T. Harvey and K. Kennedy "A Simple, Fast Dominance Algorithm" |
3285 // Softw. Pract. Exper. 4 (2001), pp. 1-10. | 3286 // Softw. Pract. Exper. 4 (2001), pp. 1-10. |
3286 bool HeapSnapshotGenerator::BuildDominatorTree( | 3287 bool HeapSnapshotGenerator::BuildDominatorTree( |
3287 const Vector<HeapEntry*>& entries, | 3288 const Vector<HeapEntry*>& entries, |
3288 Vector<HeapEntry*>* dominators) { | 3289 Vector<int>* dominators) { |
3289 if (entries.length() == 0) return true; | 3290 if (entries.length() == 0) return true; |
3290 const int entries_length = entries.length(), root_index = entries_length - 1; | 3291 const int entries_length = entries.length(), root_index = entries_length - 1; |
3291 for (int i = 0; i < root_index; ++i) (*dominators)[i] = NULL; | 3292 static const int kNoDominator = -1; |
3292 (*dominators)[root_index] = entries[root_index]; | 3293 for (int i = 0; i < root_index; ++i) (*dominators)[i] = kNoDominator; |
| 3294 (*dominators)[root_index] = root_index; |
| 3295 |
| 3296 // We use time_stamps array to stamp entries with the iteration number |
| 3297 // when the dominance for the entry has been updated. |
| 3298 ScopedVector<int> time_stamps(entries_length); |
| 3299 for (int i = 0; i < entries_length; ++i) time_stamps[i] = -1; |
| 3300 Vector<HeapGraphEdge> children = entries[root_index]->children(); |
| 3301 for (int i = 0; i < children.length(); ++i) { |
| 3302 // Mark the root direct children as affected on iteration zero. |
| 3303 time_stamps[children[i].to()->ordered_index()] = 0; |
| 3304 } |
| 3305 |
3293 int changed = 1; | 3306 int changed = 1; |
| 3307 int iteration = 0; |
3294 const int base_progress_counter = progress_counter_; | 3308 const int base_progress_counter = progress_counter_; |
3295 while (changed != 0) { | 3309 while (changed != 0) { |
| 3310 ++iteration; |
3296 changed = 0; | 3311 changed = 0; |
3297 for (int i = root_index - 1; i >= 0; --i) { | 3312 for (int i = root_index - 1; i >= 0; --i) { |
3298 HeapEntry* new_idom = NULL; | 3313 // If dominator of the entry has already been set to root, |
| 3314 // then it can't propagate any further. |
| 3315 if ((*dominators)[i] == root_index) continue; |
| 3316 // If no retainers of the entry had been updated on current |
| 3317 // or previous iteration, then this entry is not affected. |
| 3318 if (time_stamps[i] < iteration - 1) continue; |
| 3319 int new_idom_index = kNoDominator; |
3299 Vector<HeapGraphEdge*> rets = entries[i]->retainers(); | 3320 Vector<HeapGraphEdge*> rets = entries[i]->retainers(); |
3300 int j = 0; | 3321 for (int j = 0; j < rets.length(); ++j) { |
3301 for (; j < rets.length(); ++j) { | |
3302 if (rets[j]->type() == HeapGraphEdge::kShortcut) continue; | 3322 if (rets[j]->type() == HeapGraphEdge::kShortcut) continue; |
3303 HeapEntry* ret = rets[j]->From(); | 3323 int ret_index = rets[j]->From()->ordered_index(); |
3304 if (dominators->at(ret->ordered_index()) != NULL) { | 3324 if (dominators->at(ret_index) != kNoDominator) { |
3305 new_idom = ret; | 3325 new_idom_index = new_idom_index == kNoDominator |
3306 break; | 3326 ? ret_index |
| 3327 : Intersect(ret_index, new_idom_index, *dominators); |
| 3328 // If idom has already reached the root, it doesn't make sense |
| 3329 // to check other retainers. |
| 3330 if (new_idom_index == root_index) break; |
3307 } | 3331 } |
3308 } | 3332 } |
3309 for (++j; j < rets.length(); ++j) { | 3333 if (new_idom_index != kNoDominator |
3310 if (rets[j]->type() == HeapGraphEdge::kShortcut) continue; | 3334 && dominators->at(i) != new_idom_index) { |
3311 HeapEntry* ret = rets[j]->From(); | 3335 (*dominators)[i] = new_idom_index; |
3312 if (dominators->at(ret->ordered_index()) != NULL) { | 3336 ++changed; |
3313 new_idom = entries[Intersect(ret->ordered_index(), | 3337 Vector<HeapGraphEdge> children = entries[i]->children(); |
3314 new_idom->ordered_index(), | 3338 for (int j = 0; j < children.length(); ++j) { |
3315 *dominators)]; | 3339 time_stamps[children[j].to()->ordered_index()] = iteration; |
3316 } | 3340 } |
3317 } | 3341 } |
3318 if (new_idom != NULL && dominators->at(i) != new_idom) { | |
3319 (*dominators)[i] = new_idom; | |
3320 ++changed; | |
3321 } | |
3322 } | 3342 } |
3323 int remaining = entries_length - changed; | 3343 int remaining = entries_length - changed; |
3324 if (remaining < 0) remaining = 0; | 3344 ASSERT(remaining >= 0); |
3325 progress_counter_ = base_progress_counter + remaining; | 3345 progress_counter_ = base_progress_counter + remaining; |
3326 if (!ProgressReport(true)) return false; | 3346 if (!ProgressReport(true)) return false; |
3327 } | 3347 } |
3328 return true; | 3348 return true; |
3329 } | 3349 } |
3330 | 3350 |
3331 | 3351 |
3332 bool HeapSnapshotGenerator::SetEntriesDominators() { | 3352 bool HeapSnapshotGenerator::SetEntriesDominators() { |
3333 // This array is used for maintaining reverse postorder of nodes. | 3353 // This array is used for maintaining reverse postorder of nodes. |
3334 ScopedVector<HeapEntry*> ordered_entries(snapshot_->entries()->length()); | 3354 ScopedVector<HeapEntry*> ordered_entries(snapshot_->entries()->length()); |
3335 FillReversePostorderIndexes(&ordered_entries); | 3355 FillReversePostorderIndexes(&ordered_entries); |
3336 ScopedVector<HeapEntry*> dominators(ordered_entries.length()); | 3356 ScopedVector<int> dominators(ordered_entries.length()); |
3337 if (!BuildDominatorTree(ordered_entries, &dominators)) return false; | 3357 if (!BuildDominatorTree(ordered_entries, &dominators)) return false; |
3338 for (int i = 0; i < ordered_entries.length(); ++i) { | 3358 for (int i = 0; i < ordered_entries.length(); ++i) { |
3339 ASSERT(dominators[i] != NULL); | 3359 ASSERT(dominators[i] >= 0); |
3340 ordered_entries[i]->set_dominator(dominators[i]); | 3360 ordered_entries[i]->set_dominator(ordered_entries[dominators[i]]); |
3341 } | 3361 } |
3342 return true; | 3362 return true; |
3343 } | 3363 } |
3344 | 3364 |
3345 | 3365 |
3346 bool HeapSnapshotGenerator::ApproximateRetainedSizes() { | 3366 bool HeapSnapshotGenerator::ApproximateRetainedSizes() { |
3347 // As for the dominators tree we only know parent nodes, not | 3367 // As for the dominators tree we only know parent nodes, not |
3348 // children, to sum up total sizes we "bubble" node's self size | 3368 // children, to sum up total sizes we "bubble" node's self size |
3349 // adding it to all of its parents. | 3369 // adding it to all of its parents. |
3350 for (int i = 0; i < snapshot_->entries()->length(); ++i) { | 3370 for (int i = 0; i < snapshot_->entries()->length(); ++i) { |
(...skipping 435 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3786 | 3806 |
3787 | 3807 |
3788 void HeapSnapshotJSONSerializer::SortHashMap( | 3808 void HeapSnapshotJSONSerializer::SortHashMap( |
3789 HashMap* map, List<HashMap::Entry*>* sorted_entries) { | 3809 HashMap* map, List<HashMap::Entry*>* sorted_entries) { |
3790 for (HashMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) | 3810 for (HashMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) |
3791 sorted_entries->Add(p); | 3811 sorted_entries->Add(p); |
3792 sorted_entries->Sort(SortUsingEntryValue); | 3812 sorted_entries->Sort(SortUsingEntryValue); |
3793 } | 3813 } |
3794 | 3814 |
3795 } } // namespace v8::internal | 3815 } } // namespace v8::internal |
OLD | NEW |