OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 1294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1305 const SnapshotObjectId HeapObjectsMap::kInternalRootObjectId = 1; | 1305 const SnapshotObjectId HeapObjectsMap::kInternalRootObjectId = 1; |
1306 const SnapshotObjectId HeapObjectsMap::kGcRootsObjectId = | 1306 const SnapshotObjectId HeapObjectsMap::kGcRootsObjectId = |
1307 HeapObjectsMap::kInternalRootObjectId + HeapObjectsMap::kObjectIdStep; | 1307 HeapObjectsMap::kInternalRootObjectId + HeapObjectsMap::kObjectIdStep; |
1308 const SnapshotObjectId HeapObjectsMap::kGcRootsFirstSubrootId = | 1308 const SnapshotObjectId HeapObjectsMap::kGcRootsFirstSubrootId = |
1309 HeapObjectsMap::kGcRootsObjectId + HeapObjectsMap::kObjectIdStep; | 1309 HeapObjectsMap::kGcRootsObjectId + HeapObjectsMap::kObjectIdStep; |
1310 const SnapshotObjectId HeapObjectsMap::kFirstAvailableObjectId = | 1310 const SnapshotObjectId HeapObjectsMap::kFirstAvailableObjectId = |
1311 HeapObjectsMap::kGcRootsFirstSubrootId + | 1311 HeapObjectsMap::kGcRootsFirstSubrootId + |
1312 VisitorSynchronization::kNumberOfSyncTags * HeapObjectsMap::kObjectIdStep; | 1312 VisitorSynchronization::kNumberOfSyncTags * HeapObjectsMap::kObjectIdStep; |
1313 | 1313 |
1314 HeapObjectsMap::HeapObjectsMap() | 1314 HeapObjectsMap::HeapObjectsMap() |
1315 : initial_fill_mode_(true), | 1315 : next_id_(kFirstAvailableObjectId), |
1316 next_id_(kFirstAvailableObjectId), | |
1317 entries_map_(AddressesMatch), | 1316 entries_map_(AddressesMatch), |
1318 entries_(new List<EntryInfo>()) { | 1317 entries_(new List<EntryInfo>()) { |
1319 // This dummy element solves a problem with entries_map_. | 1318 // This dummy element solves a problem with entries_map_. |
1320 // When we do lookup in HashMap we see no difference between two cases: | 1319 // When we do lookup in HashMap we see no difference between two cases: |
1321 // it has an entry with NULL as the value or it has created | 1320 // it has an entry with NULL as the value or it has created |
1322 // a new entry on the fly with NULL as the default value. | 1321 // a new entry on the fly with NULL as the default value. |
1323 // With such dummy element we have a guaranty that all entries_map_ entries | 1322 // With such dummy element we have a guaranty that all entries_map_ entries |
1324 // will have the value field grater than 0. | 1323 // will have the value field grater than 0. |
1325 // This fact is using in MoveObject method. | 1324 // This fact is using in MoveObject method. |
1326 entries_->Add(EntryInfo(0, NULL)); | 1325 entries_->Add(EntryInfo(0, NULL, 0)); |
1327 } | 1326 } |
1328 | 1327 |
1329 | 1328 |
1330 HeapObjectsMap::~HeapObjectsMap() { | 1329 HeapObjectsMap::~HeapObjectsMap() { |
1331 delete entries_; | 1330 delete entries_; |
1332 } | 1331 } |
1333 | 1332 |
1334 | 1333 |
1335 void HeapObjectsMap::SnapshotGenerationFinished() { | 1334 void HeapObjectsMap::SnapshotGenerationFinished() { |
1336 initial_fill_mode_ = false; | |
1337 RemoveDeadEntries(); | 1335 RemoveDeadEntries(); |
1338 } | 1336 } |
1339 | 1337 |
1340 | 1338 |
1341 SnapshotObjectId HeapObjectsMap::FindObject(Address addr) { | |
1342 if (!initial_fill_mode_) { | |
1343 SnapshotObjectId existing = FindEntry(addr); | |
1344 if (existing != 0) return existing; | |
1345 } | |
1346 SnapshotObjectId id = next_id_; | |
1347 next_id_ += kObjectIdStep; | |
1348 AddEntry(addr, id); | |
1349 // Here and in other places the length of entries_ list has to be | |
1350 // the same or greater than the length of entries_map_. But entries_ list | |
1351 // has a dummy element at index 0. | |
1352 ASSERT(static_cast<uint32_t>(entries_->length()) > entries_map_.occupancy()); | |
1353 return id; | |
1354 } | |
1355 | |
1356 | |
1357 void HeapObjectsMap::MoveObject(Address from, Address to) { | 1339 void HeapObjectsMap::MoveObject(Address from, Address to) { |
1358 ASSERT(to != NULL); | 1340 ASSERT(to != NULL); |
1359 ASSERT(from != NULL); | 1341 ASSERT(from != NULL); |
1360 if (from == to) return; | 1342 if (from == to) return; |
1361 void* from_value = entries_map_.Remove(from, AddressHash(from)); | 1343 void* from_value = entries_map_.Remove(from, AddressHash(from)); |
1362 if (from_value == NULL) return; | 1344 if (from_value == NULL) return; |
1363 int from_entry_info_index = | 1345 int from_entry_info_index = |
1364 static_cast<int>(reinterpret_cast<intptr_t>(from_value)); | 1346 static_cast<int>(reinterpret_cast<intptr_t>(from_value)); |
1365 entries_->at(from_entry_info_index).addr = to; | 1347 entries_->at(from_entry_info_index).addr = to; |
1366 HashMap::Entry* to_entry = entries_map_.Lookup(to, AddressHash(to), true); | 1348 HashMap::Entry* to_entry = entries_map_.Lookup(to, AddressHash(to), true); |
1367 if (to_entry->value != NULL) { | 1349 if (to_entry->value != NULL) { |
1368 int to_entry_info_index = | 1350 int to_entry_info_index = |
1369 static_cast<int>(reinterpret_cast<intptr_t>(to_entry->value)); | 1351 static_cast<int>(reinterpret_cast<intptr_t>(to_entry->value)); |
1370 // Without this operation we will have two EntryInfo's with the same | 1352 // Without this operation we will have two EntryInfo's with the same |
1371 // value in addr field. It is bad because later at RemoveDeadEntries | 1353 // value in addr field. It is bad because later at RemoveDeadEntries |
1372 // one of this entry will be removed with the corresponding entries_map_ | 1354 // one of this entry will be removed with the corresponding entries_map_ |
1373 // entry. | 1355 // entry. |
1374 entries_->at(to_entry_info_index).addr = NULL; | 1356 entries_->at(to_entry_info_index).addr = NULL; |
1375 } | 1357 } |
1376 to_entry->value = reinterpret_cast<void*>(from_entry_info_index); | 1358 to_entry->value = reinterpret_cast<void*>(from_entry_info_index); |
1377 } | 1359 } |
1378 | 1360 |
1379 | 1361 |
1380 void HeapObjectsMap::AddEntry(Address addr, SnapshotObjectId id) { | |
1381 HashMap::Entry* entry = entries_map_.Lookup(addr, AddressHash(addr), true); | |
1382 ASSERT(entry->value == NULL); | |
1383 ASSERT(entries_->length() > 0 && | |
1384 entries_->at(0).id == 0 && | |
1385 entries_->at(0).addr == NULL); | |
1386 ASSERT(entries_->at(entries_->length() - 1).id < id); | |
1387 entry->value = reinterpret_cast<void*>(entries_->length()); | |
1388 entries_->Add(EntryInfo(id, addr)); | |
1389 ASSERT(static_cast<uint32_t>(entries_->length()) > entries_map_.occupancy()); | |
1390 } | |
1391 | |
1392 | |
1393 SnapshotObjectId HeapObjectsMap::FindEntry(Address addr) { | 1362 SnapshotObjectId HeapObjectsMap::FindEntry(Address addr) { |
1394 HashMap::Entry* entry = entries_map_.Lookup(addr, AddressHash(addr), false); | 1363 HashMap::Entry* entry = entries_map_.Lookup(addr, AddressHash(addr), false); |
1395 if (entry != NULL) { | 1364 if (entry == NULL) return 0; |
1396 int entry_index = | 1365 int entry_index = static_cast<int>(reinterpret_cast<intptr_t>(entry->value)); |
1397 static_cast<int>(reinterpret_cast<intptr_t>(entry->value)); | 1366 EntryInfo& entry_info = entries_->at(entry_index); |
1398 EntryInfo& entry_info = entries_->at(entry_index); | 1367 entry_info.accessed = true; |
1399 entry_info.accessed = true; | 1368 ASSERT(static_cast<uint32_t>(entries_->length()) > entries_map_.occupancy()); |
1400 ASSERT(static_cast<uint32_t>(entries_->length()) > | 1369 return entry_info.id; |
1401 entries_map_.occupancy()); | |
1402 return entry_info.id; | |
1403 } else { | |
1404 return 0; | |
1405 } | |
1406 } | 1370 } |
1407 | 1371 |
1408 | 1372 |
1409 SnapshotObjectId HeapObjectsMap::FindOrAddEntry(Address addr) { | 1373 SnapshotObjectId HeapObjectsMap::FindOrAddEntry(Address addr, |
1374 unsigned int size) { | |
1410 ASSERT(static_cast<uint32_t>(entries_->length()) > entries_map_.occupancy()); | 1375 ASSERT(static_cast<uint32_t>(entries_->length()) > entries_map_.occupancy()); |
1411 HashMap::Entry* entry = entries_map_.Lookup(addr, AddressHash(addr), true); | 1376 HashMap::Entry* entry = entries_map_.Lookup(addr, AddressHash(addr), true); |
1412 if (entry->value != NULL) { | 1377 if (entry->value != NULL) { |
1413 int entry_index = | 1378 int entry_index = |
1414 static_cast<int>(reinterpret_cast<intptr_t>(entry->value)); | 1379 static_cast<int>(reinterpret_cast<intptr_t>(entry->value)); |
1415 EntryInfo& entry_info = entries_->at(entry_index); | 1380 EntryInfo& entry_info = entries_->at(entry_index); |
1416 entry_info.accessed = true; | 1381 entry_info.accessed = true; |
1382 entry_info.size = size; | |
1417 return entry_info.id; | 1383 return entry_info.id; |
1418 } | 1384 } |
1419 entry->value = reinterpret_cast<void*>(entries_->length()); | 1385 entry->value = reinterpret_cast<void*>(entries_->length()); |
1420 SnapshotObjectId id = next_id_; | 1386 SnapshotObjectId id = next_id_; |
1421 next_id_ += kObjectIdStep; | 1387 next_id_ += kObjectIdStep; |
1422 entries_->Add(EntryInfo(id, addr)); | 1388 entries_->Add(EntryInfo(id, addr, size)); |
1423 ASSERT(static_cast<uint32_t>(entries_->length()) > entries_map_.occupancy()); | 1389 ASSERT(static_cast<uint32_t>(entries_->length()) > entries_map_.occupancy()); |
1424 return id; | 1390 return id; |
1425 } | 1391 } |
1426 | 1392 |
1427 | 1393 |
1428 void HeapObjectsMap::StopHeapObjectsTracking() { | 1394 void HeapObjectsMap::StopHeapObjectsTracking() { |
1429 time_intervals_.Clear(); | 1395 time_intervals_.Clear(); |
1430 } | 1396 } |
1431 | 1397 |
1432 void HeapObjectsMap::UpdateHeapObjectsMap() { | 1398 void HeapObjectsMap::UpdateHeapObjectsMap() { |
1433 HEAP->CollectAllGarbage(Heap::kMakeHeapIterableMask, | 1399 HEAP->CollectAllGarbage(Heap::kMakeHeapIterableMask, |
1434 "HeapSnapshotsCollection::UpdateHeapObjectsMap"); | 1400 "HeapSnapshotsCollection::UpdateHeapObjectsMap"); |
1435 HeapIterator iterator(HeapIterator::kFilterUnreachable); | 1401 HeapIterator iterator; |
1436 for (HeapObject* obj = iterator.next(); | 1402 for (HeapObject* obj = iterator.next(); |
1437 obj != NULL; | 1403 obj != NULL; |
1438 obj = iterator.next()) { | 1404 obj = iterator.next()) { |
1439 FindOrAddEntry(obj->address()); | 1405 FindOrAddEntry(obj->address(), obj->Size()); |
1440 } | 1406 } |
1441 initial_fill_mode_ = false; | |
1442 RemoveDeadEntries(); | 1407 RemoveDeadEntries(); |
1443 } | 1408 } |
1444 | 1409 |
1445 | 1410 |
1446 void HeapObjectsMap::PushHeapObjectsStats(OutputStream* stream) { | 1411 void HeapObjectsMap::PushHeapObjectsStats(OutputStream* stream) { |
1447 UpdateHeapObjectsMap(); | 1412 UpdateHeapObjectsMap(); |
1448 time_intervals_.Add(TimeInterval(next_id_)); | 1413 time_intervals_.Add(TimeInterval(next_id_)); |
1449 int prefered_chunk_size = stream->GetChunkSize(); | 1414 int prefered_chunk_size = stream->GetChunkSize(); |
1450 List<uint32_t> stats_buffer; | 1415 List<uint32_t> stats_buffer; |
1451 ASSERT(!entries_->is_empty()); | 1416 ASSERT(!entries_->is_empty()); |
1452 EntryInfo* entry_info = &entries_->first(); | 1417 EntryInfo* entry_info = &entries_->first(); |
1453 EntryInfo* end_entry_info = &entries_->last() + 1; | 1418 EntryInfo* end_entry_info = &entries_->last() + 1; |
1454 for (int time_interval_index = 0; | 1419 for (int time_interval_index = 0; |
1455 time_interval_index < time_intervals_.length(); | 1420 time_interval_index < time_intervals_.length(); |
1456 ++time_interval_index) { | 1421 ++time_interval_index) { |
1457 TimeInterval& time_interval = time_intervals_[time_interval_index]; | 1422 TimeInterval& time_interval = time_intervals_[time_interval_index]; |
1458 SnapshotObjectId time_interval_id = time_interval.id; | 1423 SnapshotObjectId time_interval_id = time_interval.id; |
1459 uint32_t entries_count = 0; | 1424 uint32_t entries_size = 0; |
1425 EntryInfo* start_entry_info = entry_info; | |
1460 while (entry_info < end_entry_info && entry_info->id < time_interval_id) { | 1426 while (entry_info < end_entry_info && entry_info->id < time_interval_id) { |
1461 ++entries_count; | 1427 entries_size += entry_info->size; |
1462 ++entry_info; | 1428 ++entry_info; |
1463 } | 1429 } |
1464 if (time_interval.count != entries_count) { | 1430 uint32_t entries_count = entry_info - start_entry_info; |
mnaganov (inactive)
2012/04/16 08:13:54
Are you sure this compiles on all platforms, for e
| |
1431 if (time_interval.count != entries_count || | |
1432 time_interval.size != entries_size) { | |
1465 stats_buffer.Add(time_interval_index); | 1433 stats_buffer.Add(time_interval_index); |
1466 stats_buffer.Add(time_interval.count = entries_count); | 1434 stats_buffer.Add(time_interval.count = entries_count); |
1435 stats_buffer.Add(time_interval.size = entries_size); | |
1467 if (stats_buffer.length() >= prefered_chunk_size) { | 1436 if (stats_buffer.length() >= prefered_chunk_size) { |
1468 OutputStream::WriteResult result = stream->WriteUint32Chunk( | 1437 OutputStream::WriteResult result = stream->WriteUint32Chunk( |
1469 &stats_buffer.first(), stats_buffer.length()); | 1438 &stats_buffer.first(), stats_buffer.length()); |
1470 if (result == OutputStream::kAbort) return; | 1439 if (result == OutputStream::kAbort) return; |
1471 stats_buffer.Clear(); | 1440 stats_buffer.Clear(); |
1472 } | 1441 } |
1473 } | 1442 } |
1474 } | 1443 } |
1475 ASSERT(entry_info == end_entry_info); | 1444 ASSERT(entry_info == end_entry_info); |
1476 if (!stats_buffer.is_empty()) { | 1445 if (!stats_buffer.is_empty()) { |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1587 // First perform a full GC in order to avoid dead objects. | 1556 // First perform a full GC in order to avoid dead objects. |
1588 HEAP->CollectAllGarbage(Heap::kMakeHeapIterableMask, | 1557 HEAP->CollectAllGarbage(Heap::kMakeHeapIterableMask, |
1589 "HeapSnapshotsCollection::FindHeapObjectById"); | 1558 "HeapSnapshotsCollection::FindHeapObjectById"); |
1590 AssertNoAllocation no_allocation; | 1559 AssertNoAllocation no_allocation; |
1591 HeapObject* object = NULL; | 1560 HeapObject* object = NULL; |
1592 HeapIterator iterator(HeapIterator::kFilterUnreachable); | 1561 HeapIterator iterator(HeapIterator::kFilterUnreachable); |
1593 // Make sure that object with the given id is still reachable. | 1562 // Make sure that object with the given id is still reachable. |
1594 for (HeapObject* obj = iterator.next(); | 1563 for (HeapObject* obj = iterator.next(); |
1595 obj != NULL; | 1564 obj != NULL; |
1596 obj = iterator.next()) { | 1565 obj = iterator.next()) { |
1597 if (ids_.FindObject(obj->address()) == id) { | 1566 if (ids_.FindEntry(obj->address()) == id) { |
1598 ASSERT(object == NULL); | 1567 ASSERT(object == NULL); |
1599 object = obj; | 1568 object = obj; |
1600 // Can't break -- kFilterUnreachable requires full heap traversal. | 1569 // Can't break -- kFilterUnreachable requires full heap traversal. |
1601 } | 1570 } |
1602 } | 1571 } |
1603 return object != NULL ? Handle<HeapObject>(object) : Handle<HeapObject>(); | 1572 return object != NULL ? Handle<HeapObject>(object) : Handle<HeapObject>(); |
1604 } | 1573 } |
1605 | 1574 |
1606 | 1575 |
1607 HeapEntry* const HeapEntriesMap::kHeapEntryPlaceholder = | 1576 HeapEntry* const HeapEntriesMap::kHeapEntryPlaceholder = |
(...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1888 children_count, | 1857 children_count, |
1889 retainers_count); | 1858 retainers_count); |
1890 } | 1859 } |
1891 | 1860 |
1892 | 1861 |
1893 HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object, | 1862 HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object, |
1894 HeapEntry::Type type, | 1863 HeapEntry::Type type, |
1895 const char* name, | 1864 const char* name, |
1896 int children_count, | 1865 int children_count, |
1897 int retainers_count) { | 1866 int retainers_count) { |
1867 int object_size = object->Size(); | |
1868 SnapshotObjectId object_id = | |
1869 collection_->GetObjectId(object->address(), object_size); | |
1898 return snapshot_->AddEntry(type, | 1870 return snapshot_->AddEntry(type, |
1899 name, | 1871 name, |
1900 collection_->GetObjectId(object->address()), | 1872 object_id, |
1901 object->Size(), | 1873 object_size, |
1902 children_count, | 1874 children_count, |
1903 retainers_count); | 1875 retainers_count); |
1904 } | 1876 } |
1905 | 1877 |
1906 | 1878 |
1907 class GcSubrootsEnumerator : public ObjectVisitor { | 1879 class GcSubrootsEnumerator : public ObjectVisitor { |
1908 public: | 1880 public: |
1909 GcSubrootsEnumerator( | 1881 GcSubrootsEnumerator( |
1910 SnapshotFillerInterface* filler, V8HeapExplorer* explorer) | 1882 SnapshotFillerInterface* filler, V8HeapExplorer* explorer) |
1911 : filler_(filler), | 1883 : filler_(filler), |
(...skipping 1950 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3862 | 3834 |
3863 | 3835 |
3864 void HeapSnapshotJSONSerializer::SortHashMap( | 3836 void HeapSnapshotJSONSerializer::SortHashMap( |
3865 HashMap* map, List<HashMap::Entry*>* sorted_entries) { | 3837 HashMap* map, List<HashMap::Entry*>* sorted_entries) { |
3866 for (HashMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) | 3838 for (HashMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) |
3867 sorted_entries->Add(p); | 3839 sorted_entries->Add(p); |
3868 sorted_entries->Sort(SortUsingEntryValue); | 3840 sorted_entries->Sort(SortUsingEntryValue); |
3869 } | 3841 } |
3870 | 3842 |
3871 } } // namespace v8::internal | 3843 } } // namespace v8::internal |
OLD | NEW |