| 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 27 matching lines...) Expand all Loading... |
| 439 to, | 428 to, |
| 440 entries_.at(from_entry_info_index).size, | 429 entries_.at(from_entry_info_index).size, |
| 441 object_size); | 430 object_size); |
| 442 } | 431 } |
| 443 entries_.at(from_entry_info_index).size = object_size; | 432 entries_.at(from_entry_info_index).size = object_size; |
| 444 to_entry->value = from_value; | 433 to_entry->value = from_value; |
| 445 } | 434 } |
| 446 } | 435 } |
| 447 | 436 |
| 448 | 437 |
| 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) { | 438 void HeapObjectsMap::UpdateObjectSize(Address addr, int size) { |
| 462 FindOrAddEntry(addr, size, false); | 439 FindOrAddEntry(addr, size, false); |
| 463 } | 440 } |
| 464 | 441 |
| 465 | 442 |
| 466 SnapshotObjectId HeapObjectsMap::FindEntry(Address addr) { | 443 SnapshotObjectId HeapObjectsMap::FindEntry(Address addr) { |
| 467 HashMap::Entry* entry = entries_map_.Lookup(addr, ComputePointerHash(addr), | 444 HashMap::Entry* entry = entries_map_.Lookup(addr, ComputePointerHash(addr), |
| 468 false); | 445 false); |
| 469 if (entry == NULL) return 0; | 446 if (entry == NULL) return 0; |
| 470 int entry_index = static_cast<int>(reinterpret_cast<intptr_t>(entry->value)); | 447 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(); | 484 time_intervals_.Clear(); |
| 508 } | 485 } |
| 509 | 486 |
| 510 | 487 |
| 511 void HeapObjectsMap::UpdateHeapObjectsMap() { | 488 void HeapObjectsMap::UpdateHeapObjectsMap() { |
| 512 if (FLAG_heap_profiler_trace_objects) { | 489 if (FLAG_heap_profiler_trace_objects) { |
| 513 PrintF("Begin HeapObjectsMap::UpdateHeapObjectsMap. map has %d entries.\n", | 490 PrintF("Begin HeapObjectsMap::UpdateHeapObjectsMap. map has %d entries.\n", |
| 514 entries_map_.occupancy()); | 491 entries_map_.occupancy()); |
| 515 } | 492 } |
| 516 heap_->CollectAllGarbage(Heap::kMakeHeapIterableMask, | 493 heap_->CollectAllGarbage(Heap::kMakeHeapIterableMask, |
| 517 "HeapSnapshotsCollection::UpdateHeapObjectsMap"); | 494 "HeapObjectsMap::UpdateHeapObjectsMap"); |
| 518 HeapIterator iterator(heap_); | 495 HeapIterator iterator(heap_); |
| 519 for (HeapObject* obj = iterator.next(); | 496 for (HeapObject* obj = iterator.next(); |
| 520 obj != NULL; | 497 obj != NULL; |
| 521 obj = iterator.next()) { | 498 obj = iterator.next()) { |
| 522 FindOrAddEntry(obj->address(), obj->Size()); | 499 FindOrAddEntry(obj->address(), obj->Size()); |
| 523 if (FLAG_heap_profiler_trace_objects) { | 500 if (FLAG_heap_profiler_trace_objects) { |
| 524 PrintF("Update object : %p %6d. Next address is %p\n", | 501 PrintF("Update object : %p %6d. Next address is %p\n", |
| 525 obj->address(), | 502 obj->address(), |
| 526 obj->Size(), | 503 obj->Size(), |
| 527 obj->address() + obj->Size()); | 504 obj->address() + obj->Size()); |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 715 ComputePointerHash(entry_info.addr)); | 692 ComputePointerHash(entry_info.addr)); |
| 716 } | 693 } |
| 717 } | 694 } |
| 718 } | 695 } |
| 719 entries_.Rewind(first_free_entry); | 696 entries_.Rewind(first_free_entry); |
| 720 ASSERT(static_cast<uint32_t>(entries_.length()) - 1 == | 697 ASSERT(static_cast<uint32_t>(entries_.length()) - 1 == |
| 721 entries_map_.occupancy()); | 698 entries_map_.occupancy()); |
| 722 } | 699 } |
| 723 | 700 |
| 724 | 701 |
| 725 SnapshotObjectId HeapObjectsMap::GenerateId(Heap* heap, | 702 SnapshotObjectId HeapObjectsMap::GenerateId(v8::RetainedObjectInfo* info) { |
| 726 v8::RetainedObjectInfo* info) { | |
| 727 SnapshotObjectId id = static_cast<SnapshotObjectId>(info->GetHash()); | 703 SnapshotObjectId id = static_cast<SnapshotObjectId>(info->GetHash()); |
| 728 const char* label = info->GetLabel(); | 704 const char* label = info->GetLabel(); |
| 729 id ^= StringHasher::HashSequentialString(label, | 705 id ^= StringHasher::HashSequentialString(label, |
| 730 static_cast<int>(strlen(label)), | 706 static_cast<int>(strlen(label)), |
| 731 heap->HashSeed()); | 707 heap_->HashSeed()); |
| 732 intptr_t element_count = info->GetElementCount(); | 708 intptr_t element_count = info->GetElementCount(); |
| 733 if (element_count != -1) | 709 if (element_count != -1) |
| 734 id ^= ComputeIntegerHash(static_cast<uint32_t>(element_count), | 710 id ^= ComputeIntegerHash(static_cast<uint32_t>(element_count), |
| 735 v8::internal::kZeroHashSeed); | 711 v8::internal::kZeroHashSeed); |
| 736 return id << 1; | 712 return id << 1; |
| 737 } | 713 } |
| 738 | 714 |
| 739 | 715 |
| 740 size_t HeapObjectsMap::GetUsedMemorySize() const { | 716 size_t HeapObjectsMap::GetUsedMemorySize() const { |
| 741 return | 717 return |
| 742 sizeof(*this) + | 718 sizeof(*this) + |
| 743 sizeof(HashMap::Entry) * entries_map_.capacity() + | 719 sizeof(HashMap::Entry) * entries_map_.capacity() + |
| 744 GetMemoryUsedByList(entries_) + | 720 GetMemoryUsedByList(entries_) + |
| 745 GetMemoryUsedByList(time_intervals_); | 721 GetMemoryUsedByList(time_intervals_); |
| 746 } | 722 } |
| 747 | 723 |
| 748 | 724 |
| 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() | 725 HeapEntriesMap::HeapEntriesMap() |
| 851 : entries_(HeapThingsMatch) { | 726 : entries_(HeapThingsMatch) { |
| 852 } | 727 } |
| 853 | 728 |
| 854 | 729 |
| 855 int HeapEntriesMap::Map(HeapThing thing) { | 730 int HeapEntriesMap::Map(HeapThing thing) { |
| 856 HashMap::Entry* cache_entry = entries_.Lookup(thing, Hash(thing), false); | 731 HashMap::Entry* cache_entry = entries_.Lookup(thing, Hash(thing), false); |
| 857 if (cache_entry == NULL) return HeapEntry::kNoEntry; | 732 if (cache_entry == NULL) return HeapEntry::kNoEntry; |
| 858 return static_cast<int>(reinterpret_cast<intptr_t>(cache_entry->value)); | 733 return static_cast<int>(reinterpret_cast<intptr_t>(cache_entry->value)); |
| 859 } | 734 } |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 920 static_cast<intptr_t>(HeapObjectsMap::kGcRootsFirstSubrootId)); | 795 static_cast<intptr_t>(HeapObjectsMap::kGcRootsFirstSubrootId)); |
| 921 HeapObject* const V8HeapExplorer::kLastGcSubrootObject = | 796 HeapObject* const V8HeapExplorer::kLastGcSubrootObject = |
| 922 reinterpret_cast<HeapObject*>( | 797 reinterpret_cast<HeapObject*>( |
| 923 static_cast<intptr_t>(HeapObjectsMap::kFirstAvailableObjectId)); | 798 static_cast<intptr_t>(HeapObjectsMap::kFirstAvailableObjectId)); |
| 924 | 799 |
| 925 | 800 |
| 926 V8HeapExplorer::V8HeapExplorer( | 801 V8HeapExplorer::V8HeapExplorer( |
| 927 HeapSnapshot* snapshot, | 802 HeapSnapshot* snapshot, |
| 928 SnapshottingProgressReportingInterface* progress, | 803 SnapshottingProgressReportingInterface* progress, |
| 929 v8::HeapProfiler::ObjectNameResolver* resolver) | 804 v8::HeapProfiler::ObjectNameResolver* resolver) |
| 930 : heap_(snapshot->collection()->heap()), | 805 : heap_(snapshot->profiler()->heap_object_map()->heap()), |
| 931 snapshot_(snapshot), | 806 snapshot_(snapshot), |
| 932 collection_(snapshot_->collection()), | 807 names_(snapshot_->profiler()->names()), |
| 808 heap_object_map_(snapshot_->profiler()->heap_object_map()), |
| 933 progress_(progress), | 809 progress_(progress), |
| 934 filler_(NULL), | 810 filler_(NULL), |
| 935 global_object_name_resolver_(resolver) { | 811 global_object_name_resolver_(resolver) { |
| 936 } | 812 } |
| 937 | 813 |
| 938 | 814 |
| 939 V8HeapExplorer::~V8HeapExplorer() { | 815 V8HeapExplorer::~V8HeapExplorer() { |
| 940 } | 816 } |
| 941 | 817 |
| 942 | 818 |
| 943 HeapEntry* V8HeapExplorer::AllocateEntry(HeapThing ptr) { | 819 HeapEntry* V8HeapExplorer::AllocateEntry(HeapThing ptr) { |
| 944 return AddEntry(reinterpret_cast<HeapObject*>(ptr)); | 820 return AddEntry(reinterpret_cast<HeapObject*>(ptr)); |
| 945 } | 821 } |
| 946 | 822 |
| 947 | 823 |
| 948 HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object) { | 824 HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object) { |
| 949 if (object == kInternalRootObject) { | 825 if (object == kInternalRootObject) { |
| 950 snapshot_->AddRootEntry(); | 826 snapshot_->AddRootEntry(); |
| 951 return snapshot_->root(); | 827 return snapshot_->root(); |
| 952 } else if (object == kGcRootsObject) { | 828 } else if (object == kGcRootsObject) { |
| 953 HeapEntry* entry = snapshot_->AddGcRootsEntry(); | 829 HeapEntry* entry = snapshot_->AddGcRootsEntry(); |
| 954 return entry; | 830 return entry; |
| 955 } else if (object >= kFirstGcSubrootObject && object < kLastGcSubrootObject) { | 831 } else if (object >= kFirstGcSubrootObject && object < kLastGcSubrootObject) { |
| 956 HeapEntry* entry = snapshot_->AddGcSubrootEntry(GetGcSubrootOrder(object)); | 832 HeapEntry* entry = snapshot_->AddGcSubrootEntry(GetGcSubrootOrder(object)); |
| 957 return entry; | 833 return entry; |
| 958 } else if (object->IsJSFunction()) { | 834 } else if (object->IsJSFunction()) { |
| 959 JSFunction* func = JSFunction::cast(object); | 835 JSFunction* func = JSFunction::cast(object); |
| 960 SharedFunctionInfo* shared = func->shared(); | 836 SharedFunctionInfo* shared = func->shared(); |
| 961 const char* name = shared->bound() ? "native_bind" : | 837 const char* name = shared->bound() ? "native_bind" : |
| 962 collection_->names()->GetName(String::cast(shared->name())); | 838 names_->GetName(String::cast(shared->name())); |
| 963 return AddEntry(object, HeapEntry::kClosure, name); | 839 return AddEntry(object, HeapEntry::kClosure, name); |
| 964 } else if (object->IsJSRegExp()) { | 840 } else if (object->IsJSRegExp()) { |
| 965 JSRegExp* re = JSRegExp::cast(object); | 841 JSRegExp* re = JSRegExp::cast(object); |
| 966 return AddEntry(object, | 842 return AddEntry(object, |
| 967 HeapEntry::kRegExp, | 843 HeapEntry::kRegExp, |
| 968 collection_->names()->GetName(re->Pattern())); | 844 names_->GetName(re->Pattern())); |
| 969 } else if (object->IsJSObject()) { | 845 } else if (object->IsJSObject()) { |
| 970 const char* name = collection_->names()->GetName( | 846 const char* name = names_->GetName( |
| 971 GetConstructorName(JSObject::cast(object))); | 847 GetConstructorName(JSObject::cast(object))); |
| 972 if (object->IsJSGlobalObject()) { | 848 if (object->IsJSGlobalObject()) { |
| 973 const char* tag = objects_tags_.GetTag(object); | 849 const char* tag = objects_tags_.GetTag(object); |
| 974 if (tag != NULL) { | 850 if (tag != NULL) { |
| 975 name = collection_->names()->GetFormatted("%s / %s", name, tag); | 851 name = names_->GetFormatted("%s / %s", name, tag); |
| 976 } | 852 } |
| 977 } | 853 } |
| 978 return AddEntry(object, HeapEntry::kObject, name); | 854 return AddEntry(object, HeapEntry::kObject, name); |
| 979 } else if (object->IsString()) { | 855 } else if (object->IsString()) { |
| 980 String* string = String::cast(object); | 856 String* string = String::cast(object); |
| 981 if (string->IsConsString()) | 857 if (string->IsConsString()) |
| 982 return AddEntry(object, | 858 return AddEntry(object, |
| 983 HeapEntry::kConsString, | 859 HeapEntry::kConsString, |
| 984 "(concatenated string)"); | 860 "(concatenated string)"); |
| 985 if (string->IsSlicedString()) | 861 if (string->IsSlicedString()) |
| 986 return AddEntry(object, | 862 return AddEntry(object, |
| 987 HeapEntry::kSlicedString, | 863 HeapEntry::kSlicedString, |
| 988 "(sliced string)"); | 864 "(sliced string)"); |
| 989 return AddEntry(object, | 865 return AddEntry(object, |
| 990 HeapEntry::kString, | 866 HeapEntry::kString, |
| 991 collection_->names()->GetName(String::cast(object))); | 867 names_->GetName(String::cast(object))); |
| 992 } else if (object->IsCode()) { | 868 } else if (object->IsCode()) { |
| 993 return AddEntry(object, HeapEntry::kCode, ""); | 869 return AddEntry(object, HeapEntry::kCode, ""); |
| 994 } else if (object->IsSharedFunctionInfo()) { | 870 } else if (object->IsSharedFunctionInfo()) { |
| 995 String* name = String::cast(SharedFunctionInfo::cast(object)->name()); | 871 String* name = String::cast(SharedFunctionInfo::cast(object)->name()); |
| 996 return AddEntry(object, | 872 return AddEntry(object, |
| 997 HeapEntry::kCode, | 873 HeapEntry::kCode, |
| 998 collection_->names()->GetName(name)); | 874 names_->GetName(name)); |
| 999 } else if (object->IsScript()) { | 875 } else if (object->IsScript()) { |
| 1000 Object* name = Script::cast(object)->name(); | 876 Object* name = Script::cast(object)->name(); |
| 1001 return AddEntry(object, | 877 return AddEntry(object, |
| 1002 HeapEntry::kCode, | 878 HeapEntry::kCode, |
| 1003 name->IsString() | 879 name->IsString() |
| 1004 ? collection_->names()->GetName(String::cast(name)) | 880 ? names_->GetName(String::cast(name)) |
| 1005 : ""); | 881 : ""); |
| 1006 } else if (object->IsNativeContext()) { | 882 } else if (object->IsNativeContext()) { |
| 1007 return AddEntry(object, HeapEntry::kHidden, "system / NativeContext"); | 883 return AddEntry(object, HeapEntry::kHidden, "system / NativeContext"); |
| 1008 } else if (object->IsContext()) { | 884 } else if (object->IsContext()) { |
| 1009 return AddEntry(object, HeapEntry::kObject, "system / Context"); | 885 return AddEntry(object, HeapEntry::kObject, "system / Context"); |
| 1010 } else if (object->IsFixedArray() || | 886 } else if (object->IsFixedArray() || |
| 1011 object->IsFixedDoubleArray() || | 887 object->IsFixedDoubleArray() || |
| 1012 object->IsByteArray() || | 888 object->IsByteArray() || |
| 1013 object->IsExternalArray()) { | 889 object->IsExternalArray()) { |
| 1014 return AddEntry(object, HeapEntry::kArray, ""); | 890 return AddEntry(object, HeapEntry::kArray, ""); |
| 1015 } else if (object->IsHeapNumber()) { | 891 } else if (object->IsHeapNumber()) { |
| 1016 return AddEntry(object, HeapEntry::kHeapNumber, "number"); | 892 return AddEntry(object, HeapEntry::kHeapNumber, "number"); |
| 1017 } | 893 } |
| 1018 return AddEntry(object, HeapEntry::kHidden, GetSystemEntryName(object)); | 894 return AddEntry(object, HeapEntry::kHidden, GetSystemEntryName(object)); |
| 1019 } | 895 } |
| 1020 | 896 |
| 1021 | 897 |
| 1022 HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object, | 898 HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object, |
| 1023 HeapEntry::Type type, | 899 HeapEntry::Type type, |
| 1024 const char* name) { | 900 const char* name) { |
| 1025 int object_size = object->Size(); | 901 int object_size = object->Size(); |
| 1026 SnapshotObjectId object_id = | 902 SnapshotObjectId object_id = |
| 1027 collection_->GetObjectId(object->address(), object_size); | 903 heap_object_map_->FindOrAddEntry(object->address(), object_size); |
| 1028 return snapshot_->AddEntry(type, name, object_id, object_size); | 904 return snapshot_->AddEntry(type, name, object_id, object_size); |
| 1029 } | 905 } |
| 1030 | 906 |
| 1031 | 907 |
| 1032 class GcSubrootsEnumerator : public ObjectVisitor { | 908 class GcSubrootsEnumerator : public ObjectVisitor { |
| 1033 public: | 909 public: |
| 1034 GcSubrootsEnumerator( | 910 GcSubrootsEnumerator( |
| 1035 SnapshotFillerInterface* filler, V8HeapExplorer* explorer) | 911 SnapshotFillerInterface* filler, V8HeapExplorer* explorer) |
| 1036 : filler_(filler), | 912 : filler_(filler), |
| 1037 explorer_(explorer), | 913 explorer_(explorer), |
| (...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1364 TagObject(map->dependent_code(), "(dependent code)"); | 1240 TagObject(map->dependent_code(), "(dependent code)"); |
| 1365 SetInternalReference(map, entry, | 1241 SetInternalReference(map, entry, |
| 1366 "dependent_code", map->dependent_code(), | 1242 "dependent_code", map->dependent_code(), |
| 1367 Map::kDependentCodeOffset); | 1243 Map::kDependentCodeOffset); |
| 1368 } | 1244 } |
| 1369 | 1245 |
| 1370 | 1246 |
| 1371 void V8HeapExplorer::ExtractSharedFunctionInfoReferences( | 1247 void V8HeapExplorer::ExtractSharedFunctionInfoReferences( |
| 1372 int entry, SharedFunctionInfo* shared) { | 1248 int entry, SharedFunctionInfo* shared) { |
| 1373 HeapObject* obj = shared; | 1249 HeapObject* obj = shared; |
| 1374 StringsStorage* names = collection_->names(); | |
| 1375 String* shared_name = shared->DebugName(); | 1250 String* shared_name = shared->DebugName(); |
| 1376 const char* name = NULL; | 1251 const char* name = NULL; |
| 1377 if (shared_name != *heap_->isolate()->factory()->empty_string()) { | 1252 if (shared_name != *heap_->isolate()->factory()->empty_string()) { |
| 1378 name = names->GetName(shared_name); | 1253 name = names_->GetName(shared_name); |
| 1379 TagObject(shared->code(), names->GetFormatted("(code for %s)", name)); | 1254 TagObject(shared->code(), names_->GetFormatted("(code for %s)", name)); |
| 1380 } else { | 1255 } else { |
| 1381 TagObject(shared->code(), names->GetFormatted("(%s code)", | 1256 TagObject(shared->code(), names_->GetFormatted("(%s code)", |
| 1382 Code::Kind2String(shared->code()->kind()))); | 1257 Code::Kind2String(shared->code()->kind()))); |
| 1383 } | 1258 } |
| 1384 | 1259 |
| 1385 SetInternalReference(obj, entry, | 1260 SetInternalReference(obj, entry, |
| 1386 "name", shared->name(), | 1261 "name", shared->name(), |
| 1387 SharedFunctionInfo::kNameOffset); | 1262 SharedFunctionInfo::kNameOffset); |
| 1388 SetInternalReference(obj, entry, | 1263 SetInternalReference(obj, entry, |
| 1389 "code", shared->code(), | 1264 "code", shared->code(), |
| 1390 SharedFunctionInfo::kCodeOffset); | 1265 SharedFunctionInfo::kCodeOffset); |
| 1391 TagObject(shared->scope_info(), "(function scope info)"); | 1266 TagObject(shared->scope_info(), "(function scope info)"); |
| 1392 SetInternalReference(obj, entry, | 1267 SetInternalReference(obj, entry, |
| 1393 "scope_info", shared->scope_info(), | 1268 "scope_info", shared->scope_info(), |
| 1394 SharedFunctionInfo::kScopeInfoOffset); | 1269 SharedFunctionInfo::kScopeInfoOffset); |
| 1395 SetInternalReference(obj, entry, | 1270 SetInternalReference(obj, entry, |
| 1396 "instance_class_name", shared->instance_class_name(), | 1271 "instance_class_name", shared->instance_class_name(), |
| 1397 SharedFunctionInfo::kInstanceClassNameOffset); | 1272 SharedFunctionInfo::kInstanceClassNameOffset); |
| 1398 SetInternalReference(obj, entry, | 1273 SetInternalReference(obj, entry, |
| 1399 "script", shared->script(), | 1274 "script", shared->script(), |
| 1400 SharedFunctionInfo::kScriptOffset); | 1275 SharedFunctionInfo::kScriptOffset); |
| 1401 const char* construct_stub_name = name ? | 1276 const char* construct_stub_name = name ? |
| 1402 names->GetFormatted("(construct stub code for %s)", name) : | 1277 names_->GetFormatted("(construct stub code for %s)", name) : |
| 1403 "(construct stub code)"; | 1278 "(construct stub code)"; |
| 1404 TagObject(shared->construct_stub(), construct_stub_name); | 1279 TagObject(shared->construct_stub(), construct_stub_name); |
| 1405 SetInternalReference(obj, entry, | 1280 SetInternalReference(obj, entry, |
| 1406 "construct_stub", shared->construct_stub(), | 1281 "construct_stub", shared->construct_stub(), |
| 1407 SharedFunctionInfo::kConstructStubOffset); | 1282 SharedFunctionInfo::kConstructStubOffset); |
| 1408 SetInternalReference(obj, entry, | 1283 SetInternalReference(obj, entry, |
| 1409 "function_data", shared->function_data(), | 1284 "function_data", shared->function_data(), |
| 1410 SharedFunctionInfo::kFunctionDataOffset); | 1285 SharedFunctionInfo::kFunctionDataOffset); |
| 1411 SetInternalReference(obj, entry, | 1286 SetInternalReference(obj, entry, |
| 1412 "debug_info", shared->debug_info(), | 1287 "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(), | 1335 "default_cache", code_cache->default_cache(), |
| 1461 CodeCache::kDefaultCacheOffset); | 1336 CodeCache::kDefaultCacheOffset); |
| 1462 TagObject(code_cache->normal_type_cache(), "(code type cache)"); | 1337 TagObject(code_cache->normal_type_cache(), "(code type cache)"); |
| 1463 SetInternalReference(code_cache, entry, | 1338 SetInternalReference(code_cache, entry, |
| 1464 "type_cache", code_cache->normal_type_cache(), | 1339 "type_cache", code_cache->normal_type_cache(), |
| 1465 CodeCache::kNormalTypeCacheOffset); | 1340 CodeCache::kNormalTypeCacheOffset); |
| 1466 } | 1341 } |
| 1467 | 1342 |
| 1468 | 1343 |
| 1469 void V8HeapExplorer::TagCodeObject(Code* code, const char* external_name) { | 1344 void V8HeapExplorer::TagCodeObject(Code* code, const char* external_name) { |
| 1470 TagObject(code, collection_->names()->GetFormatted("(%s code)", | 1345 TagObject(code, names_->GetFormatted("(%s code)", external_name)); |
| 1471 external_name)); | |
| 1472 } | 1346 } |
| 1473 | 1347 |
| 1474 | 1348 |
| 1475 void V8HeapExplorer::TagCodeObject(Code* code) { | 1349 void V8HeapExplorer::TagCodeObject(Code* code) { |
| 1476 if (code->kind() == Code::STUB) { | 1350 if (code->kind() == Code::STUB) { |
| 1477 TagObject(code, collection_->names()->GetFormatted( | 1351 TagObject(code, names_->GetFormatted( |
| 1478 "(%s code)", CodeStub::MajorName( | 1352 "(%s code)", CodeStub::MajorName( |
| 1479 static_cast<CodeStub::Major>(code->major_key()), true))); | 1353 static_cast<CodeStub::Major>(code->major_key()), true))); |
| 1480 } | 1354 } |
| 1481 } | 1355 } |
| 1482 | 1356 |
| 1483 | 1357 |
| 1484 void V8HeapExplorer::ExtractCodeReferences(int entry, Code* code) { | 1358 void V8HeapExplorer::ExtractCodeReferences(int entry, Code* code) { |
| 1485 TagCodeObject(code); | 1359 TagCodeObject(code); |
| 1486 TagObject(code->relocation_info(), "(code relocation info)"); | 1360 TagObject(code->relocation_info(), "(code relocation info)"); |
| 1487 SetInternalReference(code, entry, | 1361 SetInternalReference(code, entry, |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1545 | 1419 |
| 1546 JSFunction* func = JSFunction::cast(js_obj); | 1420 JSFunction* func = JSFunction::cast(js_obj); |
| 1547 if (func->shared()->bound()) { | 1421 if (func->shared()->bound()) { |
| 1548 FixedArray* bindings = func->function_bindings(); | 1422 FixedArray* bindings = func->function_bindings(); |
| 1549 SetNativeBindReference(js_obj, entry, "bound_this", | 1423 SetNativeBindReference(js_obj, entry, "bound_this", |
| 1550 bindings->get(JSFunction::kBoundThisIndex)); | 1424 bindings->get(JSFunction::kBoundThisIndex)); |
| 1551 SetNativeBindReference(js_obj, entry, "bound_function", | 1425 SetNativeBindReference(js_obj, entry, "bound_function", |
| 1552 bindings->get(JSFunction::kBoundFunctionIndex)); | 1426 bindings->get(JSFunction::kBoundFunctionIndex)); |
| 1553 for (int i = JSFunction::kBoundArgumentsStartIndex; | 1427 for (int i = JSFunction::kBoundArgumentsStartIndex; |
| 1554 i < bindings->length(); i++) { | 1428 i < bindings->length(); i++) { |
| 1555 const char* reference_name = collection_->names()->GetFormatted( | 1429 const char* reference_name = names_->GetFormatted( |
| 1556 "bound_argument_%d", | 1430 "bound_argument_%d", |
| 1557 i - JSFunction::kBoundArgumentsStartIndex); | 1431 i - JSFunction::kBoundArgumentsStartIndex); |
| 1558 SetNativeBindReference(js_obj, entry, reference_name, | 1432 SetNativeBindReference(js_obj, entry, reference_name, |
| 1559 bindings->get(i)); | 1433 bindings->get(i)); |
| 1560 } | 1434 } |
| 1561 } | 1435 } |
| 1562 } | 1436 } |
| 1563 | 1437 |
| 1564 | 1438 |
| 1565 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... |
| 1852 void V8HeapExplorer::SetContextReference(HeapObject* parent_obj, | 1726 void V8HeapExplorer::SetContextReference(HeapObject* parent_obj, |
| 1853 int parent_entry, | 1727 int parent_entry, |
| 1854 String* reference_name, | 1728 String* reference_name, |
| 1855 Object* child_obj, | 1729 Object* child_obj, |
| 1856 int field_offset) { | 1730 int field_offset) { |
| 1857 ASSERT(parent_entry == GetEntry(parent_obj)->index()); | 1731 ASSERT(parent_entry == GetEntry(parent_obj)->index()); |
| 1858 HeapEntry* child_entry = GetEntry(child_obj); | 1732 HeapEntry* child_entry = GetEntry(child_obj); |
| 1859 if (child_entry != NULL) { | 1733 if (child_entry != NULL) { |
| 1860 filler_->SetNamedReference(HeapGraphEdge::kContextVariable, | 1734 filler_->SetNamedReference(HeapGraphEdge::kContextVariable, |
| 1861 parent_entry, | 1735 parent_entry, |
| 1862 collection_->names()->GetName(reference_name), | 1736 names_->GetName(reference_name), |
| 1863 child_entry); | 1737 child_entry); |
| 1864 IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset); | 1738 IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset); |
| 1865 } | 1739 } |
| 1866 } | 1740 } |
| 1867 | 1741 |
| 1868 | 1742 |
| 1869 void V8HeapExplorer::SetNativeBindReference(HeapObject* parent_obj, | 1743 void V8HeapExplorer::SetNativeBindReference(HeapObject* parent_obj, |
| 1870 int parent_entry, | 1744 int parent_entry, |
| 1871 const char* reference_name, | 1745 const char* reference_name, |
| 1872 Object* child_obj) { | 1746 Object* child_obj) { |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1918 int parent_entry, | 1792 int parent_entry, |
| 1919 int index, | 1793 int index, |
| 1920 Object* child_obj, | 1794 Object* child_obj, |
| 1921 int field_offset) { | 1795 int field_offset) { |
| 1922 ASSERT(parent_entry == GetEntry(parent_obj)->index()); | 1796 ASSERT(parent_entry == GetEntry(parent_obj)->index()); |
| 1923 HeapEntry* child_entry = GetEntry(child_obj); | 1797 HeapEntry* child_entry = GetEntry(child_obj); |
| 1924 if (child_entry == NULL) return; | 1798 if (child_entry == NULL) return; |
| 1925 if (IsEssentialObject(child_obj)) { | 1799 if (IsEssentialObject(child_obj)) { |
| 1926 filler_->SetNamedReference(HeapGraphEdge::kInternal, | 1800 filler_->SetNamedReference(HeapGraphEdge::kInternal, |
| 1927 parent_entry, | 1801 parent_entry, |
| 1928 collection_->names()->GetName(index), | 1802 names_->GetName(index), |
| 1929 child_entry); | 1803 child_entry); |
| 1930 } | 1804 } |
| 1931 IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset); | 1805 IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset); |
| 1932 } | 1806 } |
| 1933 | 1807 |
| 1934 | 1808 |
| 1935 void V8HeapExplorer::SetHiddenReference(HeapObject* parent_obj, | 1809 void V8HeapExplorer::SetHiddenReference(HeapObject* parent_obj, |
| 1936 int parent_entry, | 1810 int parent_entry, |
| 1937 int index, | 1811 int index, |
| 1938 Object* child_obj) { | 1812 Object* child_obj) { |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1971 Object* child_obj, | 1845 Object* child_obj, |
| 1972 const char* name_format_string, | 1846 const char* name_format_string, |
| 1973 int field_offset) { | 1847 int field_offset) { |
| 1974 ASSERT(parent_entry == GetEntry(parent_obj)->index()); | 1848 ASSERT(parent_entry == GetEntry(parent_obj)->index()); |
| 1975 HeapEntry* child_entry = GetEntry(child_obj); | 1849 HeapEntry* child_entry = GetEntry(child_obj); |
| 1976 if (child_entry != NULL) { | 1850 if (child_entry != NULL) { |
| 1977 HeapGraphEdge::Type type = | 1851 HeapGraphEdge::Type type = |
| 1978 reference_name->IsSymbol() || String::cast(reference_name)->length() > 0 | 1852 reference_name->IsSymbol() || String::cast(reference_name)->length() > 0 |
| 1979 ? HeapGraphEdge::kProperty : HeapGraphEdge::kInternal; | 1853 ? HeapGraphEdge::kProperty : HeapGraphEdge::kInternal; |
| 1980 const char* name = name_format_string != NULL && reference_name->IsString() | 1854 const char* name = name_format_string != NULL && reference_name->IsString() |
| 1981 ? collection_->names()->GetFormatted( | 1855 ? names_->GetFormatted( |
| 1982 name_format_string, | 1856 name_format_string, |
| 1983 *String::cast(reference_name)->ToCString( | 1857 *String::cast(reference_name)->ToCString( |
| 1984 DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL)) : | 1858 DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL)) : |
| 1985 collection_->names()->GetName(reference_name); | 1859 names_->GetName(reference_name); |
| 1986 | 1860 |
| 1987 filler_->SetNamedReference(type, | 1861 filler_->SetNamedReference(type, |
| 1988 parent_entry, | 1862 parent_entry, |
| 1989 name, | 1863 name, |
| 1990 child_entry); | 1864 child_entry); |
| 1991 IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset); | 1865 IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset); |
| 1992 } | 1866 } |
| 1993 } | 1867 } |
| 1994 | 1868 |
| 1995 | 1869 |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2151 NativeObjectsExplorer* explorer_; | 2025 NativeObjectsExplorer* explorer_; |
| 2152 }; | 2026 }; |
| 2153 | 2027 |
| 2154 | 2028 |
| 2155 class BasicHeapEntriesAllocator : public HeapEntriesAllocator { | 2029 class BasicHeapEntriesAllocator : public HeapEntriesAllocator { |
| 2156 public: | 2030 public: |
| 2157 BasicHeapEntriesAllocator( | 2031 BasicHeapEntriesAllocator( |
| 2158 HeapSnapshot* snapshot, | 2032 HeapSnapshot* snapshot, |
| 2159 HeapEntry::Type entries_type) | 2033 HeapEntry::Type entries_type) |
| 2160 : snapshot_(snapshot), | 2034 : snapshot_(snapshot), |
| 2161 collection_(snapshot_->collection()), | 2035 names_(snapshot_->profiler()->names()), |
| 2036 heap_object_map_(snapshot_->profiler()->heap_object_map()), |
| 2162 entries_type_(entries_type) { | 2037 entries_type_(entries_type) { |
| 2163 } | 2038 } |
| 2164 virtual HeapEntry* AllocateEntry(HeapThing ptr); | 2039 virtual HeapEntry* AllocateEntry(HeapThing ptr); |
| 2165 private: | 2040 private: |
| 2166 HeapSnapshot* snapshot_; | 2041 HeapSnapshot* snapshot_; |
| 2167 HeapSnapshotsCollection* collection_; | 2042 StringsStorage* names_; |
| 2043 HeapObjectsMap* heap_object_map_; |
| 2168 HeapEntry::Type entries_type_; | 2044 HeapEntry::Type entries_type_; |
| 2169 }; | 2045 }; |
| 2170 | 2046 |
| 2171 | 2047 |
| 2172 HeapEntry* BasicHeapEntriesAllocator::AllocateEntry(HeapThing ptr) { | 2048 HeapEntry* BasicHeapEntriesAllocator::AllocateEntry(HeapThing ptr) { |
| 2173 v8::RetainedObjectInfo* info = reinterpret_cast<v8::RetainedObjectInfo*>(ptr); | 2049 v8::RetainedObjectInfo* info = reinterpret_cast<v8::RetainedObjectInfo*>(ptr); |
| 2174 intptr_t elements = info->GetElementCount(); | 2050 intptr_t elements = info->GetElementCount(); |
| 2175 intptr_t size = info->GetSizeInBytes(); | 2051 intptr_t size = info->GetSizeInBytes(); |
| 2176 const char* name = elements != -1 | 2052 const char* name = elements != -1 |
| 2177 ? collection_->names()->GetFormatted( | 2053 ? names_->GetFormatted( |
| 2178 "%s / %" V8_PTR_PREFIX "d entries", info->GetLabel(), elements) | 2054 "%s / %" V8_PTR_PREFIX "d entries", info->GetLabel(), elements) |
| 2179 : collection_->names()->GetCopy(info->GetLabel()); | 2055 : names_->GetCopy(info->GetLabel()); |
| 2180 return snapshot_->AddEntry( | 2056 return snapshot_->AddEntry( |
| 2181 entries_type_, | 2057 entries_type_, |
| 2182 name, | 2058 name, |
| 2183 HeapObjectsMap::GenerateId(collection_->heap(), info), | 2059 heap_object_map_->GenerateId(info), |
| 2184 size != -1 ? static_cast<int>(size) : 0); | 2060 size != -1 ? static_cast<int>(size) : 0); |
| 2185 } | 2061 } |
| 2186 | 2062 |
| 2187 | 2063 |
| 2188 NativeObjectsExplorer::NativeObjectsExplorer( | 2064 NativeObjectsExplorer::NativeObjectsExplorer( |
| 2189 HeapSnapshot* snapshot, | 2065 HeapSnapshot* snapshot, |
| 2190 SnapshottingProgressReportingInterface* progress) | 2066 SnapshottingProgressReportingInterface* progress) |
| 2191 : isolate_(snapshot->collection()->heap()->isolate()), | 2067 : isolate_(snapshot->profiler()->heap_object_map()->heap()->isolate()), |
| 2192 snapshot_(snapshot), | 2068 snapshot_(snapshot), |
| 2193 collection_(snapshot_->collection()), | 2069 names_(snapshot_->profiler()->names()), |
| 2194 progress_(progress), | 2070 progress_(progress), |
| 2195 embedder_queried_(false), | 2071 embedder_queried_(false), |
| 2196 objects_by_info_(RetainedInfosMatch), | 2072 objects_by_info_(RetainedInfosMatch), |
| 2197 native_groups_(StringsMatch), | 2073 native_groups_(StringsMatch), |
| 2198 filler_(NULL) { | 2074 filler_(NULL) { |
| 2199 synthetic_entries_allocator_ = | 2075 synthetic_entries_allocator_ = |
| 2200 new BasicHeapEntriesAllocator(snapshot, HeapEntry::kSynthetic); | 2076 new BasicHeapEntriesAllocator(snapshot, HeapEntry::kSynthetic); |
| 2201 native_entries_allocator_ = | 2077 native_entries_allocator_ = |
| 2202 new BasicHeapEntriesAllocator(snapshot, HeapEntry::kNative); | 2078 new BasicHeapEntriesAllocator(snapshot, HeapEntry::kNative); |
| 2203 } | 2079 } |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2345 | 2221 |
| 2346 private: | 2222 private: |
| 2347 bool disposed_; | 2223 bool disposed_; |
| 2348 intptr_t hash_; | 2224 intptr_t hash_; |
| 2349 const char* label_; | 2225 const char* label_; |
| 2350 }; | 2226 }; |
| 2351 | 2227 |
| 2352 | 2228 |
| 2353 NativeGroupRetainedObjectInfo* NativeObjectsExplorer::FindOrAddGroupInfo( | 2229 NativeGroupRetainedObjectInfo* NativeObjectsExplorer::FindOrAddGroupInfo( |
| 2354 const char* label) { | 2230 const char* label) { |
| 2355 const char* label_copy = collection_->names()->GetCopy(label); | 2231 const char* label_copy = names_->GetCopy(label); |
| 2356 uint32_t hash = StringHasher::HashSequentialString( | 2232 uint32_t hash = StringHasher::HashSequentialString( |
| 2357 label_copy, | 2233 label_copy, |
| 2358 static_cast<int>(strlen(label_copy)), | 2234 static_cast<int>(strlen(label_copy)), |
| 2359 isolate_->heap()->HashSeed()); | 2235 isolate_->heap()->HashSeed()); |
| 2360 HashMap::Entry* entry = native_groups_.Lookup(const_cast<char*>(label_copy), | 2236 HashMap::Entry* entry = native_groups_.Lookup(const_cast<char*>(label_copy), |
| 2361 hash, true); | 2237 hash, true); |
| 2362 if (entry->value == NULL) { | 2238 if (entry->value == NULL) { |
| 2363 entry->value = new NativeGroupRetainedObjectInfo(label); | 2239 entry->value = new NativeGroupRetainedObjectInfo(label); |
| 2364 } | 2240 } |
| 2365 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... |
| 2423 isolate->heap_profiler()->ExecuteWrapperClassCallback(class_id, p); | 2299 isolate->heap_profiler()->ExecuteWrapperClassCallback(class_id, p); |
| 2424 if (info == NULL) return; | 2300 if (info == NULL) return; |
| 2425 GetListMaybeDisposeInfo(info)->Add(HeapObject::cast(*p)); | 2301 GetListMaybeDisposeInfo(info)->Add(HeapObject::cast(*p)); |
| 2426 } | 2302 } |
| 2427 | 2303 |
| 2428 | 2304 |
| 2429 class SnapshotFiller : public SnapshotFillerInterface { | 2305 class SnapshotFiller : public SnapshotFillerInterface { |
| 2430 public: | 2306 public: |
| 2431 explicit SnapshotFiller(HeapSnapshot* snapshot, HeapEntriesMap* entries) | 2307 explicit SnapshotFiller(HeapSnapshot* snapshot, HeapEntriesMap* entries) |
| 2432 : snapshot_(snapshot), | 2308 : snapshot_(snapshot), |
| 2433 collection_(snapshot->collection()), | 2309 names_(snapshot->profiler()->names()), |
| 2434 entries_(entries) { } | 2310 entries_(entries) { } |
| 2435 HeapEntry* AddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) { | 2311 HeapEntry* AddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) { |
| 2436 HeapEntry* entry = allocator->AllocateEntry(ptr); | 2312 HeapEntry* entry = allocator->AllocateEntry(ptr); |
| 2437 entries_->Pair(ptr, entry->index()); | 2313 entries_->Pair(ptr, entry->index()); |
| 2438 return entry; | 2314 return entry; |
| 2439 } | 2315 } |
| 2440 HeapEntry* FindEntry(HeapThing ptr) { | 2316 HeapEntry* FindEntry(HeapThing ptr) { |
| 2441 int index = entries_->Map(ptr); | 2317 int index = entries_->Map(ptr); |
| 2442 return index != HeapEntry::kNoEntry ? &snapshot_->entries()[index] : NULL; | 2318 return index != HeapEntry::kNoEntry ? &snapshot_->entries()[index] : NULL; |
| 2443 } | 2319 } |
| (...skipping 22 matching lines...) Expand all Loading... |
| 2466 HeapEntry* parent_entry = &snapshot_->entries()[parent]; | 2342 HeapEntry* parent_entry = &snapshot_->entries()[parent]; |
| 2467 parent_entry->SetNamedReference(type, reference_name, child_entry); | 2343 parent_entry->SetNamedReference(type, reference_name, child_entry); |
| 2468 } | 2344 } |
| 2469 void SetNamedAutoIndexReference(HeapGraphEdge::Type type, | 2345 void SetNamedAutoIndexReference(HeapGraphEdge::Type type, |
| 2470 int parent, | 2346 int parent, |
| 2471 HeapEntry* child_entry) { | 2347 HeapEntry* child_entry) { |
| 2472 HeapEntry* parent_entry = &snapshot_->entries()[parent]; | 2348 HeapEntry* parent_entry = &snapshot_->entries()[parent]; |
| 2473 int index = parent_entry->children_count() + 1; | 2349 int index = parent_entry->children_count() + 1; |
| 2474 parent_entry->SetNamedReference( | 2350 parent_entry->SetNamedReference( |
| 2475 type, | 2351 type, |
| 2476 collection_->names()->GetName(index), | 2352 names_->GetName(index), |
| 2477 child_entry); | 2353 child_entry); |
| 2478 } | 2354 } |
| 2479 | 2355 |
| 2480 private: | 2356 private: |
| 2481 HeapSnapshot* snapshot_; | 2357 HeapSnapshot* snapshot_; |
| 2482 HeapSnapshotsCollection* collection_; | 2358 StringsStorage* names_; |
| 2483 HeapEntriesMap* entries_; | 2359 HeapEntriesMap* entries_; |
| 2484 }; | 2360 }; |
| 2485 | 2361 |
| 2486 | 2362 |
| 2487 HeapSnapshotGenerator::HeapSnapshotGenerator( | 2363 HeapSnapshotGenerator::HeapSnapshotGenerator( |
| 2488 HeapSnapshot* snapshot, | 2364 HeapSnapshot* snapshot, |
| 2489 v8::ActivityControl* control, | 2365 v8::ActivityControl* control, |
| 2490 v8::HeapProfiler::ObjectNameResolver* resolver, | 2366 v8::HeapProfiler::ObjectNameResolver* resolver, |
| 2491 Heap* heap) | 2367 Heap* heap) |
| 2492 : snapshot_(snapshot), | 2368 : snapshot_(snapshot), |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2678 }; | 2554 }; |
| 2679 | 2555 |
| 2680 | 2556 |
| 2681 // type, name|index, to_node. | 2557 // type, name|index, to_node. |
| 2682 const int HeapSnapshotJSONSerializer::kEdgeFieldsCount = 3; | 2558 const int HeapSnapshotJSONSerializer::kEdgeFieldsCount = 3; |
| 2683 // type, name, id, self_size, children_index. | 2559 // type, name, id, self_size, children_index. |
| 2684 const int HeapSnapshotJSONSerializer::kNodeFieldsCount = 5; | 2560 const int HeapSnapshotJSONSerializer::kNodeFieldsCount = 5; |
| 2685 | 2561 |
| 2686 void HeapSnapshotJSONSerializer::Serialize(v8::OutputStream* stream) { | 2562 void HeapSnapshotJSONSerializer::Serialize(v8::OutputStream* stream) { |
| 2687 if (AllocationTracker* allocation_tracker = | 2563 if (AllocationTracker* allocation_tracker = |
| 2688 snapshot_->collection()->allocation_tracker()) { | 2564 snapshot_->profiler()->allocation_tracker()) { |
| 2689 allocation_tracker->PrepareForSerialization(); | 2565 allocation_tracker->PrepareForSerialization(); |
| 2690 } | 2566 } |
| 2691 ASSERT(writer_ == NULL); | 2567 ASSERT(writer_ == NULL); |
| 2692 writer_ = new OutputStreamWriter(stream); | 2568 writer_ = new OutputStreamWriter(stream); |
| 2693 SerializeImpl(); | 2569 SerializeImpl(); |
| 2694 delete writer_; | 2570 delete writer_; |
| 2695 writer_ = NULL; | 2571 writer_ = NULL; |
| 2696 } | 2572 } |
| 2697 | 2573 |
| 2698 | 2574 |
| (...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2897 JSON_S("children")))); | 2773 JSON_S("children")))); |
| 2898 #undef JSON_S | 2774 #undef JSON_S |
| 2899 #undef JSON_O | 2775 #undef JSON_O |
| 2900 #undef JSON_A | 2776 #undef JSON_A |
| 2901 writer_->AddString(",\"node_count\":"); | 2777 writer_->AddString(",\"node_count\":"); |
| 2902 writer_->AddNumber(snapshot_->entries().length()); | 2778 writer_->AddNumber(snapshot_->entries().length()); |
| 2903 writer_->AddString(",\"edge_count\":"); | 2779 writer_->AddString(",\"edge_count\":"); |
| 2904 writer_->AddNumber(snapshot_->edges().length()); | 2780 writer_->AddNumber(snapshot_->edges().length()); |
| 2905 writer_->AddString(",\"trace_function_count\":"); | 2781 writer_->AddString(",\"trace_function_count\":"); |
| 2906 uint32_t count = 0; | 2782 uint32_t count = 0; |
| 2907 AllocationTracker* tracker = snapshot_->collection()->allocation_tracker(); | 2783 AllocationTracker* tracker = snapshot_->profiler()->allocation_tracker(); |
| 2908 if (tracker) { | 2784 if (tracker) { |
| 2909 count = tracker->id_to_function_info()->occupancy(); | 2785 count = tracker->id_to_function_info()->occupancy(); |
| 2910 } | 2786 } |
| 2911 writer_->AddNumber(count); | 2787 writer_->AddNumber(count); |
| 2912 } | 2788 } |
| 2913 | 2789 |
| 2914 | 2790 |
| 2915 static void WriteUChar(OutputStreamWriter* w, unibrow::uchar u) { | 2791 static void WriteUChar(OutputStreamWriter* w, unibrow::uchar u) { |
| 2916 static const char hex_chars[] = "0123456789ABCDEF"; | 2792 static const char hex_chars[] = "0123456789ABCDEF"; |
| 2917 w->AddString("\\u"); | 2793 w->AddString("\\u"); |
| 2918 w->AddCharacter(hex_chars[(u >> 12) & 0xf]); | 2794 w->AddCharacter(hex_chars[(u >> 12) & 0xf]); |
| 2919 w->AddCharacter(hex_chars[(u >> 8) & 0xf]); | 2795 w->AddCharacter(hex_chars[(u >> 8) & 0xf]); |
| 2920 w->AddCharacter(hex_chars[(u >> 4) & 0xf]); | 2796 w->AddCharacter(hex_chars[(u >> 4) & 0xf]); |
| 2921 w->AddCharacter(hex_chars[u & 0xf]); | 2797 w->AddCharacter(hex_chars[u & 0xf]); |
| 2922 } | 2798 } |
| 2923 | 2799 |
| 2924 | 2800 |
| 2925 void HeapSnapshotJSONSerializer::SerializeTraceTree() { | 2801 void HeapSnapshotJSONSerializer::SerializeTraceTree() { |
| 2926 AllocationTracker* tracker = snapshot_->collection()->allocation_tracker(); | 2802 AllocationTracker* tracker = snapshot_->profiler()->allocation_tracker(); |
| 2927 if (!tracker) return; | 2803 if (!tracker) return; |
| 2928 AllocationTraceTree* traces = tracker->trace_tree(); | 2804 AllocationTraceTree* traces = tracker->trace_tree(); |
| 2929 SerializeTraceNode(traces->root()); | 2805 SerializeTraceNode(traces->root()); |
| 2930 } | 2806 } |
| 2931 | 2807 |
| 2932 | 2808 |
| 2933 void HeapSnapshotJSONSerializer::SerializeTraceNode(AllocationTraceNode* node) { | 2809 void HeapSnapshotJSONSerializer::SerializeTraceNode(AllocationTraceNode* node) { |
| 2934 // 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 |
| 2935 const int kBufferSize = | 2811 const int kBufferSize = |
| 2936 4 * MaxDecimalDigitsIn<sizeof(unsigned)>::kUnsigned // NOLINT | 2812 4 * MaxDecimalDigitsIn<sizeof(unsigned)>::kUnsigned // NOLINT |
| (...skipping 30 matching lines...) Expand all Loading... |
| 2967 buffer[buffer_pos++] = '0'; | 2843 buffer[buffer_pos++] = '0'; |
| 2968 } else { | 2844 } else { |
| 2969 ASSERT(position >= 0); | 2845 ASSERT(position >= 0); |
| 2970 buffer_pos = utoa(static_cast<unsigned>(position + 1), buffer, buffer_pos); | 2846 buffer_pos = utoa(static_cast<unsigned>(position + 1), buffer, buffer_pos); |
| 2971 } | 2847 } |
| 2972 return buffer_pos; | 2848 return buffer_pos; |
| 2973 } | 2849 } |
| 2974 | 2850 |
| 2975 | 2851 |
| 2976 void HeapSnapshotJSONSerializer::SerializeTraceNodeInfos() { | 2852 void HeapSnapshotJSONSerializer::SerializeTraceNodeInfos() { |
| 2977 AllocationTracker* tracker = snapshot_->collection()->allocation_tracker(); | 2853 AllocationTracker* tracker = snapshot_->profiler()->allocation_tracker(); |
| 2978 if (!tracker) return; | 2854 if (!tracker) return; |
| 2979 // 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 |
| 2980 const int kBufferSize = | 2856 const int kBufferSize = |
| 2981 6 * MaxDecimalDigitsIn<sizeof(unsigned)>::kUnsigned // NOLINT | 2857 6 * MaxDecimalDigitsIn<sizeof(unsigned)>::kUnsigned // NOLINT |
| 2982 + 6 + 1 + 1; | 2858 + 6 + 1 + 1; |
| 2983 EmbeddedVector<char, kBufferSize> buffer; | 2859 EmbeddedVector<char, kBufferSize> buffer; |
| 2984 HashMap* id_to_function_info = tracker->id_to_function_info(); | 2860 HashMap* id_to_function_info = tracker->id_to_function_info(); |
| 2985 bool first_entry = true; | 2861 bool first_entry = true; |
| 2986 for (HashMap::Entry* p = id_to_function_info->Start(); | 2862 for (HashMap::Entry* p = id_to_function_info->Start(); |
| 2987 p != NULL; | 2863 p != NULL; |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3078 writer_->AddString("\"<dummy>\""); | 2954 writer_->AddString("\"<dummy>\""); |
| 3079 for (int i = 1; i < sorted_strings.length(); ++i) { | 2955 for (int i = 1; i < sorted_strings.length(); ++i) { |
| 3080 writer_->AddCharacter(','); | 2956 writer_->AddCharacter(','); |
| 3081 SerializeString(sorted_strings[i]); | 2957 SerializeString(sorted_strings[i]); |
| 3082 if (writer_->aborted()) return; | 2958 if (writer_->aborted()) return; |
| 3083 } | 2959 } |
| 3084 } | 2960 } |
| 3085 | 2961 |
| 3086 | 2962 |
| 3087 } } // namespace v8::internal | 2963 } } // namespace v8::internal |
| OLD | NEW |