| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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::GetCopy(const char* src) { |
| 108 int len = static_cast<int>(strlen(src)); |
| 109 Vector<char> dst = Vector<char>::New(len + 1); |
| 110 OS::StrNCpy(dst, src, len); |
| 111 dst[len] = '\0'; |
| 112 uint32_t hash = HashSequentialString(dst.start(), len); |
| 113 return AddOrDisposeString(dst.start(), hash); |
| 114 } |
| 115 |
| 116 |
| 117 const char* StringsStorage::GetFormatted(const char* format, ...) { |
| 118 va_list args; |
| 119 va_start(args, format); |
| 120 const char* result = GetVFormatted(format, args); |
| 121 va_end(args); |
| 122 return result; |
| 123 } |
| 124 |
| 125 |
| 126 const char* StringsStorage::AddOrDisposeString(char* str, uint32_t hash) { |
| 127 HashMap::Entry* cache_entry = names_.Lookup(str, hash, true); |
| 128 if (cache_entry->value == NULL) { |
| 129 // New entry added. |
| 130 cache_entry->value = str; |
| 131 } else { |
| 132 DeleteArray(str); |
| 133 } |
| 134 return reinterpret_cast<const char*>(cache_entry->value); |
| 135 } |
| 136 |
| 137 |
| 138 const char* StringsStorage::GetVFormatted(const char* format, va_list args) { |
| 139 Vector<char> str = Vector<char>::New(1024); |
| 140 int len = OS::VSNPrintF(str, format, args); |
| 141 if (len == -1) { |
| 142 DeleteArray(str.start()); |
| 143 return format; |
| 144 } |
| 145 uint32_t hash = HashSequentialString(str.start(), len); |
| 146 return AddOrDisposeString(str.start(), hash); |
| 109 } | 147 } |
| 110 | 148 |
| 111 | 149 |
| 112 const char* StringsStorage::GetName(String* name) { | 150 const char* StringsStorage::GetName(String* name) { |
| 113 if (name->IsString()) { | 151 if (name->IsString()) { |
| 114 char* c_name = | 152 return AddOrDisposeString( |
| 115 name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL).Detach(); | 153 name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL).Detach(), |
| 116 HashMap::Entry* cache_entry = names_.Lookup(c_name, name->Hash(), true); | 154 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 } | 155 } |
| 125 return ""; | 156 return ""; |
| 126 } | 157 } |
| 127 | 158 |
| 128 | 159 |
| 129 const char* StringsStorage::GetName(int index) { | 160 const char* StringsStorage::GetName(int index) { |
| 130 ASSERT(index >= 0); | 161 return GetFormatted("%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 } | 162 } |
| 143 | 163 |
| 144 | 164 |
| 145 const char* CodeEntry::kEmptyNamePrefix = ""; | 165 const char* CodeEntry::kEmptyNamePrefix = ""; |
| 146 | 166 |
| 147 | 167 |
| 148 void CodeEntry::CopyData(const CodeEntry& source) { | 168 void CodeEntry::CopyData(const CodeEntry& source) { |
| 149 tag_ = source.tag_; | 169 tag_ = source.tag_; |
| 150 name_prefix_ = source.name_prefix_; | 170 name_prefix_ = source.name_prefix_; |
| 151 name_ = source.name_; | 171 name_ = source.name_; |
| (...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 458 | 478 |
| 459 | 479 |
| 460 void CpuProfile::Print() { | 480 void CpuProfile::Print() { |
| 461 OS::Print("[Top down]:\n"); | 481 OS::Print("[Top down]:\n"); |
| 462 top_down_.Print(); | 482 top_down_.Print(); |
| 463 OS::Print("[Bottom up]:\n"); | 483 OS::Print("[Bottom up]:\n"); |
| 464 bottom_up_.Print(); | 484 bottom_up_.Print(); |
| 465 } | 485 } |
| 466 | 486 |
| 467 | 487 |
| 468 CodeEntry* const CodeMap::kSfiCodeEntry = NULL; | 488 CodeEntry* const CodeMap::kSharedFunctionCodeEntry = NULL; |
| 469 const CodeMap::CodeTreeConfig::Key CodeMap::CodeTreeConfig::kNoKey = NULL; | 489 const CodeMap::CodeTreeConfig::Key CodeMap::CodeTreeConfig::kNoKey = NULL; |
| 470 const CodeMap::CodeTreeConfig::Value CodeMap::CodeTreeConfig::kNoValue = | 490 const CodeMap::CodeTreeConfig::Value CodeMap::CodeTreeConfig::kNoValue = |
| 471 CodeMap::CodeEntryInfo(NULL, 0); | 491 CodeMap::CodeEntryInfo(NULL, 0); |
| 472 | 492 |
| 473 | 493 |
| 474 CodeEntry* CodeMap::FindEntry(Address addr) { | 494 CodeEntry* CodeMap::FindEntry(Address addr) { |
| 475 CodeTree::Locator locator; | 495 CodeTree::Locator locator; |
| 476 if (tree_.FindGreatestLessThan(addr, &locator)) { | 496 if (tree_.FindGreatestLessThan(addr, &locator)) { |
| 477 // locator.key() <= addr. Need to check that addr is within entry. | 497 // locator.key() <= addr. Need to check that addr is within entry. |
| 478 const CodeEntryInfo& entry = locator.value(); | 498 const CodeEntryInfo& entry = locator.value(); |
| 479 if (addr < (locator.key() + entry.size)) | 499 if (addr < (locator.key() + entry.size)) |
| 480 return entry.entry; | 500 return entry.entry; |
| 481 } | 501 } |
| 482 return NULL; | 502 return NULL; |
| 483 } | 503 } |
| 484 | 504 |
| 485 | 505 |
| 486 int CodeMap::GetSFITag(Address addr) { | 506 int CodeMap::GetSharedId(Address addr) { |
| 487 CodeTree::Locator locator; | 507 CodeTree::Locator locator; |
| 488 // For SFI entries, 'size' field is used to store their IDs. | 508 // For shared function entries, 'size' field is used to store their IDs. |
| 489 if (tree_.Find(addr, &locator)) { | 509 if (tree_.Find(addr, &locator)) { |
| 490 const CodeEntryInfo& entry = locator.value(); | 510 const CodeEntryInfo& entry = locator.value(); |
| 491 ASSERT(entry.entry == kSfiCodeEntry); | 511 ASSERT(entry.entry == kSharedFunctionCodeEntry); |
| 492 return entry.size; | 512 return entry.size; |
| 493 } else { | 513 } else { |
| 494 tree_.Insert(addr, &locator); | 514 tree_.Insert(addr, &locator); |
| 495 int tag = next_sfi_tag_++; | 515 int id = next_shared_id_++; |
| 496 locator.set_value(CodeEntryInfo(kSfiCodeEntry, tag)); | 516 locator.set_value(CodeEntryInfo(kSharedFunctionCodeEntry, id)); |
| 497 return tag; | 517 return id; |
| 498 } | 518 } |
| 499 } | 519 } |
| 500 | 520 |
| 501 | 521 |
| 502 void CodeMap::CodeTreePrinter::Call( | 522 void CodeMap::CodeTreePrinter::Call( |
| 503 const Address& key, const CodeMap::CodeEntryInfo& value) { | 523 const Address& key, const CodeMap::CodeEntryInfo& value) { |
| 504 OS::Print("%p %5d %s\n", key, value.size, value.entry->name()); | 524 OS::Print("%p %5d %s\n", key, value.size, value.entry->name()); |
| 505 } | 525 } |
| 506 | 526 |
| 507 | 527 |
| (...skipping 494 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1002 const char* HeapEntry::TypeAsString() { | 1022 const char* HeapEntry::TypeAsString() { |
| 1003 switch (type()) { | 1023 switch (type()) { |
| 1004 case kHidden: return "/hidden/"; | 1024 case kHidden: return "/hidden/"; |
| 1005 case kObject: return "/object/"; | 1025 case kObject: return "/object/"; |
| 1006 case kClosure: return "/closure/"; | 1026 case kClosure: return "/closure/"; |
| 1007 case kString: return "/string/"; | 1027 case kString: return "/string/"; |
| 1008 case kCode: return "/code/"; | 1028 case kCode: return "/code/"; |
| 1009 case kArray: return "/array/"; | 1029 case kArray: return "/array/"; |
| 1010 case kRegExp: return "/regexp/"; | 1030 case kRegExp: return "/regexp/"; |
| 1011 case kHeapNumber: return "/number/"; | 1031 case kHeapNumber: return "/number/"; |
| 1032 case kNative: return "/native/"; |
| 1012 default: return "???"; | 1033 default: return "???"; |
| 1013 } | 1034 } |
| 1014 } | 1035 } |
| 1015 | 1036 |
| 1016 | 1037 |
| 1017 int HeapEntry::EntriesSize(int entries_count, | 1038 int HeapEntry::EntriesSize(int entries_count, |
| 1018 int children_count, | 1039 int children_count, |
| 1019 int retainers_count) { | 1040 int retainers_count) { |
| 1020 return sizeof(HeapEntry) * entries_count // NOLINT | 1041 return sizeof(HeapEntry) * entries_count // NOLINT |
| 1021 + sizeof(HeapGraphEdge) * children_count // NOLINT | 1042 + sizeof(HeapGraphEdge) * children_count // NOLINT |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1198 HeapSnapshot::HeapSnapshot(HeapSnapshotsCollection* collection, | 1219 HeapSnapshot::HeapSnapshot(HeapSnapshotsCollection* collection, |
| 1199 HeapSnapshot::Type type, | 1220 HeapSnapshot::Type type, |
| 1200 const char* title, | 1221 const char* title, |
| 1201 unsigned uid) | 1222 unsigned uid) |
| 1202 : collection_(collection), | 1223 : collection_(collection), |
| 1203 type_(type), | 1224 type_(type), |
| 1204 title_(title), | 1225 title_(title), |
| 1205 uid_(uid), | 1226 uid_(uid), |
| 1206 root_entry_(NULL), | 1227 root_entry_(NULL), |
| 1207 gc_roots_entry_(NULL), | 1228 gc_roots_entry_(NULL), |
| 1229 natives_root_entry_(NULL), |
| 1208 raw_entries_(NULL), | 1230 raw_entries_(NULL), |
| 1209 entries_sorted_(false), | 1231 entries_sorted_(false), |
| 1210 retaining_paths_(HeapEntry::Match) { | 1232 retaining_paths_(HeapEntry::Match) { |
| 1211 STATIC_ASSERT( | 1233 STATIC_ASSERT( |
| 1212 sizeof(HeapGraphEdge) == | 1234 sizeof(HeapGraphEdge) == |
| 1213 SnapshotSizeConstants<sizeof(void*)>::kExpectedHeapGraphEdgeSize); // NOL
INT | 1235 SnapshotSizeConstants<sizeof(void*)>::kExpectedHeapGraphEdgeSize); // NOL
INT |
| 1214 STATIC_ASSERT( | 1236 STATIC_ASSERT( |
| 1215 sizeof(HeapEntry) == | 1237 sizeof(HeapEntry) == |
| 1216 SnapshotSizeConstants<sizeof(void*)>::kExpectedHeapEntrySize); // NOLINT | 1238 SnapshotSizeConstants<sizeof(void*)>::kExpectedHeapEntrySize); // NOLINT |
| 1217 } | 1239 } |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1272 ASSERT(gc_roots_entry_ == NULL); | 1294 ASSERT(gc_roots_entry_ == NULL); |
| 1273 return (gc_roots_entry_ = AddEntry(HeapEntry::kObject, | 1295 return (gc_roots_entry_ = AddEntry(HeapEntry::kObject, |
| 1274 "(GC roots)", | 1296 "(GC roots)", |
| 1275 HeapObjectsMap::kGcRootsObjectId, | 1297 HeapObjectsMap::kGcRootsObjectId, |
| 1276 0, | 1298 0, |
| 1277 children_count, | 1299 children_count, |
| 1278 retainers_count)); | 1300 retainers_count)); |
| 1279 } | 1301 } |
| 1280 | 1302 |
| 1281 | 1303 |
| 1304 HeapEntry* HeapSnapshot::AddNativesRootEntry(int children_count, |
| 1305 int retainers_count) { |
| 1306 ASSERT(natives_root_entry_ == NULL); |
| 1307 return (natives_root_entry_ = AddEntry( |
| 1308 HeapEntry::kObject, |
| 1309 "(Native objects)", |
| 1310 HeapObjectsMap::kNativesRootObjectId, |
| 1311 0, |
| 1312 children_count, |
| 1313 retainers_count)); |
| 1314 } |
| 1315 |
| 1316 |
| 1282 HeapEntry* HeapSnapshot::AddEntry(HeapEntry::Type type, | 1317 HeapEntry* HeapSnapshot::AddEntry(HeapEntry::Type type, |
| 1283 const char* name, | 1318 const char* name, |
| 1284 uint64_t id, | 1319 uint64_t id, |
| 1285 int size, | 1320 int size, |
| 1286 int children_count, | 1321 int children_count, |
| 1287 int retainers_count) { | 1322 int retainers_count) { |
| 1288 HeapEntry* entry = GetNextEntryToInit(); | 1323 HeapEntry* entry = GetNextEntryToInit(); |
| 1289 entry->Init(this, type, name, id, size, children_count, retainers_count); | 1324 entry->Init(this, type, name, id, size, children_count, retainers_count); |
| 1290 return entry; | 1325 return entry; |
| 1291 } | 1326 } |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1365 } | 1400 } |
| 1366 return &entries_; | 1401 return &entries_; |
| 1367 } | 1402 } |
| 1368 | 1403 |
| 1369 | 1404 |
| 1370 void HeapSnapshot::Print(int max_depth) { | 1405 void HeapSnapshot::Print(int max_depth) { |
| 1371 root()->Print(max_depth, 0); | 1406 root()->Print(max_depth, 0); |
| 1372 } | 1407 } |
| 1373 | 1408 |
| 1374 | 1409 |
| 1375 const uint64_t HeapObjectsMap::kInternalRootObjectId = 0; | 1410 // We split IDs on evens for embedder objects (see |
| 1376 const uint64_t HeapObjectsMap::kGcRootsObjectId = 1; | 1411 // HeapObjectsMap::GenerateId) and odds for native objects. |
| 1412 const uint64_t HeapObjectsMap::kInternalRootObjectId = 1; |
| 1413 const uint64_t HeapObjectsMap::kGcRootsObjectId = 3; |
| 1414 const uint64_t HeapObjectsMap::kNativesRootObjectId = 5; |
| 1377 // Increase kFirstAvailableObjectId if new 'special' objects appear. | 1415 // Increase kFirstAvailableObjectId if new 'special' objects appear. |
| 1378 const uint64_t HeapObjectsMap::kFirstAvailableObjectId = 2; | 1416 const uint64_t HeapObjectsMap::kFirstAvailableObjectId = 7; |
| 1379 | 1417 |
| 1380 HeapObjectsMap::HeapObjectsMap() | 1418 HeapObjectsMap::HeapObjectsMap() |
| 1381 : initial_fill_mode_(true), | 1419 : initial_fill_mode_(true), |
| 1382 next_id_(kFirstAvailableObjectId), | 1420 next_id_(kFirstAvailableObjectId), |
| 1383 entries_map_(AddressesMatch), | 1421 entries_map_(AddressesMatch), |
| 1384 entries_(new List<EntryInfo>()) { } | 1422 entries_(new List<EntryInfo>()) { } |
| 1385 | 1423 |
| 1386 | 1424 |
| 1387 HeapObjectsMap::~HeapObjectsMap() { | 1425 HeapObjectsMap::~HeapObjectsMap() { |
| 1388 delete entries_; | 1426 delete entries_; |
| 1389 } | 1427 } |
| 1390 | 1428 |
| 1391 | 1429 |
| 1392 void HeapObjectsMap::SnapshotGenerationFinished() { | 1430 void HeapObjectsMap::SnapshotGenerationFinished() { |
| 1393 initial_fill_mode_ = false; | 1431 initial_fill_mode_ = false; |
| 1394 RemoveDeadEntries(); | 1432 RemoveDeadEntries(); |
| 1395 } | 1433 } |
| 1396 | 1434 |
| 1397 | 1435 |
| 1398 uint64_t HeapObjectsMap::FindObject(Address addr) { | 1436 uint64_t HeapObjectsMap::FindObject(Address addr) { |
| 1399 if (!initial_fill_mode_) { | 1437 if (!initial_fill_mode_) { |
| 1400 uint64_t existing = FindEntry(addr); | 1438 uint64_t existing = FindEntry(addr); |
| 1401 if (existing != 0) return existing; | 1439 if (existing != 0) return existing; |
| 1402 } | 1440 } |
| 1403 uint64_t id = next_id_++; | 1441 uint64_t id = next_id_; |
| 1442 next_id_ += 2; |
| 1404 AddEntry(addr, id); | 1443 AddEntry(addr, id); |
| 1405 return id; | 1444 return id; |
| 1406 } | 1445 } |
| 1407 | 1446 |
| 1408 | 1447 |
| 1409 void HeapObjectsMap::MoveObject(Address from, Address to) { | 1448 void HeapObjectsMap::MoveObject(Address from, Address to) { |
| 1410 if (from == to) return; | 1449 if (from == to) return; |
| 1411 HashMap::Entry* entry = entries_map_.Lookup(from, AddressHash(from), false); | 1450 HashMap::Entry* entry = entries_map_.Lookup(from, AddressHash(from), false); |
| 1412 if (entry != NULL) { | 1451 if (entry != NULL) { |
| 1413 void* value = entry->value; | 1452 void* value = entry->value; |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1461 for (int i = 0; i < dead_entries.length(); ++i) { | 1500 for (int i = 0; i < dead_entries.length(); ++i) { |
| 1462 void* raw_entry = dead_entries[i]; | 1501 void* raw_entry = dead_entries[i]; |
| 1463 entries_map_.Remove( | 1502 entries_map_.Remove( |
| 1464 raw_entry, AddressHash(reinterpret_cast<Address>(raw_entry))); | 1503 raw_entry, AddressHash(reinterpret_cast<Address>(raw_entry))); |
| 1465 } | 1504 } |
| 1466 delete entries_; | 1505 delete entries_; |
| 1467 entries_ = new_entries; | 1506 entries_ = new_entries; |
| 1468 } | 1507 } |
| 1469 | 1508 |
| 1470 | 1509 |
| 1510 uint64_t HeapObjectsMap::GenerateId(v8::RetainedObjectInfo* info) { |
| 1511 uint64_t id = static_cast<uint64_t>(info->GetHash()); |
| 1512 const char* label = info->GetLabel(); |
| 1513 id ^= HashSequentialString(label, static_cast<int>(strlen(label))); |
| 1514 intptr_t element_count = info->GetElementCount(); |
| 1515 if (element_count != -1) |
| 1516 id ^= ComputeIntegerHash(static_cast<uint32_t>(element_count)); |
| 1517 return id << 1; |
| 1518 } |
| 1519 |
| 1520 |
| 1471 HeapSnapshotsCollection::HeapSnapshotsCollection() | 1521 HeapSnapshotsCollection::HeapSnapshotsCollection() |
| 1472 : is_tracking_objects_(false), | 1522 : is_tracking_objects_(false), |
| 1473 snapshots_uids_(HeapSnapshotsMatch), | 1523 snapshots_uids_(HeapSnapshotsMatch), |
| 1474 token_enumerator_(new TokenEnumerator()) { | 1524 token_enumerator_(new TokenEnumerator()) { |
| 1475 } | 1525 } |
| 1476 | 1526 |
| 1477 | 1527 |
| 1478 static void DeleteHeapSnapshot(HeapSnapshot** snapshot_ptr) { | 1528 static void DeleteHeapSnapshot(HeapSnapshot** snapshot_ptr) { |
| 1479 delete *snapshot_ptr; | 1529 delete *snapshot_ptr; |
| 1480 } | 1530 } |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1544 | 1594 |
| 1545 void HeapEntriesMap::AllocateEntries() { | 1595 void HeapEntriesMap::AllocateEntries() { |
| 1546 for (HashMap::Entry* p = entries_.Start(); | 1596 for (HashMap::Entry* p = entries_.Start(); |
| 1547 p != NULL; | 1597 p != NULL; |
| 1548 p = entries_.Next(p)) { | 1598 p = entries_.Next(p)) { |
| 1549 EntryInfo* entry_info = reinterpret_cast<EntryInfo*>(p->value); | 1599 EntryInfo* entry_info = reinterpret_cast<EntryInfo*>(p->value); |
| 1550 entry_info->entry = entry_info->allocator->AllocateEntry( | 1600 entry_info->entry = entry_info->allocator->AllocateEntry( |
| 1551 p->key, | 1601 p->key, |
| 1552 entry_info->children_count, | 1602 entry_info->children_count, |
| 1553 entry_info->retainers_count); | 1603 entry_info->retainers_count); |
| 1604 ASSERT(entry_info->entry != NULL); |
| 1605 ASSERT(entry_info->entry != kHeapEntryPlaceholder); |
| 1554 entry_info->children_count = 0; | 1606 entry_info->children_count = 0; |
| 1555 entry_info->retainers_count = 0; | 1607 entry_info->retainers_count = 0; |
| 1556 } | 1608 } |
| 1557 } | 1609 } |
| 1558 | 1610 |
| 1559 | 1611 |
| 1560 HeapEntry* HeapEntriesMap::Map(HeapThing thing) { | 1612 HeapEntry* HeapEntriesMap::Map(HeapThing thing) { |
| 1561 HashMap::Entry* cache_entry = entries_.Lookup(thing, Hash(thing), false); | 1613 HashMap::Entry* cache_entry = entries_.Lookup(thing, Hash(thing), false); |
| 1562 if (cache_entry != NULL) { | 1614 if (cache_entry != NULL) { |
| 1563 EntryInfo* entry_info = reinterpret_cast<EntryInfo*>(cache_entry->value); | 1615 EntryInfo* entry_info = reinterpret_cast<EntryInfo*>(cache_entry->value); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1623 HeapObject* object = HeapObject::cast(obj); | 1675 HeapObject* object = HeapObject::cast(obj); |
| 1624 HashMap::Entry* cache_entry = | 1676 HashMap::Entry* cache_entry = |
| 1625 entries_.Lookup(object, HeapEntriesMap::Hash(object), true); | 1677 entries_.Lookup(object, HeapEntriesMap::Hash(object), true); |
| 1626 if (cache_entry->value == NULL) { | 1678 if (cache_entry->value == NULL) { |
| 1627 cache_entry->value = HeapEntriesMap::kHeapEntryPlaceholder; | 1679 cache_entry->value = HeapEntriesMap::kHeapEntryPlaceholder; |
| 1628 } | 1680 } |
| 1629 } | 1681 } |
| 1630 | 1682 |
| 1631 | 1683 |
| 1632 HeapObject *const V8HeapExplorer::kInternalRootObject = | 1684 HeapObject *const V8HeapExplorer::kInternalRootObject = |
| 1633 reinterpret_cast<HeapObject*>(1); | 1685 reinterpret_cast<HeapObject*>( |
| 1686 static_cast<intptr_t>(HeapObjectsMap::kInternalRootObjectId)); |
| 1634 HeapObject *const V8HeapExplorer::kGcRootsObject = | 1687 HeapObject *const V8HeapExplorer::kGcRootsObject = |
| 1635 reinterpret_cast<HeapObject*>(2); | 1688 reinterpret_cast<HeapObject*>( |
| 1689 static_cast<intptr_t>(HeapObjectsMap::kGcRootsObjectId)); |
| 1636 | 1690 |
| 1637 | 1691 |
| 1638 V8HeapExplorer::V8HeapExplorer( | 1692 V8HeapExplorer::V8HeapExplorer( |
| 1639 HeapSnapshot* snapshot, | 1693 HeapSnapshot* snapshot, |
| 1640 SnapshottingProgressReportingInterface* progress) | 1694 SnapshottingProgressReportingInterface* progress) |
| 1641 : snapshot_(snapshot), | 1695 : snapshot_(snapshot), |
| 1642 collection_(snapshot_->collection()), | 1696 collection_(snapshot_->collection()), |
| 1643 progress_(progress), | 1697 progress_(progress), |
| 1644 filler_(NULL) { | 1698 filler_(NULL) { |
| 1645 } | 1699 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1662 if (object == kInternalRootObject) { | 1716 if (object == kInternalRootObject) { |
| 1663 ASSERT(retainers_count == 0); | 1717 ASSERT(retainers_count == 0); |
| 1664 return snapshot_->AddRootEntry(children_count); | 1718 return snapshot_->AddRootEntry(children_count); |
| 1665 } else if (object == kGcRootsObject) { | 1719 } else if (object == kGcRootsObject) { |
| 1666 return snapshot_->AddGcRootsEntry(children_count, retainers_count); | 1720 return snapshot_->AddGcRootsEntry(children_count, retainers_count); |
| 1667 } else if (object->IsJSFunction()) { | 1721 } else if (object->IsJSFunction()) { |
| 1668 JSFunction* func = JSFunction::cast(object); | 1722 JSFunction* func = JSFunction::cast(object); |
| 1669 SharedFunctionInfo* shared = func->shared(); | 1723 SharedFunctionInfo* shared = func->shared(); |
| 1670 return AddEntry(object, | 1724 return AddEntry(object, |
| 1671 HeapEntry::kClosure, | 1725 HeapEntry::kClosure, |
| 1672 collection_->GetName(String::cast(shared->name())), | 1726 collection_->names()->GetName(String::cast(shared->name())), |
| 1673 children_count, | 1727 children_count, |
| 1674 retainers_count); | 1728 retainers_count); |
| 1675 } else if (object->IsJSRegExp()) { | 1729 } else if (object->IsJSRegExp()) { |
| 1676 JSRegExp* re = JSRegExp::cast(object); | 1730 JSRegExp* re = JSRegExp::cast(object); |
| 1677 return AddEntry(object, | 1731 return AddEntry(object, |
| 1678 HeapEntry::kRegExp, | 1732 HeapEntry::kRegExp, |
| 1679 collection_->GetName(re->Pattern()), | 1733 collection_->names()->GetName(re->Pattern()), |
| 1680 children_count, | 1734 children_count, |
| 1681 retainers_count); | 1735 retainers_count); |
| 1682 } else if (object->IsJSObject()) { | 1736 } else if (object->IsJSObject()) { |
| 1683 return AddEntry(object, | 1737 return AddEntry(object, |
| 1684 HeapEntry::kObject, | 1738 HeapEntry::kObject, |
| 1685 collection_->GetName(GetConstructorNameForHeapProfile( | 1739 collection_->names()->GetName( |
| 1686 JSObject::cast(object))), | 1740 GetConstructorNameForHeapProfile( |
| 1741 JSObject::cast(object))), |
| 1687 children_count, | 1742 children_count, |
| 1688 retainers_count); | 1743 retainers_count); |
| 1689 } else if (object->IsString()) { | 1744 } else if (object->IsString()) { |
| 1690 return AddEntry(object, | 1745 return AddEntry(object, |
| 1691 HeapEntry::kString, | 1746 HeapEntry::kString, |
| 1692 collection_->GetName(String::cast(object)), | 1747 collection_->names()->GetName(String::cast(object)), |
| 1693 children_count, | 1748 children_count, |
| 1694 retainers_count); | 1749 retainers_count); |
| 1695 } else if (object->IsCode()) { | 1750 } else if (object->IsCode()) { |
| 1696 return AddEntry(object, | 1751 return AddEntry(object, |
| 1697 HeapEntry::kCode, | 1752 HeapEntry::kCode, |
| 1698 "", | 1753 "", |
| 1699 children_count, | 1754 children_count, |
| 1700 retainers_count); | 1755 retainers_count); |
| 1701 } else if (object->IsSharedFunctionInfo()) { | 1756 } else if (object->IsSharedFunctionInfo()) { |
| 1702 SharedFunctionInfo* shared = SharedFunctionInfo::cast(object); | 1757 SharedFunctionInfo* shared = SharedFunctionInfo::cast(object); |
| 1703 return AddEntry(object, | 1758 return AddEntry(object, |
| 1704 HeapEntry::kCode, | 1759 HeapEntry::kCode, |
| 1705 collection_->GetName(String::cast(shared->name())), | 1760 collection_->names()->GetName(String::cast(shared->name())), |
| 1706 children_count, | 1761 children_count, |
| 1707 retainers_count); | 1762 retainers_count); |
| 1708 } else if (object->IsScript()) { | 1763 } else if (object->IsScript()) { |
| 1709 Script* script = Script::cast(object); | 1764 Script* script = Script::cast(object); |
| 1710 return AddEntry(object, | 1765 return AddEntry(object, |
| 1711 HeapEntry::kCode, | 1766 HeapEntry::kCode, |
| 1712 script->name()->IsString() ? | 1767 script->name()->IsString() ? |
| 1713 collection_->GetName(String::cast(script->name())) : "", | 1768 collection_->names()->GetName( |
| 1769 String::cast(script->name())) |
| 1770 : "", |
| 1714 children_count, | 1771 children_count, |
| 1715 retainers_count); | 1772 retainers_count); |
| 1716 } else if (object->IsFixedArray()) { | 1773 } else if (object->IsFixedArray()) { |
| 1717 return AddEntry(object, | 1774 return AddEntry(object, |
| 1718 HeapEntry::kArray, | 1775 HeapEntry::kArray, |
| 1719 "", | 1776 "", |
| 1720 children_count, | 1777 children_count, |
| 1721 retainers_count); | 1778 retainers_count); |
| 1722 } else if (object->IsHeapNumber()) { | 1779 } else if (object->IsHeapNumber()) { |
| 1723 return AddEntry(object, | 1780 return AddEntry(object, |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1742 return snapshot_->AddEntry(type, | 1799 return snapshot_->AddEntry(type, |
| 1743 name, | 1800 name, |
| 1744 collection_->GetObjectId(object->address()), | 1801 collection_->GetObjectId(object->address()), |
| 1745 object->Size(), | 1802 object->Size(), |
| 1746 children_count, | 1803 children_count, |
| 1747 retainers_count); | 1804 retainers_count); |
| 1748 } | 1805 } |
| 1749 | 1806 |
| 1750 | 1807 |
| 1751 void V8HeapExplorer::AddRootEntries(SnapshotFillerInterface* filler) { | 1808 void V8HeapExplorer::AddRootEntries(SnapshotFillerInterface* filler) { |
| 1752 filler->AddEntry(kInternalRootObject); | 1809 filler->AddEntry(kInternalRootObject, this); |
| 1753 filler->AddEntry(kGcRootsObject); | 1810 filler->AddEntry(kGcRootsObject, this); |
| 1754 } | 1811 } |
| 1755 | 1812 |
| 1756 | 1813 |
| 1757 int V8HeapExplorer::EstimateObjectsCount() { | 1814 int V8HeapExplorer::EstimateObjectsCount() { |
| 1758 HeapIterator iterator(HeapIterator::kFilterUnreachable); | 1815 HeapIterator iterator(HeapIterator::kFilterUnreachable); |
| 1759 int objects_count = 0; | 1816 int objects_count = 0; |
| 1760 for (HeapObject* obj = iterator.next(); | 1817 for (HeapObject* obj = iterator.next(); |
| 1761 obj != NULL; | 1818 obj != NULL; |
| 1762 obj = iterator.next(), ++objects_count) {} | 1819 obj = iterator.next(), ++objects_count) {} |
| 1763 return objects_count; | 1820 return objects_count; |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1933 int length = js_obj->GetInternalFieldCount(); | 1990 int length = js_obj->GetInternalFieldCount(); |
| 1934 for (int i = 0; i < length; ++i) { | 1991 for (int i = 0; i < length; ++i) { |
| 1935 Object* o = js_obj->GetInternalField(i); | 1992 Object* o = js_obj->GetInternalField(i); |
| 1936 SetInternalReference(js_obj, entry, i, o); | 1993 SetInternalReference(js_obj, entry, i, o); |
| 1937 } | 1994 } |
| 1938 } | 1995 } |
| 1939 | 1996 |
| 1940 | 1997 |
| 1941 HeapEntry* V8HeapExplorer::GetEntry(Object* obj) { | 1998 HeapEntry* V8HeapExplorer::GetEntry(Object* obj) { |
| 1942 if (!obj->IsHeapObject()) return NULL; | 1999 if (!obj->IsHeapObject()) return NULL; |
| 1943 return filler_->FindOrAddEntry(obj); | 2000 return filler_->FindOrAddEntry(obj, this); |
| 1944 } | 2001 } |
| 1945 | 2002 |
| 1946 | 2003 |
| 1947 class RootsReferencesExtractor : public ObjectVisitor { | 2004 class RootsReferencesExtractor : public ObjectVisitor { |
| 1948 public: | 2005 public: |
| 1949 explicit RootsReferencesExtractor(V8HeapExplorer* explorer) | 2006 explicit RootsReferencesExtractor(V8HeapExplorer* explorer) |
| 1950 : explorer_(explorer) { | 2007 : explorer_(explorer) { |
| 1951 } | 2008 } |
| 1952 void VisitPointers(Object** start, Object** end) { | 2009 void VisitPointers(Object** start, Object** end) { |
| 1953 for (Object** p = start; p < end; p++) explorer_->SetGcRootsReference(*p); | 2010 for (Object** p = start; p < end; p++) explorer_->SetGcRootsReference(*p); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1985 | 2042 |
| 1986 void V8HeapExplorer::SetClosureReference(HeapObject* parent_obj, | 2043 void V8HeapExplorer::SetClosureReference(HeapObject* parent_obj, |
| 1987 HeapEntry* parent_entry, | 2044 HeapEntry* parent_entry, |
| 1988 String* reference_name, | 2045 String* reference_name, |
| 1989 Object* child_obj) { | 2046 Object* child_obj) { |
| 1990 HeapEntry* child_entry = GetEntry(child_obj); | 2047 HeapEntry* child_entry = GetEntry(child_obj); |
| 1991 if (child_entry != NULL) { | 2048 if (child_entry != NULL) { |
| 1992 filler_->SetNamedReference(HeapGraphEdge::kContextVariable, | 2049 filler_->SetNamedReference(HeapGraphEdge::kContextVariable, |
| 1993 parent_obj, | 2050 parent_obj, |
| 1994 parent_entry, | 2051 parent_entry, |
| 1995 collection_->GetName(reference_name), | 2052 collection_->names()->GetName(reference_name), |
| 1996 child_obj, | 2053 child_obj, |
| 1997 child_entry); | 2054 child_entry); |
| 1998 known_references_.Insert(child_obj); | 2055 known_references_.Insert(child_obj); |
| 1999 } | 2056 } |
| 2000 } | 2057 } |
| 2001 | 2058 |
| 2002 | 2059 |
| 2003 void V8HeapExplorer::SetElementReference(HeapObject* parent_obj, | 2060 void V8HeapExplorer::SetElementReference(HeapObject* parent_obj, |
| 2004 HeapEntry* parent_entry, | 2061 HeapEntry* parent_entry, |
| 2005 int index, | 2062 int index, |
| (...skipping 30 matching lines...) Expand all Loading... |
| 2036 | 2093 |
| 2037 void V8HeapExplorer::SetInternalReference(HeapObject* parent_obj, | 2094 void V8HeapExplorer::SetInternalReference(HeapObject* parent_obj, |
| 2038 HeapEntry* parent_entry, | 2095 HeapEntry* parent_entry, |
| 2039 int index, | 2096 int index, |
| 2040 Object* child_obj) { | 2097 Object* child_obj) { |
| 2041 HeapEntry* child_entry = GetEntry(child_obj); | 2098 HeapEntry* child_entry = GetEntry(child_obj); |
| 2042 if (child_entry != NULL) { | 2099 if (child_entry != NULL) { |
| 2043 filler_->SetNamedReference(HeapGraphEdge::kInternal, | 2100 filler_->SetNamedReference(HeapGraphEdge::kInternal, |
| 2044 parent_obj, | 2101 parent_obj, |
| 2045 parent_entry, | 2102 parent_entry, |
| 2046 collection_->GetName(index), | 2103 collection_->names()->GetName(index), |
| 2047 child_obj, | 2104 child_obj, |
| 2048 child_entry); | 2105 child_entry); |
| 2049 known_references_.Insert(child_obj); | 2106 known_references_.Insert(child_obj); |
| 2050 } | 2107 } |
| 2051 } | 2108 } |
| 2052 | 2109 |
| 2053 | 2110 |
| 2054 void V8HeapExplorer::SetHiddenReference(HeapObject* parent_obj, | 2111 void V8HeapExplorer::SetHiddenReference(HeapObject* parent_obj, |
| 2055 HeapEntry* parent_entry, | 2112 HeapEntry* parent_entry, |
| 2056 int index, | 2113 int index, |
| (...skipping 14 matching lines...) Expand all Loading... |
| 2071 HeapEntry* parent_entry, | 2128 HeapEntry* parent_entry, |
| 2072 String* reference_name, | 2129 String* reference_name, |
| 2073 Object* child_obj) { | 2130 Object* child_obj) { |
| 2074 HeapEntry* child_entry = GetEntry(child_obj); | 2131 HeapEntry* child_entry = GetEntry(child_obj); |
| 2075 if (child_entry != NULL) { | 2132 if (child_entry != NULL) { |
| 2076 HeapGraphEdge::Type type = reference_name->length() > 0 ? | 2133 HeapGraphEdge::Type type = reference_name->length() > 0 ? |
| 2077 HeapGraphEdge::kProperty : HeapGraphEdge::kInternal; | 2134 HeapGraphEdge::kProperty : HeapGraphEdge::kInternal; |
| 2078 filler_->SetNamedReference(type, | 2135 filler_->SetNamedReference(type, |
| 2079 parent_obj, | 2136 parent_obj, |
| 2080 parent_entry, | 2137 parent_entry, |
| 2081 collection_->GetName(reference_name), | 2138 collection_->names()->GetName(reference_name), |
| 2082 child_obj, | 2139 child_obj, |
| 2083 child_entry); | 2140 child_entry); |
| 2084 known_references_.Insert(child_obj); | 2141 known_references_.Insert(child_obj); |
| 2085 } | 2142 } |
| 2086 } | 2143 } |
| 2087 | 2144 |
| 2088 | 2145 |
| 2089 void V8HeapExplorer::SetPropertyShortcutReference( | 2146 void V8HeapExplorer::SetPropertyShortcutReference( |
| 2090 HeapObject* parent_obj, | 2147 HeapObject* parent_obj, |
| 2091 HeapEntry* parent_entry, | 2148 HeapEntry* parent_entry, |
| 2092 String* reference_name, | 2149 String* reference_name, |
| 2093 Object* child_obj) { | 2150 Object* child_obj) { |
| 2094 HeapEntry* child_entry = GetEntry(child_obj); | 2151 HeapEntry* child_entry = GetEntry(child_obj); |
| 2095 if (child_entry != NULL) { | 2152 if (child_entry != NULL) { |
| 2096 filler_->SetNamedReference(HeapGraphEdge::kShortcut, | 2153 filler_->SetNamedReference(HeapGraphEdge::kShortcut, |
| 2097 parent_obj, | 2154 parent_obj, |
| 2098 parent_entry, | 2155 parent_entry, |
| 2099 collection_->GetName(reference_name), | 2156 collection_->names()->GetName(reference_name), |
| 2100 child_obj, | 2157 child_obj, |
| 2101 child_entry); | 2158 child_entry); |
| 2102 } | 2159 } |
| 2103 } | 2160 } |
| 2104 | 2161 |
| 2105 | 2162 |
| 2106 void V8HeapExplorer::SetRootGcRootsReference() { | 2163 void V8HeapExplorer::SetRootGcRootsReference() { |
| 2107 filler_->SetIndexedAutoIndexReference( | 2164 filler_->SetIndexedAutoIndexReference( |
| 2108 HeapGraphEdge::kElement, | 2165 HeapGraphEdge::kElement, |
| 2109 kInternalRootObject, snapshot_->root(), | 2166 kInternalRootObject, snapshot_->root(), |
| (...skipping 15 matching lines...) Expand all Loading... |
| 2125 HeapEntry* child_entry = GetEntry(child_obj); | 2182 HeapEntry* child_entry = GetEntry(child_obj); |
| 2126 if (child_entry != NULL) { | 2183 if (child_entry != NULL) { |
| 2127 filler_->SetIndexedAutoIndexReference( | 2184 filler_->SetIndexedAutoIndexReference( |
| 2128 HeapGraphEdge::kElement, | 2185 HeapGraphEdge::kElement, |
| 2129 kGcRootsObject, snapshot_->gc_roots(), | 2186 kGcRootsObject, snapshot_->gc_roots(), |
| 2130 child_obj, child_entry); | 2187 child_obj, child_entry); |
| 2131 } | 2188 } |
| 2132 } | 2189 } |
| 2133 | 2190 |
| 2134 | 2191 |
| 2192 class GlobalHandlesExtractor : public ObjectVisitor { |
| 2193 public: |
| 2194 explicit GlobalHandlesExtractor(NativeObjectsExplorer* explorer) |
| 2195 : explorer_(explorer) {} |
| 2196 virtual ~GlobalHandlesExtractor() {} |
| 2197 virtual void VisitPointers(Object** start, Object** end) { |
| 2198 UNREACHABLE(); |
| 2199 } |
| 2200 virtual void VisitEmbedderReference(Object** p, uint16_t class_id) { |
| 2201 explorer_->VisitSubtreeWrapper(p, class_id); |
| 2202 } |
| 2203 private: |
| 2204 NativeObjectsExplorer* explorer_; |
| 2205 }; |
| 2206 |
| 2207 HeapThing const NativeObjectsExplorer::kNativesRootObject = |
| 2208 reinterpret_cast<HeapThing>( |
| 2209 static_cast<intptr_t>(HeapObjectsMap::kNativesRootObjectId)); |
| 2210 |
| 2211 |
| 2212 NativeObjectsExplorer::NativeObjectsExplorer( |
| 2213 HeapSnapshot* snapshot, SnapshottingProgressReportingInterface* progress) |
| 2214 : snapshot_(snapshot), |
| 2215 collection_(snapshot_->collection()), |
| 2216 progress_(progress), |
| 2217 embedder_queried_(false), |
| 2218 objects_by_info_(RetainedInfosMatch), |
| 2219 filler_(NULL) { |
| 2220 } |
| 2221 |
| 2222 |
| 2223 NativeObjectsExplorer::~NativeObjectsExplorer() { |
| 2224 for (HashMap::Entry* p = objects_by_info_.Start(); |
| 2225 p != NULL; |
| 2226 p = objects_by_info_.Next(p)) { |
| 2227 v8::RetainedObjectInfo* info = |
| 2228 reinterpret_cast<v8::RetainedObjectInfo*>(p->key); |
| 2229 info->Dispose(); |
| 2230 List<HeapObject*>* objects = |
| 2231 reinterpret_cast<List<HeapObject*>* >(p->value); |
| 2232 delete objects; |
| 2233 } |
| 2234 } |
| 2235 |
| 2236 |
| 2237 HeapEntry* NativeObjectsExplorer::AllocateEntry( |
| 2238 HeapThing ptr, int children_count, int retainers_count) { |
| 2239 if (ptr == kNativesRootObject) { |
| 2240 return snapshot_->AddNativesRootEntry(children_count, retainers_count); |
| 2241 } else { |
| 2242 v8::RetainedObjectInfo* info = |
| 2243 reinterpret_cast<v8::RetainedObjectInfo*>(ptr); |
| 2244 intptr_t elements = info->GetElementCount(); |
| 2245 intptr_t size = info->GetSizeInBytes(); |
| 2246 return snapshot_->AddEntry( |
| 2247 HeapEntry::kNative, |
| 2248 elements != -1 ? |
| 2249 collection_->names()->GetFormatted( |
| 2250 "%s / %" V8_PTR_PREFIX "d entries", |
| 2251 info->GetLabel(), |
| 2252 info->GetElementCount()) : |
| 2253 collection_->names()->GetCopy(info->GetLabel()), |
| 2254 HeapObjectsMap::GenerateId(info), |
| 2255 size != -1 ? static_cast<int>(size) : 0, |
| 2256 children_count, |
| 2257 retainers_count); |
| 2258 } |
| 2259 } |
| 2260 |
| 2261 |
| 2262 void NativeObjectsExplorer::AddRootEntries(SnapshotFillerInterface* filler) { |
| 2263 if (EstimateObjectsCount() <= 0) return; |
| 2264 filler->AddEntry(kNativesRootObject, this); |
| 2265 } |
| 2266 |
| 2267 |
| 2268 int NativeObjectsExplorer::EstimateObjectsCount() { |
| 2269 FillRetainedObjects(); |
| 2270 return objects_by_info_.occupancy(); |
| 2271 } |
| 2272 |
| 2273 |
| 2274 void NativeObjectsExplorer::FillRetainedObjects() { |
| 2275 if (embedder_queried_) return; |
| 2276 // Record objects that are joined into ObjectGroups. |
| 2277 Heap::CallGlobalGCPrologueCallback(); |
| 2278 List<ObjectGroup*>* groups = GlobalHandles::ObjectGroups(); |
| 2279 for (int i = 0; i < groups->length(); ++i) { |
| 2280 ObjectGroup* group = groups->at(i); |
| 2281 if (group->info_ == NULL) continue; |
| 2282 List<HeapObject*>* list = GetListMaybeDisposeInfo(group->info_); |
| 2283 for (int j = 0; j < group->objects_.length(); ++j) { |
| 2284 HeapObject* obj = HeapObject::cast(*group->objects_[j]); |
| 2285 list->Add(obj); |
| 2286 in_groups_.Insert(obj); |
| 2287 } |
| 2288 group->info_ = NULL; // Acquire info object ownership. |
| 2289 } |
| 2290 GlobalHandles::RemoveObjectGroups(); |
| 2291 Heap::CallGlobalGCEpilogueCallback(); |
| 2292 // Record objects that are not in ObjectGroups, but have class ID. |
| 2293 GlobalHandlesExtractor extractor(this); |
| 2294 GlobalHandles::IterateAllRootsWithClassIds(&extractor); |
| 2295 embedder_queried_ = true; |
| 2296 } |
| 2297 |
| 2298 |
| 2299 List<HeapObject*>* NativeObjectsExplorer::GetListMaybeDisposeInfo( |
| 2300 v8::RetainedObjectInfo* info) { |
| 2301 HashMap::Entry* entry = |
| 2302 objects_by_info_.Lookup(info, InfoHash(info), true); |
| 2303 if (entry->value != NULL) { |
| 2304 info->Dispose(); |
| 2305 } else { |
| 2306 entry->value = new List<HeapObject*>(4); |
| 2307 } |
| 2308 return reinterpret_cast<List<HeapObject*>* >(entry->value); |
| 2309 } |
| 2310 |
| 2311 |
| 2312 bool NativeObjectsExplorer::IterateAndExtractReferences( |
| 2313 SnapshotFillerInterface* filler) { |
| 2314 if (EstimateObjectsCount() <= 0) return true; |
| 2315 filler_ = filler; |
| 2316 FillRetainedObjects(); |
| 2317 for (HashMap::Entry* p = objects_by_info_.Start(); |
| 2318 p != NULL; |
| 2319 p = objects_by_info_.Next(p)) { |
| 2320 v8::RetainedObjectInfo* info = |
| 2321 reinterpret_cast<v8::RetainedObjectInfo*>(p->key); |
| 2322 SetNativeRootReference(info); |
| 2323 List<HeapObject*>* objects = |
| 2324 reinterpret_cast<List<HeapObject*>* >(p->value); |
| 2325 for (int i = 0; i < objects->length(); ++i) { |
| 2326 SetWrapperNativeReferences(objects->at(i), info); |
| 2327 } |
| 2328 } |
| 2329 SetRootNativesRootReference(); |
| 2330 filler_ = NULL; |
| 2331 return true; |
| 2332 } |
| 2333 |
| 2334 |
| 2335 void NativeObjectsExplorer::SetNativeRootReference( |
| 2336 v8::RetainedObjectInfo* info) { |
| 2337 HeapEntry* child_entry = filler_->FindOrAddEntry(info, this); |
| 2338 ASSERT(child_entry != NULL); |
| 2339 filler_->SetIndexedAutoIndexReference( |
| 2340 HeapGraphEdge::kElement, |
| 2341 kNativesRootObject, snapshot_->natives_root(), |
| 2342 info, child_entry); |
| 2343 } |
| 2344 |
| 2345 |
| 2346 void NativeObjectsExplorer::SetWrapperNativeReferences( |
| 2347 HeapObject* wrapper, v8::RetainedObjectInfo* info) { |
| 2348 HeapEntry* wrapper_entry = filler_->FindEntry(wrapper); |
| 2349 ASSERT(wrapper_entry != NULL); |
| 2350 HeapEntry* info_entry = filler_->FindOrAddEntry(info, this); |
| 2351 ASSERT(info_entry != NULL); |
| 2352 filler_->SetNamedReference(HeapGraphEdge::kInternal, |
| 2353 wrapper, wrapper_entry, |
| 2354 "Native", |
| 2355 info, info_entry); |
| 2356 filler_->SetIndexedAutoIndexReference(HeapGraphEdge::kElement, |
| 2357 info, info_entry, |
| 2358 wrapper, wrapper_entry); |
| 2359 } |
| 2360 |
| 2361 |
| 2362 void NativeObjectsExplorer::SetRootNativesRootReference() { |
| 2363 filler_->SetIndexedAutoIndexReference( |
| 2364 HeapGraphEdge::kElement, |
| 2365 V8HeapExplorer::kInternalRootObject, snapshot_->root(), |
| 2366 kNativesRootObject, snapshot_->natives_root()); |
| 2367 } |
| 2368 |
| 2369 |
| 2370 void NativeObjectsExplorer::VisitSubtreeWrapper(Object** p, uint16_t class_id) { |
| 2371 if (in_groups_.Contains(*p)) return; |
| 2372 v8::RetainedObjectInfo* info = |
| 2373 HeapProfiler::ExecuteWrapperClassCallback(class_id, p); |
| 2374 if (info == NULL) return; |
| 2375 GetListMaybeDisposeInfo(info)->Add(HeapObject::cast(*p)); |
| 2376 } |
| 2377 |
| 2378 |
| 2135 HeapSnapshotGenerator::HeapSnapshotGenerator(HeapSnapshot* snapshot, | 2379 HeapSnapshotGenerator::HeapSnapshotGenerator(HeapSnapshot* snapshot, |
| 2136 v8::ActivityControl* control) | 2380 v8::ActivityControl* control) |
| 2137 : snapshot_(snapshot), | 2381 : snapshot_(snapshot), |
| 2138 control_(control), | 2382 control_(control), |
| 2139 v8_heap_explorer_(snapshot_, this) { | 2383 v8_heap_explorer_(snapshot_, this), |
| 2384 dom_explorer_(snapshot_, this) { |
| 2140 } | 2385 } |
| 2141 | 2386 |
| 2142 | 2387 |
| 2143 class SnapshotCounter : public SnapshotFillerInterface { | 2388 class SnapshotCounter : public SnapshotFillerInterface { |
| 2144 public: | 2389 public: |
| 2145 SnapshotCounter(HeapEntriesAllocator* allocator, HeapEntriesMap* entries) | 2390 explicit SnapshotCounter(HeapEntriesMap* entries) : entries_(entries) { } |
| 2146 : allocator_(allocator), entries_(entries) { } | 2391 HeapEntry* AddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) { |
| 2147 HeapEntry* AddEntry(HeapThing ptr) { | 2392 entries_->Pair(ptr, allocator, HeapEntriesMap::kHeapEntryPlaceholder); |
| 2148 entries_->Pair(ptr, allocator_, HeapEntriesMap::kHeapEntryPlaceholder); | |
| 2149 return HeapEntriesMap::kHeapEntryPlaceholder; | 2393 return HeapEntriesMap::kHeapEntryPlaceholder; |
| 2150 } | 2394 } |
| 2151 HeapEntry* FindOrAddEntry(HeapThing ptr) { | 2395 HeapEntry* FindEntry(HeapThing ptr) { |
| 2152 HeapEntry* entry = entries_->Map(ptr); | 2396 return entries_->Map(ptr); |
| 2153 return entry != NULL ? entry : AddEntry(ptr); | 2397 } |
| 2398 HeapEntry* FindOrAddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) { |
| 2399 HeapEntry* entry = FindEntry(ptr); |
| 2400 return entry != NULL ? entry : AddEntry(ptr, allocator); |
| 2154 } | 2401 } |
| 2155 void SetIndexedReference(HeapGraphEdge::Type, | 2402 void SetIndexedReference(HeapGraphEdge::Type, |
| 2156 HeapThing parent_ptr, | 2403 HeapThing parent_ptr, |
| 2157 HeapEntry*, | 2404 HeapEntry*, |
| 2158 int, | 2405 int, |
| 2159 HeapThing child_ptr, | 2406 HeapThing child_ptr, |
| 2160 HeapEntry*) { | 2407 HeapEntry*) { |
| 2161 entries_->CountReference(parent_ptr, child_ptr); | 2408 entries_->CountReference(parent_ptr, child_ptr); |
| 2162 } | 2409 } |
| 2163 void SetIndexedAutoIndexReference(HeapGraphEdge::Type, | 2410 void SetIndexedAutoIndexReference(HeapGraphEdge::Type, |
| (...skipping 12 matching lines...) Expand all Loading... |
| 2176 entries_->CountReference(parent_ptr, child_ptr); | 2423 entries_->CountReference(parent_ptr, child_ptr); |
| 2177 } | 2424 } |
| 2178 void SetNamedAutoIndexReference(HeapGraphEdge::Type, | 2425 void SetNamedAutoIndexReference(HeapGraphEdge::Type, |
| 2179 HeapThing parent_ptr, | 2426 HeapThing parent_ptr, |
| 2180 HeapEntry*, | 2427 HeapEntry*, |
| 2181 HeapThing child_ptr, | 2428 HeapThing child_ptr, |
| 2182 HeapEntry*) { | 2429 HeapEntry*) { |
| 2183 entries_->CountReference(parent_ptr, child_ptr); | 2430 entries_->CountReference(parent_ptr, child_ptr); |
| 2184 } | 2431 } |
| 2185 private: | 2432 private: |
| 2186 HeapEntriesAllocator* allocator_; | |
| 2187 HeapEntriesMap* entries_; | 2433 HeapEntriesMap* entries_; |
| 2188 }; | 2434 }; |
| 2189 | 2435 |
| 2190 | 2436 |
| 2191 class SnapshotFiller : public SnapshotFillerInterface { | 2437 class SnapshotFiller : public SnapshotFillerInterface { |
| 2192 public: | 2438 public: |
| 2193 explicit SnapshotFiller(HeapSnapshot* snapshot, HeapEntriesMap* entries) | 2439 explicit SnapshotFiller(HeapSnapshot* snapshot, HeapEntriesMap* entries) |
| 2194 : snapshot_(snapshot), | 2440 : snapshot_(snapshot), |
| 2195 collection_(snapshot->collection()), | 2441 collection_(snapshot->collection()), |
| 2196 entries_(entries) { } | 2442 entries_(entries) { } |
| 2197 HeapEntry* AddEntry(HeapThing ptr) { | 2443 HeapEntry* AddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) { |
| 2198 UNREACHABLE(); | 2444 UNREACHABLE(); |
| 2199 return NULL; | 2445 return NULL; |
| 2200 } | 2446 } |
| 2201 HeapEntry* FindOrAddEntry(HeapThing ptr) { | 2447 HeapEntry* FindEntry(HeapThing ptr) { |
| 2202 HeapEntry* entry = entries_->Map(ptr); | 2448 return entries_->Map(ptr); |
| 2203 return entry != NULL ? entry : AddEntry(ptr); | 2449 } |
| 2450 HeapEntry* FindOrAddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) { |
| 2451 HeapEntry* entry = FindEntry(ptr); |
| 2452 return entry != NULL ? entry : AddEntry(ptr, allocator); |
| 2204 } | 2453 } |
| 2205 void SetIndexedReference(HeapGraphEdge::Type type, | 2454 void SetIndexedReference(HeapGraphEdge::Type type, |
| 2206 HeapThing parent_ptr, | 2455 HeapThing parent_ptr, |
| 2207 HeapEntry* parent_entry, | 2456 HeapEntry* parent_entry, |
| 2208 int index, | 2457 int index, |
| 2209 HeapThing child_ptr, | 2458 HeapThing child_ptr, |
| 2210 HeapEntry* child_entry) { | 2459 HeapEntry* child_entry) { |
| 2211 int child_index, retainer_index; | 2460 int child_index, retainer_index; |
| 2212 entries_->CountReference( | 2461 entries_->CountReference( |
| 2213 parent_ptr, child_ptr, &child_index, &retainer_index); | 2462 parent_ptr, child_ptr, &child_index, &retainer_index); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 2240 void SetNamedAutoIndexReference(HeapGraphEdge::Type type, | 2489 void SetNamedAutoIndexReference(HeapGraphEdge::Type type, |
| 2241 HeapThing parent_ptr, | 2490 HeapThing parent_ptr, |
| 2242 HeapEntry* parent_entry, | 2491 HeapEntry* parent_entry, |
| 2243 HeapThing child_ptr, | 2492 HeapThing child_ptr, |
| 2244 HeapEntry* child_entry) { | 2493 HeapEntry* child_entry) { |
| 2245 int child_index, retainer_index; | 2494 int child_index, retainer_index; |
| 2246 entries_->CountReference( | 2495 entries_->CountReference( |
| 2247 parent_ptr, child_ptr, &child_index, &retainer_index); | 2496 parent_ptr, child_ptr, &child_index, &retainer_index); |
| 2248 parent_entry->SetNamedReference(type, | 2497 parent_entry->SetNamedReference(type, |
| 2249 child_index, | 2498 child_index, |
| 2250 collection_->GetName(child_index + 1), | 2499 collection_->names()->GetName(child_index + 1), |
| 2251 child_entry, | 2500 child_entry, |
| 2252 retainer_index); | 2501 retainer_index); |
| 2253 } | 2502 } |
| 2254 private: | 2503 private: |
| 2255 HeapSnapshot* snapshot_; | 2504 HeapSnapshot* snapshot_; |
| 2256 HeapSnapshotsCollection* collection_; | 2505 HeapSnapshotsCollection* collection_; |
| 2257 HeapEntriesMap* entries_; | 2506 HeapEntriesMap* entries_; |
| 2258 }; | 2507 }; |
| 2259 | 2508 |
| 2260 | 2509 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2296 return | 2545 return |
| 2297 control_->ReportProgressValue(progress_counter_, progress_total_) == | 2546 control_->ReportProgressValue(progress_counter_, progress_total_) == |
| 2298 v8::ActivityControl::kContinue; | 2547 v8::ActivityControl::kContinue; |
| 2299 } | 2548 } |
| 2300 return true; | 2549 return true; |
| 2301 } | 2550 } |
| 2302 | 2551 |
| 2303 | 2552 |
| 2304 void HeapSnapshotGenerator::SetProgressTotal(int iterations_count) { | 2553 void HeapSnapshotGenerator::SetProgressTotal(int iterations_count) { |
| 2305 if (control_ == NULL) return; | 2554 if (control_ == NULL) return; |
| 2306 progress_total_ = v8_heap_explorer_.EstimateObjectsCount() * iterations_count; | 2555 progress_total_ = ( |
| 2556 v8_heap_explorer_.EstimateObjectsCount() + |
| 2557 dom_explorer_.EstimateObjectsCount()) * iterations_count; |
| 2307 progress_counter_ = 0; | 2558 progress_counter_ = 0; |
| 2308 } | 2559 } |
| 2309 | 2560 |
| 2310 | 2561 |
| 2311 bool HeapSnapshotGenerator::CountEntriesAndReferences() { | 2562 bool HeapSnapshotGenerator::CountEntriesAndReferences() { |
| 2312 SnapshotCounter counter(&v8_heap_explorer_, &entries_); | 2563 SnapshotCounter counter(&entries_); |
| 2313 v8_heap_explorer_.AddRootEntries(&counter); | 2564 v8_heap_explorer_.AddRootEntries(&counter); |
| 2314 return v8_heap_explorer_.IterateAndExtractReferences(&counter); | 2565 dom_explorer_.AddRootEntries(&counter); |
| 2566 return |
| 2567 v8_heap_explorer_.IterateAndExtractReferences(&counter) && |
| 2568 dom_explorer_.IterateAndExtractReferences(&counter); |
| 2315 } | 2569 } |
| 2316 | 2570 |
| 2317 | 2571 |
| 2318 bool HeapSnapshotGenerator::FillReferences() { | 2572 bool HeapSnapshotGenerator::FillReferences() { |
| 2319 SnapshotFiller filler(snapshot_, &entries_); | 2573 SnapshotFiller filler(snapshot_, &entries_); |
| 2320 return v8_heap_explorer_.IterateAndExtractReferences(&filler); | 2574 return |
| 2575 v8_heap_explorer_.IterateAndExtractReferences(&filler) && |
| 2576 dom_explorer_.IterateAndExtractReferences(&filler); |
| 2321 } | 2577 } |
| 2322 | 2578 |
| 2323 | 2579 |
| 2324 void HeapSnapshotGenerator::FillReversePostorderIndexes( | 2580 void HeapSnapshotGenerator::FillReversePostorderIndexes( |
| 2325 Vector<HeapEntry*>* entries) { | 2581 Vector<HeapEntry*>* entries) { |
| 2326 snapshot_->ClearPaint(); | 2582 snapshot_->ClearPaint(); |
| 2327 int current_entry = 0; | 2583 int current_entry = 0; |
| 2328 List<HeapEntry*> nodes_to_visit; | 2584 List<HeapEntry*> nodes_to_visit; |
| 2329 nodes_to_visit.Add(snapshot_->root()); | 2585 nodes_to_visit.Add(snapshot_->root()); |
| 2330 snapshot_->root()->paint_reachable(); | 2586 snapshot_->root()->paint_reachable(); |
| (...skipping 397 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2728 "," JSON_S("children")) | 2984 "," JSON_S("children")) |
| 2729 "," JSON_S("types") ":" JSON_A( | 2985 "," JSON_S("types") ":" JSON_A( |
| 2730 JSON_A( | 2986 JSON_A( |
| 2731 JSON_S("hidden") | 2987 JSON_S("hidden") |
| 2732 "," JSON_S("array") | 2988 "," JSON_S("array") |
| 2733 "," JSON_S("string") | 2989 "," JSON_S("string") |
| 2734 "," JSON_S("object") | 2990 "," JSON_S("object") |
| 2735 "," JSON_S("code") | 2991 "," JSON_S("code") |
| 2736 "," JSON_S("closure") | 2992 "," JSON_S("closure") |
| 2737 "," JSON_S("regexp") | 2993 "," JSON_S("regexp") |
| 2738 "," JSON_S("number")) | 2994 "," JSON_S("number") |
| 2995 "," JSON_S("native")) |
| 2739 "," JSON_S("string") | 2996 "," JSON_S("string") |
| 2740 "," JSON_S("number") | 2997 "," JSON_S("number") |
| 2741 "," JSON_S("number") | 2998 "," JSON_S("number") |
| 2742 "," JSON_S("number") | 2999 "," JSON_S("number") |
| 2743 "," JSON_S("number") | 3000 "," JSON_S("number") |
| 2744 "," JSON_S("number") | 3001 "," JSON_S("number") |
| 2745 "," JSON_O( | 3002 "," JSON_O( |
| 2746 JSON_S("fields") ":" JSON_A( | 3003 JSON_S("fields") ":" JSON_A( |
| 2747 JSON_S("type") | 3004 JSON_S("type") |
| 2748 "," JSON_S("name_or_index") | 3005 "," JSON_S("name_or_index") |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2890 | 3147 |
| 2891 | 3148 |
| 2892 String* GetConstructorNameForHeapProfile(JSObject* object) { | 3149 String* GetConstructorNameForHeapProfile(JSObject* object) { |
| 2893 if (object->IsJSFunction()) return Heap::closure_symbol(); | 3150 if (object->IsJSFunction()) return Heap::closure_symbol(); |
| 2894 return object->constructor_name(); | 3151 return object->constructor_name(); |
| 2895 } | 3152 } |
| 2896 | 3153 |
| 2897 } } // namespace v8::internal | 3154 } } // namespace v8::internal |
| 2898 | 3155 |
| 2899 #endif // ENABLE_LOGGING_AND_PROFILING | 3156 #endif // ENABLE_LOGGING_AND_PROFILING |
| OLD | NEW |