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