OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 920 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
931 || type == kInternal | 931 || type == kInternal |
932 || type == kShortcut); | 932 || type == kShortcut); |
933 child_index_ = child_index; | 933 child_index_ = child_index; |
934 type_ = type; | 934 type_ = type; |
935 name_ = name; | 935 name_ = name; |
936 to_ = to; | 936 to_ = to; |
937 } | 937 } |
938 | 938 |
939 | 939 |
940 void HeapGraphEdge::Init(int child_index, Type type, int index, HeapEntry* to) { | 940 void HeapGraphEdge::Init(int child_index, Type type, int index, HeapEntry* to) { |
941 ASSERT(type == kElement || type == kHidden); | 941 ASSERT(type == kElement || type == kHidden || type == kWeak); |
942 child_index_ = child_index; | 942 child_index_ = child_index; |
943 type_ = type; | 943 type_ = type; |
944 index_ = index; | 944 index_ = index; |
945 to_ = to; | 945 to_ = to; |
946 } | 946 } |
947 | 947 |
948 | 948 |
949 void HeapGraphEdge::Init(int child_index, int index, HeapEntry* to) { | 949 void HeapGraphEdge::Init(int child_index, int index, HeapEntry* to) { |
950 Init(child_index, kElement, index, to); | 950 Init(child_index, kElement, index, to); |
951 } | 951 } |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1046 public: | 1046 public: |
1047 void Apply(HeapEntry* entry) { } | 1047 void Apply(HeapEntry* entry) { } |
1048 }; | 1048 }; |
1049 | 1049 |
1050 void HeapEntry::PaintAllReachable() { | 1050 void HeapEntry::PaintAllReachable() { |
1051 NullClass null; | 1051 NullClass null; |
1052 ApplyAndPaintAllReachable(&null); | 1052 ApplyAndPaintAllReachable(&null); |
1053 } | 1053 } |
1054 | 1054 |
1055 | 1055 |
1056 void HeapEntry::Print(int max_depth, int indent) { | 1056 void HeapEntry::Print( |
1057 OS::Print("%6d %6d [%llu] ", self_size(), RetainedSize(false), id()); | 1057 const char* prefix, const char* edge_name, int max_depth, int indent) { |
| 1058 OS::Print("%6d %7d @%6llu %*c %s%s: ", |
| 1059 self_size(), RetainedSize(false), id(), |
| 1060 indent, ' ', prefix, edge_name); |
1058 if (type() != kString) { | 1061 if (type() != kString) { |
1059 OS::Print("%s %.40s\n", TypeAsString(), name_); | 1062 OS::Print("%s %.40s\n", TypeAsString(), name_); |
1060 } else { | 1063 } else { |
1061 OS::Print("\""); | 1064 OS::Print("\""); |
1062 const char* c = name_; | 1065 const char* c = name_; |
1063 while (*c && (c - name_) <= 40) { | 1066 while (*c && (c - name_) <= 40) { |
1064 if (*c != '\n') | 1067 if (*c != '\n') |
1065 OS::Print("%c", *c); | 1068 OS::Print("%c", *c); |
1066 else | 1069 else |
1067 OS::Print("\\n"); | 1070 OS::Print("\\n"); |
1068 ++c; | 1071 ++c; |
1069 } | 1072 } |
1070 OS::Print("\"\n"); | 1073 OS::Print("\"\n"); |
1071 } | 1074 } |
1072 if (--max_depth == 0) return; | 1075 if (--max_depth == 0) return; |
1073 Vector<HeapGraphEdge> ch = children(); | 1076 Vector<HeapGraphEdge> ch = children(); |
1074 for (int i = 0; i < ch.length(); ++i) { | 1077 for (int i = 0; i < ch.length(); ++i) { |
1075 HeapGraphEdge& edge = ch[i]; | 1078 HeapGraphEdge& edge = ch[i]; |
| 1079 const char* edge_prefix = ""; |
| 1080 ScopedVector<char> index(64); |
| 1081 const char* edge_name = index.start(); |
1076 switch (edge.type()) { | 1082 switch (edge.type()) { |
1077 case HeapGraphEdge::kContextVariable: | 1083 case HeapGraphEdge::kContextVariable: |
1078 OS::Print(" %*c #%s: ", indent, ' ', edge.name()); | 1084 edge_prefix = "#"; |
| 1085 edge_name = edge.name(); |
1079 break; | 1086 break; |
1080 case HeapGraphEdge::kElement: | 1087 case HeapGraphEdge::kElement: |
1081 OS::Print(" %*c %d: ", indent, ' ', edge.index()); | 1088 OS::SNPrintF(index, "%d", edge.index()); |
1082 break; | 1089 break; |
1083 case HeapGraphEdge::kInternal: | 1090 case HeapGraphEdge::kInternal: |
1084 OS::Print(" %*c $%s: ", indent, ' ', edge.name()); | 1091 edge_prefix = "$"; |
| 1092 edge_name = edge.name(); |
1085 break; | 1093 break; |
1086 case HeapGraphEdge::kProperty: | 1094 case HeapGraphEdge::kProperty: |
1087 OS::Print(" %*c %s: ", indent, ' ', edge.name()); | 1095 edge_name = edge.name(); |
1088 break; | 1096 break; |
1089 case HeapGraphEdge::kHidden: | 1097 case HeapGraphEdge::kHidden: |
1090 OS::Print(" %*c $%d: ", indent, ' ', edge.index()); | 1098 edge_prefix = "$"; |
| 1099 OS::SNPrintF(index, "%d", edge.index()); |
1091 break; | 1100 break; |
1092 case HeapGraphEdge::kShortcut: | 1101 case HeapGraphEdge::kShortcut: |
1093 OS::Print(" %*c ^%s: ", indent, ' ', edge.name()); | 1102 edge_prefix = "^"; |
| 1103 edge_name = edge.name(); |
| 1104 break; |
| 1105 case HeapGraphEdge::kWeak: |
| 1106 edge_prefix = "w"; |
| 1107 OS::SNPrintF(index, "%d", edge.index()); |
1094 break; | 1108 break; |
1095 default: | 1109 default: |
1096 OS::Print("!!! unknown edge type: %d ", edge.type()); | 1110 OS::SNPrintF(index, "!!! unknown edge type: %d ", edge.type()); |
1097 } | 1111 } |
1098 edge.to()->Print(max_depth, indent + 2); | 1112 edge.to()->Print(edge_prefix, edge_name, max_depth, indent + 2); |
1099 } | 1113 } |
1100 } | 1114 } |
1101 | 1115 |
1102 | 1116 |
1103 const char* HeapEntry::TypeAsString() { | 1117 const char* HeapEntry::TypeAsString() { |
1104 switch (type()) { | 1118 switch (type()) { |
1105 case kHidden: return "/hidden/"; | 1119 case kHidden: return "/hidden/"; |
1106 case kObject: return "/object/"; | 1120 case kObject: return "/object/"; |
1107 case kClosure: return "/closure/"; | 1121 case kClosure: return "/closure/"; |
1108 case kString: return "/string/"; | 1122 case kString: return "/string/"; |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1208 gc_roots_entry_(NULL), | 1222 gc_roots_entry_(NULL), |
1209 natives_root_entry_(NULL), | 1223 natives_root_entry_(NULL), |
1210 raw_entries_(NULL), | 1224 raw_entries_(NULL), |
1211 entries_sorted_(false) { | 1225 entries_sorted_(false) { |
1212 STATIC_ASSERT( | 1226 STATIC_ASSERT( |
1213 sizeof(HeapGraphEdge) == | 1227 sizeof(HeapGraphEdge) == |
1214 SnapshotSizeConstants<sizeof(void*)>::kExpectedHeapGraphEdgeSize); // NOL
INT | 1228 SnapshotSizeConstants<sizeof(void*)>::kExpectedHeapGraphEdgeSize); // NOL
INT |
1215 STATIC_ASSERT( | 1229 STATIC_ASSERT( |
1216 sizeof(HeapEntry) == | 1230 sizeof(HeapEntry) == |
1217 SnapshotSizeConstants<sizeof(void*)>::kExpectedHeapEntrySize); // NOLINT | 1231 SnapshotSizeConstants<sizeof(void*)>::kExpectedHeapEntrySize); // NOLINT |
| 1232 for (int i = 0; i < VisitorSynchronization::kNumberOfSyncTags; ++i) { |
| 1233 gc_subroot_entries_[i] = NULL; |
| 1234 } |
1218 } | 1235 } |
1219 | 1236 |
1220 HeapSnapshot::~HeapSnapshot() { | 1237 HeapSnapshot::~HeapSnapshot() { |
1221 DeleteArray(raw_entries_); | 1238 DeleteArray(raw_entries_); |
1222 } | 1239 } |
1223 | 1240 |
1224 | 1241 |
1225 void HeapSnapshot::Delete() { | 1242 void HeapSnapshot::Delete() { |
1226 collection_->RemoveSnapshot(this); | 1243 collection_->RemoveSnapshot(this); |
1227 delete this; | 1244 delete this; |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1263 ASSERT(gc_roots_entry_ == NULL); | 1280 ASSERT(gc_roots_entry_ == NULL); |
1264 return (gc_roots_entry_ = AddEntry(HeapEntry::kObject, | 1281 return (gc_roots_entry_ = AddEntry(HeapEntry::kObject, |
1265 "(GC roots)", | 1282 "(GC roots)", |
1266 HeapObjectsMap::kGcRootsObjectId, | 1283 HeapObjectsMap::kGcRootsObjectId, |
1267 0, | 1284 0, |
1268 children_count, | 1285 children_count, |
1269 retainers_count)); | 1286 retainers_count)); |
1270 } | 1287 } |
1271 | 1288 |
1272 | 1289 |
| 1290 HeapEntry* HeapSnapshot::AddGcSubrootEntry(int tag, |
| 1291 int children_count, |
| 1292 int retainers_count) { |
| 1293 ASSERT(gc_subroot_entries_[tag] == NULL); |
| 1294 ASSERT(0 <= tag && tag < VisitorSynchronization::kNumberOfSyncTags); |
| 1295 return (gc_subroot_entries_[tag] = AddEntry( |
| 1296 HeapEntry::kObject, |
| 1297 VisitorSynchronization::kTagNames[tag], |
| 1298 HeapObjectsMap::GetNthGcSubrootId(tag), |
| 1299 0, |
| 1300 children_count, |
| 1301 retainers_count)); |
| 1302 } |
| 1303 |
| 1304 |
1273 HeapEntry* HeapSnapshot::AddNativesRootEntry(int children_count, | 1305 HeapEntry* HeapSnapshot::AddNativesRootEntry(int children_count, |
1274 int retainers_count) { | 1306 int retainers_count) { |
1275 ASSERT(natives_root_entry_ == NULL); | 1307 ASSERT(natives_root_entry_ == NULL); |
1276 return (natives_root_entry_ = AddEntry( | 1308 return (natives_root_entry_ = AddEntry( |
1277 HeapEntry::kObject, | 1309 HeapEntry::kObject, |
1278 "(Native objects)", | 1310 "(Native objects)", |
1279 HeapObjectsMap::kNativesRootObjectId, | 1311 HeapObjectsMap::kNativesRootObjectId, |
1280 0, | 1312 0, |
1281 children_count, | 1313 children_count, |
1282 retainers_count)); | 1314 retainers_count)); |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1348 List<HeapEntry*>* HeapSnapshot::GetSortedEntriesList() { | 1380 List<HeapEntry*>* HeapSnapshot::GetSortedEntriesList() { |
1349 if (!entries_sorted_) { | 1381 if (!entries_sorted_) { |
1350 entries_.Sort(SortByIds); | 1382 entries_.Sort(SortByIds); |
1351 entries_sorted_ = true; | 1383 entries_sorted_ = true; |
1352 } | 1384 } |
1353 return &entries_; | 1385 return &entries_; |
1354 } | 1386 } |
1355 | 1387 |
1356 | 1388 |
1357 void HeapSnapshot::Print(int max_depth) { | 1389 void HeapSnapshot::Print(int max_depth) { |
1358 root()->Print(max_depth, 0); | 1390 root()->Print("", "", max_depth, 0); |
1359 } | 1391 } |
1360 | 1392 |
1361 | 1393 |
1362 // We split IDs on evens for embedder objects (see | 1394 // We split IDs on evens for embedder objects (see |
1363 // HeapObjectsMap::GenerateId) and odds for native objects. | 1395 // HeapObjectsMap::GenerateId) and odds for native objects. |
1364 const uint64_t HeapObjectsMap::kInternalRootObjectId = 1; | 1396 const uint64_t HeapObjectsMap::kInternalRootObjectId = 1; |
1365 const uint64_t HeapObjectsMap::kGcRootsObjectId = 3; | 1397 const uint64_t HeapObjectsMap::kGcRootsObjectId = |
1366 const uint64_t HeapObjectsMap::kNativesRootObjectId = 5; | 1398 HeapObjectsMap::kInternalRootObjectId + HeapObjectsMap::kObjectIdStep; |
1367 // Increase kFirstAvailableObjectId if new 'special' objects appear. | 1399 const uint64_t HeapObjectsMap::kNativesRootObjectId = |
1368 const uint64_t HeapObjectsMap::kFirstAvailableObjectId = 7; | 1400 HeapObjectsMap::kGcRootsObjectId + HeapObjectsMap::kObjectIdStep; |
| 1401 const uint64_t HeapObjectsMap::kGcRootsFirstSubrootId = |
| 1402 HeapObjectsMap::kNativesRootObjectId + HeapObjectsMap::kObjectIdStep; |
| 1403 const uint64_t HeapObjectsMap::kFirstAvailableObjectId = |
| 1404 HeapObjectsMap::kGcRootsFirstSubrootId + |
| 1405 VisitorSynchronization::kNumberOfSyncTags * HeapObjectsMap::kObjectIdStep; |
1369 | 1406 |
1370 HeapObjectsMap::HeapObjectsMap() | 1407 HeapObjectsMap::HeapObjectsMap() |
1371 : initial_fill_mode_(true), | 1408 : initial_fill_mode_(true), |
1372 next_id_(kFirstAvailableObjectId), | 1409 next_id_(kFirstAvailableObjectId), |
1373 entries_map_(AddressesMatch), | 1410 entries_map_(AddressesMatch), |
1374 entries_(new List<EntryInfo>()) { } | 1411 entries_(new List<EntryInfo>()) { } |
1375 | 1412 |
1376 | 1413 |
1377 HeapObjectsMap::~HeapObjectsMap() { | 1414 HeapObjectsMap::~HeapObjectsMap() { |
1378 delete entries_; | 1415 delete entries_; |
1379 } | 1416 } |
1380 | 1417 |
1381 | 1418 |
1382 void HeapObjectsMap::SnapshotGenerationFinished() { | 1419 void HeapObjectsMap::SnapshotGenerationFinished() { |
1383 initial_fill_mode_ = false; | 1420 initial_fill_mode_ = false; |
1384 RemoveDeadEntries(); | 1421 RemoveDeadEntries(); |
1385 } | 1422 } |
1386 | 1423 |
1387 | 1424 |
1388 uint64_t HeapObjectsMap::FindObject(Address addr) { | 1425 uint64_t HeapObjectsMap::FindObject(Address addr) { |
1389 if (!initial_fill_mode_) { | 1426 if (!initial_fill_mode_) { |
1390 uint64_t existing = FindEntry(addr); | 1427 uint64_t existing = FindEntry(addr); |
1391 if (existing != 0) return existing; | 1428 if (existing != 0) return existing; |
1392 } | 1429 } |
1393 uint64_t id = next_id_; | 1430 uint64_t id = next_id_; |
1394 next_id_ += 2; | 1431 next_id_ += kObjectIdStep; |
1395 AddEntry(addr, id); | 1432 AddEntry(addr, id); |
1396 return id; | 1433 return id; |
1397 } | 1434 } |
1398 | 1435 |
1399 | 1436 |
1400 void HeapObjectsMap::MoveObject(Address from, Address to) { | 1437 void HeapObjectsMap::MoveObject(Address from, Address to) { |
1401 if (from == to) return; | 1438 if (from == to) return; |
1402 HashMap::Entry* entry = entries_map_.Lookup(from, AddressHash(from), false); | 1439 HashMap::Entry* entry = entries_map_.Lookup(from, AddressHash(from), false); |
1403 if (entry != NULL) { | 1440 if (entry != NULL) { |
1404 void* value = entry->value; | 1441 void* value = entry->value; |
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1677 cache_entry->value = const_cast<char*>(tag); | 1714 cache_entry->value = const_cast<char*>(tag); |
1678 } | 1715 } |
1679 | 1716 |
1680 | 1717 |
1681 HeapObject *const V8HeapExplorer::kInternalRootObject = | 1718 HeapObject *const V8HeapExplorer::kInternalRootObject = |
1682 reinterpret_cast<HeapObject*>( | 1719 reinterpret_cast<HeapObject*>( |
1683 static_cast<intptr_t>(HeapObjectsMap::kInternalRootObjectId)); | 1720 static_cast<intptr_t>(HeapObjectsMap::kInternalRootObjectId)); |
1684 HeapObject *const V8HeapExplorer::kGcRootsObject = | 1721 HeapObject *const V8HeapExplorer::kGcRootsObject = |
1685 reinterpret_cast<HeapObject*>( | 1722 reinterpret_cast<HeapObject*>( |
1686 static_cast<intptr_t>(HeapObjectsMap::kGcRootsObjectId)); | 1723 static_cast<intptr_t>(HeapObjectsMap::kGcRootsObjectId)); |
| 1724 HeapObject *const V8HeapExplorer::kFirstGcSubrootObject = |
| 1725 reinterpret_cast<HeapObject*>( |
| 1726 static_cast<intptr_t>(HeapObjectsMap::kGcRootsFirstSubrootId)); |
| 1727 HeapObject *const V8HeapExplorer::kLastGcSubrootObject = |
| 1728 reinterpret_cast<HeapObject*>( |
| 1729 static_cast<intptr_t>(HeapObjectsMap::kFirstAvailableObjectId)); |
1687 | 1730 |
1688 | 1731 |
1689 V8HeapExplorer::V8HeapExplorer( | 1732 V8HeapExplorer::V8HeapExplorer( |
1690 HeapSnapshot* snapshot, | 1733 HeapSnapshot* snapshot, |
1691 SnapshottingProgressReportingInterface* progress) | 1734 SnapshottingProgressReportingInterface* progress) |
1692 : heap_(Isolate::Current()->heap()), | 1735 : heap_(Isolate::Current()->heap()), |
1693 snapshot_(snapshot), | 1736 snapshot_(snapshot), |
1694 collection_(snapshot_->collection()), | 1737 collection_(snapshot_->collection()), |
1695 progress_(progress), | 1738 progress_(progress), |
1696 filler_(NULL) { | 1739 filler_(NULL) { |
(...skipping 12 matching lines...) Expand all Loading... |
1709 | 1752 |
1710 | 1753 |
1711 HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object, | 1754 HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object, |
1712 int children_count, | 1755 int children_count, |
1713 int retainers_count) { | 1756 int retainers_count) { |
1714 if (object == kInternalRootObject) { | 1757 if (object == kInternalRootObject) { |
1715 ASSERT(retainers_count == 0); | 1758 ASSERT(retainers_count == 0); |
1716 return snapshot_->AddRootEntry(children_count); | 1759 return snapshot_->AddRootEntry(children_count); |
1717 } else if (object == kGcRootsObject) { | 1760 } else if (object == kGcRootsObject) { |
1718 return snapshot_->AddGcRootsEntry(children_count, retainers_count); | 1761 return snapshot_->AddGcRootsEntry(children_count, retainers_count); |
| 1762 } else if (object >= kFirstGcSubrootObject && object < kLastGcSubrootObject) { |
| 1763 return snapshot_->AddGcSubrootEntry( |
| 1764 GetGcSubrootOrder(object), |
| 1765 children_count, |
| 1766 retainers_count); |
1719 } else if (object->IsJSGlobalObject()) { | 1767 } else if (object->IsJSGlobalObject()) { |
1720 const char* tag = objects_tags_.GetTag(object); | 1768 const char* tag = objects_tags_.GetTag(object); |
1721 const char* name = collection_->names()->GetName( | 1769 const char* name = collection_->names()->GetName( |
1722 GetConstructorName(JSObject::cast(object))); | 1770 GetConstructorName(JSObject::cast(object))); |
1723 if (tag != NULL) { | 1771 if (tag != NULL) { |
1724 name = collection_->names()->GetFormatted("%s / %s", name, tag); | 1772 name = collection_->names()->GetFormatted("%s / %s", name, tag); |
1725 } | 1773 } |
1726 return AddEntry(object, | 1774 return AddEntry(object, |
1727 HeapEntry::kObject, | 1775 HeapEntry::kObject, |
1728 name, | 1776 name, |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1772 } else if (object->IsScript()) { | 1820 } else if (object->IsScript()) { |
1773 Script* script = Script::cast(object); | 1821 Script* script = Script::cast(object); |
1774 return AddEntry(object, | 1822 return AddEntry(object, |
1775 HeapEntry::kCode, | 1823 HeapEntry::kCode, |
1776 script->name()->IsString() ? | 1824 script->name()->IsString() ? |
1777 collection_->names()->GetName( | 1825 collection_->names()->GetName( |
1778 String::cast(script->name())) | 1826 String::cast(script->name())) |
1779 : "", | 1827 : "", |
1780 children_count, | 1828 children_count, |
1781 retainers_count); | 1829 retainers_count); |
| 1830 } else if (object->IsGlobalContext()) { |
| 1831 return AddEntry(object, |
| 1832 HeapEntry::kHidden, |
| 1833 "system / GlobalContext", |
| 1834 children_count, |
| 1835 retainers_count); |
| 1836 } else if (object->IsContext()) { |
| 1837 return AddEntry(object, |
| 1838 HeapEntry::kHidden, |
| 1839 "system / Context", |
| 1840 children_count, |
| 1841 retainers_count); |
1782 } else if (object->IsFixedArray() || | 1842 } else if (object->IsFixedArray() || |
1783 object->IsFixedDoubleArray() || | 1843 object->IsFixedDoubleArray() || |
1784 object->IsByteArray() || | 1844 object->IsByteArray() || |
1785 object->IsExternalArray()) { | 1845 object->IsExternalArray()) { |
1786 const char* tag = objects_tags_.GetTag(object); | 1846 const char* tag = objects_tags_.GetTag(object); |
1787 return AddEntry(object, | 1847 return AddEntry(object, |
1788 HeapEntry::kArray, | 1848 HeapEntry::kArray, |
1789 tag != NULL ? tag : "", | 1849 tag != NULL ? tag : "", |
1790 children_count, | 1850 children_count, |
1791 retainers_count); | 1851 retainers_count); |
(...skipping 19 matching lines...) Expand all Loading... |
1811 int retainers_count) { | 1871 int retainers_count) { |
1812 return snapshot_->AddEntry(type, | 1872 return snapshot_->AddEntry(type, |
1813 name, | 1873 name, |
1814 collection_->GetObjectId(object->address()), | 1874 collection_->GetObjectId(object->address()), |
1815 object->Size(), | 1875 object->Size(), |
1816 children_count, | 1876 children_count, |
1817 retainers_count); | 1877 retainers_count); |
1818 } | 1878 } |
1819 | 1879 |
1820 | 1880 |
| 1881 class GcSubrootsEnumerator : public ObjectVisitor { |
| 1882 public: |
| 1883 GcSubrootsEnumerator( |
| 1884 SnapshotFillerInterface* filler, V8HeapExplorer* explorer) |
| 1885 : filler_(filler), |
| 1886 explorer_(explorer), |
| 1887 previous_object_count_(0), |
| 1888 object_count_(0) { |
| 1889 } |
| 1890 void VisitPointers(Object** start, Object** end) { |
| 1891 object_count_ += end - start; |
| 1892 } |
| 1893 void Synchronize(VisitorSynchronization::SyncTag tag) { |
| 1894 // Skip empty subroots. |
| 1895 if (previous_object_count_ != object_count_) { |
| 1896 previous_object_count_ = object_count_; |
| 1897 filler_->AddEntry(V8HeapExplorer::GetNthGcSubrootObject(tag), explorer_); |
| 1898 } |
| 1899 } |
| 1900 private: |
| 1901 SnapshotFillerInterface* filler_; |
| 1902 V8HeapExplorer* explorer_; |
| 1903 intptr_t previous_object_count_; |
| 1904 intptr_t object_count_; |
| 1905 }; |
| 1906 |
| 1907 |
1821 void V8HeapExplorer::AddRootEntries(SnapshotFillerInterface* filler) { | 1908 void V8HeapExplorer::AddRootEntries(SnapshotFillerInterface* filler) { |
1822 filler->AddEntry(kInternalRootObject, this); | 1909 filler->AddEntry(kInternalRootObject, this); |
1823 filler->AddEntry(kGcRootsObject, this); | 1910 filler->AddEntry(kGcRootsObject, this); |
| 1911 GcSubrootsEnumerator enumerator(filler, this); |
| 1912 heap_->IterateRoots(&enumerator, VISIT_ALL); |
1824 } | 1913 } |
1825 | 1914 |
1826 | 1915 |
1827 const char* V8HeapExplorer::GetSystemEntryName(HeapObject* object) { | 1916 const char* V8HeapExplorer::GetSystemEntryName(HeapObject* object) { |
1828 switch (object->map()->instance_type()) { | 1917 switch (object->map()->instance_type()) { |
1829 case MAP_TYPE: return "system / Map"; | 1918 case MAP_TYPE: return "system / Map"; |
1830 case JS_GLOBAL_PROPERTY_CELL_TYPE: return "system / JSGlobalPropertyCell"; | 1919 case JS_GLOBAL_PROPERTY_CELL_TYPE: return "system / JSGlobalPropertyCell"; |
1831 case FOREIGN_TYPE: return "system / Foreign"; | 1920 case FOREIGN_TYPE: return "system / Foreign"; |
1832 case ODDBALL_TYPE: return "system / Oddball"; | 1921 case ODDBALL_TYPE: return "system / Oddball"; |
1833 #define MAKE_STRUCT_CASE(NAME, Name, name) \ | 1922 #define MAKE_STRUCT_CASE(NAME, Name, name) \ |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1932 TagObject(js_fun->unchecked_context(), "(context)"); | 2021 TagObject(js_fun->unchecked_context(), "(context)"); |
1933 SetInternalReference(js_fun, entry, | 2022 SetInternalReference(js_fun, entry, |
1934 "context", js_fun->unchecked_context(), | 2023 "context", js_fun->unchecked_context(), |
1935 JSFunction::kContextOffset); | 2024 JSFunction::kContextOffset); |
1936 TagObject(js_fun->literals_or_bindings(), | 2025 TagObject(js_fun->literals_or_bindings(), |
1937 "(function literals_or_bindings)"); | 2026 "(function literals_or_bindings)"); |
1938 SetInternalReference(js_fun, entry, | 2027 SetInternalReference(js_fun, entry, |
1939 "literals_or_bindings", | 2028 "literals_or_bindings", |
1940 js_fun->literals_or_bindings(), | 2029 js_fun->literals_or_bindings(), |
1941 JSFunction::kLiteralsOffset); | 2030 JSFunction::kLiteralsOffset); |
| 2031 for (int i = JSFunction::kNonWeakFieldsEndOffset; |
| 2032 i < JSFunction::kSize; |
| 2033 i += kPointerSize) { |
| 2034 SetWeakReference(js_fun, entry, i, *HeapObject::RawField(js_fun, i), i); |
| 2035 } |
1942 } | 2036 } |
1943 TagObject(js_obj->properties(), "(object properties)"); | 2037 TagObject(js_obj->properties(), "(object properties)"); |
1944 SetInternalReference(obj, entry, | 2038 SetInternalReference(obj, entry, |
1945 "properties", js_obj->properties(), | 2039 "properties", js_obj->properties(), |
1946 JSObject::kPropertiesOffset); | 2040 JSObject::kPropertiesOffset); |
1947 TagObject(js_obj->elements(), "(object elements)"); | 2041 TagObject(js_obj->elements(), "(object elements)"); |
1948 SetInternalReference(obj, entry, | 2042 SetInternalReference(obj, entry, |
1949 "elements", js_obj->elements(), | 2043 "elements", js_obj->elements(), |
1950 JSObject::kElementsOffset); | 2044 JSObject::kElementsOffset); |
1951 } else if (obj->IsString()) { | 2045 } else if (obj->IsString()) { |
1952 if (obj->IsConsString()) { | 2046 if (obj->IsConsString()) { |
1953 ConsString* cs = ConsString::cast(obj); | 2047 ConsString* cs = ConsString::cast(obj); |
1954 SetInternalReference(obj, entry, 1, cs->first()); | 2048 SetInternalReference(obj, entry, 1, cs->first()); |
1955 SetInternalReference(obj, entry, 2, cs->second()); | 2049 SetInternalReference(obj, entry, 2, cs->second()); |
1956 } | 2050 } |
1957 if (obj->IsSlicedString()) { | 2051 if (obj->IsSlicedString()) { |
1958 SlicedString* ss = SlicedString::cast(obj); | 2052 SlicedString* ss = SlicedString::cast(obj); |
1959 SetInternalReference(obj, entry, "parent", ss->parent()); | 2053 SetInternalReference(obj, entry, "parent", ss->parent()); |
1960 } | 2054 } |
1961 extract_indexed_refs = false; | 2055 extract_indexed_refs = false; |
1962 } else if (obj->IsGlobalContext()) { | 2056 } else if (obj->IsGlobalContext()) { |
1963 Context* context = Context::cast(obj); | 2057 Context* context = Context::cast(obj); |
1964 TagObject(context->jsfunction_result_caches(), | 2058 TagObject(context->jsfunction_result_caches(), |
1965 "(context func. result caches)"); | 2059 "(context func. result caches)"); |
1966 TagObject(context->normalized_map_cache(), "(context norm. map cache)"); | 2060 TagObject(context->normalized_map_cache(), "(context norm. map cache)"); |
1967 TagObject(context->runtime_context(), "(runtime context)"); | 2061 TagObject(context->runtime_context(), "(runtime context)"); |
1968 TagObject(context->map_cache(), "(context map cache)"); | |
1969 TagObject(context->data(), "(context data)"); | 2062 TagObject(context->data(), "(context data)"); |
| 2063 for (int i = Context::FIRST_WEAK_SLOT; |
| 2064 i < Context::GLOBAL_CONTEXT_SLOTS; |
| 2065 ++i) { |
| 2066 SetWeakReference(obj, entry, |
| 2067 i, context->get(i), |
| 2068 FixedArray::OffsetOfElementAt(i)); |
| 2069 } |
1970 } else if (obj->IsMap()) { | 2070 } else if (obj->IsMap()) { |
1971 Map* map = Map::cast(obj); | 2071 Map* map = Map::cast(obj); |
1972 SetInternalReference(obj, entry, | 2072 SetInternalReference(obj, entry, |
1973 "prototype", map->prototype(), Map::kPrototypeOffset); | 2073 "prototype", map->prototype(), Map::kPrototypeOffset); |
1974 SetInternalReference(obj, entry, | 2074 SetInternalReference(obj, entry, |
1975 "constructor", map->constructor(), | 2075 "constructor", map->constructor(), |
1976 Map::kConstructorOffset); | 2076 Map::kConstructorOffset); |
1977 if (!map->instance_descriptors()->IsEmpty()) { | 2077 if (!map->instance_descriptors()->IsEmpty()) { |
1978 TagObject(map->instance_descriptors(), "(map descriptors)"); | 2078 TagObject(map->instance_descriptors(), "(map descriptors)"); |
1979 SetInternalReference(obj, entry, | 2079 SetInternalReference(obj, entry, |
(...skipping 22 matching lines...) Expand all Loading... |
2002 TagObject(shared->scope_info(), "(function scope info)"); | 2102 TagObject(shared->scope_info(), "(function scope info)"); |
2003 SetInternalReference(obj, entry, | 2103 SetInternalReference(obj, entry, |
2004 "scope_info", shared->scope_info(), | 2104 "scope_info", shared->scope_info(), |
2005 SharedFunctionInfo::kScopeInfoOffset); | 2105 SharedFunctionInfo::kScopeInfoOffset); |
2006 SetInternalReference(obj, entry, | 2106 SetInternalReference(obj, entry, |
2007 "instance_class_name", shared->instance_class_name(), | 2107 "instance_class_name", shared->instance_class_name(), |
2008 SharedFunctionInfo::kInstanceClassNameOffset); | 2108 SharedFunctionInfo::kInstanceClassNameOffset); |
2009 SetInternalReference(obj, entry, | 2109 SetInternalReference(obj, entry, |
2010 "script", shared->script(), | 2110 "script", shared->script(), |
2011 SharedFunctionInfo::kScriptOffset); | 2111 SharedFunctionInfo::kScriptOffset); |
| 2112 SetWeakReference(obj, entry, |
| 2113 1, shared->initial_map(), |
| 2114 SharedFunctionInfo::kInitialMapOffset); |
2012 } else if (obj->IsScript()) { | 2115 } else if (obj->IsScript()) { |
2013 Script* script = Script::cast(obj); | 2116 Script* script = Script::cast(obj); |
2014 SetInternalReference(obj, entry, | 2117 SetInternalReference(obj, entry, |
2015 "source", script->source(), | 2118 "source", script->source(), |
2016 Script::kSourceOffset); | 2119 Script::kSourceOffset); |
2017 SetInternalReference(obj, entry, | 2120 SetInternalReference(obj, entry, |
2018 "name", script->name(), | 2121 "name", script->name(), |
2019 Script::kNameOffset); | 2122 Script::kNameOffset); |
2020 SetInternalReference(obj, entry, | 2123 SetInternalReference(obj, entry, |
2021 "data", script->data(), | 2124 "data", script->data(), |
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2228 } | 2331 } |
2229 | 2332 |
2230 | 2333 |
2231 HeapEntry* V8HeapExplorer::GetEntry(Object* obj) { | 2334 HeapEntry* V8HeapExplorer::GetEntry(Object* obj) { |
2232 if (!obj->IsHeapObject()) return NULL; | 2335 if (!obj->IsHeapObject()) return NULL; |
2233 return filler_->FindOrAddEntry(obj, this); | 2336 return filler_->FindOrAddEntry(obj, this); |
2234 } | 2337 } |
2235 | 2338 |
2236 | 2339 |
2237 class RootsReferencesExtractor : public ObjectVisitor { | 2340 class RootsReferencesExtractor : public ObjectVisitor { |
| 2341 private: |
| 2342 struct IndexTag { |
| 2343 IndexTag(int index, VisitorSynchronization::SyncTag tag) |
| 2344 : index(index), tag(tag) { } |
| 2345 int index; |
| 2346 VisitorSynchronization::SyncTag tag; |
| 2347 }; |
| 2348 |
2238 public: | 2349 public: |
2239 explicit RootsReferencesExtractor(V8HeapExplorer* explorer) | 2350 RootsReferencesExtractor() |
2240 : explorer_(explorer) { | 2351 : collecting_all_references_(false), |
| 2352 previous_reference_count_(0) { |
2241 } | 2353 } |
| 2354 |
2242 void VisitPointers(Object** start, Object** end) { | 2355 void VisitPointers(Object** start, Object** end) { |
2243 for (Object** p = start; p < end; p++) explorer_->SetGcRootsReference(*p); | 2356 if (collecting_all_references_) { |
| 2357 for (Object** p = start; p < end; p++) all_references_.Add(*p); |
| 2358 } else { |
| 2359 for (Object** p = start; p < end; p++) strong_references_.Add(*p); |
| 2360 } |
2244 } | 2361 } |
| 2362 |
| 2363 void SetCollectingAllReferences() { collecting_all_references_ = true; } |
| 2364 |
| 2365 void FillReferences(V8HeapExplorer* explorer) { |
| 2366 ASSERT(strong_references_.length() <= all_references_.length()); |
| 2367 for (int i = 0; i < reference_tags_.length(); ++i) { |
| 2368 explorer->SetGcRootsReference(reference_tags_[i].tag); |
| 2369 } |
| 2370 int strong_index = 0, all_index = 0, tags_index = 0; |
| 2371 while (all_index < all_references_.length()) { |
| 2372 if (strong_index < strong_references_.length() && |
| 2373 strong_references_[strong_index] == all_references_[all_index]) { |
| 2374 explorer->SetGcSubrootReference(reference_tags_[tags_index].tag, |
| 2375 false, |
| 2376 all_references_[all_index++]); |
| 2377 ++strong_index; |
| 2378 } else { |
| 2379 explorer->SetGcSubrootReference(reference_tags_[tags_index].tag, |
| 2380 true, |
| 2381 all_references_[all_index++]); |
| 2382 } |
| 2383 if (reference_tags_[tags_index].index == all_index) ++tags_index; |
| 2384 } |
| 2385 } |
| 2386 |
| 2387 void Synchronize(VisitorSynchronization::SyncTag tag) { |
| 2388 if (collecting_all_references_ && |
| 2389 previous_reference_count_ != all_references_.length()) { |
| 2390 previous_reference_count_ = all_references_.length(); |
| 2391 reference_tags_.Add(IndexTag(previous_reference_count_, tag)); |
| 2392 } |
| 2393 } |
| 2394 |
2245 private: | 2395 private: |
2246 V8HeapExplorer* explorer_; | 2396 bool collecting_all_references_; |
| 2397 List<Object*> strong_references_; |
| 2398 List<Object*> all_references_; |
| 2399 int previous_reference_count_; |
| 2400 List<IndexTag> reference_tags_; |
2247 }; | 2401 }; |
2248 | 2402 |
2249 | 2403 |
2250 bool V8HeapExplorer::IterateAndExtractReferences( | 2404 bool V8HeapExplorer::IterateAndExtractReferences( |
2251 SnapshotFillerInterface* filler) { | 2405 SnapshotFillerInterface* filler) { |
2252 HeapIterator iterator(HeapIterator::kFilterUnreachable); | 2406 HeapIterator iterator(HeapIterator::kFilterUnreachable); |
2253 | 2407 |
2254 filler_ = filler; | 2408 filler_ = filler; |
2255 bool interrupted = false; | 2409 bool interrupted = false; |
2256 | 2410 |
2257 // Heap iteration with filtering must be finished in any case. | 2411 // Heap iteration with filtering must be finished in any case. |
2258 for (HeapObject* obj = iterator.next(); | 2412 for (HeapObject* obj = iterator.next(); |
2259 obj != NULL; | 2413 obj != NULL; |
2260 obj = iterator.next(), progress_->ProgressStep()) { | 2414 obj = iterator.next(), progress_->ProgressStep()) { |
2261 if (!interrupted) { | 2415 if (!interrupted) { |
2262 ExtractReferences(obj); | 2416 ExtractReferences(obj); |
2263 if (!progress_->ProgressReport(false)) interrupted = true; | 2417 if (!progress_->ProgressReport(false)) interrupted = true; |
2264 } | 2418 } |
2265 } | 2419 } |
2266 if (interrupted) { | 2420 if (interrupted) { |
2267 filler_ = NULL; | 2421 filler_ = NULL; |
2268 return false; | 2422 return false; |
2269 } | 2423 } |
2270 SetRootGcRootsReference(); | 2424 SetRootGcRootsReference(); |
2271 RootsReferencesExtractor extractor(this); | 2425 RootsReferencesExtractor extractor; |
| 2426 heap_->IterateRoots(&extractor, VISIT_ONLY_STRONG); |
| 2427 extractor.SetCollectingAllReferences(); |
2272 heap_->IterateRoots(&extractor, VISIT_ALL); | 2428 heap_->IterateRoots(&extractor, VISIT_ALL); |
| 2429 extractor.FillReferences(this); |
2273 filler_ = NULL; | 2430 filler_ = NULL; |
2274 return progress_->ProgressReport(false); | 2431 return progress_->ProgressReport(false); |
2275 } | 2432 } |
2276 | 2433 |
2277 | 2434 |
2278 void V8HeapExplorer::SetClosureReference(HeapObject* parent_obj, | 2435 void V8HeapExplorer::SetClosureReference(HeapObject* parent_obj, |
2279 HeapEntry* parent_entry, | 2436 HeapEntry* parent_entry, |
2280 String* reference_name, | 2437 String* reference_name, |
2281 Object* child_obj) { | 2438 Object* child_obj) { |
2282 HeapEntry* child_entry = GetEntry(child_obj); | 2439 HeapEntry* child_entry = GetEntry(child_obj); |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2352 filler_->SetIndexedReference(HeapGraphEdge::kHidden, | 2509 filler_->SetIndexedReference(HeapGraphEdge::kHidden, |
2353 parent_obj, | 2510 parent_obj, |
2354 parent_entry, | 2511 parent_entry, |
2355 index, | 2512 index, |
2356 child_obj, | 2513 child_obj, |
2357 child_entry); | 2514 child_entry); |
2358 } | 2515 } |
2359 } | 2516 } |
2360 | 2517 |
2361 | 2518 |
| 2519 void V8HeapExplorer::SetWeakReference(HeapObject* parent_obj, |
| 2520 HeapEntry* parent_entry, |
| 2521 int index, |
| 2522 Object* child_obj, |
| 2523 int field_offset) { |
| 2524 HeapEntry* child_entry = GetEntry(child_obj); |
| 2525 if (child_entry != NULL) { |
| 2526 filler_->SetIndexedReference(HeapGraphEdge::kWeak, |
| 2527 parent_obj, |
| 2528 parent_entry, |
| 2529 index, |
| 2530 child_obj, |
| 2531 child_entry); |
| 2532 IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset); |
| 2533 } |
| 2534 } |
| 2535 |
| 2536 |
2362 void V8HeapExplorer::SetPropertyReference(HeapObject* parent_obj, | 2537 void V8HeapExplorer::SetPropertyReference(HeapObject* parent_obj, |
2363 HeapEntry* parent_entry, | 2538 HeapEntry* parent_entry, |
2364 String* reference_name, | 2539 String* reference_name, |
2365 Object* child_obj, | 2540 Object* child_obj, |
2366 const char* name_format_string, | 2541 const char* name_format_string, |
2367 int field_offset) { | 2542 int field_offset) { |
2368 HeapEntry* child_entry = GetEntry(child_obj); | 2543 HeapEntry* child_entry = GetEntry(child_obj); |
2369 if (child_entry != NULL) { | 2544 if (child_entry != NULL) { |
2370 HeapGraphEdge::Type type = reference_name->length() > 0 ? | 2545 HeapGraphEdge::Type type = reference_name->length() > 0 ? |
2371 HeapGraphEdge::kProperty : HeapGraphEdge::kInternal; | 2546 HeapGraphEdge::kProperty : HeapGraphEdge::kInternal; |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2414 void V8HeapExplorer::SetRootShortcutReference(Object* child_obj) { | 2589 void V8HeapExplorer::SetRootShortcutReference(Object* child_obj) { |
2415 HeapEntry* child_entry = GetEntry(child_obj); | 2590 HeapEntry* child_entry = GetEntry(child_obj); |
2416 ASSERT(child_entry != NULL); | 2591 ASSERT(child_entry != NULL); |
2417 filler_->SetNamedAutoIndexReference( | 2592 filler_->SetNamedAutoIndexReference( |
2418 HeapGraphEdge::kShortcut, | 2593 HeapGraphEdge::kShortcut, |
2419 kInternalRootObject, snapshot_->root(), | 2594 kInternalRootObject, snapshot_->root(), |
2420 child_obj, child_entry); | 2595 child_obj, child_entry); |
2421 } | 2596 } |
2422 | 2597 |
2423 | 2598 |
2424 void V8HeapExplorer::SetGcRootsReference(Object* child_obj) { | 2599 void V8HeapExplorer::SetGcRootsReference(VisitorSynchronization::SyncTag tag) { |
| 2600 filler_->SetIndexedAutoIndexReference( |
| 2601 HeapGraphEdge::kElement, |
| 2602 kGcRootsObject, snapshot_->gc_roots(), |
| 2603 GetNthGcSubrootObject(tag), snapshot_->gc_subroot(tag)); |
| 2604 } |
| 2605 |
| 2606 |
| 2607 void V8HeapExplorer::SetGcSubrootReference( |
| 2608 VisitorSynchronization::SyncTag tag, bool is_weak, Object* child_obj) { |
2425 HeapEntry* child_entry = GetEntry(child_obj); | 2609 HeapEntry* child_entry = GetEntry(child_obj); |
2426 if (child_entry != NULL) { | 2610 if (child_entry != NULL) { |
2427 filler_->SetIndexedAutoIndexReference( | 2611 filler_->SetIndexedAutoIndexReference( |
2428 HeapGraphEdge::kElement, | 2612 is_weak ? HeapGraphEdge::kWeak : HeapGraphEdge::kElement, |
2429 kGcRootsObject, snapshot_->gc_roots(), | 2613 GetNthGcSubrootObject(tag), snapshot_->gc_subroot(tag), |
2430 child_obj, child_entry); | 2614 child_obj, child_entry); |
2431 } | 2615 } |
2432 } | 2616 } |
2433 | 2617 |
2434 | 2618 |
2435 void V8HeapExplorer::TagObject(Object* obj, const char* tag) { | 2619 void V8HeapExplorer::TagObject(Object* obj, const char* tag) { |
2436 if (obj->IsHeapObject() && | 2620 if (obj->IsHeapObject() && |
2437 !obj->IsOddball() && | 2621 !obj->IsOddball() && |
2438 obj != heap_->raw_unchecked_empty_byte_array() && | 2622 obj != heap_->raw_unchecked_empty_byte_array() && |
2439 obj != heap_->raw_unchecked_empty_fixed_array() && | 2623 obj != heap_->raw_unchecked_empty_fixed_array() && |
(...skipping 788 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3228 } | 3412 } |
3229 return static_cast<int>(reinterpret_cast<intptr_t>(cache_entry->value)); | 3413 return static_cast<int>(reinterpret_cast<intptr_t>(cache_entry->value)); |
3230 } | 3414 } |
3231 | 3415 |
3232 | 3416 |
3233 void HeapSnapshotJSONSerializer::SerializeEdge(HeapGraphEdge* edge) { | 3417 void HeapSnapshotJSONSerializer::SerializeEdge(HeapGraphEdge* edge) { |
3234 writer_->AddCharacter(','); | 3418 writer_->AddCharacter(','); |
3235 writer_->AddNumber(edge->type()); | 3419 writer_->AddNumber(edge->type()); |
3236 writer_->AddCharacter(','); | 3420 writer_->AddCharacter(','); |
3237 if (edge->type() == HeapGraphEdge::kElement | 3421 if (edge->type() == HeapGraphEdge::kElement |
3238 || edge->type() == HeapGraphEdge::kHidden) { | 3422 || edge->type() == HeapGraphEdge::kHidden |
| 3423 || edge->type() == HeapGraphEdge::kWeak) { |
3239 writer_->AddNumber(edge->index()); | 3424 writer_->AddNumber(edge->index()); |
3240 } else { | 3425 } else { |
3241 writer_->AddNumber(GetStringId(edge->name())); | 3426 writer_->AddNumber(GetStringId(edge->name())); |
3242 } | 3427 } |
3243 writer_->AddCharacter(','); | 3428 writer_->AddCharacter(','); |
3244 writer_->AddNumber(GetNodeId(edge->to())); | 3429 writer_->AddNumber(GetNodeId(edge->to())); |
3245 } | 3430 } |
3246 | 3431 |
3247 | 3432 |
3248 void HeapSnapshotJSONSerializer::SerializeNode(HeapEntry* entry) { | 3433 void HeapSnapshotJSONSerializer::SerializeNode(HeapEntry* entry) { |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3308 JSON_S("type") | 3493 JSON_S("type") |
3309 "," JSON_S("name_or_index") | 3494 "," JSON_S("name_or_index") |
3310 "," JSON_S("to_node")) | 3495 "," JSON_S("to_node")) |
3311 "," JSON_S("types") ":" JSON_A( | 3496 "," JSON_S("types") ":" JSON_A( |
3312 JSON_A( | 3497 JSON_A( |
3313 JSON_S("context") | 3498 JSON_S("context") |
3314 "," JSON_S("element") | 3499 "," JSON_S("element") |
3315 "," JSON_S("property") | 3500 "," JSON_S("property") |
3316 "," JSON_S("internal") | 3501 "," JSON_S("internal") |
3317 "," JSON_S("hidden") | 3502 "," JSON_S("hidden") |
3318 "," JSON_S("shortcut")) | 3503 "," JSON_S("shortcut") |
| 3504 "," JSON_S("weak")) |
3319 "," JSON_S("string_or_number") | 3505 "," JSON_S("string_or_number") |
3320 "," JSON_S("node")))))); | 3506 "," JSON_S("node")))))); |
3321 #undef JSON_S | 3507 #undef JSON_S |
3322 #undef JSON_O | 3508 #undef JSON_O |
3323 #undef JSON_A | 3509 #undef JSON_A |
3324 | 3510 |
3325 const int node_fields_count = 7; | 3511 const int node_fields_count = 7; |
3326 // type,name,id,self_size,retained_size,dominator,children_count. | 3512 // type,name,id,self_size,retained_size,dominator,children_count. |
3327 const int edge_fields_count = 3; // type,name|index,to_node. | 3513 const int edge_fields_count = 3; // type,name|index,to_node. |
3328 List<HashMap::Entry*> sorted_nodes; | 3514 List<HashMap::Entry*> sorted_nodes; |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3443 | 3629 |
3444 | 3630 |
3445 void HeapSnapshotJSONSerializer::SortHashMap( | 3631 void HeapSnapshotJSONSerializer::SortHashMap( |
3446 HashMap* map, List<HashMap::Entry*>* sorted_entries) { | 3632 HashMap* map, List<HashMap::Entry*>* sorted_entries) { |
3447 for (HashMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) | 3633 for (HashMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) |
3448 sorted_entries->Add(p); | 3634 sorted_entries->Add(p); |
3449 sorted_entries->Sort(SortUsingEntryValue); | 3635 sorted_entries->Sort(SortUsingEntryValue); |
3450 } | 3636 } |
3451 | 3637 |
3452 } } // namespace v8::internal | 3638 } } // namespace v8::internal |
OLD | NEW |