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 |