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 |