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 |