Index: src/profile-generator.cc |
diff --git a/src/profile-generator.cc b/src/profile-generator.cc |
index 2c8cb14f78af34949f0d575c663606d1367841be..1ba68a166719c86b403e14546a0af6e265d6b784 100644 |
--- a/src/profile-generator.cc |
+++ b/src/profile-generator.cc |
@@ -3271,57 +3271,77 @@ void HeapSnapshotGenerator::FillReversePostorderIndexes( |
} |
-static int Intersect(int i1, int i2, const Vector<HeapEntry*>& dominators) { |
+static int Intersect(int i1, int i2, const Vector<int>& dominators) { |
int finger1 = i1, finger2 = i2; |
while (finger1 != finger2) { |
- while (finger1 < finger2) finger1 = dominators[finger1]->ordered_index(); |
- while (finger2 < finger1) finger2 = dominators[finger2]->ordered_index(); |
+ while (finger1 < finger2) finger1 = dominators[finger1]; |
+ while (finger2 < finger1) finger2 = dominators[finger2]; |
} |
return finger1; |
} |
+ |
// The algorithm is based on the article: |
// K. Cooper, T. Harvey and K. Kennedy "A Simple, Fast Dominance Algorithm" |
// Softw. Pract. Exper. 4 (2001), pp. 1-10. |
bool HeapSnapshotGenerator::BuildDominatorTree( |
const Vector<HeapEntry*>& entries, |
- Vector<HeapEntry*>* dominators) { |
+ Vector<int>* dominators) { |
if (entries.length() == 0) return true; |
const int entries_length = entries.length(), root_index = entries_length - 1; |
- for (int i = 0; i < root_index; ++i) (*dominators)[i] = NULL; |
- (*dominators)[root_index] = entries[root_index]; |
+ static const int kNoDominator = -1; |
+ for (int i = 0; i < root_index; ++i) (*dominators)[i] = kNoDominator; |
+ (*dominators)[root_index] = root_index; |
+ |
+ // We use time_stamps array to stamp entries with the iteration number |
+ // when the dominance for the entry has been updated. |
+ ScopedVector<int> time_stamps(entries_length); |
+ for (int i = 0; i < entries_length; ++i) time_stamps[i] = -1; |
+ Vector<HeapGraphEdge> children = entries[root_index]->children(); |
+ for (int i = 0; i < children.length(); ++i) { |
+ // Mark the root direct children as affected on iteration zero. |
+ time_stamps[children[i].to()->ordered_index()] = 0; |
+ } |
+ |
int changed = 1; |
+ int iteration = 0; |
const int base_progress_counter = progress_counter_; |
while (changed != 0) { |
+ ++iteration; |
changed = 0; |
for (int i = root_index - 1; i >= 0; --i) { |
- HeapEntry* new_idom = NULL; |
+ // If dominator of the entry has already been set to root, |
+ // then it can't propagate any further. |
+ if ((*dominators)[i] == root_index) continue; |
+ // If no retainers of the entry had been updated on current |
+ // or previous iteration, then this entry is not affected. |
+ if (time_stamps[i] < iteration - 1) continue; |
+ int new_idom_index = kNoDominator; |
Vector<HeapGraphEdge*> rets = entries[i]->retainers(); |
- int j = 0; |
- for (; j < rets.length(); ++j) { |
+ for (int j = 0; j < rets.length(); ++j) { |
if (rets[j]->type() == HeapGraphEdge::kShortcut) continue; |
- HeapEntry* ret = rets[j]->From(); |
- if (dominators->at(ret->ordered_index()) != NULL) { |
- new_idom = ret; |
- break; |
+ int ret_index = rets[j]->From()->ordered_index(); |
+ if (dominators->at(ret_index) != kNoDominator) { |
+ new_idom_index = new_idom_index == kNoDominator |
+ ? ret_index |
+ : Intersect(ret_index, new_idom_index, *dominators); |
+ // If idom has already reached the root, it doesn't make sense |
+ // to check other retainers. |
+ if (new_idom_index == root_index) break; |
} |
} |
- for (++j; j < rets.length(); ++j) { |
- if (rets[j]->type() == HeapGraphEdge::kShortcut) continue; |
- HeapEntry* ret = rets[j]->From(); |
- if (dominators->at(ret->ordered_index()) != NULL) { |
- new_idom = entries[Intersect(ret->ordered_index(), |
- new_idom->ordered_index(), |
- *dominators)]; |
- } |
- } |
- if (new_idom != NULL && dominators->at(i) != new_idom) { |
- (*dominators)[i] = new_idom; |
+ if (new_idom_index != kNoDominator |
+ && dominators->at(i) != new_idom_index) { |
+ (*dominators)[i] = new_idom_index; |
++changed; |
+ Vector<HeapGraphEdge> children = entries[i]->children(); |
+ for (int j = 0; j < children.length(); ++j) { |
+ time_stamps[children[j].to()->ordered_index()] = iteration; |
+ } |
} |
} |
int remaining = entries_length - changed; |
- if (remaining < 0) remaining = 0; |
+ ASSERT(remaining >= 0); |
progress_counter_ = base_progress_counter + remaining; |
if (!ProgressReport(true)) return false; |
} |
@@ -3333,11 +3353,11 @@ bool HeapSnapshotGenerator::SetEntriesDominators() { |
// This array is used for maintaining reverse postorder of nodes. |
ScopedVector<HeapEntry*> ordered_entries(snapshot_->entries()->length()); |
FillReversePostorderIndexes(&ordered_entries); |
- ScopedVector<HeapEntry*> dominators(ordered_entries.length()); |
+ ScopedVector<int> dominators(ordered_entries.length()); |
if (!BuildDominatorTree(ordered_entries, &dominators)) return false; |
for (int i = 0; i < ordered_entries.length(); ++i) { |
- ASSERT(dominators[i] != NULL); |
- ordered_entries[i]->set_dominator(dominators[i]); |
+ ASSERT(dominators[i] >= 0); |
+ ordered_entries[i]->set_dominator(ordered_entries[dominators[i]]); |
} |
return true; |
} |