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 377 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
388 // This fact is using in MoveObject method. | 388 // This fact is using in MoveObject method. |
389 entries_.Add(EntryInfo(0, NULL, 0)); | 389 entries_.Add(EntryInfo(0, NULL, 0)); |
390 } | 390 } |
391 | 391 |
392 | 392 |
393 void HeapObjectsMap::SnapshotGenerationFinished() { | 393 void HeapObjectsMap::SnapshotGenerationFinished() { |
394 RemoveDeadEntries(); | 394 RemoveDeadEntries(); |
395 } | 395 } |
396 | 396 |
397 | 397 |
398 void HeapObjectsMap::MoveObject(Address from, Address to) { | 398 void HeapObjectsMap::MoveObject(Address from, Address to, int object_size) { |
loislo
2013/08/27 09:04:57
I think that we need new method UpdateObjectSize a
Alexandra Mikhaylova
2013/09/19 16:03:38
Done.
| |
399 ASSERT(to != NULL); | 399 ASSERT(to != NULL); |
400 ASSERT(from != NULL); | 400 ASSERT(from != NULL); |
401 if (from == to) return; | 401 if (from == to) return; |
402 void* from_value = entries_map_.Remove(from, ComputePointerHash(from)); | 402 void* from_value = entries_map_.Remove(from, ComputePointerHash(from)); |
403 if (from_value == NULL) { | 403 if (from_value == NULL) { |
404 // It may occur that some untracked object moves to an address X and there | 404 // It may occur that some untracked object moves to an address X and there |
405 // is a tracked object at that address. In this case we should remove the | 405 // is a tracked object at that address. In this case we should remove the |
406 // entry as we know that the object has died. | 406 // entry as we know that the object has died. |
407 void* to_value = entries_map_.Remove(to, ComputePointerHash(to)); | 407 void* to_value = entries_map_.Remove(to, ComputePointerHash(to)); |
408 if (to_value != NULL) { | 408 if (to_value != NULL) { |
(...skipping 10 matching lines...) Expand all Loading... | |
419 // value in addr field. It is bad because later at RemoveDeadEntries | 419 // value in addr field. It is bad because later at RemoveDeadEntries |
420 // one of this entry will be removed with the corresponding entries_map_ | 420 // one of this entry will be removed with the corresponding entries_map_ |
421 // entry. | 421 // entry. |
422 int to_entry_info_index = | 422 int to_entry_info_index = |
423 static_cast<int>(reinterpret_cast<intptr_t>(to_entry->value)); | 423 static_cast<int>(reinterpret_cast<intptr_t>(to_entry->value)); |
424 entries_.at(to_entry_info_index).addr = NULL; | 424 entries_.at(to_entry_info_index).addr = NULL; |
425 } | 425 } |
426 int from_entry_info_index = | 426 int from_entry_info_index = |
427 static_cast<int>(reinterpret_cast<intptr_t>(from_value)); | 427 static_cast<int>(reinterpret_cast<intptr_t>(from_value)); |
428 entries_.at(from_entry_info_index).addr = to; | 428 entries_.at(from_entry_info_index).addr = to; |
429 // Size of an object can change during its life, so to keep information | |
430 // about the object in entries_ consistent, we have to adjust size when the | |
431 // object is migrated. | |
432 entries_.at(from_entry_info_index).size = object_size; | |
429 to_entry->value = from_value; | 433 to_entry->value = from_value; |
430 } | 434 } |
431 } | 435 } |
432 | 436 |
433 | 437 |
438 void HeapObjectsMap::NewObject(Address addr, int size) { | |
439 ASSERT(addr != NULL); | |
440 FindOrAddEntry(addr, size, false); | |
441 } | |
442 | |
443 | |
434 SnapshotObjectId HeapObjectsMap::FindEntry(Address addr) { | 444 SnapshotObjectId HeapObjectsMap::FindEntry(Address addr) { |
435 HashMap::Entry* entry = entries_map_.Lookup(addr, ComputePointerHash(addr), | 445 HashMap::Entry* entry = entries_map_.Lookup(addr, ComputePointerHash(addr), |
436 false); | 446 false); |
437 if (entry == NULL) return 0; | 447 if (entry == NULL) return 0; |
438 int entry_index = static_cast<int>(reinterpret_cast<intptr_t>(entry->value)); | 448 int entry_index = static_cast<int>(reinterpret_cast<intptr_t>(entry->value)); |
439 EntryInfo& entry_info = entries_.at(entry_index); | 449 EntryInfo& entry_info = entries_.at(entry_index); |
440 ASSERT(static_cast<uint32_t>(entries_.length()) > entries_map_.occupancy()); | 450 ASSERT(static_cast<uint32_t>(entries_.length()) > entries_map_.occupancy()); |
441 return entry_info.id; | 451 return entry_info.id; |
442 } | 452 } |
443 | 453 |
444 | 454 |
445 SnapshotObjectId HeapObjectsMap::FindOrAddEntry(Address addr, | 455 SnapshotObjectId HeapObjectsMap::FindOrAddEntry(Address addr, |
446 unsigned int size) { | 456 unsigned int size, |
457 bool accessed) { | |
447 ASSERT(static_cast<uint32_t>(entries_.length()) > entries_map_.occupancy()); | 458 ASSERT(static_cast<uint32_t>(entries_.length()) > entries_map_.occupancy()); |
448 HashMap::Entry* entry = entries_map_.Lookup(addr, ComputePointerHash(addr), | 459 HashMap::Entry* entry = entries_map_.Lookup(addr, ComputePointerHash(addr), |
449 true); | 460 true); |
450 if (entry->value != NULL) { | 461 if (entry->value != NULL) { |
451 int entry_index = | 462 int entry_index = |
452 static_cast<int>(reinterpret_cast<intptr_t>(entry->value)); | 463 static_cast<int>(reinterpret_cast<intptr_t>(entry->value)); |
453 EntryInfo& entry_info = entries_.at(entry_index); | 464 EntryInfo& entry_info = entries_.at(entry_index); |
454 entry_info.accessed = true; | 465 entry_info.accessed = accessed; |
455 entry_info.size = size; | 466 entry_info.size = size; |
456 return entry_info.id; | 467 return entry_info.id; |
457 } | 468 } |
458 entry->value = reinterpret_cast<void*>(entries_.length()); | 469 entry->value = reinterpret_cast<void*>(entries_.length()); |
459 SnapshotObjectId id = next_id_; | 470 SnapshotObjectId id = next_id_; |
460 next_id_ += kObjectIdStep; | 471 next_id_ += kObjectIdStep; |
461 entries_.Add(EntryInfo(id, addr, size)); | 472 entries_.Add(EntryInfo(id, addr, size, accessed)); |
462 ASSERT(static_cast<uint32_t>(entries_.length()) > entries_map_.occupancy()); | 473 ASSERT(static_cast<uint32_t>(entries_.length()) > entries_map_.occupancy()); |
463 return id; | 474 return id; |
464 } | 475 } |
465 | 476 |
466 | 477 |
467 void HeapObjectsMap::StopHeapObjectsTracking() { | 478 void HeapObjectsMap::StopHeapObjectsTracking() { |
468 time_intervals_.Clear(); | 479 time_intervals_.Clear(); |
469 } | 480 } |
470 | 481 |
471 | 482 |
472 void HeapObjectsMap::UpdateHeapObjectsMap() { | 483 void HeapObjectsMap::UpdateHeapObjectsMap() { |
473 HEAP->CollectAllGarbage(Heap::kMakeHeapIterableMask, | 484 HEAP->CollectAllGarbage(Heap::kMakeHeapIterableMask, |
474 "HeapSnapshotsCollection::UpdateHeapObjectsMap"); | 485 "HeapSnapshotsCollection::UpdateHeapObjectsMap"); |
475 HeapIterator iterator(heap_); | 486 HeapIterator iterator(heap_); |
476 for (HeapObject* obj = iterator.next(); | 487 for (HeapObject* obj = iterator.next(); |
477 obj != NULL; | 488 obj != NULL; |
478 obj = iterator.next()) { | 489 obj = iterator.next()) { |
479 FindOrAddEntry(obj->address(), obj->Size()); | 490 FindOrAddEntry(obj->address(), obj->Size()); |
480 } | 491 } |
481 RemoveDeadEntries(); | 492 RemoveDeadEntries(); |
482 } | 493 } |
483 | 494 |
484 | 495 |
496 int HeapObjectsMap::FindUntrackedObjects() { | |
497 HeapIterator iterator(heap_); | |
498 int untracked = 0; | |
499 for (HeapObject* obj = iterator.next(); | |
500 obj != NULL; | |
501 obj = iterator.next()) { | |
502 HashMap::Entry* entry = entries_map_.Lookup( | |
503 obj->address(), ComputePointerHash(obj->address()), false); | |
504 if (entry == NULL) { | |
505 untracked++; | |
506 } else { | |
507 int entry_index = static_cast<int>( | |
508 reinterpret_cast<intptr_t>(entry->value)); | |
509 EntryInfo& entry_info = entries_.at(entry_index); | |
510 ASSERT_EQ(obj->Size(), static_cast<int>(entry_info.size)); | |
511 } | |
512 } | |
513 return untracked; | |
514 } | |
515 | |
516 | |
485 SnapshotObjectId HeapObjectsMap::PushHeapObjectsStats(OutputStream* stream) { | 517 SnapshotObjectId HeapObjectsMap::PushHeapObjectsStats(OutputStream* stream) { |
486 UpdateHeapObjectsMap(); | 518 UpdateHeapObjectsMap(); |
487 time_intervals_.Add(TimeInterval(next_id_)); | 519 time_intervals_.Add(TimeInterval(next_id_)); |
488 int prefered_chunk_size = stream->GetChunkSize(); | 520 int prefered_chunk_size = stream->GetChunkSize(); |
489 List<v8::HeapStatsUpdate> stats_buffer; | 521 List<v8::HeapStatsUpdate> stats_buffer; |
490 ASSERT(!entries_.is_empty()); | 522 ASSERT(!entries_.is_empty()); |
491 EntryInfo* entry_info = &entries_.first(); | 523 EntryInfo* entry_info = &entries_.first(); |
492 EntryInfo* end_entry_info = &entries_.last() + 1; | 524 EntryInfo* end_entry_info = &entries_.last() + 1; |
493 for (int time_interval_index = 0; | 525 for (int time_interval_index = 0; |
494 time_interval_index < time_intervals_.length(); | 526 time_interval_index < time_intervals_.length(); |
(...skipping 2208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2703 | 2735 |
2704 | 2736 |
2705 void HeapSnapshotJSONSerializer::SortHashMap( | 2737 void HeapSnapshotJSONSerializer::SortHashMap( |
2706 HashMap* map, List<HashMap::Entry*>* sorted_entries) { | 2738 HashMap* map, List<HashMap::Entry*>* sorted_entries) { |
2707 for (HashMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) | 2739 for (HashMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) |
2708 sorted_entries->Add(p); | 2740 sorted_entries->Add(p); |
2709 sorted_entries->Sort(SortUsingEntryValue); | 2741 sorted_entries->Sort(SortUsingEntryValue); |
2710 } | 2742 } |
2711 | 2743 |
2712 } } // namespace v8::internal | 2744 } } // namespace v8::internal |
OLD | NEW |