| 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 811 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 822 *entry++ = EntryForVMState(sample.state); | 822 *entry++ = EntryForVMState(sample.state); |
| 823 } | 823 } |
| 824 } | 824 } |
| 825 | 825 |
| 826 profiles_->AddPathToCurrentProfiles(entries); | 826 profiles_->AddPathToCurrentProfiles(entries); |
| 827 } | 827 } |
| 828 | 828 |
| 829 | 829 |
| 830 void HeapGraphEdge::Init( | 830 void HeapGraphEdge::Init( |
| 831 int child_index, Type type, const char* name, HeapEntry* to) { | 831 int child_index, Type type, const char* name, HeapEntry* to) { |
| 832 ASSERT(type == kContextVariable || type == kProperty || type == kInternal); | 832 ASSERT(type == kContextVariable |
| 833 || type == kProperty |
| 834 || type == kInternal |
| 835 || type == kShortcut); |
| 833 child_index_ = child_index; | 836 child_index_ = child_index; |
| 834 type_ = type; | 837 type_ = type; |
| 835 name_ = name; | 838 name_ = name; |
| 836 to_ = to; | 839 to_ = to; |
| 837 } | 840 } |
| 838 | 841 |
| 839 | 842 |
| 843 void HeapGraphEdge::Init(int child_index, Type type, int index, HeapEntry* to) { |
| 844 ASSERT(type == kElement || type == kHidden); |
| 845 child_index_ = child_index; |
| 846 type_ = type; |
| 847 index_ = index; |
| 848 to_ = to; |
| 849 } |
| 850 |
| 851 |
| 840 void HeapGraphEdge::Init(int child_index, int index, HeapEntry* to) { | 852 void HeapGraphEdge::Init(int child_index, int index, HeapEntry* to) { |
| 841 child_index_ = child_index; | 853 Init(child_index, kElement, index, to); |
| 842 type_ = kElement; | |
| 843 index_ = index; | |
| 844 to_ = to; | |
| 845 } | 854 } |
| 846 | 855 |
| 847 | 856 |
| 848 HeapEntry* HeapGraphEdge::From() { | 857 HeapEntry* HeapGraphEdge::From() { |
| 849 return reinterpret_cast<HeapEntry*>(this - child_index_) - 1; | 858 return reinterpret_cast<HeapEntry*>(this - child_index_) - 1; |
| 850 } | 859 } |
| 851 | 860 |
| 852 | 861 |
| 853 void HeapEntry::Init(HeapSnapshot* snapshot, | 862 void HeapEntry::Init(HeapSnapshot* snapshot, |
| 854 Type type, | 863 Type type, |
| 855 const char* name, | 864 const char* name, |
| 856 uint64_t id, | 865 uint64_t id, |
| 857 int self_size, | 866 int self_size, |
| 858 int children_count, | 867 int children_count, |
| 859 int retainers_count) { | 868 int retainers_count) { |
| 860 snapshot_ = snapshot; | 869 snapshot_ = snapshot; |
| 861 type_ = type; | 870 type_ = type; |
| 862 painted_ = kUnpainted; | 871 painted_ = kUnpainted; |
| 863 calculated_data_index_ = kNoCalculatedData; | |
| 864 name_ = name; | 872 name_ = name; |
| 865 id_ = id; | |
| 866 self_size_ = self_size; | 873 self_size_ = self_size; |
| 874 retained_size_ = 0; |
| 867 children_count_ = children_count; | 875 children_count_ = children_count; |
| 868 retainers_count_ = retainers_count; | 876 retainers_count_ = retainers_count; |
| 877 dominator_ = NULL; |
| 878 |
| 879 union { |
| 880 uint64_t set_id; |
| 881 Id stored_id; |
| 882 } id_adaptor = {id}; |
| 883 id_ = id_adaptor.stored_id; |
| 869 } | 884 } |
| 870 | 885 |
| 871 | 886 |
| 872 void HeapEntry::SetNamedReference(HeapGraphEdge::Type type, | 887 void HeapEntry::SetNamedReference(HeapGraphEdge::Type type, |
| 873 int child_index, | 888 int child_index, |
| 874 const char* name, | 889 const char* name, |
| 875 HeapEntry* entry, | 890 HeapEntry* entry, |
| 876 int retainer_index) { | 891 int retainer_index) { |
| 877 children_arr()[child_index].Init(child_index, type, name, entry); | 892 children_arr()[child_index].Init(child_index, type, name, entry); |
| 878 entry->retainers_arr()[retainer_index] = children_arr() + child_index; | 893 entry->retainers_arr()[retainer_index] = children_arr() + child_index; |
| 879 } | 894 } |
| 880 | 895 |
| 881 | 896 |
| 882 void HeapEntry::SetElementReference( | 897 void HeapEntry::SetIndexedReference(HeapGraphEdge::Type type, |
| 883 int child_index, int index, HeapEntry* entry, int retainer_index) { | 898 int child_index, |
| 884 children_arr()[child_index].Init(child_index, index, entry); | 899 int index, |
| 900 HeapEntry* entry, |
| 901 int retainer_index) { |
| 902 children_arr()[child_index].Init(child_index, type, index, entry); |
| 885 entry->retainers_arr()[retainer_index] = children_arr() + child_index; | 903 entry->retainers_arr()[retainer_index] = children_arr() + child_index; |
| 886 } | 904 } |
| 887 | 905 |
| 888 | 906 |
| 889 void HeapEntry::SetUnidirElementReference( | 907 void HeapEntry::SetUnidirElementReference( |
| 890 int child_index, int index, HeapEntry* entry) { | 908 int child_index, int index, HeapEntry* entry) { |
| 891 children_arr()[child_index].Init(child_index, index, entry); | 909 children_arr()[child_index].Init(child_index, index, entry); |
| 892 } | 910 } |
| 893 | 911 |
| 894 | 912 |
| 895 int HeapEntry::ReachableSize() { | 913 int HeapEntry::RetainedSize(bool exact) { |
| 896 if (calculated_data_index_ == kNoCalculatedData) { | 914 if (exact && (retained_size_ & kExactRetainedSizeTag) == 0) { |
| 897 calculated_data_index_ = snapshot_->AddCalculatedData(); | 915 CalculateExactRetainedSize(); |
| 898 } | 916 } |
| 899 return snapshot_->GetCalculatedData( | 917 return retained_size_ & (~kExactRetainedSizeTag); |
| 900 calculated_data_index_).ReachableSize(this); | |
| 901 } | |
| 902 | |
| 903 | |
| 904 int HeapEntry::RetainedSize() { | |
| 905 if (calculated_data_index_ == kNoCalculatedData) { | |
| 906 calculated_data_index_ = snapshot_->AddCalculatedData(); | |
| 907 } | |
| 908 return snapshot_->GetCalculatedData( | |
| 909 calculated_data_index_).RetainedSize(this); | |
| 910 } | 918 } |
| 911 | 919 |
| 912 | 920 |
| 913 List<HeapGraphPath*>* HeapEntry::GetRetainingPaths() { | 921 List<HeapGraphPath*>* HeapEntry::GetRetainingPaths() { |
| 914 if (calculated_data_index_ == kNoCalculatedData) { | 922 return snapshot_->GetRetainingPaths(this); |
| 915 calculated_data_index_ = snapshot_->AddCalculatedData(); | |
| 916 } | |
| 917 return snapshot_->GetCalculatedData( | |
| 918 calculated_data_index_).GetRetainingPaths(this); | |
| 919 } | 923 } |
| 920 | 924 |
| 921 | 925 |
| 922 template<class Visitor> | 926 template<class Visitor> |
| 923 void HeapEntry::ApplyAndPaintAllReachable(Visitor* visitor) { | 927 void HeapEntry::ApplyAndPaintAllReachable(Visitor* visitor) { |
| 924 List<HeapEntry*> list(10); | 928 List<HeapEntry*> list(10); |
| 925 list.Add(this); | 929 list.Add(this); |
| 926 this->paint_reachable(); | 930 this->paint_reachable(); |
| 927 visitor->Apply(this); | 931 visitor->Apply(this); |
| 928 while (!list.is_empty()) { | 932 while (!list.is_empty()) { |
| 929 HeapEntry* entry = list.RemoveLast(); | 933 HeapEntry* entry = list.RemoveLast(); |
| 930 Vector<HeapGraphEdge> children = entry->children(); | 934 Vector<HeapGraphEdge> children = entry->children(); |
| 931 for (int i = 0; i < children.length(); ++i) { | 935 for (int i = 0; i < children.length(); ++i) { |
| 936 if (children[i].type() == HeapGraphEdge::kShortcut) continue; |
| 932 HeapEntry* child = children[i].to(); | 937 HeapEntry* child = children[i].to(); |
| 933 if (!child->painted_reachable()) { | 938 if (!child->painted_reachable()) { |
| 934 list.Add(child); | 939 list.Add(child); |
| 935 child->paint_reachable(); | 940 child->paint_reachable(); |
| 936 visitor->Apply(child); | 941 visitor->Apply(child); |
| 937 } | 942 } |
| 938 } | 943 } |
| 939 } | 944 } |
| 940 } | 945 } |
| 941 | 946 |
| 942 | 947 |
| 943 class NullClass { | 948 class NullClass { |
| 944 public: | 949 public: |
| 945 void Apply(HeapEntry* entry) { } | 950 void Apply(HeapEntry* entry) { } |
| 946 }; | 951 }; |
| 947 | 952 |
| 948 void HeapEntry::PaintAllReachable() { | 953 void HeapEntry::PaintAllReachable() { |
| 949 NullClass null; | 954 NullClass null; |
| 950 ApplyAndPaintAllReachable(&null); | 955 ApplyAndPaintAllReachable(&null); |
| 951 } | 956 } |
| 952 | 957 |
| 953 | 958 |
| 954 void HeapEntry::Print(int max_depth, int indent) { | 959 void HeapEntry::Print(int max_depth, int indent) { |
| 955 OS::Print("%6d %6d %6d [%llu] ", | 960 OS::Print("%6d %6d [%llu] ", self_size(), RetainedSize(false), id()); |
| 956 self_size(), ReachableSize(), RetainedSize(), id_); | |
| 957 if (type() != kString) { | 961 if (type() != kString) { |
| 958 OS::Print("%s %.40s\n", TypeAsString(), name_); | 962 OS::Print("%s %.40s\n", TypeAsString(), name_); |
| 959 } else { | 963 } else { |
| 960 OS::Print("\""); | 964 OS::Print("\""); |
| 961 const char* c = name_; | 965 const char* c = name_; |
| 962 while (*c && (c - name_) <= 40) { | 966 while (*c && (c - name_) <= 40) { |
| 963 if (*c != '\n') | 967 if (*c != '\n') |
| 964 OS::Print("%c", *c); | 968 OS::Print("%c", *c); |
| 965 else | 969 else |
| 966 OS::Print("\\n"); | 970 OS::Print("\\n"); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 978 break; | 982 break; |
| 979 case HeapGraphEdge::kElement: | 983 case HeapGraphEdge::kElement: |
| 980 OS::Print(" %*c %d: ", indent, ' ', edge.index()); | 984 OS::Print(" %*c %d: ", indent, ' ', edge.index()); |
| 981 break; | 985 break; |
| 982 case HeapGraphEdge::kInternal: | 986 case HeapGraphEdge::kInternal: |
| 983 OS::Print(" %*c $%s: ", indent, ' ', edge.name()); | 987 OS::Print(" %*c $%s: ", indent, ' ', edge.name()); |
| 984 break; | 988 break; |
| 985 case HeapGraphEdge::kProperty: | 989 case HeapGraphEdge::kProperty: |
| 986 OS::Print(" %*c %s: ", indent, ' ', edge.name()); | 990 OS::Print(" %*c %s: ", indent, ' ', edge.name()); |
| 987 break; | 991 break; |
| 992 case HeapGraphEdge::kHidden: |
| 993 OS::Print(" %*c $%d: ", indent, ' ', edge.index()); |
| 994 break; |
| 995 case HeapGraphEdge::kShortcut: |
| 996 OS::Print(" %*c ^%s: ", indent, ' ', edge.name()); |
| 997 break; |
| 988 default: | 998 default: |
| 989 OS::Print("!!! unknown edge type: %d ", edge.type()); | 999 OS::Print("!!! unknown edge type: %d ", edge.type()); |
| 990 } | 1000 } |
| 991 edge.to()->Print(max_depth, indent + 2); | 1001 edge.to()->Print(max_depth, indent + 2); |
| 992 } | 1002 } |
| 993 } | 1003 } |
| 994 | 1004 |
| 995 | 1005 |
| 996 const char* HeapEntry::TypeAsString() { | 1006 const char* HeapEntry::TypeAsString() { |
| 997 switch (type()) { | 1007 switch (type()) { |
| 998 case kInternal: return "/internal/"; | 1008 case kHidden: return "/hidden/"; |
| 999 case kObject: return "/object/"; | 1009 case kObject: return "/object/"; |
| 1000 case kClosure: return "/closure/"; | 1010 case kClosure: return "/closure/"; |
| 1001 case kString: return "/string/"; | 1011 case kString: return "/string/"; |
| 1002 case kCode: return "/code/"; | 1012 case kCode: return "/code/"; |
| 1003 case kArray: return "/array/"; | 1013 case kArray: return "/array/"; |
| 1004 case kRegExp: return "/regexp/"; | 1014 case kRegExp: return "/regexp/"; |
| 1005 case kHeapNumber: return "/number/"; | 1015 case kHeapNumber: return "/number/"; |
| 1006 default: return "???"; | 1016 default: return "???"; |
| 1007 } | 1017 } |
| 1008 } | 1018 } |
| 1009 | 1019 |
| 1010 | 1020 |
| 1011 int HeapEntry::EntriesSize(int entries_count, | 1021 int HeapEntry::EntriesSize(int entries_count, |
| 1012 int children_count, | 1022 int children_count, |
| 1013 int retainers_count) { | 1023 int retainers_count) { |
| 1014 return sizeof(HeapEntry) * entries_count // NOLINT | 1024 return sizeof(HeapEntry) * entries_count // NOLINT |
| 1015 + sizeof(HeapGraphEdge) * children_count // NOLINT | 1025 + sizeof(HeapGraphEdge) * children_count // NOLINT |
| 1016 + sizeof(HeapGraphEdge*) * retainers_count; // NOLINT | 1026 + sizeof(HeapGraphEdge*) * retainers_count; // NOLINT |
| 1017 } | 1027 } |
| 1018 | 1028 |
| 1019 | 1029 |
| 1020 static void DeleteHeapGraphPath(HeapGraphPath** path_ptr) { | |
| 1021 delete *path_ptr; | |
| 1022 } | |
| 1023 | |
| 1024 void HeapEntryCalculatedData::Dispose() { | |
| 1025 if (retaining_paths_ != NULL) retaining_paths_->Iterate(DeleteHeapGraphPath); | |
| 1026 delete retaining_paths_; | |
| 1027 } | |
| 1028 | |
| 1029 | |
| 1030 int HeapEntryCalculatedData::ReachableSize(HeapEntry* entry) { | |
| 1031 if (reachable_size_ == kUnknownSize) CalculateSizes(entry); | |
| 1032 return reachable_size_; | |
| 1033 } | |
| 1034 | |
| 1035 | |
| 1036 int HeapEntryCalculatedData::RetainedSize(HeapEntry* entry) { | |
| 1037 if (retained_size_ == kUnknownSize) CalculateSizes(entry); | |
| 1038 return retained_size_; | |
| 1039 } | |
| 1040 | |
| 1041 | |
| 1042 class ReachableSizeCalculator { | |
| 1043 public: | |
| 1044 ReachableSizeCalculator() | |
| 1045 : reachable_size_(0) { | |
| 1046 } | |
| 1047 | |
| 1048 int reachable_size() const { return reachable_size_; } | |
| 1049 | |
| 1050 void Apply(HeapEntry* entry) { | |
| 1051 reachable_size_ += entry->self_size(); | |
| 1052 } | |
| 1053 | |
| 1054 private: | |
| 1055 int reachable_size_; | |
| 1056 }; | |
| 1057 | |
| 1058 class RetainedSizeCalculator { | 1030 class RetainedSizeCalculator { |
| 1059 public: | 1031 public: |
| 1060 RetainedSizeCalculator() | 1032 RetainedSizeCalculator() |
| 1061 : retained_size_(0) { | 1033 : retained_size_(0) { |
| 1062 } | 1034 } |
| 1063 | 1035 |
| 1064 int reained_size() const { return retained_size_; } | 1036 int reained_size() const { return retained_size_; } |
| 1065 | 1037 |
| 1066 void Apply(HeapEntry** entry_ptr) { | 1038 void Apply(HeapEntry** entry_ptr) { |
| 1067 if ((*entry_ptr)->painted_reachable()) { | 1039 if ((*entry_ptr)->painted_reachable()) { |
| 1068 retained_size_ += (*entry_ptr)->self_size(); | 1040 retained_size_ += (*entry_ptr)->self_size(); |
| 1069 } | 1041 } |
| 1070 } | 1042 } |
| 1071 | 1043 |
| 1072 private: | 1044 private: |
| 1073 int retained_size_; | 1045 int retained_size_; |
| 1074 }; | 1046 }; |
| 1075 | 1047 |
| 1076 void HeapEntryCalculatedData::CalculateSizes(HeapEntry* entry) { | 1048 void HeapEntry::CalculateExactRetainedSize() { |
| 1077 // To calculate retained size, first we paint all reachable nodes in | 1049 // To calculate retained size, first we paint all reachable nodes in |
| 1078 // one color (and calculate reachable size as a byproduct), then we | 1050 // one color, then we paint (or re-paint) all nodes reachable from |
| 1079 // paint (or re-paint) all nodes reachable from other nodes with a | 1051 // other nodes with a different color. Then we sum up self sizes of |
| 1080 // different color. Then we consider only nodes painted with the | 1052 // nodes painted with the first color. |
| 1081 // first color for calculating the retained size. | 1053 snapshot()->ClearPaint(); |
| 1082 entry->snapshot()->ClearPaint(); | 1054 PaintAllReachable(); |
| 1083 ReachableSizeCalculator rch_size_calc; | |
| 1084 entry->ApplyAndPaintAllReachable(&rch_size_calc); | |
| 1085 reachable_size_ = rch_size_calc.reachable_size(); | |
| 1086 | 1055 |
| 1087 List<HeapEntry*> list(10); | 1056 List<HeapEntry*> list(10); |
| 1088 HeapEntry* root = entry->snapshot()->root(); | 1057 HeapEntry* root = snapshot()->root(); |
| 1089 if (entry != root) { | 1058 if (this != root) { |
| 1090 list.Add(root); | 1059 list.Add(root); |
| 1091 root->paint_reachable_from_others(); | 1060 root->paint_reachable_from_others(); |
| 1092 } | 1061 } |
| 1093 while (!list.is_empty()) { | 1062 while (!list.is_empty()) { |
| 1094 HeapEntry* curr = list.RemoveLast(); | 1063 HeapEntry* curr = list.RemoveLast(); |
| 1095 Vector<HeapGraphEdge> children = curr->children(); | 1064 Vector<HeapGraphEdge> children = curr->children(); |
| 1096 for (int i = 0; i < children.length(); ++i) { | 1065 for (int i = 0; i < children.length(); ++i) { |
| 1066 if (children[i].type() == HeapGraphEdge::kShortcut) continue; |
| 1097 HeapEntry* child = children[i].to(); | 1067 HeapEntry* child = children[i].to(); |
| 1098 if (child != entry && child->not_painted_reachable_from_others()) { | 1068 if (child != this && child->not_painted_reachable_from_others()) { |
| 1099 list.Add(child); | 1069 list.Add(child); |
| 1100 child->paint_reachable_from_others(); | 1070 child->paint_reachable_from_others(); |
| 1101 } | 1071 } |
| 1102 } | 1072 } |
| 1103 } | 1073 } |
| 1104 | 1074 |
| 1105 RetainedSizeCalculator ret_size_calc; | 1075 RetainedSizeCalculator ret_size_calc; |
| 1106 entry->snapshot()->IterateEntries(&ret_size_calc); | 1076 snapshot()->IterateEntries(&ret_size_calc); |
| 1107 retained_size_ = ret_size_calc.reained_size(); | 1077 retained_size_ = ret_size_calc.reained_size(); |
| 1078 ASSERT((retained_size_ & kExactRetainedSizeTag) == 0); |
| 1079 retained_size_ |= kExactRetainedSizeTag; |
| 1108 } | 1080 } |
| 1109 | 1081 |
| 1110 | 1082 |
| 1111 class CachedHeapGraphPath { | 1083 class CachedHeapGraphPath { |
| 1112 public: | 1084 public: |
| 1113 CachedHeapGraphPath() | 1085 CachedHeapGraphPath() |
| 1114 : nodes_(NodesMatch) { } | 1086 : nodes_(NodesMatch) { } |
| 1115 CachedHeapGraphPath(const CachedHeapGraphPath& src) | 1087 CachedHeapGraphPath(const CachedHeapGraphPath& src) |
| 1116 : nodes_(NodesMatch, &HashMap::DefaultAllocator, src.nodes_.capacity()), | 1088 : nodes_(NodesMatch, &HashMap::DefaultAllocator, src.nodes_.capacity()), |
| 1117 path_(src.path_.length() + 1) { | 1089 path_(src.path_.length() + 1) { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1135 static uint32_t Hash(HeapEntry* entry) { | 1107 static uint32_t Hash(HeapEntry* entry) { |
| 1136 return static_cast<uint32_t>(reinterpret_cast<intptr_t>(entry)); | 1108 return static_cast<uint32_t>(reinterpret_cast<intptr_t>(entry)); |
| 1137 } | 1109 } |
| 1138 static bool NodesMatch(void* key1, void* key2) { return key1 == key2; } | 1110 static bool NodesMatch(void* key1, void* key2) { return key1 == key2; } |
| 1139 | 1111 |
| 1140 HashMap nodes_; | 1112 HashMap nodes_; |
| 1141 List<HeapGraphEdge*> path_; | 1113 List<HeapGraphEdge*> path_; |
| 1142 }; | 1114 }; |
| 1143 | 1115 |
| 1144 | 1116 |
| 1145 List<HeapGraphPath*>* HeapEntryCalculatedData::GetRetainingPaths( | 1117 List<HeapGraphPath*>* HeapEntry::CalculateRetainingPaths() { |
| 1146 HeapEntry* entry) { | 1118 List<HeapGraphPath*>* retaining_paths = new List<HeapGraphPath*>(4); |
| 1147 if (retaining_paths_ == NULL) retaining_paths_ = new List<HeapGraphPath*>(4); | 1119 CachedHeapGraphPath path; |
| 1148 if (retaining_paths_->length() == 0 && entry->retainers().length() != 0) { | 1120 FindRetainingPaths(&path, retaining_paths); |
| 1149 CachedHeapGraphPath path; | 1121 return retaining_paths; |
| 1150 FindRetainingPaths(entry, &path); | |
| 1151 } | |
| 1152 return retaining_paths_; | |
| 1153 } | 1122 } |
| 1154 | 1123 |
| 1155 | 1124 |
| 1156 void HeapEntryCalculatedData::FindRetainingPaths( | 1125 void HeapEntry::FindRetainingPaths(CachedHeapGraphPath* prev_path, |
| 1157 HeapEntry* entry, | 1126 List<HeapGraphPath*>* retaining_paths) { |
| 1158 CachedHeapGraphPath* prev_path) { | 1127 Vector<HeapGraphEdge*> rets = retainers(); |
| 1159 Vector<HeapGraphEdge*> retainers = entry->retainers(); | 1128 for (int i = 0; i < rets.length(); ++i) { |
| 1160 for (int i = 0; i < retainers.length(); ++i) { | 1129 HeapGraphEdge* ret_edge = rets[i]; |
| 1161 HeapGraphEdge* ret_edge = retainers[i]; | |
| 1162 if (prev_path->ContainsNode(ret_edge->From())) continue; | 1130 if (prev_path->ContainsNode(ret_edge->From())) continue; |
| 1163 if (ret_edge->From() != entry->snapshot()->root()) { | 1131 if (ret_edge->From() != snapshot()->root()) { |
| 1164 CachedHeapGraphPath path(*prev_path); | 1132 CachedHeapGraphPath path(*prev_path); |
| 1165 path.Add(ret_edge); | 1133 path.Add(ret_edge); |
| 1166 FindRetainingPaths(ret_edge->From(), &path); | 1134 ret_edge->From()->FindRetainingPaths(&path, retaining_paths); |
| 1167 } else { | 1135 } else { |
| 1168 HeapGraphPath* ret_path = new HeapGraphPath(*prev_path->path()); | 1136 HeapGraphPath* ret_path = new HeapGraphPath(*prev_path->path()); |
| 1169 ret_path->Set(0, ret_edge); | 1137 ret_path->Set(0, ret_edge); |
| 1170 retaining_paths_->Add(ret_path); | 1138 retaining_paths->Add(ret_path); |
| 1171 } | 1139 } |
| 1172 } | 1140 } |
| 1173 } | 1141 } |
| 1174 | 1142 |
| 1175 | 1143 |
| 1176 HeapGraphPath::HeapGraphPath(const List<HeapGraphEdge*>& path) | 1144 HeapGraphPath::HeapGraphPath(const List<HeapGraphEdge*>& path) |
| 1177 : path_(path.length() + 1) { | 1145 : path_(path.length() + 1) { |
| 1178 Add(NULL); | 1146 Add(NULL); |
| 1179 for (int i = path.length() - 1; i >= 0; --i) { | 1147 for (int i = path.length() - 1; i >= 0; --i) { |
| 1180 Add(path[i]); | 1148 Add(path[i]); |
| 1181 } | 1149 } |
| 1182 } | 1150 } |
| 1183 | 1151 |
| 1184 | 1152 |
| 1185 void HeapGraphPath::Print() { | 1153 void HeapGraphPath::Print() { |
| 1186 path_[0]->From()->Print(1, 0); | 1154 path_[0]->From()->Print(1, 0); |
| 1187 for (int i = 0; i < path_.length(); ++i) { | 1155 for (int i = 0; i < path_.length(); ++i) { |
| 1188 OS::Print(" -> "); | 1156 OS::Print(" -> "); |
| 1189 HeapGraphEdge* edge = path_[i]; | 1157 HeapGraphEdge* edge = path_[i]; |
| 1190 switch (edge->type()) { | 1158 switch (edge->type()) { |
| 1191 case HeapGraphEdge::kContextVariable: | 1159 case HeapGraphEdge::kContextVariable: |
| 1192 OS::Print("[#%s] ", edge->name()); | 1160 OS::Print("[#%s] ", edge->name()); |
| 1193 break; | 1161 break; |
| 1194 case HeapGraphEdge::kElement: | 1162 case HeapGraphEdge::kElement: |
| 1163 case HeapGraphEdge::kHidden: |
| 1195 OS::Print("[%d] ", edge->index()); | 1164 OS::Print("[%d] ", edge->index()); |
| 1196 break; | 1165 break; |
| 1197 case HeapGraphEdge::kInternal: | 1166 case HeapGraphEdge::kInternal: |
| 1198 OS::Print("[$%s] ", edge->name()); | 1167 OS::Print("[$%s] ", edge->name()); |
| 1199 break; | 1168 break; |
| 1200 case HeapGraphEdge::kProperty: | 1169 case HeapGraphEdge::kProperty: |
| 1201 OS::Print("[%s] ", edge->name()); | 1170 OS::Print("[%s] ", edge->name()); |
| 1202 break; | 1171 break; |
| 1172 case HeapGraphEdge::kShortcut: |
| 1173 OS::Print("[^%s] ", edge->name()); |
| 1174 break; |
| 1203 default: | 1175 default: |
| 1204 OS::Print("!!! unknown edge type: %d ", edge->type()); | 1176 OS::Print("!!! unknown edge type: %d ", edge->type()); |
| 1205 } | 1177 } |
| 1206 edge->to()->Print(1, 0); | 1178 edge->to()->Print(1, 0); |
| 1207 } | 1179 } |
| 1208 OS::Print("\n"); | 1180 OS::Print("\n"); |
| 1209 } | 1181 } |
| 1210 | 1182 |
| 1211 | 1183 |
| 1212 HeapObject *const HeapSnapshot::kInternalRootObject = | 1184 HeapObject *const HeapSnapshot::kInternalRootObject = |
| 1213 reinterpret_cast<HeapObject*>(1); | 1185 reinterpret_cast<HeapObject*>(1); |
| 1186 HeapObject *const HeapSnapshot::kGcRootsObject = |
| 1187 reinterpret_cast<HeapObject*>(2); |
| 1214 | 1188 |
| 1215 | 1189 |
| 1216 // It is very important to keep objects that form a heap snapshot | 1190 // It is very important to keep objects that form a heap snapshot |
| 1217 // as small as possible. | 1191 // as small as possible. |
| 1218 namespace { // Avoid littering the global namespace. | 1192 namespace { // Avoid littering the global namespace. |
| 1219 | 1193 |
| 1220 template <size_t ptr_size> struct SnapshotSizeConstants; | 1194 template <size_t ptr_size> struct SnapshotSizeConstants; |
| 1221 | 1195 |
| 1222 template <> struct SnapshotSizeConstants<4> { | 1196 template <> struct SnapshotSizeConstants<4> { |
| 1223 static const int kExpectedHeapGraphEdgeSize = 12; | 1197 static const int kExpectedHeapGraphEdgeSize = 12; |
| 1224 static const int kExpectedHeapEntrySize = 32; | 1198 static const int kExpectedHeapEntrySize = 36; |
| 1225 }; | 1199 }; |
| 1226 | 1200 |
| 1227 template <> struct SnapshotSizeConstants<8> { | 1201 template <> struct SnapshotSizeConstants<8> { |
| 1228 static const int kExpectedHeapGraphEdgeSize = 24; | 1202 static const int kExpectedHeapGraphEdgeSize = 24; |
| 1229 static const int kExpectedHeapEntrySize = 40; | 1203 static const int kExpectedHeapEntrySize = 48; |
| 1230 }; | 1204 }; |
| 1231 | 1205 |
| 1232 } // namespace | 1206 } // namespace |
| 1233 | 1207 |
| 1234 HeapSnapshot::HeapSnapshot(HeapSnapshotsCollection* collection, | 1208 HeapSnapshot::HeapSnapshot(HeapSnapshotsCollection* collection, |
| 1235 HeapSnapshot::Type type, | 1209 HeapSnapshot::Type type, |
| 1236 const char* title, | 1210 const char* title, |
| 1237 unsigned uid) | 1211 unsigned uid) |
| 1238 : collection_(collection), | 1212 : collection_(collection), |
| 1239 type_(type), | 1213 type_(type), |
| 1240 title_(title), | 1214 title_(title), |
| 1241 uid_(uid), | 1215 uid_(uid), |
| 1242 root_entry_(NULL), | 1216 root_entry_(NULL), |
| 1217 gc_roots_entry_(NULL), |
| 1243 raw_entries_(NULL), | 1218 raw_entries_(NULL), |
| 1244 entries_sorted_(false) { | 1219 entries_sorted_(false), |
| 1220 retaining_paths_(HeapEntry::Match) { |
| 1245 STATIC_ASSERT( | 1221 STATIC_ASSERT( |
| 1246 sizeof(HeapGraphEdge) == | 1222 sizeof(HeapGraphEdge) == |
| 1247 SnapshotSizeConstants<sizeof(void*)>::kExpectedHeapGraphEdgeSize); // NOL
INT | 1223 SnapshotSizeConstants<sizeof(void*)>::kExpectedHeapGraphEdgeSize); // NOL
INT |
| 1248 STATIC_ASSERT( | 1224 STATIC_ASSERT( |
| 1249 sizeof(HeapEntry) == | 1225 sizeof(HeapEntry) == |
| 1250 SnapshotSizeConstants<sizeof(void*)>::kExpectedHeapEntrySize); // NOLINT | 1226 SnapshotSizeConstants<sizeof(void*)>::kExpectedHeapEntrySize); // NOLINT |
| 1251 } | 1227 } |
| 1252 | 1228 |
| 1253 | 1229 |
| 1254 static void DisposeCalculatedData(HeapEntryCalculatedData* cdata) { | 1230 static void DeleteHeapGraphPath(HeapGraphPath** path_ptr) { |
| 1255 cdata->Dispose(); | 1231 delete *path_ptr; |
| 1256 } | 1232 } |
| 1257 | 1233 |
| 1258 HeapSnapshot::~HeapSnapshot() { | 1234 HeapSnapshot::~HeapSnapshot() { |
| 1259 DeleteArray(raw_entries_); | 1235 DeleteArray(raw_entries_); |
| 1260 calculated_data_.Iterate(DisposeCalculatedData); | 1236 for (HashMap::Entry* p = retaining_paths_.Start(); |
| 1237 p != NULL; |
| 1238 p = retaining_paths_.Next(p)) { |
| 1239 List<HeapGraphPath*>* list = |
| 1240 reinterpret_cast<List<HeapGraphPath*>*>(p->value); |
| 1241 list->Iterate(DeleteHeapGraphPath); |
| 1242 delete list; |
| 1243 } |
| 1261 } | 1244 } |
| 1262 | 1245 |
| 1263 | 1246 |
| 1264 void HeapSnapshot::AllocateEntries(int entries_count, | 1247 void HeapSnapshot::AllocateEntries(int entries_count, |
| 1265 int children_count, | 1248 int children_count, |
| 1266 int retainers_count) { | 1249 int retainers_count) { |
| 1267 ASSERT(raw_entries_ == NULL); | 1250 ASSERT(raw_entries_ == NULL); |
| 1268 raw_entries_ = NewArray<char>( | 1251 raw_entries_ = NewArray<char>( |
| 1269 HeapEntry::EntriesSize(entries_count, children_count, retainers_count)); | 1252 HeapEntry::EntriesSize(entries_count, children_count, retainers_count)); |
| 1270 #ifdef DEBUG | 1253 #ifdef DEBUG |
| 1271 raw_entries_size_ = | 1254 raw_entries_size_ = |
| 1272 HeapEntry::EntriesSize(entries_count, children_count, retainers_count); | 1255 HeapEntry::EntriesSize(entries_count, children_count, retainers_count); |
| 1273 #endif | 1256 #endif |
| 1274 } | 1257 } |
| 1275 | 1258 |
| 1276 | 1259 |
| 1277 HeapEntry* HeapSnapshot::AddEntry(HeapObject* object, | 1260 HeapEntry* HeapSnapshot::AddEntry(HeapObject* object, |
| 1278 int children_count, | 1261 int children_count, |
| 1279 int retainers_count) { | 1262 int retainers_count) { |
| 1280 if (object == kInternalRootObject) { | 1263 if (object == kInternalRootObject) { |
| 1281 ASSERT(root_entry_ == NULL); | 1264 ASSERT(root_entry_ == NULL); |
| 1282 ASSERT(retainers_count == 0); | 1265 ASSERT(retainers_count == 0); |
| 1283 root_entry_ = AddEntry( | 1266 return (root_entry_ = AddEntry(HeapEntry::kObject, |
| 1284 HeapEntry::kInternal, "", 0, 0, children_count, retainers_count); | 1267 "", |
| 1285 return root_entry_; | 1268 HeapObjectsMap::kInternalRootObjectId, |
| 1269 0, |
| 1270 children_count, |
| 1271 retainers_count)); |
| 1272 } else if (object == kGcRootsObject) { |
| 1273 ASSERT(gc_roots_entry_ == NULL); |
| 1274 return (gc_roots_entry_ = AddEntry(HeapEntry::kObject, |
| 1275 "(GC roots)", |
| 1276 HeapObjectsMap::kGcRootsObjectId, |
| 1277 0, |
| 1278 children_count, |
| 1279 retainers_count)); |
| 1286 } else if (object->IsJSFunction()) { | 1280 } else if (object->IsJSFunction()) { |
| 1287 JSFunction* func = JSFunction::cast(object); | 1281 JSFunction* func = JSFunction::cast(object); |
| 1288 SharedFunctionInfo* shared = func->shared(); | 1282 SharedFunctionInfo* shared = func->shared(); |
| 1289 return AddEntry(object, | 1283 return AddEntry(object, |
| 1290 HeapEntry::kClosure, | 1284 HeapEntry::kClosure, |
| 1291 collection_->GetName(String::cast(shared->name())), | 1285 collection_->GetName(String::cast(shared->name())), |
| 1292 children_count, | 1286 children_count, |
| 1293 retainers_count); | 1287 retainers_count); |
| 1294 } else if (object->IsJSRegExp()) { | 1288 } else if (object->IsJSRegExp()) { |
| 1295 JSRegExp* re = JSRegExp::cast(object); | 1289 JSRegExp* re = JSRegExp::cast(object); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1338 "", | 1332 "", |
| 1339 children_count, | 1333 children_count, |
| 1340 retainers_count); | 1334 retainers_count); |
| 1341 } else if (object->IsHeapNumber()) { | 1335 } else if (object->IsHeapNumber()) { |
| 1342 return AddEntry(object, | 1336 return AddEntry(object, |
| 1343 HeapEntry::kHeapNumber, | 1337 HeapEntry::kHeapNumber, |
| 1344 "number", | 1338 "number", |
| 1345 children_count, | 1339 children_count, |
| 1346 retainers_count); | 1340 retainers_count); |
| 1347 } | 1341 } |
| 1348 // No interest in this object. | 1342 return AddEntry(object, |
| 1349 return NULL; | 1343 HeapEntry::kHidden, |
| 1350 } | 1344 "system", |
| 1351 | 1345 children_count, |
| 1352 | 1346 retainers_count); |
| 1353 bool HeapSnapshot::WillAddEntry(HeapObject* object) { | |
| 1354 return object == kInternalRootObject | |
| 1355 || object->IsJSFunction() | |
| 1356 || object->IsJSRegExp() | |
| 1357 || object->IsJSObject() | |
| 1358 || object->IsString() | |
| 1359 || object->IsCode() | |
| 1360 || object->IsSharedFunctionInfo() | |
| 1361 || object->IsScript() | |
| 1362 || object->IsFixedArray() | |
| 1363 || object->IsHeapNumber(); | |
| 1364 } | 1347 } |
| 1365 | 1348 |
| 1366 | 1349 |
| 1367 static void HeapEntryClearPaint(HeapEntry** entry_ptr) { | 1350 static void HeapEntryClearPaint(HeapEntry** entry_ptr) { |
| 1368 (*entry_ptr)->clear_paint(); | 1351 (*entry_ptr)->clear_paint(); |
| 1369 } | 1352 } |
| 1370 | 1353 |
| 1371 void HeapSnapshot::ClearPaint() { | 1354 void HeapSnapshot::ClearPaint() { |
| 1372 entries_.Iterate(HeapEntryClearPaint); | 1355 entries_.Iterate(HeapEntryClearPaint); |
| 1373 } | 1356 } |
| 1374 | 1357 |
| 1375 | 1358 |
| 1376 int HeapSnapshot::AddCalculatedData() { | |
| 1377 calculated_data_.Add(HeapEntryCalculatedData()); | |
| 1378 return calculated_data_.length() - 1; | |
| 1379 } | |
| 1380 | |
| 1381 | |
| 1382 HeapEntry* HeapSnapshot::AddEntry(HeapObject* object, | 1359 HeapEntry* HeapSnapshot::AddEntry(HeapObject* object, |
| 1383 HeapEntry::Type type, | 1360 HeapEntry::Type type, |
| 1384 const char* name, | 1361 const char* name, |
| 1385 int children_count, | 1362 int children_count, |
| 1386 int retainers_count) { | 1363 int retainers_count) { |
| 1387 return AddEntry(type, | 1364 return AddEntry(type, |
| 1388 name, | 1365 name, |
| 1389 collection_->GetObjectId(object->address()), | 1366 collection_->GetObjectId(object->address()), |
| 1390 GetObjectSize(object), | 1367 object->Size(), |
| 1391 children_count, | 1368 children_count, |
| 1392 retainers_count); | 1369 retainers_count); |
| 1393 } | 1370 } |
| 1394 | 1371 |
| 1395 | 1372 |
| 1396 HeapEntry* HeapSnapshot::AddEntry(HeapEntry::Type type, | 1373 HeapEntry* HeapSnapshot::AddEntry(HeapEntry::Type type, |
| 1397 const char* name, | 1374 const char* name, |
| 1398 uint64_t id, | 1375 uint64_t id, |
| 1399 int size, | 1376 int size, |
| 1400 int children_count, | 1377 int children_count, |
| 1401 int retainers_count) { | 1378 int retainers_count) { |
| 1402 HeapEntry* entry = GetNextEntryToInit(); | 1379 HeapEntry* entry = GetNextEntryToInit(); |
| 1403 entry->Init(this, type, name, id, size, children_count, retainers_count); | 1380 entry->Init(this, type, name, id, size, children_count, retainers_count); |
| 1404 return entry; | 1381 return entry; |
| 1405 } | 1382 } |
| 1406 | 1383 |
| 1407 | 1384 |
| 1385 void HeapSnapshot::FillReversePostorderIndexes(Vector<HeapEntry*>* entries) { |
| 1386 ClearPaint(); |
| 1387 int current_entry = 0; |
| 1388 List<HeapEntry*> nodes_to_visit; |
| 1389 nodes_to_visit.Add(root()); |
| 1390 root()->paint_reachable(); |
| 1391 while (!nodes_to_visit.is_empty()) { |
| 1392 HeapEntry* entry = nodes_to_visit.last(); |
| 1393 Vector<HeapGraphEdge> children = entry->children(); |
| 1394 bool has_new_edges = false; |
| 1395 for (int i = 0; i < children.length(); ++i) { |
| 1396 if (children[i].type() == HeapGraphEdge::kShortcut) continue; |
| 1397 HeapEntry* child = children[i].to(); |
| 1398 if (!child->painted_reachable()) { |
| 1399 nodes_to_visit.Add(child); |
| 1400 child->paint_reachable(); |
| 1401 has_new_edges = true; |
| 1402 } |
| 1403 } |
| 1404 if (!has_new_edges) { |
| 1405 entry->set_ordered_index(current_entry); |
| 1406 entries->at(current_entry++) = entry; |
| 1407 nodes_to_visit.RemoveLast(); |
| 1408 } |
| 1409 } |
| 1410 entries->Truncate(current_entry); |
| 1411 } |
| 1412 |
| 1413 |
| 1414 static int Intersect(int i1, int i2, const Vector<HeapEntry*>& dominators) { |
| 1415 int finger1 = i1, finger2 = i2; |
| 1416 while (finger1 != finger2) { |
| 1417 while (finger1 < finger2) finger1 = dominators[finger1]->ordered_index(); |
| 1418 while (finger2 < finger1) finger2 = dominators[finger2]->ordered_index(); |
| 1419 } |
| 1420 return finger1; |
| 1421 } |
| 1422 |
| 1423 // The algorithm is based on the article: |
| 1424 // K. Cooper, T. Harvey and K. Kennedy "A Simple, Fast Dominance Algorithm" |
| 1425 // Softw. Pract. Exper. 4 (2001), pp. 1–10. |
| 1426 void HeapSnapshot::BuildDominatorTree(const Vector<HeapEntry*>& entries, |
| 1427 Vector<HeapEntry*>* dominators) { |
| 1428 if (entries.length() == 0) return; |
| 1429 const int root_index = entries.length() - 1; |
| 1430 for (int i = 0; i < root_index; ++i) dominators->at(i) = NULL; |
| 1431 dominators->at(root_index) = entries[root_index]; |
| 1432 bool changed = true; |
| 1433 while (changed) { |
| 1434 changed = false; |
| 1435 for (int i = root_index - 1; i >= 0; --i) { |
| 1436 HeapEntry* new_idom = NULL; |
| 1437 Vector<HeapGraphEdge*> rets = entries[i]->retainers(); |
| 1438 int j = 0; |
| 1439 for (; j < rets.length(); ++j) { |
| 1440 if (rets[j]->type() == HeapGraphEdge::kShortcut) continue; |
| 1441 HeapEntry* ret = rets[j]->From(); |
| 1442 if (dominators->at(ret->ordered_index()) != NULL) { |
| 1443 new_idom = ret; |
| 1444 break; |
| 1445 } |
| 1446 } |
| 1447 for (++j; j < rets.length(); ++j) { |
| 1448 if (rets[j]->type() == HeapGraphEdge::kShortcut) continue; |
| 1449 HeapEntry* ret = rets[j]->From(); |
| 1450 if (dominators->at(ret->ordered_index()) != NULL) { |
| 1451 new_idom = entries[Intersect(ret->ordered_index(), |
| 1452 new_idom->ordered_index(), |
| 1453 *dominators)]; |
| 1454 } |
| 1455 } |
| 1456 if (new_idom != NULL && dominators->at(i) != new_idom) { |
| 1457 dominators->at(i) = new_idom; |
| 1458 changed = true; |
| 1459 } |
| 1460 } |
| 1461 } |
| 1462 } |
| 1463 |
| 1464 |
| 1465 void HeapSnapshot::SetEntriesDominators() { |
| 1466 // This array is used for maintaining reverse postorder of nodes. |
| 1467 ScopedVector<HeapEntry*> ordered_entries(entries_.length()); |
| 1468 FillReversePostorderIndexes(&ordered_entries); |
| 1469 ScopedVector<HeapEntry*> dominators(ordered_entries.length()); |
| 1470 BuildDominatorTree(ordered_entries, &dominators); |
| 1471 for (int i = 0; i < ordered_entries.length(); ++i) { |
| 1472 ASSERT(dominators[i] != NULL); |
| 1473 ordered_entries[i]->set_dominator(dominators[i]); |
| 1474 } |
| 1475 // For nodes unreachable from root, set dominator to itself. |
| 1476 for (int i = 0; i < entries_.length(); ++i) { |
| 1477 HeapEntry* entry = entries_[i]; |
| 1478 if (entry->dominator() == NULL) entry->set_dominator(entry); |
| 1479 } |
| 1480 } |
| 1481 |
| 1482 |
| 1483 void HeapSnapshot::ApproximateRetainedSizes() { |
| 1484 SetEntriesDominators(); |
| 1485 // As for the dominators tree we only know parent nodes, not |
| 1486 // children, to sum up total sizes we traverse the tree level by |
| 1487 // level upwards, starting from leaves. |
| 1488 for (int i = 0; i < entries_.length(); ++i) { |
| 1489 HeapEntry* entry = entries_[i]; |
| 1490 entry->set_retained_size(entry->self_size()); |
| 1491 entry->set_leaf(); |
| 1492 } |
| 1493 while (true) { |
| 1494 bool onlyLeaves = true; |
| 1495 for (int i = 0; i < entries_.length(); ++i) { |
| 1496 HeapEntry *entry = entries_[i], *dominator = entry->dominator(); |
| 1497 if (!entry->is_processed() && dominator != entry) { |
| 1498 dominator->set_non_leaf(); |
| 1499 onlyLeaves = false; |
| 1500 } |
| 1501 } |
| 1502 if (onlyLeaves) break; |
| 1503 |
| 1504 for (int i = 0; i < entries_.length(); ++i) { |
| 1505 HeapEntry *entry = entries_[i], *dominator = entry->dominator(); |
| 1506 if (entry->is_leaf() && dominator != entry) { |
| 1507 dominator->add_retained_size(entry->retained_size()); |
| 1508 } |
| 1509 } |
| 1510 |
| 1511 // Mark all current leaves as processed, reset non-leaves back to leaves. |
| 1512 for (int i = 0; i < entries_.length(); ++i) { |
| 1513 HeapEntry* entry = entries_[i]; |
| 1514 if (entry->is_leaf()) |
| 1515 entry->set_processed(); |
| 1516 else if (entry->is_non_leaf()) |
| 1517 entry->set_leaf(); |
| 1518 } |
| 1519 } |
| 1520 } |
| 1521 |
| 1522 |
| 1408 HeapEntry* HeapSnapshot::GetNextEntryToInit() { | 1523 HeapEntry* HeapSnapshot::GetNextEntryToInit() { |
| 1409 if (entries_.length() > 0) { | 1524 if (entries_.length() > 0) { |
| 1410 HeapEntry* last_entry = entries_.last(); | 1525 HeapEntry* last_entry = entries_.last(); |
| 1411 entries_.Add(reinterpret_cast<HeapEntry*>( | 1526 entries_.Add(reinterpret_cast<HeapEntry*>( |
| 1412 reinterpret_cast<char*>(last_entry) + last_entry->EntrySize())); | 1527 reinterpret_cast<char*>(last_entry) + last_entry->EntrySize())); |
| 1413 } else { | 1528 } else { |
| 1414 entries_.Add(reinterpret_cast<HeapEntry*>(raw_entries_)); | 1529 entries_.Add(reinterpret_cast<HeapEntry*>(raw_entries_)); |
| 1415 } | 1530 } |
| 1416 ASSERT(reinterpret_cast<char*>(entries_.last()) < | 1531 ASSERT(reinterpret_cast<char*>(entries_.last()) < |
| 1417 (raw_entries_ + raw_entries_size_)); | 1532 (raw_entries_ + raw_entries_size_)); |
| 1418 return entries_.last(); | 1533 return entries_.last(); |
| 1419 } | 1534 } |
| 1420 | 1535 |
| 1421 | 1536 |
| 1422 int HeapSnapshot::GetObjectSize(HeapObject* obj) { | |
| 1423 return obj->IsJSObject() ? | |
| 1424 CalculateNetworkSize(JSObject::cast(obj)) : obj->Size(); | |
| 1425 } | |
| 1426 | |
| 1427 | |
| 1428 int HeapSnapshot::CalculateNetworkSize(JSObject* obj) { | |
| 1429 int size = obj->Size(); | |
| 1430 // If 'properties' and 'elements' are non-empty (thus, non-shared), | |
| 1431 // take their size into account. | |
| 1432 if (obj->properties() != Heap::empty_fixed_array()) { | |
| 1433 size += obj->properties()->Size(); | |
| 1434 } | |
| 1435 if (obj->elements() != Heap::empty_fixed_array()) { | |
| 1436 size += obj->elements()->Size(); | |
| 1437 } | |
| 1438 // For functions, also account non-empty context and literals sizes. | |
| 1439 if (obj->IsJSFunction()) { | |
| 1440 JSFunction* f = JSFunction::cast(obj); | |
| 1441 if (f->unchecked_context()->IsContext()) { | |
| 1442 size += f->context()->Size(); | |
| 1443 } | |
| 1444 if (f->literals()->length() != 0) { | |
| 1445 size += f->literals()->Size(); | |
| 1446 } | |
| 1447 } | |
| 1448 return size; | |
| 1449 } | |
| 1450 | |
| 1451 | |
| 1452 HeapSnapshotsDiff* HeapSnapshot::CompareWith(HeapSnapshot* snapshot) { | 1537 HeapSnapshotsDiff* HeapSnapshot::CompareWith(HeapSnapshot* snapshot) { |
| 1453 return collection_->CompareSnapshots(this, snapshot); | 1538 return collection_->CompareSnapshots(this, snapshot); |
| 1454 } | 1539 } |
| 1455 | 1540 |
| 1456 | 1541 |
| 1542 List<HeapGraphPath*>* HeapSnapshot::GetRetainingPaths(HeapEntry* entry) { |
| 1543 HashMap::Entry* p = |
| 1544 retaining_paths_.Lookup(entry, HeapEntry::Hash(entry), true); |
| 1545 if (p->value == NULL) { |
| 1546 p->value = entry->CalculateRetainingPaths(); |
| 1547 } |
| 1548 return reinterpret_cast<List<HeapGraphPath*>*>(p->value); |
| 1549 } |
| 1550 |
| 1551 |
| 1457 template<class T> | 1552 template<class T> |
| 1458 static int SortByIds(const T* entry1_ptr, | 1553 static int SortByIds(const T* entry1_ptr, |
| 1459 const T* entry2_ptr) { | 1554 const T* entry2_ptr) { |
| 1460 if ((*entry1_ptr)->id() == (*entry2_ptr)->id()) return 0; | 1555 if ((*entry1_ptr)->id() == (*entry2_ptr)->id()) return 0; |
| 1461 return (*entry1_ptr)->id() < (*entry2_ptr)->id() ? -1 : 1; | 1556 return (*entry1_ptr)->id() < (*entry2_ptr)->id() ? -1 : 1; |
| 1462 } | 1557 } |
| 1463 | 1558 |
| 1464 List<HeapEntry*>* HeapSnapshot::GetSortedEntriesList() { | 1559 List<HeapEntry*>* HeapSnapshot::GetSortedEntriesList() { |
| 1465 if (!entries_sorted_) { | 1560 if (!entries_sorted_) { |
| 1466 entries_.Sort(SortByIds); | 1561 entries_.Sort(SortByIds); |
| 1467 entries_sorted_ = true; | 1562 entries_sorted_ = true; |
| 1468 } | 1563 } |
| 1469 return &entries_; | 1564 return &entries_; |
| 1470 } | 1565 } |
| 1471 | 1566 |
| 1472 | 1567 |
| 1473 void HeapSnapshot::Print(int max_depth) { | 1568 void HeapSnapshot::Print(int max_depth) { |
| 1474 root()->Print(max_depth, 0); | 1569 root()->Print(max_depth, 0); |
| 1475 } | 1570 } |
| 1476 | 1571 |
| 1477 | 1572 |
| 1573 const uint64_t HeapObjectsMap::kInternalRootObjectId = 0; |
| 1574 const uint64_t HeapObjectsMap::kGcRootsObjectId = 1; |
| 1575 // Increase kFirstAvailableObjectId if new 'special' objects appear. |
| 1576 const uint64_t HeapObjectsMap::kFirstAvailableObjectId = 2; |
| 1577 |
| 1478 HeapObjectsMap::HeapObjectsMap() | 1578 HeapObjectsMap::HeapObjectsMap() |
| 1479 : initial_fill_mode_(true), | 1579 : initial_fill_mode_(true), |
| 1480 next_id_(1), | 1580 next_id_(kFirstAvailableObjectId), |
| 1481 entries_map_(AddressesMatch), | 1581 entries_map_(AddressesMatch), |
| 1482 entries_(new List<EntryInfo>()) { } | 1582 entries_(new List<EntryInfo>()) { } |
| 1483 | 1583 |
| 1484 | 1584 |
| 1485 HeapObjectsMap::~HeapObjectsMap() { | 1585 HeapObjectsMap::~HeapObjectsMap() { |
| 1486 delete entries_; | 1586 delete entries_; |
| 1487 } | 1587 } |
| 1488 | 1588 |
| 1489 | 1589 |
| 1490 void HeapObjectsMap::SnapshotGenerationFinished() { | 1590 void HeapObjectsMap::SnapshotGenerationFinished() { |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1621 HeapEntriesMap::HeapEntriesMap() | 1721 HeapEntriesMap::HeapEntriesMap() |
| 1622 : entries_(HeapObjectsMatch), | 1722 : entries_(HeapObjectsMatch), |
| 1623 entries_count_(0), | 1723 entries_count_(0), |
| 1624 total_children_count_(0), | 1724 total_children_count_(0), |
| 1625 total_retainers_count_(0) { | 1725 total_retainers_count_(0) { |
| 1626 } | 1726 } |
| 1627 | 1727 |
| 1628 | 1728 |
| 1629 HeapEntriesMap::~HeapEntriesMap() { | 1729 HeapEntriesMap::~HeapEntriesMap() { |
| 1630 for (HashMap::Entry* p = entries_.Start(); p != NULL; p = entries_.Next(p)) { | 1730 for (HashMap::Entry* p = entries_.Start(); p != NULL; p = entries_.Next(p)) { |
| 1631 if (!IsAlias(p->value)) delete reinterpret_cast<EntryInfo*>(p->value); | 1731 delete reinterpret_cast<EntryInfo*>(p->value); |
| 1632 } | |
| 1633 } | |
| 1634 | |
| 1635 | |
| 1636 void HeapEntriesMap::Alias(HeapObject* from, HeapObject* to) { | |
| 1637 HashMap::Entry* from_cache_entry = entries_.Lookup(from, Hash(from), true); | |
| 1638 HashMap::Entry* to_cache_entry = entries_.Lookup(to, Hash(to), false); | |
| 1639 if (from_cache_entry->value == NULL) { | |
| 1640 ASSERT(to_cache_entry != NULL); | |
| 1641 from_cache_entry->value = MakeAlias(to_cache_entry->value); | |
| 1642 } | 1732 } |
| 1643 } | 1733 } |
| 1644 | 1734 |
| 1645 | 1735 |
| 1646 HeapEntry* HeapEntriesMap::Map(HeapObject* object) { | 1736 HeapEntry* HeapEntriesMap::Map(HeapObject* object) { |
| 1647 HashMap::Entry* cache_entry = entries_.Lookup(object, Hash(object), false); | 1737 HashMap::Entry* cache_entry = entries_.Lookup(object, Hash(object), false); |
| 1648 if (cache_entry != NULL) { | 1738 if (cache_entry != NULL) { |
| 1649 EntryInfo* entry_info = | 1739 EntryInfo* entry_info = reinterpret_cast<EntryInfo*>(cache_entry->value); |
| 1650 reinterpret_cast<EntryInfo*>(Unalias(cache_entry->value)); | |
| 1651 return entry_info->entry; | 1740 return entry_info->entry; |
| 1652 } else { | 1741 } else { |
| 1653 return NULL; | 1742 return NULL; |
| 1654 } | 1743 } |
| 1655 } | 1744 } |
| 1656 | 1745 |
| 1657 | 1746 |
| 1658 void HeapEntriesMap::Pair(HeapObject* object, HeapEntry* entry) { | 1747 void HeapEntriesMap::Pair(HeapObject* object, HeapEntry* entry) { |
| 1659 HashMap::Entry* cache_entry = entries_.Lookup(object, Hash(object), true); | 1748 HashMap::Entry* cache_entry = entries_.Lookup(object, Hash(object), true); |
| 1660 ASSERT(cache_entry->value == NULL); | 1749 ASSERT(cache_entry->value == NULL); |
| 1661 cache_entry->value = new EntryInfo(entry); | 1750 cache_entry->value = new EntryInfo(entry); |
| 1662 ++entries_count_; | 1751 ++entries_count_; |
| 1663 } | 1752 } |
| 1664 | 1753 |
| 1665 | 1754 |
| 1666 void HeapEntriesMap::CountReference(HeapObject* from, HeapObject* to, | 1755 void HeapEntriesMap::CountReference(HeapObject* from, HeapObject* to, |
| 1667 int* prev_children_count, | 1756 int* prev_children_count, |
| 1668 int* prev_retainers_count) { | 1757 int* prev_retainers_count) { |
| 1669 HashMap::Entry* from_cache_entry = entries_.Lookup(from, Hash(from), false); | 1758 HashMap::Entry* from_cache_entry = entries_.Lookup(from, Hash(from), false); |
| 1670 HashMap::Entry* to_cache_entry = entries_.Lookup(to, Hash(to), false); | 1759 HashMap::Entry* to_cache_entry = entries_.Lookup(to, Hash(to), false); |
| 1671 ASSERT(from_cache_entry != NULL); | 1760 ASSERT(from_cache_entry != NULL); |
| 1672 ASSERT(to_cache_entry != NULL); | 1761 ASSERT(to_cache_entry != NULL); |
| 1673 EntryInfo* from_entry_info = | 1762 EntryInfo* from_entry_info = |
| 1674 reinterpret_cast<EntryInfo*>(Unalias(from_cache_entry->value)); | 1763 reinterpret_cast<EntryInfo*>(from_cache_entry->value); |
| 1675 EntryInfo* to_entry_info = | 1764 EntryInfo* to_entry_info = |
| 1676 reinterpret_cast<EntryInfo*>(Unalias(to_cache_entry->value)); | 1765 reinterpret_cast<EntryInfo*>(to_cache_entry->value); |
| 1677 if (prev_children_count) | 1766 if (prev_children_count) |
| 1678 *prev_children_count = from_entry_info->children_count; | 1767 *prev_children_count = from_entry_info->children_count; |
| 1679 if (prev_retainers_count) | 1768 if (prev_retainers_count) |
| 1680 *prev_retainers_count = to_entry_info->retainers_count; | 1769 *prev_retainers_count = to_entry_info->retainers_count; |
| 1681 ++from_entry_info->children_count; | 1770 ++from_entry_info->children_count; |
| 1682 ++to_entry_info->retainers_count; | 1771 ++to_entry_info->retainers_count; |
| 1683 ++total_children_count_; | 1772 ++total_children_count_; |
| 1684 ++total_retainers_count_; | 1773 ++total_retainers_count_; |
| 1685 } | 1774 } |
| 1686 | 1775 |
| 1687 | 1776 |
| 1777 HeapObjectsSet::HeapObjectsSet() |
| 1778 : entries_(HeapEntriesMap::HeapObjectsMatch) { |
| 1779 } |
| 1780 |
| 1781 |
| 1782 void HeapObjectsSet::Clear() { |
| 1783 entries_.Clear(); |
| 1784 } |
| 1785 |
| 1786 |
| 1787 bool HeapObjectsSet::Contains(Object* obj) { |
| 1788 if (!obj->IsHeapObject()) return false; |
| 1789 HeapObject* object = HeapObject::cast(obj); |
| 1790 HashMap::Entry* cache_entry = |
| 1791 entries_.Lookup(object, HeapEntriesMap::Hash(object), false); |
| 1792 return cache_entry != NULL; |
| 1793 } |
| 1794 |
| 1795 |
| 1796 void HeapObjectsSet::Insert(Object* obj) { |
| 1797 if (!obj->IsHeapObject()) return; |
| 1798 HeapObject* object = HeapObject::cast(obj); |
| 1799 HashMap::Entry* cache_entry = |
| 1800 entries_.Lookup(object, HeapEntriesMap::Hash(object), true); |
| 1801 if (cache_entry->value == NULL) { |
| 1802 cache_entry->value = HeapEntriesMap::kHeapEntryPlaceholder; |
| 1803 } |
| 1804 } |
| 1805 |
| 1806 |
| 1688 HeapSnapshotGenerator::HeapSnapshotGenerator(HeapSnapshot* snapshot) | 1807 HeapSnapshotGenerator::HeapSnapshotGenerator(HeapSnapshot* snapshot) |
| 1689 : snapshot_(snapshot), | 1808 : snapshot_(snapshot), |
| 1690 collection_(snapshot->collection()), | 1809 collection_(snapshot->collection()), |
| 1691 filler_(NULL) { | 1810 filler_(NULL) { |
| 1692 } | 1811 } |
| 1693 | 1812 |
| 1694 class SnapshotCounter : public HeapSnapshotGenerator::SnapshotFillerInterface { | 1813 class SnapshotCounter : public HeapSnapshotGenerator::SnapshotFillerInterface { |
| 1695 public: | 1814 public: |
| 1696 explicit SnapshotCounter(HeapEntriesMap* entries) | 1815 explicit SnapshotCounter(HeapEntriesMap* entries) |
| 1697 : entries_(entries) { } | 1816 : entries_(entries) { } |
| 1698 HeapEntry* AddEntry(HeapObject* obj) { | 1817 HeapEntry* AddEntry(HeapObject* obj) { |
| 1699 entries_->Pair(obj, HeapEntriesMap::kHeapEntryPlaceholder); | 1818 entries_->Pair(obj, HeapEntriesMap::kHeapEntryPlaceholder); |
| 1700 return HeapEntriesMap::kHeapEntryPlaceholder; | 1819 return HeapEntriesMap::kHeapEntryPlaceholder; |
| 1701 } | 1820 } |
| 1702 void SetElementReference(HeapObject* parent_obj, | 1821 void SetIndexedReference(HeapGraphEdge::Type, |
| 1822 HeapObject* parent_obj, |
| 1703 HeapEntry*, | 1823 HeapEntry*, |
| 1704 int, | 1824 int, |
| 1705 Object* child_obj, | 1825 Object* child_obj, |
| 1706 HeapEntry*) { | 1826 HeapEntry*) { |
| 1707 entries_->CountReference(parent_obj, HeapObject::cast(child_obj)); | 1827 entries_->CountReference(parent_obj, HeapObject::cast(child_obj)); |
| 1708 } | 1828 } |
| 1709 void SetNamedReference(HeapGraphEdge::Type, | 1829 void SetNamedReference(HeapGraphEdge::Type, |
| 1710 HeapObject* parent_obj, | 1830 HeapObject* parent_obj, |
| 1711 HeapEntry*, | 1831 HeapEntry*, |
| 1712 const char*, | 1832 const char*, |
| 1713 Object* child_obj, | 1833 Object* child_obj, |
| 1714 HeapEntry*) { | 1834 HeapEntry*) { |
| 1715 entries_->CountReference(parent_obj, HeapObject::cast(child_obj)); | 1835 entries_->CountReference(parent_obj, HeapObject::cast(child_obj)); |
| 1716 } | 1836 } |
| 1717 void SetRootReference(Object* child_obj, HeapEntry*) { | 1837 void SetRootShortcutReference(Object* child_obj, HeapEntry*) { |
| 1718 entries_->CountReference( | 1838 entries_->CountReference( |
| 1719 HeapSnapshot::kInternalRootObject, HeapObject::cast(child_obj)); | 1839 HeapSnapshot::kInternalRootObject, HeapObject::cast(child_obj)); |
| 1720 } | 1840 } |
| 1841 void SetRootGcRootsReference() { |
| 1842 entries_->CountReference( |
| 1843 HeapSnapshot::kInternalRootObject, HeapSnapshot::kGcRootsObject); |
| 1844 } |
| 1845 void SetStrongRootReference(Object* child_obj, HeapEntry*) { |
| 1846 entries_->CountReference( |
| 1847 HeapSnapshot::kGcRootsObject, HeapObject::cast(child_obj)); |
| 1848 } |
| 1721 private: | 1849 private: |
| 1722 HeapEntriesMap* entries_; | 1850 HeapEntriesMap* entries_; |
| 1723 }; | 1851 }; |
| 1724 | 1852 |
| 1725 | 1853 |
| 1726 class SnapshotFiller : public HeapSnapshotGenerator::SnapshotFillerInterface { | 1854 class SnapshotFiller : public HeapSnapshotGenerator::SnapshotFillerInterface { |
| 1727 public: | 1855 public: |
| 1728 explicit SnapshotFiller(HeapSnapshot* snapshot, HeapEntriesMap* entries) | 1856 explicit SnapshotFiller(HeapSnapshot* snapshot, HeapEntriesMap* entries) |
| 1729 : snapshot_(snapshot), | 1857 : snapshot_(snapshot), |
| 1730 collection_(snapshot->collection()), | 1858 collection_(snapshot->collection()), |
| 1731 entries_(entries) { } | 1859 entries_(entries) { } |
| 1732 HeapEntry* AddEntry(HeapObject* obj) { | 1860 HeapEntry* AddEntry(HeapObject* obj) { |
| 1733 UNREACHABLE(); | 1861 UNREACHABLE(); |
| 1734 return NULL; | 1862 return NULL; |
| 1735 } | 1863 } |
| 1736 void SetElementReference(HeapObject* parent_obj, | 1864 void SetIndexedReference(HeapGraphEdge::Type type, |
| 1865 HeapObject* parent_obj, |
| 1737 HeapEntry* parent_entry, | 1866 HeapEntry* parent_entry, |
| 1738 int index, | 1867 int index, |
| 1739 Object* child_obj, | 1868 Object* child_obj, |
| 1740 HeapEntry* child_entry) { | 1869 HeapEntry* child_entry) { |
| 1741 int child_index, retainer_index; | 1870 int child_index, retainer_index; |
| 1742 entries_->CountReference(parent_obj, HeapObject::cast(child_obj), | 1871 entries_->CountReference(parent_obj, |
| 1743 &child_index, &retainer_index); | 1872 HeapObject::cast(child_obj), |
| 1744 parent_entry->SetElementReference( | 1873 &child_index, |
| 1745 child_index, index, child_entry, retainer_index); | 1874 &retainer_index); |
| 1875 parent_entry->SetIndexedReference( |
| 1876 type, child_index, index, child_entry, retainer_index); |
| 1746 } | 1877 } |
| 1747 void SetNamedReference(HeapGraphEdge::Type type, | 1878 void SetNamedReference(HeapGraphEdge::Type type, |
| 1748 HeapObject* parent_obj, | 1879 HeapObject* parent_obj, |
| 1749 HeapEntry* parent_entry, | 1880 HeapEntry* parent_entry, |
| 1750 const char* reference_name, | 1881 const char* reference_name, |
| 1751 Object* child_obj, | 1882 Object* child_obj, |
| 1752 HeapEntry* child_entry) { | 1883 HeapEntry* child_entry) { |
| 1753 int child_index, retainer_index; | 1884 int child_index, retainer_index; |
| 1754 entries_->CountReference(parent_obj, HeapObject::cast(child_obj), | 1885 entries_->CountReference(parent_obj, HeapObject::cast(child_obj), |
| 1755 &child_index, &retainer_index); | 1886 &child_index, &retainer_index); |
| 1756 parent_entry->SetNamedReference(type, | 1887 parent_entry->SetNamedReference(type, |
| 1757 child_index, | 1888 child_index, |
| 1758 reference_name, | 1889 reference_name, |
| 1759 child_entry, | 1890 child_entry, |
| 1760 retainer_index); | 1891 retainer_index); |
| 1761 } | 1892 } |
| 1762 void SetRootReference(Object* child_obj, HeapEntry* child_entry) { | 1893 void SetRootGcRootsReference() { |
| 1763 int child_index, retainer_index; | 1894 int child_index, retainer_index; |
| 1764 entries_->CountReference( | 1895 entries_->CountReference(HeapSnapshot::kInternalRootObject, |
| 1765 HeapSnapshot::kInternalRootObject, HeapObject::cast(child_obj), | 1896 HeapSnapshot::kGcRootsObject, |
| 1766 &child_index, &retainer_index); | 1897 &child_index, |
| 1767 snapshot_->root()->SetElementReference( | 1898 &retainer_index); |
| 1768 child_index, child_index + 1, child_entry, retainer_index); | 1899 snapshot_->root()->SetIndexedReference(HeapGraphEdge::kElement, |
| 1900 child_index, |
| 1901 child_index + 1, |
| 1902 snapshot_->gc_roots(), |
| 1903 retainer_index); |
| 1904 } |
| 1905 void SetRootShortcutReference(Object* child_obj, |
| 1906 HeapEntry* child_entry) { |
| 1907 int child_index, retainer_index; |
| 1908 entries_->CountReference(HeapSnapshot::kInternalRootObject, |
| 1909 HeapObject::cast(child_obj), |
| 1910 &child_index, |
| 1911 &retainer_index); |
| 1912 snapshot_->root()->SetNamedReference(HeapGraphEdge::kShortcut, |
| 1913 child_index, |
| 1914 collection_->GetName(child_index + 1), |
| 1915 child_entry, |
| 1916 retainer_index); |
| 1917 } |
| 1918 void SetStrongRootReference(Object* child_obj, |
| 1919 HeapEntry* child_entry) { |
| 1920 int child_index, retainer_index; |
| 1921 entries_->CountReference(HeapSnapshot::kGcRootsObject, |
| 1922 HeapObject::cast(child_obj), |
| 1923 &child_index, |
| 1924 &retainer_index); |
| 1925 snapshot_->gc_roots()->SetIndexedReference(HeapGraphEdge::kElement, |
| 1926 child_index, |
| 1927 child_index + 1, |
| 1928 child_entry, |
| 1929 retainer_index); |
| 1769 } | 1930 } |
| 1770 private: | 1931 private: |
| 1771 HeapSnapshot* snapshot_; | 1932 HeapSnapshot* snapshot_; |
| 1772 HeapSnapshotsCollection* collection_; | 1933 HeapSnapshotsCollection* collection_; |
| 1773 HeapEntriesMap* entries_; | 1934 HeapEntriesMap* entries_; |
| 1774 }; | 1935 }; |
| 1775 | 1936 |
| 1776 class SnapshotAllocator { | 1937 class SnapshotAllocator { |
| 1777 public: | 1938 public: |
| 1778 explicit SnapshotAllocator(HeapSnapshot* snapshot) | 1939 explicit SnapshotAllocator(HeapSnapshot* snapshot) |
| 1779 : snapshot_(snapshot) { } | 1940 : snapshot_(snapshot) { } |
| 1780 HeapEntry* GetEntry( | 1941 HeapEntry* GetEntry( |
| 1781 HeapObject* obj, int children_count, int retainers_count) { | 1942 HeapObject* obj, int children_count, int retainers_count) { |
| 1782 HeapEntry* entry = | 1943 HeapEntry* entry = |
| 1783 snapshot_->AddEntry(obj, children_count, retainers_count); | 1944 snapshot_->AddEntry(obj, children_count, retainers_count); |
| 1784 ASSERT(entry != NULL); | 1945 ASSERT(entry != NULL); |
| 1785 return entry; | 1946 return entry; |
| 1786 } | 1947 } |
| 1787 private: | 1948 private: |
| 1788 HeapSnapshot* snapshot_; | 1949 HeapSnapshot* snapshot_; |
| 1789 }; | 1950 }; |
| 1790 | 1951 |
| 1952 class RootsReferencesExtractor : public ObjectVisitor { |
| 1953 public: |
| 1954 explicit RootsReferencesExtractor(HeapSnapshotGenerator* generator) |
| 1955 : generator_(generator) { |
| 1956 } |
| 1957 void VisitPointers(Object** start, Object** end) { |
| 1958 for (Object** p = start; p < end; p++) generator_->SetGcRootsReference(*p); |
| 1959 } |
| 1960 private: |
| 1961 HeapSnapshotGenerator* generator_; |
| 1962 }; |
| 1963 |
| 1964 |
| 1791 void HeapSnapshotGenerator::GenerateSnapshot() { | 1965 void HeapSnapshotGenerator::GenerateSnapshot() { |
| 1792 AssertNoAllocation no_alloc; | 1966 AssertNoAllocation no_alloc; |
| 1793 | 1967 |
| 1794 // Pass 1. Iterate heap contents to count entries and references. | 1968 // Pass 1. Iterate heap contents to count entries and references. |
| 1795 SnapshotCounter counter(&entries_); | 1969 SnapshotCounter counter(&entries_); |
| 1796 filler_ = &counter; | 1970 filler_ = &counter; |
| 1797 filler_->AddEntry(HeapSnapshot::kInternalRootObject); | 1971 filler_->AddEntry(HeapSnapshot::kInternalRootObject); |
| 1798 HeapIterator iterator1; | 1972 filler_->AddEntry(HeapSnapshot::kGcRootsObject); |
| 1799 for (HeapObject* obj = iterator1.next(); | 1973 HeapIterator iterator(HeapIterator::kPreciseFiltering); |
| 1800 obj != NULL; | 1974 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) { |
| 1801 obj = iterator1.next()) { | |
| 1802 ExtractReferences(obj); | 1975 ExtractReferences(obj); |
| 1803 } | 1976 } |
| 1977 SetRootGcRootsReference(); |
| 1978 RootsReferencesExtractor extractor(this); |
| 1979 Heap::IterateRoots(&extractor, VISIT_ONLY_STRONG); |
| 1804 | 1980 |
| 1805 // Allocate and fill entries in the snapshot, allocate references. | 1981 // Allocate and fill entries in the snapshot, allocate references. |
| 1806 snapshot_->AllocateEntries(entries_.entries_count(), | 1982 snapshot_->AllocateEntries(entries_.entries_count(), |
| 1807 entries_.total_children_count(), | 1983 entries_.total_children_count(), |
| 1808 entries_.total_retainers_count()); | 1984 entries_.total_retainers_count()); |
| 1809 SnapshotAllocator allocator(snapshot_); | 1985 SnapshotAllocator allocator(snapshot_); |
| 1810 entries_.UpdateEntries(&allocator); | 1986 entries_.UpdateEntries(&allocator); |
| 1811 | 1987 |
| 1812 // Pass 2. Fill references. | 1988 // Pass 2. Fill references. |
| 1813 SnapshotFiller filler(snapshot_, &entries_); | 1989 SnapshotFiller filler(snapshot_, &entries_); |
| 1814 filler_ = &filler; | 1990 filler_ = &filler; |
| 1815 HeapIterator iterator2; | 1991 iterator.reset(); |
| 1816 for (HeapObject* obj = iterator2.next(); | 1992 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) { |
| 1817 obj != NULL; | |
| 1818 obj = iterator2.next()) { | |
| 1819 ExtractReferences(obj); | 1993 ExtractReferences(obj); |
| 1820 } | 1994 } |
| 1995 SetRootGcRootsReference(); |
| 1996 Heap::IterateRoots(&extractor, VISIT_ONLY_STRONG); |
| 1997 |
| 1998 snapshot_->ApproximateRetainedSizes(); |
| 1821 } | 1999 } |
| 1822 | 2000 |
| 1823 | 2001 |
| 1824 HeapEntry* HeapSnapshotGenerator::GetEntry(Object* obj) { | 2002 HeapEntry* HeapSnapshotGenerator::GetEntry(Object* obj) { |
| 1825 if (!obj->IsHeapObject()) return NULL; | 2003 if (!obj->IsHeapObject()) return NULL; |
| 1826 HeapObject* object = HeapObject::cast(obj); | 2004 HeapObject* object = HeapObject::cast(obj); |
| 1827 HeapEntry* entry = entries_.Map(object); | 2005 HeapEntry* entry = entries_.Map(object); |
| 1828 | |
| 1829 // A new entry. | 2006 // A new entry. |
| 1830 if (entry == NULL) { | 2007 if (entry == NULL) entry = filler_->AddEntry(object); |
| 1831 if (obj->IsJSGlobalPropertyCell()) { | |
| 1832 Object* cell_target = JSGlobalPropertyCell::cast(obj)->value(); | |
| 1833 entry = GetEntry(cell_target); | |
| 1834 // If GPC references an object that we have interest in (see | |
| 1835 // HeapSnapshot::AddEntry, WillAddEntry), add the object. We | |
| 1836 // don't store HeapEntries for GPCs. Instead, we make our hash | |
| 1837 // map to point to object's HeapEntry by GPCs address. | |
| 1838 if (entry != NULL) { | |
| 1839 entries_.Alias(object, HeapObject::cast(cell_target)); | |
| 1840 } | |
| 1841 return entry; | |
| 1842 } | |
| 1843 | |
| 1844 if (snapshot_->WillAddEntry(object)) entry = filler_->AddEntry(object); | |
| 1845 } | |
| 1846 | |
| 1847 return entry; | 2008 return entry; |
| 1848 } | 2009 } |
| 1849 | 2010 |
| 1850 | 2011 |
| 1851 class IndexedReferencesExtractor : public ObjectVisitor { | 2012 class IndexedReferencesExtractor : public ObjectVisitor { |
| 1852 public: | 2013 public: |
| 1853 IndexedReferencesExtractor(HeapSnapshotGenerator* generator, | 2014 IndexedReferencesExtractor(HeapSnapshotGenerator* generator, |
| 1854 HeapObject* parent_obj, | 2015 HeapObject* parent_obj, |
| 1855 HeapEntry* parent_entry) | 2016 HeapEntry* parent_entry, |
| 2017 HeapObjectsSet* known_references = NULL) |
| 1856 : generator_(generator), | 2018 : generator_(generator), |
| 1857 parent_obj_(parent_obj), | 2019 parent_obj_(parent_obj), |
| 1858 parent_(parent_entry), | 2020 parent_(parent_entry), |
| 2021 known_references_(known_references), |
| 1859 next_index_(1) { | 2022 next_index_(1) { |
| 1860 } | 2023 } |
| 1861 | 2024 void VisitPointers(Object** start, Object** end) { |
| 1862 void VisitPointer(Object** o) { | 2025 for (Object** p = start; p < end; p++) { |
| 1863 generator_->SetElementReference(parent_obj_, parent_, next_index_++, *o); | 2026 if (!known_references_ || !known_references_->Contains(*p)) { |
| 2027 generator_->SetHiddenReference(parent_obj_, parent_, next_index_++, *p); |
| 2028 } |
| 2029 } |
| 1864 } | 2030 } |
| 1865 | |
| 1866 void VisitPointers(Object** start, Object** end) { | |
| 1867 for (Object** p = start; p < end; p++) VisitPointer(p); | |
| 1868 } | |
| 1869 | |
| 1870 private: | 2031 private: |
| 1871 HeapSnapshotGenerator* generator_; | 2032 HeapSnapshotGenerator* generator_; |
| 1872 HeapObject* parent_obj_; | 2033 HeapObject* parent_obj_; |
| 1873 HeapEntry* parent_; | 2034 HeapEntry* parent_; |
| 2035 HeapObjectsSet* known_references_; |
| 1874 int next_index_; | 2036 int next_index_; |
| 1875 }; | 2037 }; |
| 1876 | 2038 |
| 1877 | 2039 |
| 1878 void HeapSnapshotGenerator::ExtractReferences(HeapObject* obj) { | 2040 void HeapSnapshotGenerator::ExtractReferences(HeapObject* obj) { |
| 1879 // We need to reference JS global objects from snapshot's root. | |
| 1880 // We use JSGlobalProxy because this is what embedder (e.g. browser) | |
| 1881 // uses for the global object. | |
| 1882 if (obj->IsJSGlobalProxy()) { | |
| 1883 JSGlobalProxy* proxy = JSGlobalProxy::cast(obj); | |
| 1884 SetRootReference(proxy->map()->prototype()); | |
| 1885 return; | |
| 1886 } | |
| 1887 | |
| 1888 HeapEntry* entry = GetEntry(obj); | 2041 HeapEntry* entry = GetEntry(obj); |
| 1889 if (entry == NULL) return; // No interest in this object. | 2042 if (entry == NULL) return; // No interest in this object. |
| 1890 | 2043 |
| 1891 if (obj->IsJSObject()) { | 2044 known_references_.Clear(); |
| 2045 if (obj->IsJSGlobalProxy()) { |
| 2046 // We need to reference JS global objects from snapshot's root. |
| 2047 // We use JSGlobalProxy because this is what embedder (e.g. browser) |
| 2048 // uses for the global object. |
| 2049 JSGlobalProxy* proxy = JSGlobalProxy::cast(obj); |
| 2050 SetRootShortcutReference(proxy->map()->prototype()); |
| 2051 IndexedReferencesExtractor refs_extractor(this, obj, entry); |
| 2052 obj->Iterate(&refs_extractor); |
| 2053 } else if (obj->IsJSObject()) { |
| 1892 JSObject* js_obj = JSObject::cast(obj); | 2054 JSObject* js_obj = JSObject::cast(obj); |
| 1893 ExtractClosureReferences(js_obj, entry); | 2055 ExtractClosureReferences(js_obj, entry); |
| 1894 ExtractPropertyReferences(js_obj, entry); | 2056 ExtractPropertyReferences(js_obj, entry); |
| 1895 ExtractElementReferences(js_obj, entry); | 2057 ExtractElementReferences(js_obj, entry); |
| 1896 ExtractInternalReferences(js_obj, entry); | 2058 ExtractInternalReferences(js_obj, entry); |
| 1897 SetPropertyReference( | 2059 SetPropertyReference( |
| 1898 obj, entry, Heap::Proto_symbol(), js_obj->GetPrototype()); | 2060 obj, entry, Heap::Proto_symbol(), js_obj->GetPrototype()); |
| 1899 if (obj->IsJSFunction()) { | 2061 if (obj->IsJSFunction()) { |
| 1900 JSFunction* js_fun = JSFunction::cast(obj); | 2062 JSFunction* js_fun = JSFunction::cast(obj); |
| 1901 if (js_fun->has_prototype()) { | 2063 if (js_fun->has_prototype()) { |
| 1902 SetPropertyReference( | 2064 SetPropertyReference( |
| 1903 obj, entry, Heap::prototype_symbol(), js_fun->prototype()); | 2065 obj, entry, Heap::prototype_symbol(), js_fun->prototype()); |
| 1904 } | 2066 } |
| 1905 } | 2067 } |
| 2068 IndexedReferencesExtractor refs_extractor( |
| 2069 this, obj, entry, &known_references_); |
| 2070 obj->Iterate(&refs_extractor); |
| 1906 } else if (obj->IsString()) { | 2071 } else if (obj->IsString()) { |
| 1907 if (obj->IsConsString()) { | 2072 if (obj->IsConsString()) { |
| 1908 ConsString* cs = ConsString::cast(obj); | 2073 ConsString* cs = ConsString::cast(obj); |
| 1909 SetInternalReference(obj, entry, "1", cs->first()); | 2074 SetInternalReference(obj, entry, 1, cs->first()); |
| 1910 SetInternalReference(obj, entry, "2", cs->second()); | 2075 SetInternalReference(obj, entry, 2, cs->second()); |
| 1911 } | 2076 } |
| 1912 } else if (obj->IsCode() || obj->IsSharedFunctionInfo() || obj->IsScript()) { | 2077 } else { |
| 1913 IndexedReferencesExtractor refs_extractor(this, obj, entry); | |
| 1914 obj->Iterate(&refs_extractor); | |
| 1915 } else if (obj->IsFixedArray()) { | |
| 1916 IndexedReferencesExtractor refs_extractor(this, obj, entry); | 2078 IndexedReferencesExtractor refs_extractor(this, obj, entry); |
| 1917 obj->Iterate(&refs_extractor); | 2079 obj->Iterate(&refs_extractor); |
| 1918 } | 2080 } |
| 1919 } | 2081 } |
| 1920 | 2082 |
| 1921 | 2083 |
| 1922 void HeapSnapshotGenerator::ExtractClosureReferences(JSObject* js_obj, | 2084 void HeapSnapshotGenerator::ExtractClosureReferences(JSObject* js_obj, |
| 1923 HeapEntry* entry) { | 2085 HeapEntry* entry) { |
| 1924 if (js_obj->IsJSFunction()) { | 2086 if (js_obj->IsJSFunction()) { |
| 1925 HandleScope hs; | 2087 HandleScope hs; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1960 break; | 2122 break; |
| 1961 default: ; | 2123 default: ; |
| 1962 } | 2124 } |
| 1963 } | 2125 } |
| 1964 } else { | 2126 } else { |
| 1965 StringDictionary* dictionary = js_obj->property_dictionary(); | 2127 StringDictionary* dictionary = js_obj->property_dictionary(); |
| 1966 int length = dictionary->Capacity(); | 2128 int length = dictionary->Capacity(); |
| 1967 for (int i = 0; i < length; ++i) { | 2129 for (int i = 0; i < length; ++i) { |
| 1968 Object* k = dictionary->KeyAt(i); | 2130 Object* k = dictionary->KeyAt(i); |
| 1969 if (dictionary->IsKey(k)) { | 2131 if (dictionary->IsKey(k)) { |
| 2132 Object* target = dictionary->ValueAt(i); |
| 1970 SetPropertyReference( | 2133 SetPropertyReference( |
| 1971 js_obj, entry, String::cast(k), dictionary->ValueAt(i)); | 2134 js_obj, entry, String::cast(k), target); |
| 2135 // We assume that global objects can only have slow properties. |
| 2136 if (target->IsJSGlobalPropertyCell()) { |
| 2137 SetPropertyShortcutReference(js_obj, |
| 2138 entry, |
| 2139 String::cast(k), |
| 2140 JSGlobalPropertyCell::cast( |
| 2141 target)->value()); |
| 2142 } |
| 1972 } | 2143 } |
| 1973 } | 2144 } |
| 1974 } | 2145 } |
| 1975 } | 2146 } |
| 1976 | 2147 |
| 1977 | 2148 |
| 1978 void HeapSnapshotGenerator::ExtractElementReferences(JSObject* js_obj, | 2149 void HeapSnapshotGenerator::ExtractElementReferences(JSObject* js_obj, |
| 1979 HeapEntry* entry) { | 2150 HeapEntry* entry) { |
| 1980 if (js_obj->HasFastElements()) { | 2151 if (js_obj->HasFastElements()) { |
| 1981 FixedArray* elements = FixedArray::cast(js_obj->elements()); | 2152 FixedArray* elements = FixedArray::cast(js_obj->elements()); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2017 String* reference_name, | 2188 String* reference_name, |
| 2018 Object* child_obj) { | 2189 Object* child_obj) { |
| 2019 HeapEntry* child_entry = GetEntry(child_obj); | 2190 HeapEntry* child_entry = GetEntry(child_obj); |
| 2020 if (child_entry != NULL) { | 2191 if (child_entry != NULL) { |
| 2021 filler_->SetNamedReference(HeapGraphEdge::kContextVariable, | 2192 filler_->SetNamedReference(HeapGraphEdge::kContextVariable, |
| 2022 parent_obj, | 2193 parent_obj, |
| 2023 parent_entry, | 2194 parent_entry, |
| 2024 collection_->GetName(reference_name), | 2195 collection_->GetName(reference_name), |
| 2025 child_obj, | 2196 child_obj, |
| 2026 child_entry); | 2197 child_entry); |
| 2198 known_references_.Insert(child_obj); |
| 2027 } | 2199 } |
| 2028 } | 2200 } |
| 2029 | 2201 |
| 2030 | 2202 |
| 2031 void HeapSnapshotGenerator::SetElementReference(HeapObject* parent_obj, | 2203 void HeapSnapshotGenerator::SetElementReference(HeapObject* parent_obj, |
| 2032 HeapEntry* parent_entry, | 2204 HeapEntry* parent_entry, |
| 2033 int index, | 2205 int index, |
| 2034 Object* child_obj) { | 2206 Object* child_obj) { |
| 2035 HeapEntry* child_entry = GetEntry(child_obj); | 2207 HeapEntry* child_entry = GetEntry(child_obj); |
| 2036 if (child_entry != NULL) { | 2208 if (child_entry != NULL) { |
| 2037 filler_->SetElementReference( | 2209 filler_->SetIndexedReference(HeapGraphEdge::kElement, |
| 2038 parent_obj, parent_entry, index, child_obj, child_entry); | 2210 parent_obj, |
| 2211 parent_entry, |
| 2212 index, |
| 2213 child_obj, |
| 2214 child_entry); |
| 2215 known_references_.Insert(child_obj); |
| 2039 } | 2216 } |
| 2040 } | 2217 } |
| 2041 | 2218 |
| 2042 | 2219 |
| 2043 void HeapSnapshotGenerator::SetInternalReference(HeapObject* parent_obj, | 2220 void HeapSnapshotGenerator::SetInternalReference(HeapObject* parent_obj, |
| 2044 HeapEntry* parent_entry, | 2221 HeapEntry* parent_entry, |
| 2045 const char* reference_name, | 2222 const char* reference_name, |
| 2046 Object* child_obj) { | 2223 Object* child_obj) { |
| 2047 HeapEntry* child_entry = GetEntry(child_obj); | 2224 HeapEntry* child_entry = GetEntry(child_obj); |
| 2048 if (child_entry != NULL) { | 2225 if (child_entry != NULL) { |
| 2049 filler_->SetNamedReference(HeapGraphEdge::kInternal, | 2226 filler_->SetNamedReference(HeapGraphEdge::kInternal, |
| 2050 parent_obj, | 2227 parent_obj, |
| 2051 parent_entry, | 2228 parent_entry, |
| 2052 reference_name, | 2229 reference_name, |
| 2053 child_obj, | 2230 child_obj, |
| 2054 child_entry); | 2231 child_entry); |
| 2232 known_references_.Insert(child_obj); |
| 2055 } | 2233 } |
| 2056 } | 2234 } |
| 2057 | 2235 |
| 2058 | 2236 |
| 2059 void HeapSnapshotGenerator::SetInternalReference(HeapObject* parent_obj, | 2237 void HeapSnapshotGenerator::SetInternalReference(HeapObject* parent_obj, |
| 2060 HeapEntry* parent_entry, | 2238 HeapEntry* parent_entry, |
| 2061 int index, | 2239 int index, |
| 2062 Object* child_obj) { | 2240 Object* child_obj) { |
| 2063 HeapEntry* child_entry = GetEntry(child_obj); | 2241 HeapEntry* child_entry = GetEntry(child_obj); |
| 2064 if (child_entry != NULL) { | 2242 if (child_entry != NULL) { |
| 2065 filler_->SetNamedReference(HeapGraphEdge::kInternal, | 2243 filler_->SetNamedReference(HeapGraphEdge::kInternal, |
| 2066 parent_obj, | 2244 parent_obj, |
| 2067 parent_entry, | 2245 parent_entry, |
| 2068 collection_->GetName(index), | 2246 collection_->GetName(index), |
| 2069 child_obj, | 2247 child_obj, |
| 2070 child_entry); | 2248 child_entry); |
| 2249 known_references_.Insert(child_obj); |
| 2250 } |
| 2251 } |
| 2252 |
| 2253 |
| 2254 void HeapSnapshotGenerator::SetHiddenReference(HeapObject* parent_obj, |
| 2255 HeapEntry* parent_entry, |
| 2256 int index, |
| 2257 Object* child_obj) { |
| 2258 HeapEntry* child_entry = GetEntry(child_obj); |
| 2259 if (child_entry != NULL) { |
| 2260 filler_->SetIndexedReference(HeapGraphEdge::kHidden, |
| 2261 parent_obj, |
| 2262 parent_entry, |
| 2263 index, |
| 2264 child_obj, |
| 2265 child_entry); |
| 2071 } | 2266 } |
| 2072 } | 2267 } |
| 2073 | 2268 |
| 2074 | 2269 |
| 2075 void HeapSnapshotGenerator::SetPropertyReference(HeapObject* parent_obj, | 2270 void HeapSnapshotGenerator::SetPropertyReference(HeapObject* parent_obj, |
| 2076 HeapEntry* parent_entry, | 2271 HeapEntry* parent_entry, |
| 2077 String* reference_name, | 2272 String* reference_name, |
| 2078 Object* child_obj) { | 2273 Object* child_obj) { |
| 2079 HeapEntry* child_entry = GetEntry(child_obj); | 2274 HeapEntry* child_entry = GetEntry(child_obj); |
| 2080 if (child_entry != NULL) { | 2275 if (child_entry != NULL) { |
| 2081 HeapGraphEdge::Type type = reference_name->length() > 0 ? | 2276 HeapGraphEdge::Type type = reference_name->length() > 0 ? |
| 2082 HeapGraphEdge::kProperty : HeapGraphEdge::kInternal; | 2277 HeapGraphEdge::kProperty : HeapGraphEdge::kInternal; |
| 2083 filler_->SetNamedReference(type, | 2278 filler_->SetNamedReference(type, |
| 2084 parent_obj, | 2279 parent_obj, |
| 2085 parent_entry, | 2280 parent_entry, |
| 2086 collection_->GetName(reference_name), | 2281 collection_->GetName(reference_name), |
| 2087 child_obj, | 2282 child_obj, |
| 2088 child_entry); | 2283 child_entry); |
| 2284 known_references_.Insert(child_obj); |
| 2285 } |
| 2286 } |
| 2287 |
| 2288 |
| 2289 void HeapSnapshotGenerator::SetPropertyShortcutReference( |
| 2290 HeapObject* parent_obj, |
| 2291 HeapEntry* parent_entry, |
| 2292 String* reference_name, |
| 2293 Object* child_obj) { |
| 2294 HeapEntry* child_entry = GetEntry(child_obj); |
| 2295 if (child_entry != NULL) { |
| 2296 filler_->SetNamedReference(HeapGraphEdge::kShortcut, |
| 2297 parent_obj, |
| 2298 parent_entry, |
| 2299 collection_->GetName(reference_name), |
| 2300 child_obj, |
| 2301 child_entry); |
| 2089 } | 2302 } |
| 2090 } | 2303 } |
| 2091 | 2304 |
| 2092 | 2305 |
| 2093 void HeapSnapshotGenerator::SetRootReference(Object* child_obj) { | 2306 void HeapSnapshotGenerator::SetRootGcRootsReference() { |
| 2307 filler_->SetRootGcRootsReference(); |
| 2308 } |
| 2309 |
| 2310 |
| 2311 void HeapSnapshotGenerator::SetRootShortcutReference(Object* child_obj) { |
| 2094 HeapEntry* child_entry = GetEntry(child_obj); | 2312 HeapEntry* child_entry = GetEntry(child_obj); |
| 2095 ASSERT(child_entry != NULL); | 2313 ASSERT(child_entry != NULL); |
| 2096 filler_->SetRootReference(child_obj, child_entry); | 2314 filler_->SetRootShortcutReference(child_obj, child_entry); |
| 2315 } |
| 2316 |
| 2317 |
| 2318 void HeapSnapshotGenerator::SetGcRootsReference(Object* child_obj) { |
| 2319 HeapEntry* child_entry = GetEntry(child_obj); |
| 2320 if (child_entry != NULL) { |
| 2321 filler_->SetStrongRootReference(child_obj, child_entry); |
| 2322 } |
| 2097 } | 2323 } |
| 2098 | 2324 |
| 2099 | 2325 |
| 2100 void HeapSnapshotsDiff::CreateRoots(int additions_count, int deletions_count) { | 2326 void HeapSnapshotsDiff::CreateRoots(int additions_count, int deletions_count) { |
| 2101 raw_additions_root_ = | 2327 raw_additions_root_ = |
| 2102 NewArray<char>(HeapEntry::EntriesSize(1, additions_count, 0)); | 2328 NewArray<char>(HeapEntry::EntriesSize(1, additions_count, 0)); |
| 2103 additions_root()->Init( | 2329 additions_root()->Init( |
| 2104 snapshot2_, HeapEntry::kInternal, "", 0, 0, additions_count, 0); | 2330 snapshot2_, HeapEntry::kHidden, "", 0, 0, additions_count, 0); |
| 2105 raw_deletions_root_ = | 2331 raw_deletions_root_ = |
| 2106 NewArray<char>(HeapEntry::EntriesSize(1, deletions_count, 0)); | 2332 NewArray<char>(HeapEntry::EntriesSize(1, deletions_count, 0)); |
| 2107 deletions_root()->Init( | 2333 deletions_root()->Init( |
| 2108 snapshot1_, HeapEntry::kInternal, "", 0, 0, deletions_count, 0); | 2334 snapshot1_, HeapEntry::kHidden, "", 0, 0, deletions_count, 0); |
| 2109 } | 2335 } |
| 2110 | 2336 |
| 2111 | 2337 |
| 2112 static void DeleteHeapSnapshotsDiff(HeapSnapshotsDiff** diff_ptr) { | 2338 static void DeleteHeapSnapshotsDiff(HeapSnapshotsDiff** diff_ptr) { |
| 2113 delete *diff_ptr; | 2339 delete *diff_ptr; |
| 2114 } | 2340 } |
| 2115 | 2341 |
| 2116 HeapSnapshotsComparator::~HeapSnapshotsComparator() { | 2342 HeapSnapshotsComparator::~HeapSnapshotsComparator() { |
| 2117 diffs_.Iterate(DeleteHeapSnapshotsDiff); | 2343 diffs_.Iterate(DeleteHeapSnapshotsDiff); |
| 2118 } | 2344 } |
| (...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2317 cache_entry->value = reinterpret_cast<void*>(next_string_id_++); | 2543 cache_entry->value = reinterpret_cast<void*>(next_string_id_++); |
| 2318 } | 2544 } |
| 2319 return static_cast<int>(reinterpret_cast<intptr_t>(cache_entry->value)); | 2545 return static_cast<int>(reinterpret_cast<intptr_t>(cache_entry->value)); |
| 2320 } | 2546 } |
| 2321 | 2547 |
| 2322 | 2548 |
| 2323 void HeapSnapshotJSONSerializer::SerializeEdge(HeapGraphEdge* edge) { | 2549 void HeapSnapshotJSONSerializer::SerializeEdge(HeapGraphEdge* edge) { |
| 2324 writer_->AddCharacter(','); | 2550 writer_->AddCharacter(','); |
| 2325 writer_->AddNumber(edge->type()); | 2551 writer_->AddNumber(edge->type()); |
| 2326 writer_->AddCharacter(','); | 2552 writer_->AddCharacter(','); |
| 2327 if (edge->type() == HeapGraphEdge::kElement) { | 2553 if (edge->type() == HeapGraphEdge::kElement |
| 2554 || edge->type() == HeapGraphEdge::kHidden) { |
| 2328 writer_->AddNumber(edge->index()); | 2555 writer_->AddNumber(edge->index()); |
| 2329 } else { | 2556 } else { |
| 2330 writer_->AddNumber(GetStringId(edge->name())); | 2557 writer_->AddNumber(GetStringId(edge->name())); |
| 2331 } | 2558 } |
| 2332 writer_->AddCharacter(','); | 2559 writer_->AddCharacter(','); |
| 2333 writer_->AddNumber(GetNodeId(edge->to())); | 2560 writer_->AddNumber(GetNodeId(edge->to())); |
| 2334 } | 2561 } |
| 2335 | 2562 |
| 2336 | 2563 |
| 2337 void HeapSnapshotJSONSerializer::SerializeNode(HeapEntry* entry) { | 2564 void HeapSnapshotJSONSerializer::SerializeNode(HeapEntry* entry) { |
| 2338 writer_->AddCharacter('\n'); | 2565 writer_->AddCharacter('\n'); |
| 2339 writer_->AddCharacter(','); | 2566 writer_->AddCharacter(','); |
| 2340 writer_->AddNumber(entry->type()); | 2567 writer_->AddNumber(entry->type()); |
| 2341 writer_->AddCharacter(','); | 2568 writer_->AddCharacter(','); |
| 2342 writer_->AddNumber(GetStringId(entry->name())); | 2569 writer_->AddNumber(GetStringId(entry->name())); |
| 2343 writer_->AddCharacter(','); | 2570 writer_->AddCharacter(','); |
| 2344 writer_->AddNumber(entry->id()); | 2571 writer_->AddNumber(entry->id()); |
| 2345 writer_->AddCharacter(','); | 2572 writer_->AddCharacter(','); |
| 2346 writer_->AddNumber(entry->self_size()); | 2573 writer_->AddNumber(entry->self_size()); |
| 2574 writer_->AddCharacter(','); |
| 2575 writer_->AddNumber(entry->RetainedSize(false)); |
| 2576 writer_->AddCharacter(','); |
| 2577 writer_->AddNumber(GetNodeId(entry->dominator())); |
| 2347 Vector<HeapGraphEdge> children = entry->children(); | 2578 Vector<HeapGraphEdge> children = entry->children(); |
| 2348 writer_->AddCharacter(','); | 2579 writer_->AddCharacter(','); |
| 2349 writer_->AddNumber(children.length()); | 2580 writer_->AddNumber(children.length()); |
| 2350 for (int i = 0; i < children.length(); ++i) { | 2581 for (int i = 0; i < children.length(); ++i) { |
| 2351 SerializeEdge(&children[i]); | 2582 SerializeEdge(&children[i]); |
| 2352 if (writer_->aborted()) return; | 2583 if (writer_->aborted()) return; |
| 2353 } | 2584 } |
| 2354 } | 2585 } |
| 2355 | 2586 |
| 2356 | 2587 |
| 2357 void HeapSnapshotJSONSerializer::SerializeNodes() { | 2588 void HeapSnapshotJSONSerializer::SerializeNodes() { |
| 2358 // The first (zero) item of nodes array is a JSON-ified object | 2589 // The first (zero) item of nodes array is an object describing node |
| 2359 // describing node serialization layout. | 2590 // serialization layout. We use a set of macros to improve |
| 2360 // We use a set of macros to improve readability. | 2591 // readability. |
| 2361 #define JSON_A(s) "["s"]" | 2592 #define JSON_A(s) "["s"]" |
| 2362 #define JSON_O(s) "{"s"}" | 2593 #define JSON_O(s) "{"s"}" |
| 2363 #define JSON_S(s) "\\\""s"\\\"" | 2594 #define JSON_S(s) "\""s"\"" |
| 2364 writer_->AddString("\"" JSON_O( | 2595 writer_->AddString(JSON_O( |
| 2365 JSON_S("fields") ":" JSON_A( | 2596 JSON_S("fields") ":" JSON_A( |
| 2366 JSON_S("type") | 2597 JSON_S("type") |
| 2367 "," JSON_S("name") | 2598 "," JSON_S("name") |
| 2368 "," JSON_S("id") | 2599 "," JSON_S("id") |
| 2369 "," JSON_S("self_size") | 2600 "," JSON_S("self_size") |
| 2601 "," JSON_S("retained_size") |
| 2602 "," JSON_S("dominator") |
| 2370 "," JSON_S("children_count") | 2603 "," JSON_S("children_count") |
| 2371 "," JSON_S("children")) | 2604 "," JSON_S("children")) |
| 2372 "," JSON_S("types") ":" JSON_A( | 2605 "," JSON_S("types") ":" JSON_A( |
| 2373 JSON_A( | 2606 JSON_A( |
| 2374 JSON_S("internal") | 2607 JSON_S("hidden") |
| 2375 "," JSON_S("array") | 2608 "," JSON_S("array") |
| 2376 "," JSON_S("string") | 2609 "," JSON_S("string") |
| 2377 "," JSON_S("object") | 2610 "," JSON_S("object") |
| 2378 "," JSON_S("code") | 2611 "," JSON_S("code") |
| 2379 "," JSON_S("closure") | 2612 "," JSON_S("closure") |
| 2380 "," JSON_S("regexp") | 2613 "," JSON_S("regexp") |
| 2381 "," JSON_S("number")) | 2614 "," JSON_S("number")) |
| 2382 "," JSON_S("string") | 2615 "," JSON_S("string") |
| 2383 "," JSON_S("number") | 2616 "," JSON_S("number") |
| 2384 "," JSON_S("number") | 2617 "," JSON_S("number") |
| 2385 "," JSON_S("number") | 2618 "," JSON_S("number") |
| 2619 "," JSON_S("number") |
| 2620 "," JSON_S("number") |
| 2386 "," JSON_O( | 2621 "," JSON_O( |
| 2387 JSON_S("fields") ":" JSON_A( | 2622 JSON_S("fields") ":" JSON_A( |
| 2388 JSON_S("type") | 2623 JSON_S("type") |
| 2389 "," JSON_S("name_or_index") | 2624 "," JSON_S("name_or_index") |
| 2390 "," JSON_S("to_node")) | 2625 "," JSON_S("to_node")) |
| 2391 "," JSON_S("types") ":" JSON_A( | 2626 "," JSON_S("types") ":" JSON_A( |
| 2392 JSON_A( | 2627 JSON_A( |
| 2393 JSON_S("context") | 2628 JSON_S("context") |
| 2394 "," JSON_S("element") | 2629 "," JSON_S("element") |
| 2395 "," JSON_S("property") | 2630 "," JSON_S("property") |
| 2396 "," JSON_S("internal")) | 2631 "," JSON_S("internal") |
| 2632 "," JSON_S("hidden") |
| 2633 "," JSON_S("shortcut")) |
| 2397 "," JSON_S("string_or_number") | 2634 "," JSON_S("string_or_number") |
| 2398 "," JSON_S("node"))))) "\""); | 2635 "," JSON_S("node")))))); |
| 2399 #undef JSON_S | 2636 #undef JSON_S |
| 2400 #undef JSON_O | 2637 #undef JSON_O |
| 2401 #undef JSON_A | 2638 #undef JSON_A |
| 2402 | 2639 |
| 2403 const int node_fields_count = 5; // type,name,id,self_size,children_count. | 2640 const int node_fields_count = 7; |
| 2641 // type,name,id,self_size,retained_size,dominator,children_count. |
| 2404 const int edge_fields_count = 3; // type,name|index,to_node. | 2642 const int edge_fields_count = 3; // type,name|index,to_node. |
| 2405 List<HashMap::Entry*> sorted_nodes; | 2643 List<HashMap::Entry*> sorted_nodes; |
| 2406 SortHashMap(&nodes_, &sorted_nodes); | 2644 SortHashMap(&nodes_, &sorted_nodes); |
| 2407 // Rewrite node ids, so they refer to actual array positions. | 2645 // Rewrite node ids, so they refer to actual array positions. |
| 2408 if (sorted_nodes.length() > 1) { | 2646 if (sorted_nodes.length() > 1) { |
| 2409 // Nodes start from array index 1. | 2647 // Nodes start from array index 1. |
| 2410 int prev_value = 1; | 2648 int prev_value = 1; |
| 2411 sorted_nodes[0]->value = reinterpret_cast<void*>(prev_value); | 2649 sorted_nodes[0]->value = reinterpret_cast<void*>(prev_value); |
| 2412 for (int i = 1; i < sorted_nodes.length(); ++i) { | 2650 for (int i = 1; i < sorted_nodes.length(); ++i) { |
| 2413 HeapEntry* prev_heap_entry = | 2651 HeapEntry* prev_heap_entry = |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2522 void HeapSnapshotJSONSerializer::SortHashMap( | 2760 void HeapSnapshotJSONSerializer::SortHashMap( |
| 2523 HashMap* map, List<HashMap::Entry*>* sorted_entries) { | 2761 HashMap* map, List<HashMap::Entry*>* sorted_entries) { |
| 2524 for (HashMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) | 2762 for (HashMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) |
| 2525 sorted_entries->Add(p); | 2763 sorted_entries->Add(p); |
| 2526 sorted_entries->Sort(SortUsingEntryValue); | 2764 sorted_entries->Sort(SortUsingEntryValue); |
| 2527 } | 2765 } |
| 2528 | 2766 |
| 2529 } } // namespace v8::internal | 2767 } } // namespace v8::internal |
| 2530 | 2768 |
| 2531 #endif // ENABLE_LOGGING_AND_PROFILING | 2769 #endif // ENABLE_LOGGING_AND_PROFILING |
| OLD | NEW |