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 11 matching lines...) Expand all Loading... |
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | 27 |
28 #ifdef ENABLE_LOGGING_AND_PROFILING | 28 #ifdef ENABLE_LOGGING_AND_PROFILING |
29 | 29 |
30 #include "v8.h" | 30 #include "v8.h" |
31 #include "global-handles.h" | 31 #include "global-handles.h" |
| 32 #include "heap-profiler.h" |
32 #include "scopeinfo.h" | 33 #include "scopeinfo.h" |
33 #include "top.h" | 34 #include "top.h" |
34 #include "unicode.h" | 35 #include "unicode.h" |
35 #include "zone-inl.h" | 36 #include "zone-inl.h" |
36 | 37 |
37 #include "profile-generator-inl.h" | 38 #include "profile-generator-inl.h" |
38 | 39 |
39 namespace v8 { | 40 namespace v8 { |
40 namespace internal { | 41 namespace internal { |
41 | 42 |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
87 } | 88 } |
88 } | 89 } |
89 } | 90 } |
90 | 91 |
91 | 92 |
92 StringsStorage::StringsStorage() | 93 StringsStorage::StringsStorage() |
93 : names_(StringsMatch) { | 94 : names_(StringsMatch) { |
94 } | 95 } |
95 | 96 |
96 | 97 |
97 static void DeleteIndexName(char** name_ptr) { | |
98 DeleteArray(*name_ptr); | |
99 } | |
100 | |
101 | |
102 StringsStorage::~StringsStorage() { | 98 StringsStorage::~StringsStorage() { |
103 for (HashMap::Entry* p = names_.Start(); | 99 for (HashMap::Entry* p = names_.Start(); |
104 p != NULL; | 100 p != NULL; |
105 p = names_.Next(p)) { | 101 p = names_.Next(p)) { |
106 DeleteArray(reinterpret_cast<const char*>(p->value)); | 102 DeleteArray(reinterpret_cast<const char*>(p->value)); |
107 } | 103 } |
108 index_names_.Iterate(DeleteIndexName); | 104 } |
| 105 |
| 106 |
| 107 const char* StringsStorage::GetCopy(const char* src) { |
| 108 int len = strlen(src); |
| 109 Vector<char> dst = Vector<char>::New(len + 1); |
| 110 OS::StrNCpy(dst, src, len); |
| 111 dst[len] = '\0'; |
| 112 uint32_t hash = HashSequentialString(dst.start(), len); |
| 113 return AddOrDisposeString(dst.start(), hash); |
| 114 } |
| 115 |
| 116 |
| 117 const char* StringsStorage::GetFormatted(const char* format, ...) { |
| 118 va_list args; |
| 119 va_start(args, format); |
| 120 const char* result = GetVFormatted(format, args); |
| 121 va_end(args); |
| 122 return result; |
| 123 } |
| 124 |
| 125 |
| 126 const char* StringsStorage::AddOrDisposeString(char* str, uint32_t hash) { |
| 127 HashMap::Entry* cache_entry = names_.Lookup(str, hash, true); |
| 128 if (cache_entry->value == NULL) { |
| 129 // New entry added. |
| 130 cache_entry->value = str; |
| 131 } else { |
| 132 DeleteArray(str); |
| 133 } |
| 134 return reinterpret_cast<const char*>(cache_entry->value); |
| 135 } |
| 136 |
| 137 |
| 138 const char* StringsStorage::GetVFormatted(const char* format, va_list args) { |
| 139 Vector<char> str = Vector<char>::New(1024); |
| 140 int len = OS::VSNPrintF(str, format, args); |
| 141 if (len == -1) { |
| 142 DeleteArray(str.start()); |
| 143 return format; |
| 144 } |
| 145 uint32_t hash = HashSequentialString(str.start(), len); |
| 146 return AddOrDisposeString(str.start(), hash); |
109 } | 147 } |
110 | 148 |
111 | 149 |
112 const char* StringsStorage::GetName(String* name) { | 150 const char* StringsStorage::GetName(String* name) { |
113 if (name->IsString()) { | 151 if (name->IsString()) { |
114 char* c_name = | 152 return AddOrDisposeString( |
115 name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL).Detach(); | 153 name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL).Detach(), |
116 HashMap::Entry* cache_entry = names_.Lookup(c_name, name->Hash(), true); | 154 name->Hash()); |
117 if (cache_entry->value == NULL) { | |
118 // New entry added. | |
119 cache_entry->value = c_name; | |
120 } else { | |
121 DeleteArray(c_name); | |
122 } | |
123 return reinterpret_cast<const char*>(cache_entry->value); | |
124 } | 155 } |
125 return ""; | 156 return ""; |
126 } | 157 } |
127 | 158 |
128 | 159 |
129 const char* StringsStorage::GetName(int index) { | 160 const char* StringsStorage::GetName(int index) { |
130 ASSERT(index >= 0); | 161 return GetFormatted("%d", index); |
131 if (index_names_.length() <= index) { | |
132 index_names_.AddBlock( | |
133 NULL, index - index_names_.length() + 1); | |
134 } | |
135 if (index_names_[index] == NULL) { | |
136 const int kMaximumNameLength = 32; | |
137 char* name = NewArray<char>(kMaximumNameLength); | |
138 OS::SNPrintF(Vector<char>(name, kMaximumNameLength), "%d", index); | |
139 index_names_[index] = name; | |
140 } | |
141 return index_names_[index]; | |
142 } | 162 } |
143 | 163 |
144 | 164 |
145 const char* CodeEntry::kEmptyNamePrefix = ""; | 165 const char* CodeEntry::kEmptyNamePrefix = ""; |
146 | 166 |
147 | 167 |
148 void CodeEntry::CopyData(const CodeEntry& source) { | 168 void CodeEntry::CopyData(const CodeEntry& source) { |
149 tag_ = source.tag_; | 169 tag_ = source.tag_; |
150 name_prefix_ = source.name_prefix_; | 170 name_prefix_ = source.name_prefix_; |
151 name_ = source.name_; | 171 name_ = source.name_; |
(...skipping 850 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1002 const char* HeapEntry::TypeAsString() { | 1022 const char* HeapEntry::TypeAsString() { |
1003 switch (type()) { | 1023 switch (type()) { |
1004 case kHidden: return "/hidden/"; | 1024 case kHidden: return "/hidden/"; |
1005 case kObject: return "/object/"; | 1025 case kObject: return "/object/"; |
1006 case kClosure: return "/closure/"; | 1026 case kClosure: return "/closure/"; |
1007 case kString: return "/string/"; | 1027 case kString: return "/string/"; |
1008 case kCode: return "/code/"; | 1028 case kCode: return "/code/"; |
1009 case kArray: return "/array/"; | 1029 case kArray: return "/array/"; |
1010 case kRegExp: return "/regexp/"; | 1030 case kRegExp: return "/regexp/"; |
1011 case kHeapNumber: return "/number/"; | 1031 case kHeapNumber: return "/number/"; |
| 1032 case kNative: return "/native/"; |
1012 default: return "???"; | 1033 default: return "???"; |
1013 } | 1034 } |
1014 } | 1035 } |
1015 | 1036 |
1016 | 1037 |
1017 int HeapEntry::EntriesSize(int entries_count, | 1038 int HeapEntry::EntriesSize(int entries_count, |
1018 int children_count, | 1039 int children_count, |
1019 int retainers_count) { | 1040 int retainers_count) { |
1020 return sizeof(HeapEntry) * entries_count // NOLINT | 1041 return sizeof(HeapEntry) * entries_count // NOLINT |
1021 + sizeof(HeapGraphEdge) * children_count // NOLINT | 1042 + sizeof(HeapGraphEdge) * children_count // NOLINT |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1198 HeapSnapshot::HeapSnapshot(HeapSnapshotsCollection* collection, | 1219 HeapSnapshot::HeapSnapshot(HeapSnapshotsCollection* collection, |
1199 HeapSnapshot::Type type, | 1220 HeapSnapshot::Type type, |
1200 const char* title, | 1221 const char* title, |
1201 unsigned uid) | 1222 unsigned uid) |
1202 : collection_(collection), | 1223 : collection_(collection), |
1203 type_(type), | 1224 type_(type), |
1204 title_(title), | 1225 title_(title), |
1205 uid_(uid), | 1226 uid_(uid), |
1206 root_entry_(NULL), | 1227 root_entry_(NULL), |
1207 gc_roots_entry_(NULL), | 1228 gc_roots_entry_(NULL), |
| 1229 dom_subtrees_root_entry_(NULL), |
1208 raw_entries_(NULL), | 1230 raw_entries_(NULL), |
1209 entries_sorted_(false), | 1231 entries_sorted_(false), |
1210 retaining_paths_(HeapEntry::Match) { | 1232 retaining_paths_(HeapEntry::Match) { |
1211 STATIC_ASSERT( | 1233 STATIC_ASSERT( |
1212 sizeof(HeapGraphEdge) == | 1234 sizeof(HeapGraphEdge) == |
1213 SnapshotSizeConstants<sizeof(void*)>::kExpectedHeapGraphEdgeSize); // NOL
INT | 1235 SnapshotSizeConstants<sizeof(void*)>::kExpectedHeapGraphEdgeSize); // NOL
INT |
1214 STATIC_ASSERT( | 1236 STATIC_ASSERT( |
1215 sizeof(HeapEntry) == | 1237 sizeof(HeapEntry) == |
1216 SnapshotSizeConstants<sizeof(void*)>::kExpectedHeapEntrySize); // NOLINT | 1238 SnapshotSizeConstants<sizeof(void*)>::kExpectedHeapEntrySize); // NOLINT |
1217 } | 1239 } |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1272 ASSERT(gc_roots_entry_ == NULL); | 1294 ASSERT(gc_roots_entry_ == NULL); |
1273 return (gc_roots_entry_ = AddEntry(HeapEntry::kObject, | 1295 return (gc_roots_entry_ = AddEntry(HeapEntry::kObject, |
1274 "(GC roots)", | 1296 "(GC roots)", |
1275 HeapObjectsMap::kGcRootsObjectId, | 1297 HeapObjectsMap::kGcRootsObjectId, |
1276 0, | 1298 0, |
1277 children_count, | 1299 children_count, |
1278 retainers_count)); | 1300 retainers_count)); |
1279 } | 1301 } |
1280 | 1302 |
1281 | 1303 |
| 1304 HeapEntry* HeapSnapshot::AddNativesRootEntry(int children_count, |
| 1305 int retainers_count) { |
| 1306 ASSERT(dom_subtrees_root_entry_ == NULL); |
| 1307 return (dom_subtrees_root_entry_ = AddEntry( |
| 1308 HeapEntry::kObject, |
| 1309 "(Native objects)", |
| 1310 HeapObjectsMap::kNativesRootObjectId, |
| 1311 0, |
| 1312 children_count, |
| 1313 retainers_count)); |
| 1314 } |
| 1315 |
| 1316 |
1282 HeapEntry* HeapSnapshot::AddEntry(HeapEntry::Type type, | 1317 HeapEntry* HeapSnapshot::AddEntry(HeapEntry::Type type, |
1283 const char* name, | 1318 const char* name, |
1284 uint64_t id, | 1319 uint64_t id, |
1285 int size, | 1320 int size, |
1286 int children_count, | 1321 int children_count, |
1287 int retainers_count) { | 1322 int retainers_count) { |
1288 HeapEntry* entry = GetNextEntryToInit(); | 1323 HeapEntry* entry = GetNextEntryToInit(); |
1289 entry->Init(this, type, name, id, size, children_count, retainers_count); | 1324 entry->Init(this, type, name, id, size, children_count, retainers_count); |
1290 return entry; | 1325 return entry; |
1291 } | 1326 } |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1365 } | 1400 } |
1366 return &entries_; | 1401 return &entries_; |
1367 } | 1402 } |
1368 | 1403 |
1369 | 1404 |
1370 void HeapSnapshot::Print(int max_depth) { | 1405 void HeapSnapshot::Print(int max_depth) { |
1371 root()->Print(max_depth, 0); | 1406 root()->Print(max_depth, 0); |
1372 } | 1407 } |
1373 | 1408 |
1374 | 1409 |
1375 const uint64_t HeapObjectsMap::kInternalRootObjectId = 0; | 1410 // We split IDs on evens for embedder objects (see |
1376 const uint64_t HeapObjectsMap::kGcRootsObjectId = 1; | 1411 // HeapObjectsMap::GenerateId) and odds for native objects. |
| 1412 const uint64_t HeapObjectsMap::kInternalRootObjectId = 1; |
| 1413 const uint64_t HeapObjectsMap::kGcRootsObjectId = 3; |
| 1414 const uint64_t HeapObjectsMap::kNativesRootObjectId = 5; |
1377 // Increase kFirstAvailableObjectId if new 'special' objects appear. | 1415 // Increase kFirstAvailableObjectId if new 'special' objects appear. |
1378 const uint64_t HeapObjectsMap::kFirstAvailableObjectId = 2; | 1416 const uint64_t HeapObjectsMap::kFirstAvailableObjectId = 7; |
1379 | 1417 |
1380 HeapObjectsMap::HeapObjectsMap() | 1418 HeapObjectsMap::HeapObjectsMap() |
1381 : initial_fill_mode_(true), | 1419 : initial_fill_mode_(true), |
1382 next_id_(kFirstAvailableObjectId), | 1420 next_id_(kFirstAvailableObjectId), |
1383 entries_map_(AddressesMatch), | 1421 entries_map_(AddressesMatch), |
1384 entries_(new List<EntryInfo>()) { } | 1422 entries_(new List<EntryInfo>()) { } |
1385 | 1423 |
1386 | 1424 |
1387 HeapObjectsMap::~HeapObjectsMap() { | 1425 HeapObjectsMap::~HeapObjectsMap() { |
1388 delete entries_; | 1426 delete entries_; |
1389 } | 1427 } |
1390 | 1428 |
1391 | 1429 |
1392 void HeapObjectsMap::SnapshotGenerationFinished() { | 1430 void HeapObjectsMap::SnapshotGenerationFinished() { |
1393 initial_fill_mode_ = false; | 1431 initial_fill_mode_ = false; |
1394 RemoveDeadEntries(); | 1432 RemoveDeadEntries(); |
1395 } | 1433 } |
1396 | 1434 |
1397 | 1435 |
1398 uint64_t HeapObjectsMap::FindObject(Address addr) { | 1436 uint64_t HeapObjectsMap::FindObject(Address addr) { |
1399 if (!initial_fill_mode_) { | 1437 if (!initial_fill_mode_) { |
1400 uint64_t existing = FindEntry(addr); | 1438 uint64_t existing = FindEntry(addr); |
1401 if (existing != 0) return existing; | 1439 if (existing != 0) return existing; |
1402 } | 1440 } |
1403 uint64_t id = next_id_++; | 1441 uint64_t id = next_id_; |
| 1442 next_id_ += 2; |
1404 AddEntry(addr, id); | 1443 AddEntry(addr, id); |
1405 return id; | 1444 return id; |
1406 } | 1445 } |
1407 | 1446 |
1408 | 1447 |
1409 void HeapObjectsMap::MoveObject(Address from, Address to) { | 1448 void HeapObjectsMap::MoveObject(Address from, Address to) { |
1410 if (from == to) return; | 1449 if (from == to) return; |
1411 HashMap::Entry* entry = entries_map_.Lookup(from, AddressHash(from), false); | 1450 HashMap::Entry* entry = entries_map_.Lookup(from, AddressHash(from), false); |
1412 if (entry != NULL) { | 1451 if (entry != NULL) { |
1413 void* value = entry->value; | 1452 void* value = entry->value; |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1461 for (int i = 0; i < dead_entries.length(); ++i) { | 1500 for (int i = 0; i < dead_entries.length(); ++i) { |
1462 void* raw_entry = dead_entries[i]; | 1501 void* raw_entry = dead_entries[i]; |
1463 entries_map_.Remove( | 1502 entries_map_.Remove( |
1464 raw_entry, AddressHash(reinterpret_cast<Address>(raw_entry))); | 1503 raw_entry, AddressHash(reinterpret_cast<Address>(raw_entry))); |
1465 } | 1504 } |
1466 delete entries_; | 1505 delete entries_; |
1467 entries_ = new_entries; | 1506 entries_ = new_entries; |
1468 } | 1507 } |
1469 | 1508 |
1470 | 1509 |
| 1510 uint64_t HeapObjectsMap::GenerateId(v8::RetainedObjectInfo* info) { |
| 1511 uint64_t id = static_cast<uint64_t>(info->GetHash()); |
| 1512 const char* label = info->GetLabel(); |
| 1513 id ^= HashSequentialString(label, strlen(label)); |
| 1514 intptr_t element_count = info->GetElementCount(); |
| 1515 if (element_count != -1) |
| 1516 id ^= ComputeIntegerHash(static_cast<uint32_t>(element_count)); |
| 1517 return id << 1; |
| 1518 } |
| 1519 |
| 1520 |
1471 HeapSnapshotsCollection::HeapSnapshotsCollection() | 1521 HeapSnapshotsCollection::HeapSnapshotsCollection() |
1472 : is_tracking_objects_(false), | 1522 : is_tracking_objects_(false), |
1473 snapshots_uids_(HeapSnapshotsMatch), | 1523 snapshots_uids_(HeapSnapshotsMatch), |
1474 token_enumerator_(new TokenEnumerator()) { | 1524 token_enumerator_(new TokenEnumerator()) { |
1475 } | 1525 } |
1476 | 1526 |
1477 | 1527 |
1478 static void DeleteHeapSnapshot(HeapSnapshot** snapshot_ptr) { | 1528 static void DeleteHeapSnapshot(HeapSnapshot** snapshot_ptr) { |
1479 delete *snapshot_ptr; | 1529 delete *snapshot_ptr; |
1480 } | 1530 } |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1544 | 1594 |
1545 void HeapEntriesMap::AllocateEntries() { | 1595 void HeapEntriesMap::AllocateEntries() { |
1546 for (HashMap::Entry* p = entries_.Start(); | 1596 for (HashMap::Entry* p = entries_.Start(); |
1547 p != NULL; | 1597 p != NULL; |
1548 p = entries_.Next(p)) { | 1598 p = entries_.Next(p)) { |
1549 EntryInfo* entry_info = reinterpret_cast<EntryInfo*>(p->value); | 1599 EntryInfo* entry_info = reinterpret_cast<EntryInfo*>(p->value); |
1550 entry_info->entry = entry_info->allocator->AllocateEntry( | 1600 entry_info->entry = entry_info->allocator->AllocateEntry( |
1551 p->key, | 1601 p->key, |
1552 entry_info->children_count, | 1602 entry_info->children_count, |
1553 entry_info->retainers_count); | 1603 entry_info->retainers_count); |
| 1604 ASSERT(entry_info->entry != NULL); |
| 1605 ASSERT(entry_info->entry != kHeapEntryPlaceholder); |
1554 entry_info->children_count = 0; | 1606 entry_info->children_count = 0; |
1555 entry_info->retainers_count = 0; | 1607 entry_info->retainers_count = 0; |
1556 } | 1608 } |
1557 } | 1609 } |
1558 | 1610 |
1559 | 1611 |
1560 HeapEntry* HeapEntriesMap::Map(HeapThing thing) { | 1612 HeapEntry* HeapEntriesMap::Map(HeapThing thing) { |
1561 HashMap::Entry* cache_entry = entries_.Lookup(thing, Hash(thing), false); | 1613 HashMap::Entry* cache_entry = entries_.Lookup(thing, Hash(thing), false); |
1562 if (cache_entry != NULL) { | 1614 if (cache_entry != NULL) { |
1563 EntryInfo* entry_info = reinterpret_cast<EntryInfo*>(cache_entry->value); | 1615 EntryInfo* entry_info = reinterpret_cast<EntryInfo*>(cache_entry->value); |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1623 HeapObject* object = HeapObject::cast(obj); | 1675 HeapObject* object = HeapObject::cast(obj); |
1624 HashMap::Entry* cache_entry = | 1676 HashMap::Entry* cache_entry = |
1625 entries_.Lookup(object, HeapEntriesMap::Hash(object), true); | 1677 entries_.Lookup(object, HeapEntriesMap::Hash(object), true); |
1626 if (cache_entry->value == NULL) { | 1678 if (cache_entry->value == NULL) { |
1627 cache_entry->value = HeapEntriesMap::kHeapEntryPlaceholder; | 1679 cache_entry->value = HeapEntriesMap::kHeapEntryPlaceholder; |
1628 } | 1680 } |
1629 } | 1681 } |
1630 | 1682 |
1631 | 1683 |
1632 HeapObject *const V8HeapExplorer::kInternalRootObject = | 1684 HeapObject *const V8HeapExplorer::kInternalRootObject = |
1633 reinterpret_cast<HeapObject*>(1); | 1685 reinterpret_cast<HeapObject*>( |
| 1686 static_cast<intptr_t>(HeapObjectsMap::kInternalRootObjectId)); |
1634 HeapObject *const V8HeapExplorer::kGcRootsObject = | 1687 HeapObject *const V8HeapExplorer::kGcRootsObject = |
1635 reinterpret_cast<HeapObject*>(2); | 1688 reinterpret_cast<HeapObject*>( |
| 1689 static_cast<intptr_t>(HeapObjectsMap::kGcRootsObjectId)); |
1636 | 1690 |
1637 | 1691 |
1638 V8HeapExplorer::V8HeapExplorer( | 1692 V8HeapExplorer::V8HeapExplorer( |
1639 HeapSnapshot* snapshot, | 1693 HeapSnapshot* snapshot, |
1640 SnapshottingProgressReportingInterface* progress) | 1694 SnapshottingProgressReportingInterface* progress) |
1641 : snapshot_(snapshot), | 1695 : snapshot_(snapshot), |
1642 collection_(snapshot_->collection()), | 1696 collection_(snapshot_->collection()), |
1643 progress_(progress), | 1697 progress_(progress), |
1644 filler_(NULL) { | 1698 filler_(NULL) { |
1645 } | 1699 } |
(...skipping 16 matching lines...) Expand all Loading... |
1662 if (object == kInternalRootObject) { | 1716 if (object == kInternalRootObject) { |
1663 ASSERT(retainers_count == 0); | 1717 ASSERT(retainers_count == 0); |
1664 return snapshot_->AddRootEntry(children_count); | 1718 return snapshot_->AddRootEntry(children_count); |
1665 } else if (object == kGcRootsObject) { | 1719 } else if (object == kGcRootsObject) { |
1666 return snapshot_->AddGcRootsEntry(children_count, retainers_count); | 1720 return snapshot_->AddGcRootsEntry(children_count, retainers_count); |
1667 } else if (object->IsJSFunction()) { | 1721 } else if (object->IsJSFunction()) { |
1668 JSFunction* func = JSFunction::cast(object); | 1722 JSFunction* func = JSFunction::cast(object); |
1669 SharedFunctionInfo* shared = func->shared(); | 1723 SharedFunctionInfo* shared = func->shared(); |
1670 return AddEntry(object, | 1724 return AddEntry(object, |
1671 HeapEntry::kClosure, | 1725 HeapEntry::kClosure, |
1672 collection_->GetName(String::cast(shared->name())), | 1726 collection_->names()->GetName(String::cast(shared->name())), |
1673 children_count, | 1727 children_count, |
1674 retainers_count); | 1728 retainers_count); |
1675 } else if (object->IsJSRegExp()) { | 1729 } else if (object->IsJSRegExp()) { |
1676 JSRegExp* re = JSRegExp::cast(object); | 1730 JSRegExp* re = JSRegExp::cast(object); |
1677 return AddEntry(object, | 1731 return AddEntry(object, |
1678 HeapEntry::kRegExp, | 1732 HeapEntry::kRegExp, |
1679 collection_->GetName(re->Pattern()), | 1733 collection_->names()->GetName(re->Pattern()), |
1680 children_count, | 1734 children_count, |
1681 retainers_count); | 1735 retainers_count); |
1682 } else if (object->IsJSObject()) { | 1736 } else if (object->IsJSObject()) { |
1683 return AddEntry(object, | 1737 return AddEntry(object, |
1684 HeapEntry::kObject, | 1738 HeapEntry::kObject, |
1685 collection_->GetName(GetConstructorNameForHeapProfile( | 1739 collection_->names()->GetName( |
1686 JSObject::cast(object))), | 1740 GetConstructorNameForHeapProfile( |
| 1741 JSObject::cast(object))), |
1687 children_count, | 1742 children_count, |
1688 retainers_count); | 1743 retainers_count); |
1689 } else if (object->IsString()) { | 1744 } else if (object->IsString()) { |
1690 return AddEntry(object, | 1745 return AddEntry(object, |
1691 HeapEntry::kString, | 1746 HeapEntry::kString, |
1692 collection_->GetName(String::cast(object)), | 1747 collection_->names()->GetName(String::cast(object)), |
1693 children_count, | 1748 children_count, |
1694 retainers_count); | 1749 retainers_count); |
1695 } else if (object->IsCode()) { | 1750 } else if (object->IsCode()) { |
1696 return AddEntry(object, | 1751 return AddEntry(object, |
1697 HeapEntry::kCode, | 1752 HeapEntry::kCode, |
1698 "", | 1753 "", |
1699 children_count, | 1754 children_count, |
1700 retainers_count); | 1755 retainers_count); |
1701 } else if (object->IsSharedFunctionInfo()) { | 1756 } else if (object->IsSharedFunctionInfo()) { |
1702 SharedFunctionInfo* shared = SharedFunctionInfo::cast(object); | 1757 SharedFunctionInfo* shared = SharedFunctionInfo::cast(object); |
1703 return AddEntry(object, | 1758 return AddEntry(object, |
1704 HeapEntry::kCode, | 1759 HeapEntry::kCode, |
1705 collection_->GetName(String::cast(shared->name())), | 1760 collection_->names()->GetName(String::cast(shared->name())), |
1706 children_count, | 1761 children_count, |
1707 retainers_count); | 1762 retainers_count); |
1708 } else if (object->IsScript()) { | 1763 } else if (object->IsScript()) { |
1709 Script* script = Script::cast(object); | 1764 Script* script = Script::cast(object); |
1710 return AddEntry(object, | 1765 return AddEntry(object, |
1711 HeapEntry::kCode, | 1766 HeapEntry::kCode, |
1712 script->name()->IsString() ? | 1767 script->name()->IsString() ? |
1713 collection_->GetName(String::cast(script->name())) : "", | 1768 collection_->names()->GetName( |
| 1769 String::cast(script->name())) |
| 1770 : "", |
1714 children_count, | 1771 children_count, |
1715 retainers_count); | 1772 retainers_count); |
1716 } else if (object->IsFixedArray()) { | 1773 } else if (object->IsFixedArray()) { |
1717 return AddEntry(object, | 1774 return AddEntry(object, |
1718 HeapEntry::kArray, | 1775 HeapEntry::kArray, |
1719 "", | 1776 "", |
1720 children_count, | 1777 children_count, |
1721 retainers_count); | 1778 retainers_count); |
1722 } else if (object->IsHeapNumber()) { | 1779 } else if (object->IsHeapNumber()) { |
1723 return AddEntry(object, | 1780 return AddEntry(object, |
(...skipping 18 matching lines...) Expand all Loading... |
1742 return snapshot_->AddEntry(type, | 1799 return snapshot_->AddEntry(type, |
1743 name, | 1800 name, |
1744 collection_->GetObjectId(object->address()), | 1801 collection_->GetObjectId(object->address()), |
1745 object->Size(), | 1802 object->Size(), |
1746 children_count, | 1803 children_count, |
1747 retainers_count); | 1804 retainers_count); |
1748 } | 1805 } |
1749 | 1806 |
1750 | 1807 |
1751 void V8HeapExplorer::AddRootEntries(SnapshotFillerInterface* filler) { | 1808 void V8HeapExplorer::AddRootEntries(SnapshotFillerInterface* filler) { |
1752 filler->AddEntry(kInternalRootObject); | 1809 filler->AddEntry(kInternalRootObject, this); |
1753 filler->AddEntry(kGcRootsObject); | 1810 filler->AddEntry(kGcRootsObject, this); |
1754 } | 1811 } |
1755 | 1812 |
1756 | 1813 |
1757 int V8HeapExplorer::EstimateObjectsCount() { | 1814 int V8HeapExplorer::EstimateObjectsCount() { |
1758 HeapIterator iterator(HeapIterator::kFilterUnreachable); | 1815 HeapIterator iterator(HeapIterator::kFilterUnreachable); |
1759 int objects_count = 0; | 1816 int objects_count = 0; |
1760 for (HeapObject* obj = iterator.next(); | 1817 for (HeapObject* obj = iterator.next(); |
1761 obj != NULL; | 1818 obj != NULL; |
1762 obj = iterator.next(), ++objects_count) {} | 1819 obj = iterator.next(), ++objects_count) {} |
1763 return objects_count; | 1820 return objects_count; |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1933 int length = js_obj->GetInternalFieldCount(); | 1990 int length = js_obj->GetInternalFieldCount(); |
1934 for (int i = 0; i < length; ++i) { | 1991 for (int i = 0; i < length; ++i) { |
1935 Object* o = js_obj->GetInternalField(i); | 1992 Object* o = js_obj->GetInternalField(i); |
1936 SetInternalReference(js_obj, entry, i, o); | 1993 SetInternalReference(js_obj, entry, i, o); |
1937 } | 1994 } |
1938 } | 1995 } |
1939 | 1996 |
1940 | 1997 |
1941 HeapEntry* V8HeapExplorer::GetEntry(Object* obj) { | 1998 HeapEntry* V8HeapExplorer::GetEntry(Object* obj) { |
1942 if (!obj->IsHeapObject()) return NULL; | 1999 if (!obj->IsHeapObject()) return NULL; |
1943 return filler_->FindOrAddEntry(obj); | 2000 return filler_->FindOrAddEntry(obj, this); |
1944 } | 2001 } |
1945 | 2002 |
1946 | 2003 |
1947 class RootsReferencesExtractor : public ObjectVisitor { | 2004 class RootsReferencesExtractor : public ObjectVisitor { |
1948 public: | 2005 public: |
1949 explicit RootsReferencesExtractor(V8HeapExplorer* explorer) | 2006 explicit RootsReferencesExtractor(V8HeapExplorer* explorer) |
1950 : explorer_(explorer) { | 2007 : explorer_(explorer) { |
1951 } | 2008 } |
1952 void VisitPointers(Object** start, Object** end) { | 2009 void VisitPointers(Object** start, Object** end) { |
1953 for (Object** p = start; p < end; p++) explorer_->SetGcRootsReference(*p); | 2010 for (Object** p = start; p < end; p++) explorer_->SetGcRootsReference(*p); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1985 | 2042 |
1986 void V8HeapExplorer::SetClosureReference(HeapObject* parent_obj, | 2043 void V8HeapExplorer::SetClosureReference(HeapObject* parent_obj, |
1987 HeapEntry* parent_entry, | 2044 HeapEntry* parent_entry, |
1988 String* reference_name, | 2045 String* reference_name, |
1989 Object* child_obj) { | 2046 Object* child_obj) { |
1990 HeapEntry* child_entry = GetEntry(child_obj); | 2047 HeapEntry* child_entry = GetEntry(child_obj); |
1991 if (child_entry != NULL) { | 2048 if (child_entry != NULL) { |
1992 filler_->SetNamedReference(HeapGraphEdge::kContextVariable, | 2049 filler_->SetNamedReference(HeapGraphEdge::kContextVariable, |
1993 parent_obj, | 2050 parent_obj, |
1994 parent_entry, | 2051 parent_entry, |
1995 collection_->GetName(reference_name), | 2052 collection_->names()->GetName(reference_name), |
1996 child_obj, | 2053 child_obj, |
1997 child_entry); | 2054 child_entry); |
1998 known_references_.Insert(child_obj); | 2055 known_references_.Insert(child_obj); |
1999 } | 2056 } |
2000 } | 2057 } |
2001 | 2058 |
2002 | 2059 |
2003 void V8HeapExplorer::SetElementReference(HeapObject* parent_obj, | 2060 void V8HeapExplorer::SetElementReference(HeapObject* parent_obj, |
2004 HeapEntry* parent_entry, | 2061 HeapEntry* parent_entry, |
2005 int index, | 2062 int index, |
(...skipping 30 matching lines...) Expand all Loading... |
2036 | 2093 |
2037 void V8HeapExplorer::SetInternalReference(HeapObject* parent_obj, | 2094 void V8HeapExplorer::SetInternalReference(HeapObject* parent_obj, |
2038 HeapEntry* parent_entry, | 2095 HeapEntry* parent_entry, |
2039 int index, | 2096 int index, |
2040 Object* child_obj) { | 2097 Object* child_obj) { |
2041 HeapEntry* child_entry = GetEntry(child_obj); | 2098 HeapEntry* child_entry = GetEntry(child_obj); |
2042 if (child_entry != NULL) { | 2099 if (child_entry != NULL) { |
2043 filler_->SetNamedReference(HeapGraphEdge::kInternal, | 2100 filler_->SetNamedReference(HeapGraphEdge::kInternal, |
2044 parent_obj, | 2101 parent_obj, |
2045 parent_entry, | 2102 parent_entry, |
2046 collection_->GetName(index), | 2103 collection_->names()->GetName(index), |
2047 child_obj, | 2104 child_obj, |
2048 child_entry); | 2105 child_entry); |
2049 known_references_.Insert(child_obj); | 2106 known_references_.Insert(child_obj); |
2050 } | 2107 } |
2051 } | 2108 } |
2052 | 2109 |
2053 | 2110 |
2054 void V8HeapExplorer::SetHiddenReference(HeapObject* parent_obj, | 2111 void V8HeapExplorer::SetHiddenReference(HeapObject* parent_obj, |
2055 HeapEntry* parent_entry, | 2112 HeapEntry* parent_entry, |
2056 int index, | 2113 int index, |
(...skipping 14 matching lines...) Expand all Loading... |
2071 HeapEntry* parent_entry, | 2128 HeapEntry* parent_entry, |
2072 String* reference_name, | 2129 String* reference_name, |
2073 Object* child_obj) { | 2130 Object* child_obj) { |
2074 HeapEntry* child_entry = GetEntry(child_obj); | 2131 HeapEntry* child_entry = GetEntry(child_obj); |
2075 if (child_entry != NULL) { | 2132 if (child_entry != NULL) { |
2076 HeapGraphEdge::Type type = reference_name->length() > 0 ? | 2133 HeapGraphEdge::Type type = reference_name->length() > 0 ? |
2077 HeapGraphEdge::kProperty : HeapGraphEdge::kInternal; | 2134 HeapGraphEdge::kProperty : HeapGraphEdge::kInternal; |
2078 filler_->SetNamedReference(type, | 2135 filler_->SetNamedReference(type, |
2079 parent_obj, | 2136 parent_obj, |
2080 parent_entry, | 2137 parent_entry, |
2081 collection_->GetName(reference_name), | 2138 collection_->names()->GetName(reference_name), |
2082 child_obj, | 2139 child_obj, |
2083 child_entry); | 2140 child_entry); |
2084 known_references_.Insert(child_obj); | 2141 known_references_.Insert(child_obj); |
2085 } | 2142 } |
2086 } | 2143 } |
2087 | 2144 |
2088 | 2145 |
2089 void V8HeapExplorer::SetPropertyShortcutReference( | 2146 void V8HeapExplorer::SetPropertyShortcutReference( |
2090 HeapObject* parent_obj, | 2147 HeapObject* parent_obj, |
2091 HeapEntry* parent_entry, | 2148 HeapEntry* parent_entry, |
2092 String* reference_name, | 2149 String* reference_name, |
2093 Object* child_obj) { | 2150 Object* child_obj) { |
2094 HeapEntry* child_entry = GetEntry(child_obj); | 2151 HeapEntry* child_entry = GetEntry(child_obj); |
2095 if (child_entry != NULL) { | 2152 if (child_entry != NULL) { |
2096 filler_->SetNamedReference(HeapGraphEdge::kShortcut, | 2153 filler_->SetNamedReference(HeapGraphEdge::kShortcut, |
2097 parent_obj, | 2154 parent_obj, |
2098 parent_entry, | 2155 parent_entry, |
2099 collection_->GetName(reference_name), | 2156 collection_->names()->GetName(reference_name), |
2100 child_obj, | 2157 child_obj, |
2101 child_entry); | 2158 child_entry); |
2102 } | 2159 } |
2103 } | 2160 } |
2104 | 2161 |
2105 | 2162 |
2106 void V8HeapExplorer::SetRootGcRootsReference() { | 2163 void V8HeapExplorer::SetRootGcRootsReference() { |
2107 filler_->SetIndexedAutoIndexReference( | 2164 filler_->SetIndexedAutoIndexReference( |
2108 HeapGraphEdge::kElement, | 2165 HeapGraphEdge::kElement, |
2109 kInternalRootObject, snapshot_->root(), | 2166 kInternalRootObject, snapshot_->root(), |
(...skipping 15 matching lines...) Expand all Loading... |
2125 HeapEntry* child_entry = GetEntry(child_obj); | 2182 HeapEntry* child_entry = GetEntry(child_obj); |
2126 if (child_entry != NULL) { | 2183 if (child_entry != NULL) { |
2127 filler_->SetIndexedAutoIndexReference( | 2184 filler_->SetIndexedAutoIndexReference( |
2128 HeapGraphEdge::kElement, | 2185 HeapGraphEdge::kElement, |
2129 kGcRootsObject, snapshot_->gc_roots(), | 2186 kGcRootsObject, snapshot_->gc_roots(), |
2130 child_obj, child_entry); | 2187 child_obj, child_entry); |
2131 } | 2188 } |
2132 } | 2189 } |
2133 | 2190 |
2134 | 2191 |
| 2192 class GlobalHandlesExtractor : public ObjectVisitor { |
| 2193 public: |
| 2194 explicit GlobalHandlesExtractor(NativeObjectsExplorer* explorer) |
| 2195 : explorer_(explorer) {} |
| 2196 virtual ~GlobalHandlesExtractor() {} |
| 2197 virtual void VisitPointers(Object** start, Object** end) { |
| 2198 UNREACHABLE(); |
| 2199 } |
| 2200 virtual void VisitEmbedderReference(Object** p, uint16_t class_id) { |
| 2201 explorer_->VisitSubtreeWrapper(p, class_id); |
| 2202 } |
| 2203 private: |
| 2204 NativeObjectsExplorer* explorer_; |
| 2205 }; |
| 2206 |
| 2207 HeapThing const NativeObjectsExplorer::kNativesRootObject = |
| 2208 reinterpret_cast<HeapThing>( |
| 2209 static_cast<intptr_t>(HeapObjectsMap::kNativesRootObjectId)); |
| 2210 |
| 2211 |
| 2212 NativeObjectsExplorer::NativeObjectsExplorer( |
| 2213 HeapSnapshot* snapshot, SnapshottingProgressReportingInterface* progress) |
| 2214 : snapshot_(snapshot), |
| 2215 collection_(snapshot_->collection()), |
| 2216 progress_(progress), |
| 2217 embedder_queried_(false), |
| 2218 objects_by_info_(RetainedInfosMatch), |
| 2219 filler_(NULL) { |
| 2220 } |
| 2221 |
| 2222 |
| 2223 NativeObjectsExplorer::~NativeObjectsExplorer() { |
| 2224 for (HashMap::Entry* p = objects_by_info_.Start(); |
| 2225 p != NULL; |
| 2226 p = objects_by_info_.Next(p)) { |
| 2227 v8::RetainedObjectInfo* info = |
| 2228 reinterpret_cast<v8::RetainedObjectInfo*>(p->key); |
| 2229 info->Dispose(); |
| 2230 List<HeapObject*>* objects = |
| 2231 reinterpret_cast<List<HeapObject*>* >(p->value); |
| 2232 delete objects; |
| 2233 } |
| 2234 } |
| 2235 |
| 2236 |
| 2237 HeapEntry* NativeObjectsExplorer::AllocateEntry( |
| 2238 HeapThing ptr, int children_count, int retainers_count) { |
| 2239 if (ptr == kNativesRootObject) { |
| 2240 return snapshot_->AddNativesRootEntry(children_count, retainers_count); |
| 2241 } else { |
| 2242 v8::RetainedObjectInfo* info = |
| 2243 reinterpret_cast<v8::RetainedObjectInfo*>(ptr); |
| 2244 intptr_t elements = info->GetElementCount(); |
| 2245 intptr_t size = info->GetSizeInBytes(); |
| 2246 return snapshot_->AddEntry( |
| 2247 HeapEntry::kNative, |
| 2248 elements != -1 ? |
| 2249 collection_->names()->GetFormatted( |
| 2250 "%s / %" V8_PTR_PREFIX "d entries", |
| 2251 info->GetLabel(), |
| 2252 info->GetElementCount()) : |
| 2253 collection_->names()->GetCopy(info->GetLabel()), |
| 2254 HeapObjectsMap::GenerateId(info), |
| 2255 size != -1 ? static_cast<int>(size) : 0, |
| 2256 children_count, |
| 2257 retainers_count); |
| 2258 } |
| 2259 } |
| 2260 |
| 2261 |
| 2262 void NativeObjectsExplorer::AddRootEntries(SnapshotFillerInterface* filler) { |
| 2263 if (EstimateObjectsCount() <= 0) return; |
| 2264 filler->AddEntry(kNativesRootObject, this); |
| 2265 } |
| 2266 |
| 2267 |
| 2268 int NativeObjectsExplorer::EstimateObjectsCount() { |
| 2269 FillRetainedObjects(); |
| 2270 return objects_by_info_.occupancy(); |
| 2271 } |
| 2272 |
| 2273 |
| 2274 void NativeObjectsExplorer::FillRetainedObjects() { |
| 2275 if (embedder_queried_) return; |
| 2276 // Record objects that are joined into ObjectGroups. |
| 2277 Heap::CallGlobalGCPrologueCallback(); |
| 2278 List<ObjectGroup*>* groups = GlobalHandles::ObjectGroups(); |
| 2279 for (int i = 0; i < groups->length(); ++i) { |
| 2280 ObjectGroup* group = groups->at(i); |
| 2281 if (group->info_ == NULL) continue; |
| 2282 List<HeapObject*>* list = GetListMaybeDisposeInfo(group->info_); |
| 2283 for (int j = 0; j < group->objects_.length(); ++j) { |
| 2284 HeapObject* obj = HeapObject::cast(*group->objects_[j]); |
| 2285 list->Add(obj); |
| 2286 in_groups_.Insert(obj); |
| 2287 } |
| 2288 group->info_ = NULL; // Acquire info object ownership. |
| 2289 } |
| 2290 GlobalHandles::RemoveObjectGroups(); |
| 2291 Heap::CallGlobalGCEpilogueCallback(); |
| 2292 // Record objects that are not in ObjectGroups, but have class ID. |
| 2293 GlobalHandlesExtractor extractor(this); |
| 2294 GlobalHandles::IterateAllRootsWithClassIds(&extractor); |
| 2295 embedder_queried_ = true; |
| 2296 } |
| 2297 |
| 2298 |
| 2299 List<HeapObject*>* NativeObjectsExplorer::GetListMaybeDisposeInfo( |
| 2300 v8::RetainedObjectInfo* info) { |
| 2301 HashMap::Entry* entry = |
| 2302 objects_by_info_.Lookup(info, InfoHash(info), true); |
| 2303 if (entry->value != NULL) { |
| 2304 info->Dispose(); |
| 2305 } else { |
| 2306 entry->value = new List<HeapObject*>(4); |
| 2307 } |
| 2308 return reinterpret_cast<List<HeapObject*>* >(entry->value); |
| 2309 } |
| 2310 |
| 2311 |
| 2312 bool NativeObjectsExplorer::IterateAndExtractReferences( |
| 2313 SnapshotFillerInterface* filler) { |
| 2314 if (EstimateObjectsCount() <= 0) return true; |
| 2315 filler_ = filler; |
| 2316 FillRetainedObjects(); |
| 2317 for (HashMap::Entry* p = objects_by_info_.Start(); |
| 2318 p != NULL; |
| 2319 p = objects_by_info_.Next(p)) { |
| 2320 v8::RetainedObjectInfo* info = |
| 2321 reinterpret_cast<v8::RetainedObjectInfo*>(p->key); |
| 2322 SetNativeRootReference(info); |
| 2323 List<HeapObject*>* objects = |
| 2324 reinterpret_cast<List<HeapObject*>* >(p->value); |
| 2325 for (int i = 0; i < objects->length(); ++i) { |
| 2326 SetWrapperNativeReferences(objects->at(i), info); |
| 2327 } |
| 2328 } |
| 2329 SetRootNativesRootReference(); |
| 2330 filler_ = NULL; |
| 2331 return true; |
| 2332 } |
| 2333 |
| 2334 |
| 2335 void NativeObjectsExplorer::SetNativeRootReference( |
| 2336 v8::RetainedObjectInfo* info) { |
| 2337 HeapEntry* child_entry = filler_->FindOrAddEntry(info, this); |
| 2338 ASSERT(child_entry != NULL); |
| 2339 filler_->SetIndexedAutoIndexReference( |
| 2340 HeapGraphEdge::kElement, |
| 2341 kNativesRootObject, snapshot_->dom_subtrees_root(), |
| 2342 info, child_entry); |
| 2343 } |
| 2344 |
| 2345 |
| 2346 void NativeObjectsExplorer::SetWrapperNativeReferences( |
| 2347 HeapObject* wrapper, v8::RetainedObjectInfo* info) { |
| 2348 HeapEntry* wrapper_entry = filler_->FindEntry(wrapper); |
| 2349 ASSERT(wrapper_entry != NULL); |
| 2350 HeapEntry* info_entry = filler_->FindOrAddEntry(info, this); |
| 2351 ASSERT(info_entry != NULL); |
| 2352 filler_->SetNamedReference(HeapGraphEdge::kInternal, |
| 2353 wrapper, wrapper_entry, |
| 2354 "Native", |
| 2355 info, info_entry); |
| 2356 filler_->SetIndexedAutoIndexReference(HeapGraphEdge::kElement, |
| 2357 info, info_entry, |
| 2358 wrapper, wrapper_entry); |
| 2359 } |
| 2360 |
| 2361 |
| 2362 void NativeObjectsExplorer::SetRootNativesRootReference() { |
| 2363 filler_->SetIndexedAutoIndexReference( |
| 2364 HeapGraphEdge::kElement, |
| 2365 V8HeapExplorer::kInternalRootObject, snapshot_->root(), |
| 2366 kNativesRootObject, snapshot_->dom_subtrees_root()); |
| 2367 } |
| 2368 |
| 2369 |
| 2370 void NativeObjectsExplorer::VisitSubtreeWrapper(Object** p, uint16_t class_id) { |
| 2371 if (in_groups_.Contains(*p)) return; |
| 2372 v8::RetainedObjectInfo* info = |
| 2373 HeapProfiler::ExecuteWrapperClassCallback(class_id, p); |
| 2374 if (info == NULL) return; |
| 2375 GetListMaybeDisposeInfo(info)->Add(HeapObject::cast(*p)); |
| 2376 } |
| 2377 |
| 2378 |
2135 HeapSnapshotGenerator::HeapSnapshotGenerator(HeapSnapshot* snapshot, | 2379 HeapSnapshotGenerator::HeapSnapshotGenerator(HeapSnapshot* snapshot, |
2136 v8::ActivityControl* control) | 2380 v8::ActivityControl* control) |
2137 : snapshot_(snapshot), | 2381 : snapshot_(snapshot), |
2138 control_(control), | 2382 control_(control), |
2139 v8_heap_explorer_(snapshot_, this) { | 2383 v8_heap_explorer_(snapshot_, this), |
| 2384 dom_explorer_(snapshot_, this) { |
2140 } | 2385 } |
2141 | 2386 |
2142 | 2387 |
2143 class SnapshotCounter : public SnapshotFillerInterface { | 2388 class SnapshotCounter : public SnapshotFillerInterface { |
2144 public: | 2389 public: |
2145 SnapshotCounter(HeapEntriesAllocator* allocator, HeapEntriesMap* entries) | 2390 explicit SnapshotCounter(HeapEntriesMap* entries) : entries_(entries) { } |
2146 : allocator_(allocator), entries_(entries) { } | 2391 HeapEntry* AddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) { |
2147 HeapEntry* AddEntry(HeapThing ptr) { | 2392 entries_->Pair(ptr, allocator, HeapEntriesMap::kHeapEntryPlaceholder); |
2148 entries_->Pair(ptr, allocator_, HeapEntriesMap::kHeapEntryPlaceholder); | |
2149 return HeapEntriesMap::kHeapEntryPlaceholder; | 2393 return HeapEntriesMap::kHeapEntryPlaceholder; |
2150 } | 2394 } |
2151 HeapEntry* FindOrAddEntry(HeapThing ptr) { | 2395 HeapEntry* FindEntry(HeapThing ptr) { |
2152 HeapEntry* entry = entries_->Map(ptr); | 2396 return entries_->Map(ptr); |
2153 return entry != NULL ? entry : AddEntry(ptr); | 2397 } |
| 2398 HeapEntry* FindOrAddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) { |
| 2399 HeapEntry* entry = FindEntry(ptr); |
| 2400 return entry != NULL ? entry : AddEntry(ptr, allocator); |
2154 } | 2401 } |
2155 void SetIndexedReference(HeapGraphEdge::Type, | 2402 void SetIndexedReference(HeapGraphEdge::Type, |
2156 HeapThing parent_ptr, | 2403 HeapThing parent_ptr, |
2157 HeapEntry*, | 2404 HeapEntry*, |
2158 int, | 2405 int, |
2159 HeapThing child_ptr, | 2406 HeapThing child_ptr, |
2160 HeapEntry*) { | 2407 HeapEntry*) { |
2161 entries_->CountReference(parent_ptr, child_ptr); | 2408 entries_->CountReference(parent_ptr, child_ptr); |
2162 } | 2409 } |
2163 void SetIndexedAutoIndexReference(HeapGraphEdge::Type, | 2410 void SetIndexedAutoIndexReference(HeapGraphEdge::Type, |
(...skipping 12 matching lines...) Expand all Loading... |
2176 entries_->CountReference(parent_ptr, child_ptr); | 2423 entries_->CountReference(parent_ptr, child_ptr); |
2177 } | 2424 } |
2178 void SetNamedAutoIndexReference(HeapGraphEdge::Type, | 2425 void SetNamedAutoIndexReference(HeapGraphEdge::Type, |
2179 HeapThing parent_ptr, | 2426 HeapThing parent_ptr, |
2180 HeapEntry*, | 2427 HeapEntry*, |
2181 HeapThing child_ptr, | 2428 HeapThing child_ptr, |
2182 HeapEntry*) { | 2429 HeapEntry*) { |
2183 entries_->CountReference(parent_ptr, child_ptr); | 2430 entries_->CountReference(parent_ptr, child_ptr); |
2184 } | 2431 } |
2185 private: | 2432 private: |
2186 HeapEntriesAllocator* allocator_; | |
2187 HeapEntriesMap* entries_; | 2433 HeapEntriesMap* entries_; |
2188 }; | 2434 }; |
2189 | 2435 |
2190 | 2436 |
2191 class SnapshotFiller : public SnapshotFillerInterface { | 2437 class SnapshotFiller : public SnapshotFillerInterface { |
2192 public: | 2438 public: |
2193 explicit SnapshotFiller(HeapSnapshot* snapshot, HeapEntriesMap* entries) | 2439 explicit SnapshotFiller(HeapSnapshot* snapshot, HeapEntriesMap* entries) |
2194 : snapshot_(snapshot), | 2440 : snapshot_(snapshot), |
2195 collection_(snapshot->collection()), | 2441 collection_(snapshot->collection()), |
2196 entries_(entries) { } | 2442 entries_(entries) { } |
2197 HeapEntry* AddEntry(HeapThing ptr) { | 2443 HeapEntry* AddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) { |
2198 UNREACHABLE(); | 2444 UNREACHABLE(); |
2199 return NULL; | 2445 return NULL; |
2200 } | 2446 } |
2201 HeapEntry* FindOrAddEntry(HeapThing ptr) { | 2447 HeapEntry* FindEntry(HeapThing ptr) { |
2202 HeapEntry* entry = entries_->Map(ptr); | 2448 return entries_->Map(ptr); |
2203 return entry != NULL ? entry : AddEntry(ptr); | 2449 } |
| 2450 HeapEntry* FindOrAddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) { |
| 2451 HeapEntry* entry = FindEntry(ptr); |
| 2452 return entry != NULL ? entry : AddEntry(ptr, allocator); |
2204 } | 2453 } |
2205 void SetIndexedReference(HeapGraphEdge::Type type, | 2454 void SetIndexedReference(HeapGraphEdge::Type type, |
2206 HeapThing parent_ptr, | 2455 HeapThing parent_ptr, |
2207 HeapEntry* parent_entry, | 2456 HeapEntry* parent_entry, |
2208 int index, | 2457 int index, |
2209 HeapThing child_ptr, | 2458 HeapThing child_ptr, |
2210 HeapEntry* child_entry) { | 2459 HeapEntry* child_entry) { |
2211 int child_index, retainer_index; | 2460 int child_index, retainer_index; |
2212 entries_->CountReference( | 2461 entries_->CountReference( |
2213 parent_ptr, child_ptr, &child_index, &retainer_index); | 2462 parent_ptr, child_ptr, &child_index, &retainer_index); |
(...skipping 26 matching lines...) Expand all Loading... |
2240 void SetNamedAutoIndexReference(HeapGraphEdge::Type type, | 2489 void SetNamedAutoIndexReference(HeapGraphEdge::Type type, |
2241 HeapThing parent_ptr, | 2490 HeapThing parent_ptr, |
2242 HeapEntry* parent_entry, | 2491 HeapEntry* parent_entry, |
2243 HeapThing child_ptr, | 2492 HeapThing child_ptr, |
2244 HeapEntry* child_entry) { | 2493 HeapEntry* child_entry) { |
2245 int child_index, retainer_index; | 2494 int child_index, retainer_index; |
2246 entries_->CountReference( | 2495 entries_->CountReference( |
2247 parent_ptr, child_ptr, &child_index, &retainer_index); | 2496 parent_ptr, child_ptr, &child_index, &retainer_index); |
2248 parent_entry->SetNamedReference(type, | 2497 parent_entry->SetNamedReference(type, |
2249 child_index, | 2498 child_index, |
2250 collection_->GetName(child_index + 1), | 2499 collection_->names()->GetName(child_index + 1), |
2251 child_entry, | 2500 child_entry, |
2252 retainer_index); | 2501 retainer_index); |
2253 } | 2502 } |
2254 private: | 2503 private: |
2255 HeapSnapshot* snapshot_; | 2504 HeapSnapshot* snapshot_; |
2256 HeapSnapshotsCollection* collection_; | 2505 HeapSnapshotsCollection* collection_; |
2257 HeapEntriesMap* entries_; | 2506 HeapEntriesMap* entries_; |
2258 }; | 2507 }; |
2259 | 2508 |
2260 | 2509 |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2296 return | 2545 return |
2297 control_->ReportProgressValue(progress_counter_, progress_total_) == | 2546 control_->ReportProgressValue(progress_counter_, progress_total_) == |
2298 v8::ActivityControl::kContinue; | 2547 v8::ActivityControl::kContinue; |
2299 } | 2548 } |
2300 return true; | 2549 return true; |
2301 } | 2550 } |
2302 | 2551 |
2303 | 2552 |
2304 void HeapSnapshotGenerator::SetProgressTotal(int iterations_count) { | 2553 void HeapSnapshotGenerator::SetProgressTotal(int iterations_count) { |
2305 if (control_ == NULL) return; | 2554 if (control_ == NULL) return; |
2306 progress_total_ = v8_heap_explorer_.EstimateObjectsCount() * iterations_count; | 2555 progress_total_ = ( |
| 2556 v8_heap_explorer_.EstimateObjectsCount() + |
| 2557 dom_explorer_.EstimateObjectsCount()) * iterations_count; |
2307 progress_counter_ = 0; | 2558 progress_counter_ = 0; |
2308 } | 2559 } |
2309 | 2560 |
2310 | 2561 |
2311 bool HeapSnapshotGenerator::CountEntriesAndReferences() { | 2562 bool HeapSnapshotGenerator::CountEntriesAndReferences() { |
2312 SnapshotCounter counter(&v8_heap_explorer_, &entries_); | 2563 SnapshotCounter counter(&entries_); |
2313 v8_heap_explorer_.AddRootEntries(&counter); | 2564 v8_heap_explorer_.AddRootEntries(&counter); |
2314 return v8_heap_explorer_.IterateAndExtractReferences(&counter); | 2565 dom_explorer_.AddRootEntries(&counter); |
| 2566 return |
| 2567 v8_heap_explorer_.IterateAndExtractReferences(&counter) && |
| 2568 dom_explorer_.IterateAndExtractReferences(&counter); |
2315 } | 2569 } |
2316 | 2570 |
2317 | 2571 |
2318 bool HeapSnapshotGenerator::FillReferences() { | 2572 bool HeapSnapshotGenerator::FillReferences() { |
2319 SnapshotFiller filler(snapshot_, &entries_); | 2573 SnapshotFiller filler(snapshot_, &entries_); |
2320 return v8_heap_explorer_.IterateAndExtractReferences(&filler); | 2574 return |
| 2575 v8_heap_explorer_.IterateAndExtractReferences(&filler) && |
| 2576 dom_explorer_.IterateAndExtractReferences(&filler); |
2321 } | 2577 } |
2322 | 2578 |
2323 | 2579 |
2324 void HeapSnapshotGenerator::FillReversePostorderIndexes( | 2580 void HeapSnapshotGenerator::FillReversePostorderIndexes( |
2325 Vector<HeapEntry*>* entries) { | 2581 Vector<HeapEntry*>* entries) { |
2326 snapshot_->ClearPaint(); | 2582 snapshot_->ClearPaint(); |
2327 int current_entry = 0; | 2583 int current_entry = 0; |
2328 List<HeapEntry*> nodes_to_visit; | 2584 List<HeapEntry*> nodes_to_visit; |
2329 nodes_to_visit.Add(snapshot_->root()); | 2585 nodes_to_visit.Add(snapshot_->root()); |
2330 snapshot_->root()->paint_reachable(); | 2586 snapshot_->root()->paint_reachable(); |
(...skipping 397 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2728 "," JSON_S("children")) | 2984 "," JSON_S("children")) |
2729 "," JSON_S("types") ":" JSON_A( | 2985 "," JSON_S("types") ":" JSON_A( |
2730 JSON_A( | 2986 JSON_A( |
2731 JSON_S("hidden") | 2987 JSON_S("hidden") |
2732 "," JSON_S("array") | 2988 "," JSON_S("array") |
2733 "," JSON_S("string") | 2989 "," JSON_S("string") |
2734 "," JSON_S("object") | 2990 "," JSON_S("object") |
2735 "," JSON_S("code") | 2991 "," JSON_S("code") |
2736 "," JSON_S("closure") | 2992 "," JSON_S("closure") |
2737 "," JSON_S("regexp") | 2993 "," JSON_S("regexp") |
2738 "," JSON_S("number")) | 2994 "," JSON_S("number") |
| 2995 "," JSON_S("native")) |
2739 "," JSON_S("string") | 2996 "," JSON_S("string") |
2740 "," JSON_S("number") | 2997 "," JSON_S("number") |
2741 "," JSON_S("number") | 2998 "," JSON_S("number") |
2742 "," JSON_S("number") | 2999 "," JSON_S("number") |
2743 "," JSON_S("number") | 3000 "," JSON_S("number") |
2744 "," JSON_S("number") | 3001 "," JSON_S("number") |
2745 "," JSON_O( | 3002 "," JSON_O( |
2746 JSON_S("fields") ":" JSON_A( | 3003 JSON_S("fields") ":" JSON_A( |
2747 JSON_S("type") | 3004 JSON_S("type") |
2748 "," JSON_S("name_or_index") | 3005 "," JSON_S("name_or_index") |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2890 | 3147 |
2891 | 3148 |
2892 String* GetConstructorNameForHeapProfile(JSObject* object) { | 3149 String* GetConstructorNameForHeapProfile(JSObject* object) { |
2893 if (object->IsJSFunction()) return Heap::closure_symbol(); | 3150 if (object->IsJSFunction()) return Heap::closure_symbol(); |
2894 return object->constructor_name(); | 3151 return object->constructor_name(); |
2895 } | 3152 } |
2896 | 3153 |
2897 } } // namespace v8::internal | 3154 } } // namespace v8::internal |
2898 | 3155 |
2899 #endif // ENABLE_LOGGING_AND_PROFILING | 3156 #endif // ENABLE_LOGGING_AND_PROFILING |
OLD | NEW |