Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(120)

Side by Side Diff: src/profile-generator.cc

Issue 5274002: Version 2.5.8... (Closed) Base URL: http://v8.googlecode.com/svn/trunk/
Patch Set: Created 10 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/profile-generator.h ('k') | src/profile-generator-inl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/profile-generator.h ('k') | src/profile-generator-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698