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

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

Issue 6626043: Add an interface for an embedder to provide information about native (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 9 years, 9 months 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 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 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 11 matching lines...) Expand all
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #ifdef ENABLE_LOGGING_AND_PROFILING 28 #ifdef ENABLE_LOGGING_AND_PROFILING
29 29
30 #include "v8.h" 30 #include "v8.h"
31 #include "global-handles.h" 31 #include "global-handles.h"
32 #include "heap-profiler.h"
32 #include "scopeinfo.h" 33 #include "scopeinfo.h"
33 #include "top.h" 34 #include "top.h"
34 #include "unicode.h" 35 #include "unicode.h"
35 #include "zone-inl.h" 36 #include "zone-inl.h"
36 37
37 #include "profile-generator-inl.h" 38 #include "profile-generator-inl.h"
38 39
39 namespace v8 { 40 namespace v8 {
40 namespace internal { 41 namespace internal {
41 42
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
87 } 88 }
88 } 89 }
89 } 90 }
90 91
91 92
92 StringsStorage::StringsStorage() 93 StringsStorage::StringsStorage()
93 : names_(StringsMatch) { 94 : names_(StringsMatch) {
94 } 95 }
95 96
96 97
97 static void DeleteIndexName(char** name_ptr) {
98 DeleteArray(*name_ptr);
99 }
100
101
102 StringsStorage::~StringsStorage() { 98 StringsStorage::~StringsStorage() {
103 for (HashMap::Entry* p = names_.Start(); 99 for (HashMap::Entry* p = names_.Start();
104 p != NULL; 100 p != NULL;
105 p = names_.Next(p)) { 101 p = names_.Next(p)) {
106 DeleteArray(reinterpret_cast<const char*>(p->value)); 102 DeleteArray(reinterpret_cast<const char*>(p->value));
107 } 103 }
108 index_names_.Iterate(DeleteIndexName); 104 }
105
106
107 const char* StringsStorage::PrintF(const char* format, ...) {
108 va_list args;
109 va_start(args, format);
110 const char* result = VPrintF(format, args);
111 va_end(args);
112 return result;
113 }
114
115
116 const char* StringsStorage::AddOrDisposeString(char* str, uint32_t hash) {
117 HashMap::Entry* cache_entry = names_.Lookup(str, hash, true);
118 if (cache_entry->value == NULL) {
119 // New entry added.
120 cache_entry->value = str;
121 } else {
122 DeleteArray(str);
123 }
124 return reinterpret_cast<const char*>(cache_entry->value);
125 }
126
127
128 const char* StringsStorage::VPrintF(const char* format, va_list args) {
129 Vector<char> str = Vector<char>::New(1024);
130 int len = OS::VSNPrintF(str, format, args);
131 if (len == -1) {
132 DeleteArray(str.start());
133 return format;
134 }
135 uint32_t hash = HashSequentialString(str.start(), len);
136 return AddOrDisposeString(str.start(), hash);
109 } 137 }
110 138
111 139
112 const char* StringsStorage::GetName(String* name) { 140 const char* StringsStorage::GetName(String* name) {
113 if (name->IsString()) { 141 if (name->IsString()) {
114 char* c_name = 142 return AddOrDisposeString(
115 name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL).Detach(); 143 name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL).Detach(),
116 HashMap::Entry* cache_entry = names_.Lookup(c_name, name->Hash(), true); 144 name->Hash());
117 if (cache_entry->value == NULL) {
118 // New entry added.
119 cache_entry->value = c_name;
120 } else {
121 DeleteArray(c_name);
122 }
123 return reinterpret_cast<const char*>(cache_entry->value);
124 } 145 }
125 return ""; 146 return "";
126 } 147 }
127 148
128 149
129 const char* StringsStorage::GetName(int index) { 150 const char* StringsStorage::GetName(int index) {
130 ASSERT(index >= 0); 151 return PrintF("%d", index);
131 if (index_names_.length() <= index) {
132 index_names_.AddBlock(
133 NULL, index - index_names_.length() + 1);
134 }
135 if (index_names_[index] == NULL) {
136 const int kMaximumNameLength = 32;
137 char* name = NewArray<char>(kMaximumNameLength);
138 OS::SNPrintF(Vector<char>(name, kMaximumNameLength), "%d", index);
139 index_names_[index] = name;
140 }
141 return index_names_[index];
142 } 152 }
143 153
144 154
145 const char* CodeEntry::kEmptyNamePrefix = ""; 155 const char* CodeEntry::kEmptyNamePrefix = "";
146 156
147 157
148 void CodeEntry::CopyData(const CodeEntry& source) { 158 void CodeEntry::CopyData(const CodeEntry& source) {
149 tag_ = source.tag_; 159 tag_ = source.tag_;
150 name_prefix_ = source.name_prefix_; 160 name_prefix_ = source.name_prefix_;
151 name_ = source.name_; 161 name_ = source.name_;
(...skipping 850 matching lines...) Expand 10 before | Expand all | Expand 10 after
1002 const char* HeapEntry::TypeAsString() { 1012 const char* HeapEntry::TypeAsString() {
1003 switch (type()) { 1013 switch (type()) {
1004 case kHidden: return "/hidden/"; 1014 case kHidden: return "/hidden/";
1005 case kObject: return "/object/"; 1015 case kObject: return "/object/";
1006 case kClosure: return "/closure/"; 1016 case kClosure: return "/closure/";
1007 case kString: return "/string/"; 1017 case kString: return "/string/";
1008 case kCode: return "/code/"; 1018 case kCode: return "/code/";
1009 case kArray: return "/array/"; 1019 case kArray: return "/array/";
1010 case kRegExp: return "/regexp/"; 1020 case kRegExp: return "/regexp/";
1011 case kHeapNumber: return "/number/"; 1021 case kHeapNumber: return "/number/";
1022 case kNative: return "/native/";
1012 default: return "???"; 1023 default: return "???";
1013 } 1024 }
1014 } 1025 }
1015 1026
1016 1027
1017 int HeapEntry::EntriesSize(int entries_count, 1028 int HeapEntry::EntriesSize(int entries_count,
1018 int children_count, 1029 int children_count,
1019 int retainers_count) { 1030 int retainers_count) {
1020 return sizeof(HeapEntry) * entries_count // NOLINT 1031 return sizeof(HeapEntry) * entries_count // NOLINT
1021 + sizeof(HeapGraphEdge) * children_count // NOLINT 1032 + sizeof(HeapGraphEdge) * children_count // NOLINT
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
1198 HeapSnapshot::HeapSnapshot(HeapSnapshotsCollection* collection, 1209 HeapSnapshot::HeapSnapshot(HeapSnapshotsCollection* collection,
1199 HeapSnapshot::Type type, 1210 HeapSnapshot::Type type,
1200 const char* title, 1211 const char* title,
1201 unsigned uid) 1212 unsigned uid)
1202 : collection_(collection), 1213 : collection_(collection),
1203 type_(type), 1214 type_(type),
1204 title_(title), 1215 title_(title),
1205 uid_(uid), 1216 uid_(uid),
1206 root_entry_(NULL), 1217 root_entry_(NULL),
1207 gc_roots_entry_(NULL), 1218 gc_roots_entry_(NULL),
1219 dom_subtrees_root_entry_(NULL),
1208 raw_entries_(NULL), 1220 raw_entries_(NULL),
1209 entries_sorted_(false), 1221 entries_sorted_(false),
1210 retaining_paths_(HeapEntry::Match) { 1222 retaining_paths_(HeapEntry::Match) {
1211 STATIC_ASSERT( 1223 STATIC_ASSERT(
1212 sizeof(HeapGraphEdge) == 1224 sizeof(HeapGraphEdge) ==
1213 SnapshotSizeConstants<sizeof(void*)>::kExpectedHeapGraphEdgeSize); // NOL INT 1225 SnapshotSizeConstants<sizeof(void*)>::kExpectedHeapGraphEdgeSize); // NOL INT
1214 STATIC_ASSERT( 1226 STATIC_ASSERT(
1215 sizeof(HeapEntry) == 1227 sizeof(HeapEntry) ==
1216 SnapshotSizeConstants<sizeof(void*)>::kExpectedHeapEntrySize); // NOLINT 1228 SnapshotSizeConstants<sizeof(void*)>::kExpectedHeapEntrySize); // NOLINT
1217 } 1229 }
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
1272 ASSERT(gc_roots_entry_ == NULL); 1284 ASSERT(gc_roots_entry_ == NULL);
1273 return (gc_roots_entry_ = AddEntry(HeapEntry::kObject, 1285 return (gc_roots_entry_ = AddEntry(HeapEntry::kObject,
1274 "(GC roots)", 1286 "(GC roots)",
1275 HeapObjectsMap::kGcRootsObjectId, 1287 HeapObjectsMap::kGcRootsObjectId,
1276 0, 1288 0,
1277 children_count, 1289 children_count,
1278 retainers_count)); 1290 retainers_count));
1279 } 1291 }
1280 1292
1281 1293
1294 HeapEntry* HeapSnapshot::AddNativesRootEntry(int children_count,
1295 int retainers_count) {
1296 ASSERT(dom_subtrees_root_entry_ == NULL);
1297 return (dom_subtrees_root_entry_ = AddEntry(
1298 HeapEntry::kObject,
1299 "(Native objects)",
1300 HeapObjectsMap::kNativesRootObjectId,
1301 0,
1302 children_count,
1303 retainers_count));
1304 }
1305
1306
1282 HeapEntry* HeapSnapshot::AddEntry(HeapEntry::Type type, 1307 HeapEntry* HeapSnapshot::AddEntry(HeapEntry::Type type,
1283 const char* name, 1308 const char* name,
1284 uint64_t id, 1309 uint64_t id,
1285 int size, 1310 int size,
1286 int children_count, 1311 int children_count,
1287 int retainers_count) { 1312 int retainers_count) {
1288 HeapEntry* entry = GetNextEntryToInit(); 1313 HeapEntry* entry = GetNextEntryToInit();
1289 entry->Init(this, type, name, id, size, children_count, retainers_count); 1314 entry->Init(this, type, name, id, size, children_count, retainers_count);
1290 return entry; 1315 return entry;
1291 } 1316 }
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
1365 } 1390 }
1366 return &entries_; 1391 return &entries_;
1367 } 1392 }
1368 1393
1369 1394
1370 void HeapSnapshot::Print(int max_depth) { 1395 void HeapSnapshot::Print(int max_depth) {
1371 root()->Print(max_depth, 0); 1396 root()->Print(max_depth, 0);
1372 } 1397 }
1373 1398
1374 1399
1375 const uint64_t HeapObjectsMap::kInternalRootObjectId = 0; 1400 const uint64_t HeapObjectsMap::kInternalRootObjectId = 1;
Vitaly Repeshko 2011/03/09 14:15:49 Document why these have to be odd.
mnaganov (inactive) 2011/03/09 15:26:32 Done.
1376 const uint64_t HeapObjectsMap::kGcRootsObjectId = 1; 1401 const uint64_t HeapObjectsMap::kGcRootsObjectId = 3;
1402 const uint64_t HeapObjectsMap::kNativesRootObjectId = 5;
1377 // Increase kFirstAvailableObjectId if new 'special' objects appear. 1403 // Increase kFirstAvailableObjectId if new 'special' objects appear.
1378 const uint64_t HeapObjectsMap::kFirstAvailableObjectId = 2; 1404 const uint64_t HeapObjectsMap::kFirstAvailableObjectId = 7;
1379 1405
1380 HeapObjectsMap::HeapObjectsMap() 1406 HeapObjectsMap::HeapObjectsMap()
1381 : initial_fill_mode_(true), 1407 : initial_fill_mode_(true),
1382 next_id_(kFirstAvailableObjectId), 1408 next_id_(kFirstAvailableObjectId),
1383 entries_map_(AddressesMatch), 1409 entries_map_(AddressesMatch),
1384 entries_(new List<EntryInfo>()) { } 1410 entries_(new List<EntryInfo>()) { }
1385 1411
1386 1412
1387 HeapObjectsMap::~HeapObjectsMap() { 1413 HeapObjectsMap::~HeapObjectsMap() {
1388 delete entries_; 1414 delete entries_;
1389 } 1415 }
1390 1416
1391 1417
1392 void HeapObjectsMap::SnapshotGenerationFinished() { 1418 void HeapObjectsMap::SnapshotGenerationFinished() {
1393 initial_fill_mode_ = false; 1419 initial_fill_mode_ = false;
1394 RemoveDeadEntries(); 1420 RemoveDeadEntries();
1395 } 1421 }
1396 1422
1397 1423
1398 uint64_t HeapObjectsMap::FindObject(Address addr) { 1424 uint64_t HeapObjectsMap::FindObject(Address addr) {
1399 if (!initial_fill_mode_) { 1425 if (!initial_fill_mode_) {
1400 uint64_t existing = FindEntry(addr); 1426 uint64_t existing = FindEntry(addr);
1401 if (existing != 0) return existing; 1427 if (existing != 0) return existing;
1402 } 1428 }
1403 uint64_t id = next_id_++; 1429 uint64_t id = next_id_;
1430 next_id_ += 2;
1404 AddEntry(addr, id); 1431 AddEntry(addr, id);
1405 return id; 1432 return id;
1406 } 1433 }
1407 1434
1408 1435
1409 void HeapObjectsMap::MoveObject(Address from, Address to) { 1436 void HeapObjectsMap::MoveObject(Address from, Address to) {
1410 if (from == to) return; 1437 if (from == to) return;
1411 HashMap::Entry* entry = entries_map_.Lookup(from, AddressHash(from), false); 1438 HashMap::Entry* entry = entries_map_.Lookup(from, AddressHash(from), false);
1412 if (entry != NULL) { 1439 if (entry != NULL) {
1413 void* value = entry->value; 1440 void* value = entry->value;
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
1461 for (int i = 0; i < dead_entries.length(); ++i) { 1488 for (int i = 0; i < dead_entries.length(); ++i) {
1462 void* raw_entry = dead_entries[i]; 1489 void* raw_entry = dead_entries[i];
1463 entries_map_.Remove( 1490 entries_map_.Remove(
1464 raw_entry, AddressHash(reinterpret_cast<Address>(raw_entry))); 1491 raw_entry, AddressHash(reinterpret_cast<Address>(raw_entry)));
1465 } 1492 }
1466 delete entries_; 1493 delete entries_;
1467 entries_ = new_entries; 1494 entries_ = new_entries;
1468 } 1495 }
1469 1496
1470 1497
1498 uint64_t HeapObjectsMap::GenerateId(v8::RetainedObjectInfo* info) {
1499 uint64_t id = static_cast<uint64_t>(info->GetHash());
1500 const char* label = info->GetLabel();
1501 id ^= HashSequentialString(label, strlen(label));
1502 intptr_t element_count = info->GetElementCount();
1503 if (element_count != -1)
1504 id ^= ComputeIntegerHash(static_cast<uint32_t>(element_count));
1505 return id << 1;
1506 }
1507
1508
1471 HeapSnapshotsCollection::HeapSnapshotsCollection() 1509 HeapSnapshotsCollection::HeapSnapshotsCollection()
1472 : is_tracking_objects_(false), 1510 : is_tracking_objects_(false),
1473 snapshots_uids_(HeapSnapshotsMatch), 1511 snapshots_uids_(HeapSnapshotsMatch),
1474 token_enumerator_(new TokenEnumerator()) { 1512 token_enumerator_(new TokenEnumerator()) {
1475 } 1513 }
1476 1514
1477 1515
1478 static void DeleteHeapSnapshot(HeapSnapshot** snapshot_ptr) { 1516 static void DeleteHeapSnapshot(HeapSnapshot** snapshot_ptr) {
1479 delete *snapshot_ptr; 1517 delete *snapshot_ptr;
1480 } 1518 }
(...skipping 29 matching lines...) Expand all
1510 1548
1511 1549
1512 HeapSnapshot* HeapSnapshotsCollection::GetSnapshot(unsigned uid) { 1550 HeapSnapshot* HeapSnapshotsCollection::GetSnapshot(unsigned uid) {
1513 HashMap::Entry* entry = snapshots_uids_.Lookup(reinterpret_cast<void*>(uid), 1551 HashMap::Entry* entry = snapshots_uids_.Lookup(reinterpret_cast<void*>(uid),
1514 static_cast<uint32_t>(uid), 1552 static_cast<uint32_t>(uid),
1515 false); 1553 false);
1516 return entry != NULL ? reinterpret_cast<HeapSnapshot*>(entry->value) : NULL; 1554 return entry != NULL ? reinterpret_cast<HeapSnapshot*>(entry->value) : NULL;
1517 } 1555 }
1518 1556
1519 1557
1558 const char* HeapSnapshotsCollection::PrintF(const char* format, ...) {
1559 va_list args;
1560 va_start(args, format);
1561 const char* result = names_.VPrintF(format, args);
1562 va_end(args);
1563 return result;
1564 }
1565
1566
1520 HeapSnapshotsDiff* HeapSnapshotsCollection::CompareSnapshots( 1567 HeapSnapshotsDiff* HeapSnapshotsCollection::CompareSnapshots(
1521 HeapSnapshot* snapshot1, 1568 HeapSnapshot* snapshot1,
1522 HeapSnapshot* snapshot2) { 1569 HeapSnapshot* snapshot2) {
1523 return comparator_.Compare(snapshot1, snapshot2); 1570 return comparator_.Compare(snapshot1, snapshot2);
1524 } 1571 }
1525 1572
1526 1573
1527 HeapEntry *const HeapEntriesMap::kHeapEntryPlaceholder = 1574 HeapEntry *const HeapEntriesMap::kHeapEntryPlaceholder =
1528 reinterpret_cast<HeapEntry*>(1); 1575 reinterpret_cast<HeapEntry*>(1);
1529 1576
(...skipping 14 matching lines...) Expand all
1544 1591
1545 void HeapEntriesMap::AllocateEntries() { 1592 void HeapEntriesMap::AllocateEntries() {
1546 for (HashMap::Entry* p = entries_.Start(); 1593 for (HashMap::Entry* p = entries_.Start();
1547 p != NULL; 1594 p != NULL;
1548 p = entries_.Next(p)) { 1595 p = entries_.Next(p)) {
1549 EntryInfo* entry_info = reinterpret_cast<EntryInfo*>(p->value); 1596 EntryInfo* entry_info = reinterpret_cast<EntryInfo*>(p->value);
1550 entry_info->entry = entry_info->allocator->AllocateEntry( 1597 entry_info->entry = entry_info->allocator->AllocateEntry(
1551 p->key, 1598 p->key,
1552 entry_info->children_count, 1599 entry_info->children_count,
1553 entry_info->retainers_count); 1600 entry_info->retainers_count);
1601 ASSERT(entry_info->entry != NULL);
1602 ASSERT(entry_info->entry != kHeapEntryPlaceholder);
1554 entry_info->children_count = 0; 1603 entry_info->children_count = 0;
1555 entry_info->retainers_count = 0; 1604 entry_info->retainers_count = 0;
1556 } 1605 }
1557 } 1606 }
1558 1607
1559 1608
1560 HeapEntry* HeapEntriesMap::Map(HeapThing thing) { 1609 HeapEntry* HeapEntriesMap::Map(HeapThing thing) {
1561 HashMap::Entry* cache_entry = entries_.Lookup(thing, Hash(thing), false); 1610 HashMap::Entry* cache_entry = entries_.Lookup(thing, Hash(thing), false);
1562 if (cache_entry != NULL) { 1611 if (cache_entry != NULL) {
1563 EntryInfo* entry_info = reinterpret_cast<EntryInfo*>(cache_entry->value); 1612 EntryInfo* entry_info = reinterpret_cast<EntryInfo*>(cache_entry->value);
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
1625 entries_.Lookup(object, HeapEntriesMap::Hash(object), true); 1674 entries_.Lookup(object, HeapEntriesMap::Hash(object), true);
1626 if (cache_entry->value == NULL) { 1675 if (cache_entry->value == NULL) {
1627 cache_entry->value = HeapEntriesMap::kHeapEntryPlaceholder; 1676 cache_entry->value = HeapEntriesMap::kHeapEntryPlaceholder;
1628 } 1677 }
1629 } 1678 }
1630 1679
1631 1680
1632 HeapObject *const V8HeapExplorer::kInternalRootObject = 1681 HeapObject *const V8HeapExplorer::kInternalRootObject =
1633 reinterpret_cast<HeapObject*>(1); 1682 reinterpret_cast<HeapObject*>(1);
1634 HeapObject *const V8HeapExplorer::kGcRootsObject = 1683 HeapObject *const V8HeapExplorer::kGcRootsObject =
1635 reinterpret_cast<HeapObject*>(2); 1684 reinterpret_cast<HeapObject*>(3);
Vitaly Repeshko 2011/03/09 14:15:49 Shouldn't the constants defined above be reused he
mnaganov (inactive) 2011/03/09 15:26:32 Done.
1636 1685
1637 1686
1638 V8HeapExplorer::V8HeapExplorer( 1687 V8HeapExplorer::V8HeapExplorer(
1639 HeapSnapshot* snapshot, 1688 HeapSnapshot* snapshot,
1640 SnapshottingProgressReportingInterface* progress) 1689 SnapshottingProgressReportingInterface* progress)
1641 : snapshot_(snapshot), 1690 : snapshot_(snapshot),
1642 collection_(snapshot_->collection()), 1691 collection_(snapshot_->collection()),
1643 progress_(progress), 1692 progress_(progress),
1644 filler_(NULL) { 1693 filler_(NULL) {
1645 } 1694 }
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
1742 return snapshot_->AddEntry(type, 1791 return snapshot_->AddEntry(type,
1743 name, 1792 name,
1744 collection_->GetObjectId(object->address()), 1793 collection_->GetObjectId(object->address()),
1745 object->Size(), 1794 object->Size(),
1746 children_count, 1795 children_count,
1747 retainers_count); 1796 retainers_count);
1748 } 1797 }
1749 1798
1750 1799
1751 void V8HeapExplorer::AddRootEntries(SnapshotFillerInterface* filler) { 1800 void V8HeapExplorer::AddRootEntries(SnapshotFillerInterface* filler) {
1752 filler->AddEntry(kInternalRootObject); 1801 filler->AddEntry(kInternalRootObject, this);
1753 filler->AddEntry(kGcRootsObject); 1802 filler->AddEntry(kGcRootsObject, this);
1754 } 1803 }
1755 1804
1756 1805
1757 int V8HeapExplorer::EstimateObjectsCount() { 1806 int V8HeapExplorer::EstimateObjectsCount() {
1758 HeapIterator iterator(HeapIterator::kFilterUnreachable); 1807 HeapIterator iterator(HeapIterator::kFilterUnreachable);
1759 int objects_count = 0; 1808 int objects_count = 0;
1760 for (HeapObject* obj = iterator.next(); 1809 for (HeapObject* obj = iterator.next();
1761 obj != NULL; 1810 obj != NULL;
1762 obj = iterator.next(), ++objects_count) {} 1811 obj = iterator.next(), ++objects_count) {}
1763 return objects_count; 1812 return objects_count;
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
1933 int length = js_obj->GetInternalFieldCount(); 1982 int length = js_obj->GetInternalFieldCount();
1934 for (int i = 0; i < length; ++i) { 1983 for (int i = 0; i < length; ++i) {
1935 Object* o = js_obj->GetInternalField(i); 1984 Object* o = js_obj->GetInternalField(i);
1936 SetInternalReference(js_obj, entry, i, o); 1985 SetInternalReference(js_obj, entry, i, o);
1937 } 1986 }
1938 } 1987 }
1939 1988
1940 1989
1941 HeapEntry* V8HeapExplorer::GetEntry(Object* obj) { 1990 HeapEntry* V8HeapExplorer::GetEntry(Object* obj) {
1942 if (!obj->IsHeapObject()) return NULL; 1991 if (!obj->IsHeapObject()) return NULL;
1943 return filler_->FindOrAddEntry(obj); 1992 return filler_->FindOrAddEntry(obj, this);
1944 } 1993 }
1945 1994
1946 1995
1947 class RootsReferencesExtractor : public ObjectVisitor { 1996 class RootsReferencesExtractor : public ObjectVisitor {
1948 public: 1997 public:
1949 explicit RootsReferencesExtractor(V8HeapExplorer* explorer) 1998 explicit RootsReferencesExtractor(V8HeapExplorer* explorer)
1950 : explorer_(explorer) { 1999 : explorer_(explorer) {
1951 } 2000 }
1952 void VisitPointers(Object** start, Object** end) { 2001 void VisitPointers(Object** start, Object** end) {
1953 for (Object** p = start; p < end; p++) explorer_->SetGcRootsReference(*p); 2002 for (Object** p = start; p < end; p++) explorer_->SetGcRootsReference(*p);
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
2125 HeapEntry* child_entry = GetEntry(child_obj); 2174 HeapEntry* child_entry = GetEntry(child_obj);
2126 if (child_entry != NULL) { 2175 if (child_entry != NULL) {
2127 filler_->SetIndexedAutoIndexReference( 2176 filler_->SetIndexedAutoIndexReference(
2128 HeapGraphEdge::kElement, 2177 HeapGraphEdge::kElement,
2129 kGcRootsObject, snapshot_->gc_roots(), 2178 kGcRootsObject, snapshot_->gc_roots(),
2130 child_obj, child_entry); 2179 child_obj, child_entry);
2131 } 2180 }
2132 } 2181 }
2133 2182
2134 2183
2184 class GlobalHandlesExtractor : public ObjectVisitor {
2185 public:
2186 explicit GlobalHandlesExtractor(NativeObjectsExplorer* explorer)
2187 : explorer_(explorer) {}
2188 virtual ~GlobalHandlesExtractor() {}
2189 virtual void VisitPointers(Object** start, Object** end) {
2190 UNREACHABLE();
2191 }
2192 virtual void VisitEmbedderReference(Object** p, uint16_t class_id) {
2193 explorer_->VisitSubtreeWrapper(p, class_id);
2194 }
2195 private:
2196 NativeObjectsExplorer* explorer_;
2197 };
2198
2199 HeapThing const NativeObjectsExplorer::kNativesRootObject =
2200 reinterpret_cast<HeapThing>(5);
Vitaly Repeshko 2011/03/09 14:15:49 Same as above.
mnaganov (inactive) 2011/03/09 15:26:32 Done.
2201
2202
2203 NativeObjectsExplorer::NativeObjectsExplorer(
2204 HeapSnapshot* snapshot, SnapshottingProgressReportingInterface* progress)
2205 : snapshot_(snapshot),
2206 collection_(snapshot_->collection()),
2207 progress_(progress),
2208 embedder_queried_(false),
2209 objects_by_info_(RetainedInfosMatch),
2210 filler_(NULL) {
2211 }
2212
2213
2214 NativeObjectsExplorer::~NativeObjectsExplorer() {
2215 for (HashMap::Entry* p = objects_by_info_.Start();
2216 p != NULL;
2217 p = objects_by_info_.Next(p)) {
2218 v8::RetainedObjectInfo* info =
2219 reinterpret_cast<v8::RetainedObjectInfo*>(p->key);
2220 info->Dispose();
2221 List<HeapObject*>* objects =
2222 reinterpret_cast<List<HeapObject*>* >(p->value);
2223 delete objects;
2224 }
2225 }
2226
2227
2228 HeapEntry* NativeObjectsExplorer::AllocateEntry(
2229 HeapThing ptr, int children_count, int retainers_count) {
2230 if (ptr == kNativesRootObject) {
2231 return snapshot_->AddNativesRootEntry(children_count, retainers_count);
2232 } else {
2233 v8::RetainedObjectInfo* info =
2234 reinterpret_cast<v8::RetainedObjectInfo*>(ptr);
2235 intptr_t elements = info->GetElementCount();
2236 intptr_t size = info->GetSizeInBytes();
2237 return snapshot_->AddEntry(
2238 HeapEntry::kNative,
2239 elements != -1 ?
2240 collection_->PrintF("%s / %" V8_PTR_PREFIX "d entries",
2241 info->GetLabel(),
2242 info->GetElementCount()) :
2243 info->GetLabel(),
Vitaly Repeshko 2011/03/09 14:15:49 What if the returned label's lifetime is tied to t
mnaganov (inactive) 2011/03/09 15:26:32 Fixed.
2244 HeapObjectsMap::GenerateId(info),
2245 size != -1 ? static_cast<int>(size) : 0,
2246 children_count,
2247 retainers_count);
2248 }
2249 }
2250
2251
2252 void NativeObjectsExplorer::AddRootEntries(SnapshotFillerInterface* filler) {
2253 if (EstimateObjectsCount() <= 0) return;
2254 filler->AddEntry(kNativesRootObject, this);
2255 }
2256
2257
2258 int NativeObjectsExplorer::EstimateObjectsCount() {
2259 FillRetainedObjects();
2260 return objects_by_info_.occupancy();
2261 }
2262
2263
2264 void NativeObjectsExplorer::FillRetainedObjects() {
2265 if (embedder_queried_) return;
2266 // Record objects that are joined into ObjectGroups.
2267 Heap::call_global_gc_prologue_callback();
2268 List<ObjectGroup*>* groups = GlobalHandles::ObjectGroups();
2269 for (int i = 0; i < groups->length(); ++i) {
2270 ObjectGroup* group = groups->at(i);
2271 if (group->info_ == NULL) continue;
2272 List<HeapObject*>* list = GetListMaybeDisposeInfo(group->info_);
2273 for (int j = 0; j < group->objects_.length(); ++j) {
2274 HeapObject* obj = HeapObject::cast(*group->objects_[j]);
2275 list->Add(obj);
2276 in_groups_.Insert(obj);
2277 }
2278 group->info_ = NULL; // Acquire info object ownership.
2279 }
2280 GlobalHandles::RemoveObjectGroups();
2281 Heap::call_global_gc_epilogue_callback();
2282 // Record objects that are not in ObjectGroups, but have class ID.
2283 GlobalHandlesExtractor extractor(this);
2284 GlobalHandles::IterateAllRootsWithClassIds(&extractor);
2285 embedder_queried_ = true;
2286 }
2287
2288
2289 List<HeapObject*>* NativeObjectsExplorer::GetListMaybeDisposeInfo(
2290 v8::RetainedObjectInfo* info) {
2291 HashMap::Entry* entry =
2292 objects_by_info_.Lookup(info, InfoHash(info), true);
2293 if (entry->value != NULL) {
2294 info->Dispose();
2295 } else {
2296 entry->value = new List<HeapObject*>(4);
2297 }
2298 return reinterpret_cast<List<HeapObject*>* >(entry->value);
2299 }
2300
2301
2302 bool NativeObjectsExplorer::IterateAndExtractReferences(
2303 SnapshotFillerInterface* filler) {
2304 if (EstimateObjectsCount() <= 0) return true;
2305 filler_ = filler;
2306 FillRetainedObjects();
2307 for (HashMap::Entry* p = objects_by_info_.Start();
2308 p != NULL;
2309 p = objects_by_info_.Next(p)) {
2310 v8::RetainedObjectInfo* info =
2311 reinterpret_cast<v8::RetainedObjectInfo*>(p->key);
2312 SetNativeRootReference(info);
2313 List<HeapObject*>* objects =
2314 reinterpret_cast<List<HeapObject*>* >(p->value);
2315 for (int i = 0; i < objects->length(); ++i) {
2316 SetWrapperNativeReferences(objects->at(i), info);
2317 }
2318 }
2319 SetRootNativesRootReference();
2320 filler_ = NULL;
2321 return true;
2322 }
2323
2324
2325 void NativeObjectsExplorer::SetNativeRootReference(
2326 v8::RetainedObjectInfo* info) {
2327 HeapEntry* child_entry = filler_->FindOrAddEntry(info, this);
2328 ASSERT(child_entry != NULL);
2329 filler_->SetIndexedAutoIndexReference(
2330 HeapGraphEdge::kElement,
2331 kNativesRootObject, snapshot_->dom_subtrees_root(),
2332 info, child_entry);
2333 }
2334
2335
2336 void NativeObjectsExplorer::SetWrapperNativeReferences(
2337 HeapObject* wrapper, v8::RetainedObjectInfo* info) {
2338 HeapEntry* wrapper_entry = filler_->FindEntry(wrapper);
2339 ASSERT(wrapper_entry != NULL);
2340 HeapEntry* info_entry = filler_->FindOrAddEntry(info, this);
2341 ASSERT(info_entry != NULL);
2342 filler_->SetNamedReference(HeapGraphEdge::kInternal,
2343 wrapper, wrapper_entry,
2344 "Native",
2345 info, info_entry);
2346 filler_->SetIndexedAutoIndexReference(HeapGraphEdge::kElement,
2347 info, info_entry,
2348 wrapper, wrapper_entry);
2349 }
2350
2351
2352 void NativeObjectsExplorer::SetRootNativesRootReference() {
2353 filler_->SetIndexedAutoIndexReference(
2354 HeapGraphEdge::kElement,
2355 V8HeapExplorer::kInternalRootObject, snapshot_->root(),
2356 kNativesRootObject, snapshot_->dom_subtrees_root());
2357 }
2358
2359
2360 void NativeObjectsExplorer::VisitSubtreeWrapper(Object** p, uint16_t class_id) {
2361 if (in_groups_.Contains(*p)) return;
2362 v8::RetainedObjectInfo* info =
2363 HeapProfiler::ExecuteWrapperClassCallback(class_id, p);
2364 if (info == NULL) return;
2365 GetListMaybeDisposeInfo(info)->Add(HeapObject::cast(*p));
2366 }
2367
2368
2135 HeapSnapshotGenerator::HeapSnapshotGenerator(HeapSnapshot* snapshot, 2369 HeapSnapshotGenerator::HeapSnapshotGenerator(HeapSnapshot* snapshot,
2136 v8::ActivityControl* control) 2370 v8::ActivityControl* control)
2137 : snapshot_(snapshot), 2371 : snapshot_(snapshot),
2138 control_(control), 2372 control_(control),
2139 v8_heap_explorer_(snapshot_, this) { 2373 v8_heap_explorer_(snapshot_, this),
2374 dom_explorer_(snapshot_, this) {
2140 } 2375 }
2141 2376
2142 2377
2143 class SnapshotCounter : public SnapshotFillerInterface { 2378 class SnapshotCounter : public SnapshotFillerInterface {
2144 public: 2379 public:
2145 SnapshotCounter(HeapEntriesAllocator* allocator, HeapEntriesMap* entries) 2380 explicit SnapshotCounter(HeapEntriesMap* entries) : entries_(entries) { }
2146 : allocator_(allocator), entries_(entries) { } 2381 HeapEntry* AddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) {
2147 HeapEntry* AddEntry(HeapThing ptr) { 2382 entries_->Pair(ptr, allocator, HeapEntriesMap::kHeapEntryPlaceholder);
2148 entries_->Pair(ptr, allocator_, HeapEntriesMap::kHeapEntryPlaceholder);
2149 return HeapEntriesMap::kHeapEntryPlaceholder; 2383 return HeapEntriesMap::kHeapEntryPlaceholder;
2150 } 2384 }
2151 HeapEntry* FindOrAddEntry(HeapThing ptr) { 2385 HeapEntry* FindEntry(HeapThing ptr) {
2152 HeapEntry* entry = entries_->Map(ptr); 2386 return entries_->Map(ptr);
2153 return entry != NULL ? entry : AddEntry(ptr); 2387 }
2388 HeapEntry* FindOrAddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) {
2389 HeapEntry* entry = FindEntry(ptr);
2390 return entry != NULL ? entry : AddEntry(ptr, allocator);
2154 } 2391 }
2155 void SetIndexedReference(HeapGraphEdge::Type, 2392 void SetIndexedReference(HeapGraphEdge::Type,
2156 HeapThing parent_ptr, 2393 HeapThing parent_ptr,
2157 HeapEntry*, 2394 HeapEntry*,
2158 int, 2395 int,
2159 HeapThing child_ptr, 2396 HeapThing child_ptr,
2160 HeapEntry*) { 2397 HeapEntry*) {
2161 entries_->CountReference(parent_ptr, child_ptr); 2398 entries_->CountReference(parent_ptr, child_ptr);
2162 } 2399 }
2163 void SetIndexedAutoIndexReference(HeapGraphEdge::Type, 2400 void SetIndexedAutoIndexReference(HeapGraphEdge::Type,
(...skipping 12 matching lines...) Expand all
2176 entries_->CountReference(parent_ptr, child_ptr); 2413 entries_->CountReference(parent_ptr, child_ptr);
2177 } 2414 }
2178 void SetNamedAutoIndexReference(HeapGraphEdge::Type, 2415 void SetNamedAutoIndexReference(HeapGraphEdge::Type,
2179 HeapThing parent_ptr, 2416 HeapThing parent_ptr,
2180 HeapEntry*, 2417 HeapEntry*,
2181 HeapThing child_ptr, 2418 HeapThing child_ptr,
2182 HeapEntry*) { 2419 HeapEntry*) {
2183 entries_->CountReference(parent_ptr, child_ptr); 2420 entries_->CountReference(parent_ptr, child_ptr);
2184 } 2421 }
2185 private: 2422 private:
2186 HeapEntriesAllocator* allocator_;
2187 HeapEntriesMap* entries_; 2423 HeapEntriesMap* entries_;
2188 }; 2424 };
2189 2425
2190 2426
2191 class SnapshotFiller : public SnapshotFillerInterface { 2427 class SnapshotFiller : public SnapshotFillerInterface {
2192 public: 2428 public:
2193 explicit SnapshotFiller(HeapSnapshot* snapshot, HeapEntriesMap* entries) 2429 explicit SnapshotFiller(HeapSnapshot* snapshot, HeapEntriesMap* entries)
2194 : snapshot_(snapshot), 2430 : snapshot_(snapshot),
2195 collection_(snapshot->collection()), 2431 collection_(snapshot->collection()),
2196 entries_(entries) { } 2432 entries_(entries) { }
2197 HeapEntry* AddEntry(HeapThing ptr) { 2433 HeapEntry* AddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) {
2198 UNREACHABLE(); 2434 UNREACHABLE();
2199 return NULL; 2435 return NULL;
2200 } 2436 }
2201 HeapEntry* FindOrAddEntry(HeapThing ptr) { 2437 HeapEntry* FindEntry(HeapThing ptr) {
2202 HeapEntry* entry = entries_->Map(ptr); 2438 return entries_->Map(ptr);
2203 return entry != NULL ? entry : AddEntry(ptr); 2439 }
2440 HeapEntry* FindOrAddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) {
2441 HeapEntry* entry = FindEntry(ptr);
2442 return entry != NULL ? entry : AddEntry(ptr, allocator);
2204 } 2443 }
2205 void SetIndexedReference(HeapGraphEdge::Type type, 2444 void SetIndexedReference(HeapGraphEdge::Type type,
2206 HeapThing parent_ptr, 2445 HeapThing parent_ptr,
2207 HeapEntry* parent_entry, 2446 HeapEntry* parent_entry,
2208 int index, 2447 int index,
2209 HeapThing child_ptr, 2448 HeapThing child_ptr,
2210 HeapEntry* child_entry) { 2449 HeapEntry* child_entry) {
2211 int child_index, retainer_index; 2450 int child_index, retainer_index;
2212 entries_->CountReference( 2451 entries_->CountReference(
2213 parent_ptr, child_ptr, &child_index, &retainer_index); 2452 parent_ptr, child_ptr, &child_index, &retainer_index);
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
2296 return 2535 return
2297 control_->ReportProgressValue(progress_counter_, progress_total_) == 2536 control_->ReportProgressValue(progress_counter_, progress_total_) ==
2298 v8::ActivityControl::kContinue; 2537 v8::ActivityControl::kContinue;
2299 } 2538 }
2300 return true; 2539 return true;
2301 } 2540 }
2302 2541
2303 2542
2304 void HeapSnapshotGenerator::SetProgressTotal(int iterations_count) { 2543 void HeapSnapshotGenerator::SetProgressTotal(int iterations_count) {
2305 if (control_ == NULL) return; 2544 if (control_ == NULL) return;
2306 progress_total_ = v8_heap_explorer_.EstimateObjectsCount() * iterations_count; 2545 progress_total_ = (
2546 v8_heap_explorer_.EstimateObjectsCount() +
2547 dom_explorer_.EstimateObjectsCount()) * iterations_count;
2307 progress_counter_ = 0; 2548 progress_counter_ = 0;
2308 } 2549 }
2309 2550
2310 2551
2311 bool HeapSnapshotGenerator::CountEntriesAndReferences() { 2552 bool HeapSnapshotGenerator::CountEntriesAndReferences() {
2312 SnapshotCounter counter(&v8_heap_explorer_, &entries_); 2553 SnapshotCounter counter(&entries_);
2313 v8_heap_explorer_.AddRootEntries(&counter); 2554 v8_heap_explorer_.AddRootEntries(&counter);
2314 return v8_heap_explorer_.IterateAndExtractReferences(&counter); 2555 dom_explorer_.AddRootEntries(&counter);
2556 return
2557 v8_heap_explorer_.IterateAndExtractReferences(&counter) &&
2558 dom_explorer_.IterateAndExtractReferences(&counter);
2315 } 2559 }
2316 2560
2317 2561
2318 bool HeapSnapshotGenerator::FillReferences() { 2562 bool HeapSnapshotGenerator::FillReferences() {
2319 SnapshotFiller filler(snapshot_, &entries_); 2563 SnapshotFiller filler(snapshot_, &entries_);
2320 return v8_heap_explorer_.IterateAndExtractReferences(&filler); 2564 return
2565 v8_heap_explorer_.IterateAndExtractReferences(&filler) &&
2566 dom_explorer_.IterateAndExtractReferences(&filler);
2321 } 2567 }
2322 2568
2323 2569
2324 void HeapSnapshotGenerator::FillReversePostorderIndexes( 2570 void HeapSnapshotGenerator::FillReversePostorderIndexes(
2325 Vector<HeapEntry*>* entries) { 2571 Vector<HeapEntry*>* entries) {
2326 snapshot_->ClearPaint(); 2572 snapshot_->ClearPaint();
2327 int current_entry = 0; 2573 int current_entry = 0;
2328 List<HeapEntry*> nodes_to_visit; 2574 List<HeapEntry*> nodes_to_visit;
2329 nodes_to_visit.Add(snapshot_->root()); 2575 nodes_to_visit.Add(snapshot_->root());
2330 snapshot_->root()->paint_reachable(); 2576 snapshot_->root()->paint_reachable();
(...skipping 397 matching lines...) Expand 10 before | Expand all | Expand 10 after
2728 "," JSON_S("children")) 2974 "," JSON_S("children"))
2729 "," JSON_S("types") ":" JSON_A( 2975 "," JSON_S("types") ":" JSON_A(
2730 JSON_A( 2976 JSON_A(
2731 JSON_S("hidden") 2977 JSON_S("hidden")
2732 "," JSON_S("array") 2978 "," JSON_S("array")
2733 "," JSON_S("string") 2979 "," JSON_S("string")
2734 "," JSON_S("object") 2980 "," JSON_S("object")
2735 "," JSON_S("code") 2981 "," JSON_S("code")
2736 "," JSON_S("closure") 2982 "," JSON_S("closure")
2737 "," JSON_S("regexp") 2983 "," JSON_S("regexp")
2738 "," JSON_S("number")) 2984 "," JSON_S("number")
2985 "," JSON_S("native"))
2739 "," JSON_S("string") 2986 "," JSON_S("string")
2740 "," JSON_S("number") 2987 "," JSON_S("number")
2741 "," JSON_S("number") 2988 "," JSON_S("number")
2742 "," JSON_S("number") 2989 "," JSON_S("number")
2743 "," JSON_S("number") 2990 "," JSON_S("number")
2744 "," JSON_S("number") 2991 "," JSON_S("number")
2745 "," JSON_O( 2992 "," JSON_O(
2746 JSON_S("fields") ":" JSON_A( 2993 JSON_S("fields") ":" JSON_A(
2747 JSON_S("type") 2994 JSON_S("type")
2748 "," JSON_S("name_or_index") 2995 "," JSON_S("name_or_index")
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
2890 3137
2891 3138
2892 String* GetConstructorNameForHeapProfile(JSObject* object) { 3139 String* GetConstructorNameForHeapProfile(JSObject* object) {
2893 if (object->IsJSFunction()) return Heap::closure_symbol(); 3140 if (object->IsJSFunction()) return Heap::closure_symbol();
2894 return object->constructor_name(); 3141 return object->constructor_name();
2895 } 3142 }
2896 3143
2897 } } // namespace v8::internal 3144 } } // namespace v8::internal
2898 3145
2899 #endif // ENABLE_LOGGING_AND_PROFILING 3146 #endif // ENABLE_LOGGING_AND_PROFILING
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698