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

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

Issue 8822019: Reapply r10158: Distinguish weak references in heap snapshots, group GC roots. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/profile-generator.h ('k') | src/profile-generator-inl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/profile-generator.h ('k') | src/profile-generator-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698