| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 390 // This fact is using in MoveObject method. | 390 // This fact is using in MoveObject method. |
| 391 entries_.Add(EntryInfo(0, NULL, 0)); | 391 entries_.Add(EntryInfo(0, NULL, 0)); |
| 392 } | 392 } |
| 393 | 393 |
| 394 | 394 |
| 395 void HeapObjectsMap::SnapshotGenerationFinished() { | 395 void HeapObjectsMap::SnapshotGenerationFinished() { |
| 396 RemoveDeadEntries(); | 396 RemoveDeadEntries(); |
| 397 } | 397 } |
| 398 | 398 |
| 399 | 399 |
| 400 void HeapObjectsMap::MoveObject(Address from, Address to) { | 400 void HeapObjectsMap::MoveObject(Address from, Address to, int object_size) { |
| 401 ASSERT(to != NULL); | 401 ASSERT(to != NULL); |
| 402 ASSERT(from != NULL); | 402 ASSERT(from != NULL); |
| 403 if (from == to) return; | 403 if (from == to) return; |
| 404 void* from_value = entries_map_.Remove(from, ComputePointerHash(from)); | 404 void* from_value = entries_map_.Remove(from, ComputePointerHash(from)); |
| 405 if (from_value == NULL) { | 405 if (from_value == NULL) { |
| 406 // It may occur that some untracked object moves to an address X and there | 406 // It may occur that some untracked object moves to an address X and there |
| 407 // is a tracked object at that address. In this case we should remove the | 407 // is a tracked object at that address. In this case we should remove the |
| 408 // entry as we know that the object has died. | 408 // entry as we know that the object has died. |
| 409 void* to_value = entries_map_.Remove(to, ComputePointerHash(to)); | 409 void* to_value = entries_map_.Remove(to, ComputePointerHash(to)); |
| 410 if (to_value != NULL) { | 410 if (to_value != NULL) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 421 // value in addr field. It is bad because later at RemoveDeadEntries | 421 // value in addr field. It is bad because later at RemoveDeadEntries |
| 422 // one of this entry will be removed with the corresponding entries_map_ | 422 // one of this entry will be removed with the corresponding entries_map_ |
| 423 // entry. | 423 // entry. |
| 424 int to_entry_info_index = | 424 int to_entry_info_index = |
| 425 static_cast<int>(reinterpret_cast<intptr_t>(to_entry->value)); | 425 static_cast<int>(reinterpret_cast<intptr_t>(to_entry->value)); |
| 426 entries_.at(to_entry_info_index).addr = NULL; | 426 entries_.at(to_entry_info_index).addr = NULL; |
| 427 } | 427 } |
| 428 int from_entry_info_index = | 428 int from_entry_info_index = |
| 429 static_cast<int>(reinterpret_cast<intptr_t>(from_value)); | 429 static_cast<int>(reinterpret_cast<intptr_t>(from_value)); |
| 430 entries_.at(from_entry_info_index).addr = to; | 430 entries_.at(from_entry_info_index).addr = to; |
| 431 // Size of an object can change during its life, so to keep information |
| 432 // about the object in entries_ consistent, we have to adjust size when the |
| 433 // object is migrated. |
| 434 printf("Adjust\n"); |
| 435 entries_.at(from_entry_info_index).size = object_size; |
| 431 to_entry->value = from_value; | 436 to_entry->value = from_value; |
| 432 } | 437 } |
| 433 } | 438 } |
| 434 | 439 |
| 435 | 440 |
| 441 void HeapObjectsMap::NewObject(Address addr, int size) { |
| 442 ASSERT(addr != NULL); |
| 443 FindOrAddEntry(addr, size, false); |
| 444 } |
| 445 |
| 446 |
| 447 void HeapObjectsMap::UpdateObjectSize(Address addr, int size) { |
| 448 FindOrAddEntry(addr, size, false); |
| 449 } |
| 450 |
| 451 |
| 436 SnapshotObjectId HeapObjectsMap::FindEntry(Address addr) { | 452 SnapshotObjectId HeapObjectsMap::FindEntry(Address addr) { |
| 437 HashMap::Entry* entry = entries_map_.Lookup(addr, ComputePointerHash(addr), | 453 HashMap::Entry* entry = entries_map_.Lookup(addr, ComputePointerHash(addr), |
| 438 false); | 454 false); |
| 439 if (entry == NULL) return 0; | 455 if (entry == NULL) return 0; |
| 440 int entry_index = static_cast<int>(reinterpret_cast<intptr_t>(entry->value)); | 456 int entry_index = static_cast<int>(reinterpret_cast<intptr_t>(entry->value)); |
| 441 EntryInfo& entry_info = entries_.at(entry_index); | 457 EntryInfo& entry_info = entries_.at(entry_index); |
| 442 ASSERT(static_cast<uint32_t>(entries_.length()) > entries_map_.occupancy()); | 458 ASSERT(static_cast<uint32_t>(entries_.length()) > entries_map_.occupancy()); |
| 443 return entry_info.id; | 459 return entry_info.id; |
| 444 } | 460 } |
| 445 | 461 |
| 446 | 462 |
| 447 SnapshotObjectId HeapObjectsMap::FindOrAddEntry(Address addr, | 463 SnapshotObjectId HeapObjectsMap::FindOrAddEntry(Address addr, |
| 448 unsigned int size) { | 464 unsigned int size, |
| 465 bool accessed) { |
| 449 ASSERT(static_cast<uint32_t>(entries_.length()) > entries_map_.occupancy()); | 466 ASSERT(static_cast<uint32_t>(entries_.length()) > entries_map_.occupancy()); |
| 450 HashMap::Entry* entry = entries_map_.Lookup(addr, ComputePointerHash(addr), | 467 HashMap::Entry* entry = entries_map_.Lookup(addr, ComputePointerHash(addr), |
| 451 true); | 468 true); |
| 452 if (entry->value != NULL) { | 469 if (entry->value != NULL) { |
| 453 int entry_index = | 470 int entry_index = |
| 454 static_cast<int>(reinterpret_cast<intptr_t>(entry->value)); | 471 static_cast<int>(reinterpret_cast<intptr_t>(entry->value)); |
| 455 EntryInfo& entry_info = entries_.at(entry_index); | 472 EntryInfo& entry_info = entries_.at(entry_index); |
| 456 entry_info.accessed = true; | 473 entry_info.accessed = accessed; |
| 457 entry_info.size = size; | 474 entry_info.size = size; |
| 458 return entry_info.id; | 475 return entry_info.id; |
| 459 } | 476 } |
| 460 entry->value = reinterpret_cast<void*>(entries_.length()); | 477 entry->value = reinterpret_cast<void*>(entries_.length()); |
| 461 SnapshotObjectId id = next_id_; | 478 SnapshotObjectId id = next_id_; |
| 462 next_id_ += kObjectIdStep; | 479 next_id_ += kObjectIdStep; |
| 463 entries_.Add(EntryInfo(id, addr, size)); | 480 entries_.Add(EntryInfo(id, addr, size, accessed)); |
| 464 ASSERT(static_cast<uint32_t>(entries_.length()) > entries_map_.occupancy()); | 481 ASSERT(static_cast<uint32_t>(entries_.length()) > entries_map_.occupancy()); |
| 465 return id; | 482 return id; |
| 466 } | 483 } |
| 467 | 484 |
| 468 | 485 |
| 469 void HeapObjectsMap::StopHeapObjectsTracking() { | 486 void HeapObjectsMap::StopHeapObjectsTracking() { |
| 470 time_intervals_.Clear(); | 487 time_intervals_.Clear(); |
| 471 } | 488 } |
| 472 | 489 |
| 473 | 490 |
| 474 void HeapObjectsMap::UpdateHeapObjectsMap() { | 491 void HeapObjectsMap::UpdateHeapObjectsMap() { |
| 475 heap_->CollectAllGarbage(Heap::kMakeHeapIterableMask, | 492 heap_->CollectAllGarbage(Heap::kMakeHeapIterableMask, |
| 476 "HeapSnapshotsCollection::UpdateHeapObjectsMap"); | 493 "HeapSnapshotsCollection::UpdateHeapObjectsMap"); |
| 477 HeapIterator iterator(heap_); | 494 HeapIterator iterator(heap_); |
| 478 for (HeapObject* obj = iterator.next(); | 495 for (HeapObject* obj = iterator.next(); |
| 479 obj != NULL; | 496 obj != NULL; |
| 480 obj = iterator.next()) { | 497 obj = iterator.next()) { |
| 481 FindOrAddEntry(obj->address(), obj->Size()); | 498 FindOrAddEntry(obj->address(), obj->Size()); |
| 482 } | 499 } |
| 483 RemoveDeadEntries(); | 500 RemoveDeadEntries(); |
| 484 } | 501 } |
| 485 | 502 |
| 486 | 503 |
| 504 void HeapObjectsMap::UpdateMap() { |
| 505 HeapIterator iterator(heap_); |
| 506 for (HeapObject* obj = iterator.next(); |
| 507 obj != NULL; |
| 508 obj = iterator.next()) { |
| 509 FindOrAddEntry(obj->address(), obj->Size()); |
| 510 } |
| 511 } |
| 512 |
| 513 |
| 514 int HeapObjectsMap::FindUntrackedObjects() { |
| 515 HeapIterator iterator(heap_); |
| 516 int untracked = 0; |
| 517 for (HeapObject* obj = iterator.next(); |
| 518 obj != NULL; |
| 519 obj = iterator.next()) { |
| 520 HashMap::Entry* entry = entries_map_.Lookup( |
| 521 obj->address(), ComputePointerHash(obj->address()), false); |
| 522 if (entry == NULL) { |
| 523 untracked++; |
| 524 } else { |
| 525 int entry_index = static_cast<int>( |
| 526 reinterpret_cast<intptr_t>(entry->value)); |
| 527 EntryInfo& entry_info = entries_.at(entry_index); |
| 528 CHECK_EQ(obj->Size(), static_cast<int>(entry_info.size)); |
| 529 } |
| 530 } |
| 531 return untracked; |
| 532 } |
| 533 |
| 534 |
| 487 SnapshotObjectId HeapObjectsMap::PushHeapObjectsStats(OutputStream* stream) { | 535 SnapshotObjectId HeapObjectsMap::PushHeapObjectsStats(OutputStream* stream) { |
| 488 UpdateHeapObjectsMap(); | 536 UpdateHeapObjectsMap(); |
| 489 time_intervals_.Add(TimeInterval(next_id_)); | 537 time_intervals_.Add(TimeInterval(next_id_)); |
| 490 int prefered_chunk_size = stream->GetChunkSize(); | 538 int prefered_chunk_size = stream->GetChunkSize(); |
| 491 List<v8::HeapStatsUpdate> stats_buffer; | 539 List<v8::HeapStatsUpdate> stats_buffer; |
| 492 ASSERT(!entries_.is_empty()); | 540 ASSERT(!entries_.is_empty()); |
| 493 EntryInfo* entry_info = &entries_.first(); | 541 EntryInfo* entry_info = &entries_.first(); |
| 494 EntryInfo* end_entry_info = &entries_.last() + 1; | 542 EntryInfo* end_entry_info = &entries_.last() + 1; |
| 495 for (int time_interval_index = 0; | 543 for (int time_interval_index = 0; |
| 496 time_interval_index < time_intervals_.length(); | 544 time_interval_index < time_intervals_.length(); |
| (...skipping 2207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2704 writer_->AddString("\"<dummy>\""); | 2752 writer_->AddString("\"<dummy>\""); |
| 2705 for (int i = 1; i < sorted_strings.length(); ++i) { | 2753 for (int i = 1; i < sorted_strings.length(); ++i) { |
| 2706 writer_->AddCharacter(','); | 2754 writer_->AddCharacter(','); |
| 2707 SerializeString(sorted_strings[i]); | 2755 SerializeString(sorted_strings[i]); |
| 2708 if (writer_->aborted()) return; | 2756 if (writer_->aborted()) return; |
| 2709 } | 2757 } |
| 2710 } | 2758 } |
| 2711 | 2759 |
| 2712 | 2760 |
| 2713 } } // namespace v8::internal | 2761 } } // namespace v8::internal |
| OLD | NEW |