| 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 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 93 void HeapEntry::SetIndexedReference(HeapGraphEdge::Type type, | 93 void HeapEntry::SetIndexedReference(HeapGraphEdge::Type type, |
| 94 int index, | 94 int index, |
| 95 HeapEntry* entry) { | 95 HeapEntry* entry) { |
| 96 HeapGraphEdge edge(type, index, this->index(), entry->index()); | 96 HeapGraphEdge edge(type, index, this->index(), entry->index()); |
| 97 snapshot_->edges().Add(edge); | 97 snapshot_->edges().Add(edge); |
| 98 ++children_count_; | 98 ++children_count_; |
| 99 } | 99 } |
| 100 | 100 |
| 101 | 101 |
| 102 Handle<HeapObject> HeapEntry::GetHeapObject() { | 102 Handle<HeapObject> HeapEntry::GetHeapObject() { |
| 103 return snapshot_->collection()->FindHeapObjectById(id()); | 103 return snapshot_->profiler()->FindHeapObjectById(id()); |
| 104 } | 104 } |
| 105 | 105 |
| 106 | 106 |
| 107 void HeapEntry::Print( | 107 void HeapEntry::Print( |
| 108 const char* prefix, const char* edge_name, int max_depth, int indent) { | 108 const char* prefix, const char* edge_name, int max_depth, int indent) { |
| 109 STATIC_CHECK(sizeof(unsigned) == sizeof(id())); | 109 STATIC_CHECK(sizeof(unsigned) == sizeof(id())); |
| 110 OS::Print("%6d @%6u %*c %s%s: ", | 110 OS::Print("%6d @%6u %*c %s%s: ", |
| 111 self_size(), id(), indent, ' ', prefix, edge_name); | 111 self_size(), id(), indent, ' ', prefix, edge_name); |
| 112 if (type() != kString) { | 112 if (type() != kString) { |
| 113 OS::Print("%s %.40s\n", TypeAsString(), name_); | 113 OS::Print("%s %.40s\n", TypeAsString(), name_); |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 195 static const int kExpectedHeapEntrySize = 24; | 195 static const int kExpectedHeapEntrySize = 24; |
| 196 }; | 196 }; |
| 197 | 197 |
| 198 template <> struct SnapshotSizeConstants<8> { | 198 template <> struct SnapshotSizeConstants<8> { |
| 199 static const int kExpectedHeapGraphEdgeSize = 24; | 199 static const int kExpectedHeapGraphEdgeSize = 24; |
| 200 static const int kExpectedHeapEntrySize = 32; | 200 static const int kExpectedHeapEntrySize = 32; |
| 201 }; | 201 }; |
| 202 | 202 |
| 203 } // namespace | 203 } // namespace |
| 204 | 204 |
| 205 HeapSnapshot::HeapSnapshot(HeapSnapshotsCollection* collection, | 205 HeapSnapshot::HeapSnapshot(HeapProfiler* profiler, |
| 206 const char* title, | 206 const char* title, |
| 207 unsigned uid) | 207 unsigned uid) |
| 208 : collection_(collection), | 208 : profiler_(profiler), |
| 209 title_(title), | 209 title_(title), |
| 210 uid_(uid), | 210 uid_(uid), |
| 211 root_index_(HeapEntry::kNoEntry), | 211 root_index_(HeapEntry::kNoEntry), |
| 212 gc_roots_index_(HeapEntry::kNoEntry), | 212 gc_roots_index_(HeapEntry::kNoEntry), |
| 213 natives_root_index_(HeapEntry::kNoEntry), | 213 natives_root_index_(HeapEntry::kNoEntry), |
| 214 max_snapshot_js_object_id_(0) { | 214 max_snapshot_js_object_id_(0) { |
| 215 STATIC_CHECK( | 215 STATIC_CHECK( |
| 216 sizeof(HeapGraphEdge) == | 216 sizeof(HeapGraphEdge) == |
| 217 SnapshotSizeConstants<kPointerSize>::kExpectedHeapGraphEdgeSize); | 217 SnapshotSizeConstants<kPointerSize>::kExpectedHeapGraphEdgeSize); |
| 218 STATIC_CHECK( | 218 STATIC_CHECK( |
| 219 sizeof(HeapEntry) == | 219 sizeof(HeapEntry) == |
| 220 SnapshotSizeConstants<kPointerSize>::kExpectedHeapEntrySize); | 220 SnapshotSizeConstants<kPointerSize>::kExpectedHeapEntrySize); |
| 221 for (int i = 0; i < VisitorSynchronization::kNumberOfSyncTags; ++i) { | 221 for (int i = 0; i < VisitorSynchronization::kNumberOfSyncTags; ++i) { |
| 222 gc_subroot_indexes_[i] = HeapEntry::kNoEntry; | 222 gc_subroot_indexes_[i] = HeapEntry::kNoEntry; |
| 223 } | 223 } |
| 224 } | 224 } |
| 225 | 225 |
| 226 | 226 |
| 227 void HeapSnapshot::Delete() { | 227 void HeapSnapshot::Delete() { |
| 228 collection_->RemoveSnapshot(this); | 228 profiler_->RemoveSnapshot(this); |
| 229 delete this; | 229 delete this; |
| 230 } | 230 } |
| 231 | 231 |
| 232 | 232 |
| 233 void HeapSnapshot::RememberLastJSObjectId() { | 233 void HeapSnapshot::RememberLastJSObjectId() { |
| 234 max_snapshot_js_object_id_ = collection_->last_assigned_id(); | 234 max_snapshot_js_object_id_ = profiler_->heap_object_map()->last_assigned_id(); |
| 235 } | 235 } |
| 236 | 236 |
| 237 | 237 |
| 238 HeapEntry* HeapSnapshot::AddRootEntry() { | 238 HeapEntry* HeapSnapshot::AddRootEntry() { |
| 239 ASSERT(root_index_ == HeapEntry::kNoEntry); | 239 ASSERT(root_index_ == HeapEntry::kNoEntry); |
| 240 ASSERT(entries_.is_empty()); // Root entry must be the first one. | 240 ASSERT(entries_.is_empty()); // Root entry must be the first one. |
| 241 HeapEntry* entry = AddEntry(HeapEntry::kSynthetic, | 241 HeapEntry* entry = AddEntry(HeapEntry::kSynthetic, |
| 242 "", | 242 "", |
| 243 HeapObjectsMap::kInternalRootObjectId, | 243 HeapObjectsMap::kInternalRootObjectId, |
| 244 0); | 244 0); |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 339 } | 339 } |
| 340 return &sorted_entries_; | 340 return &sorted_entries_; |
| 341 } | 341 } |
| 342 | 342 |
| 343 | 343 |
| 344 void HeapSnapshot::Print(int max_depth) { | 344 void HeapSnapshot::Print(int max_depth) { |
| 345 root()->Print("", "", max_depth, 0); | 345 root()->Print("", "", max_depth, 0); |
| 346 } | 346 } |
| 347 | 347 |
| 348 | 348 |
| 349 template<typename T, class P> | |
| 350 static size_t GetMemoryUsedByList(const List<T, P>& list) { | |
| 351 return list.length() * sizeof(T) + sizeof(list); | |
| 352 } | |
| 353 | |
| 354 | |
| 355 size_t HeapSnapshot::RawSnapshotSize() const { | 349 size_t HeapSnapshot::RawSnapshotSize() const { |
| 356 return | 350 return |
| 357 sizeof(*this) + | 351 sizeof(*this) + |
| 358 GetMemoryUsedByList(entries_) + | 352 GetMemoryUsedByList(entries_) + |
| 359 GetMemoryUsedByList(edges_) + | 353 GetMemoryUsedByList(edges_) + |
| 360 GetMemoryUsedByList(children_) + | 354 GetMemoryUsedByList(children_) + |
| 361 GetMemoryUsedByList(sorted_entries_); | 355 GetMemoryUsedByList(sorted_entries_); |
| 362 } | 356 } |
| 363 | 357 |
| 364 | 358 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 387 // When we do lookup in HashMap we see no difference between two cases: | 381 // When we do lookup in HashMap we see no difference between two cases: |
| 388 // it has an entry with NULL as the value or it has created | 382 // it has an entry with NULL as the value or it has created |
| 389 // a new entry on the fly with NULL as the default value. | 383 // a new entry on the fly with NULL as the default value. |
| 390 // With such dummy element we have a guaranty that all entries_map_ entries | 384 // With such dummy element we have a guaranty that all entries_map_ entries |
| 391 // will have the value field grater than 0. | 385 // will have the value field grater than 0. |
| 392 // This fact is using in MoveObject method. | 386 // This fact is using in MoveObject method. |
| 393 entries_.Add(EntryInfo(0, NULL, 0)); | 387 entries_.Add(EntryInfo(0, NULL, 0)); |
| 394 } | 388 } |
| 395 | 389 |
| 396 | 390 |
| 397 void HeapObjectsMap::SnapshotGenerationFinished() { | |
| 398 RemoveDeadEntries(); | |
| 399 } | |
| 400 | |
| 401 | |
| 402 void HeapObjectsMap::MoveObject(Address from, Address to, int object_size) { | 391 void HeapObjectsMap::MoveObject(Address from, Address to, int object_size) { |
| 403 ASSERT(to != NULL); | 392 ASSERT(to != NULL); |
| 404 ASSERT(from != NULL); | 393 ASSERT(from != NULL); |
| 405 if (from == to) return; | 394 if (from == to) return; |
| 406 void* from_value = entries_map_.Remove(from, ComputePointerHash(from)); | 395 void* from_value = entries_map_.Remove(from, ComputePointerHash(from)); |
| 407 if (from_value == NULL) { | 396 if (from_value == NULL) { |
| 408 // It may occur that some untracked object moves to an address X and there | 397 // It may occur that some untracked object moves to an address X and there |
| 409 // is a tracked object at that address. In this case we should remove the | 398 // is a tracked object at that address. In this case we should remove the |
| 410 // entry as we know that the object has died. | 399 // entry as we know that the object has died. |
| 411 void* to_value = entries_map_.Remove(to, ComputePointerHash(to)); | 400 void* to_value = entries_map_.Remove(to, ComputePointerHash(to)); |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 495 time_intervals_.Clear(); | 484 time_intervals_.Clear(); |
| 496 } | 485 } |
| 497 | 486 |
| 498 | 487 |
| 499 void HeapObjectsMap::UpdateHeapObjectsMap() { | 488 void HeapObjectsMap::UpdateHeapObjectsMap() { |
| 500 if (FLAG_heap_profiler_trace_objects) { | 489 if (FLAG_heap_profiler_trace_objects) { |
| 501 PrintF("Begin HeapObjectsMap::UpdateHeapObjectsMap. map has %d entries.\n", | 490 PrintF("Begin HeapObjectsMap::UpdateHeapObjectsMap. map has %d entries.\n", |
| 502 entries_map_.occupancy()); | 491 entries_map_.occupancy()); |
| 503 } | 492 } |
| 504 heap_->CollectAllGarbage(Heap::kMakeHeapIterableMask, | 493 heap_->CollectAllGarbage(Heap::kMakeHeapIterableMask, |
| 505 "HeapSnapshotsCollection::UpdateHeapObjectsMap"); | 494 "HeapObjectsMap::UpdateHeapObjectsMap"); |
| 506 HeapIterator iterator(heap_); | 495 HeapIterator iterator(heap_); |
| 507 for (HeapObject* obj = iterator.next(); | 496 for (HeapObject* obj = iterator.next(); |
| 508 obj != NULL; | 497 obj != NULL; |
| 509 obj = iterator.next()) { | 498 obj = iterator.next()) { |
| 510 FindOrAddEntry(obj->address(), obj->Size()); | 499 FindOrAddEntry(obj->address(), obj->Size()); |
| 511 if (FLAG_heap_profiler_trace_objects) { | 500 if (FLAG_heap_profiler_trace_objects) { |
| 512 PrintF("Update object : %p %6d. Next address is %p\n", | 501 PrintF("Update object : %p %6d. Next address is %p\n", |
| 513 obj->address(), | 502 obj->address(), |
| 514 obj->Size(), | 503 obj->Size(), |
| 515 obj->address() + obj->Size()); | 504 obj->address() + obj->Size()); |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 703 ComputePointerHash(entry_info.addr)); | 692 ComputePointerHash(entry_info.addr)); |
| 704 } | 693 } |
| 705 } | 694 } |
| 706 } | 695 } |
| 707 entries_.Rewind(first_free_entry); | 696 entries_.Rewind(first_free_entry); |
| 708 ASSERT(static_cast<uint32_t>(entries_.length()) - 1 == | 697 ASSERT(static_cast<uint32_t>(entries_.length()) - 1 == |
| 709 entries_map_.occupancy()); | 698 entries_map_.occupancy()); |
| 710 } | 699 } |
| 711 | 700 |
| 712 | 701 |
| 713 SnapshotObjectId HeapObjectsMap::GenerateId(Heap* heap, | 702 SnapshotObjectId HeapObjectsMap::GenerateId(v8::RetainedObjectInfo* info) { |
| 714 v8::RetainedObjectInfo* info) { | |
| 715 SnapshotObjectId id = static_cast<SnapshotObjectId>(info->GetHash()); | 703 SnapshotObjectId id = static_cast<SnapshotObjectId>(info->GetHash()); |
| 716 const char* label = info->GetLabel(); | 704 const char* label = info->GetLabel(); |
| 717 id ^= StringHasher::HashSequentialString(label, | 705 id ^= StringHasher::HashSequentialString(label, |
| 718 static_cast<int>(strlen(label)), | 706 static_cast<int>(strlen(label)), |
| 719 heap->HashSeed()); | 707 heap_->HashSeed()); |
| 720 intptr_t element_count = info->GetElementCount(); | 708 intptr_t element_count = info->GetElementCount(); |
| 721 if (element_count != -1) | 709 if (element_count != -1) |
| 722 id ^= ComputeIntegerHash(static_cast<uint32_t>(element_count), | 710 id ^= ComputeIntegerHash(static_cast<uint32_t>(element_count), |
| 723 v8::internal::kZeroHashSeed); | 711 v8::internal::kZeroHashSeed); |
| 724 return id << 1; | 712 return id << 1; |
| 725 } | 713 } |
| 726 | 714 |
| 727 | 715 |
| 728 size_t HeapObjectsMap::GetUsedMemorySize() const { | 716 size_t HeapObjectsMap::GetUsedMemorySize() const { |
| 729 return | 717 return |
| 730 sizeof(*this) + | 718 sizeof(*this) + |
| 731 sizeof(HashMap::Entry) * entries_map_.capacity() + | 719 sizeof(HashMap::Entry) * entries_map_.capacity() + |
| 732 GetMemoryUsedByList(entries_) + | 720 GetMemoryUsedByList(entries_) + |
| 733 GetMemoryUsedByList(time_intervals_); | 721 GetMemoryUsedByList(time_intervals_); |
| 734 } | 722 } |
| 735 | 723 |
| 736 | 724 |
| 737 HeapSnapshotsCollection::HeapSnapshotsCollection(Heap* heap) | |
| 738 : names_(heap), | |
| 739 ids_(heap), | |
| 740 allocation_tracker_(NULL) { | |
| 741 } | |
| 742 | |
| 743 | |
| 744 static void DeleteHeapSnapshot(HeapSnapshot** snapshot_ptr) { | |
| 745 delete *snapshot_ptr; | |
| 746 } | |
| 747 | |
| 748 | |
| 749 HeapSnapshotsCollection::~HeapSnapshotsCollection() { | |
| 750 delete allocation_tracker_; | |
| 751 snapshots_.Iterate(DeleteHeapSnapshot); | |
| 752 } | |
| 753 | |
| 754 | |
| 755 void HeapSnapshotsCollection::StartHeapObjectsTracking(bool track_allocations) { | |
| 756 ids_.UpdateHeapObjectsMap(); | |
| 757 ASSERT(allocation_tracker_ == NULL); | |
| 758 if (track_allocations) { | |
| 759 allocation_tracker_ = new AllocationTracker(&ids_, names()); | |
| 760 } | |
| 761 } | |
| 762 | |
| 763 | |
| 764 void HeapSnapshotsCollection::StopHeapObjectsTracking() { | |
| 765 ids_.StopHeapObjectsTracking(); | |
| 766 if (allocation_tracker_ != NULL) { | |
| 767 delete allocation_tracker_; | |
| 768 allocation_tracker_ = NULL; | |
| 769 } | |
| 770 } | |
| 771 | |
| 772 | |
| 773 HeapSnapshot* HeapSnapshotsCollection::NewSnapshot(const char* name, | |
| 774 unsigned uid) { | |
| 775 return new HeapSnapshot(this, name, uid); | |
| 776 } | |
| 777 | |
| 778 | |
| 779 void HeapSnapshotsCollection::SnapshotGenerationFinished( | |
| 780 HeapSnapshot* snapshot) { | |
| 781 ids_.SnapshotGenerationFinished(); | |
| 782 if (snapshot != NULL) { | |
| 783 snapshots_.Add(snapshot); | |
| 784 } | |
| 785 } | |
| 786 | |
| 787 | |
| 788 void HeapSnapshotsCollection::RemoveSnapshot(HeapSnapshot* snapshot) { | |
| 789 snapshots_.RemoveElement(snapshot); | |
| 790 } | |
| 791 | |
| 792 | |
| 793 Handle<HeapObject> HeapSnapshotsCollection::FindHeapObjectById( | |
| 794 SnapshotObjectId id) { | |
| 795 // First perform a full GC in order to avoid dead objects. | |
| 796 heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask, | |
| 797 "HeapSnapshotsCollection::FindHeapObjectById"); | |
| 798 DisallowHeapAllocation no_allocation; | |
| 799 HeapObject* object = NULL; | |
| 800 HeapIterator iterator(heap(), HeapIterator::kFilterUnreachable); | |
| 801 // Make sure that object with the given id is still reachable. | |
| 802 for (HeapObject* obj = iterator.next(); | |
| 803 obj != NULL; | |
| 804 obj = iterator.next()) { | |
| 805 if (ids_.FindEntry(obj->address()) == id) { | |
| 806 ASSERT(object == NULL); | |
| 807 object = obj; | |
| 808 // Can't break -- kFilterUnreachable requires full heap traversal. | |
| 809 } | |
| 810 } | |
| 811 return object != NULL ? Handle<HeapObject>(object) : Handle<HeapObject>(); | |
| 812 } | |
| 813 | |
| 814 | |
| 815 void HeapSnapshotsCollection::AllocationEvent(Address addr, int size) { | |
| 816 DisallowHeapAllocation no_allocation; | |
| 817 if (allocation_tracker_ != NULL) { | |
| 818 allocation_tracker_->AllocationEvent(addr, size); | |
| 819 } | |
| 820 } | |
| 821 | |
| 822 | |
| 823 size_t HeapSnapshotsCollection::GetUsedMemorySize() const { | |
| 824 size_t size = sizeof(*this); | |
| 825 size += names_.GetUsedMemorySize(); | |
| 826 size += ids_.GetUsedMemorySize(); | |
| 827 size += GetMemoryUsedByList(snapshots_); | |
| 828 for (int i = 0; i < snapshots_.length(); ++i) { | |
| 829 size += snapshots_[i]->RawSnapshotSize(); | |
| 830 } | |
| 831 return size; | |
| 832 } | |
| 833 | |
| 834 | |
| 835 HeapEntriesMap::HeapEntriesMap() | 725 HeapEntriesMap::HeapEntriesMap() |
| 836 : entries_(HeapThingsMatch) { | 726 : entries_(HeapThingsMatch) { |
| 837 } | 727 } |
| 838 | 728 |
| 839 | 729 |
| 840 int HeapEntriesMap::Map(HeapThing thing) { | 730 int HeapEntriesMap::Map(HeapThing thing) { |
| 841 HashMap::Entry* cache_entry = entries_.Lookup(thing, Hash(thing), false); | 731 HashMap::Entry* cache_entry = entries_.Lookup(thing, Hash(thing), false); |
| 842 if (cache_entry == NULL) return HeapEntry::kNoEntry; | 732 if (cache_entry == NULL) return HeapEntry::kNoEntry; |
| 843 return static_cast<int>(reinterpret_cast<intptr_t>(cache_entry->value)); | 733 return static_cast<int>(reinterpret_cast<intptr_t>(cache_entry->value)); |
| 844 } | 734 } |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 905 static_cast<intptr_t>(HeapObjectsMap::kGcRootsFirstSubrootId)); | 795 static_cast<intptr_t>(HeapObjectsMap::kGcRootsFirstSubrootId)); |
| 906 HeapObject* const V8HeapExplorer::kLastGcSubrootObject = | 796 HeapObject* const V8HeapExplorer::kLastGcSubrootObject = |
| 907 reinterpret_cast<HeapObject*>( | 797 reinterpret_cast<HeapObject*>( |
| 908 static_cast<intptr_t>(HeapObjectsMap::kFirstAvailableObjectId)); | 798 static_cast<intptr_t>(HeapObjectsMap::kFirstAvailableObjectId)); |
| 909 | 799 |
| 910 | 800 |
| 911 V8HeapExplorer::V8HeapExplorer( | 801 V8HeapExplorer::V8HeapExplorer( |
| 912 HeapSnapshot* snapshot, | 802 HeapSnapshot* snapshot, |
| 913 SnapshottingProgressReportingInterface* progress, | 803 SnapshottingProgressReportingInterface* progress, |
| 914 v8::HeapProfiler::ObjectNameResolver* resolver) | 804 v8::HeapProfiler::ObjectNameResolver* resolver) |
| 915 : heap_(snapshot->collection()->heap()), | 805 : heap_(snapshot->profiler()->heap_object_map()->heap()), |
| 916 snapshot_(snapshot), | 806 snapshot_(snapshot), |
| 917 collection_(snapshot_->collection()), | 807 names_(snapshot_->profiler()->names()), |
| 808 heap_object_map_(snapshot_->profiler()->heap_object_map()), |
| 918 progress_(progress), | 809 progress_(progress), |
| 919 filler_(NULL), | 810 filler_(NULL), |
| 920 global_object_name_resolver_(resolver) { | 811 global_object_name_resolver_(resolver) { |
| 921 } | 812 } |
| 922 | 813 |
| 923 | 814 |
| 924 V8HeapExplorer::~V8HeapExplorer() { | 815 V8HeapExplorer::~V8HeapExplorer() { |
| 925 } | 816 } |
| 926 | 817 |
| 927 | 818 |
| 928 HeapEntry* V8HeapExplorer::AllocateEntry(HeapThing ptr) { | 819 HeapEntry* V8HeapExplorer::AllocateEntry(HeapThing ptr) { |
| 929 return AddEntry(reinterpret_cast<HeapObject*>(ptr)); | 820 return AddEntry(reinterpret_cast<HeapObject*>(ptr)); |
| 930 } | 821 } |
| 931 | 822 |
| 932 | 823 |
| 933 HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object) { | 824 HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object) { |
| 934 if (object == kInternalRootObject) { | 825 if (object == kInternalRootObject) { |
| 935 snapshot_->AddRootEntry(); | 826 snapshot_->AddRootEntry(); |
| 936 return snapshot_->root(); | 827 return snapshot_->root(); |
| 937 } else if (object == kGcRootsObject) { | 828 } else if (object == kGcRootsObject) { |
| 938 HeapEntry* entry = snapshot_->AddGcRootsEntry(); | 829 HeapEntry* entry = snapshot_->AddGcRootsEntry(); |
| 939 return entry; | 830 return entry; |
| 940 } else if (object >= kFirstGcSubrootObject && object < kLastGcSubrootObject) { | 831 } else if (object >= kFirstGcSubrootObject && object < kLastGcSubrootObject) { |
| 941 HeapEntry* entry = snapshot_->AddGcSubrootEntry(GetGcSubrootOrder(object)); | 832 HeapEntry* entry = snapshot_->AddGcSubrootEntry(GetGcSubrootOrder(object)); |
| 942 return entry; | 833 return entry; |
| 943 } else if (object->IsJSFunction()) { | 834 } else if (object->IsJSFunction()) { |
| 944 JSFunction* func = JSFunction::cast(object); | 835 JSFunction* func = JSFunction::cast(object); |
| 945 SharedFunctionInfo* shared = func->shared(); | 836 SharedFunctionInfo* shared = func->shared(); |
| 946 const char* name = shared->bound() ? "native_bind" : | 837 const char* name = shared->bound() ? "native_bind" : |
| 947 collection_->names()->GetName(String::cast(shared->name())); | 838 names_->GetName(String::cast(shared->name())); |
| 948 return AddEntry(object, HeapEntry::kClosure, name); | 839 return AddEntry(object, HeapEntry::kClosure, name); |
| 949 } else if (object->IsJSRegExp()) { | 840 } else if (object->IsJSRegExp()) { |
| 950 JSRegExp* re = JSRegExp::cast(object); | 841 JSRegExp* re = JSRegExp::cast(object); |
| 951 return AddEntry(object, | 842 return AddEntry(object, |
| 952 HeapEntry::kRegExp, | 843 HeapEntry::kRegExp, |
| 953 collection_->names()->GetName(re->Pattern())); | 844 names_->GetName(re->Pattern())); |
| 954 } else if (object->IsJSObject()) { | 845 } else if (object->IsJSObject()) { |
| 955 const char* name = collection_->names()->GetName( | 846 const char* name = names_->GetName( |
| 956 GetConstructorName(JSObject::cast(object))); | 847 GetConstructorName(JSObject::cast(object))); |
| 957 if (object->IsJSGlobalObject()) { | 848 if (object->IsJSGlobalObject()) { |
| 958 const char* tag = objects_tags_.GetTag(object); | 849 const char* tag = objects_tags_.GetTag(object); |
| 959 if (tag != NULL) { | 850 if (tag != NULL) { |
| 960 name = collection_->names()->GetFormatted("%s / %s", name, tag); | 851 name = names_->GetFormatted("%s / %s", name, tag); |
| 961 } | 852 } |
| 962 } | 853 } |
| 963 return AddEntry(object, HeapEntry::kObject, name); | 854 return AddEntry(object, HeapEntry::kObject, name); |
| 964 } else if (object->IsString()) { | 855 } else if (object->IsString()) { |
| 965 String* string = String::cast(object); | 856 String* string = String::cast(object); |
| 966 if (string->IsConsString()) | 857 if (string->IsConsString()) |
| 967 return AddEntry(object, | 858 return AddEntry(object, |
| 968 HeapEntry::kConsString, | 859 HeapEntry::kConsString, |
| 969 "(concatenated string)"); | 860 "(concatenated string)"); |
| 970 if (string->IsSlicedString()) | 861 if (string->IsSlicedString()) |
| 971 return AddEntry(object, | 862 return AddEntry(object, |
| 972 HeapEntry::kSlicedString, | 863 HeapEntry::kSlicedString, |
| 973 "(sliced string)"); | 864 "(sliced string)"); |
| 974 return AddEntry(object, | 865 return AddEntry(object, |
| 975 HeapEntry::kString, | 866 HeapEntry::kString, |
| 976 collection_->names()->GetName(String::cast(object))); | 867 names_->GetName(String::cast(object))); |
| 977 } else if (object->IsCode()) { | 868 } else if (object->IsCode()) { |
| 978 return AddEntry(object, HeapEntry::kCode, ""); | 869 return AddEntry(object, HeapEntry::kCode, ""); |
| 979 } else if (object->IsSharedFunctionInfo()) { | 870 } else if (object->IsSharedFunctionInfo()) { |
| 980 String* name = String::cast(SharedFunctionInfo::cast(object)->name()); | 871 String* name = String::cast(SharedFunctionInfo::cast(object)->name()); |
| 981 return AddEntry(object, | 872 return AddEntry(object, |
| 982 HeapEntry::kCode, | 873 HeapEntry::kCode, |
| 983 collection_->names()->GetName(name)); | 874 names_->GetName(name)); |
| 984 } else if (object->IsScript()) { | 875 } else if (object->IsScript()) { |
| 985 Object* name = Script::cast(object)->name(); | 876 Object* name = Script::cast(object)->name(); |
| 986 return AddEntry(object, | 877 return AddEntry(object, |
| 987 HeapEntry::kCode, | 878 HeapEntry::kCode, |
| 988 name->IsString() | 879 name->IsString() |
| 989 ? collection_->names()->GetName(String::cast(name)) | 880 ? names_->GetName(String::cast(name)) |
| 990 : ""); | 881 : ""); |
| 991 } else if (object->IsNativeContext()) { | 882 } else if (object->IsNativeContext()) { |
| 992 return AddEntry(object, HeapEntry::kHidden, "system / NativeContext"); | 883 return AddEntry(object, HeapEntry::kHidden, "system / NativeContext"); |
| 993 } else if (object->IsContext()) { | 884 } else if (object->IsContext()) { |
| 994 return AddEntry(object, HeapEntry::kObject, "system / Context"); | 885 return AddEntry(object, HeapEntry::kObject, "system / Context"); |
| 995 } else if (object->IsFixedArray() || | 886 } else if (object->IsFixedArray() || |
| 996 object->IsFixedDoubleArray() || | 887 object->IsFixedDoubleArray() || |
| 997 object->IsByteArray() || | 888 object->IsByteArray() || |
| 998 object->IsExternalArray()) { | 889 object->IsExternalArray()) { |
| 999 return AddEntry(object, HeapEntry::kArray, ""); | 890 return AddEntry(object, HeapEntry::kArray, ""); |
| 1000 } else if (object->IsHeapNumber()) { | 891 } else if (object->IsHeapNumber()) { |
| 1001 return AddEntry(object, HeapEntry::kHeapNumber, "number"); | 892 return AddEntry(object, HeapEntry::kHeapNumber, "number"); |
| 1002 } | 893 } |
| 1003 return AddEntry(object, HeapEntry::kHidden, GetSystemEntryName(object)); | 894 return AddEntry(object, HeapEntry::kHidden, GetSystemEntryName(object)); |
| 1004 } | 895 } |
| 1005 | 896 |
| 1006 | 897 |
| 1007 HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object, | 898 HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object, |
| 1008 HeapEntry::Type type, | 899 HeapEntry::Type type, |
| 1009 const char* name) { | 900 const char* name) { |
| 1010 int object_size = object->Size(); | 901 int object_size = object->Size(); |
| 1011 SnapshotObjectId object_id = | 902 SnapshotObjectId object_id = |
| 1012 collection_->GetObjectId(object->address(), object_size); | 903 heap_object_map_->FindOrAddEntry(object->address(), object_size); |
| 1013 return snapshot_->AddEntry(type, name, object_id, object_size); | 904 return snapshot_->AddEntry(type, name, object_id, object_size); |
| 1014 } | 905 } |
| 1015 | 906 |
| 1016 | 907 |
| 1017 class GcSubrootsEnumerator : public ObjectVisitor { | 908 class GcSubrootsEnumerator : public ObjectVisitor { |
| 1018 public: | 909 public: |
| 1019 GcSubrootsEnumerator( | 910 GcSubrootsEnumerator( |
| 1020 SnapshotFillerInterface* filler, V8HeapExplorer* explorer) | 911 SnapshotFillerInterface* filler, V8HeapExplorer* explorer) |
| 1021 : filler_(filler), | 912 : filler_(filler), |
| 1022 explorer_(explorer), | 913 explorer_(explorer), |
| (...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1349 TagObject(map->dependent_code(), "(dependent code)"); | 1240 TagObject(map->dependent_code(), "(dependent code)"); |
| 1350 SetInternalReference(map, entry, | 1241 SetInternalReference(map, entry, |
| 1351 "dependent_code", map->dependent_code(), | 1242 "dependent_code", map->dependent_code(), |
| 1352 Map::kDependentCodeOffset); | 1243 Map::kDependentCodeOffset); |
| 1353 } | 1244 } |
| 1354 | 1245 |
| 1355 | 1246 |
| 1356 void V8HeapExplorer::ExtractSharedFunctionInfoReferences( | 1247 void V8HeapExplorer::ExtractSharedFunctionInfoReferences( |
| 1357 int entry, SharedFunctionInfo* shared) { | 1248 int entry, SharedFunctionInfo* shared) { |
| 1358 HeapObject* obj = shared; | 1249 HeapObject* obj = shared; |
| 1359 StringsStorage* names = collection_->names(); | |
| 1360 String* shared_name = shared->DebugName(); | 1250 String* shared_name = shared->DebugName(); |
| 1361 const char* name = NULL; | 1251 const char* name = NULL; |
| 1362 if (shared_name != *heap_->isolate()->factory()->empty_string()) { | 1252 if (shared_name != *heap_->isolate()->factory()->empty_string()) { |
| 1363 name = names->GetName(shared_name); | 1253 name = names_->GetName(shared_name); |
| 1364 TagObject(shared->code(), names->GetFormatted("(code for %s)", name)); | 1254 TagObject(shared->code(), names_->GetFormatted("(code for %s)", name)); |
| 1365 } else { | 1255 } else { |
| 1366 TagObject(shared->code(), names->GetFormatted("(%s code)", | 1256 TagObject(shared->code(), names_->GetFormatted("(%s code)", |
| 1367 Code::Kind2String(shared->code()->kind()))); | 1257 Code::Kind2String(shared->code()->kind()))); |
| 1368 } | 1258 } |
| 1369 | 1259 |
| 1370 SetInternalReference(obj, entry, | 1260 SetInternalReference(obj, entry, |
| 1371 "name", shared->name(), | 1261 "name", shared->name(), |
| 1372 SharedFunctionInfo::kNameOffset); | 1262 SharedFunctionInfo::kNameOffset); |
| 1373 SetInternalReference(obj, entry, | 1263 SetInternalReference(obj, entry, |
| 1374 "code", shared->code(), | 1264 "code", shared->code(), |
| 1375 SharedFunctionInfo::kCodeOffset); | 1265 SharedFunctionInfo::kCodeOffset); |
| 1376 TagObject(shared->scope_info(), "(function scope info)"); | 1266 TagObject(shared->scope_info(), "(function scope info)"); |
| 1377 SetInternalReference(obj, entry, | 1267 SetInternalReference(obj, entry, |
| 1378 "scope_info", shared->scope_info(), | 1268 "scope_info", shared->scope_info(), |
| 1379 SharedFunctionInfo::kScopeInfoOffset); | 1269 SharedFunctionInfo::kScopeInfoOffset); |
| 1380 SetInternalReference(obj, entry, | 1270 SetInternalReference(obj, entry, |
| 1381 "instance_class_name", shared->instance_class_name(), | 1271 "instance_class_name", shared->instance_class_name(), |
| 1382 SharedFunctionInfo::kInstanceClassNameOffset); | 1272 SharedFunctionInfo::kInstanceClassNameOffset); |
| 1383 SetInternalReference(obj, entry, | 1273 SetInternalReference(obj, entry, |
| 1384 "script", shared->script(), | 1274 "script", shared->script(), |
| 1385 SharedFunctionInfo::kScriptOffset); | 1275 SharedFunctionInfo::kScriptOffset); |
| 1386 const char* construct_stub_name = name ? | 1276 const char* construct_stub_name = name ? |
| 1387 names->GetFormatted("(construct stub code for %s)", name) : | 1277 names_->GetFormatted("(construct stub code for %s)", name) : |
| 1388 "(construct stub code)"; | 1278 "(construct stub code)"; |
| 1389 TagObject(shared->construct_stub(), construct_stub_name); | 1279 TagObject(shared->construct_stub(), construct_stub_name); |
| 1390 SetInternalReference(obj, entry, | 1280 SetInternalReference(obj, entry, |
| 1391 "construct_stub", shared->construct_stub(), | 1281 "construct_stub", shared->construct_stub(), |
| 1392 SharedFunctionInfo::kConstructStubOffset); | 1282 SharedFunctionInfo::kConstructStubOffset); |
| 1393 SetInternalReference(obj, entry, | 1283 SetInternalReference(obj, entry, |
| 1394 "function_data", shared->function_data(), | 1284 "function_data", shared->function_data(), |
| 1395 SharedFunctionInfo::kFunctionDataOffset); | 1285 SharedFunctionInfo::kFunctionDataOffset); |
| 1396 SetInternalReference(obj, entry, | 1286 SetInternalReference(obj, entry, |
| 1397 "debug_info", shared->debug_info(), | 1287 "debug_info", shared->debug_info(), |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1445 "default_cache", code_cache->default_cache(), | 1335 "default_cache", code_cache->default_cache(), |
| 1446 CodeCache::kDefaultCacheOffset); | 1336 CodeCache::kDefaultCacheOffset); |
| 1447 TagObject(code_cache->normal_type_cache(), "(code type cache)"); | 1337 TagObject(code_cache->normal_type_cache(), "(code type cache)"); |
| 1448 SetInternalReference(code_cache, entry, | 1338 SetInternalReference(code_cache, entry, |
| 1449 "type_cache", code_cache->normal_type_cache(), | 1339 "type_cache", code_cache->normal_type_cache(), |
| 1450 CodeCache::kNormalTypeCacheOffset); | 1340 CodeCache::kNormalTypeCacheOffset); |
| 1451 } | 1341 } |
| 1452 | 1342 |
| 1453 | 1343 |
| 1454 void V8HeapExplorer::TagCodeObject(Code* code, const char* external_name) { | 1344 void V8HeapExplorer::TagCodeObject(Code* code, const char* external_name) { |
| 1455 TagObject(code, collection_->names()->GetFormatted("(%s code)", | 1345 TagObject(code, names_->GetFormatted("(%s code)", external_name)); |
| 1456 external_name)); | |
| 1457 } | 1346 } |
| 1458 | 1347 |
| 1459 | 1348 |
| 1460 void V8HeapExplorer::TagCodeObject(Code* code) { | 1349 void V8HeapExplorer::TagCodeObject(Code* code) { |
| 1461 if (code->kind() == Code::STUB) { | 1350 if (code->kind() == Code::STUB) { |
| 1462 TagObject(code, collection_->names()->GetFormatted( | 1351 TagObject(code, names_->GetFormatted( |
| 1463 "(%s code)", CodeStub::MajorName( | 1352 "(%s code)", CodeStub::MajorName( |
| 1464 static_cast<CodeStub::Major>(code->major_key()), true))); | 1353 static_cast<CodeStub::Major>(code->major_key()), true))); |
| 1465 } | 1354 } |
| 1466 } | 1355 } |
| 1467 | 1356 |
| 1468 | 1357 |
| 1469 void V8HeapExplorer::ExtractCodeReferences(int entry, Code* code) { | 1358 void V8HeapExplorer::ExtractCodeReferences(int entry, Code* code) { |
| 1470 TagCodeObject(code); | 1359 TagCodeObject(code); |
| 1471 TagObject(code->relocation_info(), "(code relocation info)"); | 1360 TagObject(code->relocation_info(), "(code relocation info)"); |
| 1472 SetInternalReference(code, entry, | 1361 SetInternalReference(code, entry, |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1530 | 1419 |
| 1531 JSFunction* func = JSFunction::cast(js_obj); | 1420 JSFunction* func = JSFunction::cast(js_obj); |
| 1532 if (func->shared()->bound()) { | 1421 if (func->shared()->bound()) { |
| 1533 FixedArray* bindings = func->function_bindings(); | 1422 FixedArray* bindings = func->function_bindings(); |
| 1534 SetNativeBindReference(js_obj, entry, "bound_this", | 1423 SetNativeBindReference(js_obj, entry, "bound_this", |
| 1535 bindings->get(JSFunction::kBoundThisIndex)); | 1424 bindings->get(JSFunction::kBoundThisIndex)); |
| 1536 SetNativeBindReference(js_obj, entry, "bound_function", | 1425 SetNativeBindReference(js_obj, entry, "bound_function", |
| 1537 bindings->get(JSFunction::kBoundFunctionIndex)); | 1426 bindings->get(JSFunction::kBoundFunctionIndex)); |
| 1538 for (int i = JSFunction::kBoundArgumentsStartIndex; | 1427 for (int i = JSFunction::kBoundArgumentsStartIndex; |
| 1539 i < bindings->length(); i++) { | 1428 i < bindings->length(); i++) { |
| 1540 const char* reference_name = collection_->names()->GetFormatted( | 1429 const char* reference_name = names_->GetFormatted( |
| 1541 "bound_argument_%d", | 1430 "bound_argument_%d", |
| 1542 i - JSFunction::kBoundArgumentsStartIndex); | 1431 i - JSFunction::kBoundArgumentsStartIndex); |
| 1543 SetNativeBindReference(js_obj, entry, reference_name, | 1432 SetNativeBindReference(js_obj, entry, reference_name, |
| 1544 bindings->get(i)); | 1433 bindings->get(i)); |
| 1545 } | 1434 } |
| 1546 } | 1435 } |
| 1547 } | 1436 } |
| 1548 | 1437 |
| 1549 | 1438 |
| 1550 void V8HeapExplorer::ExtractPropertyReferences(JSObject* js_obj, int entry) { | 1439 void V8HeapExplorer::ExtractPropertyReferences(JSObject* js_obj, int entry) { |
| (...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1837 void V8HeapExplorer::SetContextReference(HeapObject* parent_obj, | 1726 void V8HeapExplorer::SetContextReference(HeapObject* parent_obj, |
| 1838 int parent_entry, | 1727 int parent_entry, |
| 1839 String* reference_name, | 1728 String* reference_name, |
| 1840 Object* child_obj, | 1729 Object* child_obj, |
| 1841 int field_offset) { | 1730 int field_offset) { |
| 1842 ASSERT(parent_entry == GetEntry(parent_obj)->index()); | 1731 ASSERT(parent_entry == GetEntry(parent_obj)->index()); |
| 1843 HeapEntry* child_entry = GetEntry(child_obj); | 1732 HeapEntry* child_entry = GetEntry(child_obj); |
| 1844 if (child_entry != NULL) { | 1733 if (child_entry != NULL) { |
| 1845 filler_->SetNamedReference(HeapGraphEdge::kContextVariable, | 1734 filler_->SetNamedReference(HeapGraphEdge::kContextVariable, |
| 1846 parent_entry, | 1735 parent_entry, |
| 1847 collection_->names()->GetName(reference_name), | 1736 names_->GetName(reference_name), |
| 1848 child_entry); | 1737 child_entry); |
| 1849 IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset); | 1738 IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset); |
| 1850 } | 1739 } |
| 1851 } | 1740 } |
| 1852 | 1741 |
| 1853 | 1742 |
| 1854 void V8HeapExplorer::SetNativeBindReference(HeapObject* parent_obj, | 1743 void V8HeapExplorer::SetNativeBindReference(HeapObject* parent_obj, |
| 1855 int parent_entry, | 1744 int parent_entry, |
| 1856 const char* reference_name, | 1745 const char* reference_name, |
| 1857 Object* child_obj) { | 1746 Object* child_obj) { |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1903 int parent_entry, | 1792 int parent_entry, |
| 1904 int index, | 1793 int index, |
| 1905 Object* child_obj, | 1794 Object* child_obj, |
| 1906 int field_offset) { | 1795 int field_offset) { |
| 1907 ASSERT(parent_entry == GetEntry(parent_obj)->index()); | 1796 ASSERT(parent_entry == GetEntry(parent_obj)->index()); |
| 1908 HeapEntry* child_entry = GetEntry(child_obj); | 1797 HeapEntry* child_entry = GetEntry(child_obj); |
| 1909 if (child_entry == NULL) return; | 1798 if (child_entry == NULL) return; |
| 1910 if (IsEssentialObject(child_obj)) { | 1799 if (IsEssentialObject(child_obj)) { |
| 1911 filler_->SetNamedReference(HeapGraphEdge::kInternal, | 1800 filler_->SetNamedReference(HeapGraphEdge::kInternal, |
| 1912 parent_entry, | 1801 parent_entry, |
| 1913 collection_->names()->GetName(index), | 1802 names_->GetName(index), |
| 1914 child_entry); | 1803 child_entry); |
| 1915 } | 1804 } |
| 1916 IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset); | 1805 IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset); |
| 1917 } | 1806 } |
| 1918 | 1807 |
| 1919 | 1808 |
| 1920 void V8HeapExplorer::SetHiddenReference(HeapObject* parent_obj, | 1809 void V8HeapExplorer::SetHiddenReference(HeapObject* parent_obj, |
| 1921 int parent_entry, | 1810 int parent_entry, |
| 1922 int index, | 1811 int index, |
| 1923 Object* child_obj) { | 1812 Object* child_obj) { |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1956 Object* child_obj, | 1845 Object* child_obj, |
| 1957 const char* name_format_string, | 1846 const char* name_format_string, |
| 1958 int field_offset) { | 1847 int field_offset) { |
| 1959 ASSERT(parent_entry == GetEntry(parent_obj)->index()); | 1848 ASSERT(parent_entry == GetEntry(parent_obj)->index()); |
| 1960 HeapEntry* child_entry = GetEntry(child_obj); | 1849 HeapEntry* child_entry = GetEntry(child_obj); |
| 1961 if (child_entry != NULL) { | 1850 if (child_entry != NULL) { |
| 1962 HeapGraphEdge::Type type = | 1851 HeapGraphEdge::Type type = |
| 1963 reference_name->IsSymbol() || String::cast(reference_name)->length() > 0 | 1852 reference_name->IsSymbol() || String::cast(reference_name)->length() > 0 |
| 1964 ? HeapGraphEdge::kProperty : HeapGraphEdge::kInternal; | 1853 ? HeapGraphEdge::kProperty : HeapGraphEdge::kInternal; |
| 1965 const char* name = name_format_string != NULL && reference_name->IsString() | 1854 const char* name = name_format_string != NULL && reference_name->IsString() |
| 1966 ? collection_->names()->GetFormatted( | 1855 ? names_->GetFormatted( |
| 1967 name_format_string, | 1856 name_format_string, |
| 1968 *String::cast(reference_name)->ToCString( | 1857 *String::cast(reference_name)->ToCString( |
| 1969 DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL)) : | 1858 DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL)) : |
| 1970 collection_->names()->GetName(reference_name); | 1859 names_->GetName(reference_name); |
| 1971 | 1860 |
| 1972 filler_->SetNamedReference(type, | 1861 filler_->SetNamedReference(type, |
| 1973 parent_entry, | 1862 parent_entry, |
| 1974 name, | 1863 name, |
| 1975 child_entry); | 1864 child_entry); |
| 1976 IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset); | 1865 IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset); |
| 1977 } | 1866 } |
| 1978 } | 1867 } |
| 1979 | 1868 |
| 1980 | 1869 |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2136 NativeObjectsExplorer* explorer_; | 2025 NativeObjectsExplorer* explorer_; |
| 2137 }; | 2026 }; |
| 2138 | 2027 |
| 2139 | 2028 |
| 2140 class BasicHeapEntriesAllocator : public HeapEntriesAllocator { | 2029 class BasicHeapEntriesAllocator : public HeapEntriesAllocator { |
| 2141 public: | 2030 public: |
| 2142 BasicHeapEntriesAllocator( | 2031 BasicHeapEntriesAllocator( |
| 2143 HeapSnapshot* snapshot, | 2032 HeapSnapshot* snapshot, |
| 2144 HeapEntry::Type entries_type) | 2033 HeapEntry::Type entries_type) |
| 2145 : snapshot_(snapshot), | 2034 : snapshot_(snapshot), |
| 2146 collection_(snapshot_->collection()), | 2035 names_(snapshot_->profiler()->names()), |
| 2036 heap_object_map_(snapshot_->profiler()->heap_object_map()), |
| 2147 entries_type_(entries_type) { | 2037 entries_type_(entries_type) { |
| 2148 } | 2038 } |
| 2149 virtual HeapEntry* AllocateEntry(HeapThing ptr); | 2039 virtual HeapEntry* AllocateEntry(HeapThing ptr); |
| 2150 private: | 2040 private: |
| 2151 HeapSnapshot* snapshot_; | 2041 HeapSnapshot* snapshot_; |
| 2152 HeapSnapshotsCollection* collection_; | 2042 StringsStorage* names_; |
| 2043 HeapObjectsMap* heap_object_map_; |
| 2153 HeapEntry::Type entries_type_; | 2044 HeapEntry::Type entries_type_; |
| 2154 }; | 2045 }; |
| 2155 | 2046 |
| 2156 | 2047 |
| 2157 HeapEntry* BasicHeapEntriesAllocator::AllocateEntry(HeapThing ptr) { | 2048 HeapEntry* BasicHeapEntriesAllocator::AllocateEntry(HeapThing ptr) { |
| 2158 v8::RetainedObjectInfo* info = reinterpret_cast<v8::RetainedObjectInfo*>(ptr); | 2049 v8::RetainedObjectInfo* info = reinterpret_cast<v8::RetainedObjectInfo*>(ptr); |
| 2159 intptr_t elements = info->GetElementCount(); | 2050 intptr_t elements = info->GetElementCount(); |
| 2160 intptr_t size = info->GetSizeInBytes(); | 2051 intptr_t size = info->GetSizeInBytes(); |
| 2161 const char* name = elements != -1 | 2052 const char* name = elements != -1 |
| 2162 ? collection_->names()->GetFormatted( | 2053 ? names_->GetFormatted( |
| 2163 "%s / %" V8_PTR_PREFIX "d entries", info->GetLabel(), elements) | 2054 "%s / %" V8_PTR_PREFIX "d entries", info->GetLabel(), elements) |
| 2164 : collection_->names()->GetCopy(info->GetLabel()); | 2055 : names_->GetCopy(info->GetLabel()); |
| 2165 return snapshot_->AddEntry( | 2056 return snapshot_->AddEntry( |
| 2166 entries_type_, | 2057 entries_type_, |
| 2167 name, | 2058 name, |
| 2168 HeapObjectsMap::GenerateId(collection_->heap(), info), | 2059 heap_object_map_->GenerateId(info), |
| 2169 size != -1 ? static_cast<int>(size) : 0); | 2060 size != -1 ? static_cast<int>(size) : 0); |
| 2170 } | 2061 } |
| 2171 | 2062 |
| 2172 | 2063 |
| 2173 NativeObjectsExplorer::NativeObjectsExplorer( | 2064 NativeObjectsExplorer::NativeObjectsExplorer( |
| 2174 HeapSnapshot* snapshot, | 2065 HeapSnapshot* snapshot, |
| 2175 SnapshottingProgressReportingInterface* progress) | 2066 SnapshottingProgressReportingInterface* progress) |
| 2176 : isolate_(snapshot->collection()->heap()->isolate()), | 2067 : isolate_(snapshot->profiler()->heap_object_map()->heap()->isolate()), |
| 2177 snapshot_(snapshot), | 2068 snapshot_(snapshot), |
| 2178 collection_(snapshot_->collection()), | 2069 names_(snapshot_->profiler()->names()), |
| 2179 progress_(progress), | 2070 progress_(progress), |
| 2180 embedder_queried_(false), | 2071 embedder_queried_(false), |
| 2181 objects_by_info_(RetainedInfosMatch), | 2072 objects_by_info_(RetainedInfosMatch), |
| 2182 native_groups_(StringsMatch), | 2073 native_groups_(StringsMatch), |
| 2183 filler_(NULL) { | 2074 filler_(NULL) { |
| 2184 synthetic_entries_allocator_ = | 2075 synthetic_entries_allocator_ = |
| 2185 new BasicHeapEntriesAllocator(snapshot, HeapEntry::kSynthetic); | 2076 new BasicHeapEntriesAllocator(snapshot, HeapEntry::kSynthetic); |
| 2186 native_entries_allocator_ = | 2077 native_entries_allocator_ = |
| 2187 new BasicHeapEntriesAllocator(snapshot, HeapEntry::kNative); | 2078 new BasicHeapEntriesAllocator(snapshot, HeapEntry::kNative); |
| 2188 } | 2079 } |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2330 | 2221 |
| 2331 private: | 2222 private: |
| 2332 bool disposed_; | 2223 bool disposed_; |
| 2333 intptr_t hash_; | 2224 intptr_t hash_; |
| 2334 const char* label_; | 2225 const char* label_; |
| 2335 }; | 2226 }; |
| 2336 | 2227 |
| 2337 | 2228 |
| 2338 NativeGroupRetainedObjectInfo* NativeObjectsExplorer::FindOrAddGroupInfo( | 2229 NativeGroupRetainedObjectInfo* NativeObjectsExplorer::FindOrAddGroupInfo( |
| 2339 const char* label) { | 2230 const char* label) { |
| 2340 const char* label_copy = collection_->names()->GetCopy(label); | 2231 const char* label_copy = names_->GetCopy(label); |
| 2341 uint32_t hash = StringHasher::HashSequentialString( | 2232 uint32_t hash = StringHasher::HashSequentialString( |
| 2342 label_copy, | 2233 label_copy, |
| 2343 static_cast<int>(strlen(label_copy)), | 2234 static_cast<int>(strlen(label_copy)), |
| 2344 isolate_->heap()->HashSeed()); | 2235 isolate_->heap()->HashSeed()); |
| 2345 HashMap::Entry* entry = native_groups_.Lookup(const_cast<char*>(label_copy), | 2236 HashMap::Entry* entry = native_groups_.Lookup(const_cast<char*>(label_copy), |
| 2346 hash, true); | 2237 hash, true); |
| 2347 if (entry->value == NULL) { | 2238 if (entry->value == NULL) { |
| 2348 entry->value = new NativeGroupRetainedObjectInfo(label); | 2239 entry->value = new NativeGroupRetainedObjectInfo(label); |
| 2349 } | 2240 } |
| 2350 return static_cast<NativeGroupRetainedObjectInfo*>(entry->value); | 2241 return static_cast<NativeGroupRetainedObjectInfo*>(entry->value); |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2408 isolate->heap_profiler()->ExecuteWrapperClassCallback(class_id, p); | 2299 isolate->heap_profiler()->ExecuteWrapperClassCallback(class_id, p); |
| 2409 if (info == NULL) return; | 2300 if (info == NULL) return; |
| 2410 GetListMaybeDisposeInfo(info)->Add(HeapObject::cast(*p)); | 2301 GetListMaybeDisposeInfo(info)->Add(HeapObject::cast(*p)); |
| 2411 } | 2302 } |
| 2412 | 2303 |
| 2413 | 2304 |
| 2414 class SnapshotFiller : public SnapshotFillerInterface { | 2305 class SnapshotFiller : public SnapshotFillerInterface { |
| 2415 public: | 2306 public: |
| 2416 explicit SnapshotFiller(HeapSnapshot* snapshot, HeapEntriesMap* entries) | 2307 explicit SnapshotFiller(HeapSnapshot* snapshot, HeapEntriesMap* entries) |
| 2417 : snapshot_(snapshot), | 2308 : snapshot_(snapshot), |
| 2418 collection_(snapshot->collection()), | 2309 names_(snapshot->profiler()->names()), |
| 2419 entries_(entries) { } | 2310 entries_(entries) { } |
| 2420 HeapEntry* AddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) { | 2311 HeapEntry* AddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) { |
| 2421 HeapEntry* entry = allocator->AllocateEntry(ptr); | 2312 HeapEntry* entry = allocator->AllocateEntry(ptr); |
| 2422 entries_->Pair(ptr, entry->index()); | 2313 entries_->Pair(ptr, entry->index()); |
| 2423 return entry; | 2314 return entry; |
| 2424 } | 2315 } |
| 2425 HeapEntry* FindEntry(HeapThing ptr) { | 2316 HeapEntry* FindEntry(HeapThing ptr) { |
| 2426 int index = entries_->Map(ptr); | 2317 int index = entries_->Map(ptr); |
| 2427 return index != HeapEntry::kNoEntry ? &snapshot_->entries()[index] : NULL; | 2318 return index != HeapEntry::kNoEntry ? &snapshot_->entries()[index] : NULL; |
| 2428 } | 2319 } |
| (...skipping 22 matching lines...) Expand all Loading... |
| 2451 HeapEntry* parent_entry = &snapshot_->entries()[parent]; | 2342 HeapEntry* parent_entry = &snapshot_->entries()[parent]; |
| 2452 parent_entry->SetNamedReference(type, reference_name, child_entry); | 2343 parent_entry->SetNamedReference(type, reference_name, child_entry); |
| 2453 } | 2344 } |
| 2454 void SetNamedAutoIndexReference(HeapGraphEdge::Type type, | 2345 void SetNamedAutoIndexReference(HeapGraphEdge::Type type, |
| 2455 int parent, | 2346 int parent, |
| 2456 HeapEntry* child_entry) { | 2347 HeapEntry* child_entry) { |
| 2457 HeapEntry* parent_entry = &snapshot_->entries()[parent]; | 2348 HeapEntry* parent_entry = &snapshot_->entries()[parent]; |
| 2458 int index = parent_entry->children_count() + 1; | 2349 int index = parent_entry->children_count() + 1; |
| 2459 parent_entry->SetNamedReference( | 2350 parent_entry->SetNamedReference( |
| 2460 type, | 2351 type, |
| 2461 collection_->names()->GetName(index), | 2352 names_->GetName(index), |
| 2462 child_entry); | 2353 child_entry); |
| 2463 } | 2354 } |
| 2464 | 2355 |
| 2465 private: | 2356 private: |
| 2466 HeapSnapshot* snapshot_; | 2357 HeapSnapshot* snapshot_; |
| 2467 HeapSnapshotsCollection* collection_; | 2358 StringsStorage* names_; |
| 2468 HeapEntriesMap* entries_; | 2359 HeapEntriesMap* entries_; |
| 2469 }; | 2360 }; |
| 2470 | 2361 |
| 2471 | 2362 |
| 2472 HeapSnapshotGenerator::HeapSnapshotGenerator( | 2363 HeapSnapshotGenerator::HeapSnapshotGenerator( |
| 2473 HeapSnapshot* snapshot, | 2364 HeapSnapshot* snapshot, |
| 2474 v8::ActivityControl* control, | 2365 v8::ActivityControl* control, |
| 2475 v8::HeapProfiler::ObjectNameResolver* resolver, | 2366 v8::HeapProfiler::ObjectNameResolver* resolver, |
| 2476 Heap* heap) | 2367 Heap* heap) |
| 2477 : snapshot_(snapshot), | 2368 : snapshot_(snapshot), |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2663 }; | 2554 }; |
| 2664 | 2555 |
| 2665 | 2556 |
| 2666 // type, name|index, to_node. | 2557 // type, name|index, to_node. |
| 2667 const int HeapSnapshotJSONSerializer::kEdgeFieldsCount = 3; | 2558 const int HeapSnapshotJSONSerializer::kEdgeFieldsCount = 3; |
| 2668 // type, name, id, self_size, children_index. | 2559 // type, name, id, self_size, children_index. |
| 2669 const int HeapSnapshotJSONSerializer::kNodeFieldsCount = 5; | 2560 const int HeapSnapshotJSONSerializer::kNodeFieldsCount = 5; |
| 2670 | 2561 |
| 2671 void HeapSnapshotJSONSerializer::Serialize(v8::OutputStream* stream) { | 2562 void HeapSnapshotJSONSerializer::Serialize(v8::OutputStream* stream) { |
| 2672 if (AllocationTracker* allocation_tracker = | 2563 if (AllocationTracker* allocation_tracker = |
| 2673 snapshot_->collection()->allocation_tracker()) { | 2564 snapshot_->profiler()->allocation_tracker()) { |
| 2674 allocation_tracker->PrepareForSerialization(); | 2565 allocation_tracker->PrepareForSerialization(); |
| 2675 } | 2566 } |
| 2676 ASSERT(writer_ == NULL); | 2567 ASSERT(writer_ == NULL); |
| 2677 writer_ = new OutputStreamWriter(stream); | 2568 writer_ = new OutputStreamWriter(stream); |
| 2678 SerializeImpl(); | 2569 SerializeImpl(); |
| 2679 delete writer_; | 2570 delete writer_; |
| 2680 writer_ = NULL; | 2571 writer_ = NULL; |
| 2681 } | 2572 } |
| 2682 | 2573 |
| 2683 | 2574 |
| (...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2882 JSON_S("children")))); | 2773 JSON_S("children")))); |
| 2883 #undef JSON_S | 2774 #undef JSON_S |
| 2884 #undef JSON_O | 2775 #undef JSON_O |
| 2885 #undef JSON_A | 2776 #undef JSON_A |
| 2886 writer_->AddString(",\"node_count\":"); | 2777 writer_->AddString(",\"node_count\":"); |
| 2887 writer_->AddNumber(snapshot_->entries().length()); | 2778 writer_->AddNumber(snapshot_->entries().length()); |
| 2888 writer_->AddString(",\"edge_count\":"); | 2779 writer_->AddString(",\"edge_count\":"); |
| 2889 writer_->AddNumber(snapshot_->edges().length()); | 2780 writer_->AddNumber(snapshot_->edges().length()); |
| 2890 writer_->AddString(",\"trace_function_count\":"); | 2781 writer_->AddString(",\"trace_function_count\":"); |
| 2891 uint32_t count = 0; | 2782 uint32_t count = 0; |
| 2892 AllocationTracker* tracker = snapshot_->collection()->allocation_tracker(); | 2783 AllocationTracker* tracker = snapshot_->profiler()->allocation_tracker(); |
| 2893 if (tracker) { | 2784 if (tracker) { |
| 2894 count = tracker->id_to_function_info()->occupancy(); | 2785 count = tracker->id_to_function_info()->occupancy(); |
| 2895 } | 2786 } |
| 2896 writer_->AddNumber(count); | 2787 writer_->AddNumber(count); |
| 2897 } | 2788 } |
| 2898 | 2789 |
| 2899 | 2790 |
| 2900 static void WriteUChar(OutputStreamWriter* w, unibrow::uchar u) { | 2791 static void WriteUChar(OutputStreamWriter* w, unibrow::uchar u) { |
| 2901 static const char hex_chars[] = "0123456789ABCDEF"; | 2792 static const char hex_chars[] = "0123456789ABCDEF"; |
| 2902 w->AddString("\\u"); | 2793 w->AddString("\\u"); |
| 2903 w->AddCharacter(hex_chars[(u >> 12) & 0xf]); | 2794 w->AddCharacter(hex_chars[(u >> 12) & 0xf]); |
| 2904 w->AddCharacter(hex_chars[(u >> 8) & 0xf]); | 2795 w->AddCharacter(hex_chars[(u >> 8) & 0xf]); |
| 2905 w->AddCharacter(hex_chars[(u >> 4) & 0xf]); | 2796 w->AddCharacter(hex_chars[(u >> 4) & 0xf]); |
| 2906 w->AddCharacter(hex_chars[u & 0xf]); | 2797 w->AddCharacter(hex_chars[u & 0xf]); |
| 2907 } | 2798 } |
| 2908 | 2799 |
| 2909 | 2800 |
| 2910 void HeapSnapshotJSONSerializer::SerializeTraceTree() { | 2801 void HeapSnapshotJSONSerializer::SerializeTraceTree() { |
| 2911 AllocationTracker* tracker = snapshot_->collection()->allocation_tracker(); | 2802 AllocationTracker* tracker = snapshot_->profiler()->allocation_tracker(); |
| 2912 if (!tracker) return; | 2803 if (!tracker) return; |
| 2913 AllocationTraceTree* traces = tracker->trace_tree(); | 2804 AllocationTraceTree* traces = tracker->trace_tree(); |
| 2914 SerializeTraceNode(traces->root()); | 2805 SerializeTraceNode(traces->root()); |
| 2915 } | 2806 } |
| 2916 | 2807 |
| 2917 | 2808 |
| 2918 void HeapSnapshotJSONSerializer::SerializeTraceNode(AllocationTraceNode* node) { | 2809 void HeapSnapshotJSONSerializer::SerializeTraceNode(AllocationTraceNode* node) { |
| 2919 // The buffer needs space for 4 unsigned ints, 4 commas, [ and \0 | 2810 // The buffer needs space for 4 unsigned ints, 4 commas, [ and \0 |
| 2920 const int kBufferSize = | 2811 const int kBufferSize = |
| 2921 4 * MaxDecimalDigitsIn<sizeof(unsigned)>::kUnsigned // NOLINT | 2812 4 * MaxDecimalDigitsIn<sizeof(unsigned)>::kUnsigned // NOLINT |
| (...skipping 30 matching lines...) Expand all Loading... |
| 2952 buffer[buffer_pos++] = '0'; | 2843 buffer[buffer_pos++] = '0'; |
| 2953 } else { | 2844 } else { |
| 2954 ASSERT(position >= 0); | 2845 ASSERT(position >= 0); |
| 2955 buffer_pos = utoa(static_cast<unsigned>(position + 1), buffer, buffer_pos); | 2846 buffer_pos = utoa(static_cast<unsigned>(position + 1), buffer, buffer_pos); |
| 2956 } | 2847 } |
| 2957 return buffer_pos; | 2848 return buffer_pos; |
| 2958 } | 2849 } |
| 2959 | 2850 |
| 2960 | 2851 |
| 2961 void HeapSnapshotJSONSerializer::SerializeTraceNodeInfos() { | 2852 void HeapSnapshotJSONSerializer::SerializeTraceNodeInfos() { |
| 2962 AllocationTracker* tracker = snapshot_->collection()->allocation_tracker(); | 2853 AllocationTracker* tracker = snapshot_->profiler()->allocation_tracker(); |
| 2963 if (!tracker) return; | 2854 if (!tracker) return; |
| 2964 // The buffer needs space for 6 unsigned ints, 6 commas, \n and \0 | 2855 // The buffer needs space for 6 unsigned ints, 6 commas, \n and \0 |
| 2965 const int kBufferSize = | 2856 const int kBufferSize = |
| 2966 6 * MaxDecimalDigitsIn<sizeof(unsigned)>::kUnsigned // NOLINT | 2857 6 * MaxDecimalDigitsIn<sizeof(unsigned)>::kUnsigned // NOLINT |
| 2967 + 6 + 1 + 1; | 2858 + 6 + 1 + 1; |
| 2968 EmbeddedVector<char, kBufferSize> buffer; | 2859 EmbeddedVector<char, kBufferSize> buffer; |
| 2969 HashMap* id_to_function_info = tracker->id_to_function_info(); | 2860 HashMap* id_to_function_info = tracker->id_to_function_info(); |
| 2970 bool first_entry = true; | 2861 bool first_entry = true; |
| 2971 for (HashMap::Entry* p = id_to_function_info->Start(); | 2862 for (HashMap::Entry* p = id_to_function_info->Start(); |
| 2972 p != NULL; | 2863 p != NULL; |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3063 writer_->AddString("\"<dummy>\""); | 2954 writer_->AddString("\"<dummy>\""); |
| 3064 for (int i = 1; i < sorted_strings.length(); ++i) { | 2955 for (int i = 1; i < sorted_strings.length(); ++i) { |
| 3065 writer_->AddCharacter(','); | 2956 writer_->AddCharacter(','); |
| 3066 SerializeString(sorted_strings[i]); | 2957 SerializeString(sorted_strings[i]); |
| 3067 if (writer_->aborted()) return; | 2958 if (writer_->aborted()) return; |
| 3068 } | 2959 } |
| 3069 } | 2960 } |
| 3070 | 2961 |
| 3071 | 2962 |
| 3072 } } // namespace v8::internal | 2963 } } // namespace v8::internal |
| OLD | NEW |