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

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

Issue 8716009: 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
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)
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« src/objects.h ('K') | « 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