Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(957)

Side by Side Diff: src/profile-generator.cc

Issue 5687003: New heap profiler: add support for progress reporting and control. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 10 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/profile-generator.h ('k') | src/profile-generator-inl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/profile-generator.h ('k') | src/profile-generator-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698