| 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 |
| 206 HeapSnapshot::HeapSnapshot(HeapProfiler* profiler, |
| 206 const char* title, | 207 const char* title, |
| 207 unsigned uid) | 208 unsigned uid) |
| 208 : collection_(collection), | 209 : profiler_(profiler), |
| 209 title_(title), | 210 title_(title), |
| 210 uid_(uid), | 211 uid_(uid), |
| 211 root_index_(HeapEntry::kNoEntry), | 212 root_index_(HeapEntry::kNoEntry), |
| 212 gc_roots_index_(HeapEntry::kNoEntry), | 213 gc_roots_index_(HeapEntry::kNoEntry), |
| 213 natives_root_index_(HeapEntry::kNoEntry), | 214 natives_root_index_(HeapEntry::kNoEntry), |
| 214 max_snapshot_js_object_id_(0) { | 215 max_snapshot_js_object_id_(0) { |
| 215 STATIC_CHECK( | 216 STATIC_CHECK( |
| 216 sizeof(HeapGraphEdge) == | 217 sizeof(HeapGraphEdge) == |
| 217 SnapshotSizeConstants<kPointerSize>::kExpectedHeapGraphEdgeSize); | 218 SnapshotSizeConstants<kPointerSize>::kExpectedHeapGraphEdgeSize); |
| 218 STATIC_CHECK( | 219 STATIC_CHECK( |
| 219 sizeof(HeapEntry) == | 220 sizeof(HeapEntry) == |
| 220 SnapshotSizeConstants<kPointerSize>::kExpectedHeapEntrySize); | 221 SnapshotSizeConstants<kPointerSize>::kExpectedHeapEntrySize); |
| 222 USE(SnapshotSizeConstants<4>::kExpectedHeapGraphEdgeSize); |
| 223 USE(SnapshotSizeConstants<4>::kExpectedHeapEntrySize); |
| 224 USE(SnapshotSizeConstants<8>::kExpectedHeapGraphEdgeSize); |
| 225 USE(SnapshotSizeConstants<8>::kExpectedHeapEntrySize); |
| 221 for (int i = 0; i < VisitorSynchronization::kNumberOfSyncTags; ++i) { | 226 for (int i = 0; i < VisitorSynchronization::kNumberOfSyncTags; ++i) { |
| 222 gc_subroot_indexes_[i] = HeapEntry::kNoEntry; | 227 gc_subroot_indexes_[i] = HeapEntry::kNoEntry; |
| 223 } | 228 } |
| 224 } | 229 } |
| 225 | 230 |
| 226 | 231 |
| 227 void HeapSnapshot::Delete() { | 232 void HeapSnapshot::Delete() { |
| 228 collection_->RemoveSnapshot(this); | 233 profiler_->RemoveSnapshot(this); |
| 229 delete this; | 234 delete this; |
| 230 } | 235 } |
| 231 | 236 |
| 232 | 237 |
| 233 void HeapSnapshot::RememberLastJSObjectId() { | 238 void HeapSnapshot::RememberLastJSObjectId() { |
| 234 max_snapshot_js_object_id_ = collection_->last_assigned_id(); | 239 max_snapshot_js_object_id_ = profiler_->heap_object_map()->last_assigned_id(); |
| 235 } | 240 } |
| 236 | 241 |
| 237 | 242 |
| 238 HeapEntry* HeapSnapshot::AddRootEntry() { | 243 HeapEntry* HeapSnapshot::AddRootEntry() { |
| 239 ASSERT(root_index_ == HeapEntry::kNoEntry); | 244 ASSERT(root_index_ == HeapEntry::kNoEntry); |
| 240 ASSERT(entries_.is_empty()); // Root entry must be the first one. | 245 ASSERT(entries_.is_empty()); // Root entry must be the first one. |
| 241 HeapEntry* entry = AddEntry(HeapEntry::kSynthetic, | 246 HeapEntry* entry = AddEntry(HeapEntry::kSynthetic, |
| 242 "", | 247 "", |
| 243 HeapObjectsMap::kInternalRootObjectId, | 248 HeapObjectsMap::kInternalRootObjectId, |
| 244 0); | 249 0); |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 339 } | 344 } |
| 340 return &sorted_entries_; | 345 return &sorted_entries_; |
| 341 } | 346 } |
| 342 | 347 |
| 343 | 348 |
| 344 void HeapSnapshot::Print(int max_depth) { | 349 void HeapSnapshot::Print(int max_depth) { |
| 345 root()->Print("", "", max_depth, 0); | 350 root()->Print("", "", max_depth, 0); |
| 346 } | 351 } |
| 347 | 352 |
| 348 | 353 |
| 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 { | 354 size_t HeapSnapshot::RawSnapshotSize() const { |
| 356 return | 355 return |
| 357 sizeof(*this) + | 356 sizeof(*this) + |
| 358 GetMemoryUsedByList(entries_) + | 357 GetMemoryUsedByList(entries_) + |
| 359 GetMemoryUsedByList(edges_) + | 358 GetMemoryUsedByList(edges_) + |
| 360 GetMemoryUsedByList(children_) + | 359 GetMemoryUsedByList(children_) + |
| 361 GetMemoryUsedByList(sorted_entries_); | 360 GetMemoryUsedByList(sorted_entries_); |
| 362 } | 361 } |
| 363 | 362 |
| 364 | 363 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 387 // When we do lookup in HashMap we see no difference between two cases: | 386 // 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 | 387 // 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. | 388 // 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 | 389 // With such dummy element we have a guaranty that all entries_map_ entries |
| 391 // will have the value field grater than 0. | 390 // will have the value field grater than 0. |
| 392 // This fact is using in MoveObject method. | 391 // This fact is using in MoveObject method. |
| 393 entries_.Add(EntryInfo(0, NULL, 0)); | 392 entries_.Add(EntryInfo(0, NULL, 0)); |
| 394 } | 393 } |
| 395 | 394 |
| 396 | 395 |
| 397 void HeapObjectsMap::SnapshotGenerationFinished() { | |
| 398 RemoveDeadEntries(); | |
| 399 } | |
| 400 | |
| 401 | |
| 402 void HeapObjectsMap::MoveObject(Address from, Address to, int object_size) { | 396 void HeapObjectsMap::MoveObject(Address from, Address to, int object_size) { |
| 403 ASSERT(to != NULL); | 397 ASSERT(to != NULL); |
| 404 ASSERT(from != NULL); | 398 ASSERT(from != NULL); |
| 405 if (from == to) return; | 399 if (from == to) return; |
| 406 void* from_value = entries_map_.Remove(from, ComputePointerHash(from)); | 400 void* from_value = entries_map_.Remove(from, ComputePointerHash(from)); |
| 407 if (from_value == NULL) { | 401 if (from_value == NULL) { |
| 408 // It may occur that some untracked object moves to an address X and there | 402 // 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 | 403 // is a tracked object at that address. In this case we should remove the |
| 410 // entry as we know that the object has died. | 404 // entry as we know that the object has died. |
| 411 void* to_value = entries_map_.Remove(to, ComputePointerHash(to)); | 405 void* to_value = entries_map_.Remove(to, ComputePointerHash(to)); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 439 to, | 433 to, |
| 440 entries_.at(from_entry_info_index).size, | 434 entries_.at(from_entry_info_index).size, |
| 441 object_size); | 435 object_size); |
| 442 } | 436 } |
| 443 entries_.at(from_entry_info_index).size = object_size; | 437 entries_.at(from_entry_info_index).size = object_size; |
| 444 to_entry->value = from_value; | 438 to_entry->value = from_value; |
| 445 } | 439 } |
| 446 } | 440 } |
| 447 | 441 |
| 448 | 442 |
| 449 void HeapObjectsMap::NewObject(Address addr, int size) { | |
| 450 if (FLAG_heap_profiler_trace_objects) { | |
| 451 PrintF("New object : %p %6d. Next address is %p\n", | |
| 452 addr, | |
| 453 size, | |
| 454 addr + size); | |
| 455 } | |
| 456 ASSERT(addr != NULL); | |
| 457 FindOrAddEntry(addr, size, false); | |
| 458 } | |
| 459 | |
| 460 | |
| 461 void HeapObjectsMap::UpdateObjectSize(Address addr, int size) { | 443 void HeapObjectsMap::UpdateObjectSize(Address addr, int size) { |
| 462 FindOrAddEntry(addr, size, false); | 444 FindOrAddEntry(addr, size, false); |
| 463 } | 445 } |
| 464 | 446 |
| 465 | 447 |
| 466 SnapshotObjectId HeapObjectsMap::FindEntry(Address addr) { | 448 SnapshotObjectId HeapObjectsMap::FindEntry(Address addr) { |
| 467 HashMap::Entry* entry = entries_map_.Lookup(addr, ComputePointerHash(addr), | 449 HashMap::Entry* entry = entries_map_.Lookup(addr, ComputePointerHash(addr), |
| 468 false); | 450 false); |
| 469 if (entry == NULL) return 0; | 451 if (entry == NULL) return 0; |
| 470 int entry_index = static_cast<int>(reinterpret_cast<intptr_t>(entry->value)); | 452 int entry_index = static_cast<int>(reinterpret_cast<intptr_t>(entry->value)); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 507 time_intervals_.Clear(); | 489 time_intervals_.Clear(); |
| 508 } | 490 } |
| 509 | 491 |
| 510 | 492 |
| 511 void HeapObjectsMap::UpdateHeapObjectsMap() { | 493 void HeapObjectsMap::UpdateHeapObjectsMap() { |
| 512 if (FLAG_heap_profiler_trace_objects) { | 494 if (FLAG_heap_profiler_trace_objects) { |
| 513 PrintF("Begin HeapObjectsMap::UpdateHeapObjectsMap. map has %d entries.\n", | 495 PrintF("Begin HeapObjectsMap::UpdateHeapObjectsMap. map has %d entries.\n", |
| 514 entries_map_.occupancy()); | 496 entries_map_.occupancy()); |
| 515 } | 497 } |
| 516 heap_->CollectAllGarbage(Heap::kMakeHeapIterableMask, | 498 heap_->CollectAllGarbage(Heap::kMakeHeapIterableMask, |
| 517 "HeapSnapshotsCollection::UpdateHeapObjectsMap"); | 499 "HeapObjectsMap::UpdateHeapObjectsMap"); |
| 518 HeapIterator iterator(heap_); | 500 HeapIterator iterator(heap_); |
| 519 for (HeapObject* obj = iterator.next(); | 501 for (HeapObject* obj = iterator.next(); |
| 520 obj != NULL; | 502 obj != NULL; |
| 521 obj = iterator.next()) { | 503 obj = iterator.next()) { |
| 522 FindOrAddEntry(obj->address(), obj->Size()); | 504 FindOrAddEntry(obj->address(), obj->Size()); |
| 523 if (FLAG_heap_profiler_trace_objects) { | 505 if (FLAG_heap_profiler_trace_objects) { |
| 524 PrintF("Update object : %p %6d. Next address is %p\n", | 506 PrintF("Update object : %p %6d. Next address is %p\n", |
| 525 obj->address(), | 507 obj->address(), |
| 526 obj->Size(), | 508 obj->Size(), |
| 527 obj->address() + obj->Size()); | 509 obj->address() + obj->Size()); |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 715 ComputePointerHash(entry_info.addr)); | 697 ComputePointerHash(entry_info.addr)); |
| 716 } | 698 } |
| 717 } | 699 } |
| 718 } | 700 } |
| 719 entries_.Rewind(first_free_entry); | 701 entries_.Rewind(first_free_entry); |
| 720 ASSERT(static_cast<uint32_t>(entries_.length()) - 1 == | 702 ASSERT(static_cast<uint32_t>(entries_.length()) - 1 == |
| 721 entries_map_.occupancy()); | 703 entries_map_.occupancy()); |
| 722 } | 704 } |
| 723 | 705 |
| 724 | 706 |
| 725 SnapshotObjectId HeapObjectsMap::GenerateId(Heap* heap, | 707 SnapshotObjectId HeapObjectsMap::GenerateId(v8::RetainedObjectInfo* info) { |
| 726 v8::RetainedObjectInfo* info) { | |
| 727 SnapshotObjectId id = static_cast<SnapshotObjectId>(info->GetHash()); | 708 SnapshotObjectId id = static_cast<SnapshotObjectId>(info->GetHash()); |
| 728 const char* label = info->GetLabel(); | 709 const char* label = info->GetLabel(); |
| 729 id ^= StringHasher::HashSequentialString(label, | 710 id ^= StringHasher::HashSequentialString(label, |
| 730 static_cast<int>(strlen(label)), | 711 static_cast<int>(strlen(label)), |
| 731 heap->HashSeed()); | 712 heap_->HashSeed()); |
| 732 intptr_t element_count = info->GetElementCount(); | 713 intptr_t element_count = info->GetElementCount(); |
| 733 if (element_count != -1) | 714 if (element_count != -1) |
| 734 id ^= ComputeIntegerHash(static_cast<uint32_t>(element_count), | 715 id ^= ComputeIntegerHash(static_cast<uint32_t>(element_count), |
| 735 v8::internal::kZeroHashSeed); | 716 v8::internal::kZeroHashSeed); |
| 736 return id << 1; | 717 return id << 1; |
| 737 } | 718 } |
| 738 | 719 |
| 739 | 720 |
| 740 size_t HeapObjectsMap::GetUsedMemorySize() const { | 721 size_t HeapObjectsMap::GetUsedMemorySize() const { |
| 741 return | 722 return |
| 742 sizeof(*this) + | 723 sizeof(*this) + |
| 743 sizeof(HashMap::Entry) * entries_map_.capacity() + | 724 sizeof(HashMap::Entry) * entries_map_.capacity() + |
| 744 GetMemoryUsedByList(entries_) + | 725 GetMemoryUsedByList(entries_) + |
| 745 GetMemoryUsedByList(time_intervals_); | 726 GetMemoryUsedByList(time_intervals_); |
| 746 } | 727 } |
| 747 | 728 |
| 748 | 729 |
| 749 HeapSnapshotsCollection::HeapSnapshotsCollection(Heap* heap) | |
| 750 : is_tracking_objects_(false), | |
| 751 names_(heap), | |
| 752 ids_(heap), | |
| 753 allocation_tracker_(NULL) { | |
| 754 } | |
| 755 | |
| 756 | |
| 757 static void DeleteHeapSnapshot(HeapSnapshot** snapshot_ptr) { | |
| 758 delete *snapshot_ptr; | |
| 759 } | |
| 760 | |
| 761 | |
| 762 HeapSnapshotsCollection::~HeapSnapshotsCollection() { | |
| 763 delete allocation_tracker_; | |
| 764 snapshots_.Iterate(DeleteHeapSnapshot); | |
| 765 } | |
| 766 | |
| 767 | |
| 768 void HeapSnapshotsCollection::StartHeapObjectsTracking() { | |
| 769 ids_.UpdateHeapObjectsMap(); | |
| 770 if (allocation_tracker_ == NULL) { | |
| 771 allocation_tracker_ = new AllocationTracker(&ids_, names()); | |
| 772 } | |
| 773 is_tracking_objects_ = true; | |
| 774 } | |
| 775 | |
| 776 | |
| 777 void HeapSnapshotsCollection::StopHeapObjectsTracking() { | |
| 778 ids_.StopHeapObjectsTracking(); | |
| 779 if (allocation_tracker_ != NULL) { | |
| 780 delete allocation_tracker_; | |
| 781 allocation_tracker_ = NULL; | |
| 782 } | |
| 783 } | |
| 784 | |
| 785 | |
| 786 HeapSnapshot* HeapSnapshotsCollection::NewSnapshot(const char* name, | |
| 787 unsigned uid) { | |
| 788 is_tracking_objects_ = true; // Start watching for heap objects moves. | |
| 789 return new HeapSnapshot(this, name, uid); | |
| 790 } | |
| 791 | |
| 792 | |
| 793 void HeapSnapshotsCollection::SnapshotGenerationFinished( | |
| 794 HeapSnapshot* snapshot) { | |
| 795 ids_.SnapshotGenerationFinished(); | |
| 796 if (snapshot != NULL) { | |
| 797 snapshots_.Add(snapshot); | |
| 798 } | |
| 799 } | |
| 800 | |
| 801 | |
| 802 void HeapSnapshotsCollection::RemoveSnapshot(HeapSnapshot* snapshot) { | |
| 803 snapshots_.RemoveElement(snapshot); | |
| 804 } | |
| 805 | |
| 806 | |
| 807 Handle<HeapObject> HeapSnapshotsCollection::FindHeapObjectById( | |
| 808 SnapshotObjectId id) { | |
| 809 // First perform a full GC in order to avoid dead objects. | |
| 810 heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask, | |
| 811 "HeapSnapshotsCollection::FindHeapObjectById"); | |
| 812 DisallowHeapAllocation no_allocation; | |
| 813 HeapObject* object = NULL; | |
| 814 HeapIterator iterator(heap(), HeapIterator::kFilterUnreachable); | |
| 815 // Make sure that object with the given id is still reachable. | |
| 816 for (HeapObject* obj = iterator.next(); | |
| 817 obj != NULL; | |
| 818 obj = iterator.next()) { | |
| 819 if (ids_.FindEntry(obj->address()) == id) { | |
| 820 ASSERT(object == NULL); | |
| 821 object = obj; | |
| 822 // Can't break -- kFilterUnreachable requires full heap traversal. | |
| 823 } | |
| 824 } | |
| 825 return object != NULL ? Handle<HeapObject>(object) : Handle<HeapObject>(); | |
| 826 } | |
| 827 | |
| 828 | |
| 829 void HeapSnapshotsCollection::NewObjectEvent(Address addr, int size) { | |
| 830 DisallowHeapAllocation no_allocation; | |
| 831 ids_.NewObject(addr, size); | |
| 832 if (allocation_tracker_ != NULL) { | |
| 833 allocation_tracker_->NewObjectEvent(addr, size); | |
| 834 } | |
| 835 } | |
| 836 | |
| 837 | |
| 838 size_t HeapSnapshotsCollection::GetUsedMemorySize() const { | |
| 839 size_t size = sizeof(*this); | |
| 840 size += names_.GetUsedMemorySize(); | |
| 841 size += ids_.GetUsedMemorySize(); | |
| 842 size += GetMemoryUsedByList(snapshots_); | |
| 843 for (int i = 0; i < snapshots_.length(); ++i) { | |
| 844 size += snapshots_[i]->RawSnapshotSize(); | |
| 845 } | |
| 846 return size; | |
| 847 } | |
| 848 | |
| 849 | |
| 850 HeapEntriesMap::HeapEntriesMap() | 730 HeapEntriesMap::HeapEntriesMap() |
| 851 : entries_(HeapThingsMatch) { | 731 : entries_(HeapThingsMatch) { |
| 852 } | 732 } |
| 853 | 733 |
| 854 | 734 |
| 855 int HeapEntriesMap::Map(HeapThing thing) { | 735 int HeapEntriesMap::Map(HeapThing thing) { |
| 856 HashMap::Entry* cache_entry = entries_.Lookup(thing, Hash(thing), false); | 736 HashMap::Entry* cache_entry = entries_.Lookup(thing, Hash(thing), false); |
| 857 if (cache_entry == NULL) return HeapEntry::kNoEntry; | 737 if (cache_entry == NULL) return HeapEntry::kNoEntry; |
| 858 return static_cast<int>(reinterpret_cast<intptr_t>(cache_entry->value)); | 738 return static_cast<int>(reinterpret_cast<intptr_t>(cache_entry->value)); |
| 859 } | 739 } |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 920 static_cast<intptr_t>(HeapObjectsMap::kGcRootsFirstSubrootId)); | 800 static_cast<intptr_t>(HeapObjectsMap::kGcRootsFirstSubrootId)); |
| 921 HeapObject* const V8HeapExplorer::kLastGcSubrootObject = | 801 HeapObject* const V8HeapExplorer::kLastGcSubrootObject = |
| 922 reinterpret_cast<HeapObject*>( | 802 reinterpret_cast<HeapObject*>( |
| 923 static_cast<intptr_t>(HeapObjectsMap::kFirstAvailableObjectId)); | 803 static_cast<intptr_t>(HeapObjectsMap::kFirstAvailableObjectId)); |
| 924 | 804 |
| 925 | 805 |
| 926 V8HeapExplorer::V8HeapExplorer( | 806 V8HeapExplorer::V8HeapExplorer( |
| 927 HeapSnapshot* snapshot, | 807 HeapSnapshot* snapshot, |
| 928 SnapshottingProgressReportingInterface* progress, | 808 SnapshottingProgressReportingInterface* progress, |
| 929 v8::HeapProfiler::ObjectNameResolver* resolver) | 809 v8::HeapProfiler::ObjectNameResolver* resolver) |
| 930 : heap_(snapshot->collection()->heap()), | 810 : heap_(snapshot->profiler()->heap_object_map()->heap()), |
| 931 snapshot_(snapshot), | 811 snapshot_(snapshot), |
| 932 collection_(snapshot_->collection()), | 812 names_(snapshot_->profiler()->names()), |
| 813 heap_object_map_(snapshot_->profiler()->heap_object_map()), |
| 933 progress_(progress), | 814 progress_(progress), |
| 934 filler_(NULL), | 815 filler_(NULL), |
| 935 global_object_name_resolver_(resolver) { | 816 global_object_name_resolver_(resolver) { |
| 936 } | 817 } |
| 937 | 818 |
| 938 | 819 |
| 939 V8HeapExplorer::~V8HeapExplorer() { | 820 V8HeapExplorer::~V8HeapExplorer() { |
| 940 } | 821 } |
| 941 | 822 |
| 942 | 823 |
| 943 HeapEntry* V8HeapExplorer::AllocateEntry(HeapThing ptr) { | 824 HeapEntry* V8HeapExplorer::AllocateEntry(HeapThing ptr) { |
| 944 return AddEntry(reinterpret_cast<HeapObject*>(ptr)); | 825 return AddEntry(reinterpret_cast<HeapObject*>(ptr)); |
| 945 } | 826 } |
| 946 | 827 |
| 947 | 828 |
| 948 HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object) { | 829 HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object) { |
| 949 if (object == kInternalRootObject) { | 830 if (object == kInternalRootObject) { |
| 950 snapshot_->AddRootEntry(); | 831 snapshot_->AddRootEntry(); |
| 951 return snapshot_->root(); | 832 return snapshot_->root(); |
| 952 } else if (object == kGcRootsObject) { | 833 } else if (object == kGcRootsObject) { |
| 953 HeapEntry* entry = snapshot_->AddGcRootsEntry(); | 834 HeapEntry* entry = snapshot_->AddGcRootsEntry(); |
| 954 return entry; | 835 return entry; |
| 955 } else if (object >= kFirstGcSubrootObject && object < kLastGcSubrootObject) { | 836 } else if (object >= kFirstGcSubrootObject && object < kLastGcSubrootObject) { |
| 956 HeapEntry* entry = snapshot_->AddGcSubrootEntry(GetGcSubrootOrder(object)); | 837 HeapEntry* entry = snapshot_->AddGcSubrootEntry(GetGcSubrootOrder(object)); |
| 957 return entry; | 838 return entry; |
| 958 } else if (object->IsJSFunction()) { | 839 } else if (object->IsJSFunction()) { |
| 959 JSFunction* func = JSFunction::cast(object); | 840 JSFunction* func = JSFunction::cast(object); |
| 960 SharedFunctionInfo* shared = func->shared(); | 841 SharedFunctionInfo* shared = func->shared(); |
| 961 const char* name = shared->bound() ? "native_bind" : | 842 const char* name = shared->bound() ? "native_bind" : |
| 962 collection_->names()->GetName(String::cast(shared->name())); | 843 names_->GetName(String::cast(shared->name())); |
| 963 return AddEntry(object, HeapEntry::kClosure, name); | 844 return AddEntry(object, HeapEntry::kClosure, name); |
| 964 } else if (object->IsJSRegExp()) { | 845 } else if (object->IsJSRegExp()) { |
| 965 JSRegExp* re = JSRegExp::cast(object); | 846 JSRegExp* re = JSRegExp::cast(object); |
| 966 return AddEntry(object, | 847 return AddEntry(object, |
| 967 HeapEntry::kRegExp, | 848 HeapEntry::kRegExp, |
| 968 collection_->names()->GetName(re->Pattern())); | 849 names_->GetName(re->Pattern())); |
| 969 } else if (object->IsJSObject()) { | 850 } else if (object->IsJSObject()) { |
| 970 const char* name = collection_->names()->GetName( | 851 const char* name = names_->GetName( |
| 971 GetConstructorName(JSObject::cast(object))); | 852 GetConstructorName(JSObject::cast(object))); |
| 972 if (object->IsJSGlobalObject()) { | 853 if (object->IsJSGlobalObject()) { |
| 973 const char* tag = objects_tags_.GetTag(object); | 854 const char* tag = objects_tags_.GetTag(object); |
| 974 if (tag != NULL) { | 855 if (tag != NULL) { |
| 975 name = collection_->names()->GetFormatted("%s / %s", name, tag); | 856 name = names_->GetFormatted("%s / %s", name, tag); |
| 976 } | 857 } |
| 977 } | 858 } |
| 978 return AddEntry(object, HeapEntry::kObject, name); | 859 return AddEntry(object, HeapEntry::kObject, name); |
| 979 } else if (object->IsString()) { | 860 } else if (object->IsString()) { |
| 980 String* string = String::cast(object); | 861 String* string = String::cast(object); |
| 981 if (string->IsConsString()) | 862 if (string->IsConsString()) |
| 982 return AddEntry(object, | 863 return AddEntry(object, |
| 983 HeapEntry::kConsString, | 864 HeapEntry::kConsString, |
| 984 "(concatenated string)"); | 865 "(concatenated string)"); |
| 985 if (string->IsSlicedString()) | 866 if (string->IsSlicedString()) |
| 986 return AddEntry(object, | 867 return AddEntry(object, |
| 987 HeapEntry::kSlicedString, | 868 HeapEntry::kSlicedString, |
| 988 "(sliced string)"); | 869 "(sliced string)"); |
| 989 return AddEntry(object, | 870 return AddEntry(object, |
| 990 HeapEntry::kString, | 871 HeapEntry::kString, |
| 991 collection_->names()->GetName(String::cast(object))); | 872 names_->GetName(String::cast(object))); |
| 992 } else if (object->IsCode()) { | 873 } else if (object->IsCode()) { |
| 993 return AddEntry(object, HeapEntry::kCode, ""); | 874 return AddEntry(object, HeapEntry::kCode, ""); |
| 994 } else if (object->IsSharedFunctionInfo()) { | 875 } else if (object->IsSharedFunctionInfo()) { |
| 995 String* name = String::cast(SharedFunctionInfo::cast(object)->name()); | 876 String* name = String::cast(SharedFunctionInfo::cast(object)->name()); |
| 996 return AddEntry(object, | 877 return AddEntry(object, |
| 997 HeapEntry::kCode, | 878 HeapEntry::kCode, |
| 998 collection_->names()->GetName(name)); | 879 names_->GetName(name)); |
| 999 } else if (object->IsScript()) { | 880 } else if (object->IsScript()) { |
| 1000 Object* name = Script::cast(object)->name(); | 881 Object* name = Script::cast(object)->name(); |
| 1001 return AddEntry(object, | 882 return AddEntry(object, |
| 1002 HeapEntry::kCode, | 883 HeapEntry::kCode, |
| 1003 name->IsString() | 884 name->IsString() |
| 1004 ? collection_->names()->GetName(String::cast(name)) | 885 ? names_->GetName(String::cast(name)) |
| 1005 : ""); | 886 : ""); |
| 1006 } else if (object->IsNativeContext()) { | 887 } else if (object->IsNativeContext()) { |
| 1007 return AddEntry(object, HeapEntry::kHidden, "system / NativeContext"); | 888 return AddEntry(object, HeapEntry::kHidden, "system / NativeContext"); |
| 1008 } else if (object->IsContext()) { | 889 } else if (object->IsContext()) { |
| 1009 return AddEntry(object, HeapEntry::kObject, "system / Context"); | 890 return AddEntry(object, HeapEntry::kObject, "system / Context"); |
| 1010 } else if (object->IsFixedArray() || | 891 } else if (object->IsFixedArray() || |
| 1011 object->IsFixedDoubleArray() || | 892 object->IsFixedDoubleArray() || |
| 1012 object->IsByteArray() || | 893 object->IsByteArray() || |
| 1013 object->IsExternalArray()) { | 894 object->IsExternalArray()) { |
| 1014 return AddEntry(object, HeapEntry::kArray, ""); | 895 return AddEntry(object, HeapEntry::kArray, ""); |
| 1015 } else if (object->IsHeapNumber()) { | 896 } else if (object->IsHeapNumber()) { |
| 1016 return AddEntry(object, HeapEntry::kHeapNumber, "number"); | 897 return AddEntry(object, HeapEntry::kHeapNumber, "number"); |
| 1017 } | 898 } |
| 1018 return AddEntry(object, HeapEntry::kHidden, GetSystemEntryName(object)); | 899 return AddEntry(object, HeapEntry::kHidden, GetSystemEntryName(object)); |
| 1019 } | 900 } |
| 1020 | 901 |
| 1021 | 902 |
| 1022 HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object, | 903 HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object, |
| 1023 HeapEntry::Type type, | 904 HeapEntry::Type type, |
| 1024 const char* name) { | 905 const char* name) { |
| 1025 int object_size = object->Size(); | 906 int object_size = object->Size(); |
| 1026 SnapshotObjectId object_id = | 907 SnapshotObjectId object_id = |
| 1027 collection_->GetObjectId(object->address(), object_size); | 908 heap_object_map_->FindOrAddEntry(object->address(), object_size); |
| 1028 return snapshot_->AddEntry(type, name, object_id, object_size); | 909 return snapshot_->AddEntry(type, name, object_id, object_size); |
| 1029 } | 910 } |
| 1030 | 911 |
| 1031 | 912 |
| 1032 class GcSubrootsEnumerator : public ObjectVisitor { | 913 class GcSubrootsEnumerator : public ObjectVisitor { |
| 1033 public: | 914 public: |
| 1034 GcSubrootsEnumerator( | 915 GcSubrootsEnumerator( |
| 1035 SnapshotFillerInterface* filler, V8HeapExplorer* explorer) | 916 SnapshotFillerInterface* filler, V8HeapExplorer* explorer) |
| 1036 : filler_(filler), | 917 : filler_(filler), |
| 1037 explorer_(explorer), | 918 explorer_(explorer), |
| (...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1364 TagObject(map->dependent_code(), "(dependent code)"); | 1245 TagObject(map->dependent_code(), "(dependent code)"); |
| 1365 SetInternalReference(map, entry, | 1246 SetInternalReference(map, entry, |
| 1366 "dependent_code", map->dependent_code(), | 1247 "dependent_code", map->dependent_code(), |
| 1367 Map::kDependentCodeOffset); | 1248 Map::kDependentCodeOffset); |
| 1368 } | 1249 } |
| 1369 | 1250 |
| 1370 | 1251 |
| 1371 void V8HeapExplorer::ExtractSharedFunctionInfoReferences( | 1252 void V8HeapExplorer::ExtractSharedFunctionInfoReferences( |
| 1372 int entry, SharedFunctionInfo* shared) { | 1253 int entry, SharedFunctionInfo* shared) { |
| 1373 HeapObject* obj = shared; | 1254 HeapObject* obj = shared; |
| 1374 StringsStorage* names = collection_->names(); | |
| 1375 String* shared_name = shared->DebugName(); | 1255 String* shared_name = shared->DebugName(); |
| 1376 const char* name = NULL; | 1256 const char* name = NULL; |
| 1377 if (shared_name != *heap_->isolate()->factory()->empty_string()) { | 1257 if (shared_name != *heap_->isolate()->factory()->empty_string()) { |
| 1378 name = names->GetName(shared_name); | 1258 name = names_->GetName(shared_name); |
| 1379 TagObject(shared->code(), names->GetFormatted("(code for %s)", name)); | 1259 TagObject(shared->code(), names_->GetFormatted("(code for %s)", name)); |
| 1380 } else { | 1260 } else { |
| 1381 TagObject(shared->code(), names->GetFormatted("(%s code)", | 1261 TagObject(shared->code(), names_->GetFormatted("(%s code)", |
| 1382 Code::Kind2String(shared->code()->kind()))); | 1262 Code::Kind2String(shared->code()->kind()))); |
| 1383 } | 1263 } |
| 1384 | 1264 |
| 1385 SetInternalReference(obj, entry, | 1265 SetInternalReference(obj, entry, |
| 1386 "name", shared->name(), | 1266 "name", shared->name(), |
| 1387 SharedFunctionInfo::kNameOffset); | 1267 SharedFunctionInfo::kNameOffset); |
| 1388 SetInternalReference(obj, entry, | 1268 SetInternalReference(obj, entry, |
| 1389 "code", shared->code(), | 1269 "code", shared->code(), |
| 1390 SharedFunctionInfo::kCodeOffset); | 1270 SharedFunctionInfo::kCodeOffset); |
| 1391 TagObject(shared->scope_info(), "(function scope info)"); | 1271 TagObject(shared->scope_info(), "(function scope info)"); |
| 1392 SetInternalReference(obj, entry, | 1272 SetInternalReference(obj, entry, |
| 1393 "scope_info", shared->scope_info(), | 1273 "scope_info", shared->scope_info(), |
| 1394 SharedFunctionInfo::kScopeInfoOffset); | 1274 SharedFunctionInfo::kScopeInfoOffset); |
| 1395 SetInternalReference(obj, entry, | 1275 SetInternalReference(obj, entry, |
| 1396 "instance_class_name", shared->instance_class_name(), | 1276 "instance_class_name", shared->instance_class_name(), |
| 1397 SharedFunctionInfo::kInstanceClassNameOffset); | 1277 SharedFunctionInfo::kInstanceClassNameOffset); |
| 1398 SetInternalReference(obj, entry, | 1278 SetInternalReference(obj, entry, |
| 1399 "script", shared->script(), | 1279 "script", shared->script(), |
| 1400 SharedFunctionInfo::kScriptOffset); | 1280 SharedFunctionInfo::kScriptOffset); |
| 1401 const char* construct_stub_name = name ? | 1281 const char* construct_stub_name = name ? |
| 1402 names->GetFormatted("(construct stub code for %s)", name) : | 1282 names_->GetFormatted("(construct stub code for %s)", name) : |
| 1403 "(construct stub code)"; | 1283 "(construct stub code)"; |
| 1404 TagObject(shared->construct_stub(), construct_stub_name); | 1284 TagObject(shared->construct_stub(), construct_stub_name); |
| 1405 SetInternalReference(obj, entry, | 1285 SetInternalReference(obj, entry, |
| 1406 "construct_stub", shared->construct_stub(), | 1286 "construct_stub", shared->construct_stub(), |
| 1407 SharedFunctionInfo::kConstructStubOffset); | 1287 SharedFunctionInfo::kConstructStubOffset); |
| 1408 SetInternalReference(obj, entry, | 1288 SetInternalReference(obj, entry, |
| 1409 "function_data", shared->function_data(), | 1289 "function_data", shared->function_data(), |
| 1410 SharedFunctionInfo::kFunctionDataOffset); | 1290 SharedFunctionInfo::kFunctionDataOffset); |
| 1411 SetInternalReference(obj, entry, | 1291 SetInternalReference(obj, entry, |
| 1412 "debug_info", shared->debug_info(), | 1292 "debug_info", shared->debug_info(), |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1460 "default_cache", code_cache->default_cache(), | 1340 "default_cache", code_cache->default_cache(), |
| 1461 CodeCache::kDefaultCacheOffset); | 1341 CodeCache::kDefaultCacheOffset); |
| 1462 TagObject(code_cache->normal_type_cache(), "(code type cache)"); | 1342 TagObject(code_cache->normal_type_cache(), "(code type cache)"); |
| 1463 SetInternalReference(code_cache, entry, | 1343 SetInternalReference(code_cache, entry, |
| 1464 "type_cache", code_cache->normal_type_cache(), | 1344 "type_cache", code_cache->normal_type_cache(), |
| 1465 CodeCache::kNormalTypeCacheOffset); | 1345 CodeCache::kNormalTypeCacheOffset); |
| 1466 } | 1346 } |
| 1467 | 1347 |
| 1468 | 1348 |
| 1469 void V8HeapExplorer::TagCodeObject(Code* code, const char* external_name) { | 1349 void V8HeapExplorer::TagCodeObject(Code* code, const char* external_name) { |
| 1470 TagObject(code, collection_->names()->GetFormatted("(%s code)", | 1350 TagObject(code, names_->GetFormatted("(%s code)", external_name)); |
| 1471 external_name)); | |
| 1472 } | 1351 } |
| 1473 | 1352 |
| 1474 | 1353 |
| 1475 void V8HeapExplorer::TagCodeObject(Code* code) { | 1354 void V8HeapExplorer::TagCodeObject(Code* code) { |
| 1476 if (code->kind() == Code::STUB) { | 1355 if (code->kind() == Code::STUB) { |
| 1477 TagObject(code, collection_->names()->GetFormatted( | 1356 TagObject(code, names_->GetFormatted( |
| 1478 "(%s code)", CodeStub::MajorName( | 1357 "(%s code)", CodeStub::MajorName( |
| 1479 static_cast<CodeStub::Major>(code->major_key()), true))); | 1358 static_cast<CodeStub::Major>(code->major_key()), true))); |
| 1480 } | 1359 } |
| 1481 } | 1360 } |
| 1482 | 1361 |
| 1483 | 1362 |
| 1484 void V8HeapExplorer::ExtractCodeReferences(int entry, Code* code) { | 1363 void V8HeapExplorer::ExtractCodeReferences(int entry, Code* code) { |
| 1485 TagCodeObject(code); | 1364 TagCodeObject(code); |
| 1486 TagObject(code->relocation_info(), "(code relocation info)"); | 1365 TagObject(code->relocation_info(), "(code relocation info)"); |
| 1487 SetInternalReference(code, entry, | 1366 SetInternalReference(code, entry, |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1545 | 1424 |
| 1546 JSFunction* func = JSFunction::cast(js_obj); | 1425 JSFunction* func = JSFunction::cast(js_obj); |
| 1547 if (func->shared()->bound()) { | 1426 if (func->shared()->bound()) { |
| 1548 FixedArray* bindings = func->function_bindings(); | 1427 FixedArray* bindings = func->function_bindings(); |
| 1549 SetNativeBindReference(js_obj, entry, "bound_this", | 1428 SetNativeBindReference(js_obj, entry, "bound_this", |
| 1550 bindings->get(JSFunction::kBoundThisIndex)); | 1429 bindings->get(JSFunction::kBoundThisIndex)); |
| 1551 SetNativeBindReference(js_obj, entry, "bound_function", | 1430 SetNativeBindReference(js_obj, entry, "bound_function", |
| 1552 bindings->get(JSFunction::kBoundFunctionIndex)); | 1431 bindings->get(JSFunction::kBoundFunctionIndex)); |
| 1553 for (int i = JSFunction::kBoundArgumentsStartIndex; | 1432 for (int i = JSFunction::kBoundArgumentsStartIndex; |
| 1554 i < bindings->length(); i++) { | 1433 i < bindings->length(); i++) { |
| 1555 const char* reference_name = collection_->names()->GetFormatted( | 1434 const char* reference_name = names_->GetFormatted( |
| 1556 "bound_argument_%d", | 1435 "bound_argument_%d", |
| 1557 i - JSFunction::kBoundArgumentsStartIndex); | 1436 i - JSFunction::kBoundArgumentsStartIndex); |
| 1558 SetNativeBindReference(js_obj, entry, reference_name, | 1437 SetNativeBindReference(js_obj, entry, reference_name, |
| 1559 bindings->get(i)); | 1438 bindings->get(i)); |
| 1560 } | 1439 } |
| 1561 } | 1440 } |
| 1562 } | 1441 } |
| 1563 | 1442 |
| 1564 | 1443 |
| 1565 void V8HeapExplorer::ExtractPropertyReferences(JSObject* js_obj, int entry) { | 1444 void V8HeapExplorer::ExtractPropertyReferences(JSObject* js_obj, int entry) { |
| (...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1852 void V8HeapExplorer::SetContextReference(HeapObject* parent_obj, | 1731 void V8HeapExplorer::SetContextReference(HeapObject* parent_obj, |
| 1853 int parent_entry, | 1732 int parent_entry, |
| 1854 String* reference_name, | 1733 String* reference_name, |
| 1855 Object* child_obj, | 1734 Object* child_obj, |
| 1856 int field_offset) { | 1735 int field_offset) { |
| 1857 ASSERT(parent_entry == GetEntry(parent_obj)->index()); | 1736 ASSERT(parent_entry == GetEntry(parent_obj)->index()); |
| 1858 HeapEntry* child_entry = GetEntry(child_obj); | 1737 HeapEntry* child_entry = GetEntry(child_obj); |
| 1859 if (child_entry != NULL) { | 1738 if (child_entry != NULL) { |
| 1860 filler_->SetNamedReference(HeapGraphEdge::kContextVariable, | 1739 filler_->SetNamedReference(HeapGraphEdge::kContextVariable, |
| 1861 parent_entry, | 1740 parent_entry, |
| 1862 collection_->names()->GetName(reference_name), | 1741 names_->GetName(reference_name), |
| 1863 child_entry); | 1742 child_entry); |
| 1864 IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset); | 1743 IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset); |
| 1865 } | 1744 } |
| 1866 } | 1745 } |
| 1867 | 1746 |
| 1868 | 1747 |
| 1869 void V8HeapExplorer::SetNativeBindReference(HeapObject* parent_obj, | 1748 void V8HeapExplorer::SetNativeBindReference(HeapObject* parent_obj, |
| 1870 int parent_entry, | 1749 int parent_entry, |
| 1871 const char* reference_name, | 1750 const char* reference_name, |
| 1872 Object* child_obj) { | 1751 Object* child_obj) { |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1918 int parent_entry, | 1797 int parent_entry, |
| 1919 int index, | 1798 int index, |
| 1920 Object* child_obj, | 1799 Object* child_obj, |
| 1921 int field_offset) { | 1800 int field_offset) { |
| 1922 ASSERT(parent_entry == GetEntry(parent_obj)->index()); | 1801 ASSERT(parent_entry == GetEntry(parent_obj)->index()); |
| 1923 HeapEntry* child_entry = GetEntry(child_obj); | 1802 HeapEntry* child_entry = GetEntry(child_obj); |
| 1924 if (child_entry == NULL) return; | 1803 if (child_entry == NULL) return; |
| 1925 if (IsEssentialObject(child_obj)) { | 1804 if (IsEssentialObject(child_obj)) { |
| 1926 filler_->SetNamedReference(HeapGraphEdge::kInternal, | 1805 filler_->SetNamedReference(HeapGraphEdge::kInternal, |
| 1927 parent_entry, | 1806 parent_entry, |
| 1928 collection_->names()->GetName(index), | 1807 names_->GetName(index), |
| 1929 child_entry); | 1808 child_entry); |
| 1930 } | 1809 } |
| 1931 IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset); | 1810 IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset); |
| 1932 } | 1811 } |
| 1933 | 1812 |
| 1934 | 1813 |
| 1935 void V8HeapExplorer::SetHiddenReference(HeapObject* parent_obj, | 1814 void V8HeapExplorer::SetHiddenReference(HeapObject* parent_obj, |
| 1936 int parent_entry, | 1815 int parent_entry, |
| 1937 int index, | 1816 int index, |
| 1938 Object* child_obj) { | 1817 Object* child_obj) { |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1971 Object* child_obj, | 1850 Object* child_obj, |
| 1972 const char* name_format_string, | 1851 const char* name_format_string, |
| 1973 int field_offset) { | 1852 int field_offset) { |
| 1974 ASSERT(parent_entry == GetEntry(parent_obj)->index()); | 1853 ASSERT(parent_entry == GetEntry(parent_obj)->index()); |
| 1975 HeapEntry* child_entry = GetEntry(child_obj); | 1854 HeapEntry* child_entry = GetEntry(child_obj); |
| 1976 if (child_entry != NULL) { | 1855 if (child_entry != NULL) { |
| 1977 HeapGraphEdge::Type type = | 1856 HeapGraphEdge::Type type = |
| 1978 reference_name->IsSymbol() || String::cast(reference_name)->length() > 0 | 1857 reference_name->IsSymbol() || String::cast(reference_name)->length() > 0 |
| 1979 ? HeapGraphEdge::kProperty : HeapGraphEdge::kInternal; | 1858 ? HeapGraphEdge::kProperty : HeapGraphEdge::kInternal; |
| 1980 const char* name = name_format_string != NULL && reference_name->IsString() | 1859 const char* name = name_format_string != NULL && reference_name->IsString() |
| 1981 ? collection_->names()->GetFormatted( | 1860 ? names_->GetFormatted( |
| 1982 name_format_string, | 1861 name_format_string, |
| 1983 *String::cast(reference_name)->ToCString( | 1862 String::cast(reference_name)->ToCString( |
| 1984 DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL)) : | 1863 DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL).get()) : |
| 1985 collection_->names()->GetName(reference_name); | 1864 names_->GetName(reference_name); |
| 1986 | 1865 |
| 1987 filler_->SetNamedReference(type, | 1866 filler_->SetNamedReference(type, |
| 1988 parent_entry, | 1867 parent_entry, |
| 1989 name, | 1868 name, |
| 1990 child_entry); | 1869 child_entry); |
| 1991 IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset); | 1870 IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset); |
| 1992 } | 1871 } |
| 1993 } | 1872 } |
| 1994 | 1873 |
| 1995 | 1874 |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2151 NativeObjectsExplorer* explorer_; | 2030 NativeObjectsExplorer* explorer_; |
| 2152 }; | 2031 }; |
| 2153 | 2032 |
| 2154 | 2033 |
| 2155 class BasicHeapEntriesAllocator : public HeapEntriesAllocator { | 2034 class BasicHeapEntriesAllocator : public HeapEntriesAllocator { |
| 2156 public: | 2035 public: |
| 2157 BasicHeapEntriesAllocator( | 2036 BasicHeapEntriesAllocator( |
| 2158 HeapSnapshot* snapshot, | 2037 HeapSnapshot* snapshot, |
| 2159 HeapEntry::Type entries_type) | 2038 HeapEntry::Type entries_type) |
| 2160 : snapshot_(snapshot), | 2039 : snapshot_(snapshot), |
| 2161 collection_(snapshot_->collection()), | 2040 names_(snapshot_->profiler()->names()), |
| 2041 heap_object_map_(snapshot_->profiler()->heap_object_map()), |
| 2162 entries_type_(entries_type) { | 2042 entries_type_(entries_type) { |
| 2163 } | 2043 } |
| 2164 virtual HeapEntry* AllocateEntry(HeapThing ptr); | 2044 virtual HeapEntry* AllocateEntry(HeapThing ptr); |
| 2165 private: | 2045 private: |
| 2166 HeapSnapshot* snapshot_; | 2046 HeapSnapshot* snapshot_; |
| 2167 HeapSnapshotsCollection* collection_; | 2047 StringsStorage* names_; |
| 2048 HeapObjectsMap* heap_object_map_; |
| 2168 HeapEntry::Type entries_type_; | 2049 HeapEntry::Type entries_type_; |
| 2169 }; | 2050 }; |
| 2170 | 2051 |
| 2171 | 2052 |
| 2172 HeapEntry* BasicHeapEntriesAllocator::AllocateEntry(HeapThing ptr) { | 2053 HeapEntry* BasicHeapEntriesAllocator::AllocateEntry(HeapThing ptr) { |
| 2173 v8::RetainedObjectInfo* info = reinterpret_cast<v8::RetainedObjectInfo*>(ptr); | 2054 v8::RetainedObjectInfo* info = reinterpret_cast<v8::RetainedObjectInfo*>(ptr); |
| 2174 intptr_t elements = info->GetElementCount(); | 2055 intptr_t elements = info->GetElementCount(); |
| 2175 intptr_t size = info->GetSizeInBytes(); | 2056 intptr_t size = info->GetSizeInBytes(); |
| 2176 const char* name = elements != -1 | 2057 const char* name = elements != -1 |
| 2177 ? collection_->names()->GetFormatted( | 2058 ? names_->GetFormatted( |
| 2178 "%s / %" V8_PTR_PREFIX "d entries", info->GetLabel(), elements) | 2059 "%s / %" V8_PTR_PREFIX "d entries", info->GetLabel(), elements) |
| 2179 : collection_->names()->GetCopy(info->GetLabel()); | 2060 : names_->GetCopy(info->GetLabel()); |
| 2180 return snapshot_->AddEntry( | 2061 return snapshot_->AddEntry( |
| 2181 entries_type_, | 2062 entries_type_, |
| 2182 name, | 2063 name, |
| 2183 HeapObjectsMap::GenerateId(collection_->heap(), info), | 2064 heap_object_map_->GenerateId(info), |
| 2184 size != -1 ? static_cast<int>(size) : 0); | 2065 size != -1 ? static_cast<int>(size) : 0); |
| 2185 } | 2066 } |
| 2186 | 2067 |
| 2187 | 2068 |
| 2188 NativeObjectsExplorer::NativeObjectsExplorer( | 2069 NativeObjectsExplorer::NativeObjectsExplorer( |
| 2189 HeapSnapshot* snapshot, | 2070 HeapSnapshot* snapshot, |
| 2190 SnapshottingProgressReportingInterface* progress) | 2071 SnapshottingProgressReportingInterface* progress) |
| 2191 : isolate_(snapshot->collection()->heap()->isolate()), | 2072 : isolate_(snapshot->profiler()->heap_object_map()->heap()->isolate()), |
| 2192 snapshot_(snapshot), | 2073 snapshot_(snapshot), |
| 2193 collection_(snapshot_->collection()), | 2074 names_(snapshot_->profiler()->names()), |
| 2194 progress_(progress), | 2075 progress_(progress), |
| 2195 embedder_queried_(false), | 2076 embedder_queried_(false), |
| 2196 objects_by_info_(RetainedInfosMatch), | 2077 objects_by_info_(RetainedInfosMatch), |
| 2197 native_groups_(StringsMatch), | 2078 native_groups_(StringsMatch), |
| 2198 filler_(NULL) { | 2079 filler_(NULL) { |
| 2199 synthetic_entries_allocator_ = | 2080 synthetic_entries_allocator_ = |
| 2200 new BasicHeapEntriesAllocator(snapshot, HeapEntry::kSynthetic); | 2081 new BasicHeapEntriesAllocator(snapshot, HeapEntry::kSynthetic); |
| 2201 native_entries_allocator_ = | 2082 native_entries_allocator_ = |
| 2202 new BasicHeapEntriesAllocator(snapshot, HeapEntry::kNative); | 2083 new BasicHeapEntriesAllocator(snapshot, HeapEntry::kNative); |
| 2203 } | 2084 } |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2345 | 2226 |
| 2346 private: | 2227 private: |
| 2347 bool disposed_; | 2228 bool disposed_; |
| 2348 intptr_t hash_; | 2229 intptr_t hash_; |
| 2349 const char* label_; | 2230 const char* label_; |
| 2350 }; | 2231 }; |
| 2351 | 2232 |
| 2352 | 2233 |
| 2353 NativeGroupRetainedObjectInfo* NativeObjectsExplorer::FindOrAddGroupInfo( | 2234 NativeGroupRetainedObjectInfo* NativeObjectsExplorer::FindOrAddGroupInfo( |
| 2354 const char* label) { | 2235 const char* label) { |
| 2355 const char* label_copy = collection_->names()->GetCopy(label); | 2236 const char* label_copy = names_->GetCopy(label); |
| 2356 uint32_t hash = StringHasher::HashSequentialString( | 2237 uint32_t hash = StringHasher::HashSequentialString( |
| 2357 label_copy, | 2238 label_copy, |
| 2358 static_cast<int>(strlen(label_copy)), | 2239 static_cast<int>(strlen(label_copy)), |
| 2359 isolate_->heap()->HashSeed()); | 2240 isolate_->heap()->HashSeed()); |
| 2360 HashMap::Entry* entry = native_groups_.Lookup(const_cast<char*>(label_copy), | 2241 HashMap::Entry* entry = native_groups_.Lookup(const_cast<char*>(label_copy), |
| 2361 hash, true); | 2242 hash, true); |
| 2362 if (entry->value == NULL) { | 2243 if (entry->value == NULL) { |
| 2363 entry->value = new NativeGroupRetainedObjectInfo(label); | 2244 entry->value = new NativeGroupRetainedObjectInfo(label); |
| 2364 } | 2245 } |
| 2365 return static_cast<NativeGroupRetainedObjectInfo*>(entry->value); | 2246 return static_cast<NativeGroupRetainedObjectInfo*>(entry->value); |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2423 isolate->heap_profiler()->ExecuteWrapperClassCallback(class_id, p); | 2304 isolate->heap_profiler()->ExecuteWrapperClassCallback(class_id, p); |
| 2424 if (info == NULL) return; | 2305 if (info == NULL) return; |
| 2425 GetListMaybeDisposeInfo(info)->Add(HeapObject::cast(*p)); | 2306 GetListMaybeDisposeInfo(info)->Add(HeapObject::cast(*p)); |
| 2426 } | 2307 } |
| 2427 | 2308 |
| 2428 | 2309 |
| 2429 class SnapshotFiller : public SnapshotFillerInterface { | 2310 class SnapshotFiller : public SnapshotFillerInterface { |
| 2430 public: | 2311 public: |
| 2431 explicit SnapshotFiller(HeapSnapshot* snapshot, HeapEntriesMap* entries) | 2312 explicit SnapshotFiller(HeapSnapshot* snapshot, HeapEntriesMap* entries) |
| 2432 : snapshot_(snapshot), | 2313 : snapshot_(snapshot), |
| 2433 collection_(snapshot->collection()), | 2314 names_(snapshot->profiler()->names()), |
| 2434 entries_(entries) { } | 2315 entries_(entries) { } |
| 2435 HeapEntry* AddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) { | 2316 HeapEntry* AddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) { |
| 2436 HeapEntry* entry = allocator->AllocateEntry(ptr); | 2317 HeapEntry* entry = allocator->AllocateEntry(ptr); |
| 2437 entries_->Pair(ptr, entry->index()); | 2318 entries_->Pair(ptr, entry->index()); |
| 2438 return entry; | 2319 return entry; |
| 2439 } | 2320 } |
| 2440 HeapEntry* FindEntry(HeapThing ptr) { | 2321 HeapEntry* FindEntry(HeapThing ptr) { |
| 2441 int index = entries_->Map(ptr); | 2322 int index = entries_->Map(ptr); |
| 2442 return index != HeapEntry::kNoEntry ? &snapshot_->entries()[index] : NULL; | 2323 return index != HeapEntry::kNoEntry ? &snapshot_->entries()[index] : NULL; |
| 2443 } | 2324 } |
| (...skipping 22 matching lines...) Expand all Loading... |
| 2466 HeapEntry* parent_entry = &snapshot_->entries()[parent]; | 2347 HeapEntry* parent_entry = &snapshot_->entries()[parent]; |
| 2467 parent_entry->SetNamedReference(type, reference_name, child_entry); | 2348 parent_entry->SetNamedReference(type, reference_name, child_entry); |
| 2468 } | 2349 } |
| 2469 void SetNamedAutoIndexReference(HeapGraphEdge::Type type, | 2350 void SetNamedAutoIndexReference(HeapGraphEdge::Type type, |
| 2470 int parent, | 2351 int parent, |
| 2471 HeapEntry* child_entry) { | 2352 HeapEntry* child_entry) { |
| 2472 HeapEntry* parent_entry = &snapshot_->entries()[parent]; | 2353 HeapEntry* parent_entry = &snapshot_->entries()[parent]; |
| 2473 int index = parent_entry->children_count() + 1; | 2354 int index = parent_entry->children_count() + 1; |
| 2474 parent_entry->SetNamedReference( | 2355 parent_entry->SetNamedReference( |
| 2475 type, | 2356 type, |
| 2476 collection_->names()->GetName(index), | 2357 names_->GetName(index), |
| 2477 child_entry); | 2358 child_entry); |
| 2478 } | 2359 } |
| 2479 | 2360 |
| 2480 private: | 2361 private: |
| 2481 HeapSnapshot* snapshot_; | 2362 HeapSnapshot* snapshot_; |
| 2482 HeapSnapshotsCollection* collection_; | 2363 StringsStorage* names_; |
| 2483 HeapEntriesMap* entries_; | 2364 HeapEntriesMap* entries_; |
| 2484 }; | 2365 }; |
| 2485 | 2366 |
| 2486 | 2367 |
| 2487 HeapSnapshotGenerator::HeapSnapshotGenerator( | 2368 HeapSnapshotGenerator::HeapSnapshotGenerator( |
| 2488 HeapSnapshot* snapshot, | 2369 HeapSnapshot* snapshot, |
| 2489 v8::ActivityControl* control, | 2370 v8::ActivityControl* control, |
| 2490 v8::HeapProfiler::ObjectNameResolver* resolver, | 2371 v8::HeapProfiler::ObjectNameResolver* resolver, |
| 2491 Heap* heap) | 2372 Heap* heap) |
| 2492 : snapshot_(snapshot), | 2373 : snapshot_(snapshot), |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2678 }; | 2559 }; |
| 2679 | 2560 |
| 2680 | 2561 |
| 2681 // type, name|index, to_node. | 2562 // type, name|index, to_node. |
| 2682 const int HeapSnapshotJSONSerializer::kEdgeFieldsCount = 3; | 2563 const int HeapSnapshotJSONSerializer::kEdgeFieldsCount = 3; |
| 2683 // type, name, id, self_size, children_index. | 2564 // type, name, id, self_size, children_index. |
| 2684 const int HeapSnapshotJSONSerializer::kNodeFieldsCount = 5; | 2565 const int HeapSnapshotJSONSerializer::kNodeFieldsCount = 5; |
| 2685 | 2566 |
| 2686 void HeapSnapshotJSONSerializer::Serialize(v8::OutputStream* stream) { | 2567 void HeapSnapshotJSONSerializer::Serialize(v8::OutputStream* stream) { |
| 2687 if (AllocationTracker* allocation_tracker = | 2568 if (AllocationTracker* allocation_tracker = |
| 2688 snapshot_->collection()->allocation_tracker()) { | 2569 snapshot_->profiler()->allocation_tracker()) { |
| 2689 allocation_tracker->PrepareForSerialization(); | 2570 allocation_tracker->PrepareForSerialization(); |
| 2690 } | 2571 } |
| 2691 ASSERT(writer_ == NULL); | 2572 ASSERT(writer_ == NULL); |
| 2692 writer_ = new OutputStreamWriter(stream); | 2573 writer_ = new OutputStreamWriter(stream); |
| 2693 SerializeImpl(); | 2574 SerializeImpl(); |
| 2694 delete writer_; | 2575 delete writer_; |
| 2695 writer_ = NULL; | 2576 writer_ = NULL; |
| 2696 } | 2577 } |
| 2697 | 2578 |
| 2698 | 2579 |
| (...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2897 JSON_S("children")))); | 2778 JSON_S("children")))); |
| 2898 #undef JSON_S | 2779 #undef JSON_S |
| 2899 #undef JSON_O | 2780 #undef JSON_O |
| 2900 #undef JSON_A | 2781 #undef JSON_A |
| 2901 writer_->AddString(",\"node_count\":"); | 2782 writer_->AddString(",\"node_count\":"); |
| 2902 writer_->AddNumber(snapshot_->entries().length()); | 2783 writer_->AddNumber(snapshot_->entries().length()); |
| 2903 writer_->AddString(",\"edge_count\":"); | 2784 writer_->AddString(",\"edge_count\":"); |
| 2904 writer_->AddNumber(snapshot_->edges().length()); | 2785 writer_->AddNumber(snapshot_->edges().length()); |
| 2905 writer_->AddString(",\"trace_function_count\":"); | 2786 writer_->AddString(",\"trace_function_count\":"); |
| 2906 uint32_t count = 0; | 2787 uint32_t count = 0; |
| 2907 AllocationTracker* tracker = snapshot_->collection()->allocation_tracker(); | 2788 AllocationTracker* tracker = snapshot_->profiler()->allocation_tracker(); |
| 2908 if (tracker) { | 2789 if (tracker) { |
| 2909 count = tracker->id_to_function_info()->occupancy(); | 2790 count = tracker->id_to_function_info()->occupancy(); |
| 2910 } | 2791 } |
| 2911 writer_->AddNumber(count); | 2792 writer_->AddNumber(count); |
| 2912 } | 2793 } |
| 2913 | 2794 |
| 2914 | 2795 |
| 2915 static void WriteUChar(OutputStreamWriter* w, unibrow::uchar u) { | 2796 static void WriteUChar(OutputStreamWriter* w, unibrow::uchar u) { |
| 2916 static const char hex_chars[] = "0123456789ABCDEF"; | 2797 static const char hex_chars[] = "0123456789ABCDEF"; |
| 2917 w->AddString("\\u"); | 2798 w->AddString("\\u"); |
| 2918 w->AddCharacter(hex_chars[(u >> 12) & 0xf]); | 2799 w->AddCharacter(hex_chars[(u >> 12) & 0xf]); |
| 2919 w->AddCharacter(hex_chars[(u >> 8) & 0xf]); | 2800 w->AddCharacter(hex_chars[(u >> 8) & 0xf]); |
| 2920 w->AddCharacter(hex_chars[(u >> 4) & 0xf]); | 2801 w->AddCharacter(hex_chars[(u >> 4) & 0xf]); |
| 2921 w->AddCharacter(hex_chars[u & 0xf]); | 2802 w->AddCharacter(hex_chars[u & 0xf]); |
| 2922 } | 2803 } |
| 2923 | 2804 |
| 2924 | 2805 |
| 2925 void HeapSnapshotJSONSerializer::SerializeTraceTree() { | 2806 void HeapSnapshotJSONSerializer::SerializeTraceTree() { |
| 2926 AllocationTracker* tracker = snapshot_->collection()->allocation_tracker(); | 2807 AllocationTracker* tracker = snapshot_->profiler()->allocation_tracker(); |
| 2927 if (!tracker) return; | 2808 if (!tracker) return; |
| 2928 AllocationTraceTree* traces = tracker->trace_tree(); | 2809 AllocationTraceTree* traces = tracker->trace_tree(); |
| 2929 SerializeTraceNode(traces->root()); | 2810 SerializeTraceNode(traces->root()); |
| 2930 } | 2811 } |
| 2931 | 2812 |
| 2932 | 2813 |
| 2933 void HeapSnapshotJSONSerializer::SerializeTraceNode(AllocationTraceNode* node) { | 2814 void HeapSnapshotJSONSerializer::SerializeTraceNode(AllocationTraceNode* node) { |
| 2934 // The buffer needs space for 4 unsigned ints, 4 commas, [ and \0 | 2815 // The buffer needs space for 4 unsigned ints, 4 commas, [ and \0 |
| 2935 const int kBufferSize = | 2816 const int kBufferSize = |
| 2936 4 * MaxDecimalDigitsIn<sizeof(unsigned)>::kUnsigned // NOLINT | 2817 4 * MaxDecimalDigitsIn<sizeof(unsigned)>::kUnsigned // NOLINT |
| (...skipping 30 matching lines...) Expand all Loading... |
| 2967 buffer[buffer_pos++] = '0'; | 2848 buffer[buffer_pos++] = '0'; |
| 2968 } else { | 2849 } else { |
| 2969 ASSERT(position >= 0); | 2850 ASSERT(position >= 0); |
| 2970 buffer_pos = utoa(static_cast<unsigned>(position + 1), buffer, buffer_pos); | 2851 buffer_pos = utoa(static_cast<unsigned>(position + 1), buffer, buffer_pos); |
| 2971 } | 2852 } |
| 2972 return buffer_pos; | 2853 return buffer_pos; |
| 2973 } | 2854 } |
| 2974 | 2855 |
| 2975 | 2856 |
| 2976 void HeapSnapshotJSONSerializer::SerializeTraceNodeInfos() { | 2857 void HeapSnapshotJSONSerializer::SerializeTraceNodeInfos() { |
| 2977 AllocationTracker* tracker = snapshot_->collection()->allocation_tracker(); | 2858 AllocationTracker* tracker = snapshot_->profiler()->allocation_tracker(); |
| 2978 if (!tracker) return; | 2859 if (!tracker) return; |
| 2979 // The buffer needs space for 6 unsigned ints, 6 commas, \n and \0 | 2860 // The buffer needs space for 6 unsigned ints, 6 commas, \n and \0 |
| 2980 const int kBufferSize = | 2861 const int kBufferSize = |
| 2981 6 * MaxDecimalDigitsIn<sizeof(unsigned)>::kUnsigned // NOLINT | 2862 6 * MaxDecimalDigitsIn<sizeof(unsigned)>::kUnsigned // NOLINT |
| 2982 + 6 + 1 + 1; | 2863 + 6 + 1 + 1; |
| 2983 EmbeddedVector<char, kBufferSize> buffer; | 2864 EmbeddedVector<char, kBufferSize> buffer; |
| 2984 HashMap* id_to_function_info = tracker->id_to_function_info(); | 2865 HashMap* id_to_function_info = tracker->id_to_function_info(); |
| 2985 bool first_entry = true; | 2866 bool first_entry = true; |
| 2986 for (HashMap::Entry* p = id_to_function_info->Start(); | 2867 for (HashMap::Entry* p = id_to_function_info->Start(); |
| 2987 p != NULL; | 2868 p != NULL; |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3078 writer_->AddString("\"<dummy>\""); | 2959 writer_->AddString("\"<dummy>\""); |
| 3079 for (int i = 1; i < sorted_strings.length(); ++i) { | 2960 for (int i = 1; i < sorted_strings.length(); ++i) { |
| 3080 writer_->AddCharacter(','); | 2961 writer_->AddCharacter(','); |
| 3081 SerializeString(sorted_strings[i]); | 2962 SerializeString(sorted_strings[i]); |
| 3082 if (writer_->aborted()) return; | 2963 if (writer_->aborted()) return; |
| 3083 } | 2964 } |
| 3084 } | 2965 } |
| 3085 | 2966 |
| 3086 | 2967 |
| 3087 } } // namespace v8::internal | 2968 } } // namespace v8::internal |
| OLD | NEW |