| 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 1293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1304 const SnapshotObjectId HeapObjectsMap::kGcRootsObjectId = | 1304 const SnapshotObjectId HeapObjectsMap::kGcRootsObjectId = |
| 1305 HeapObjectsMap::kInternalRootObjectId + HeapObjectsMap::kObjectIdStep; | 1305 HeapObjectsMap::kInternalRootObjectId + HeapObjectsMap::kObjectIdStep; |
| 1306 const SnapshotObjectId HeapObjectsMap::kGcRootsFirstSubrootId = | 1306 const SnapshotObjectId HeapObjectsMap::kGcRootsFirstSubrootId = |
| 1307 HeapObjectsMap::kGcRootsObjectId + HeapObjectsMap::kObjectIdStep; | 1307 HeapObjectsMap::kGcRootsObjectId + HeapObjectsMap::kObjectIdStep; |
| 1308 const SnapshotObjectId HeapObjectsMap::kFirstAvailableObjectId = | 1308 const SnapshotObjectId HeapObjectsMap::kFirstAvailableObjectId = |
| 1309 HeapObjectsMap::kGcRootsFirstSubrootId + | 1309 HeapObjectsMap::kGcRootsFirstSubrootId + |
| 1310 VisitorSynchronization::kNumberOfSyncTags * HeapObjectsMap::kObjectIdStep; | 1310 VisitorSynchronization::kNumberOfSyncTags * HeapObjectsMap::kObjectIdStep; |
| 1311 | 1311 |
| 1312 HeapObjectsMap::HeapObjectsMap() | 1312 HeapObjectsMap::HeapObjectsMap() |
| 1313 : next_id_(kFirstAvailableObjectId), | 1313 : next_id_(kFirstAvailableObjectId), |
| 1314 entries_map_(AddressesMatch), | 1314 entries_map_(AddressesMatch) { |
| 1315 entries_(new List<EntryInfo>()) { | |
| 1316 // This dummy element solves a problem with entries_map_. | 1315 // This dummy element solves a problem with entries_map_. |
| 1317 // When we do lookup in HashMap we see no difference between two cases: | 1316 // When we do lookup in HashMap we see no difference between two cases: |
| 1318 // it has an entry with NULL as the value or it has created | 1317 // it has an entry with NULL as the value or it has created |
| 1319 // a new entry on the fly with NULL as the default value. | 1318 // a new entry on the fly with NULL as the default value. |
| 1320 // With such dummy element we have a guaranty that all entries_map_ entries | 1319 // With such dummy element we have a guaranty that all entries_map_ entries |
| 1321 // will have the value field grater than 0. | 1320 // will have the value field grater than 0. |
| 1322 // This fact is using in MoveObject method. | 1321 // This fact is using in MoveObject method. |
| 1323 entries_->Add(EntryInfo(0, NULL, 0)); | 1322 entries_.Add(EntryInfo(0, NULL, 0)); |
| 1324 } | 1323 } |
| 1325 | 1324 |
| 1326 | 1325 |
| 1327 HeapObjectsMap::~HeapObjectsMap() { | |
| 1328 delete entries_; | |
| 1329 } | |
| 1330 | |
| 1331 | |
| 1332 void HeapObjectsMap::SnapshotGenerationFinished() { | 1326 void HeapObjectsMap::SnapshotGenerationFinished() { |
| 1333 RemoveDeadEntries(); | 1327 RemoveDeadEntries(); |
| 1334 } | 1328 } |
| 1335 | 1329 |
| 1336 | 1330 |
| 1337 void HeapObjectsMap::MoveObject(Address from, Address to) { | 1331 void HeapObjectsMap::MoveObject(Address from, Address to) { |
| 1338 ASSERT(to != NULL); | 1332 ASSERT(to != NULL); |
| 1339 ASSERT(from != NULL); | 1333 ASSERT(from != NULL); |
| 1340 if (from == to) return; | 1334 if (from == to) return; |
| 1341 void* from_value = entries_map_.Remove(from, AddressHash(from)); | 1335 void* from_value = entries_map_.Remove(from, AddressHash(from)); |
| 1342 if (from_value == NULL) return; | 1336 if (from_value == NULL) return; |
| 1343 int from_entry_info_index = | 1337 int from_entry_info_index = |
| 1344 static_cast<int>(reinterpret_cast<intptr_t>(from_value)); | 1338 static_cast<int>(reinterpret_cast<intptr_t>(from_value)); |
| 1345 entries_->at(from_entry_info_index).addr = to; | 1339 entries_.at(from_entry_info_index).addr = to; |
| 1346 HashMap::Entry* to_entry = entries_map_.Lookup(to, AddressHash(to), true); | 1340 HashMap::Entry* to_entry = entries_map_.Lookup(to, AddressHash(to), true); |
| 1347 if (to_entry->value != NULL) { | 1341 if (to_entry->value != NULL) { |
| 1348 int to_entry_info_index = | 1342 int to_entry_info_index = |
| 1349 static_cast<int>(reinterpret_cast<intptr_t>(to_entry->value)); | 1343 static_cast<int>(reinterpret_cast<intptr_t>(to_entry->value)); |
| 1350 // Without this operation we will have two EntryInfo's with the same | 1344 // Without this operation we will have two EntryInfo's with the same |
| 1351 // value in addr field. It is bad because later at RemoveDeadEntries | 1345 // value in addr field. It is bad because later at RemoveDeadEntries |
| 1352 // one of this entry will be removed with the corresponding entries_map_ | 1346 // one of this entry will be removed with the corresponding entries_map_ |
| 1353 // entry. | 1347 // entry. |
| 1354 entries_->at(to_entry_info_index).addr = NULL; | 1348 entries_.at(to_entry_info_index).addr = NULL; |
| 1355 } | 1349 } |
| 1356 to_entry->value = reinterpret_cast<void*>(from_entry_info_index); | 1350 to_entry->value = reinterpret_cast<void*>(from_entry_info_index); |
| 1357 } | 1351 } |
| 1358 | 1352 |
| 1359 | 1353 |
| 1360 SnapshotObjectId HeapObjectsMap::FindEntry(Address addr) { | 1354 SnapshotObjectId HeapObjectsMap::FindEntry(Address addr) { |
| 1361 HashMap::Entry* entry = entries_map_.Lookup(addr, AddressHash(addr), false); | 1355 HashMap::Entry* entry = entries_map_.Lookup(addr, AddressHash(addr), false); |
| 1362 if (entry == NULL) return 0; | 1356 if (entry == NULL) return 0; |
| 1363 int entry_index = static_cast<int>(reinterpret_cast<intptr_t>(entry->value)); | 1357 int entry_index = static_cast<int>(reinterpret_cast<intptr_t>(entry->value)); |
| 1364 EntryInfo& entry_info = entries_->at(entry_index); | 1358 EntryInfo& entry_info = entries_.at(entry_index); |
| 1365 ASSERT(static_cast<uint32_t>(entries_->length()) > entries_map_.occupancy()); | 1359 ASSERT(static_cast<uint32_t>(entries_.length()) > entries_map_.occupancy()); |
| 1366 return entry_info.id; | 1360 return entry_info.id; |
| 1367 } | 1361 } |
| 1368 | 1362 |
| 1369 | 1363 |
| 1370 SnapshotObjectId HeapObjectsMap::FindOrAddEntry(Address addr, | 1364 SnapshotObjectId HeapObjectsMap::FindOrAddEntry(Address addr, |
| 1371 unsigned int size) { | 1365 unsigned int size) { |
| 1372 ASSERT(static_cast<uint32_t>(entries_->length()) > entries_map_.occupancy()); | 1366 ASSERT(static_cast<uint32_t>(entries_.length()) > entries_map_.occupancy()); |
| 1373 HashMap::Entry* entry = entries_map_.Lookup(addr, AddressHash(addr), true); | 1367 HashMap::Entry* entry = entries_map_.Lookup(addr, AddressHash(addr), true); |
| 1374 if (entry->value != NULL) { | 1368 if (entry->value != NULL) { |
| 1375 int entry_index = | 1369 int entry_index = |
| 1376 static_cast<int>(reinterpret_cast<intptr_t>(entry->value)); | 1370 static_cast<int>(reinterpret_cast<intptr_t>(entry->value)); |
| 1377 EntryInfo& entry_info = entries_->at(entry_index); | 1371 EntryInfo& entry_info = entries_.at(entry_index); |
| 1378 entry_info.accessed = true; | 1372 entry_info.accessed = true; |
| 1379 entry_info.size = size; | 1373 entry_info.size = size; |
| 1380 return entry_info.id; | 1374 return entry_info.id; |
| 1381 } | 1375 } |
| 1382 entry->value = reinterpret_cast<void*>(entries_->length()); | 1376 entry->value = reinterpret_cast<void*>(entries_.length()); |
| 1383 SnapshotObjectId id = next_id_; | 1377 SnapshotObjectId id = next_id_; |
| 1384 next_id_ += kObjectIdStep; | 1378 next_id_ += kObjectIdStep; |
| 1385 entries_->Add(EntryInfo(id, addr, size)); | 1379 entries_.Add(EntryInfo(id, addr, size)); |
| 1386 ASSERT(static_cast<uint32_t>(entries_->length()) > entries_map_.occupancy()); | 1380 ASSERT(static_cast<uint32_t>(entries_.length()) > entries_map_.occupancy()); |
| 1387 return id; | 1381 return id; |
| 1388 } | 1382 } |
| 1389 | 1383 |
| 1390 | 1384 |
| 1391 void HeapObjectsMap::StopHeapObjectsTracking() { | 1385 void HeapObjectsMap::StopHeapObjectsTracking() { |
| 1392 time_intervals_.Clear(); | 1386 time_intervals_.Clear(); |
| 1393 } | 1387 } |
| 1394 | 1388 |
| 1395 void HeapObjectsMap::UpdateHeapObjectsMap() { | 1389 void HeapObjectsMap::UpdateHeapObjectsMap() { |
| 1396 HEAP->CollectAllGarbage(Heap::kMakeHeapIterableMask, | 1390 HEAP->CollectAllGarbage(Heap::kMakeHeapIterableMask, |
| 1397 "HeapSnapshotsCollection::UpdateHeapObjectsMap"); | 1391 "HeapSnapshotsCollection::UpdateHeapObjectsMap"); |
| 1398 HeapIterator iterator; | 1392 HeapIterator iterator; |
| 1399 for (HeapObject* obj = iterator.next(); | 1393 for (HeapObject* obj = iterator.next(); |
| 1400 obj != NULL; | 1394 obj != NULL; |
| 1401 obj = iterator.next()) { | 1395 obj = iterator.next()) { |
| 1402 FindOrAddEntry(obj->address(), obj->Size()); | 1396 FindOrAddEntry(obj->address(), obj->Size()); |
| 1403 } | 1397 } |
| 1404 RemoveDeadEntries(); | 1398 RemoveDeadEntries(); |
| 1405 } | 1399 } |
| 1406 | 1400 |
| 1407 | 1401 |
| 1408 void HeapObjectsMap::PushHeapObjectsStats(OutputStream* stream) { | 1402 void HeapObjectsMap::PushHeapObjectsStats(OutputStream* stream) { |
| 1409 UpdateHeapObjectsMap(); | 1403 UpdateHeapObjectsMap(); |
| 1410 time_intervals_.Add(TimeInterval(next_id_)); | 1404 time_intervals_.Add(TimeInterval(next_id_)); |
| 1411 int prefered_chunk_size = stream->GetChunkSize(); | 1405 int prefered_chunk_size = stream->GetChunkSize(); |
| 1412 List<uint32_t> stats_buffer; | 1406 List<uint32_t> stats_buffer; |
| 1413 ASSERT(!entries_->is_empty()); | 1407 ASSERT(!entries_.is_empty()); |
| 1414 EntryInfo* entry_info = &entries_->first(); | 1408 EntryInfo* entry_info = &entries_.first(); |
| 1415 EntryInfo* end_entry_info = &entries_->last() + 1; | 1409 EntryInfo* end_entry_info = &entries_.last() + 1; |
| 1416 for (int time_interval_index = 0; | 1410 for (int time_interval_index = 0; |
| 1417 time_interval_index < time_intervals_.length(); | 1411 time_interval_index < time_intervals_.length(); |
| 1418 ++time_interval_index) { | 1412 ++time_interval_index) { |
| 1419 TimeInterval& time_interval = time_intervals_[time_interval_index]; | 1413 TimeInterval& time_interval = time_intervals_[time_interval_index]; |
| 1420 SnapshotObjectId time_interval_id = time_interval.id; | 1414 SnapshotObjectId time_interval_id = time_interval.id; |
| 1421 uint32_t entries_size = 0; | 1415 uint32_t entries_size = 0; |
| 1422 EntryInfo* start_entry_info = entry_info; | 1416 EntryInfo* start_entry_info = entry_info; |
| 1423 while (entry_info < end_entry_info && entry_info->id < time_interval_id) { | 1417 while (entry_info < end_entry_info && entry_info->id < time_interval_id) { |
| 1424 entries_size += entry_info->size; | 1418 entries_size += entry_info->size; |
| 1425 ++entry_info; | 1419 ++entry_info; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1443 if (!stats_buffer.is_empty()) { | 1437 if (!stats_buffer.is_empty()) { |
| 1444 OutputStream::WriteResult result = | 1438 OutputStream::WriteResult result = |
| 1445 stream->WriteUint32Chunk(&stats_buffer.first(), stats_buffer.length()); | 1439 stream->WriteUint32Chunk(&stats_buffer.first(), stats_buffer.length()); |
| 1446 if (result == OutputStream::kAbort) return; | 1440 if (result == OutputStream::kAbort) return; |
| 1447 } | 1441 } |
| 1448 stream->EndOfStream(); | 1442 stream->EndOfStream(); |
| 1449 } | 1443 } |
| 1450 | 1444 |
| 1451 | 1445 |
| 1452 void HeapObjectsMap::RemoveDeadEntries() { | 1446 void HeapObjectsMap::RemoveDeadEntries() { |
| 1453 ASSERT(entries_->length() > 0 && | 1447 ASSERT(entries_.length() > 0 && |
| 1454 entries_->at(0).id == 0 && | 1448 entries_.at(0).id == 0 && |
| 1455 entries_->at(0).addr == NULL); | 1449 entries_.at(0).addr == NULL); |
| 1456 int first_free_entry = 1; | 1450 int first_free_entry = 1; |
| 1457 for (int i = 1; i < entries_->length(); ++i) { | 1451 for (int i = 1; i < entries_.length(); ++i) { |
| 1458 EntryInfo& entry_info = entries_->at(i); | 1452 EntryInfo& entry_info = entries_.at(i); |
| 1459 if (entry_info.accessed) { | 1453 if (entry_info.accessed) { |
| 1460 if (first_free_entry != i) { | 1454 if (first_free_entry != i) { |
| 1461 entries_->at(first_free_entry) = entry_info; | 1455 entries_.at(first_free_entry) = entry_info; |
| 1462 } | 1456 } |
| 1463 entries_->at(first_free_entry).accessed = false; | 1457 entries_.at(first_free_entry).accessed = false; |
| 1464 HashMap::Entry* entry = entries_map_.Lookup( | 1458 HashMap::Entry* entry = entries_map_.Lookup( |
| 1465 entry_info.addr, AddressHash(entry_info.addr), false); | 1459 entry_info.addr, AddressHash(entry_info.addr), false); |
| 1466 ASSERT(entry); | 1460 ASSERT(entry); |
| 1467 entry->value = reinterpret_cast<void*>(first_free_entry); | 1461 entry->value = reinterpret_cast<void*>(first_free_entry); |
| 1468 ++first_free_entry; | 1462 ++first_free_entry; |
| 1469 } else { | 1463 } else { |
| 1470 if (entry_info.addr) { | 1464 if (entry_info.addr) { |
| 1471 entries_map_.Remove(entry_info.addr, AddressHash(entry_info.addr)); | 1465 entries_map_.Remove(entry_info.addr, AddressHash(entry_info.addr)); |
| 1472 } | 1466 } |
| 1473 } | 1467 } |
| 1474 } | 1468 } |
| 1475 entries_->Rewind(first_free_entry); | 1469 entries_.Rewind(first_free_entry); |
| 1476 ASSERT(static_cast<uint32_t>(entries_->length()) - 1 == | 1470 ASSERT(static_cast<uint32_t>(entries_.length()) - 1 == |
| 1477 entries_map_.occupancy()); | 1471 entries_map_.occupancy()); |
| 1478 } | 1472 } |
| 1479 | 1473 |
| 1480 | 1474 |
| 1481 SnapshotObjectId HeapObjectsMap::GenerateId(v8::RetainedObjectInfo* info) { | 1475 SnapshotObjectId HeapObjectsMap::GenerateId(v8::RetainedObjectInfo* info) { |
| 1482 SnapshotObjectId id = static_cast<SnapshotObjectId>(info->GetHash()); | 1476 SnapshotObjectId id = static_cast<SnapshotObjectId>(info->GetHash()); |
| 1483 const char* label = info->GetLabel(); | 1477 const char* label = info->GetLabel(); |
| 1484 id ^= HashSequentialString(label, | 1478 id ^= HashSequentialString(label, |
| 1485 static_cast<int>(strlen(label)), | 1479 static_cast<int>(strlen(label)), |
| 1486 HEAP->HashSeed()); | 1480 HEAP->HashSeed()); |
| (...skipping 2412 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3899 | 3893 |
| 3900 | 3894 |
| 3901 void HeapSnapshotJSONSerializer::SortHashMap( | 3895 void HeapSnapshotJSONSerializer::SortHashMap( |
| 3902 HashMap* map, List<HashMap::Entry*>* sorted_entries) { | 3896 HashMap* map, List<HashMap::Entry*>* sorted_entries) { |
| 3903 for (HashMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) | 3897 for (HashMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) |
| 3904 sorted_entries->Add(p); | 3898 sorted_entries->Add(p); |
| 3905 sorted_entries->Sort(SortUsingEntryValue); | 3899 sorted_entries->Sort(SortUsingEntryValue); |
| 3906 } | 3900 } |
| 3907 | 3901 |
| 3908 } } // namespace v8::internal | 3902 } } // namespace v8::internal |
| OLD | NEW |