| 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/profiler/heap-snapshot-generator.h" | 5 #include "src/profiler/heap-snapshot-generator.h" |
| 6 | 6 |
| 7 #include "src/code-stubs.h" | 7 #include "src/code-stubs.h" |
| 8 #include "src/conversions.h" | 8 #include "src/conversions.h" |
| 9 #include "src/debug/debug.h" | 9 #include "src/debug/debug.h" |
| 10 #include "src/objects-body-descriptors.h" | 10 #include "src/objects-body-descriptors.h" |
| (...skipping 374 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 385 // It may occur that some untracked object moves to an address X and there | 385 // It may occur that some untracked object moves to an address X and there |
| 386 // is a tracked object at that address. In this case we should remove the | 386 // is a tracked object at that address. In this case we should remove the |
| 387 // entry as we know that the object has died. | 387 // entry as we know that the object has died. |
| 388 void* to_value = entries_map_.Remove(to, ComputePointerHash(to)); | 388 void* to_value = entries_map_.Remove(to, ComputePointerHash(to)); |
| 389 if (to_value != NULL) { | 389 if (to_value != NULL) { |
| 390 int to_entry_info_index = | 390 int to_entry_info_index = |
| 391 static_cast<int>(reinterpret_cast<intptr_t>(to_value)); | 391 static_cast<int>(reinterpret_cast<intptr_t>(to_value)); |
| 392 entries_.at(to_entry_info_index).addr = NULL; | 392 entries_.at(to_entry_info_index).addr = NULL; |
| 393 } | 393 } |
| 394 } else { | 394 } else { |
| 395 HashMap::Entry* to_entry = | 395 base::HashMap::Entry* to_entry = |
| 396 entries_map_.LookupOrInsert(to, ComputePointerHash(to)); | 396 entries_map_.LookupOrInsert(to, ComputePointerHash(to)); |
| 397 if (to_entry->value != NULL) { | 397 if (to_entry->value != NULL) { |
| 398 // We found the existing entry with to address for an old object. | 398 // We found the existing entry with to address for an old object. |
| 399 // Without this operation we will have two EntryInfo's with the same | 399 // Without this operation we will have two EntryInfo's with the same |
| 400 // value in addr field. It is bad because later at RemoveDeadEntries | 400 // value in addr field. It is bad because later at RemoveDeadEntries |
| 401 // one of this entry will be removed with the corresponding entries_map_ | 401 // one of this entry will be removed with the corresponding entries_map_ |
| 402 // entry. | 402 // entry. |
| 403 int to_entry_info_index = | 403 int to_entry_info_index = |
| 404 static_cast<int>(reinterpret_cast<intptr_t>(to_entry->value)); | 404 static_cast<int>(reinterpret_cast<intptr_t>(to_entry->value)); |
| 405 entries_.at(to_entry_info_index).addr = NULL; | 405 entries_.at(to_entry_info_index).addr = NULL; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 421 return from_value != NULL; | 421 return from_value != NULL; |
| 422 } | 422 } |
| 423 | 423 |
| 424 | 424 |
| 425 void HeapObjectsMap::UpdateObjectSize(Address addr, int size) { | 425 void HeapObjectsMap::UpdateObjectSize(Address addr, int size) { |
| 426 FindOrAddEntry(addr, size, false); | 426 FindOrAddEntry(addr, size, false); |
| 427 } | 427 } |
| 428 | 428 |
| 429 | 429 |
| 430 SnapshotObjectId HeapObjectsMap::FindEntry(Address addr) { | 430 SnapshotObjectId HeapObjectsMap::FindEntry(Address addr) { |
| 431 HashMap::Entry* entry = entries_map_.Lookup(addr, ComputePointerHash(addr)); | 431 base::HashMap::Entry* entry = |
| 432 entries_map_.Lookup(addr, ComputePointerHash(addr)); |
| 432 if (entry == NULL) return 0; | 433 if (entry == NULL) return 0; |
| 433 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)); |
| 434 EntryInfo& entry_info = entries_.at(entry_index); | 435 EntryInfo& entry_info = entries_.at(entry_index); |
| 435 DCHECK(static_cast<uint32_t>(entries_.length()) > entries_map_.occupancy()); | 436 DCHECK(static_cast<uint32_t>(entries_.length()) > entries_map_.occupancy()); |
| 436 return entry_info.id; | 437 return entry_info.id; |
| 437 } | 438 } |
| 438 | 439 |
| 439 | 440 |
| 440 SnapshotObjectId HeapObjectsMap::FindOrAddEntry(Address addr, | 441 SnapshotObjectId HeapObjectsMap::FindOrAddEntry(Address addr, |
| 441 unsigned int size, | 442 unsigned int size, |
| 442 bool accessed) { | 443 bool accessed) { |
| 443 DCHECK(static_cast<uint32_t>(entries_.length()) > entries_map_.occupancy()); | 444 DCHECK(static_cast<uint32_t>(entries_.length()) > entries_map_.occupancy()); |
| 444 HashMap::Entry* entry = | 445 base::HashMap::Entry* entry = |
| 445 entries_map_.LookupOrInsert(addr, ComputePointerHash(addr)); | 446 entries_map_.LookupOrInsert(addr, ComputePointerHash(addr)); |
| 446 if (entry->value != NULL) { | 447 if (entry->value != NULL) { |
| 447 int entry_index = | 448 int entry_index = |
| 448 static_cast<int>(reinterpret_cast<intptr_t>(entry->value)); | 449 static_cast<int>(reinterpret_cast<intptr_t>(entry->value)); |
| 449 EntryInfo& entry_info = entries_.at(entry_index); | 450 EntryInfo& entry_info = entries_.at(entry_index); |
| 450 entry_info.accessed = accessed; | 451 entry_info.accessed = accessed; |
| 451 if (FLAG_heap_profiler_trace_objects) { | 452 if (FLAG_heap_profiler_trace_objects) { |
| 452 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", |
| 453 static_cast<void*>(addr), entry_info.size, size); | 454 static_cast<void*>(addr), entry_info.size, size); |
| 454 } | 455 } |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 538 | 539 |
| 539 | 540 |
| 540 int HeapObjectsMap::FindUntrackedObjects() { | 541 int HeapObjectsMap::FindUntrackedObjects() { |
| 541 List<HeapObjectInfo> heap_objects(1000); | 542 List<HeapObjectInfo> heap_objects(1000); |
| 542 | 543 |
| 543 HeapIterator iterator(heap_); | 544 HeapIterator iterator(heap_); |
| 544 int untracked = 0; | 545 int untracked = 0; |
| 545 for (HeapObject* obj = iterator.next(); | 546 for (HeapObject* obj = iterator.next(); |
| 546 obj != NULL; | 547 obj != NULL; |
| 547 obj = iterator.next()) { | 548 obj = iterator.next()) { |
| 548 HashMap::Entry* entry = | 549 base::HashMap::Entry* entry = |
| 549 entries_map_.Lookup(obj->address(), ComputePointerHash(obj->address())); | 550 entries_map_.Lookup(obj->address(), ComputePointerHash(obj->address())); |
| 550 if (entry == NULL) { | 551 if (entry == NULL) { |
| 551 ++untracked; | 552 ++untracked; |
| 552 if (FLAG_heap_profiler_trace_objects) { | 553 if (FLAG_heap_profiler_trace_objects) { |
| 553 heap_objects.Add(HeapObjectInfo(obj, 0)); | 554 heap_objects.Add(HeapObjectInfo(obj, 0)); |
| 554 } | 555 } |
| 555 } else { | 556 } else { |
| 556 int entry_index = static_cast<int>( | 557 int entry_index = static_cast<int>( |
| 557 reinterpret_cast<intptr_t>(entry->value)); | 558 reinterpret_cast<intptr_t>(entry->value)); |
| 558 EntryInfo& entry_info = entries_.at(entry_index); | 559 EntryInfo& entry_info = entries_.at(entry_index); |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 658 entries_.at(0).id == 0 && | 659 entries_.at(0).id == 0 && |
| 659 entries_.at(0).addr == NULL); | 660 entries_.at(0).addr == NULL); |
| 660 int first_free_entry = 1; | 661 int first_free_entry = 1; |
| 661 for (int i = 1; i < entries_.length(); ++i) { | 662 for (int i = 1; i < entries_.length(); ++i) { |
| 662 EntryInfo& entry_info = entries_.at(i); | 663 EntryInfo& entry_info = entries_.at(i); |
| 663 if (entry_info.accessed) { | 664 if (entry_info.accessed) { |
| 664 if (first_free_entry != i) { | 665 if (first_free_entry != i) { |
| 665 entries_.at(first_free_entry) = entry_info; | 666 entries_.at(first_free_entry) = entry_info; |
| 666 } | 667 } |
| 667 entries_.at(first_free_entry).accessed = false; | 668 entries_.at(first_free_entry).accessed = false; |
| 668 HashMap::Entry* entry = entries_map_.Lookup( | 669 base::HashMap::Entry* entry = entries_map_.Lookup( |
| 669 entry_info.addr, ComputePointerHash(entry_info.addr)); | 670 entry_info.addr, ComputePointerHash(entry_info.addr)); |
| 670 DCHECK(entry); | 671 DCHECK(entry); |
| 671 entry->value = reinterpret_cast<void*>(first_free_entry); | 672 entry->value = reinterpret_cast<void*>(first_free_entry); |
| 672 ++first_free_entry; | 673 ++first_free_entry; |
| 673 } else { | 674 } else { |
| 674 if (entry_info.addr) { | 675 if (entry_info.addr) { |
| 675 entries_map_.Remove(entry_info.addr, | 676 entries_map_.Remove(entry_info.addr, |
| 676 ComputePointerHash(entry_info.addr)); | 677 ComputePointerHash(entry_info.addr)); |
| 677 } | 678 } |
| 678 } | 679 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 691 heap_->HashSeed()); | 692 heap_->HashSeed()); |
| 692 intptr_t element_count = info->GetElementCount(); | 693 intptr_t element_count = info->GetElementCount(); |
| 693 if (element_count != -1) | 694 if (element_count != -1) |
| 694 id ^= ComputeIntegerHash(static_cast<uint32_t>(element_count), | 695 id ^= ComputeIntegerHash(static_cast<uint32_t>(element_count), |
| 695 v8::internal::kZeroHashSeed); | 696 v8::internal::kZeroHashSeed); |
| 696 return id << 1; | 697 return id << 1; |
| 697 } | 698 } |
| 698 | 699 |
| 699 | 700 |
| 700 size_t HeapObjectsMap::GetUsedMemorySize() const { | 701 size_t HeapObjectsMap::GetUsedMemorySize() const { |
| 701 return | 702 return sizeof(*this) + |
| 702 sizeof(*this) + | 703 sizeof(base::HashMap::Entry) * entries_map_.capacity() + |
| 703 sizeof(HashMap::Entry) * entries_map_.capacity() + | 704 GetMemoryUsedByList(entries_) + GetMemoryUsedByList(time_intervals_); |
| 704 GetMemoryUsedByList(entries_) + | |
| 705 GetMemoryUsedByList(time_intervals_); | |
| 706 } | 705 } |
| 707 | 706 |
| 708 | 707 HeapEntriesMap::HeapEntriesMap() : entries_(base::HashMap::PointersMatch) {} |
| 709 HeapEntriesMap::HeapEntriesMap() | |
| 710 : entries_(HashMap::PointersMatch) { | |
| 711 } | |
| 712 | |
| 713 | 708 |
| 714 int HeapEntriesMap::Map(HeapThing thing) { | 709 int HeapEntriesMap::Map(HeapThing thing) { |
| 715 HashMap::Entry* cache_entry = entries_.Lookup(thing, Hash(thing)); | 710 base::HashMap::Entry* cache_entry = entries_.Lookup(thing, Hash(thing)); |
| 716 if (cache_entry == NULL) return HeapEntry::kNoEntry; | 711 if (cache_entry == NULL) return HeapEntry::kNoEntry; |
| 717 return static_cast<int>(reinterpret_cast<intptr_t>(cache_entry->value)); | 712 return static_cast<int>(reinterpret_cast<intptr_t>(cache_entry->value)); |
| 718 } | 713 } |
| 719 | 714 |
| 720 | 715 |
| 721 void HeapEntriesMap::Pair(HeapThing thing, int entry) { | 716 void HeapEntriesMap::Pair(HeapThing thing, int entry) { |
| 722 HashMap::Entry* cache_entry = entries_.LookupOrInsert(thing, Hash(thing)); | 717 base::HashMap::Entry* cache_entry = |
| 718 entries_.LookupOrInsert(thing, Hash(thing)); |
| 723 DCHECK(cache_entry->value == NULL); | 719 DCHECK(cache_entry->value == NULL); |
| 724 cache_entry->value = reinterpret_cast<void*>(static_cast<intptr_t>(entry)); | 720 cache_entry->value = reinterpret_cast<void*>(static_cast<intptr_t>(entry)); |
| 725 } | 721 } |
| 726 | 722 |
| 727 | 723 HeapObjectsSet::HeapObjectsSet() : entries_(base::HashMap::PointersMatch) {} |
| 728 HeapObjectsSet::HeapObjectsSet() | |
| 729 : entries_(HashMap::PointersMatch) { | |
| 730 } | |
| 731 | |
| 732 | 724 |
| 733 void HeapObjectsSet::Clear() { | 725 void HeapObjectsSet::Clear() { |
| 734 entries_.Clear(); | 726 entries_.Clear(); |
| 735 } | 727 } |
| 736 | 728 |
| 737 | 729 |
| 738 bool HeapObjectsSet::Contains(Object* obj) { | 730 bool HeapObjectsSet::Contains(Object* obj) { |
| 739 if (!obj->IsHeapObject()) return false; | 731 if (!obj->IsHeapObject()) return false; |
| 740 HeapObject* object = HeapObject::cast(obj); | 732 HeapObject* object = HeapObject::cast(obj); |
| 741 return entries_.Lookup(object, HeapEntriesMap::Hash(object)) != NULL; | 733 return entries_.Lookup(object, HeapEntriesMap::Hash(object)) != NULL; |
| 742 } | 734 } |
| 743 | 735 |
| 744 | 736 |
| 745 void HeapObjectsSet::Insert(Object* obj) { | 737 void HeapObjectsSet::Insert(Object* obj) { |
| 746 if (!obj->IsHeapObject()) return; | 738 if (!obj->IsHeapObject()) return; |
| 747 HeapObject* object = HeapObject::cast(obj); | 739 HeapObject* object = HeapObject::cast(obj); |
| 748 entries_.LookupOrInsert(object, HeapEntriesMap::Hash(object)); | 740 entries_.LookupOrInsert(object, HeapEntriesMap::Hash(object)); |
| 749 } | 741 } |
| 750 | 742 |
| 751 | 743 |
| 752 const char* HeapObjectsSet::GetTag(Object* obj) { | 744 const char* HeapObjectsSet::GetTag(Object* obj) { |
| 753 HeapObject* object = HeapObject::cast(obj); | 745 HeapObject* object = HeapObject::cast(obj); |
| 754 HashMap::Entry* cache_entry = | 746 base::HashMap::Entry* cache_entry = |
| 755 entries_.Lookup(object, HeapEntriesMap::Hash(object)); | 747 entries_.Lookup(object, HeapEntriesMap::Hash(object)); |
| 756 return cache_entry != NULL | 748 return cache_entry != NULL |
| 757 ? reinterpret_cast<const char*>(cache_entry->value) | 749 ? reinterpret_cast<const char*>(cache_entry->value) |
| 758 : NULL; | 750 : NULL; |
| 759 } | 751 } |
| 760 | 752 |
| 761 | 753 |
| 762 void HeapObjectsSet::SetTag(Object* obj, const char* tag) { | 754 void HeapObjectsSet::SetTag(Object* obj, const char* tag) { |
| 763 if (!obj->IsHeapObject()) return; | 755 if (!obj->IsHeapObject()) return; |
| 764 HeapObject* object = HeapObject::cast(obj); | 756 HeapObject* object = HeapObject::cast(obj); |
| 765 HashMap::Entry* cache_entry = | 757 base::HashMap::Entry* cache_entry = |
| 766 entries_.LookupOrInsert(object, HeapEntriesMap::Hash(object)); | 758 entries_.LookupOrInsert(object, HeapEntriesMap::Hash(object)); |
| 767 cache_entry->value = const_cast<char*>(tag); | 759 cache_entry->value = const_cast<char*>(tag); |
| 768 } | 760 } |
| 769 | 761 |
| 770 | 762 |
| 771 V8HeapExplorer::V8HeapExplorer( | 763 V8HeapExplorer::V8HeapExplorer( |
| 772 HeapSnapshot* snapshot, | 764 HeapSnapshot* snapshot, |
| 773 SnapshottingProgressReportingInterface* progress, | 765 SnapshottingProgressReportingInterface* progress, |
| 774 v8::HeapProfiler::ObjectNameResolver* resolver) | 766 v8::HeapProfiler::ObjectNameResolver* resolver) |
| 775 : heap_(snapshot->profiler()->heap_object_map()->heap()), | 767 : heap_(snapshot->profiler()->heap_object_map()->heap()), |
| (...skipping 1471 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2247 native_groups_(StringsMatch), | 2239 native_groups_(StringsMatch), |
| 2248 filler_(NULL) { | 2240 filler_(NULL) { |
| 2249 synthetic_entries_allocator_ = | 2241 synthetic_entries_allocator_ = |
| 2250 new BasicHeapEntriesAllocator(snapshot, HeapEntry::kSynthetic); | 2242 new BasicHeapEntriesAllocator(snapshot, HeapEntry::kSynthetic); |
| 2251 native_entries_allocator_ = | 2243 native_entries_allocator_ = |
| 2252 new BasicHeapEntriesAllocator(snapshot, HeapEntry::kNative); | 2244 new BasicHeapEntriesAllocator(snapshot, HeapEntry::kNative); |
| 2253 } | 2245 } |
| 2254 | 2246 |
| 2255 | 2247 |
| 2256 NativeObjectsExplorer::~NativeObjectsExplorer() { | 2248 NativeObjectsExplorer::~NativeObjectsExplorer() { |
| 2257 for (HashMap::Entry* p = objects_by_info_.Start(); | 2249 for (base::HashMap::Entry* p = objects_by_info_.Start(); p != NULL; |
| 2258 p != NULL; | |
| 2259 p = objects_by_info_.Next(p)) { | 2250 p = objects_by_info_.Next(p)) { |
| 2260 v8::RetainedObjectInfo* info = | 2251 v8::RetainedObjectInfo* info = |
| 2261 reinterpret_cast<v8::RetainedObjectInfo*>(p->key); | 2252 reinterpret_cast<v8::RetainedObjectInfo*>(p->key); |
| 2262 info->Dispose(); | 2253 info->Dispose(); |
| 2263 List<HeapObject*>* objects = | 2254 List<HeapObject*>* objects = |
| 2264 reinterpret_cast<List<HeapObject*>* >(p->value); | 2255 reinterpret_cast<List<HeapObject*>* >(p->value); |
| 2265 delete objects; | 2256 delete objects; |
| 2266 } | 2257 } |
| 2267 for (HashMap::Entry* p = native_groups_.Start(); | 2258 for (base::HashMap::Entry* p = native_groups_.Start(); p != NULL; |
| 2268 p != NULL; | |
| 2269 p = native_groups_.Next(p)) { | 2259 p = native_groups_.Next(p)) { |
| 2270 v8::RetainedObjectInfo* info = | 2260 v8::RetainedObjectInfo* info = |
| 2271 reinterpret_cast<v8::RetainedObjectInfo*>(p->value); | 2261 reinterpret_cast<v8::RetainedObjectInfo*>(p->value); |
| 2272 info->Dispose(); | 2262 info->Dispose(); |
| 2273 } | 2263 } |
| 2274 delete synthetic_entries_allocator_; | 2264 delete synthetic_entries_allocator_; |
| 2275 delete native_entries_allocator_; | 2265 delete native_entries_allocator_; |
| 2276 } | 2266 } |
| 2277 | 2267 |
| 2278 | 2268 |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2330 parent_entry, | 2320 parent_entry, |
| 2331 "native", | 2321 "native", |
| 2332 child_entry); | 2322 child_entry); |
| 2333 } | 2323 } |
| 2334 } | 2324 } |
| 2335 isolate->global_handles()->RemoveImplicitRefGroups(); | 2325 isolate->global_handles()->RemoveImplicitRefGroups(); |
| 2336 } | 2326 } |
| 2337 | 2327 |
| 2338 List<HeapObject*>* NativeObjectsExplorer::GetListMaybeDisposeInfo( | 2328 List<HeapObject*>* NativeObjectsExplorer::GetListMaybeDisposeInfo( |
| 2339 v8::RetainedObjectInfo* info) { | 2329 v8::RetainedObjectInfo* info) { |
| 2340 HashMap::Entry* entry = objects_by_info_.LookupOrInsert(info, InfoHash(info)); | 2330 base::HashMap::Entry* entry = |
| 2331 objects_by_info_.LookupOrInsert(info, InfoHash(info)); |
| 2341 if (entry->value != NULL) { | 2332 if (entry->value != NULL) { |
| 2342 info->Dispose(); | 2333 info->Dispose(); |
| 2343 } else { | 2334 } else { |
| 2344 entry->value = new List<HeapObject*>(4); | 2335 entry->value = new List<HeapObject*>(4); |
| 2345 } | 2336 } |
| 2346 return reinterpret_cast<List<HeapObject*>* >(entry->value); | 2337 return reinterpret_cast<List<HeapObject*>* >(entry->value); |
| 2347 } | 2338 } |
| 2348 | 2339 |
| 2349 | 2340 |
| 2350 bool NativeObjectsExplorer::IterateAndExtractReferences( | 2341 bool NativeObjectsExplorer::IterateAndExtractReferences( |
| 2351 SnapshotFiller* filler) { | 2342 SnapshotFiller* filler) { |
| 2352 filler_ = filler; | 2343 filler_ = filler; |
| 2353 FillRetainedObjects(); | 2344 FillRetainedObjects(); |
| 2354 FillImplicitReferences(); | 2345 FillImplicitReferences(); |
| 2355 if (EstimateObjectsCount() > 0) { | 2346 if (EstimateObjectsCount() > 0) { |
| 2356 for (HashMap::Entry* p = objects_by_info_.Start(); | 2347 for (base::HashMap::Entry* p = objects_by_info_.Start(); p != NULL; |
| 2357 p != NULL; | |
| 2358 p = objects_by_info_.Next(p)) { | 2348 p = objects_by_info_.Next(p)) { |
| 2359 v8::RetainedObjectInfo* info = | 2349 v8::RetainedObjectInfo* info = |
| 2360 reinterpret_cast<v8::RetainedObjectInfo*>(p->key); | 2350 reinterpret_cast<v8::RetainedObjectInfo*>(p->key); |
| 2361 SetNativeRootReference(info); | 2351 SetNativeRootReference(info); |
| 2362 List<HeapObject*>* objects = | 2352 List<HeapObject*>* objects = |
| 2363 reinterpret_cast<List<HeapObject*>* >(p->value); | 2353 reinterpret_cast<List<HeapObject*>* >(p->value); |
| 2364 for (int i = 0; i < objects->length(); ++i) { | 2354 for (int i = 0; i < objects->length(); ++i) { |
| 2365 SetWrapperNativeReferences(objects->at(i), info); | 2355 SetWrapperNativeReferences(objects->at(i), info); |
| 2366 } | 2356 } |
| 2367 } | 2357 } |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2399 }; | 2389 }; |
| 2400 | 2390 |
| 2401 | 2391 |
| 2402 NativeGroupRetainedObjectInfo* NativeObjectsExplorer::FindOrAddGroupInfo( | 2392 NativeGroupRetainedObjectInfo* NativeObjectsExplorer::FindOrAddGroupInfo( |
| 2403 const char* label) { | 2393 const char* label) { |
| 2404 const char* label_copy = names_->GetCopy(label); | 2394 const char* label_copy = names_->GetCopy(label); |
| 2405 uint32_t hash = StringHasher::HashSequentialString( | 2395 uint32_t hash = StringHasher::HashSequentialString( |
| 2406 label_copy, | 2396 label_copy, |
| 2407 static_cast<int>(strlen(label_copy)), | 2397 static_cast<int>(strlen(label_copy)), |
| 2408 isolate_->heap()->HashSeed()); | 2398 isolate_->heap()->HashSeed()); |
| 2409 HashMap::Entry* entry = | 2399 base::HashMap::Entry* entry = |
| 2410 native_groups_.LookupOrInsert(const_cast<char*>(label_copy), hash); | 2400 native_groups_.LookupOrInsert(const_cast<char*>(label_copy), hash); |
| 2411 if (entry->value == NULL) { | 2401 if (entry->value == NULL) { |
| 2412 entry->value = new NativeGroupRetainedObjectInfo(label); | 2402 entry->value = new NativeGroupRetainedObjectInfo(label); |
| 2413 } | 2403 } |
| 2414 return static_cast<NativeGroupRetainedObjectInfo*>(entry->value); | 2404 return static_cast<NativeGroupRetainedObjectInfo*>(entry->value); |
| 2415 } | 2405 } |
| 2416 | 2406 |
| 2417 | 2407 |
| 2418 void NativeObjectsExplorer::SetNativeRootReference( | 2408 void NativeObjectsExplorer::SetNativeRootReference( |
| 2419 v8::RetainedObjectInfo* info) { | 2409 v8::RetainedObjectInfo* info) { |
| (...skipping 25 matching lines...) Expand all Loading... |
| 2445 wrapper_entry->index(), | 2435 wrapper_entry->index(), |
| 2446 "native", | 2436 "native", |
| 2447 info_entry); | 2437 info_entry); |
| 2448 filler_->SetIndexedAutoIndexReference(HeapGraphEdge::kElement, | 2438 filler_->SetIndexedAutoIndexReference(HeapGraphEdge::kElement, |
| 2449 info_entry->index(), | 2439 info_entry->index(), |
| 2450 wrapper_entry); | 2440 wrapper_entry); |
| 2451 } | 2441 } |
| 2452 | 2442 |
| 2453 | 2443 |
| 2454 void NativeObjectsExplorer::SetRootNativeRootsReference() { | 2444 void NativeObjectsExplorer::SetRootNativeRootsReference() { |
| 2455 for (HashMap::Entry* entry = native_groups_.Start(); | 2445 for (base::HashMap::Entry* entry = native_groups_.Start(); entry; |
| 2456 entry; | |
| 2457 entry = native_groups_.Next(entry)) { | 2446 entry = native_groups_.Next(entry)) { |
| 2458 NativeGroupRetainedObjectInfo* group_info = | 2447 NativeGroupRetainedObjectInfo* group_info = |
| 2459 static_cast<NativeGroupRetainedObjectInfo*>(entry->value); | 2448 static_cast<NativeGroupRetainedObjectInfo*>(entry->value); |
| 2460 HeapEntry* group_entry = | 2449 HeapEntry* group_entry = |
| 2461 filler_->FindOrAddEntry(group_info, native_entries_allocator_); | 2450 filler_->FindOrAddEntry(group_info, native_entries_allocator_); |
| 2462 DCHECK(group_entry != NULL); | 2451 DCHECK(group_entry != NULL); |
| 2463 filler_->SetIndexedAutoIndexReference( | 2452 filler_->SetIndexedAutoIndexReference( |
| 2464 HeapGraphEdge::kElement, | 2453 HeapGraphEdge::kElement, |
| 2465 snapshot_->root()->index(), | 2454 snapshot_->root()->index(), |
| 2466 group_entry); | 2455 group_entry); |
| (...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2714 writer_->AddString("\"strings\":["); | 2703 writer_->AddString("\"strings\":["); |
| 2715 SerializeStrings(); | 2704 SerializeStrings(); |
| 2716 if (writer_->aborted()) return; | 2705 if (writer_->aborted()) return; |
| 2717 writer_->AddCharacter(']'); | 2706 writer_->AddCharacter(']'); |
| 2718 writer_->AddCharacter('}'); | 2707 writer_->AddCharacter('}'); |
| 2719 writer_->Finalize(); | 2708 writer_->Finalize(); |
| 2720 } | 2709 } |
| 2721 | 2710 |
| 2722 | 2711 |
| 2723 int HeapSnapshotJSONSerializer::GetStringId(const char* s) { | 2712 int HeapSnapshotJSONSerializer::GetStringId(const char* s) { |
| 2724 HashMap::Entry* cache_entry = | 2713 base::HashMap::Entry* cache_entry = |
| 2725 strings_.LookupOrInsert(const_cast<char*>(s), StringHash(s)); | 2714 strings_.LookupOrInsert(const_cast<char*>(s), StringHash(s)); |
| 2726 if (cache_entry->value == NULL) { | 2715 if (cache_entry->value == NULL) { |
| 2727 cache_entry->value = reinterpret_cast<void*>(next_string_id_++); | 2716 cache_entry->value = reinterpret_cast<void*>(next_string_id_++); |
| 2728 } | 2717 } |
| 2729 return static_cast<int>(reinterpret_cast<intptr_t>(cache_entry->value)); | 2718 return static_cast<int>(reinterpret_cast<intptr_t>(cache_entry->value)); |
| 2730 } | 2719 } |
| 2731 | 2720 |
| 2732 | 2721 |
| 2733 namespace { | 2722 namespace { |
| 2734 | 2723 |
| (...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3099 } | 3088 } |
| 3100 } | 3089 } |
| 3101 } | 3090 } |
| 3102 writer_->AddCharacter('\"'); | 3091 writer_->AddCharacter('\"'); |
| 3103 } | 3092 } |
| 3104 | 3093 |
| 3105 | 3094 |
| 3106 void HeapSnapshotJSONSerializer::SerializeStrings() { | 3095 void HeapSnapshotJSONSerializer::SerializeStrings() { |
| 3107 ScopedVector<const unsigned char*> sorted_strings( | 3096 ScopedVector<const unsigned char*> sorted_strings( |
| 3108 strings_.occupancy() + 1); | 3097 strings_.occupancy() + 1); |
| 3109 for (HashMap::Entry* entry = strings_.Start(); | 3098 for (base::HashMap::Entry* entry = strings_.Start(); entry != NULL; |
| 3110 entry != NULL; | |
| 3111 entry = strings_.Next(entry)) { | 3099 entry = strings_.Next(entry)) { |
| 3112 int index = static_cast<int>(reinterpret_cast<uintptr_t>(entry->value)); | 3100 int index = static_cast<int>(reinterpret_cast<uintptr_t>(entry->value)); |
| 3113 sorted_strings[index] = reinterpret_cast<const unsigned char*>(entry->key); | 3101 sorted_strings[index] = reinterpret_cast<const unsigned char*>(entry->key); |
| 3114 } | 3102 } |
| 3115 writer_->AddString("\"<dummy>\""); | 3103 writer_->AddString("\"<dummy>\""); |
| 3116 for (int i = 1; i < sorted_strings.length(); ++i) { | 3104 for (int i = 1; i < sorted_strings.length(); ++i) { |
| 3117 writer_->AddCharacter(','); | 3105 writer_->AddCharacter(','); |
| 3118 SerializeString(sorted_strings[i]); | 3106 SerializeString(sorted_strings[i]); |
| 3119 if (writer_->aborted()) return; | 3107 if (writer_->aborted()) return; |
| 3120 } | 3108 } |
| 3121 } | 3109 } |
| 3122 | 3110 |
| 3123 | 3111 |
| 3124 } // namespace internal | 3112 } // namespace internal |
| 3125 } // namespace v8 | 3113 } // namespace v8 |
| OLD | NEW |