Chromium Code Reviews| 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 |