OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 1364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1375 uint64_t id, | 1375 uint64_t id, |
1376 int size, | 1376 int size, |
1377 int children_count, | 1377 int children_count, |
1378 int retainers_count) { | 1378 int retainers_count) { |
1379 HeapEntry* entry = GetNextEntryToInit(); | 1379 HeapEntry* entry = GetNextEntryToInit(); |
1380 entry->Init(this, type, name, id, size, children_count, retainers_count); | 1380 entry->Init(this, type, name, id, size, children_count, retainers_count); |
1381 return entry; | 1381 return entry; |
1382 } | 1382 } |
1383 | 1383 |
1384 | 1384 |
1385 void HeapSnapshot::FillReversePostorderIndexes(Vector<HeapEntry*>* entries) { | |
1386 ClearPaint(); | |
1387 int current_entry = 0; | |
1388 List<HeapEntry*> nodes_to_visit; | |
1389 nodes_to_visit.Add(root()); | |
1390 root()->paint_reachable(); | |
1391 while (!nodes_to_visit.is_empty()) { | |
1392 HeapEntry* entry = nodes_to_visit.last(); | |
1393 Vector<HeapGraphEdge> children = entry->children(); | |
1394 bool has_new_edges = false; | |
1395 for (int i = 0; i < children.length(); ++i) { | |
1396 if (children[i].type() == HeapGraphEdge::kShortcut) continue; | |
1397 HeapEntry* child = children[i].to(); | |
1398 if (!child->painted_reachable()) { | |
1399 nodes_to_visit.Add(child); | |
1400 child->paint_reachable(); | |
1401 has_new_edges = true; | |
1402 } | |
1403 } | |
1404 if (!has_new_edges) { | |
1405 entry->set_ordered_index(current_entry); | |
1406 (*entries)[current_entry++] = entry; | |
1407 nodes_to_visit.RemoveLast(); | |
1408 } | |
1409 } | |
1410 entries->Truncate(current_entry); | |
1411 } | |
1412 | |
1413 | |
1414 static int Intersect(int i1, int i2, const Vector<HeapEntry*>& dominators) { | |
1415 int finger1 = i1, finger2 = i2; | |
1416 while (finger1 != finger2) { | |
1417 while (finger1 < finger2) finger1 = dominators[finger1]->ordered_index(); | |
1418 while (finger2 < finger1) finger2 = dominators[finger2]->ordered_index(); | |
1419 } | |
1420 return finger1; | |
1421 } | |
1422 | |
1423 // The algorithm is based on the article: | |
1424 // K. Cooper, T. Harvey and K. Kennedy "A Simple, Fast Dominance Algorithm" | |
1425 // Softw. Pract. Exper. 4 (2001), pp. 1–10. | |
1426 void HeapSnapshot::BuildDominatorTree(const Vector<HeapEntry*>& entries, | |
1427 Vector<HeapEntry*>* dominators) { | |
1428 if (entries.length() == 0) return; | |
1429 const int root_index = entries.length() - 1; | |
1430 for (int i = 0; i < root_index; ++i) (*dominators)[i] = NULL; | |
1431 (*dominators)[root_index] = entries[root_index]; | |
1432 bool changed = true; | |
1433 while (changed) { | |
1434 changed = false; | |
1435 for (int i = root_index - 1; i >= 0; --i) { | |
1436 HeapEntry* new_idom = NULL; | |
1437 Vector<HeapGraphEdge*> rets = entries[i]->retainers(); | |
1438 int j = 0; | |
1439 for (; j < rets.length(); ++j) { | |
1440 if (rets[j]->type() == HeapGraphEdge::kShortcut) continue; | |
1441 HeapEntry* ret = rets[j]->From(); | |
1442 if (dominators->at(ret->ordered_index()) != NULL) { | |
1443 new_idom = ret; | |
1444 break; | |
1445 } | |
1446 } | |
1447 for (++j; j < rets.length(); ++j) { | |
1448 if (rets[j]->type() == HeapGraphEdge::kShortcut) continue; | |
1449 HeapEntry* ret = rets[j]->From(); | |
1450 if (dominators->at(ret->ordered_index()) != NULL) { | |
1451 new_idom = entries[Intersect(ret->ordered_index(), | |
1452 new_idom->ordered_index(), | |
1453 *dominators)]; | |
1454 } | |
1455 } | |
1456 if (new_idom != NULL && dominators->at(i) != new_idom) { | |
1457 (*dominators)[i] = new_idom; | |
1458 changed = true; | |
1459 } | |
1460 } | |
1461 } | |
1462 } | |
1463 | |
1464 | |
1465 void HeapSnapshot::SetDominatorsToSelf() { | 1385 void HeapSnapshot::SetDominatorsToSelf() { |
1466 for (int i = 0; i < entries_.length(); ++i) { | 1386 for (int i = 0; i < entries_.length(); ++i) { |
1467 HeapEntry* entry = entries_[i]; | 1387 HeapEntry* entry = entries_[i]; |
1468 if (entry->dominator() == NULL) entry->set_dominator(entry); | 1388 if (entry->dominator() == NULL) entry->set_dominator(entry); |
1469 } | 1389 } |
1470 } | 1390 } |
1471 | 1391 |
1472 | 1392 |
1473 void HeapSnapshot::SetEntriesDominators() { | |
1474 // This array is used for maintaining reverse postorder of nodes. | |
1475 ScopedVector<HeapEntry*> ordered_entries(entries_.length()); | |
1476 FillReversePostorderIndexes(&ordered_entries); | |
1477 ScopedVector<HeapEntry*> dominators(ordered_entries.length()); | |
1478 BuildDominatorTree(ordered_entries, &dominators); | |
1479 for (int i = 0; i < ordered_entries.length(); ++i) { | |
1480 ASSERT(dominators[i] != NULL); | |
1481 ordered_entries[i]->set_dominator(dominators[i]); | |
1482 } | |
1483 // For nodes unreachable from root, set dominator to itself. | |
1484 SetDominatorsToSelf(); | |
1485 } | |
1486 | |
1487 | |
1488 void HeapSnapshot::ApproximateRetainedSizes() { | |
1489 SetEntriesDominators(); | |
1490 // As for the dominators tree we only know parent nodes, not | |
1491 // children, to sum up total sizes we traverse the tree level by | |
1492 // level upwards, starting from leaves. | |
1493 for (int i = 0; i < entries_.length(); ++i) { | |
1494 HeapEntry* entry = entries_[i]; | |
1495 entry->set_retained_size(entry->self_size()); | |
1496 entry->set_leaf(); | |
1497 } | |
1498 while (true) { | |
1499 bool onlyLeaves = true; | |
1500 for (int i = 0; i < entries_.length(); ++i) { | |
1501 HeapEntry *entry = entries_[i], *dominator = entry->dominator(); | |
1502 if (!entry->is_processed() && dominator != entry) { | |
1503 dominator->set_non_leaf(); | |
1504 onlyLeaves = false; | |
1505 } | |
1506 } | |
1507 if (onlyLeaves) break; | |
1508 | |
1509 for (int i = 0; i < entries_.length(); ++i) { | |
1510 HeapEntry *entry = entries_[i], *dominator = entry->dominator(); | |
1511 if (entry->is_leaf() && dominator != entry) { | |
1512 dominator->add_retained_size(entry->retained_size()); | |
1513 } | |
1514 } | |
1515 | |
1516 // Mark all current leaves as processed, reset non-leaves back to leaves. | |
1517 for (int i = 0; i < entries_.length(); ++i) { | |
1518 HeapEntry* entry = entries_[i]; | |
1519 if (entry->is_leaf()) | |
1520 entry->set_processed(); | |
1521 else if (entry->is_non_leaf()) | |
1522 entry->set_leaf(); | |
1523 } | |
1524 } | |
1525 } | |
1526 | |
1527 | |
1528 HeapEntry* HeapSnapshot::GetNextEntryToInit() { | 1393 HeapEntry* HeapSnapshot::GetNextEntryToInit() { |
1529 if (entries_.length() > 0) { | 1394 if (entries_.length() > 0) { |
1530 HeapEntry* last_entry = entries_.last(); | 1395 HeapEntry* last_entry = entries_.last(); |
1531 entries_.Add(reinterpret_cast<HeapEntry*>( | 1396 entries_.Add(reinterpret_cast<HeapEntry*>( |
1532 reinterpret_cast<char*>(last_entry) + last_entry->EntrySize())); | 1397 reinterpret_cast<char*>(last_entry) + last_entry->EntrySize())); |
1533 } else { | 1398 } else { |
1534 entries_.Add(reinterpret_cast<HeapEntry*>(raw_entries_)); | 1399 entries_.Add(reinterpret_cast<HeapEntry*>(raw_entries_)); |
1535 } | 1400 } |
1536 ASSERT(reinterpret_cast<char*>(entries_.last()) < | 1401 ASSERT(reinterpret_cast<char*>(entries_.last()) < |
1537 (raw_entries_ + raw_entries_size_)); | 1402 (raw_entries_ + raw_entries_size_)); |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1709 HeapSnapshotsCollection::~HeapSnapshotsCollection() { | 1574 HeapSnapshotsCollection::~HeapSnapshotsCollection() { |
1710 delete token_enumerator_; | 1575 delete token_enumerator_; |
1711 snapshots_.Iterate(DeleteHeapSnapshot); | 1576 snapshots_.Iterate(DeleteHeapSnapshot); |
1712 } | 1577 } |
1713 | 1578 |
1714 | 1579 |
1715 HeapSnapshot* HeapSnapshotsCollection::NewSnapshot(HeapSnapshot::Type type, | 1580 HeapSnapshot* HeapSnapshotsCollection::NewSnapshot(HeapSnapshot::Type type, |
1716 const char* name, | 1581 const char* name, |
1717 unsigned uid) { | 1582 unsigned uid) { |
1718 is_tracking_objects_ = true; // Start watching for heap objects moves. | 1583 is_tracking_objects_ = true; // Start watching for heap objects moves. |
1719 HeapSnapshot* snapshot = new HeapSnapshot(this, type, name, uid); | 1584 return new HeapSnapshot(this, type, name, uid); |
1720 snapshots_.Add(snapshot); | |
1721 HashMap::Entry* entry = | |
1722 snapshots_uids_.Lookup(reinterpret_cast<void*>(snapshot->uid()), | |
1723 static_cast<uint32_t>(snapshot->uid()), | |
1724 true); | |
1725 ASSERT(entry->value == NULL); | |
1726 entry->value = snapshot; | |
1727 return snapshot; | |
1728 } | 1585 } |
1729 | 1586 |
1730 | 1587 |
| 1588 void HeapSnapshotsCollection::SnapshotGenerationFinished( |
| 1589 HeapSnapshot* snapshot) { |
| 1590 ids_.SnapshotGenerationFinished(); |
| 1591 if (snapshot != NULL) { |
| 1592 snapshots_.Add(snapshot); |
| 1593 HashMap::Entry* entry = |
| 1594 snapshots_uids_.Lookup(reinterpret_cast<void*>(snapshot->uid()), |
| 1595 static_cast<uint32_t>(snapshot->uid()), |
| 1596 true); |
| 1597 ASSERT(entry->value == NULL); |
| 1598 entry->value = snapshot; |
| 1599 } |
| 1600 } |
| 1601 |
| 1602 |
1731 HeapSnapshot* HeapSnapshotsCollection::GetSnapshot(unsigned uid) { | 1603 HeapSnapshot* HeapSnapshotsCollection::GetSnapshot(unsigned uid) { |
1732 HashMap::Entry* entry = snapshots_uids_.Lookup(reinterpret_cast<void*>(uid), | 1604 HashMap::Entry* entry = snapshots_uids_.Lookup(reinterpret_cast<void*>(uid), |
1733 static_cast<uint32_t>(uid), | 1605 static_cast<uint32_t>(uid), |
1734 false); | 1606 false); |
1735 return entry != NULL ? reinterpret_cast<HeapSnapshot*>(entry->value) : NULL; | 1607 return entry != NULL ? reinterpret_cast<HeapSnapshot*>(entry->value) : NULL; |
1736 } | 1608 } |
1737 | 1609 |
1738 | 1610 |
1739 HeapSnapshotsDiff* HeapSnapshotsCollection::CompareSnapshots( | 1611 HeapSnapshotsDiff* HeapSnapshotsCollection::CompareSnapshots( |
1740 HeapSnapshot* snapshot1, | 1612 HeapSnapshot* snapshot1, |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1825 if (!obj->IsHeapObject()) return; | 1697 if (!obj->IsHeapObject()) return; |
1826 HeapObject* object = HeapObject::cast(obj); | 1698 HeapObject* object = HeapObject::cast(obj); |
1827 HashMap::Entry* cache_entry = | 1699 HashMap::Entry* cache_entry = |
1828 entries_.Lookup(object, HeapEntriesMap::Hash(object), true); | 1700 entries_.Lookup(object, HeapEntriesMap::Hash(object), true); |
1829 if (cache_entry->value == NULL) { | 1701 if (cache_entry->value == NULL) { |
1830 cache_entry->value = HeapEntriesMap::kHeapEntryPlaceholder; | 1702 cache_entry->value = HeapEntriesMap::kHeapEntryPlaceholder; |
1831 } | 1703 } |
1832 } | 1704 } |
1833 | 1705 |
1834 | 1706 |
1835 HeapSnapshotGenerator::HeapSnapshotGenerator(HeapSnapshot* snapshot) | 1707 HeapSnapshotGenerator::HeapSnapshotGenerator(HeapSnapshot* snapshot, |
| 1708 v8::ActivityControl* control) |
1836 : snapshot_(snapshot), | 1709 : snapshot_(snapshot), |
| 1710 control_(control), |
1837 collection_(snapshot->collection()), | 1711 collection_(snapshot->collection()), |
1838 filler_(NULL) { | 1712 filler_(NULL) { |
1839 } | 1713 } |
1840 | 1714 |
1841 class SnapshotCounter : public HeapSnapshotGenerator::SnapshotFillerInterface { | 1715 class SnapshotCounter : public HeapSnapshotGenerator::SnapshotFillerInterface { |
1842 public: | 1716 public: |
1843 explicit SnapshotCounter(HeapEntriesMap* entries) | 1717 explicit SnapshotCounter(HeapEntriesMap* entries) |
1844 : entries_(entries) { } | 1718 : entries_(entries) { } |
1845 HeapEntry* AddEntry(HeapObject* obj) { | 1719 HeapEntry* AddEntry(HeapObject* obj) { |
1846 entries_->Pair(obj, HeapEntriesMap::kHeapEntryPlaceholder); | 1720 entries_->Pair(obj, HeapEntriesMap::kHeapEntryPlaceholder); |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1983 : generator_(generator) { | 1857 : generator_(generator) { |
1984 } | 1858 } |
1985 void VisitPointers(Object** start, Object** end) { | 1859 void VisitPointers(Object** start, Object** end) { |
1986 for (Object** p = start; p < end; p++) generator_->SetGcRootsReference(*p); | 1860 for (Object** p = start; p < end; p++) generator_->SetGcRootsReference(*p); |
1987 } | 1861 } |
1988 private: | 1862 private: |
1989 HeapSnapshotGenerator* generator_; | 1863 HeapSnapshotGenerator* generator_; |
1990 }; | 1864 }; |
1991 | 1865 |
1992 | 1866 |
1993 void HeapSnapshotGenerator::GenerateSnapshot() { | 1867 bool HeapSnapshotGenerator::GenerateSnapshot() { |
1994 AssertNoAllocation no_alloc; | 1868 AssertNoAllocation no_alloc; |
1995 | 1869 |
| 1870 SetProgressTotal(4); // 2 passes + dominators + sizes. |
| 1871 |
1996 // Pass 1. Iterate heap contents to count entries and references. | 1872 // Pass 1. Iterate heap contents to count entries and references. |
1997 SnapshotCounter counter(&entries_); | 1873 if (!CountEntriesAndReferences()) return false; |
1998 filler_ = &counter; | |
1999 filler_->AddEntry(HeapSnapshot::kInternalRootObject); | |
2000 filler_->AddEntry(HeapSnapshot::kGcRootsObject); | |
2001 HeapIterator iterator(HeapIterator::kPreciseFiltering); | |
2002 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) { | |
2003 ExtractReferences(obj); | |
2004 } | |
2005 SetRootGcRootsReference(); | |
2006 RootsReferencesExtractor extractor(this); | |
2007 Heap::IterateRoots(&extractor, VISIT_ONLY_STRONG); | |
2008 | 1874 |
2009 // Allocate and fill entries in the snapshot, allocate references. | 1875 // Allocate and fill entries in the snapshot, allocate references. |
2010 snapshot_->AllocateEntries(entries_.entries_count(), | 1876 snapshot_->AllocateEntries(entries_.entries_count(), |
2011 entries_.total_children_count(), | 1877 entries_.total_children_count(), |
2012 entries_.total_retainers_count()); | 1878 entries_.total_retainers_count()); |
2013 SnapshotAllocator allocator(snapshot_); | 1879 SnapshotAllocator allocator(snapshot_); |
2014 entries_.UpdateEntries(&allocator); | 1880 entries_.UpdateEntries(&allocator); |
2015 | 1881 |
2016 // Pass 2. Fill references. | 1882 // Pass 2. Fill references. |
2017 SnapshotFiller filler(snapshot_, &entries_); | 1883 if (!FillReferences()) return false; |
2018 filler_ = &filler; | |
2019 iterator.reset(); | |
2020 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) { | |
2021 ExtractReferences(obj); | |
2022 } | |
2023 SetRootGcRootsReference(); | |
2024 Heap::IterateRoots(&extractor, VISIT_ONLY_STRONG); | |
2025 | 1884 |
2026 snapshot_->ApproximateRetainedSizes(); | 1885 if (!SetEntriesDominators()) return false; |
| 1886 if (!ApproximateRetainedSizes()) return false; |
| 1887 |
| 1888 progress_counter_ = progress_total_; |
| 1889 if (!ReportProgress(true)) return false; |
| 1890 return true; |
2027 } | 1891 } |
2028 | 1892 |
2029 | 1893 |
2030 HeapEntry* HeapSnapshotGenerator::GetEntry(Object* obj) { | 1894 HeapEntry* HeapSnapshotGenerator::GetEntry(Object* obj) { |
2031 if (!obj->IsHeapObject()) return NULL; | 1895 if (!obj->IsHeapObject()) return NULL; |
2032 HeapObject* object = HeapObject::cast(obj); | 1896 HeapObject* object = HeapObject::cast(obj); |
2033 HeapEntry* entry = entries_.Map(object); | 1897 HeapEntry* entry = entries_.Map(object); |
2034 // A new entry. | 1898 // A new entry. |
2035 if (entry == NULL) entry = filler_->AddEntry(object); | 1899 if (entry == NULL) entry = filler_->AddEntry(object); |
2036 return entry; | 1900 return entry; |
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2344 | 2208 |
2345 | 2209 |
2346 void HeapSnapshotGenerator::SetGcRootsReference(Object* child_obj) { | 2210 void HeapSnapshotGenerator::SetGcRootsReference(Object* child_obj) { |
2347 HeapEntry* child_entry = GetEntry(child_obj); | 2211 HeapEntry* child_entry = GetEntry(child_obj); |
2348 if (child_entry != NULL) { | 2212 if (child_entry != NULL) { |
2349 filler_->SetStrongRootReference(child_obj, child_entry); | 2213 filler_->SetStrongRootReference(child_obj, child_entry); |
2350 } | 2214 } |
2351 } | 2215 } |
2352 | 2216 |
2353 | 2217 |
| 2218 void HeapSnapshotGenerator::SetProgressTotal(int iterations_count) { |
| 2219 if (control_ == NULL) return; |
| 2220 |
| 2221 HeapIterator iterator(HeapIterator::kPreciseFiltering); |
| 2222 int objects_count = 0; |
| 2223 for (HeapObject* obj = iterator.next(); |
| 2224 obj != NULL; |
| 2225 obj = iterator.next(), ++objects_count) {} |
| 2226 progress_total_ = objects_count * iterations_count; |
| 2227 progress_counter_ = 0; |
| 2228 } |
| 2229 |
| 2230 |
| 2231 bool HeapSnapshotGenerator::CountEntriesAndReferences() { |
| 2232 SnapshotCounter counter(&entries_); |
| 2233 filler_ = &counter; |
| 2234 filler_->AddEntry(HeapSnapshot::kInternalRootObject); |
| 2235 filler_->AddEntry(HeapSnapshot::kGcRootsObject); |
| 2236 return IterateAndExtractReferences(); |
| 2237 } |
| 2238 |
| 2239 |
| 2240 bool HeapSnapshotGenerator::FillReferences() { |
| 2241 SnapshotFiller filler(snapshot_, &entries_); |
| 2242 filler_ = &filler; |
| 2243 return IterateAndExtractReferences(); |
| 2244 } |
| 2245 |
| 2246 |
| 2247 void HeapSnapshotGenerator::FillReversePostorderIndexes( |
| 2248 Vector<HeapEntry*>* entries) { |
| 2249 snapshot_->ClearPaint(); |
| 2250 int current_entry = 0; |
| 2251 List<HeapEntry*> nodes_to_visit; |
| 2252 nodes_to_visit.Add(snapshot_->root()); |
| 2253 snapshot_->root()->paint_reachable(); |
| 2254 while (!nodes_to_visit.is_empty()) { |
| 2255 HeapEntry* entry = nodes_to_visit.last(); |
| 2256 Vector<HeapGraphEdge> children = entry->children(); |
| 2257 bool has_new_edges = false; |
| 2258 for (int i = 0; i < children.length(); ++i) { |
| 2259 if (children[i].type() == HeapGraphEdge::kShortcut) continue; |
| 2260 HeapEntry* child = children[i].to(); |
| 2261 if (!child->painted_reachable()) { |
| 2262 nodes_to_visit.Add(child); |
| 2263 child->paint_reachable(); |
| 2264 has_new_edges = true; |
| 2265 } |
| 2266 } |
| 2267 if (!has_new_edges) { |
| 2268 entry->set_ordered_index(current_entry); |
| 2269 (*entries)[current_entry++] = entry; |
| 2270 nodes_to_visit.RemoveLast(); |
| 2271 } |
| 2272 } |
| 2273 entries->Truncate(current_entry); |
| 2274 } |
| 2275 |
| 2276 |
| 2277 static int Intersect(int i1, int i2, const Vector<HeapEntry*>& dominators) { |
| 2278 int finger1 = i1, finger2 = i2; |
| 2279 while (finger1 != finger2) { |
| 2280 while (finger1 < finger2) finger1 = dominators[finger1]->ordered_index(); |
| 2281 while (finger2 < finger1) finger2 = dominators[finger2]->ordered_index(); |
| 2282 } |
| 2283 return finger1; |
| 2284 } |
| 2285 |
| 2286 // The algorithm is based on the article: |
| 2287 // K. Cooper, T. Harvey and K. Kennedy "A Simple, Fast Dominance Algorithm" |
| 2288 // Softw. Pract. Exper. 4 (2001), pp. 1–10. |
| 2289 bool HeapSnapshotGenerator::BuildDominatorTree( |
| 2290 const Vector<HeapEntry*>& entries, |
| 2291 Vector<HeapEntry*>* dominators) { |
| 2292 if (entries.length() == 0) return true; |
| 2293 const int entries_length = entries.length(), root_index = entries_length - 1; |
| 2294 for (int i = 0; i < root_index; ++i) (*dominators)[i] = NULL; |
| 2295 (*dominators)[root_index] = entries[root_index]; |
| 2296 int changed = 1; |
| 2297 const int base_progress_counter = progress_counter_; |
| 2298 while (changed != 0) { |
| 2299 changed = 0; |
| 2300 for (int i = root_index - 1; i >= 0; --i) { |
| 2301 HeapEntry* new_idom = NULL; |
| 2302 Vector<HeapGraphEdge*> rets = entries[i]->retainers(); |
| 2303 int j = 0; |
| 2304 for (; j < rets.length(); ++j) { |
| 2305 if (rets[j]->type() == HeapGraphEdge::kShortcut) continue; |
| 2306 HeapEntry* ret = rets[j]->From(); |
| 2307 if (dominators->at(ret->ordered_index()) != NULL) { |
| 2308 new_idom = ret; |
| 2309 break; |
| 2310 } |
| 2311 } |
| 2312 for (++j; j < rets.length(); ++j) { |
| 2313 if (rets[j]->type() == HeapGraphEdge::kShortcut) continue; |
| 2314 HeapEntry* ret = rets[j]->From(); |
| 2315 if (dominators->at(ret->ordered_index()) != NULL) { |
| 2316 new_idom = entries[Intersect(ret->ordered_index(), |
| 2317 new_idom->ordered_index(), |
| 2318 *dominators)]; |
| 2319 } |
| 2320 } |
| 2321 if (new_idom != NULL && dominators->at(i) != new_idom) { |
| 2322 (*dominators)[i] = new_idom; |
| 2323 ++changed; |
| 2324 } |
| 2325 } |
| 2326 int remaining = entries_length - changed; |
| 2327 if (remaining < 0) remaining = 0; |
| 2328 progress_counter_ = base_progress_counter + remaining; |
| 2329 if (!ReportProgress(true)) return false; |
| 2330 } |
| 2331 return true; |
| 2332 } |
| 2333 |
| 2334 |
| 2335 bool HeapSnapshotGenerator::SetEntriesDominators() { |
| 2336 // This array is used for maintaining reverse postorder of nodes. |
| 2337 ScopedVector<HeapEntry*> ordered_entries(snapshot_->entries()->length()); |
| 2338 FillReversePostorderIndexes(&ordered_entries); |
| 2339 ScopedVector<HeapEntry*> dominators(ordered_entries.length()); |
| 2340 if (!BuildDominatorTree(ordered_entries, &dominators)) return false; |
| 2341 for (int i = 0; i < ordered_entries.length(); ++i) { |
| 2342 ASSERT(dominators[i] != NULL); |
| 2343 ordered_entries[i]->set_dominator(dominators[i]); |
| 2344 } |
| 2345 // For nodes unreachable from root, set dominator to itself. |
| 2346 snapshot_->SetDominatorsToSelf(); |
| 2347 return true; |
| 2348 } |
| 2349 |
| 2350 |
| 2351 bool HeapSnapshotGenerator::ApproximateRetainedSizes() { |
| 2352 // As for the dominators tree we only know parent nodes, not |
| 2353 // children, to sum up total sizes we "bubble" node's self size |
| 2354 // adding it to all of its parents. |
| 2355 for (int i = 0; i < snapshot_->entries()->length(); ++i) { |
| 2356 HeapEntry* entry = snapshot_->entries()->at(i); |
| 2357 entry->set_retained_size(entry->self_size()); |
| 2358 } |
| 2359 for (int i = 0; |
| 2360 i < snapshot_->entries()->length(); |
| 2361 ++i, IncProgressCounter()) { |
| 2362 HeapEntry* entry = snapshot_->entries()->at(i); |
| 2363 int entry_size = entry->self_size(); |
| 2364 for (HeapEntry* dominator = entry->dominator(); |
| 2365 dominator != entry; |
| 2366 entry = dominator, dominator = entry->dominator()) { |
| 2367 dominator->add_retained_size(entry_size); |
| 2368 } |
| 2369 if (!ReportProgress()) return false; |
| 2370 } |
| 2371 return true; |
| 2372 } |
| 2373 |
| 2374 |
| 2375 bool HeapSnapshotGenerator::IterateAndExtractReferences() { |
| 2376 HeapIterator iterator(HeapIterator::kPreciseFiltering); |
| 2377 bool interrupted = false; |
| 2378 // Heap iteration with precise filtering must be finished in any case. |
| 2379 for (HeapObject* obj = iterator.next(); |
| 2380 obj != NULL; |
| 2381 obj = iterator.next(), IncProgressCounter()) { |
| 2382 if (!interrupted) { |
| 2383 ExtractReferences(obj); |
| 2384 if (!ReportProgress()) interrupted = true; |
| 2385 } |
| 2386 } |
| 2387 if (interrupted) return false; |
| 2388 SetRootGcRootsReference(); |
| 2389 RootsReferencesExtractor extractor(this); |
| 2390 Heap::IterateRoots(&extractor, VISIT_ONLY_STRONG); |
| 2391 return ReportProgress(); |
| 2392 } |
| 2393 |
| 2394 |
2354 void HeapSnapshotsDiff::CreateRoots(int additions_count, int deletions_count) { | 2395 void HeapSnapshotsDiff::CreateRoots(int additions_count, int deletions_count) { |
2355 raw_additions_root_ = | 2396 raw_additions_root_ = |
2356 NewArray<char>(HeapEntry::EntriesSize(1, additions_count, 0)); | 2397 NewArray<char>(HeapEntry::EntriesSize(1, additions_count, 0)); |
2357 additions_root()->Init( | 2398 additions_root()->Init( |
2358 snapshot2_, HeapEntry::kHidden, "", 0, 0, additions_count, 0); | 2399 snapshot2_, HeapEntry::kHidden, "", 0, 0, additions_count, 0); |
2359 raw_deletions_root_ = | 2400 raw_deletions_root_ = |
2360 NewArray<char>(HeapEntry::EntriesSize(1, deletions_count, 0)); | 2401 NewArray<char>(HeapEntry::EntriesSize(1, deletions_count, 0)); |
2361 deletions_root()->Init( | 2402 deletions_root()->Init( |
2362 snapshot1_, HeapEntry::kHidden, "", 0, 0, deletions_count, 0); | 2403 snapshot1_, HeapEntry::kHidden, "", 0, 0, deletions_count, 0); |
2363 } | 2404 } |
(...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2794 | 2835 |
2795 | 2836 |
2796 String* GetConstructorNameForHeapProfile(JSObject* object) { | 2837 String* GetConstructorNameForHeapProfile(JSObject* object) { |
2797 if (object->IsJSFunction()) return Heap::closure_symbol(); | 2838 if (object->IsJSFunction()) return Heap::closure_symbol(); |
2798 return object->constructor_name(); | 2839 return object->constructor_name(); |
2799 } | 2840 } |
2800 | 2841 |
2801 } } // namespace v8::internal | 2842 } } // namespace v8::internal |
2802 | 2843 |
2803 #endif // ENABLE_LOGGING_AND_PROFILING | 2844 #endif // ENABLE_LOGGING_AND_PROFILING |
OLD | NEW |