| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 59 }; | 59 }; |
| 60 | 60 |
| 61 | 61 |
| 62 // Provides a storage of strings allocated in C++ heap, to hold them | 62 // Provides a storage of strings allocated in C++ heap, to hold them |
| 63 // forever, even if they disappear from JS heap or external storage. | 63 // forever, even if they disappear from JS heap or external storage. |
| 64 class StringsStorage { | 64 class StringsStorage { |
| 65 public: | 65 public: |
| 66 StringsStorage(); | 66 StringsStorage(); |
| 67 ~StringsStorage(); | 67 ~StringsStorage(); |
| 68 | 68 |
| 69 const char* GetCopy(const char* src); |
| 70 const char* GetFormatted(const char* format, ...); |
| 71 const char* GetVFormatted(const char* format, va_list args); |
| 69 const char* GetName(String* name); | 72 const char* GetName(String* name); |
| 70 const char* GetName(int index); | 73 const char* GetName(int index); |
| 71 inline const char* GetFunctionName(String* name); | 74 inline const char* GetFunctionName(String* name); |
| 72 inline const char* GetFunctionName(const char* name); | 75 inline const char* GetFunctionName(const char* name); |
| 73 | 76 |
| 74 private: | 77 private: |
| 75 INLINE(static bool StringsMatch(void* key1, void* key2)) { | 78 INLINE(static bool StringsMatch(void* key1, void* key2)) { |
| 76 return strcmp(reinterpret_cast<char*>(key1), | 79 return strcmp(reinterpret_cast<char*>(key1), |
| 77 reinterpret_cast<char*>(key2)) == 0; | 80 reinterpret_cast<char*>(key2)) == 0; |
| 78 } | 81 } |
| 82 const char* AddOrDisposeString(char* str, uint32_t hash); |
| 79 | 83 |
| 80 // Mapping of strings by String::Hash to const char* strings. | 84 // Mapping of strings by String::Hash to const char* strings. |
| 81 HashMap names_; | 85 HashMap names_; |
| 82 // Mapping from ints to char* strings. | |
| 83 List<char*> index_names_; | |
| 84 | 86 |
| 85 DISALLOW_COPY_AND_ASSIGN(StringsStorage); | 87 DISALLOW_COPY_AND_ASSIGN(StringsStorage); |
| 86 }; | 88 }; |
| 87 | 89 |
| 88 | 90 |
| 89 class CodeEntry { | 91 class CodeEntry { |
| 90 public: | 92 public: |
| 91 explicit INLINE(CodeEntry(int security_token_id)); | |
| 92 // CodeEntry doesn't own name strings, just references them. | 93 // CodeEntry doesn't own name strings, just references them. |
| 93 INLINE(CodeEntry(Logger::LogEventsAndTags tag, | 94 INLINE(CodeEntry(Logger::LogEventsAndTags tag, |
| 94 const char* name_prefix, | 95 const char* name_prefix, |
| 95 const char* name, | 96 const char* name, |
| 96 const char* resource_name, | 97 const char* resource_name, |
| 97 int line_number, | 98 int line_number, |
| 98 int security_token_id)); | 99 int security_token_id)); |
| 99 | 100 |
| 100 INLINE(bool is_js_function() const) { return is_js_function_tag(tag_); } | 101 INLINE(bool is_js_function() const) { return is_js_function_tag(tag_); } |
| 101 INLINE(const char* name_prefix() const) { return name_prefix_; } | 102 INLINE(const char* name_prefix() const) { return name_prefix_; } |
| 102 INLINE(bool has_name_prefix() const) { return name_prefix_[0] != '\0'; } | 103 INLINE(bool has_name_prefix() const) { return name_prefix_[0] != '\0'; } |
| 103 INLINE(const char* name() const) { return name_; } | 104 INLINE(const char* name() const) { return name_; } |
| 104 INLINE(const char* resource_name() const) { return resource_name_; } | 105 INLINE(const char* resource_name() const) { return resource_name_; } |
| 105 INLINE(int line_number() const) { return line_number_; } | 106 INLINE(int line_number() const) { return line_number_; } |
| 107 INLINE(int shared_id() const) { return shared_id_; } |
| 108 INLINE(void set_shared_id(int shared_id)) { shared_id_ = shared_id; } |
| 106 INLINE(int security_token_id() const) { return security_token_id_; } | 109 INLINE(int security_token_id() const) { return security_token_id_; } |
| 107 | 110 |
| 108 INLINE(static bool is_js_function_tag(Logger::LogEventsAndTags tag)); | 111 INLINE(static bool is_js_function_tag(Logger::LogEventsAndTags tag)); |
| 109 | 112 |
| 110 void CopyData(const CodeEntry& source); | 113 void CopyData(const CodeEntry& source); |
| 111 uint32_t GetCallUid() const; | 114 uint32_t GetCallUid() const; |
| 112 bool IsSameAs(CodeEntry* entry) const; | 115 bool IsSameAs(CodeEntry* entry) const; |
| 113 | 116 |
| 114 static const char* kEmptyNamePrefix; | 117 static const char* kEmptyNamePrefix; |
| 115 | 118 |
| 116 private: | 119 private: |
| 117 Logger::LogEventsAndTags tag_; | 120 Logger::LogEventsAndTags tag_; |
| 118 const char* name_prefix_; | 121 const char* name_prefix_; |
| 119 const char* name_; | 122 const char* name_; |
| 120 const char* resource_name_; | 123 const char* resource_name_; |
| 121 int line_number_; | 124 int line_number_; |
| 125 int shared_id_; |
| 122 int security_token_id_; | 126 int security_token_id_; |
| 123 | 127 |
| 124 DISALLOW_COPY_AND_ASSIGN(CodeEntry); | 128 DISALLOW_COPY_AND_ASSIGN(CodeEntry); |
| 125 }; | 129 }; |
| 126 | 130 |
| 127 | 131 |
| 128 class ProfileTree; | 132 class ProfileTree; |
| 129 | 133 |
| 130 class ProfileNode { | 134 class ProfileNode { |
| 131 public: | 135 public: |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 227 unsigned uid_; | 231 unsigned uid_; |
| 228 ProfileTree top_down_; | 232 ProfileTree top_down_; |
| 229 ProfileTree bottom_up_; | 233 ProfileTree bottom_up_; |
| 230 | 234 |
| 231 DISALLOW_COPY_AND_ASSIGN(CpuProfile); | 235 DISALLOW_COPY_AND_ASSIGN(CpuProfile); |
| 232 }; | 236 }; |
| 233 | 237 |
| 234 | 238 |
| 235 class CodeMap { | 239 class CodeMap { |
| 236 public: | 240 public: |
| 237 CodeMap() { } | 241 CodeMap() : next_shared_id_(1) { } |
| 238 INLINE(void AddCode(Address addr, CodeEntry* entry, unsigned size)); | 242 INLINE(void AddCode(Address addr, CodeEntry* entry, unsigned size)); |
| 239 INLINE(void MoveCode(Address from, Address to)); | 243 INLINE(void MoveCode(Address from, Address to)); |
| 240 INLINE(void DeleteCode(Address addr)); | 244 INLINE(void DeleteCode(Address addr)); |
| 241 void AddAlias(Address start, CodeEntry* entry, Address code_start); | |
| 242 CodeEntry* FindEntry(Address addr); | 245 CodeEntry* FindEntry(Address addr); |
| 246 int GetSharedId(Address addr); |
| 243 | 247 |
| 244 void Print(); | 248 void Print(); |
| 245 | 249 |
| 246 private: | 250 private: |
| 247 struct CodeEntryInfo { | 251 struct CodeEntryInfo { |
| 248 CodeEntryInfo(CodeEntry* an_entry, unsigned a_size) | 252 CodeEntryInfo(CodeEntry* an_entry, unsigned a_size) |
| 249 : entry(an_entry), size(a_size) { } | 253 : entry(an_entry), size(a_size) { } |
| 250 CodeEntry* entry; | 254 CodeEntry* entry; |
| 251 unsigned size; | 255 unsigned size; |
| 252 }; | 256 }; |
| 253 | 257 |
| 254 struct CodeTreeConfig { | 258 struct CodeTreeConfig { |
| 255 typedef Address Key; | 259 typedef Address Key; |
| 256 typedef CodeEntryInfo Value; | 260 typedef CodeEntryInfo Value; |
| 257 static const Key kNoKey; | 261 static const Key kNoKey; |
| 258 static const Value kNoValue; | 262 static const Value kNoValue; |
| 259 static int Compare(const Key& a, const Key& b) { | 263 static int Compare(const Key& a, const Key& b) { |
| 260 return a < b ? -1 : (a > b ? 1 : 0); | 264 return a < b ? -1 : (a > b ? 1 : 0); |
| 261 } | 265 } |
| 262 }; | 266 }; |
| 263 typedef SplayTree<CodeTreeConfig> CodeTree; | 267 typedef SplayTree<CodeTreeConfig> CodeTree; |
| 264 | 268 |
| 265 class CodeTreePrinter { | 269 class CodeTreePrinter { |
| 266 public: | 270 public: |
| 267 void Call(const Address& key, const CodeEntryInfo& value); | 271 void Call(const Address& key, const CodeEntryInfo& value); |
| 268 }; | 272 }; |
| 269 | 273 |
| 274 // Fake CodeEntry pointer to distinguish shared function entries. |
| 275 static CodeEntry* const kSharedFunctionCodeEntry; |
| 276 |
| 270 CodeTree tree_; | 277 CodeTree tree_; |
| 278 int next_shared_id_; |
| 271 | 279 |
| 272 DISALLOW_COPY_AND_ASSIGN(CodeMap); | 280 DISALLOW_COPY_AND_ASSIGN(CodeMap); |
| 273 }; | 281 }; |
| 274 | 282 |
| 275 | 283 |
| 276 class CpuProfilesCollection { | 284 class CpuProfilesCollection { |
| 277 public: | 285 public: |
| 278 CpuProfilesCollection(); | 286 CpuProfilesCollection(); |
| 279 ~CpuProfilesCollection(); | 287 ~CpuProfilesCollection(); |
| 280 | 288 |
| (...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 504 class HeapEntry BASE_EMBEDDED { | 512 class HeapEntry BASE_EMBEDDED { |
| 505 public: | 513 public: |
| 506 enum Type { | 514 enum Type { |
| 507 kHidden = v8::HeapGraphNode::kHidden, | 515 kHidden = v8::HeapGraphNode::kHidden, |
| 508 kArray = v8::HeapGraphNode::kArray, | 516 kArray = v8::HeapGraphNode::kArray, |
| 509 kString = v8::HeapGraphNode::kString, | 517 kString = v8::HeapGraphNode::kString, |
| 510 kObject = v8::HeapGraphNode::kObject, | 518 kObject = v8::HeapGraphNode::kObject, |
| 511 kCode = v8::HeapGraphNode::kCode, | 519 kCode = v8::HeapGraphNode::kCode, |
| 512 kClosure = v8::HeapGraphNode::kClosure, | 520 kClosure = v8::HeapGraphNode::kClosure, |
| 513 kRegExp = v8::HeapGraphNode::kRegExp, | 521 kRegExp = v8::HeapGraphNode::kRegExp, |
| 514 kHeapNumber = v8::HeapGraphNode::kHeapNumber | 522 kHeapNumber = v8::HeapGraphNode::kHeapNumber, |
| 523 kNative = v8::HeapGraphNode::kNative |
| 515 }; | 524 }; |
| 516 | 525 |
| 517 HeapEntry() { } | 526 HeapEntry() { } |
| 518 void Init(HeapSnapshot* snapshot, | 527 void Init(HeapSnapshot* snapshot, |
| 519 Type type, | 528 Type type, |
| 520 const char* name, | 529 const char* name, |
| 521 uint64_t id, | 530 uint64_t id, |
| 522 int self_size, | 531 int self_size, |
| 523 int children_count, | 532 int children_count, |
| 524 int retainers_count); | 533 int retainers_count); |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 591 } | 600 } |
| 592 HeapGraphEdge** retainers_arr() { | 601 HeapGraphEdge** retainers_arr() { |
| 593 return reinterpret_cast<HeapGraphEdge**>(children_arr() + children_count_); | 602 return reinterpret_cast<HeapGraphEdge**>(children_arr() + children_count_); |
| 594 } | 603 } |
| 595 void CalculateExactRetainedSize(); | 604 void CalculateExactRetainedSize(); |
| 596 void FindRetainingPaths(CachedHeapGraphPath* prev_path, | 605 void FindRetainingPaths(CachedHeapGraphPath* prev_path, |
| 597 List<HeapGraphPath*>* retaining_paths); | 606 List<HeapGraphPath*>* retaining_paths); |
| 598 const char* TypeAsString(); | 607 const char* TypeAsString(); |
| 599 | 608 |
| 600 unsigned painted_: 2; | 609 unsigned painted_: 2; |
| 601 unsigned type_: 3; | 610 unsigned type_: 4; |
| 602 int children_count_: 27; | 611 int children_count_: 26; |
| 603 int retainers_count_; | 612 int retainers_count_; |
| 604 int self_size_; | 613 int self_size_; |
| 605 union { | 614 union { |
| 606 int ordered_index_; // Used during dominator tree building. | 615 int ordered_index_; // Used during dominator tree building. |
| 607 int retained_size_; // At that moment, there is no retained size yet. | 616 int retained_size_; // At that moment, there is no retained size yet. |
| 608 }; | 617 }; |
| 609 HeapEntry* dominator_; | 618 HeapEntry* dominator_; |
| 610 HeapSnapshot* snapshot_; | 619 HeapSnapshot* snapshot_; |
| 611 struct Id { | 620 struct Id { |
| 612 uint32_t id1_; | 621 uint32_t id1_; |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 664 const char* title, | 673 const char* title, |
| 665 unsigned uid); | 674 unsigned uid); |
| 666 ~HeapSnapshot(); | 675 ~HeapSnapshot(); |
| 667 | 676 |
| 668 HeapSnapshotsCollection* collection() { return collection_; } | 677 HeapSnapshotsCollection* collection() { return collection_; } |
| 669 Type type() { return type_; } | 678 Type type() { return type_; } |
| 670 const char* title() { return title_; } | 679 const char* title() { return title_; } |
| 671 unsigned uid() { return uid_; } | 680 unsigned uid() { return uid_; } |
| 672 HeapEntry* root() { return root_entry_; } | 681 HeapEntry* root() { return root_entry_; } |
| 673 HeapEntry* gc_roots() { return gc_roots_entry_; } | 682 HeapEntry* gc_roots() { return gc_roots_entry_; } |
| 683 HeapEntry* natives_root() { return natives_root_entry_; } |
| 674 List<HeapEntry*>* entries() { return &entries_; } | 684 List<HeapEntry*>* entries() { return &entries_; } |
| 675 | 685 |
| 676 void AllocateEntries( | 686 void AllocateEntries( |
| 677 int entries_count, int children_count, int retainers_count); | 687 int entries_count, int children_count, int retainers_count); |
| 678 HeapEntry* AddEntry( | |
| 679 HeapObject* object, int children_count, int retainers_count); | |
| 680 HeapEntry* AddEntry(HeapEntry::Type type, | 688 HeapEntry* AddEntry(HeapEntry::Type type, |
| 681 const char* name, | 689 const char* name, |
| 682 uint64_t id, | 690 uint64_t id, |
| 683 int size, | 691 int size, |
| 684 int children_count, | 692 int children_count, |
| 685 int retainers_count); | 693 int retainers_count); |
| 694 HeapEntry* AddRootEntry(int children_count); |
| 695 HeapEntry* AddGcRootsEntry(int children_count, int retainers_count); |
| 696 HeapEntry* AddNativesRootEntry(int children_count, int retainers_count); |
| 686 void ClearPaint(); | 697 void ClearPaint(); |
| 687 HeapSnapshotsDiff* CompareWith(HeapSnapshot* snapshot); | 698 HeapSnapshotsDiff* CompareWith(HeapSnapshot* snapshot); |
| 688 HeapEntry* GetEntryById(uint64_t id); | 699 HeapEntry* GetEntryById(uint64_t id); |
| 689 List<HeapGraphPath*>* GetRetainingPaths(HeapEntry* entry); | 700 List<HeapGraphPath*>* GetRetainingPaths(HeapEntry* entry); |
| 690 List<HeapEntry*>* GetSortedEntriesList(); | 701 List<HeapEntry*>* GetSortedEntriesList(); |
| 691 template<class Visitor> | 702 template<class Visitor> |
| 692 void IterateEntries(Visitor* visitor) { entries_.Iterate(visitor); } | 703 void IterateEntries(Visitor* visitor) { entries_.Iterate(visitor); } |
| 693 void SetDominatorsToSelf(); | 704 void SetDominatorsToSelf(); |
| 694 | 705 |
| 695 void Print(int max_depth); | 706 void Print(int max_depth); |
| 696 void PrintEntriesSize(); | 707 void PrintEntriesSize(); |
| 697 | 708 |
| 698 static HeapObject* const kInternalRootObject; | |
| 699 static HeapObject* const kGcRootsObject; | |
| 700 | |
| 701 private: | 709 private: |
| 702 HeapEntry* AddEntry(HeapObject* object, | |
| 703 HeapEntry::Type type, | |
| 704 const char* name, | |
| 705 int children_count, | |
| 706 int retainers_count); | |
| 707 HeapEntry* GetNextEntryToInit(); | 710 HeapEntry* GetNextEntryToInit(); |
| 708 | 711 |
| 709 HeapSnapshotsCollection* collection_; | 712 HeapSnapshotsCollection* collection_; |
| 710 Type type_; | 713 Type type_; |
| 711 const char* title_; | 714 const char* title_; |
| 712 unsigned uid_; | 715 unsigned uid_; |
| 713 HeapEntry* root_entry_; | 716 HeapEntry* root_entry_; |
| 714 HeapEntry* gc_roots_entry_; | 717 HeapEntry* gc_roots_entry_; |
| 718 HeapEntry* natives_root_entry_; |
| 715 char* raw_entries_; | 719 char* raw_entries_; |
| 716 List<HeapEntry*> entries_; | 720 List<HeapEntry*> entries_; |
| 717 bool entries_sorted_; | 721 bool entries_sorted_; |
| 718 HashMap retaining_paths_; | 722 HashMap retaining_paths_; |
| 719 #ifdef DEBUG | 723 #ifdef DEBUG |
| 720 int raw_entries_size_; | 724 int raw_entries_size_; |
| 721 #endif | 725 #endif |
| 722 | 726 |
| 723 friend class HeapSnapshotTester; | 727 friend class HeapSnapshotTester; |
| 724 | 728 |
| 725 DISALLOW_COPY_AND_ASSIGN(HeapSnapshot); | 729 DISALLOW_COPY_AND_ASSIGN(HeapSnapshot); |
| 726 }; | 730 }; |
| 727 | 731 |
| 728 | 732 |
| 729 class HeapObjectsMap { | 733 class HeapObjectsMap { |
| 730 public: | 734 public: |
| 731 HeapObjectsMap(); | 735 HeapObjectsMap(); |
| 732 ~HeapObjectsMap(); | 736 ~HeapObjectsMap(); |
| 733 | 737 |
| 734 void SnapshotGenerationFinished(); | 738 void SnapshotGenerationFinished(); |
| 735 uint64_t FindObject(Address addr); | 739 uint64_t FindObject(Address addr); |
| 736 void MoveObject(Address from, Address to); | 740 void MoveObject(Address from, Address to); |
| 737 | 741 |
| 742 static uint64_t GenerateId(v8::RetainedObjectInfo* info); |
| 743 |
| 738 static const uint64_t kInternalRootObjectId; | 744 static const uint64_t kInternalRootObjectId; |
| 739 static const uint64_t kGcRootsObjectId; | 745 static const uint64_t kGcRootsObjectId; |
| 746 static const uint64_t kNativesRootObjectId; |
| 740 static const uint64_t kFirstAvailableObjectId; | 747 static const uint64_t kFirstAvailableObjectId; |
| 741 | 748 |
| 742 private: | 749 private: |
| 743 struct EntryInfo { | 750 struct EntryInfo { |
| 744 explicit EntryInfo(uint64_t id) : id(id), accessed(true) { } | 751 explicit EntryInfo(uint64_t id) : id(id), accessed(true) { } |
| 745 EntryInfo(uint64_t id, bool accessed) : id(id), accessed(accessed) { } | 752 EntryInfo(uint64_t id, bool accessed) : id(id), accessed(accessed) { } |
| 746 uint64_t id; | 753 uint64_t id; |
| 747 bool accessed; | 754 bool accessed; |
| 748 }; | 755 }; |
| 749 | 756 |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 827 ~HeapSnapshotsCollection(); | 834 ~HeapSnapshotsCollection(); |
| 828 | 835 |
| 829 bool is_tracking_objects() { return is_tracking_objects_; } | 836 bool is_tracking_objects() { return is_tracking_objects_; } |
| 830 | 837 |
| 831 HeapSnapshot* NewSnapshot( | 838 HeapSnapshot* NewSnapshot( |
| 832 HeapSnapshot::Type type, const char* name, unsigned uid); | 839 HeapSnapshot::Type type, const char* name, unsigned uid); |
| 833 void SnapshotGenerationFinished(HeapSnapshot* snapshot); | 840 void SnapshotGenerationFinished(HeapSnapshot* snapshot); |
| 834 List<HeapSnapshot*>* snapshots() { return &snapshots_; } | 841 List<HeapSnapshot*>* snapshots() { return &snapshots_; } |
| 835 HeapSnapshot* GetSnapshot(unsigned uid); | 842 HeapSnapshot* GetSnapshot(unsigned uid); |
| 836 | 843 |
| 837 const char* GetName(String* name) { return names_.GetName(name); } | 844 StringsStorage* names() { return &names_; } |
| 838 const char* GetName(int index) { return names_.GetName(index); } | |
| 839 const char* GetFunctionName(String* name) { | |
| 840 return names_.GetFunctionName(name); | |
| 841 } | |
| 842 | |
| 843 TokenEnumerator* token_enumerator() { return token_enumerator_; } | 845 TokenEnumerator* token_enumerator() { return token_enumerator_; } |
| 844 | 846 |
| 845 uint64_t GetObjectId(Address addr) { return ids_.FindObject(addr); } | 847 uint64_t GetObjectId(Address addr) { return ids_.FindObject(addr); } |
| 846 void ObjectMoveEvent(Address from, Address to) { ids_.MoveObject(from, to); } | 848 void ObjectMoveEvent(Address from, Address to) { ids_.MoveObject(from, to); } |
| 847 | 849 |
| 848 HeapSnapshotsDiff* CompareSnapshots(HeapSnapshot* snapshot1, | 850 HeapSnapshotsDiff* CompareSnapshots(HeapSnapshot* snapshot1, |
| 849 HeapSnapshot* snapshot2); | 851 HeapSnapshot* snapshot2); |
| 850 | 852 |
| 851 private: | 853 private: |
| 852 INLINE(static bool HeapSnapshotsMatch(void* key1, void* key2)) { | 854 INLINE(static bool HeapSnapshotsMatch(void* key1, void* key2)) { |
| 853 return key1 == key2; | 855 return key1 == key2; |
| 854 } | 856 } |
| 855 | 857 |
| 856 bool is_tracking_objects_; // Whether tracking object moves is needed. | 858 bool is_tracking_objects_; // Whether tracking object moves is needed. |
| 857 List<HeapSnapshot*> snapshots_; | 859 List<HeapSnapshot*> snapshots_; |
| 858 // Mapping from snapshots' uids to HeapSnapshot* pointers. | 860 // Mapping from snapshots' uids to HeapSnapshot* pointers. |
| 859 HashMap snapshots_uids_; | 861 HashMap snapshots_uids_; |
| 860 StringsStorage names_; | 862 StringsStorage names_; |
| 861 TokenEnumerator* token_enumerator_; | 863 TokenEnumerator* token_enumerator_; |
| 862 // Mapping from HeapObject addresses to objects' uids. | 864 // Mapping from HeapObject addresses to objects' uids. |
| 863 HeapObjectsMap ids_; | 865 HeapObjectsMap ids_; |
| 864 HeapSnapshotsComparator comparator_; | 866 HeapSnapshotsComparator comparator_; |
| 865 | 867 |
| 866 DISALLOW_COPY_AND_ASSIGN(HeapSnapshotsCollection); | 868 DISALLOW_COPY_AND_ASSIGN(HeapSnapshotsCollection); |
| 867 }; | 869 }; |
| 868 | 870 |
| 869 | 871 |
| 872 // A typedef for referencing anything that can be snapshotted living |
| 873 // in any kind of heap memory. |
| 874 typedef void* HeapThing; |
| 875 |
| 876 |
| 877 // An interface that creates HeapEntries by HeapThings. |
| 878 class HeapEntriesAllocator { |
| 879 public: |
| 880 virtual ~HeapEntriesAllocator() { } |
| 881 virtual HeapEntry* AllocateEntry( |
| 882 HeapThing ptr, int children_count, int retainers_count) = 0; |
| 883 }; |
| 884 |
| 885 |
| 870 // The HeapEntriesMap instance is used to track a mapping between | 886 // The HeapEntriesMap instance is used to track a mapping between |
| 871 // real heap objects and their representations in heap snapshots. | 887 // real heap objects and their representations in heap snapshots. |
| 872 class HeapEntriesMap { | 888 class HeapEntriesMap { |
| 873 public: | 889 public: |
| 874 HeapEntriesMap(); | 890 HeapEntriesMap(); |
| 875 ~HeapEntriesMap(); | 891 ~HeapEntriesMap(); |
| 876 | 892 |
| 877 HeapEntry* Map(HeapObject* object); | 893 void AllocateEntries(); |
| 878 void Pair(HeapObject* object, HeapEntry* entry); | 894 HeapEntry* Map(HeapThing thing); |
| 879 void CountReference(HeapObject* from, HeapObject* to, | 895 void Pair(HeapThing thing, HeapEntriesAllocator* allocator, HeapEntry* entry); |
| 896 void CountReference(HeapThing from, HeapThing to, |
| 880 int* prev_children_count = NULL, | 897 int* prev_children_count = NULL, |
| 881 int* prev_retainers_count = NULL); | 898 int* prev_retainers_count = NULL); |
| 882 template<class Visitor> | |
| 883 void UpdateEntries(Visitor* visitor); | |
| 884 | 899 |
| 885 int entries_count() { return entries_count_; } | 900 int entries_count() { return entries_count_; } |
| 886 int total_children_count() { return total_children_count_; } | 901 int total_children_count() { return total_children_count_; } |
| 887 int total_retainers_count() { return total_retainers_count_; } | 902 int total_retainers_count() { return total_retainers_count_; } |
| 888 | 903 |
| 889 static HeapEntry *const kHeapEntryPlaceholder; | 904 static HeapEntry *const kHeapEntryPlaceholder; |
| 890 | 905 |
| 891 private: | 906 private: |
| 892 struct EntryInfo { | 907 struct EntryInfo { |
| 893 explicit EntryInfo(HeapEntry* entry) | 908 EntryInfo(HeapEntry* entry, HeapEntriesAllocator* allocator) |
| 894 : entry(entry), children_count(0), retainers_count(0) { } | 909 : entry(entry), |
| 910 allocator(allocator), |
| 911 children_count(0), |
| 912 retainers_count(0) { |
| 913 } |
| 895 HeapEntry* entry; | 914 HeapEntry* entry; |
| 915 HeapEntriesAllocator* allocator; |
| 896 int children_count; | 916 int children_count; |
| 897 int retainers_count; | 917 int retainers_count; |
| 898 }; | 918 }; |
| 899 | 919 |
| 900 static uint32_t Hash(HeapObject* object) { | 920 static uint32_t Hash(HeapThing thing) { |
| 901 return ComputeIntegerHash( | 921 return ComputeIntegerHash( |
| 902 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(object))); | 922 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(thing))); |
| 903 } | 923 } |
| 904 static bool HeapObjectsMatch(void* key1, void* key2) { return key1 == key2; } | 924 static bool HeapThingsMatch(HeapThing key1, HeapThing key2) { |
| 925 return key1 == key2; |
| 926 } |
| 905 | 927 |
| 906 HashMap entries_; | 928 HashMap entries_; |
| 907 int entries_count_; | 929 int entries_count_; |
| 908 int total_children_count_; | 930 int total_children_count_; |
| 909 int total_retainers_count_; | 931 int total_retainers_count_; |
| 910 | 932 |
| 911 friend class HeapObjectsSet; | 933 friend class HeapObjectsSet; |
| 912 | 934 |
| 913 DISALLOW_COPY_AND_ASSIGN(HeapEntriesMap); | 935 DISALLOW_COPY_AND_ASSIGN(HeapEntriesMap); |
| 914 }; | 936 }; |
| 915 | 937 |
| 916 | 938 |
| 917 class HeapObjectsSet { | 939 class HeapObjectsSet { |
| 918 public: | 940 public: |
| 919 HeapObjectsSet(); | 941 HeapObjectsSet(); |
| 920 void Clear(); | 942 void Clear(); |
| 921 bool Contains(Object* object); | 943 bool Contains(Object* object); |
| 922 void Insert(Object* obj); | 944 void Insert(Object* obj); |
| 923 | 945 |
| 924 private: | 946 private: |
| 925 HashMap entries_; | 947 HashMap entries_; |
| 926 | 948 |
| 927 DISALLOW_COPY_AND_ASSIGN(HeapObjectsSet); | 949 DISALLOW_COPY_AND_ASSIGN(HeapObjectsSet); |
| 928 }; | 950 }; |
| 929 | 951 |
| 930 | 952 |
| 931 class HeapSnapshotGenerator { | 953 // An interface used to populate a snapshot with nodes and edges. |
| 954 class SnapshotFillerInterface { |
| 932 public: | 955 public: |
| 933 class SnapshotFillerInterface { | 956 virtual ~SnapshotFillerInterface() { } |
| 934 public: | 957 virtual HeapEntry* AddEntry(HeapThing ptr, |
| 935 virtual ~SnapshotFillerInterface() { } | 958 HeapEntriesAllocator* allocator) = 0; |
| 936 virtual HeapEntry* AddEntry(HeapObject* obj) = 0; | 959 virtual HeapEntry* FindEntry(HeapThing ptr) = 0; |
| 937 virtual void SetIndexedReference(HeapGraphEdge::Type type, | 960 virtual HeapEntry* FindOrAddEntry(HeapThing ptr, |
| 938 HeapObject* parent_obj, | 961 HeapEntriesAllocator* allocator) = 0; |
| 939 HeapEntry* parent_entry, | 962 virtual void SetIndexedReference(HeapGraphEdge::Type type, |
| 940 int index, | 963 HeapThing parent_ptr, |
| 941 Object* child_obj, | |
| 942 HeapEntry* child_entry) = 0; | |
| 943 virtual void SetNamedReference(HeapGraphEdge::Type type, | |
| 944 HeapObject* parent_obj, | |
| 945 HeapEntry* parent_entry, | 964 HeapEntry* parent_entry, |
| 946 const char* reference_name, | 965 int index, |
| 947 Object* child_obj, | 966 HeapThing child_ptr, |
| 948 HeapEntry* child_entry) = 0; | 967 HeapEntry* child_entry) = 0; |
| 949 virtual void SetRootGcRootsReference() = 0; | 968 virtual void SetIndexedAutoIndexReference(HeapGraphEdge::Type type, |
| 950 virtual void SetRootShortcutReference(Object* child_obj, | 969 HeapThing parent_ptr, |
| 970 HeapEntry* parent_entry, |
| 971 HeapThing child_ptr, |
| 972 HeapEntry* child_entry) = 0; |
| 973 virtual void SetNamedReference(HeapGraphEdge::Type type, |
| 974 HeapThing parent_ptr, |
| 975 HeapEntry* parent_entry, |
| 976 const char* reference_name, |
| 977 HeapThing child_ptr, |
| 978 HeapEntry* child_entry) = 0; |
| 979 virtual void SetNamedAutoIndexReference(HeapGraphEdge::Type type, |
| 980 HeapThing parent_ptr, |
| 981 HeapEntry* parent_entry, |
| 982 HeapThing child_ptr, |
| 951 HeapEntry* child_entry) = 0; | 983 HeapEntry* child_entry) = 0; |
| 952 virtual void SetStrongRootReference(Object* child_obj, | 984 }; |
| 953 HeapEntry* child_entry) = 0; | |
| 954 }; | |
| 955 | 985 |
| 956 HeapSnapshotGenerator(HeapSnapshot* snapshot, | 986 |
| 957 v8::ActivityControl* control); | 987 class SnapshottingProgressReportingInterface { |
| 958 bool GenerateSnapshot(); | 988 public: |
| 989 virtual ~SnapshottingProgressReportingInterface() { } |
| 990 virtual void ProgressStep() = 0; |
| 991 virtual bool ProgressReport(bool force) = 0; |
| 992 }; |
| 993 |
| 994 |
| 995 // An implementation of V8 heap graph extractor. |
| 996 class V8HeapExplorer : public HeapEntriesAllocator { |
| 997 public: |
| 998 V8HeapExplorer(HeapSnapshot* snapshot, |
| 999 SnapshottingProgressReportingInterface* progress); |
| 1000 virtual ~V8HeapExplorer(); |
| 1001 virtual HeapEntry* AllocateEntry( |
| 1002 HeapThing ptr, int children_count, int retainers_count); |
| 1003 void AddRootEntries(SnapshotFillerInterface* filler); |
| 1004 int EstimateObjectsCount(); |
| 1005 bool IterateAndExtractReferences(SnapshotFillerInterface* filler); |
| 1006 |
| 1007 static HeapObject* const kInternalRootObject; |
| 959 | 1008 |
| 960 private: | 1009 private: |
| 961 bool ApproximateRetainedSizes(); | 1010 HeapEntry* AddEntry( |
| 962 bool BuildDominatorTree(const Vector<HeapEntry*>& entries, | 1011 HeapObject* object, int children_count, int retainers_count); |
| 963 Vector<HeapEntry*>* dominators); | 1012 HeapEntry* AddEntry(HeapObject* object, |
| 964 bool CountEntriesAndReferences(); | 1013 HeapEntry::Type type, |
| 965 HeapEntry* GetEntry(Object* obj); | 1014 const char* name, |
| 966 void IncProgressCounter() { ++progress_counter_; } | 1015 int children_count, |
| 1016 int retainers_count); |
| 967 void ExtractReferences(HeapObject* obj); | 1017 void ExtractReferences(HeapObject* obj); |
| 968 void ExtractClosureReferences(JSObject* js_obj, HeapEntry* entry); | 1018 void ExtractClosureReferences(JSObject* js_obj, HeapEntry* entry); |
| 969 void ExtractPropertyReferences(JSObject* js_obj, HeapEntry* entry); | 1019 void ExtractPropertyReferences(JSObject* js_obj, HeapEntry* entry); |
| 970 void ExtractElementReferences(JSObject* js_obj, HeapEntry* entry); | 1020 void ExtractElementReferences(JSObject* js_obj, HeapEntry* entry); |
| 971 void ExtractInternalReferences(JSObject* js_obj, HeapEntry* entry); | 1021 void ExtractInternalReferences(JSObject* js_obj, HeapEntry* entry); |
| 972 bool FillReferences(); | |
| 973 void FillReversePostorderIndexes(Vector<HeapEntry*>* entries); | |
| 974 bool IterateAndExtractReferences(); | |
| 975 inline bool ReportProgress(bool force = false); | |
| 976 bool SetEntriesDominators(); | |
| 977 void SetClosureReference(HeapObject* parent_obj, | 1022 void SetClosureReference(HeapObject* parent_obj, |
| 978 HeapEntry* parent, | 1023 HeapEntry* parent, |
| 979 String* reference_name, | 1024 String* reference_name, |
| 980 Object* child); | 1025 Object* child); |
| 981 void SetElementReference(HeapObject* parent_obj, | 1026 void SetElementReference(HeapObject* parent_obj, |
| 982 HeapEntry* parent, | 1027 HeapEntry* parent, |
| 983 int index, | 1028 int index, |
| 984 Object* child); | 1029 Object* child); |
| 985 void SetInternalReference(HeapObject* parent_obj, | 1030 void SetInternalReference(HeapObject* parent_obj, |
| 986 HeapEntry* parent, | 1031 HeapEntry* parent, |
| (...skipping 11 matching lines...) Expand all Loading... |
| 998 HeapEntry* parent, | 1043 HeapEntry* parent, |
| 999 String* reference_name, | 1044 String* reference_name, |
| 1000 Object* child); | 1045 Object* child); |
| 1001 void SetPropertyShortcutReference(HeapObject* parent_obj, | 1046 void SetPropertyShortcutReference(HeapObject* parent_obj, |
| 1002 HeapEntry* parent, | 1047 HeapEntry* parent, |
| 1003 String* reference_name, | 1048 String* reference_name, |
| 1004 Object* child); | 1049 Object* child); |
| 1005 void SetRootShortcutReference(Object* child); | 1050 void SetRootShortcutReference(Object* child); |
| 1006 void SetRootGcRootsReference(); | 1051 void SetRootGcRootsReference(); |
| 1007 void SetGcRootsReference(Object* child); | 1052 void SetGcRootsReference(Object* child); |
| 1053 |
| 1054 HeapEntry* GetEntry(Object* obj); |
| 1055 |
| 1056 HeapSnapshot* snapshot_; |
| 1057 HeapSnapshotsCollection* collection_; |
| 1058 SnapshottingProgressReportingInterface* progress_; |
| 1059 // Used during references extraction to mark heap objects that |
| 1060 // are references via non-hidden properties. |
| 1061 HeapObjectsSet known_references_; |
| 1062 SnapshotFillerInterface* filler_; |
| 1063 |
| 1064 static HeapObject* const kGcRootsObject; |
| 1065 |
| 1066 friend class IndexedReferencesExtractor; |
| 1067 friend class RootsReferencesExtractor; |
| 1068 |
| 1069 DISALLOW_COPY_AND_ASSIGN(V8HeapExplorer); |
| 1070 }; |
| 1071 |
| 1072 |
| 1073 // An implementation of retained native objects extractor. |
| 1074 class NativeObjectsExplorer : public HeapEntriesAllocator { |
| 1075 public: |
| 1076 NativeObjectsExplorer(HeapSnapshot* snapshot, |
| 1077 SnapshottingProgressReportingInterface* progress); |
| 1078 virtual ~NativeObjectsExplorer(); |
| 1079 virtual HeapEntry* AllocateEntry( |
| 1080 HeapThing ptr, int children_count, int retainers_count); |
| 1081 void AddRootEntries(SnapshotFillerInterface* filler); |
| 1082 int EstimateObjectsCount(); |
| 1083 bool IterateAndExtractReferences(SnapshotFillerInterface* filler); |
| 1084 |
| 1085 private: |
| 1086 void FillRetainedObjects(); |
| 1087 List<HeapObject*>* GetListMaybeDisposeInfo(v8::RetainedObjectInfo* info); |
| 1088 void SetNativeRootReference(v8::RetainedObjectInfo* info); |
| 1089 void SetRootNativesRootReference(); |
| 1090 void SetWrapperNativeReferences(HeapObject* wrapper, |
| 1091 v8::RetainedObjectInfo* info); |
| 1092 void VisitSubtreeWrapper(Object** p, uint16_t class_id); |
| 1093 |
| 1094 static uint32_t InfoHash(v8::RetainedObjectInfo* info) { |
| 1095 return ComputeIntegerHash(static_cast<uint32_t>(info->GetHash())); |
| 1096 } |
| 1097 static bool RetainedInfosMatch(void* key1, void* key2) { |
| 1098 return key1 == key2 || |
| 1099 (reinterpret_cast<v8::RetainedObjectInfo*>(key1))->IsEquivalent( |
| 1100 reinterpret_cast<v8::RetainedObjectInfo*>(key2)); |
| 1101 } |
| 1102 |
| 1103 HeapSnapshot* snapshot_; |
| 1104 HeapSnapshotsCollection* collection_; |
| 1105 SnapshottingProgressReportingInterface* progress_; |
| 1106 bool embedder_queried_; |
| 1107 HeapObjectsSet in_groups_; |
| 1108 // RetainedObjectInfo* -> List<HeapObject*>* |
| 1109 HashMap objects_by_info_; |
| 1110 // Used during references extraction. |
| 1111 SnapshotFillerInterface* filler_; |
| 1112 |
| 1113 static HeapThing const kNativesRootObject; |
| 1114 |
| 1115 friend class GlobalHandlesExtractor; |
| 1116 |
| 1117 DISALLOW_COPY_AND_ASSIGN(NativeObjectsExplorer); |
| 1118 }; |
| 1119 |
| 1120 |
| 1121 class HeapSnapshotGenerator : public SnapshottingProgressReportingInterface { |
| 1122 public: |
| 1123 HeapSnapshotGenerator(HeapSnapshot* snapshot, |
| 1124 v8::ActivityControl* control); |
| 1125 bool GenerateSnapshot(); |
| 1126 |
| 1127 private: |
| 1128 bool ApproximateRetainedSizes(); |
| 1129 bool BuildDominatorTree(const Vector<HeapEntry*>& entries, |
| 1130 Vector<HeapEntry*>* dominators); |
| 1131 bool CountEntriesAndReferences(); |
| 1132 bool FillReferences(); |
| 1133 void FillReversePostorderIndexes(Vector<HeapEntry*>* entries); |
| 1134 void ProgressStep(); |
| 1135 bool ProgressReport(bool force = false); |
| 1136 bool SetEntriesDominators(); |
| 1008 void SetProgressTotal(int iterations_count); | 1137 void SetProgressTotal(int iterations_count); |
| 1009 | 1138 |
| 1010 HeapSnapshot* snapshot_; | 1139 HeapSnapshot* snapshot_; |
| 1011 v8::ActivityControl* control_; | 1140 v8::ActivityControl* control_; |
| 1012 HeapSnapshotsCollection* collection_; | 1141 V8HeapExplorer v8_heap_explorer_; |
| 1013 // Mapping from HeapObject* pointers to HeapEntry* pointers. | 1142 NativeObjectsExplorer dom_explorer_; |
| 1143 // Mapping from HeapThing pointers to HeapEntry* pointers. |
| 1014 HeapEntriesMap entries_; | 1144 HeapEntriesMap entries_; |
| 1015 SnapshotFillerInterface* filler_; | |
| 1016 // Used during references extraction to mark heap objects that | |
| 1017 // are references via non-hidden properties. | |
| 1018 HeapObjectsSet known_references_; | |
| 1019 // Used during snapshot generation. | 1145 // Used during snapshot generation. |
| 1020 int progress_counter_; | 1146 int progress_counter_; |
| 1021 int progress_total_; | 1147 int progress_total_; |
| 1022 | 1148 |
| 1023 friend class IndexedReferencesExtractor; | |
| 1024 friend class RootsReferencesExtractor; | |
| 1025 | |
| 1026 DISALLOW_COPY_AND_ASSIGN(HeapSnapshotGenerator); | 1149 DISALLOW_COPY_AND_ASSIGN(HeapSnapshotGenerator); |
| 1027 }; | 1150 }; |
| 1028 | 1151 |
| 1029 class OutputStreamWriter; | 1152 class OutputStreamWriter; |
| 1030 | 1153 |
| 1031 class HeapSnapshotJSONSerializer { | 1154 class HeapSnapshotJSONSerializer { |
| 1032 public: | 1155 public: |
| 1033 explicit HeapSnapshotJSONSerializer(HeapSnapshot* snapshot) | 1156 explicit HeapSnapshotJSONSerializer(HeapSnapshot* snapshot) |
| 1034 : snapshot_(snapshot), | 1157 : snapshot_(snapshot), |
| 1035 nodes_(ObjectsMatch), | 1158 nodes_(ObjectsMatch), |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1076 }; | 1199 }; |
| 1077 | 1200 |
| 1078 | 1201 |
| 1079 String* GetConstructorNameForHeapProfile(JSObject* object); | 1202 String* GetConstructorNameForHeapProfile(JSObject* object); |
| 1080 | 1203 |
| 1081 } } // namespace v8::internal | 1204 } } // namespace v8::internal |
| 1082 | 1205 |
| 1083 #endif // ENABLE_LOGGING_AND_PROFILING | 1206 #endif // ENABLE_LOGGING_AND_PROFILING |
| 1084 | 1207 |
| 1085 #endif // V8_PROFILE_GENERATOR_H_ | 1208 #endif // V8_PROFILE_GENERATOR_H_ |
| OLD | NEW |