| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #include "src/heap-snapshot-generator-inl.h" | 7 #include "src/heap-snapshot-generator-inl.h" |
| 8 | 8 |
| 9 #include "src/allocation-tracker.h" | 9 #include "src/allocation-tracker.h" |
| 10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
| (...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 384 // It may occur that some untracked object moves to an address X and there | 384 // It may occur that some untracked object moves to an address X and there |
| 385 // is a tracked object at that address. In this case we should remove the | 385 // is a tracked object at that address. In this case we should remove the |
| 386 // entry as we know that the object has died. | 386 // entry as we know that the object has died. |
| 387 void* to_value = entries_map_.Remove(to, ComputePointerHash(to)); | 387 void* to_value = entries_map_.Remove(to, ComputePointerHash(to)); |
| 388 if (to_value != NULL) { | 388 if (to_value != NULL) { |
| 389 int to_entry_info_index = | 389 int to_entry_info_index = |
| 390 static_cast<int>(reinterpret_cast<intptr_t>(to_value)); | 390 static_cast<int>(reinterpret_cast<intptr_t>(to_value)); |
| 391 entries_.at(to_entry_info_index).addr = NULL; | 391 entries_.at(to_entry_info_index).addr = NULL; |
| 392 } | 392 } |
| 393 } else { | 393 } else { |
| 394 HashMap::Entry* to_entry = entries_map_.Lookup(to, ComputePointerHash(to), | 394 HashMap::Entry* to_entry = |
| 395 true); | 395 entries_map_.LookupOrInsert(to, ComputePointerHash(to)); |
| 396 if (to_entry->value != NULL) { | 396 if (to_entry->value != NULL) { |
| 397 // We found the existing entry with to address for an old object. | 397 // We found the existing entry with to address for an old object. |
| 398 // Without this operation we will have two EntryInfo's with the same | 398 // Without this operation we will have two EntryInfo's with the same |
| 399 // value in addr field. It is bad because later at RemoveDeadEntries | 399 // value in addr field. It is bad because later at RemoveDeadEntries |
| 400 // one of this entry will be removed with the corresponding entries_map_ | 400 // one of this entry will be removed with the corresponding entries_map_ |
| 401 // entry. | 401 // entry. |
| 402 int to_entry_info_index = | 402 int to_entry_info_index = |
| 403 static_cast<int>(reinterpret_cast<intptr_t>(to_entry->value)); | 403 static_cast<int>(reinterpret_cast<intptr_t>(to_entry->value)); |
| 404 entries_.at(to_entry_info_index).addr = NULL; | 404 entries_.at(to_entry_info_index).addr = NULL; |
| 405 } | 405 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 422 return from_value != NULL; | 422 return from_value != NULL; |
| 423 } | 423 } |
| 424 | 424 |
| 425 | 425 |
| 426 void HeapObjectsMap::UpdateObjectSize(Address addr, int size) { | 426 void HeapObjectsMap::UpdateObjectSize(Address addr, int size) { |
| 427 FindOrAddEntry(addr, size, false); | 427 FindOrAddEntry(addr, size, false); |
| 428 } | 428 } |
| 429 | 429 |
| 430 | 430 |
| 431 SnapshotObjectId HeapObjectsMap::FindEntry(Address addr) { | 431 SnapshotObjectId HeapObjectsMap::FindEntry(Address addr) { |
| 432 HashMap::Entry* entry = entries_map_.Lookup(addr, ComputePointerHash(addr), | 432 HashMap::Entry* entry = entries_map_.Lookup(addr, ComputePointerHash(addr)); |
| 433 false); | |
| 434 if (entry == NULL) return 0; | 433 if (entry == NULL) return 0; |
| 435 int entry_index = static_cast<int>(reinterpret_cast<intptr_t>(entry->value)); | 434 int entry_index = static_cast<int>(reinterpret_cast<intptr_t>(entry->value)); |
| 436 EntryInfo& entry_info = entries_.at(entry_index); | 435 EntryInfo& entry_info = entries_.at(entry_index); |
| 437 DCHECK(static_cast<uint32_t>(entries_.length()) > entries_map_.occupancy()); | 436 DCHECK(static_cast<uint32_t>(entries_.length()) > entries_map_.occupancy()); |
| 438 return entry_info.id; | 437 return entry_info.id; |
| 439 } | 438 } |
| 440 | 439 |
| 441 | 440 |
| 442 SnapshotObjectId HeapObjectsMap::FindOrAddEntry(Address addr, | 441 SnapshotObjectId HeapObjectsMap::FindOrAddEntry(Address addr, |
| 443 unsigned int size, | 442 unsigned int size, |
| 444 bool accessed) { | 443 bool accessed) { |
| 445 DCHECK(static_cast<uint32_t>(entries_.length()) > entries_map_.occupancy()); | 444 DCHECK(static_cast<uint32_t>(entries_.length()) > entries_map_.occupancy()); |
| 446 HashMap::Entry* entry = entries_map_.Lookup(addr, ComputePointerHash(addr), | 445 HashMap::Entry* entry = |
| 447 true); | 446 entries_map_.LookupOrInsert(addr, ComputePointerHash(addr)); |
| 448 if (entry->value != NULL) { | 447 if (entry->value != NULL) { |
| 449 int entry_index = | 448 int entry_index = |
| 450 static_cast<int>(reinterpret_cast<intptr_t>(entry->value)); | 449 static_cast<int>(reinterpret_cast<intptr_t>(entry->value)); |
| 451 EntryInfo& entry_info = entries_.at(entry_index); | 450 EntryInfo& entry_info = entries_.at(entry_index); |
| 452 entry_info.accessed = accessed; | 451 entry_info.accessed = accessed; |
| 453 if (FLAG_heap_profiler_trace_objects) { | 452 if (FLAG_heap_profiler_trace_objects) { |
| 454 PrintF("Update object size : %p with old size %d and new size %d\n", | 453 PrintF("Update object size : %p with old size %d and new size %d\n", |
| 455 addr, | 454 addr, |
| 456 entry_info.size, | 455 entry_info.size, |
| 457 size); | 456 size); |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 547 | 546 |
| 548 | 547 |
| 549 int HeapObjectsMap::FindUntrackedObjects() { | 548 int HeapObjectsMap::FindUntrackedObjects() { |
| 550 List<HeapObjectInfo> heap_objects(1000); | 549 List<HeapObjectInfo> heap_objects(1000); |
| 551 | 550 |
| 552 HeapIterator iterator(heap_); | 551 HeapIterator iterator(heap_); |
| 553 int untracked = 0; | 552 int untracked = 0; |
| 554 for (HeapObject* obj = iterator.next(); | 553 for (HeapObject* obj = iterator.next(); |
| 555 obj != NULL; | 554 obj != NULL; |
| 556 obj = iterator.next()) { | 555 obj = iterator.next()) { |
| 557 HashMap::Entry* entry = entries_map_.Lookup( | 556 HashMap::Entry* entry = |
| 558 obj->address(), ComputePointerHash(obj->address()), false); | 557 entries_map_.Lookup(obj->address(), ComputePointerHash(obj->address())); |
| 559 if (entry == NULL) { | 558 if (entry == NULL) { |
| 560 ++untracked; | 559 ++untracked; |
| 561 if (FLAG_heap_profiler_trace_objects) { | 560 if (FLAG_heap_profiler_trace_objects) { |
| 562 heap_objects.Add(HeapObjectInfo(obj, 0)); | 561 heap_objects.Add(HeapObjectInfo(obj, 0)); |
| 563 } | 562 } |
| 564 } else { | 563 } else { |
| 565 int entry_index = static_cast<int>( | 564 int entry_index = static_cast<int>( |
| 566 reinterpret_cast<intptr_t>(entry->value)); | 565 reinterpret_cast<intptr_t>(entry->value)); |
| 567 EntryInfo& entry_info = entries_.at(entry_index); | 566 EntryInfo& entry_info = entries_.at(entry_index); |
| 568 if (FLAG_heap_profiler_trace_objects) { | 567 if (FLAG_heap_profiler_trace_objects) { |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 668 entries_.at(0).addr == NULL); | 667 entries_.at(0).addr == NULL); |
| 669 int first_free_entry = 1; | 668 int first_free_entry = 1; |
| 670 for (int i = 1; i < entries_.length(); ++i) { | 669 for (int i = 1; i < entries_.length(); ++i) { |
| 671 EntryInfo& entry_info = entries_.at(i); | 670 EntryInfo& entry_info = entries_.at(i); |
| 672 if (entry_info.accessed) { | 671 if (entry_info.accessed) { |
| 673 if (first_free_entry != i) { | 672 if (first_free_entry != i) { |
| 674 entries_.at(first_free_entry) = entry_info; | 673 entries_.at(first_free_entry) = entry_info; |
| 675 } | 674 } |
| 676 entries_.at(first_free_entry).accessed = false; | 675 entries_.at(first_free_entry).accessed = false; |
| 677 HashMap::Entry* entry = entries_map_.Lookup( | 676 HashMap::Entry* entry = entries_map_.Lookup( |
| 678 entry_info.addr, ComputePointerHash(entry_info.addr), false); | 677 entry_info.addr, ComputePointerHash(entry_info.addr)); |
| 679 DCHECK(entry); | 678 DCHECK(entry); |
| 680 entry->value = reinterpret_cast<void*>(first_free_entry); | 679 entry->value = reinterpret_cast<void*>(first_free_entry); |
| 681 ++first_free_entry; | 680 ++first_free_entry; |
| 682 } else { | 681 } else { |
| 683 if (entry_info.addr) { | 682 if (entry_info.addr) { |
| 684 entries_map_.Remove(entry_info.addr, | 683 entries_map_.Remove(entry_info.addr, |
| 685 ComputePointerHash(entry_info.addr)); | 684 ComputePointerHash(entry_info.addr)); |
| 686 } | 685 } |
| 687 } | 686 } |
| 688 } | 687 } |
| (...skipping 25 matching lines...) Expand all Loading... |
| 714 GetMemoryUsedByList(time_intervals_); | 713 GetMemoryUsedByList(time_intervals_); |
| 715 } | 714 } |
| 716 | 715 |
| 717 | 716 |
| 718 HeapEntriesMap::HeapEntriesMap() | 717 HeapEntriesMap::HeapEntriesMap() |
| 719 : entries_(HashMap::PointersMatch) { | 718 : entries_(HashMap::PointersMatch) { |
| 720 } | 719 } |
| 721 | 720 |
| 722 | 721 |
| 723 int HeapEntriesMap::Map(HeapThing thing) { | 722 int HeapEntriesMap::Map(HeapThing thing) { |
| 724 HashMap::Entry* cache_entry = entries_.Lookup(thing, Hash(thing), false); | 723 HashMap::Entry* cache_entry = entries_.Lookup(thing, Hash(thing)); |
| 725 if (cache_entry == NULL) return HeapEntry::kNoEntry; | 724 if (cache_entry == NULL) return HeapEntry::kNoEntry; |
| 726 return static_cast<int>(reinterpret_cast<intptr_t>(cache_entry->value)); | 725 return static_cast<int>(reinterpret_cast<intptr_t>(cache_entry->value)); |
| 727 } | 726 } |
| 728 | 727 |
| 729 | 728 |
| 730 void HeapEntriesMap::Pair(HeapThing thing, int entry) { | 729 void HeapEntriesMap::Pair(HeapThing thing, int entry) { |
| 731 HashMap::Entry* cache_entry = entries_.Lookup(thing, Hash(thing), true); | 730 HashMap::Entry* cache_entry = entries_.LookupOrInsert(thing, Hash(thing)); |
| 732 DCHECK(cache_entry->value == NULL); | 731 DCHECK(cache_entry->value == NULL); |
| 733 cache_entry->value = reinterpret_cast<void*>(static_cast<intptr_t>(entry)); | 732 cache_entry->value = reinterpret_cast<void*>(static_cast<intptr_t>(entry)); |
| 734 } | 733 } |
| 735 | 734 |
| 736 | 735 |
| 737 HeapObjectsSet::HeapObjectsSet() | 736 HeapObjectsSet::HeapObjectsSet() |
| 738 : entries_(HashMap::PointersMatch) { | 737 : entries_(HashMap::PointersMatch) { |
| 739 } | 738 } |
| 740 | 739 |
| 741 | 740 |
| 742 void HeapObjectsSet::Clear() { | 741 void HeapObjectsSet::Clear() { |
| 743 entries_.Clear(); | 742 entries_.Clear(); |
| 744 } | 743 } |
| 745 | 744 |
| 746 | 745 |
| 747 bool HeapObjectsSet::Contains(Object* obj) { | 746 bool HeapObjectsSet::Contains(Object* obj) { |
| 748 if (!obj->IsHeapObject()) return false; | 747 if (!obj->IsHeapObject()) return false; |
| 749 HeapObject* object = HeapObject::cast(obj); | 748 HeapObject* object = HeapObject::cast(obj); |
| 750 return entries_.Lookup(object, HeapEntriesMap::Hash(object), false) != NULL; | 749 return entries_.Lookup(object, HeapEntriesMap::Hash(object)) != NULL; |
| 751 } | 750 } |
| 752 | 751 |
| 753 | 752 |
| 754 void HeapObjectsSet::Insert(Object* obj) { | 753 void HeapObjectsSet::Insert(Object* obj) { |
| 755 if (!obj->IsHeapObject()) return; | 754 if (!obj->IsHeapObject()) return; |
| 756 HeapObject* object = HeapObject::cast(obj); | 755 HeapObject* object = HeapObject::cast(obj); |
| 757 entries_.Lookup(object, HeapEntriesMap::Hash(object), true); | 756 entries_.LookupOrInsert(object, HeapEntriesMap::Hash(object)); |
| 758 } | 757 } |
| 759 | 758 |
| 760 | 759 |
| 761 const char* HeapObjectsSet::GetTag(Object* obj) { | 760 const char* HeapObjectsSet::GetTag(Object* obj) { |
| 762 HeapObject* object = HeapObject::cast(obj); | 761 HeapObject* object = HeapObject::cast(obj); |
| 763 HashMap::Entry* cache_entry = | 762 HashMap::Entry* cache_entry = |
| 764 entries_.Lookup(object, HeapEntriesMap::Hash(object), false); | 763 entries_.Lookup(object, HeapEntriesMap::Hash(object)); |
| 765 return cache_entry != NULL | 764 return cache_entry != NULL |
| 766 ? reinterpret_cast<const char*>(cache_entry->value) | 765 ? reinterpret_cast<const char*>(cache_entry->value) |
| 767 : NULL; | 766 : NULL; |
| 768 } | 767 } |
| 769 | 768 |
| 770 | 769 |
| 771 void HeapObjectsSet::SetTag(Object* obj, const char* tag) { | 770 void HeapObjectsSet::SetTag(Object* obj, const char* tag) { |
| 772 if (!obj->IsHeapObject()) return; | 771 if (!obj->IsHeapObject()) return; |
| 773 HeapObject* object = HeapObject::cast(obj); | 772 HeapObject* object = HeapObject::cast(obj); |
| 774 HashMap::Entry* cache_entry = | 773 HashMap::Entry* cache_entry = |
| 775 entries_.Lookup(object, HeapEntriesMap::Hash(object), true); | 774 entries_.LookupOrInsert(object, HeapEntriesMap::Hash(object)); |
| 776 cache_entry->value = const_cast<char*>(tag); | 775 cache_entry->value = const_cast<char*>(tag); |
| 777 } | 776 } |
| 778 | 777 |
| 779 | 778 |
| 780 V8HeapExplorer::V8HeapExplorer( | 779 V8HeapExplorer::V8HeapExplorer( |
| 781 HeapSnapshot* snapshot, | 780 HeapSnapshot* snapshot, |
| 782 SnapshottingProgressReportingInterface* progress, | 781 SnapshottingProgressReportingInterface* progress, |
| 783 v8::HeapProfiler::ObjectNameResolver* resolver) | 782 v8::HeapProfiler::ObjectNameResolver* resolver) |
| 784 : heap_(snapshot->profiler()->heap_object_map()->heap()), | 783 : heap_(snapshot->profiler()->heap_object_map()->heap()), |
| 785 snapshot_(snapshot), | 784 snapshot_(snapshot), |
| (...skipping 1597 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2383 parent_entry, | 2382 parent_entry, |
| 2384 "native", | 2383 "native", |
| 2385 child_entry); | 2384 child_entry); |
| 2386 } | 2385 } |
| 2387 } | 2386 } |
| 2388 isolate->global_handles()->RemoveImplicitRefGroups(); | 2387 isolate->global_handles()->RemoveImplicitRefGroups(); |
| 2389 } | 2388 } |
| 2390 | 2389 |
| 2391 List<HeapObject*>* NativeObjectsExplorer::GetListMaybeDisposeInfo( | 2390 List<HeapObject*>* NativeObjectsExplorer::GetListMaybeDisposeInfo( |
| 2392 v8::RetainedObjectInfo* info) { | 2391 v8::RetainedObjectInfo* info) { |
| 2393 HashMap::Entry* entry = | 2392 HashMap::Entry* entry = objects_by_info_.LookupOrInsert(info, InfoHash(info)); |
| 2394 objects_by_info_.Lookup(info, InfoHash(info), true); | |
| 2395 if (entry->value != NULL) { | 2393 if (entry->value != NULL) { |
| 2396 info->Dispose(); | 2394 info->Dispose(); |
| 2397 } else { | 2395 } else { |
| 2398 entry->value = new List<HeapObject*>(4); | 2396 entry->value = new List<HeapObject*>(4); |
| 2399 } | 2397 } |
| 2400 return reinterpret_cast<List<HeapObject*>* >(entry->value); | 2398 return reinterpret_cast<List<HeapObject*>* >(entry->value); |
| 2401 } | 2399 } |
| 2402 | 2400 |
| 2403 | 2401 |
| 2404 bool NativeObjectsExplorer::IterateAndExtractReferences( | 2402 bool NativeObjectsExplorer::IterateAndExtractReferences( |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2453 }; | 2451 }; |
| 2454 | 2452 |
| 2455 | 2453 |
| 2456 NativeGroupRetainedObjectInfo* NativeObjectsExplorer::FindOrAddGroupInfo( | 2454 NativeGroupRetainedObjectInfo* NativeObjectsExplorer::FindOrAddGroupInfo( |
| 2457 const char* label) { | 2455 const char* label) { |
| 2458 const char* label_copy = names_->GetCopy(label); | 2456 const char* label_copy = names_->GetCopy(label); |
| 2459 uint32_t hash = StringHasher::HashSequentialString( | 2457 uint32_t hash = StringHasher::HashSequentialString( |
| 2460 label_copy, | 2458 label_copy, |
| 2461 static_cast<int>(strlen(label_copy)), | 2459 static_cast<int>(strlen(label_copy)), |
| 2462 isolate_->heap()->HashSeed()); | 2460 isolate_->heap()->HashSeed()); |
| 2463 HashMap::Entry* entry = native_groups_.Lookup(const_cast<char*>(label_copy), | 2461 HashMap::Entry* entry = |
| 2464 hash, true); | 2462 native_groups_.LookupOrInsert(const_cast<char*>(label_copy), hash); |
| 2465 if (entry->value == NULL) { | 2463 if (entry->value == NULL) { |
| 2466 entry->value = new NativeGroupRetainedObjectInfo(label); | 2464 entry->value = new NativeGroupRetainedObjectInfo(label); |
| 2467 } | 2465 } |
| 2468 return static_cast<NativeGroupRetainedObjectInfo*>(entry->value); | 2466 return static_cast<NativeGroupRetainedObjectInfo*>(entry->value); |
| 2469 } | 2467 } |
| 2470 | 2468 |
| 2471 | 2469 |
| 2472 void NativeObjectsExplorer::SetNativeRootReference( | 2470 void NativeObjectsExplorer::SetNativeRootReference( |
| 2473 v8::RetainedObjectInfo* info) { | 2471 v8::RetainedObjectInfo* info) { |
| 2474 HeapEntry* child_entry = | 2472 HeapEntry* child_entry = |
| (...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2765 writer_->AddString("\"strings\":["); | 2763 writer_->AddString("\"strings\":["); |
| 2766 SerializeStrings(); | 2764 SerializeStrings(); |
| 2767 if (writer_->aborted()) return; | 2765 if (writer_->aborted()) return; |
| 2768 writer_->AddCharacter(']'); | 2766 writer_->AddCharacter(']'); |
| 2769 writer_->AddCharacter('}'); | 2767 writer_->AddCharacter('}'); |
| 2770 writer_->Finalize(); | 2768 writer_->Finalize(); |
| 2771 } | 2769 } |
| 2772 | 2770 |
| 2773 | 2771 |
| 2774 int HeapSnapshotJSONSerializer::GetStringId(const char* s) { | 2772 int HeapSnapshotJSONSerializer::GetStringId(const char* s) { |
| 2775 HashMap::Entry* cache_entry = strings_.Lookup( | 2773 HashMap::Entry* cache_entry = |
| 2776 const_cast<char*>(s), StringHash(s), true); | 2774 strings_.LookupOrInsert(const_cast<char*>(s), StringHash(s)); |
| 2777 if (cache_entry->value == NULL) { | 2775 if (cache_entry->value == NULL) { |
| 2778 cache_entry->value = reinterpret_cast<void*>(next_string_id_++); | 2776 cache_entry->value = reinterpret_cast<void*>(next_string_id_++); |
| 2779 } | 2777 } |
| 2780 return static_cast<int>(reinterpret_cast<intptr_t>(cache_entry->value)); | 2778 return static_cast<int>(reinterpret_cast<intptr_t>(cache_entry->value)); |
| 2781 } | 2779 } |
| 2782 | 2780 |
| 2783 | 2781 |
| 2784 namespace { | 2782 namespace { |
| 2785 | 2783 |
| 2786 template<size_t size> struct ToUnsigned; | 2784 template<size_t size> struct ToUnsigned; |
| (...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3166 writer_->AddString("\"<dummy>\""); | 3164 writer_->AddString("\"<dummy>\""); |
| 3167 for (int i = 1; i < sorted_strings.length(); ++i) { | 3165 for (int i = 1; i < sorted_strings.length(); ++i) { |
| 3168 writer_->AddCharacter(','); | 3166 writer_->AddCharacter(','); |
| 3169 SerializeString(sorted_strings[i]); | 3167 SerializeString(sorted_strings[i]); |
| 3170 if (writer_->aborted()) return; | 3168 if (writer_->aborted()) return; |
| 3171 } | 3169 } |
| 3172 } | 3170 } |
| 3173 | 3171 |
| 3174 | 3172 |
| 3175 } } // namespace v8::internal | 3173 } } // namespace v8::internal |
| OLD | NEW |