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

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

Issue 10353010: Split nodes and edges into separate arrays in heap profiler. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Addressing comments. Created 8 years, 7 months 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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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 913 matching lines...) Expand 10 before | Expand all | Expand 10 after
924 // If no frames were symbolized, put the VM state entry in. 924 // If no frames were symbolized, put the VM state entry in.
925 if (no_symbolized_entries) { 925 if (no_symbolized_entries) {
926 *entry++ = EntryForVMState(sample.state); 926 *entry++ = EntryForVMState(sample.state);
927 } 927 }
928 } 928 }
929 929
930 profiles_->AddPathToCurrentProfiles(entries); 930 profiles_->AddPathToCurrentProfiles(entries);
931 } 931 }
932 932
933 933
934 void HeapGraphEdge::Init( 934 HeapGraphEdge::HeapGraphEdge(
935 int child_index, Type type, const char* name, HeapEntry* to) { 935 Type type, const char* name, int from, int to) :
936 type_(type),
937 from_index_(from),
938 to_index_(to),
939 name_(name) {
936 ASSERT(type == kContextVariable 940 ASSERT(type == kContextVariable
937 || type == kProperty 941 || type == kProperty
938 || type == kInternal 942 || type == kInternal
939 || type == kShortcut); 943 || type == kShortcut);
940 child_index_ = child_index;
941 type_ = type;
942 name_ = name;
943 to_ = to;
944 } 944 }
945 945
946 946
947 void HeapGraphEdge::Init(int child_index, Type type, int index, HeapEntry* to) { 947 HeapGraphEdge::HeapGraphEdge(Type type, int index, int from, int to) :
948 type_(type),
949 from_index_(from),
950 to_index_(to),
951 index_(index) {
948 ASSERT(type == kElement || type == kHidden || type == kWeak); 952 ASSERT(type == kElement || type == kHidden || type == kWeak);
949 child_index_ = child_index;
950 type_ = type;
951 index_ = index;
952 to_ = to;
953 } 953 }
954 954
955 955
956 void HeapGraphEdge::Init(int child_index, int index, HeapEntry* to) { 956 void HeapGraphEdge::ReplaceToIndexWithEntry(HeapSnapshot* snapshot) {
957 Init(child_index, kElement, index, to); 957 to_entry_ = &snapshot->entries()[to_index_];
958 } 958 }
959 959
960 960
961 void HeapEntry::Init(HeapSnapshot* snapshot, 961 const int HeapEntry::kNoEntry = -1;
962
963 HeapEntry::HeapEntry(HeapSnapshot* snapshot,
962 Type type, 964 Type type,
963 const char* name, 965 const char* name,
964 SnapshotObjectId id, 966 SnapshotObjectId id,
965 int self_size, 967 int self_size) :
966 int children_count, 968 painted_(false),
967 int retainers_count) { 969 user_reachable_(false),
968 snapshot_ = snapshot; 970 dominator_(kNoEntry),
969 type_ = type; 971 type_(type),
970 painted_ = false; 972 retainers_count_(0),
971 user_reachable_ = false; 973 retainers_index_(-1),
972 name_ = name; 974 children_count_(0),
973 self_size_ = self_size; 975 children_index_(-1),
974 retained_size_ = 0; 976 self_size_(self_size),
975 entry_index_ = -1; 977 retained_size_(0),
976 children_count_ = children_count; 978 id_(id),
977 retainers_count_ = retainers_count; 979 snapshot_(snapshot),
978 dominator_ = NULL; 980 name_(name) { }
979 id_ = id;
980 }
981 981
982 982
983 void HeapEntry::SetNamedReference(HeapGraphEdge::Type type, 983 void HeapEntry::SetNamedReference(HeapGraphEdge::Type type,
984 int child_index,
985 const char* name, 984 const char* name,
986 HeapEntry* entry, 985 HeapEntry* entry) {
987 int retainer_index) { 986 HeapGraphEdge edge(type, name, this->index(), entry->index());
988 children()[child_index].Init(child_index, type, name, entry); 987 snapshot_->edges().Add(edge);
989 entry->retainers()[retainer_index] = children_arr() + child_index; 988 ++children_count_;
989 ++entry->retainers_count_;
990 } 990 }
991 991
992 992
993 void HeapEntry::SetIndexedReference(HeapGraphEdge::Type type, 993 void HeapEntry::SetIndexedReference(HeapGraphEdge::Type type,
994 int child_index,
995 int index, 994 int index,
996 HeapEntry* entry, 995 HeapEntry* entry) {
997 int retainer_index) { 996 HeapGraphEdge edge(type, index, this->index(), entry->index());
998 children()[child_index].Init(child_index, type, index, entry); 997 snapshot_->edges().Add(edge);
999 entry->retainers()[retainer_index] = children_arr() + child_index; 998 ++children_count_;
999 ++entry->retainers_count_;
1000 } 1000 }
1001 1001
1002 1002
1003 void HeapEntry::SetUnidirElementReference(
1004 int child_index, int index, HeapEntry* entry) {
1005 children()[child_index].Init(child_index, index, entry);
1006 }
1007
1008
1009 Handle<HeapObject> HeapEntry::GetHeapObject() { 1003 Handle<HeapObject> HeapEntry::GetHeapObject() {
1010 return snapshot_->collection()->FindHeapObjectById(id()); 1004 return snapshot_->collection()->FindHeapObjectById(id());
1011 } 1005 }
1012 1006
1013 1007
1014 void HeapEntry::Print( 1008 void HeapEntry::Print(
1015 const char* prefix, const char* edge_name, int max_depth, int indent) { 1009 const char* prefix, const char* edge_name, int max_depth, int indent) {
1016 OS::Print("%6d %7d @%6llu %*c %s%s: ", 1010 STATIC_CHECK(sizeof(unsigned) == sizeof(id()));
1011 OS::Print("%6d %7d @%6u %*c %s%s: ",
1017 self_size(), retained_size(), id(), 1012 self_size(), retained_size(), id(),
1018 indent, ' ', prefix, edge_name); 1013 indent, ' ', prefix, edge_name);
1019 if (type() != kString) { 1014 if (type() != kString) {
1020 OS::Print("%s %.40s\n", TypeAsString(), name_); 1015 OS::Print("%s %.40s\n", TypeAsString(), name_);
1021 } else { 1016 } else {
1022 OS::Print("\""); 1017 OS::Print("\"");
1023 const char* c = name_; 1018 const char* c = name_;
1024 while (*c && (c - name_) <= 40) { 1019 while (*c && (c - name_) <= 40) {
1025 if (*c != '\n') 1020 if (*c != '\n')
1026 OS::Print("%c", *c); 1021 OS::Print("%c", *c);
1027 else 1022 else
1028 OS::Print("\\n"); 1023 OS::Print("\\n");
1029 ++c; 1024 ++c;
1030 } 1025 }
1031 OS::Print("\"\n"); 1026 OS::Print("\"\n");
1032 } 1027 }
1033 if (--max_depth == 0) return; 1028 if (--max_depth == 0) return;
1034 Vector<HeapGraphEdge> ch = children(); 1029 Vector<HeapGraphEdge*> ch = children();
1035 for (int i = 0; i < ch.length(); ++i) { 1030 for (int i = 0; i < ch.length(); ++i) {
1036 HeapGraphEdge& edge = ch[i]; 1031 HeapGraphEdge& edge = *ch[i];
1037 const char* edge_prefix = ""; 1032 const char* edge_prefix = "";
1038 EmbeddedVector<char, 64> index; 1033 EmbeddedVector<char, 64> index;
1039 const char* edge_name = index.start(); 1034 const char* edge_name = index.start();
1040 switch (edge.type()) { 1035 switch (edge.type()) {
1041 case HeapGraphEdge::kContextVariable: 1036 case HeapGraphEdge::kContextVariable:
1042 edge_prefix = "#"; 1037 edge_prefix = "#";
1043 edge_name = edge.name(); 1038 edge_name = edge.name();
1044 break; 1039 break;
1045 case HeapGraphEdge::kElement: 1040 case HeapGraphEdge::kElement:
1046 OS::SNPrintF(index, "%d", edge.index()); 1041 OS::SNPrintF(index, "%d", edge.index());
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
1082 case kArray: return "/array/"; 1077 case kArray: return "/array/";
1083 case kRegExp: return "/regexp/"; 1078 case kRegExp: return "/regexp/";
1084 case kHeapNumber: return "/number/"; 1079 case kHeapNumber: return "/number/";
1085 case kNative: return "/native/"; 1080 case kNative: return "/native/";
1086 case kSynthetic: return "/synthetic/"; 1081 case kSynthetic: return "/synthetic/";
1087 default: return "???"; 1082 default: return "???";
1088 } 1083 }
1089 } 1084 }
1090 1085
1091 1086
1092 size_t HeapEntry::EntriesSize(int entries_count,
1093 int children_count,
1094 int retainers_count) {
1095 return sizeof(HeapEntry) * entries_count // NOLINT
1096 + sizeof(HeapGraphEdge) * children_count // NOLINT
1097 + sizeof(HeapGraphEdge*) * retainers_count; // NOLINT
1098 }
1099
1100
1101 // It is very important to keep objects that form a heap snapshot 1087 // It is very important to keep objects that form a heap snapshot
1102 // as small as possible. 1088 // as small as possible.
1103 namespace { // Avoid littering the global namespace. 1089 namespace { // Avoid littering the global namespace.
1104 1090
1105 template <size_t ptr_size> struct SnapshotSizeConstants; 1091 template <size_t ptr_size> struct SnapshotSizeConstants;
1106 1092
1107 template <> struct SnapshotSizeConstants<4> { 1093 template <> struct SnapshotSizeConstants<4> {
1108 static const int kExpectedHeapGraphEdgeSize = 12; 1094 static const int kExpectedHeapGraphEdgeSize = 12;
1109 static const int kExpectedHeapEntrySize = 36; 1095 static const int kExpectedHeapEntrySize = 40;
1110 static const size_t kMaxSerializableSnapshotRawSize = 256 * MB; 1096 static const size_t kMaxSerializableSnapshotRawSize = 256 * MB;
1111 }; 1097 };
1112 1098
1113 template <> struct SnapshotSizeConstants<8> { 1099 template <> struct SnapshotSizeConstants<8> {
1114 static const int kExpectedHeapGraphEdgeSize = 24; 1100 static const int kExpectedHeapGraphEdgeSize = 24;
1115 static const int kExpectedHeapEntrySize = 48; 1101 static const int kExpectedHeapEntrySize = 48;
1116 static const uint64_t kMaxSerializableSnapshotRawSize = 1102 static const uint64_t kMaxSerializableSnapshotRawSize =
1117 static_cast<uint64_t>(6000) * MB; 1103 static_cast<uint64_t>(6000) * MB;
1118 }; 1104 };
1119 1105
1120 } // namespace 1106 } // namespace
1121 1107
1122 HeapSnapshot::HeapSnapshot(HeapSnapshotsCollection* collection, 1108 HeapSnapshot::HeapSnapshot(HeapSnapshotsCollection* collection,
1123 HeapSnapshot::Type type, 1109 HeapSnapshot::Type type,
1124 const char* title, 1110 const char* title,
1125 unsigned uid) 1111 unsigned uid)
1126 : collection_(collection), 1112 : collection_(collection),
1127 type_(type), 1113 type_(type),
1128 title_(title), 1114 title_(title),
1129 uid_(uid), 1115 uid_(uid),
1130 root_entry_(NULL), 1116 root_index_(HeapEntry::kNoEntry),
1131 gc_roots_entry_(NULL), 1117 gc_roots_index_(HeapEntry::kNoEntry),
1132 natives_root_entry_(NULL), 1118 natives_root_index_(HeapEntry::kNoEntry),
1133 raw_entries_(NULL),
1134 number_of_edges_(0),
1135 max_snapshot_js_object_id_(0) { 1119 max_snapshot_js_object_id_(0) {
1136 STATIC_CHECK( 1120 STATIC_CHECK(
1137 sizeof(HeapGraphEdge) == 1121 sizeof(HeapGraphEdge) ==
1138 SnapshotSizeConstants<kPointerSize>::kExpectedHeapGraphEdgeSize); 1122 SnapshotSizeConstants<kPointerSize>::kExpectedHeapGraphEdgeSize);
1139 STATIC_CHECK( 1123 STATIC_CHECK(
1140 sizeof(HeapEntry) == 1124 sizeof(HeapEntry) ==
1141 SnapshotSizeConstants<kPointerSize>::kExpectedHeapEntrySize); 1125 SnapshotSizeConstants<kPointerSize>::kExpectedHeapEntrySize);
1142 for (int i = 0; i < VisitorSynchronization::kNumberOfSyncTags; ++i) { 1126 for (int i = 0; i < VisitorSynchronization::kNumberOfSyncTags; ++i) {
1143 gc_subroot_entries_[i] = NULL; 1127 gc_subroot_indexes_[i] = HeapEntry::kNoEntry;
1144 } 1128 }
1145 } 1129 }
1146 1130
1147 1131
1148 HeapSnapshot::~HeapSnapshot() {
1149 DeleteArray(raw_entries_);
1150 }
1151
1152
1153 void HeapSnapshot::Delete() { 1132 void HeapSnapshot::Delete() {
1154 collection_->RemoveSnapshot(this); 1133 collection_->RemoveSnapshot(this);
1155 delete this; 1134 delete this;
1156 } 1135 }
1157 1136
1158 1137
1159 void HeapSnapshot::RememberLastJSObjectId() { 1138 void HeapSnapshot::RememberLastJSObjectId() {
1160 max_snapshot_js_object_id_ = collection_->last_assigned_id(); 1139 max_snapshot_js_object_id_ = collection_->last_assigned_id();
1161 } 1140 }
1162 1141
1163 1142
1164 void HeapSnapshot::AllocateEntries(int entries_count, 1143 static void HeapEntryClearPaint(HeapEntry* entry_ptr) {
1165 int children_count, 1144 entry_ptr->clear_paint();
1166 int retainers_count) {
1167 ASSERT(raw_entries_ == NULL);
1168 number_of_edges_ = children_count;
1169 raw_entries_size_ =
1170 HeapEntry::EntriesSize(entries_count, children_count, retainers_count);
1171 raw_entries_ = NewArray<char>(raw_entries_size_);
1172 } 1145 }
1173 1146
1174 1147
1175 static void HeapEntryClearPaint(HeapEntry** entry_ptr) {
1176 (*entry_ptr)->clear_paint();
1177 }
1178
1179
1180 void HeapSnapshot::ClearPaint() { 1148 void HeapSnapshot::ClearPaint() {
1181 entries_.Iterate(HeapEntryClearPaint); 1149 entries_.Iterate(HeapEntryClearPaint);
1182 } 1150 }
1183 1151
1184 1152
1185 HeapEntry* HeapSnapshot::AddRootEntry(int children_count) { 1153 HeapEntry* HeapSnapshot::AddRootEntry() {
1186 ASSERT(root_entry_ == NULL); 1154 ASSERT(root_index_ == HeapEntry::kNoEntry);
1187 ASSERT(entries_.is_empty()); // Root entry must be the first one. 1155 ASSERT(entries_.is_empty()); // Root entry must be the first one.
1188 return (root_entry_ = AddEntry(HeapEntry::kObject, 1156 HeapEntry* entry = AddEntry(HeapEntry::kObject,
1189 "", 1157 "",
1190 HeapObjectsMap::kInternalRootObjectId, 1158 HeapObjectsMap::kInternalRootObjectId,
1191 0, 1159 0);
1192 children_count, 1160 root_index_ = entry->index();
1193 0)); 1161 ASSERT(root_index_ == 0);
1162 return entry;
1194 } 1163 }
1195 1164
1196 1165
1197 HeapEntry* HeapSnapshot::AddGcRootsEntry(int children_count, 1166 HeapEntry* HeapSnapshot::AddGcRootsEntry() {
1198 int retainers_count) { 1167 ASSERT(gc_roots_index_ == HeapEntry::kNoEntry);
1199 ASSERT(gc_roots_entry_ == NULL); 1168 HeapEntry* entry = AddEntry(HeapEntry::kObject,
1200 return (gc_roots_entry_ = AddEntry(HeapEntry::kObject, 1169 "(GC roots)",
1201 "(GC roots)", 1170 HeapObjectsMap::kGcRootsObjectId,
1202 HeapObjectsMap::kGcRootsObjectId, 1171 0);
1203 0, 1172 gc_roots_index_ = entry->index();
1204 children_count, 1173 return entry;
1205 retainers_count));
1206 } 1174 }
1207 1175
1208 1176
1209 HeapEntry* HeapSnapshot::AddGcSubrootEntry(int tag, 1177 HeapEntry* HeapSnapshot::AddGcSubrootEntry(int tag) {
1210 int children_count, 1178 ASSERT(gc_subroot_indexes_[tag] == HeapEntry::kNoEntry);
1211 int retainers_count) {
1212 ASSERT(gc_subroot_entries_[tag] == NULL);
1213 ASSERT(0 <= tag && tag < VisitorSynchronization::kNumberOfSyncTags); 1179 ASSERT(0 <= tag && tag < VisitorSynchronization::kNumberOfSyncTags);
1214 return (gc_subroot_entries_[tag] = AddEntry( 1180 HeapEntry* entry = AddEntry(
1215 HeapEntry::kObject, 1181 HeapEntry::kObject,
1216 VisitorSynchronization::kTagNames[tag], 1182 VisitorSynchronization::kTagNames[tag],
1217 HeapObjectsMap::GetNthGcSubrootId(tag), 1183 HeapObjectsMap::GetNthGcSubrootId(tag),
1218 0, 1184 0);
1219 children_count, 1185 gc_subroot_indexes_[tag] = entry->index();
1220 retainers_count)); 1186 return entry;
1221 } 1187 }
1222 1188
1223 1189
1224 HeapEntry* HeapSnapshot::AddEntry(HeapEntry::Type type, 1190 HeapEntry* HeapSnapshot::AddEntry(HeapEntry::Type type,
1225 const char* name, 1191 const char* name,
1226 SnapshotObjectId id, 1192 SnapshotObjectId id,
1227 int size, 1193 int size) {
1228 int children_count, 1194 HeapEntry entry(this, type, name, id, size);
1229 int retainers_count) { 1195 entries_.Add(entry);
1230 HeapEntry* entry = GetNextEntryToInit(); 1196 return &entries_.last();
1231 entry->Init(this, type, name, id, size, children_count, retainers_count); 1197 }
1232 return entry; 1198
1199
1200 void HeapSnapshot::FillChildrenAndRetainers() {
1201 ASSERT(children().is_empty());
1202 children().Allocate(edges().length());
1203 ASSERT(retainers().is_empty());
1204 retainers().Allocate(edges().length());
1205 int children_index = 0;
1206 int retainers_index = 0;
1207 for (int i = 0; i < entries().length(); ++i) {
1208 HeapEntry* entry = &entries()[i];
1209 children_index = entry->set_children_index(children_index);
1210 retainers_index = entry->set_retainers_index(retainers_index);
1211 }
1212 ASSERT(edges().length() == children_index);
1213 ASSERT(edges().length() == retainers_index);
1214 for (int i = 0; i < edges().length(); ++i) {
1215 HeapGraphEdge* edge = &edges()[i];
1216 edge->ReplaceToIndexWithEntry(this);
1217 edge->from()->add_child(edge);
1218 edge->to()->add_retainer(edge);
1219 }
1233 } 1220 }
1234 1221
1235 1222
1236 void HeapSnapshot::SetDominatorsToSelf() { 1223 void HeapSnapshot::SetDominatorsToSelf() {
1237 for (int i = 0; i < entries_.length(); ++i) { 1224 for (int i = 0; i < entries_.length(); ++i) {
1238 HeapEntry* entry = entries_[i]; 1225 entries_[i].set_dominator(&entries_[i]);
1239 if (entry->dominator() == NULL) entry->set_dominator(entry);
1240 } 1226 }
1241 } 1227 }
1242 1228
1243 1229
1244 HeapEntry* HeapSnapshot::GetNextEntryToInit() {
1245 if (entries_.length() > 0) {
1246 HeapEntry* last_entry = entries_.last();
1247 entries_.Add(reinterpret_cast<HeapEntry*>(
1248 reinterpret_cast<char*>(last_entry) + last_entry->EntrySize()));
1249 } else {
1250 entries_.Add(reinterpret_cast<HeapEntry*>(raw_entries_));
1251 }
1252 ASSERT(reinterpret_cast<char*>(entries_.last()) <
1253 (raw_entries_ + raw_entries_size_));
1254 return entries_.last();
1255 }
1256
1257
1258 class FindEntryById { 1230 class FindEntryById {
1259 public: 1231 public:
1260 explicit FindEntryById(SnapshotObjectId id) : id_(id) { } 1232 explicit FindEntryById(SnapshotObjectId id) : id_(id) { }
1261 int operator()(HeapEntry* const* entry) { 1233 int operator()(HeapEntry* const* entry) {
1262 if ((*entry)->id() == id_) return 0; 1234 if ((*entry)->id() == id_) return 0;
1263 return (*entry)->id() < id_ ? -1 : 1; 1235 return (*entry)->id() < id_ ? -1 : 1;
1264 } 1236 }
1265 private: 1237 private:
1266 SnapshotObjectId id_; 1238 SnapshotObjectId id_;
1267 }; 1239 };
(...skipping 12 matching lines...) Expand all
1280 template<class T> 1252 template<class T>
1281 static int SortByIds(const T* entry1_ptr, 1253 static int SortByIds(const T* entry1_ptr,
1282 const T* entry2_ptr) { 1254 const T* entry2_ptr) {
1283 if ((*entry1_ptr)->id() == (*entry2_ptr)->id()) return 0; 1255 if ((*entry1_ptr)->id() == (*entry2_ptr)->id()) return 0;
1284 return (*entry1_ptr)->id() < (*entry2_ptr)->id() ? -1 : 1; 1256 return (*entry1_ptr)->id() < (*entry2_ptr)->id() ? -1 : 1;
1285 } 1257 }
1286 1258
1287 1259
1288 List<HeapEntry*>* HeapSnapshot::GetSortedEntriesList() { 1260 List<HeapEntry*>* HeapSnapshot::GetSortedEntriesList() {
1289 if (sorted_entries_.is_empty()) { 1261 if (sorted_entries_.is_empty()) {
1290 sorted_entries_.AddAll(entries_); 1262 sorted_entries_.Allocate(entries_.length());
1263 for (int i = 0; i < entries_.length(); ++i) {
1264 sorted_entries_[i] = &entries_[i];
1265 }
1291 sorted_entries_.Sort(SortByIds); 1266 sorted_entries_.Sort(SortByIds);
1292 } 1267 }
1293 return &sorted_entries_; 1268 return &sorted_entries_;
1294 } 1269 }
1295 1270
1296 1271
1297 void HeapSnapshot::Print(int max_depth) { 1272 void HeapSnapshot::Print(int max_depth) {
1298 root()->Print("", "", max_depth, 0); 1273 root()->Print("", "", max_depth, 0);
1299 } 1274 }
1300 1275
1301 1276
1277 template<typename T, class P>
1278 static size_t GetMemoryUsedByList(const List<T,P>& list) {
1279 return list.capacity() * sizeof(T);
1280 }
1281
1282
1283 size_t HeapSnapshot::RawSnapshotSize() const {
1284 return
1285 GetMemoryUsedByList(entries_) +
1286 GetMemoryUsedByList(edges_) +
1287 GetMemoryUsedByList(children_) +
1288 GetMemoryUsedByList(retainers_) +
1289 GetMemoryUsedByList(sorted_entries_);
1290 }
1291
1292
1302 // We split IDs on evens for embedder objects (see 1293 // We split IDs on evens for embedder objects (see
1303 // HeapObjectsMap::GenerateId) and odds for native objects. 1294 // HeapObjectsMap::GenerateId) and odds for native objects.
1304 const SnapshotObjectId HeapObjectsMap::kInternalRootObjectId = 1; 1295 const SnapshotObjectId HeapObjectsMap::kInternalRootObjectId = 1;
1305 const SnapshotObjectId HeapObjectsMap::kGcRootsObjectId = 1296 const SnapshotObjectId HeapObjectsMap::kGcRootsObjectId =
1306 HeapObjectsMap::kInternalRootObjectId + HeapObjectsMap::kObjectIdStep; 1297 HeapObjectsMap::kInternalRootObjectId + HeapObjectsMap::kObjectIdStep;
1307 const SnapshotObjectId HeapObjectsMap::kGcRootsFirstSubrootId = 1298 const SnapshotObjectId HeapObjectsMap::kGcRootsFirstSubrootId =
1308 HeapObjectsMap::kGcRootsObjectId + HeapObjectsMap::kObjectIdStep; 1299 HeapObjectsMap::kGcRootsObjectId + HeapObjectsMap::kObjectIdStep;
1309 const SnapshotObjectId HeapObjectsMap::kFirstAvailableObjectId = 1300 const SnapshotObjectId HeapObjectsMap::kFirstAvailableObjectId =
1310 HeapObjectsMap::kGcRootsFirstSubrootId + 1301 HeapObjectsMap::kGcRootsFirstSubrootId +
1311 VisitorSynchronization::kNumberOfSyncTags * HeapObjectsMap::kObjectIdStep; 1302 VisitorSynchronization::kNumberOfSyncTags * HeapObjectsMap::kObjectIdStep;
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after
1560 if (ids_.FindEntry(obj->address()) == id) { 1551 if (ids_.FindEntry(obj->address()) == id) {
1561 ASSERT(object == NULL); 1552 ASSERT(object == NULL);
1562 object = obj; 1553 object = obj;
1563 // Can't break -- kFilterUnreachable requires full heap traversal. 1554 // Can't break -- kFilterUnreachable requires full heap traversal.
1564 } 1555 }
1565 } 1556 }
1566 return object != NULL ? Handle<HeapObject>(object) : Handle<HeapObject>(); 1557 return object != NULL ? Handle<HeapObject>(object) : Handle<HeapObject>();
1567 } 1558 }
1568 1559
1569 1560
1570 HeapEntry* const HeapEntriesMap::kHeapEntryPlaceholder =
1571 reinterpret_cast<HeapEntry*>(1);
1572
1573 HeapEntriesMap::HeapEntriesMap() 1561 HeapEntriesMap::HeapEntriesMap()
1574 : entries_(HeapThingsMatch), 1562 : entries_(HeapThingsMatch) {
1575 entries_count_(0),
1576 total_children_count_(0),
1577 total_retainers_count_(0) {
1578 } 1563 }
1579 1564
1580 1565
1581 HeapEntriesMap::~HeapEntriesMap() { 1566 int HeapEntriesMap::Map(HeapThing thing) {
1582 for (HashMap::Entry* p = entries_.Start(); p != NULL; p = entries_.Next(p)) { 1567 HashMap::Entry* cache_entry = entries_.Lookup(thing, Hash(thing), false);
1583 delete reinterpret_cast<EntryInfo*>(p->value); 1568 if (cache_entry == NULL) return HeapEntry::kNoEntry;
1584 } 1569 return static_cast<int>(reinterpret_cast<intptr_t>(cache_entry->value));
1585 } 1570 }
1586 1571
1587 1572
1588 void HeapEntriesMap::AllocateHeapEntryForMapEntry(HashMap::Entry* map_entry) { 1573 void HeapEntriesMap::Pair(HeapThing thing, int entry) {
1589 EntryInfo* entry_info = reinterpret_cast<EntryInfo*>(map_entry->value); 1574 HashMap::Entry* cache_entry = entries_.Lookup(thing, Hash(thing), true);
1590 entry_info->entry = entry_info->allocator->AllocateEntry( 1575 ASSERT(cache_entry->value == NULL);
1591 map_entry->key, 1576 cache_entry->value = reinterpret_cast<void*>(static_cast<intptr_t>(entry));
1592 entry_info->children_count,
1593 entry_info->retainers_count);
1594 ASSERT(entry_info->entry != NULL);
1595 ASSERT(entry_info->entry != kHeapEntryPlaceholder);
1596 entry_info->children_count = 0;
1597 entry_info->retainers_count = 0;
1598 } 1577 }
1599 1578
1600 1579
1601 void HeapEntriesMap::AllocateEntries(HeapThing root_object) {
1602 HashMap::Entry* root_entry =
1603 entries_.Lookup(root_object, Hash(root_object), false);
1604 ASSERT(root_entry != NULL);
1605 // Make sure root entry is allocated first.
1606 AllocateHeapEntryForMapEntry(root_entry);
1607 void* root_entry_value = root_entry->value;
1608 // Remove the root object from map while iterating through other entries.
1609 entries_.Remove(root_object, Hash(root_object));
1610 root_entry = NULL;
1611
1612 for (HashMap::Entry* p = entries_.Start();
1613 p != NULL;
1614 p = entries_.Next(p)) {
1615 AllocateHeapEntryForMapEntry(p);
1616 }
1617
1618 // Insert root entry back.
1619 root_entry = entries_.Lookup(root_object, Hash(root_object), true);
1620 root_entry->value = root_entry_value;
1621 }
1622
1623
1624 HeapEntry* HeapEntriesMap::Map(HeapThing thing) {
1625 HashMap::Entry* cache_entry = entries_.Lookup(thing, Hash(thing), false);
1626 if (cache_entry != NULL) {
1627 EntryInfo* entry_info = reinterpret_cast<EntryInfo*>(cache_entry->value);
1628 return entry_info->entry;
1629 } else {
1630 return NULL;
1631 }
1632 }
1633
1634
1635 void HeapEntriesMap::Pair(
1636 HeapThing thing, HeapEntriesAllocator* allocator, HeapEntry* entry) {
1637 HashMap::Entry* cache_entry = entries_.Lookup(thing, Hash(thing), true);
1638 ASSERT(cache_entry->value == NULL);
1639 cache_entry->value = new EntryInfo(entry, allocator);
1640 ++entries_count_;
1641 }
1642
1643
1644 void HeapEntriesMap::CountReference(HeapThing from, HeapThing to,
1645 int* prev_children_count,
1646 int* prev_retainers_count) {
1647 HashMap::Entry* from_cache_entry = entries_.Lookup(from, Hash(from), false);
1648 HashMap::Entry* to_cache_entry = entries_.Lookup(to, Hash(to), false);
1649 ASSERT(from_cache_entry != NULL);
1650 ASSERT(to_cache_entry != NULL);
1651 EntryInfo* from_entry_info =
1652 reinterpret_cast<EntryInfo*>(from_cache_entry->value);
1653 EntryInfo* to_entry_info =
1654 reinterpret_cast<EntryInfo*>(to_cache_entry->value);
1655 if (prev_children_count)
1656 *prev_children_count = from_entry_info->children_count;
1657 if (prev_retainers_count)
1658 *prev_retainers_count = to_entry_info->retainers_count;
1659 ++from_entry_info->children_count;
1660 ++to_entry_info->retainers_count;
1661 ++total_children_count_;
1662 ++total_retainers_count_;
1663 }
1664
1665
1666 HeapObjectsSet::HeapObjectsSet() 1580 HeapObjectsSet::HeapObjectsSet()
1667 : entries_(HeapEntriesMap::HeapThingsMatch) { 1581 : entries_(HeapEntriesMap::HeapThingsMatch) {
1668 } 1582 }
1669 1583
1670 1584
1671 void HeapObjectsSet::Clear() { 1585 void HeapObjectsSet::Clear() {
1672 entries_.Clear(); 1586 entries_.Clear();
1673 } 1587 }
1674 1588
1675 1589
1676 bool HeapObjectsSet::Contains(Object* obj) { 1590 bool HeapObjectsSet::Contains(Object* obj) {
1677 if (!obj->IsHeapObject()) return false; 1591 if (!obj->IsHeapObject()) return false;
1678 HeapObject* object = HeapObject::cast(obj); 1592 HeapObject* object = HeapObject::cast(obj);
1679 HashMap::Entry* cache_entry = 1593 return entries_.Lookup(object, HeapEntriesMap::Hash(object), false) != NULL;
1680 entries_.Lookup(object, HeapEntriesMap::Hash(object), false);
1681 return cache_entry != NULL;
1682 } 1594 }
1683 1595
1684 1596
1685 void HeapObjectsSet::Insert(Object* obj) { 1597 void HeapObjectsSet::Insert(Object* obj) {
1686 if (!obj->IsHeapObject()) return; 1598 if (!obj->IsHeapObject()) return;
1687 HeapObject* object = HeapObject::cast(obj); 1599 HeapObject* object = HeapObject::cast(obj);
1688 HashMap::Entry* cache_entry = 1600 entries_.Lookup(object, HeapEntriesMap::Hash(object), true);
1689 entries_.Lookup(object, HeapEntriesMap::Hash(object), true);
1690 if (cache_entry->value == NULL) {
1691 cache_entry->value = HeapEntriesMap::kHeapEntryPlaceholder;
1692 }
1693 } 1601 }
1694 1602
1695 1603
1696 const char* HeapObjectsSet::GetTag(Object* obj) { 1604 const char* HeapObjectsSet::GetTag(Object* obj) {
1697 HeapObject* object = HeapObject::cast(obj); 1605 HeapObject* object = HeapObject::cast(obj);
1698 HashMap::Entry* cache_entry = 1606 HashMap::Entry* cache_entry =
1699 entries_.Lookup(object, HeapEntriesMap::Hash(object), false); 1607 entries_.Lookup(object, HeapEntriesMap::Hash(object), false);
1700 if (cache_entry != NULL 1608 return cache_entry != NULL
1701 && cache_entry->value != HeapEntriesMap::kHeapEntryPlaceholder) { 1609 ? reinterpret_cast<const char*>(cache_entry->value)
1702 return reinterpret_cast<const char*>(cache_entry->value); 1610 : NULL;
1703 } else {
1704 return NULL;
1705 }
1706 } 1611 }
1707 1612
1708 1613
1709 void HeapObjectsSet::SetTag(Object* obj, const char* tag) { 1614 void HeapObjectsSet::SetTag(Object* obj, const char* tag) {
1710 if (!obj->IsHeapObject()) return; 1615 if (!obj->IsHeapObject()) return;
1711 HeapObject* object = HeapObject::cast(obj); 1616 HeapObject* object = HeapObject::cast(obj);
1712 HashMap::Entry* cache_entry = 1617 HashMap::Entry* cache_entry =
1713 entries_.Lookup(object, HeapEntriesMap::Hash(object), true); 1618 entries_.Lookup(object, HeapEntriesMap::Hash(object), true);
1714 cache_entry->value = const_cast<char*>(tag); 1619 cache_entry->value = const_cast<char*>(tag);
1715 } 1620 }
(...skipping 21 matching lines...) Expand all
1737 collection_(snapshot_->collection()), 1642 collection_(snapshot_->collection()),
1738 progress_(progress), 1643 progress_(progress),
1739 filler_(NULL) { 1644 filler_(NULL) {
1740 } 1645 }
1741 1646
1742 1647
1743 V8HeapExplorer::~V8HeapExplorer() { 1648 V8HeapExplorer::~V8HeapExplorer() {
1744 } 1649 }
1745 1650
1746 1651
1747 HeapEntry* V8HeapExplorer::AllocateEntry( 1652 HeapEntry* V8HeapExplorer::AllocateEntry(HeapThing ptr) {
1748 HeapThing ptr, int children_count, int retainers_count) { 1653 return AddEntry(reinterpret_cast<HeapObject*>(ptr));
1749 return AddEntry(
1750 reinterpret_cast<HeapObject*>(ptr), children_count, retainers_count);
1751 } 1654 }
1752 1655
1753 1656
1754 HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object, 1657 HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object) {
1755 int children_count,
1756 int retainers_count) {
1757 if (object == kInternalRootObject) { 1658 if (object == kInternalRootObject) {
1758 ASSERT(retainers_count == 0); 1659 snapshot_->AddRootEntry();
1759 return snapshot_->AddRootEntry(children_count); 1660 return snapshot_->root();
1760 } else if (object == kGcRootsObject) { 1661 } else if (object == kGcRootsObject) {
1761 return snapshot_->AddGcRootsEntry(children_count, retainers_count); 1662 HeapEntry* entry = snapshot_->AddGcRootsEntry();
1663 return entry;
1762 } else if (object >= kFirstGcSubrootObject && object < kLastGcSubrootObject) { 1664 } else if (object >= kFirstGcSubrootObject && object < kLastGcSubrootObject) {
1763 return snapshot_->AddGcSubrootEntry( 1665 HeapEntry* entry = snapshot_->AddGcSubrootEntry(GetGcSubrootOrder(object));
1764 GetGcSubrootOrder(object), 1666 return entry;
1765 children_count,
1766 retainers_count);
1767 } else if (object->IsJSFunction()) { 1667 } else if (object->IsJSFunction()) {
1768 JSFunction* func = JSFunction::cast(object); 1668 JSFunction* func = JSFunction::cast(object);
1769 SharedFunctionInfo* shared = func->shared(); 1669 SharedFunctionInfo* shared = func->shared();
1770 const char* name = shared->bound() ? "native_bind" : 1670 const char* name = shared->bound() ? "native_bind" :
1771 collection_->names()->GetName(String::cast(shared->name())); 1671 collection_->names()->GetName(String::cast(shared->name()));
1772 return AddEntry(object, 1672 return AddEntry(object, HeapEntry::kClosure, name);
1773 HeapEntry::kClosure,
1774 name,
1775 children_count,
1776 retainers_count);
1777 } else if (object->IsJSRegExp()) { 1673 } else if (object->IsJSRegExp()) {
1778 JSRegExp* re = JSRegExp::cast(object); 1674 JSRegExp* re = JSRegExp::cast(object);
1779 return AddEntry(object, 1675 return AddEntry(object,
1780 HeapEntry::kRegExp, 1676 HeapEntry::kRegExp,
1781 collection_->names()->GetName(re->Pattern()), 1677 collection_->names()->GetName(re->Pattern()));
1782 children_count,
1783 retainers_count);
1784 } else if (object->IsJSObject()) { 1678 } else if (object->IsJSObject()) {
1785 return AddEntry(object, 1679 return AddEntry(object, HeapEntry::kObject, "");
1786 HeapEntry::kObject,
1787 "",
1788 children_count,
1789 retainers_count);
1790 } else if (object->IsString()) { 1680 } else if (object->IsString()) {
1791 return AddEntry(object, 1681 return AddEntry(object,
1792 HeapEntry::kString, 1682 HeapEntry::kString,
1793 collection_->names()->GetName(String::cast(object)), 1683 collection_->names()->GetName(String::cast(object)));
1794 children_count,
1795 retainers_count);
1796 } else if (object->IsCode()) { 1684 } else if (object->IsCode()) {
1685 return AddEntry(object, HeapEntry::kCode, "");
1686 } else if (object->IsSharedFunctionInfo()) {
1687 String* name = String::cast(SharedFunctionInfo::cast(object)->name());
1797 return AddEntry(object, 1688 return AddEntry(object,
1798 HeapEntry::kCode, 1689 HeapEntry::kCode,
1799 "", 1690 collection_->names()->GetName(name));
1800 children_count, 1691 } else if (object->IsScript()) {
1801 retainers_count); 1692 Object* name = Script::cast(object)->name();
1802 } else if (object->IsSharedFunctionInfo()) {
1803 SharedFunctionInfo* shared = SharedFunctionInfo::cast(object);
1804 return AddEntry(object, 1693 return AddEntry(object,
1805 HeapEntry::kCode, 1694 HeapEntry::kCode,
1806 collection_->names()->GetName(String::cast(shared->name())), 1695 name->IsString()
1807 children_count, 1696 ? collection_->names()->GetName(String::cast(name))
1808 retainers_count); 1697 : "");
1809 } else if (object->IsScript()) {
1810 Script* script = Script::cast(object);
1811 return AddEntry(object,
1812 HeapEntry::kCode,
1813 script->name()->IsString() ?
1814 collection_->names()->GetName(
1815 String::cast(script->name()))
1816 : "",
1817 children_count,
1818 retainers_count);
1819 } else if (object->IsGlobalContext()) { 1698 } else if (object->IsGlobalContext()) {
1820 return AddEntry(object, 1699 return AddEntry(object, HeapEntry::kHidden, "system / GlobalContext");
1821 HeapEntry::kHidden,
1822 "system / GlobalContext",
1823 children_count,
1824 retainers_count);
1825 } else if (object->IsContext()) { 1700 } else if (object->IsContext()) {
1826 return AddEntry(object, 1701 return AddEntry(object, HeapEntry::kHidden, "system / Context");
1827 HeapEntry::kHidden,
1828 "system / Context",
1829 children_count,
1830 retainers_count);
1831 } else if (object->IsFixedArray() || 1702 } else if (object->IsFixedArray() ||
1832 object->IsFixedDoubleArray() || 1703 object->IsFixedDoubleArray() ||
1833 object->IsByteArray() || 1704 object->IsByteArray() ||
1834 object->IsExternalArray()) { 1705 object->IsExternalArray()) {
1835 const char* tag = objects_tags_.GetTag(object); 1706 const char* tag = objects_tags_.GetTag(object);
1836 return AddEntry(object, 1707 return AddEntry(object, HeapEntry::kArray, tag != NULL ? tag : "");
1837 HeapEntry::kArray,
1838 tag != NULL ? tag : "",
1839 children_count,
1840 retainers_count);
1841 } else if (object->IsHeapNumber()) { 1708 } else if (object->IsHeapNumber()) {
1842 return AddEntry(object, 1709 return AddEntry(object, HeapEntry::kHeapNumber, "number");
1843 HeapEntry::kHeapNumber,
1844 "number",
1845 children_count,
1846 retainers_count);
1847 } 1710 }
1848 return AddEntry(object, 1711 return AddEntry(object, HeapEntry::kHidden, GetSystemEntryName(object));
1849 HeapEntry::kHidden,
1850 GetSystemEntryName(object),
1851 children_count,
1852 retainers_count);
1853 } 1712 }
1854 1713
1855 1714
1856 HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object, 1715 HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object,
1857 HeapEntry::Type type, 1716 HeapEntry::Type type,
1858 const char* name, 1717 const char* name) {
1859 int children_count,
1860 int retainers_count) {
1861 int object_size = object->Size(); 1718 int object_size = object->Size();
1862 SnapshotObjectId object_id = 1719 SnapshotObjectId object_id =
1863 collection_->GetObjectId(object->address(), object_size); 1720 collection_->GetObjectId(object->address(), object_size);
1864 return snapshot_->AddEntry(type, 1721 return snapshot_->AddEntry(type, name, object_id, object_size);
1865 name,
1866 object_id,
1867 object_size,
1868 children_count,
1869 retainers_count);
1870 } 1722 }
1871 1723
1872 1724
1873 class GcSubrootsEnumerator : public ObjectVisitor { 1725 class GcSubrootsEnumerator : public ObjectVisitor {
1874 public: 1726 public:
1875 GcSubrootsEnumerator( 1727 GcSubrootsEnumerator(
1876 SnapshotFillerInterface* filler, V8HeapExplorer* explorer) 1728 SnapshotFillerInterface* filler, V8HeapExplorer* explorer)
1877 : filler_(filler), 1729 : filler_(filler),
1878 explorer_(explorer), 1730 explorer_(explorer),
1879 previous_object_count_(0), 1731 previous_object_count_(0),
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
1928 objects_count++; 1780 objects_count++;
1929 } 1781 }
1930 return objects_count; 1782 return objects_count;
1931 } 1783 }
1932 1784
1933 1785
1934 class IndexedReferencesExtractor : public ObjectVisitor { 1786 class IndexedReferencesExtractor : public ObjectVisitor {
1935 public: 1787 public:
1936 IndexedReferencesExtractor(V8HeapExplorer* generator, 1788 IndexedReferencesExtractor(V8HeapExplorer* generator,
1937 HeapObject* parent_obj, 1789 HeapObject* parent_obj,
1938 HeapEntry* parent_entry) 1790 int parent)
1939 : generator_(generator), 1791 : generator_(generator),
1940 parent_obj_(parent_obj), 1792 parent_obj_(parent_obj),
1941 parent_(parent_entry), 1793 parent_(parent),
1942 next_index_(1) { 1794 next_index_(1) {
1943 } 1795 }
1944 void VisitPointers(Object** start, Object** end) { 1796 void VisitPointers(Object** start, Object** end) {
1945 for (Object** p = start; p < end; p++) { 1797 for (Object** p = start; p < end; p++) {
1946 if (CheckVisitedAndUnmark(p)) continue; 1798 if (CheckVisitedAndUnmark(p)) continue;
1947 generator_->SetHiddenReference(parent_obj_, parent_, next_index_++, *p); 1799 generator_->SetHiddenReference(parent_obj_, parent_, next_index_++, *p);
1948 } 1800 }
1949 } 1801 }
1950 static void MarkVisitedField(HeapObject* obj, int offset) { 1802 static void MarkVisitedField(HeapObject* obj, int offset) {
1951 if (offset < 0) return; 1803 if (offset < 0) return;
1952 Address field = obj->address() + offset; 1804 Address field = obj->address() + offset;
1953 ASSERT(!Memory::Object_at(field)->IsFailure()); 1805 ASSERT(!Memory::Object_at(field)->IsFailure());
1954 ASSERT(Memory::Object_at(field)->IsHeapObject()); 1806 ASSERT(Memory::Object_at(field)->IsHeapObject());
1955 *field |= kFailureTag; 1807 *field |= kFailureTag;
1956 } 1808 }
1957 1809
1958 private: 1810 private:
1959 bool CheckVisitedAndUnmark(Object** field) { 1811 bool CheckVisitedAndUnmark(Object** field) {
1960 if ((*field)->IsFailure()) { 1812 if ((*field)->IsFailure()) {
1961 intptr_t untagged = reinterpret_cast<intptr_t>(*field) & ~kFailureTagMask; 1813 intptr_t untagged = reinterpret_cast<intptr_t>(*field) & ~kFailureTagMask;
1962 *field = reinterpret_cast<Object*>(untagged | kHeapObjectTag); 1814 *field = reinterpret_cast<Object*>(untagged | kHeapObjectTag);
1963 ASSERT((*field)->IsHeapObject()); 1815 ASSERT((*field)->IsHeapObject());
1964 return true; 1816 return true;
1965 } 1817 }
1966 return false; 1818 return false;
1967 } 1819 }
1968 V8HeapExplorer* generator_; 1820 V8HeapExplorer* generator_;
1969 HeapObject* parent_obj_; 1821 HeapObject* parent_obj_;
1970 HeapEntry* parent_; 1822 int parent_;
1971 int next_index_; 1823 int next_index_;
1972 }; 1824 };
1973 1825
1974 1826
1975 void V8HeapExplorer::ExtractReferences(HeapObject* obj) { 1827 void V8HeapExplorer::ExtractReferences(HeapObject* obj) {
1976 HeapEntry* entry = GetEntry(obj); 1828 HeapEntry* heap_entry = GetEntry(obj);
1977 if (entry == NULL) return; // No interest in this object. 1829 if (heap_entry == NULL) return; // No interest in this object.
1830 int entry = heap_entry->index();
1978 1831
1979 bool extract_indexed_refs = true; 1832 bool extract_indexed_refs = true;
1980 if (obj->IsJSGlobalProxy()) { 1833 if (obj->IsJSGlobalProxy()) {
1981 ExtractJSGlobalProxyReferences(JSGlobalProxy::cast(obj)); 1834 ExtractJSGlobalProxyReferences(JSGlobalProxy::cast(obj));
1982 } else if (obj->IsJSObject()) { 1835 } else if (obj->IsJSObject()) {
1983 ExtractJSObjectReferences(entry, JSObject::cast(obj)); 1836 ExtractJSObjectReferences(entry, JSObject::cast(obj));
1984 } else if (obj->IsString()) { 1837 } else if (obj->IsString()) {
1985 ExtractStringReferences(entry, String::cast(obj)); 1838 ExtractStringReferences(entry, String::cast(obj));
1986 extract_indexed_refs = false; 1839 extract_indexed_refs = false;
1987 } else if (obj->IsContext()) { 1840 } else if (obj->IsContext()) {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
2019 is_debug_object = object->IsGlobalObject() && 1872 is_debug_object = object->IsGlobalObject() &&
2020 Isolate::Current()->debug()->IsDebugGlobal(GlobalObject::cast(object)); 1873 Isolate::Current()->debug()->IsDebugGlobal(GlobalObject::cast(object));
2021 #endif 1874 #endif
2022 if (!is_debug_object) { 1875 if (!is_debug_object) {
2023 SetUserGlobalReference(object); 1876 SetUserGlobalReference(object);
2024 } 1877 }
2025 } 1878 }
2026 1879
2027 1880
2028 void V8HeapExplorer::ExtractJSObjectReferences( 1881 void V8HeapExplorer::ExtractJSObjectReferences(
2029 HeapEntry* entry, JSObject* js_obj) { 1882 int entry, JSObject* js_obj) {
2030 HeapObject* obj = js_obj; 1883 HeapObject* obj = js_obj;
2031 ExtractClosureReferences(js_obj, entry); 1884 ExtractClosureReferences(js_obj, entry);
2032 ExtractPropertyReferences(js_obj, entry); 1885 ExtractPropertyReferences(js_obj, entry);
2033 ExtractElementReferences(js_obj, entry); 1886 ExtractElementReferences(js_obj, entry);
2034 ExtractInternalReferences(js_obj, entry); 1887 ExtractInternalReferences(js_obj, entry);
2035 SetPropertyReference( 1888 SetPropertyReference(
2036 obj, entry, heap_->Proto_symbol(), js_obj->GetPrototype()); 1889 obj, entry, heap_->Proto_symbol(), js_obj->GetPrototype());
2037 if (obj->IsJSFunction()) { 1890 if (obj->IsJSFunction()) {
2038 JSFunction* js_fun = JSFunction::cast(js_obj); 1891 JSFunction* js_fun = JSFunction::cast(js_obj);
2039 Object* proto_or_map = js_fun->prototype_or_initial_map(); 1892 Object* proto_or_map = js_fun->prototype_or_initial_map();
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
2088 SetInternalReference(obj, entry, 1941 SetInternalReference(obj, entry,
2089 "properties", js_obj->properties(), 1942 "properties", js_obj->properties(),
2090 JSObject::kPropertiesOffset); 1943 JSObject::kPropertiesOffset);
2091 TagObject(js_obj->elements(), "(object elements)"); 1944 TagObject(js_obj->elements(), "(object elements)");
2092 SetInternalReference(obj, entry, 1945 SetInternalReference(obj, entry,
2093 "elements", js_obj->elements(), 1946 "elements", js_obj->elements(),
2094 JSObject::kElementsOffset); 1947 JSObject::kElementsOffset);
2095 } 1948 }
2096 1949
2097 1950
2098 void V8HeapExplorer::ExtractStringReferences(HeapEntry* entry, String* string) { 1951 void V8HeapExplorer::ExtractStringReferences(int entry, String* string) {
2099 if (string->IsConsString()) { 1952 if (string->IsConsString()) {
2100 ConsString* cs = ConsString::cast(string); 1953 ConsString* cs = ConsString::cast(string);
2101 SetInternalReference(cs, entry, "first", cs->first()); 1954 SetInternalReference(cs, entry, "first", cs->first());
2102 SetInternalReference(cs, entry, "second", cs->second()); 1955 SetInternalReference(cs, entry, "second", cs->second());
2103 } else if (string->IsSlicedString()) { 1956 } else if (string->IsSlicedString()) {
2104 SlicedString* ss = SlicedString::cast(string); 1957 SlicedString* ss = SlicedString::cast(string);
2105 SetInternalReference(ss, entry, "parent", ss->parent()); 1958 SetInternalReference(ss, entry, "parent", ss->parent());
2106 } 1959 }
2107 } 1960 }
2108 1961
2109 1962
2110 void V8HeapExplorer::ExtractContextReferences( 1963 void V8HeapExplorer::ExtractContextReferences(int entry, Context* context) {
2111 HeapEntry* entry, Context* context) {
2112 #define EXTRACT_CONTEXT_FIELD(index, type, name) \ 1964 #define EXTRACT_CONTEXT_FIELD(index, type, name) \
2113 SetInternalReference(context, entry, #name, context->get(Context::index), \ 1965 SetInternalReference(context, entry, #name, context->get(Context::index), \
2114 FixedArray::OffsetOfElementAt(Context::index)); 1966 FixedArray::OffsetOfElementAt(Context::index));
2115 EXTRACT_CONTEXT_FIELD(CLOSURE_INDEX, JSFunction, closure); 1967 EXTRACT_CONTEXT_FIELD(CLOSURE_INDEX, JSFunction, closure);
2116 EXTRACT_CONTEXT_FIELD(PREVIOUS_INDEX, Context, previous); 1968 EXTRACT_CONTEXT_FIELD(PREVIOUS_INDEX, Context, previous);
2117 EXTRACT_CONTEXT_FIELD(EXTENSION_INDEX, Object, extension); 1969 EXTRACT_CONTEXT_FIELD(EXTENSION_INDEX, Object, extension);
2118 EXTRACT_CONTEXT_FIELD(GLOBAL_INDEX, GlobalObject, global); 1970 EXTRACT_CONTEXT_FIELD(GLOBAL_INDEX, GlobalObject, global);
2119 if (context->IsGlobalContext()) { 1971 if (context->IsGlobalContext()) {
2120 TagObject(context->jsfunction_result_caches(), 1972 TagObject(context->jsfunction_result_caches(),
2121 "(context func. result caches)"); 1973 "(context func. result caches)");
2122 TagObject(context->normalized_map_cache(), "(context norm. map cache)"); 1974 TagObject(context->normalized_map_cache(), "(context norm. map cache)");
2123 TagObject(context->runtime_context(), "(runtime context)"); 1975 TagObject(context->runtime_context(), "(runtime context)");
2124 TagObject(context->data(), "(context data)"); 1976 TagObject(context->data(), "(context data)");
2125 GLOBAL_CONTEXT_FIELDS(EXTRACT_CONTEXT_FIELD); 1977 GLOBAL_CONTEXT_FIELDS(EXTRACT_CONTEXT_FIELD);
2126 #undef EXTRACT_CONTEXT_FIELD 1978 #undef EXTRACT_CONTEXT_FIELD
2127 for (int i = Context::FIRST_WEAK_SLOT; 1979 for (int i = Context::FIRST_WEAK_SLOT;
2128 i < Context::GLOBAL_CONTEXT_SLOTS; 1980 i < Context::GLOBAL_CONTEXT_SLOTS;
2129 ++i) { 1981 ++i) {
2130 SetWeakReference(context, entry, i, context->get(i), 1982 SetWeakReference(context, entry, i, context->get(i),
2131 FixedArray::OffsetOfElementAt(i)); 1983 FixedArray::OffsetOfElementAt(i));
2132 } 1984 }
2133 } 1985 }
2134 } 1986 }
2135 1987
2136 1988
2137 void V8HeapExplorer::ExtractMapReferences(HeapEntry* entry, Map* map) { 1989 void V8HeapExplorer::ExtractMapReferences(int entry, Map* map) {
2138 SetInternalReference(map, entry, 1990 SetInternalReference(map, entry,
2139 "prototype", map->prototype(), Map::kPrototypeOffset); 1991 "prototype", map->prototype(), Map::kPrototypeOffset);
2140 SetInternalReference(map, entry, 1992 SetInternalReference(map, entry,
2141 "constructor", map->constructor(), 1993 "constructor", map->constructor(),
2142 Map::kConstructorOffset); 1994 Map::kConstructorOffset);
2143 if (!map->instance_descriptors()->IsEmpty()) { 1995 if (!map->instance_descriptors()->IsEmpty()) {
2144 TagObject(map->instance_descriptors(), "(map descriptors)"); 1996 TagObject(map->instance_descriptors(), "(map descriptors)");
2145 SetInternalReference(map, entry, 1997 SetInternalReference(map, entry,
2146 "descriptors", map->instance_descriptors(), 1998 "descriptors", map->instance_descriptors(),
2147 Map::kInstanceDescriptorsOrBitField3Offset); 1999 Map::kInstanceDescriptorsOrBitField3Offset);
2148 } 2000 }
2149 TagObject(map->prototype_transitions(), "(prototype transitions)"); 2001 TagObject(map->prototype_transitions(), "(prototype transitions)");
2150 SetInternalReference(map, entry, 2002 SetInternalReference(map, entry,
2151 "prototype_transitions", map->prototype_transitions(), 2003 "prototype_transitions", map->prototype_transitions(),
2152 Map::kPrototypeTransitionsOffset); 2004 Map::kPrototypeTransitionsOffset);
2153 SetInternalReference(map, entry, 2005 SetInternalReference(map, entry,
2154 "code_cache", map->code_cache(), 2006 "code_cache", map->code_cache(),
2155 Map::kCodeCacheOffset); 2007 Map::kCodeCacheOffset);
2156 } 2008 }
2157 2009
2158 2010
2159 void V8HeapExplorer::ExtractSharedFunctionInfoReferences( 2011 void V8HeapExplorer::ExtractSharedFunctionInfoReferences(
2160 HeapEntry* entry, SharedFunctionInfo* shared) { 2012 int entry, SharedFunctionInfo* shared) {
2161 HeapObject* obj = shared; 2013 HeapObject* obj = shared;
2162 SetInternalReference(obj, entry, 2014 SetInternalReference(obj, entry,
2163 "name", shared->name(), 2015 "name", shared->name(),
2164 SharedFunctionInfo::kNameOffset); 2016 SharedFunctionInfo::kNameOffset);
2165 TagObject(shared->code(), "(code)"); 2017 TagObject(shared->code(), "(code)");
2166 SetInternalReference(obj, entry, 2018 SetInternalReference(obj, entry,
2167 "code", shared->code(), 2019 "code", shared->code(),
2168 SharedFunctionInfo::kCodeOffset); 2020 SharedFunctionInfo::kCodeOffset);
2169 TagObject(shared->scope_info(), "(function scope info)"); 2021 TagObject(shared->scope_info(), "(function scope info)");
2170 SetInternalReference(obj, entry, 2022 SetInternalReference(obj, entry,
(...skipping 21 matching lines...) Expand all
2192 SetInternalReference(obj, entry, 2044 SetInternalReference(obj, entry,
2193 "this_property_assignments", 2045 "this_property_assignments",
2194 shared->this_property_assignments(), 2046 shared->this_property_assignments(),
2195 SharedFunctionInfo::kThisPropertyAssignmentsOffset); 2047 SharedFunctionInfo::kThisPropertyAssignmentsOffset);
2196 SetWeakReference(obj, entry, 2048 SetWeakReference(obj, entry,
2197 1, shared->initial_map(), 2049 1, shared->initial_map(),
2198 SharedFunctionInfo::kInitialMapOffset); 2050 SharedFunctionInfo::kInitialMapOffset);
2199 } 2051 }
2200 2052
2201 2053
2202 void V8HeapExplorer::ExtractScriptReferences(HeapEntry* entry, Script* script) { 2054 void V8HeapExplorer::ExtractScriptReferences(int entry, Script* script) {
2203 HeapObject* obj = script; 2055 HeapObject* obj = script;
2204 SetInternalReference(obj, entry, 2056 SetInternalReference(obj, entry,
2205 "source", script->source(), 2057 "source", script->source(),
2206 Script::kSourceOffset); 2058 Script::kSourceOffset);
2207 SetInternalReference(obj, entry, 2059 SetInternalReference(obj, entry,
2208 "name", script->name(), 2060 "name", script->name(),
2209 Script::kNameOffset); 2061 Script::kNameOffset);
2210 SetInternalReference(obj, entry, 2062 SetInternalReference(obj, entry,
2211 "data", script->data(), 2063 "data", script->data(),
2212 Script::kDataOffset); 2064 Script::kDataOffset);
2213 SetInternalReference(obj, entry, 2065 SetInternalReference(obj, entry,
2214 "context_data", script->context_data(), 2066 "context_data", script->context_data(),
2215 Script::kContextOffset); 2067 Script::kContextOffset);
2216 TagObject(script->line_ends(), "(script line ends)"); 2068 TagObject(script->line_ends(), "(script line ends)");
2217 SetInternalReference(obj, entry, 2069 SetInternalReference(obj, entry,
2218 "line_ends", script->line_ends(), 2070 "line_ends", script->line_ends(),
2219 Script::kLineEndsOffset); 2071 Script::kLineEndsOffset);
2220 } 2072 }
2221 2073
2222 2074
2223 void V8HeapExplorer::ExtractCodeCacheReferences( 2075 void V8HeapExplorer::ExtractCodeCacheReferences(
2224 HeapEntry* entry, CodeCache* code_cache) { 2076 int entry, CodeCache* code_cache) {
2225 TagObject(code_cache->default_cache(), "(default code cache)"); 2077 TagObject(code_cache->default_cache(), "(default code cache)");
2226 SetInternalReference(code_cache, entry, 2078 SetInternalReference(code_cache, entry,
2227 "default_cache", code_cache->default_cache(), 2079 "default_cache", code_cache->default_cache(),
2228 CodeCache::kDefaultCacheOffset); 2080 CodeCache::kDefaultCacheOffset);
2229 TagObject(code_cache->normal_type_cache(), "(code type cache)"); 2081 TagObject(code_cache->normal_type_cache(), "(code type cache)");
2230 SetInternalReference(code_cache, entry, 2082 SetInternalReference(code_cache, entry,
2231 "type_cache", code_cache->normal_type_cache(), 2083 "type_cache", code_cache->normal_type_cache(),
2232 CodeCache::kNormalTypeCacheOffset); 2084 CodeCache::kNormalTypeCacheOffset);
2233 } 2085 }
2234 2086
2235 2087
2236 void V8HeapExplorer::ExtractCodeReferences(HeapEntry* entry, Code* code) { 2088 void V8HeapExplorer::ExtractCodeReferences(int entry, Code* code) {
2237 TagObject(code->relocation_info(), "(code relocation info)"); 2089 TagObject(code->relocation_info(), "(code relocation info)");
2238 SetInternalReference(code, entry, 2090 SetInternalReference(code, entry,
2239 "relocation_info", code->relocation_info(), 2091 "relocation_info", code->relocation_info(),
2240 Code::kRelocationInfoOffset); 2092 Code::kRelocationInfoOffset);
2241 SetInternalReference(code, entry, 2093 SetInternalReference(code, entry,
2242 "handler_table", code->handler_table(), 2094 "handler_table", code->handler_table(),
2243 Code::kHandlerTableOffset); 2095 Code::kHandlerTableOffset);
2244 TagObject(code->deoptimization_data(), "(code deopt data)"); 2096 TagObject(code->deoptimization_data(), "(code deopt data)");
2245 SetInternalReference(code, entry, 2097 SetInternalReference(code, entry,
2246 "deoptimization_data", code->deoptimization_data(), 2098 "deoptimization_data", code->deoptimization_data(),
2247 Code::kDeoptimizationDataOffset); 2099 Code::kDeoptimizationDataOffset);
2248 SetInternalReference(code, entry, 2100 SetInternalReference(code, entry,
2249 "type_feedback_info", code->type_feedback_info(), 2101 "type_feedback_info", code->type_feedback_info(),
2250 Code::kTypeFeedbackInfoOffset); 2102 Code::kTypeFeedbackInfoOffset);
2251 SetInternalReference(code, entry, 2103 SetInternalReference(code, entry,
2252 "gc_metadata", code->gc_metadata(), 2104 "gc_metadata", code->gc_metadata(),
2253 Code::kGCMetadataOffset); 2105 Code::kGCMetadataOffset);
2254 } 2106 }
2255 2107
2256 2108
2257 void V8HeapExplorer::ExtractJSGlobalPropertyCellReferences( 2109 void V8HeapExplorer::ExtractJSGlobalPropertyCellReferences(
2258 HeapEntry* entry, JSGlobalPropertyCell* cell) { 2110 int entry, JSGlobalPropertyCell* cell) {
2259 SetInternalReference(cell, entry, "value", cell->value()); 2111 SetInternalReference(cell, entry, "value", cell->value());
2260 } 2112 }
2261 2113
2262 2114
2263 void V8HeapExplorer::ExtractClosureReferences(JSObject* js_obj, 2115 void V8HeapExplorer::ExtractClosureReferences(JSObject* js_obj, int entry) {
2264 HeapEntry* entry) {
2265 if (!js_obj->IsJSFunction()) return; 2116 if (!js_obj->IsJSFunction()) return;
2266 2117
2267 JSFunction* func = JSFunction::cast(js_obj); 2118 JSFunction* func = JSFunction::cast(js_obj);
2268 if (func->shared()->bound()) { 2119 if (func->shared()->bound()) {
2269 FixedArray* bindings = func->function_bindings(); 2120 FixedArray* bindings = func->function_bindings();
2270 SetNativeBindReference(js_obj, entry, "bound_this", 2121 SetNativeBindReference(js_obj, entry, "bound_this",
2271 bindings->get(JSFunction::kBoundThisIndex)); 2122 bindings->get(JSFunction::kBoundThisIndex));
2272 SetNativeBindReference(js_obj, entry, "bound_function", 2123 SetNativeBindReference(js_obj, entry, "bound_function",
2273 bindings->get(JSFunction::kBoundFunctionIndex)); 2124 bindings->get(JSFunction::kBoundFunctionIndex));
2274 for (int i = JSFunction::kBoundArgumentsStartIndex; 2125 for (int i = JSFunction::kBoundArgumentsStartIndex;
(...skipping 21 matching lines...) Expand all
2296 VariableMode mode; 2147 VariableMode mode;
2297 int idx = scope_info->FunctionContextSlotIndex(name, &mode); 2148 int idx = scope_info->FunctionContextSlotIndex(name, &mode);
2298 if (idx >= 0) { 2149 if (idx >= 0) {
2299 SetClosureReference(js_obj, entry, name, context->get(idx)); 2150 SetClosureReference(js_obj, entry, name, context->get(idx));
2300 } 2151 }
2301 } 2152 }
2302 } 2153 }
2303 } 2154 }
2304 2155
2305 2156
2306 void V8HeapExplorer::ExtractPropertyReferences(JSObject* js_obj, 2157 void V8HeapExplorer::ExtractPropertyReferences(JSObject* js_obj, int entry) {
2307 HeapEntry* entry) {
2308 if (js_obj->HasFastProperties()) { 2158 if (js_obj->HasFastProperties()) {
2309 DescriptorArray* descs = js_obj->map()->instance_descriptors(); 2159 DescriptorArray* descs = js_obj->map()->instance_descriptors();
2310 for (int i = 0; i < descs->number_of_descriptors(); i++) { 2160 for (int i = 0; i < descs->number_of_descriptors(); i++) {
2311 switch (descs->GetType(i)) { 2161 switch (descs->GetType(i)) {
2312 case FIELD: { 2162 case FIELD: {
2313 int index = descs->GetFieldIndex(i); 2163 int index = descs->GetFieldIndex(i);
2314 if (index < js_obj->map()->inobject_properties()) { 2164 if (index < js_obj->map()->inobject_properties()) {
2315 SetPropertyReference( 2165 SetPropertyReference(
2316 js_obj, entry, 2166 js_obj, entry,
2317 descs->GetKey(i), js_obj->InObjectPropertyAt(index), 2167 descs->GetKey(i), js_obj->InObjectPropertyAt(index),
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
2370 } else { 2220 } else {
2371 TagObject(value, "(hidden properties)"); 2221 TagObject(value, "(hidden properties)");
2372 SetInternalReference(js_obj, entry, "hidden_properties", value); 2222 SetInternalReference(js_obj, entry, "hidden_properties", value);
2373 } 2223 }
2374 } 2224 }
2375 } 2225 }
2376 } 2226 }
2377 } 2227 }
2378 2228
2379 2229
2380 void V8HeapExplorer::ExtractElementReferences(JSObject* js_obj, 2230 void V8HeapExplorer::ExtractElementReferences(JSObject* js_obj, int entry) {
2381 HeapEntry* entry) {
2382 if (js_obj->HasFastElements()) { 2231 if (js_obj->HasFastElements()) {
2383 FixedArray* elements = FixedArray::cast(js_obj->elements()); 2232 FixedArray* elements = FixedArray::cast(js_obj->elements());
2384 int length = js_obj->IsJSArray() ? 2233 int length = js_obj->IsJSArray() ?
2385 Smi::cast(JSArray::cast(js_obj)->length())->value() : 2234 Smi::cast(JSArray::cast(js_obj)->length())->value() :
2386 elements->length(); 2235 elements->length();
2387 for (int i = 0; i < length; ++i) { 2236 for (int i = 0; i < length; ++i) {
2388 if (!elements->get(i)->IsTheHole()) { 2237 if (!elements->get(i)->IsTheHole()) {
2389 SetElementReference(js_obj, entry, i, elements->get(i)); 2238 SetElementReference(js_obj, entry, i, elements->get(i));
2390 } 2239 }
2391 } 2240 }
2392 } else if (js_obj->HasDictionaryElements()) { 2241 } else if (js_obj->HasDictionaryElements()) {
2393 SeededNumberDictionary* dictionary = js_obj->element_dictionary(); 2242 SeededNumberDictionary* dictionary = js_obj->element_dictionary();
2394 int length = dictionary->Capacity(); 2243 int length = dictionary->Capacity();
2395 for (int i = 0; i < length; ++i) { 2244 for (int i = 0; i < length; ++i) {
2396 Object* k = dictionary->KeyAt(i); 2245 Object* k = dictionary->KeyAt(i);
2397 if (dictionary->IsKey(k)) { 2246 if (dictionary->IsKey(k)) {
2398 ASSERT(k->IsNumber()); 2247 ASSERT(k->IsNumber());
2399 uint32_t index = static_cast<uint32_t>(k->Number()); 2248 uint32_t index = static_cast<uint32_t>(k->Number());
2400 SetElementReference(js_obj, entry, index, dictionary->ValueAt(i)); 2249 SetElementReference(js_obj, entry, index, dictionary->ValueAt(i));
2401 } 2250 }
2402 } 2251 }
2403 } 2252 }
2404 } 2253 }
2405 2254
2406 2255
2407 void V8HeapExplorer::ExtractInternalReferences(JSObject* js_obj, 2256 void V8HeapExplorer::ExtractInternalReferences(JSObject* js_obj, int entry) {
2408 HeapEntry* entry) {
2409 int length = js_obj->GetInternalFieldCount(); 2257 int length = js_obj->GetInternalFieldCount();
2410 for (int i = 0; i < length; ++i) { 2258 for (int i = 0; i < length; ++i) {
2411 Object* o = js_obj->GetInternalField(i); 2259 Object* o = js_obj->GetInternalField(i);
2412 SetInternalReference( 2260 SetInternalReference(
2413 js_obj, entry, i, o, js_obj->GetInternalFieldOffset(i)); 2261 js_obj, entry, i, o, js_obj->GetInternalFieldOffset(i));
2414 } 2262 }
2415 } 2263 }
2416 2264
2417 2265
2418 String* V8HeapExplorer::GetConstructorName(JSObject* object) { 2266 String* V8HeapExplorer::GetConstructorName(JSObject* object) {
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
2524 obj = iterator.next(), progress_->ProgressStep()) { 2372 obj = iterator.next(), progress_->ProgressStep()) {
2525 if (!interrupted) { 2373 if (!interrupted) {
2526 ExtractReferences(obj); 2374 ExtractReferences(obj);
2527 if (!progress_->ProgressReport(false)) interrupted = true; 2375 if (!progress_->ProgressReport(false)) interrupted = true;
2528 } 2376 }
2529 } 2377 }
2530 if (interrupted) { 2378 if (interrupted) {
2531 filler_ = NULL; 2379 filler_ = NULL;
2532 return false; 2380 return false;
2533 } 2381 }
2382
2534 SetRootGcRootsReference(); 2383 SetRootGcRootsReference();
2535 RootsReferencesExtractor extractor; 2384 RootsReferencesExtractor extractor;
2536 heap_->IterateRoots(&extractor, VISIT_ONLY_STRONG); 2385 heap_->IterateRoots(&extractor, VISIT_ONLY_STRONG);
2537 extractor.SetCollectingAllReferences(); 2386 extractor.SetCollectingAllReferences();
2538 heap_->IterateRoots(&extractor, VISIT_ALL); 2387 heap_->IterateRoots(&extractor, VISIT_ALL);
2539 extractor.FillReferences(this); 2388 extractor.FillReferences(this);
2540 filler_ = NULL; 2389 filler_ = NULL;
2541 return progress_->ProgressReport(false); 2390 return progress_->ProgressReport(true);
2542 } 2391 }
2543 2392
2544 2393
2545 bool V8HeapExplorer::IterateAndSetObjectNames(SnapshotFillerInterface* filler) { 2394 bool V8HeapExplorer::IterateAndSetObjectNames(SnapshotFillerInterface* filler) {
2546 HeapIterator iterator(HeapIterator::kFilterUnreachable); 2395 HeapIterator iterator(HeapIterator::kFilterUnreachable);
2547 filler_ = filler; 2396 filler_ = filler;
2548 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) { 2397 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
2549 SetObjectName(obj); 2398 SetObjectName(obj);
2550 } 2399 }
2551 return true; 2400 return true;
(...skipping 27 matching lines...) Expand all
2579 && object != heap_->raw_unchecked_fixed_array_map() 2428 && object != heap_->raw_unchecked_fixed_array_map()
2580 && object != heap_->raw_unchecked_global_property_cell_map() 2429 && object != heap_->raw_unchecked_global_property_cell_map()
2581 && object != heap_->raw_unchecked_shared_function_info_map() 2430 && object != heap_->raw_unchecked_shared_function_info_map()
2582 && object != heap_->raw_unchecked_free_space_map() 2431 && object != heap_->raw_unchecked_free_space_map()
2583 && object != heap_->raw_unchecked_one_pointer_filler_map() 2432 && object != heap_->raw_unchecked_one_pointer_filler_map()
2584 && object != heap_->raw_unchecked_two_pointer_filler_map(); 2433 && object != heap_->raw_unchecked_two_pointer_filler_map();
2585 } 2434 }
2586 2435
2587 2436
2588 void V8HeapExplorer::SetClosureReference(HeapObject* parent_obj, 2437 void V8HeapExplorer::SetClosureReference(HeapObject* parent_obj,
2589 HeapEntry* parent_entry, 2438 int parent_entry,
2590 String* reference_name, 2439 String* reference_name,
2591 Object* child_obj) { 2440 Object* child_obj) {
2592 HeapEntry* child_entry = GetEntry(child_obj); 2441 HeapEntry* child_entry = GetEntry(child_obj);
2593 if (child_entry != NULL) { 2442 if (child_entry != NULL) {
2594 filler_->SetNamedReference(HeapGraphEdge::kContextVariable, 2443 filler_->SetNamedReference(HeapGraphEdge::kContextVariable,
2595 parent_obj,
2596 parent_entry, 2444 parent_entry,
2597 collection_->names()->GetName(reference_name), 2445 collection_->names()->GetName(reference_name),
2598 child_obj,
2599 child_entry); 2446 child_entry);
2600 } 2447 }
2601 } 2448 }
2602 2449
2603 2450
2604 void V8HeapExplorer::SetNativeBindReference(HeapObject* parent_obj, 2451 void V8HeapExplorer::SetNativeBindReference(HeapObject* parent_obj,
2605 HeapEntry* parent_entry, 2452 int parent_entry,
2606 const char* reference_name, 2453 const char* reference_name,
2607 Object* child_obj) { 2454 Object* child_obj) {
2608 HeapEntry* child_entry = GetEntry(child_obj); 2455 HeapEntry* child_entry = GetEntry(child_obj);
2609 if (child_entry != NULL) { 2456 if (child_entry != NULL) {
2610 filler_->SetNamedReference(HeapGraphEdge::kShortcut, 2457 filler_->SetNamedReference(HeapGraphEdge::kShortcut,
2611 parent_obj,
2612 parent_entry, 2458 parent_entry,
2613 reference_name, 2459 reference_name,
2614 child_obj,
2615 child_entry); 2460 child_entry);
2616 } 2461 }
2617 } 2462 }
2618 2463
2619 2464
2620 void V8HeapExplorer::SetElementReference(HeapObject* parent_obj, 2465 void V8HeapExplorer::SetElementReference(HeapObject* parent_obj,
2621 HeapEntry* parent_entry, 2466 int parent_entry,
2622 int index, 2467 int index,
2623 Object* child_obj) { 2468 Object* child_obj) {
2624 HeapEntry* child_entry = GetEntry(child_obj); 2469 HeapEntry* child_entry = GetEntry(child_obj);
2625 if (child_entry != NULL) { 2470 if (child_entry != NULL) {
2626 filler_->SetIndexedReference(HeapGraphEdge::kElement, 2471 filler_->SetIndexedReference(HeapGraphEdge::kElement,
2627 parent_obj,
2628 parent_entry, 2472 parent_entry,
2629 index, 2473 index,
2630 child_obj,
2631 child_entry); 2474 child_entry);
2632 } 2475 }
2633 } 2476 }
2634 2477
2635 2478
2636 void V8HeapExplorer::SetInternalReference(HeapObject* parent_obj, 2479 void V8HeapExplorer::SetInternalReference(HeapObject* parent_obj,
2637 HeapEntry* parent_entry, 2480 int parent_entry,
2638 const char* reference_name, 2481 const char* reference_name,
2639 Object* child_obj, 2482 Object* child_obj,
2640 int field_offset) { 2483 int field_offset) {
2641 HeapEntry* child_entry = GetEntry(child_obj); 2484 HeapEntry* child_entry = GetEntry(child_obj);
2642 if (child_entry == NULL) return; 2485 if (child_entry == NULL) return;
2643 if (IsEssentialObject(child_obj)) { 2486 if (IsEssentialObject(child_obj)) {
2644 filler_->SetNamedReference(HeapGraphEdge::kInternal, 2487 filler_->SetNamedReference(HeapGraphEdge::kInternal,
2645 parent_obj, parent_entry, 2488 parent_entry,
2646 reference_name, 2489 reference_name,
2647 child_obj, child_entry); 2490 child_entry);
2648 } 2491 }
2649 IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset); 2492 IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset);
2650 } 2493 }
2651 2494
2652 2495
2653 void V8HeapExplorer::SetInternalReference(HeapObject* parent_obj, 2496 void V8HeapExplorer::SetInternalReference(HeapObject* parent_obj,
2654 HeapEntry* parent_entry, 2497 int parent_entry,
2655 int index, 2498 int index,
2656 Object* child_obj, 2499 Object* child_obj,
2657 int field_offset) { 2500 int field_offset) {
2658 HeapEntry* child_entry = GetEntry(child_obj); 2501 HeapEntry* child_entry = GetEntry(child_obj);
2659 if (child_entry == NULL) return; 2502 if (child_entry == NULL) return;
2660 if (IsEssentialObject(child_obj)) { 2503 if (IsEssentialObject(child_obj)) {
2661 filler_->SetNamedReference(HeapGraphEdge::kInternal, 2504 filler_->SetNamedReference(HeapGraphEdge::kInternal,
2662 parent_obj, parent_entry, 2505 parent_entry,
2663 collection_->names()->GetName(index), 2506 collection_->names()->GetName(index),
2664 child_obj, child_entry); 2507 child_entry);
2665 } 2508 }
2666 IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset); 2509 IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset);
2667 } 2510 }
2668 2511
2669 2512
2670 void V8HeapExplorer::SetHiddenReference(HeapObject* parent_obj, 2513 void V8HeapExplorer::SetHiddenReference(HeapObject* parent_obj,
2671 HeapEntry* parent_entry, 2514 int parent_entry,
2672 int index, 2515 int index,
2673 Object* child_obj) { 2516 Object* child_obj) {
2674 HeapEntry* child_entry = GetEntry(child_obj); 2517 HeapEntry* child_entry = GetEntry(child_obj);
2675 if (child_entry != NULL && IsEssentialObject(child_obj)) { 2518 if (child_entry != NULL && IsEssentialObject(child_obj)) {
2676 filler_->SetIndexedReference(HeapGraphEdge::kHidden, 2519 filler_->SetIndexedReference(HeapGraphEdge::kHidden,
2677 parent_obj,
2678 parent_entry, 2520 parent_entry,
2679 index, 2521 index,
2680 child_obj,
2681 child_entry); 2522 child_entry);
2682 } 2523 }
2683 } 2524 }
2684 2525
2685 2526
2686 void V8HeapExplorer::SetWeakReference(HeapObject* parent_obj, 2527 void V8HeapExplorer::SetWeakReference(HeapObject* parent_obj,
2687 HeapEntry* parent_entry, 2528 int parent_entry,
2688 int index, 2529 int index,
2689 Object* child_obj, 2530 Object* child_obj,
2690 int field_offset) { 2531 int field_offset) {
2691 HeapEntry* child_entry = GetEntry(child_obj); 2532 HeapEntry* child_entry = GetEntry(child_obj);
2692 if (child_entry != NULL) { 2533 if (child_entry != NULL) {
2693 filler_->SetIndexedReference(HeapGraphEdge::kWeak, 2534 filler_->SetIndexedReference(HeapGraphEdge::kWeak,
2694 parent_obj,
2695 parent_entry, 2535 parent_entry,
2696 index, 2536 index,
2697 child_obj,
2698 child_entry); 2537 child_entry);
2699 IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset); 2538 IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset);
2700 } 2539 }
2701 } 2540 }
2702 2541
2703 2542
2704 void V8HeapExplorer::SetPropertyReference(HeapObject* parent_obj, 2543 void V8HeapExplorer::SetPropertyReference(HeapObject* parent_obj,
2705 HeapEntry* parent_entry, 2544 int parent_entry,
2706 String* reference_name, 2545 String* reference_name,
2707 Object* child_obj, 2546 Object* child_obj,
2708 const char* name_format_string, 2547 const char* name_format_string,
2709 int field_offset) { 2548 int field_offset) {
2710 HeapEntry* child_entry = GetEntry(child_obj); 2549 HeapEntry* child_entry = GetEntry(child_obj);
2711 if (child_entry != NULL) { 2550 if (child_entry != NULL) {
2712 HeapGraphEdge::Type type = reference_name->length() > 0 ? 2551 HeapGraphEdge::Type type = reference_name->length() > 0 ?
2713 HeapGraphEdge::kProperty : HeapGraphEdge::kInternal; 2552 HeapGraphEdge::kProperty : HeapGraphEdge::kInternal;
2714 const char* name = name_format_string != NULL ? 2553 const char* name = name_format_string != NULL ?
2715 collection_->names()->GetFormatted( 2554 collection_->names()->GetFormatted(
2716 name_format_string, 2555 name_format_string,
2717 *reference_name->ToCString(DISALLOW_NULLS, 2556 *reference_name->ToCString(DISALLOW_NULLS,
2718 ROBUST_STRING_TRAVERSAL)) : 2557 ROBUST_STRING_TRAVERSAL)) :
2719 collection_->names()->GetName(reference_name); 2558 collection_->names()->GetName(reference_name);
2720 2559
2721 filler_->SetNamedReference(type, 2560 filler_->SetNamedReference(type,
2722 parent_obj,
2723 parent_entry, 2561 parent_entry,
2724 name, 2562 name,
2725 child_obj,
2726 child_entry); 2563 child_entry);
2727 IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset); 2564 IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset);
2728 } 2565 }
2729 } 2566 }
2730 2567
2731 2568
2732 void V8HeapExplorer::SetPropertyShortcutReference(HeapObject* parent_obj, 2569 void V8HeapExplorer::SetPropertyShortcutReference(HeapObject* parent_obj,
2733 HeapEntry* parent_entry, 2570 int parent_entry,
2734 String* reference_name, 2571 String* reference_name,
2735 Object* child_obj) { 2572 Object* child_obj) {
2736 HeapEntry* child_entry = GetEntry(child_obj); 2573 HeapEntry* child_entry = GetEntry(child_obj);
2737 if (child_entry != NULL) { 2574 if (child_entry != NULL) {
2738 filler_->SetNamedReference(HeapGraphEdge::kShortcut, 2575 filler_->SetNamedReference(HeapGraphEdge::kShortcut,
2739 parent_obj,
2740 parent_entry, 2576 parent_entry,
2741 collection_->names()->GetName(reference_name), 2577 collection_->names()->GetName(reference_name),
2742 child_obj,
2743 child_entry); 2578 child_entry);
2744 } 2579 }
2745 } 2580 }
2746 2581
2747 2582
2748 void V8HeapExplorer::SetRootGcRootsReference() { 2583 void V8HeapExplorer::SetRootGcRootsReference() {
2749 filler_->SetIndexedAutoIndexReference( 2584 filler_->SetIndexedAutoIndexReference(
2750 HeapGraphEdge::kElement, 2585 HeapGraphEdge::kElement,
2751 kInternalRootObject, snapshot_->root(), 2586 snapshot_->root()->index(),
2752 kGcRootsObject, snapshot_->gc_roots()); 2587 snapshot_->gc_roots());
2753 } 2588 }
2754 2589
2755 2590
2756 void V8HeapExplorer::SetUserGlobalReference(Object* child_obj) { 2591 void V8HeapExplorer::SetUserGlobalReference(Object* child_obj) {
2757 HeapEntry* child_entry = GetEntry(child_obj); 2592 HeapEntry* child_entry = GetEntry(child_obj);
2758 ASSERT(child_entry != NULL); 2593 ASSERT(child_entry != NULL);
2759 filler_->SetNamedAutoIndexReference( 2594 filler_->SetNamedAutoIndexReference(
2760 HeapGraphEdge::kShortcut, 2595 HeapGraphEdge::kShortcut,
2761 kInternalRootObject, snapshot_->root(), 2596 snapshot_->root()->index(),
2762 child_obj, child_entry); 2597 child_entry);
2763 } 2598 }
2764 2599
2765 2600
2766 void V8HeapExplorer::SetGcRootsReference(VisitorSynchronization::SyncTag tag) { 2601 void V8HeapExplorer::SetGcRootsReference(VisitorSynchronization::SyncTag tag) {
2767 filler_->SetIndexedAutoIndexReference( 2602 filler_->SetIndexedAutoIndexReference(
2768 HeapGraphEdge::kElement, 2603 HeapGraphEdge::kElement,
2769 kGcRootsObject, snapshot_->gc_roots(), 2604 snapshot_->gc_roots()->index(),
2770 GetNthGcSubrootObject(tag), snapshot_->gc_subroot(tag)); 2605 snapshot_->gc_subroot(tag));
2771 } 2606 }
2772 2607
2773 2608
2774 void V8HeapExplorer::SetGcSubrootReference( 2609 void V8HeapExplorer::SetGcSubrootReference(
2775 VisitorSynchronization::SyncTag tag, bool is_weak, Object* child_obj) { 2610 VisitorSynchronization::SyncTag tag, bool is_weak, Object* child_obj) {
2776 HeapEntry* child_entry = GetEntry(child_obj); 2611 HeapEntry* child_entry = GetEntry(child_obj);
2777 if (child_entry != NULL) { 2612 if (child_entry != NULL) {
2778 const char* name = GetStrongGcSubrootName(child_obj); 2613 const char* name = GetStrongGcSubrootName(child_obj);
2779 if (name != NULL) { 2614 if (name != NULL) {
2780 filler_->SetNamedReference( 2615 filler_->SetNamedReference(
2781 HeapGraphEdge::kInternal, 2616 HeapGraphEdge::kInternal,
2782 GetNthGcSubrootObject(tag), snapshot_->gc_subroot(tag), 2617 snapshot_->gc_subroot(tag)->index(),
2783 name, 2618 name,
2784 child_obj, child_entry); 2619 child_entry);
2785 } else { 2620 } else {
2786 filler_->SetIndexedAutoIndexReference( 2621 filler_->SetIndexedAutoIndexReference(
2787 is_weak ? HeapGraphEdge::kWeak : HeapGraphEdge::kElement, 2622 is_weak ? HeapGraphEdge::kWeak : HeapGraphEdge::kElement,
2788 GetNthGcSubrootObject(tag), snapshot_->gc_subroot(tag), 2623 snapshot_->gc_subroot(tag)->index(),
2789 child_obj, child_entry); 2624 child_entry);
2790 } 2625 }
2791 } 2626 }
2792 } 2627 }
2793 2628
2794 2629
2795 const char* V8HeapExplorer::GetStrongGcSubrootName(Object* object) { 2630 const char* V8HeapExplorer::GetStrongGcSubrootName(Object* object) {
2796 if (strong_gc_subroot_names_.is_empty()) { 2631 if (strong_gc_subroot_names_.is_empty()) {
2797 #define NAME_ENTRY(name) strong_gc_subroot_names_.SetTag(heap_->name(), #name); 2632 #define NAME_ENTRY(name) strong_gc_subroot_names_.SetTag(heap_->name(), #name);
2798 #define ROOT_NAME(type, name, camel_name) NAME_ENTRY(name) 2633 #define ROOT_NAME(type, name, camel_name) NAME_ENTRY(name)
2799 STRONG_ROOT_LIST(ROOT_NAME) 2634 STRONG_ROOT_LIST(ROOT_NAME)
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
2896 2731
2897 class BasicHeapEntriesAllocator : public HeapEntriesAllocator { 2732 class BasicHeapEntriesAllocator : public HeapEntriesAllocator {
2898 public: 2733 public:
2899 BasicHeapEntriesAllocator( 2734 BasicHeapEntriesAllocator(
2900 HeapSnapshot* snapshot, 2735 HeapSnapshot* snapshot,
2901 HeapEntry::Type entries_type) 2736 HeapEntry::Type entries_type)
2902 : snapshot_(snapshot), 2737 : snapshot_(snapshot),
2903 collection_(snapshot_->collection()), 2738 collection_(snapshot_->collection()),
2904 entries_type_(entries_type) { 2739 entries_type_(entries_type) {
2905 } 2740 }
2906 virtual HeapEntry* AllocateEntry( 2741 virtual HeapEntry* AllocateEntry(HeapThing ptr);
2907 HeapThing ptr, int children_count, int retainers_count);
2908 private: 2742 private:
2909 HeapSnapshot* snapshot_; 2743 HeapSnapshot* snapshot_;
2910 HeapSnapshotsCollection* collection_; 2744 HeapSnapshotsCollection* collection_;
2911 HeapEntry::Type entries_type_; 2745 HeapEntry::Type entries_type_;
2912 }; 2746 };
2913 2747
2914 2748
2915 HeapEntry* BasicHeapEntriesAllocator::AllocateEntry( 2749 HeapEntry* BasicHeapEntriesAllocator::AllocateEntry(HeapThing ptr) {
2916 HeapThing ptr, int children_count, int retainers_count) {
2917 v8::RetainedObjectInfo* info = reinterpret_cast<v8::RetainedObjectInfo*>(ptr); 2750 v8::RetainedObjectInfo* info = reinterpret_cast<v8::RetainedObjectInfo*>(ptr);
2918 intptr_t elements = info->GetElementCount(); 2751 intptr_t elements = info->GetElementCount();
2919 intptr_t size = info->GetSizeInBytes(); 2752 intptr_t size = info->GetSizeInBytes();
2753 const char* name = elements != -1
2754 ? collection_->names()->GetFormatted(
2755 "%s / %" V8_PTR_PREFIX "d entries", info->GetLabel(), elements)
2756 : collection_->names()->GetCopy(info->GetLabel());
2920 return snapshot_->AddEntry( 2757 return snapshot_->AddEntry(
2921 entries_type_, 2758 entries_type_,
2922 elements != -1 ? 2759 name,
2923 collection_->names()->GetFormatted(
2924 "%s / %" V8_PTR_PREFIX "d entries",
2925 info->GetLabel(),
2926 info->GetElementCount()) :
2927 collection_->names()->GetCopy(info->GetLabel()),
2928 HeapObjectsMap::GenerateId(info), 2760 HeapObjectsMap::GenerateId(info),
2929 size != -1 ? static_cast<int>(size) : 0, 2761 size != -1 ? static_cast<int>(size) : 0);
2930 children_count,
2931 retainers_count);
2932 } 2762 }
2933 2763
2934 2764
2935 NativeObjectsExplorer::NativeObjectsExplorer( 2765 NativeObjectsExplorer::NativeObjectsExplorer(
2936 HeapSnapshot* snapshot, SnapshottingProgressReportingInterface* progress) 2766 HeapSnapshot* snapshot, SnapshottingProgressReportingInterface* progress)
2937 : snapshot_(snapshot), 2767 : snapshot_(snapshot),
2938 collection_(snapshot_->collection()), 2768 collection_(snapshot_->collection()),
2939 progress_(progress), 2769 progress_(progress),
2940 embedder_queried_(false), 2770 embedder_queried_(false),
2941 objects_by_info_(RetainedInfosMatch), 2771 objects_by_info_(RetainedInfosMatch),
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
3002 embedder_queried_ = true; 2832 embedder_queried_ = true;
3003 } 2833 }
3004 2834
3005 void NativeObjectsExplorer::FillImplicitReferences() { 2835 void NativeObjectsExplorer::FillImplicitReferences() {
3006 Isolate* isolate = Isolate::Current(); 2836 Isolate* isolate = Isolate::Current();
3007 List<ImplicitRefGroup*>* groups = 2837 List<ImplicitRefGroup*>* groups =
3008 isolate->global_handles()->implicit_ref_groups(); 2838 isolate->global_handles()->implicit_ref_groups();
3009 for (int i = 0; i < groups->length(); ++i) { 2839 for (int i = 0; i < groups->length(); ++i) {
3010 ImplicitRefGroup* group = groups->at(i); 2840 ImplicitRefGroup* group = groups->at(i);
3011 HeapObject* parent = *group->parent_; 2841 HeapObject* parent = *group->parent_;
3012 HeapEntry* parent_entry = 2842 int parent_entry =
3013 filler_->FindOrAddEntry(parent, native_entries_allocator_); 2843 filler_->FindOrAddEntry(parent, native_entries_allocator_)->index();
3014 ASSERT(parent_entry != NULL); 2844 ASSERT(parent_entry != HeapEntry::kNoEntry);
3015 Object*** children = group->children_; 2845 Object*** children = group->children_;
3016 for (size_t j = 0; j < group->length_; ++j) { 2846 for (size_t j = 0; j < group->length_; ++j) {
3017 Object* child = *children[j]; 2847 Object* child = *children[j];
3018 HeapEntry* child_entry = 2848 HeapEntry* child_entry =
3019 filler_->FindOrAddEntry(child, native_entries_allocator_); 2849 filler_->FindOrAddEntry(child, native_entries_allocator_);
3020 filler_->SetNamedReference( 2850 filler_->SetNamedReference(
3021 HeapGraphEdge::kInternal, 2851 HeapGraphEdge::kInternal,
3022 parent, parent_entry, 2852 parent_entry,
3023 "native", 2853 "native",
3024 child, child_entry); 2854 child_entry);
3025 } 2855 }
3026 } 2856 }
3027 } 2857 }
3028 2858
3029 List<HeapObject*>* NativeObjectsExplorer::GetListMaybeDisposeInfo( 2859 List<HeapObject*>* NativeObjectsExplorer::GetListMaybeDisposeInfo(
3030 v8::RetainedObjectInfo* info) { 2860 v8::RetainedObjectInfo* info) {
3031 HashMap::Entry* entry = 2861 HashMap::Entry* entry =
3032 objects_by_info_.Lookup(info, InfoHash(info), true); 2862 objects_by_info_.Lookup(info, InfoHash(info), true);
3033 if (entry->value != NULL) { 2863 if (entry->value != NULL) {
3034 info->Dispose(); 2864 info->Dispose();
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
3092 2922
3093 2923
3094 NativeGroupRetainedObjectInfo* NativeObjectsExplorer::FindOrAddGroupInfo( 2924 NativeGroupRetainedObjectInfo* NativeObjectsExplorer::FindOrAddGroupInfo(
3095 const char* label) { 2925 const char* label) {
3096 const char* label_copy = collection_->names()->GetCopy(label); 2926 const char* label_copy = collection_->names()->GetCopy(label);
3097 uint32_t hash = HashSequentialString(label_copy, 2927 uint32_t hash = HashSequentialString(label_copy,
3098 static_cast<int>(strlen(label_copy)), 2928 static_cast<int>(strlen(label_copy)),
3099 HEAP->HashSeed()); 2929 HEAP->HashSeed());
3100 HashMap::Entry* entry = native_groups_.Lookup(const_cast<char*>(label_copy), 2930 HashMap::Entry* entry = native_groups_.Lookup(const_cast<char*>(label_copy),
3101 hash, true); 2931 hash, true);
3102 if (entry->value == NULL) 2932 if (entry->value == NULL) {
3103 entry->value = new NativeGroupRetainedObjectInfo(label); 2933 entry->value = new NativeGroupRetainedObjectInfo(label);
2934 }
3104 return static_cast<NativeGroupRetainedObjectInfo*>(entry->value); 2935 return static_cast<NativeGroupRetainedObjectInfo*>(entry->value);
3105 } 2936 }
3106 2937
3107 2938
3108 void NativeObjectsExplorer::SetNativeRootReference( 2939 void NativeObjectsExplorer::SetNativeRootReference(
3109 v8::RetainedObjectInfo* info) { 2940 v8::RetainedObjectInfo* info) {
3110 HeapEntry* child_entry = 2941 HeapEntry* child_entry =
3111 filler_->FindOrAddEntry(info, native_entries_allocator_); 2942 filler_->FindOrAddEntry(info, native_entries_allocator_);
3112 ASSERT(child_entry != NULL); 2943 ASSERT(child_entry != NULL);
3113 NativeGroupRetainedObjectInfo* group_info = 2944 NativeGroupRetainedObjectInfo* group_info =
3114 FindOrAddGroupInfo(info->GetGroupLabel()); 2945 FindOrAddGroupInfo(info->GetGroupLabel());
3115 HeapEntry* group_entry = 2946 HeapEntry* group_entry =
3116 filler_->FindOrAddEntry(group_info, synthetic_entries_allocator_); 2947 filler_->FindOrAddEntry(group_info, synthetic_entries_allocator_);
3117 filler_->SetNamedAutoIndexReference( 2948 filler_->SetNamedAutoIndexReference(
3118 HeapGraphEdge::kInternal, 2949 HeapGraphEdge::kInternal,
3119 group_info, group_entry, 2950 group_entry->index(),
3120 info, child_entry); 2951 child_entry);
3121 } 2952 }
3122 2953
3123 2954
3124 void NativeObjectsExplorer::SetWrapperNativeReferences( 2955 void NativeObjectsExplorer::SetWrapperNativeReferences(
3125 HeapObject* wrapper, v8::RetainedObjectInfo* info) { 2956 HeapObject* wrapper, v8::RetainedObjectInfo* info) {
3126 HeapEntry* wrapper_entry = filler_->FindEntry(wrapper); 2957 HeapEntry* wrapper_entry = filler_->FindEntry(wrapper);
3127 ASSERT(wrapper_entry != NULL); 2958 ASSERT(wrapper_entry != NULL);
3128 HeapEntry* info_entry = 2959 HeapEntry* info_entry =
3129 filler_->FindOrAddEntry(info, native_entries_allocator_); 2960 filler_->FindOrAddEntry(info, native_entries_allocator_);
3130 ASSERT(info_entry != NULL); 2961 ASSERT(info_entry != NULL);
3131 filler_->SetNamedReference(HeapGraphEdge::kInternal, 2962 filler_->SetNamedReference(HeapGraphEdge::kInternal,
3132 wrapper, wrapper_entry, 2963 wrapper_entry->index(),
3133 "native", 2964 "native",
3134 info, info_entry); 2965 info_entry);
3135 filler_->SetIndexedAutoIndexReference(HeapGraphEdge::kElement, 2966 filler_->SetIndexedAutoIndexReference(HeapGraphEdge::kElement,
3136 info, info_entry, 2967 info_entry->index(),
3137 wrapper, wrapper_entry); 2968 wrapper_entry);
3138 } 2969 }
3139 2970
3140 2971
3141 void NativeObjectsExplorer::SetRootNativeRootsReference() { 2972 void NativeObjectsExplorer::SetRootNativeRootsReference() {
3142 for (HashMap::Entry* entry = native_groups_.Start(); 2973 for (HashMap::Entry* entry = native_groups_.Start();
3143 entry; 2974 entry;
3144 entry = native_groups_.Next(entry)) { 2975 entry = native_groups_.Next(entry)) {
3145 NativeGroupRetainedObjectInfo* group_info = 2976 NativeGroupRetainedObjectInfo* group_info =
3146 static_cast<NativeGroupRetainedObjectInfo*>(entry->value); 2977 static_cast<NativeGroupRetainedObjectInfo*>(entry->value);
3147 HeapEntry* group_entry = 2978 HeapEntry* group_entry =
3148 filler_->FindOrAddEntry(group_info, native_entries_allocator_); 2979 filler_->FindOrAddEntry(group_info, native_entries_allocator_);
3149 ASSERT(group_entry != NULL); 2980 ASSERT(group_entry != NULL);
3150 filler_->SetIndexedAutoIndexReference( 2981 filler_->SetIndexedAutoIndexReference(
3151 HeapGraphEdge::kElement, 2982 HeapGraphEdge::kElement,
3152 V8HeapExplorer::kInternalRootObject, snapshot_->root(), 2983 snapshot_->root()->index(),
3153 group_info, group_entry); 2984 group_entry);
3154 } 2985 }
3155 } 2986 }
3156 2987
3157 2988
3158 void NativeObjectsExplorer::VisitSubtreeWrapper(Object** p, uint16_t class_id) { 2989 void NativeObjectsExplorer::VisitSubtreeWrapper(Object** p, uint16_t class_id) {
3159 if (in_groups_.Contains(*p)) return; 2990 if (in_groups_.Contains(*p)) return;
3160 Isolate* isolate = Isolate::Current(); 2991 Isolate* isolate = Isolate::Current();
3161 v8::RetainedObjectInfo* info = 2992 v8::RetainedObjectInfo* info =
3162 isolate->heap_profiler()->ExecuteWrapperClassCallback(class_id, p); 2993 isolate->heap_profiler()->ExecuteWrapperClassCallback(class_id, p);
3163 if (info == NULL) return; 2994 if (info == NULL) return;
3164 GetListMaybeDisposeInfo(info)->Add(HeapObject::cast(*p)); 2995 GetListMaybeDisposeInfo(info)->Add(HeapObject::cast(*p));
3165 } 2996 }
3166 2997
3167 2998
3168 class SnapshotCounter : public SnapshotFillerInterface {
3169 public:
3170 explicit SnapshotCounter(HeapEntriesMap* entries) : entries_(entries) { }
3171 HeapEntry* AddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) {
3172 entries_->Pair(ptr, allocator, HeapEntriesMap::kHeapEntryPlaceholder);
3173 return HeapEntriesMap::kHeapEntryPlaceholder;
3174 }
3175 HeapEntry* FindEntry(HeapThing ptr) {
3176 return entries_->Map(ptr);
3177 }
3178 HeapEntry* FindOrAddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) {
3179 HeapEntry* entry = FindEntry(ptr);
3180 return entry != NULL ? entry : AddEntry(ptr, allocator);
3181 }
3182 void SetIndexedReference(HeapGraphEdge::Type,
3183 HeapThing parent_ptr,
3184 HeapEntry*,
3185 int,
3186 HeapThing child_ptr,
3187 HeapEntry*) {
3188 entries_->CountReference(parent_ptr, child_ptr);
3189 }
3190 void SetIndexedAutoIndexReference(HeapGraphEdge::Type,
3191 HeapThing parent_ptr,
3192 HeapEntry*,
3193 HeapThing child_ptr,
3194 HeapEntry*) {
3195 entries_->CountReference(parent_ptr, child_ptr);
3196 }
3197 void SetNamedReference(HeapGraphEdge::Type,
3198 HeapThing parent_ptr,
3199 HeapEntry*,
3200 const char*,
3201 HeapThing child_ptr,
3202 HeapEntry*) {
3203 entries_->CountReference(parent_ptr, child_ptr);
3204 }
3205 void SetNamedAutoIndexReference(HeapGraphEdge::Type,
3206 HeapThing parent_ptr,
3207 HeapEntry*,
3208 HeapThing child_ptr,
3209 HeapEntry*) {
3210 entries_->CountReference(parent_ptr, child_ptr);
3211 }
3212
3213 private:
3214 HeapEntriesMap* entries_;
3215 };
3216
3217
3218 class SnapshotFiller : public SnapshotFillerInterface { 2999 class SnapshotFiller : public SnapshotFillerInterface {
3219 public: 3000 public:
3220 explicit SnapshotFiller(HeapSnapshot* snapshot, HeapEntriesMap* entries) 3001 explicit SnapshotFiller(HeapSnapshot* snapshot, HeapEntriesMap* entries)
3221 : snapshot_(snapshot), 3002 : snapshot_(snapshot),
3222 collection_(snapshot->collection()), 3003 collection_(snapshot->collection()),
3223 entries_(entries) { } 3004 entries_(entries) { }
3224 HeapEntry* AddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) { 3005 HeapEntry* AddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) {
3225 UNREACHABLE(); 3006 HeapEntry* entry = allocator->AllocateEntry(ptr);
3226 return NULL; 3007 entries_->Pair(ptr, entry->index());
3008 return entry;
3227 } 3009 }
3228 HeapEntry* FindEntry(HeapThing ptr) { 3010 HeapEntry* FindEntry(HeapThing ptr) {
3229 return entries_->Map(ptr); 3011 int index = entries_->Map(ptr);
3012 return index != HeapEntry::kNoEntry ? &snapshot_->entries()[index] : NULL;
3230 } 3013 }
3231 HeapEntry* FindOrAddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) { 3014 HeapEntry* FindOrAddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) {
3232 HeapEntry* entry = FindEntry(ptr); 3015 HeapEntry* entry = FindEntry(ptr);
3233 return entry != NULL ? entry : AddEntry(ptr, allocator); 3016 return entry != NULL ? entry : AddEntry(ptr, allocator);
3234 } 3017 }
3235 void SetIndexedReference(HeapGraphEdge::Type type, 3018 void SetIndexedReference(HeapGraphEdge::Type type,
3236 HeapThing parent_ptr, 3019 int parent,
3237 HeapEntry* parent_entry,
3238 int index, 3020 int index,
3239 HeapThing child_ptr,
3240 HeapEntry* child_entry) { 3021 HeapEntry* child_entry) {
3241 int child_index, retainer_index; 3022 HeapEntry* parent_entry = &snapshot_->entries()[parent];
3242 entries_->CountReference( 3023 parent_entry->SetIndexedReference(type, index, child_entry);
3243 parent_ptr, child_ptr, &child_index, &retainer_index);
3244 parent_entry->SetIndexedReference(
3245 type, child_index, index, child_entry, retainer_index);
3246 } 3024 }
3247 void SetIndexedAutoIndexReference(HeapGraphEdge::Type type, 3025 void SetIndexedAutoIndexReference(HeapGraphEdge::Type type,
3248 HeapThing parent_ptr, 3026 int parent,
3249 HeapEntry* parent_entry,
3250 HeapThing child_ptr,
3251 HeapEntry* child_entry) { 3027 HeapEntry* child_entry) {
3252 int child_index, retainer_index; 3028 HeapEntry* parent_entry = &snapshot_->entries()[parent];
3253 entries_->CountReference( 3029 int index = parent_entry->children_count() + 1;
3254 parent_ptr, child_ptr, &child_index, &retainer_index); 3030 parent_entry->SetIndexedReference(type, index, child_entry);
3255 parent_entry->SetIndexedReference(
3256 type, child_index, child_index + 1, child_entry, retainer_index);
3257 } 3031 }
3258 void SetNamedReference(HeapGraphEdge::Type type, 3032 void SetNamedReference(HeapGraphEdge::Type type,
3259 HeapThing parent_ptr, 3033 int parent,
3260 HeapEntry* parent_entry,
3261 const char* reference_name, 3034 const char* reference_name,
3262 HeapThing child_ptr,
3263 HeapEntry* child_entry) { 3035 HeapEntry* child_entry) {
3264 int child_index, retainer_index; 3036 HeapEntry* parent_entry = &snapshot_->entries()[parent];
3265 entries_->CountReference( 3037 parent_entry->SetNamedReference(type, reference_name, child_entry);
3266 parent_ptr, child_ptr, &child_index, &retainer_index);
3267 parent_entry->SetNamedReference(
3268 type, child_index, reference_name, child_entry, retainer_index);
3269 } 3038 }
3270 void SetNamedAutoIndexReference(HeapGraphEdge::Type type, 3039 void SetNamedAutoIndexReference(HeapGraphEdge::Type type,
3271 HeapThing parent_ptr, 3040 int parent,
3272 HeapEntry* parent_entry,
3273 HeapThing child_ptr,
3274 HeapEntry* child_entry) { 3041 HeapEntry* child_entry) {
3275 int child_index, retainer_index; 3042 HeapEntry* parent_entry = &snapshot_->entries()[parent];
3276 entries_->CountReference( 3043 int index = parent_entry->children_count() + 1;
3277 parent_ptr, child_ptr, &child_index, &retainer_index); 3044 parent_entry->SetNamedReference(
3278 parent_entry->SetNamedReference(type, 3045 type,
3279 child_index, 3046 collection_->names()->GetName(index),
3280 collection_->names()->GetName(child_index + 1), 3047 child_entry);
3281 child_entry,
3282 retainer_index);
3283 } 3048 }
3284 3049
3285 private: 3050 private:
3286 HeapSnapshot* snapshot_; 3051 HeapSnapshot* snapshot_;
3287 HeapSnapshotsCollection* collection_; 3052 HeapSnapshotsCollection* collection_;
3288 HeapEntriesMap* entries_; 3053 HeapEntriesMap* entries_;
3289 }; 3054 };
3290 3055
3291 3056
3292 HeapSnapshotGenerator::HeapSnapshotGenerator(HeapSnapshot* snapshot, 3057 HeapSnapshotGenerator::HeapSnapshotGenerator(HeapSnapshot* snapshot,
(...skipping 29 matching lines...) Expand all
3322 #endif 3087 #endif
3323 3088
3324 // The following code uses heap iterators, so we want the heap to be 3089 // The following code uses heap iterators, so we want the heap to be
3325 // stable. It should follow TagGlobalObjects as that can allocate. 3090 // stable. It should follow TagGlobalObjects as that can allocate.
3326 AssertNoAllocation no_alloc; 3091 AssertNoAllocation no_alloc;
3327 3092
3328 #ifdef DEBUG 3093 #ifdef DEBUG
3329 debug_heap->Verify(); 3094 debug_heap->Verify();
3330 #endif 3095 #endif
3331 3096
3332 SetProgressTotal(2); // 2 passes. 3097 SetProgressTotal(1); // 1 pass.
3333 3098
3334 #ifdef DEBUG 3099 #ifdef DEBUG
3335 debug_heap->Verify(); 3100 debug_heap->Verify();
3336 #endif 3101 #endif
3337 3102
3338 // Pass 1. Iterate heap contents to count entries and references.
3339 if (!CountEntriesAndReferences()) return false;
3340
3341 #ifdef DEBUG
3342 debug_heap->Verify();
3343 #endif
3344
3345 // Allocate memory for entries and references.
3346 snapshot_->AllocateEntries(entries_.entries_count(),
3347 entries_.total_children_count(),
3348 entries_.total_retainers_count());
3349
3350 // Allocate heap objects to entries hash map.
3351 entries_.AllocateEntries(V8HeapExplorer::kInternalRootObject);
3352
3353 // Pass 2. Fill references.
3354 if (!FillReferences()) return false; 3103 if (!FillReferences()) return false;
3355 3104
3105 snapshot_->FillChildrenAndRetainers();
3356 snapshot_->RememberLastJSObjectId(); 3106 snapshot_->RememberLastJSObjectId();
3357 3107
3358 if (!SetEntriesDominators()) return false; 3108 if (!SetEntriesDominators()) return false;
3359 if (!CalculateRetainedSizes()) return false; 3109 if (!CalculateRetainedSizes()) return false;
3360 3110
3361 progress_counter_ = progress_total_; 3111 progress_counter_ = progress_total_;
3362 if (!ProgressReport(true)) return false; 3112 if (!ProgressReport(true)) return false;
3363 return true; 3113 return true;
3364 } 3114 }
3365 3115
(...skipping 11 matching lines...) Expand all
3377 control_->ReportProgressValue(progress_counter_, progress_total_) == 3127 control_->ReportProgressValue(progress_counter_, progress_total_) ==
3378 v8::ActivityControl::kContinue; 3128 v8::ActivityControl::kContinue;
3379 } 3129 }
3380 return true; 3130 return true;
3381 } 3131 }
3382 3132
3383 3133
3384 void HeapSnapshotGenerator::SetProgressTotal(int iterations_count) { 3134 void HeapSnapshotGenerator::SetProgressTotal(int iterations_count) {
3385 if (control_ == NULL) return; 3135 if (control_ == NULL) return;
3386 HeapIterator iterator(HeapIterator::kFilterUnreachable); 3136 HeapIterator iterator(HeapIterator::kFilterUnreachable);
3387 progress_total_ = ( 3137 progress_total_ = iterations_count * (
3388 v8_heap_explorer_.EstimateObjectsCount(&iterator) + 3138 v8_heap_explorer_.EstimateObjectsCount(&iterator) +
3389 dom_explorer_.EstimateObjectsCount()) * iterations_count; 3139 dom_explorer_.EstimateObjectsCount());
3390 progress_counter_ = 0; 3140 progress_counter_ = 0;
3391 } 3141 }
3392 3142
3393 3143
3394 bool HeapSnapshotGenerator::CountEntriesAndReferences() {
3395 SnapshotCounter counter(&entries_);
3396 v8_heap_explorer_.AddRootEntries(&counter);
3397 return v8_heap_explorer_.IterateAndExtractReferences(&counter)
3398 && dom_explorer_.IterateAndExtractReferences(&counter);
3399 }
3400
3401
3402 bool HeapSnapshotGenerator::FillReferences() { 3144 bool HeapSnapshotGenerator::FillReferences() {
3403 SnapshotFiller filler(snapshot_, &entries_); 3145 SnapshotFiller filler(snapshot_, &entries_);
3146 v8_heap_explorer_.AddRootEntries(&filler);
3404 // IterateAndExtractReferences cannot set object names because 3147 // IterateAndExtractReferences cannot set object names because
3405 // it makes call to JSObject::LocalLookupRealNamedProperty which 3148 // it makes call to JSObject::LocalLookupRealNamedProperty which
3406 // in turn may relocate objects in property maps thus changing the heap 3149 // in turn may relocate objects in property maps thus changing the heap
3407 // layout and affecting retainer counts. This is not acceptable because 3150 // layout and affecting retainer counts. This is not acceptable because
3408 // number of retainers must not change between count and fill passes. 3151 // number of retainers must not change between count and fill passes.
3409 // To avoid this there's a separate postpass that set object names. 3152 // To avoid this there's a separate postpass that set object names.
3410 return v8_heap_explorer_.IterateAndExtractReferences(&filler) 3153 return v8_heap_explorer_.IterateAndExtractReferences(&filler)
3411 && dom_explorer_.IterateAndExtractReferences(&filler) 3154 && dom_explorer_.IterateAndExtractReferences(&filler)
3412 && v8_heap_explorer_.IterateAndSetObjectNames(&filler); 3155 && v8_heap_explorer_.IterateAndSetObjectNames(&filler);
3413 } 3156 }
3414 3157
3415 3158
3416 bool HeapSnapshotGenerator::IsUserGlobalReference(const HeapGraphEdge& edge) { 3159 bool HeapSnapshotGenerator::IsUserGlobalReference(const HeapGraphEdge* edge) {
3417 ASSERT(edge.from() == snapshot_->root()); 3160 ASSERT(edge->from() == snapshot_->root());
3418 return edge.type() == HeapGraphEdge::kShortcut; 3161 return edge->type() == HeapGraphEdge::kShortcut;
3419 } 3162 }
3420 3163
3421 3164
3422 void HeapSnapshotGenerator::MarkUserReachableObjects() { 3165 void HeapSnapshotGenerator::MarkUserReachableObjects() {
3423 List<HeapEntry*> worklist; 3166 List<HeapEntry*> worklist;
3424 3167
3425 Vector<HeapGraphEdge> children = snapshot_->root()->children(); 3168 Vector<HeapGraphEdge*> children = snapshot_->root()->children();
3426 for (int i = 0; i < children.length(); ++i) { 3169 for (int i = 0; i < children.length(); ++i) {
3427 if (IsUserGlobalReference(children[i])) { 3170 if (IsUserGlobalReference(children[i])) {
3428 worklist.Add(children[i].to()); 3171 worklist.Add(children[i]->to());
3429 } 3172 }
3430 } 3173 }
3431 3174
3432 while (!worklist.is_empty()) { 3175 while (!worklist.is_empty()) {
3433 HeapEntry* entry = worklist.RemoveLast(); 3176 HeapEntry* entry = worklist.RemoveLast();
3434 if (entry->user_reachable()) continue; 3177 if (entry->user_reachable()) continue;
3435 entry->set_user_reachable(); 3178 entry->set_user_reachable();
3436 Vector<HeapGraphEdge> children = entry->children(); 3179 Vector<HeapGraphEdge*> children = entry->children();
3437 for (int i = 0; i < children.length(); ++i) { 3180 for (int i = 0; i < children.length(); ++i) {
3438 HeapEntry* child = children[i].to(); 3181 HeapEntry* child = children[i]->to();
3439 if (!child->user_reachable()) { 3182 if (!child->user_reachable()) {
3440 worklist.Add(child); 3183 worklist.Add(child);
3441 } 3184 }
3442 } 3185 }
3443 } 3186 }
3444 } 3187 }
3445 3188
3446 3189
3447 static bool IsRetainingEdge(HeapGraphEdge* edge) { 3190 static bool IsRetainingEdge(HeapGraphEdge* edge) {
3448 if (edge->type() == HeapGraphEdge::kShortcut) return false; 3191 if (edge->type() == HeapGraphEdge::kShortcut) return false;
3449 // The edge is not retaining if it goes from system domain 3192 // The edge is not retaining if it goes from system domain
3450 // (i.e. an object not reachable from window) to the user domain 3193 // (i.e. an object not reachable from window) to the user domain
3451 // (i.e. a reachable object). 3194 // (i.e. a reachable object).
3452 return edge->from()->user_reachable() 3195 return edge->from()->user_reachable()
3453 || !edge->to()->user_reachable(); 3196 || !edge->to()->user_reachable();
3454 } 3197 }
3455 3198
3456 3199
3457 void HeapSnapshotGenerator::FillPostorderIndexes( 3200 void HeapSnapshotGenerator::FillPostorderIndexes(
3458 Vector<HeapEntry*>* entries) { 3201 Vector<HeapEntry*>* entries) {
3459 snapshot_->ClearPaint(); 3202 snapshot_->ClearPaint();
3460 int current_entry = 0; 3203 int current_entry = 0;
3461 List<HeapEntry*> nodes_to_visit; 3204 List<HeapEntry*> nodes_to_visit;
3462 HeapEntry* root = snapshot_->root(); 3205 HeapEntry* root = snapshot_->root();
3463 nodes_to_visit.Add(root); 3206 nodes_to_visit.Add(root);
3464 snapshot_->root()->paint(); 3207 snapshot_->root()->paint();
3465 while (!nodes_to_visit.is_empty()) { 3208 while (!nodes_to_visit.is_empty()) {
3466 HeapEntry* entry = nodes_to_visit.last(); 3209 HeapEntry* entry = nodes_to_visit.last();
3467 Vector<HeapGraphEdge> children = entry->children(); 3210 Vector<HeapGraphEdge*> children = entry->children();
3468 bool has_new_edges = false; 3211 bool has_new_edges = false;
3469 for (int i = 0; i < children.length(); ++i) { 3212 for (int i = 0; i < children.length(); ++i) {
3470 if (entry != root && !IsRetainingEdge(&children[i])) continue; 3213 if (entry != root && !IsRetainingEdge(children[i])) continue;
3471 HeapEntry* child = children[i].to(); 3214 HeapEntry* child = children[i]->to();
3472 if (!child->painted()) { 3215 if (!child->painted()) {
3473 nodes_to_visit.Add(child); 3216 nodes_to_visit.Add(child);
3474 child->paint(); 3217 child->paint();
3475 has_new_edges = true; 3218 has_new_edges = true;
3476 } 3219 }
3477 } 3220 }
3478 if (!has_new_edges) { 3221 if (!has_new_edges) {
3479 entry->set_ordered_index(current_entry); 3222 entry->set_postorder_index(current_entry);
3480 (*entries)[current_entry++] = entry; 3223 (*entries)[current_entry++] = entry;
3481 nodes_to_visit.RemoveLast(); 3224 nodes_to_visit.RemoveLast();
3482 } 3225 }
3483 } 3226 }
3484 ASSERT_EQ(current_entry, entries->length()); 3227 ASSERT_EQ(current_entry, entries->length());
3485 } 3228 }
3486 3229
3487 3230
3488 static int Intersect(int i1, int i2, const Vector<int>& dominators) { 3231 static int Intersect(int i1, int i2, const Vector<int>& dominators) {
3489 int finger1 = i1, finger2 = i2; 3232 int finger1 = i1, finger2 = i2;
3490 while (finger1 != finger2) { 3233 while (finger1 != finger2) {
3491 while (finger1 < finger2) finger1 = dominators[finger1]; 3234 while (finger1 < finger2) finger1 = dominators[finger1];
3492 while (finger2 < finger1) finger2 = dominators[finger2]; 3235 while (finger2 < finger1) finger2 = dominators[finger2];
3493 } 3236 }
3494 return finger1; 3237 return finger1;
3495 } 3238 }
3496 3239
3497 3240
3498 // The algorithm is based on the article: 3241 // The algorithm is based on the article:
3499 // K. Cooper, T. Harvey and K. Kennedy "A Simple, Fast Dominance Algorithm" 3242 // K. Cooper, T. Harvey and K. Kennedy "A Simple, Fast Dominance Algorithm"
3500 // Softw. Pract. Exper. 4 (2001), pp. 1-10. 3243 // Softw. Pract. Exper. 4 (2001), pp. 1-10.
3501 bool HeapSnapshotGenerator::BuildDominatorTree( 3244 bool HeapSnapshotGenerator::BuildDominatorTree(
3502 const Vector<HeapEntry*>& entries, 3245 const Vector<HeapEntry*>& entries,
3503 Vector<int>* dominators) { 3246 Vector<int>* dominators) {
3504 if (entries.length() == 0) return true; 3247 if (entries.length() == 0) return true;
3505 HeapEntry* root = snapshot_->root(); 3248 HeapEntry* root = snapshot_->root();
3506 const int entries_length = entries.length(), root_index = entries_length - 1; 3249 const int entries_length = entries.length(), root_index = entries_length - 1;
3507 static const int kNoDominator = -1; 3250 for (int i = 0; i < root_index; ++i) (*dominators)[i] = HeapEntry::kNoEntry;
3508 for (int i = 0; i < root_index; ++i) (*dominators)[i] = kNoDominator;
3509 (*dominators)[root_index] = root_index; 3251 (*dominators)[root_index] = root_index;
3510 3252
3511 // The affected array is used to mark entries which dominators 3253 // The affected array is used to mark entries which dominators
3512 // have to be racalculated because of changes in their retainers. 3254 // have to be racalculated because of changes in their retainers.
3513 ScopedVector<bool> affected(entries_length); 3255 ScopedVector<bool> affected(entries_length);
3514 for (int i = 0; i < affected.length(); ++i) affected[i] = false; 3256 for (int i = 0; i < affected.length(); ++i) affected[i] = false;
3515 // Mark the root direct children as affected. 3257 // Mark the root direct children as affected.
3516 Vector<HeapGraphEdge> children = entries[root_index]->children(); 3258 Vector<HeapGraphEdge*> children = entries[root_index]->children();
3517 for (int i = 0; i < children.length(); ++i) { 3259 for (int i = 0; i < children.length(); ++i) {
3518 affected[children[i].to()->ordered_index()] = true; 3260 affected[children[i]->to()->postorder_index()] = true;
3519 } 3261 }
3520 3262
3521 bool changed = true; 3263 bool changed = true;
3522 while (changed) { 3264 while (changed) {
3523 changed = false; 3265 changed = false;
3524 if (!ProgressReport(true)) return false; 3266 if (!ProgressReport(false)) return false;
3525 for (int i = root_index - 1; i >= 0; --i) { 3267 for (int i = root_index - 1; i >= 0; --i) {
3526 if (!affected[i]) continue; 3268 if (!affected[i]) continue;
3527 affected[i] = false; 3269 affected[i] = false;
3528 // If dominator of the entry has already been set to root, 3270 // If dominator of the entry has already been set to root,
3529 // then it can't propagate any further. 3271 // then it can't propagate any further.
3530 if ((*dominators)[i] == root_index) continue; 3272 if ((*dominators)[i] == root_index) continue;
3531 int new_idom_index = kNoDominator; 3273 int new_idom_index = HeapEntry::kNoEntry;
3532 Vector<HeapGraphEdge*> rets = entries[i]->retainers(); 3274 Vector<HeapGraphEdge*> rets = entries[i]->retainers();
3533 for (int j = 0; j < rets.length(); ++j) { 3275 for (int j = 0; j < rets.length(); ++j) {
3534 if (rets[j]->from() != root && !IsRetainingEdge(rets[j])) continue; 3276 if (rets[j]->from() != root && !IsRetainingEdge(rets[j])) continue;
3535 int ret_index = rets[j]->from()->ordered_index(); 3277 int ret_index = rets[j]->from()->postorder_index();
3536 if (dominators->at(ret_index) != kNoDominator) { 3278 if (dominators->at(ret_index) != HeapEntry::kNoEntry) {
3537 new_idom_index = new_idom_index == kNoDominator 3279 new_idom_index = new_idom_index == HeapEntry::kNoEntry
3538 ? ret_index 3280 ? ret_index
3539 : Intersect(ret_index, new_idom_index, *dominators); 3281 : Intersect(ret_index, new_idom_index, *dominators);
3540 // If idom has already reached the root, it doesn't make sense 3282 // If idom has already reached the root, it doesn't make sense
3541 // to check other retainers. 3283 // to check other retainers.
3542 if (new_idom_index == root_index) break; 3284 if (new_idom_index == root_index) break;
3543 } 3285 }
3544 } 3286 }
3545 if (new_idom_index != kNoDominator 3287 if (new_idom_index != HeapEntry::kNoEntry
3546 && dominators->at(i) != new_idom_index) { 3288 && dominators->at(i) != new_idom_index) {
3547 (*dominators)[i] = new_idom_index; 3289 (*dominators)[i] = new_idom_index;
3548 changed = true; 3290 changed = true;
3549 Vector<HeapGraphEdge> children = entries[i]->children(); 3291 Vector<HeapGraphEdge*> children = entries[i]->children();
3550 for (int j = 0; j < children.length(); ++j) { 3292 for (int j = 0; j < children.length(); ++j) {
3551 affected[children[j].to()->ordered_index()] = true; 3293 affected[children[j]->to()->postorder_index()] = true;
3552 } 3294 }
3553 } 3295 }
3554 } 3296 }
3555 } 3297 }
3556 return true; 3298 return true;
3557 } 3299 }
3558 3300
3559 3301
3560 bool HeapSnapshotGenerator::SetEntriesDominators() { 3302 bool HeapSnapshotGenerator::SetEntriesDominators() {
3561 MarkUserReachableObjects(); 3303 MarkUserReachableObjects();
3562 // This array is used for maintaining postorder of nodes. 3304 // This array is used for maintaining postorder of nodes.
3563 ScopedVector<HeapEntry*> ordered_entries(snapshot_->entries()->length()); 3305 ScopedVector<HeapEntry*> ordered_entries(snapshot_->entries().length());
3564 FillPostorderIndexes(&ordered_entries); 3306 FillPostorderIndexes(&ordered_entries);
3565 ScopedVector<int> dominators(ordered_entries.length()); 3307 ScopedVector<int> dominators(ordered_entries.length());
3566 if (!BuildDominatorTree(ordered_entries, &dominators)) return false; 3308 if (!BuildDominatorTree(ordered_entries, &dominators)) return false;
3567 for (int i = 0; i < ordered_entries.length(); ++i) { 3309 for (int i = 0; i < ordered_entries.length(); ++i) {
3568 ASSERT(dominators[i] >= 0); 3310 ASSERT(dominators[i] != HeapEntry::kNoEntry);
3569 ordered_entries[i]->set_dominator(ordered_entries[dominators[i]]); 3311 ordered_entries[i]->set_dominator(ordered_entries[dominators[i]]);
3570 } 3312 }
3571 return true; 3313 return true;
3572 } 3314 }
3573 3315
3574 3316
3575 bool HeapSnapshotGenerator::CalculateRetainedSizes() { 3317 bool HeapSnapshotGenerator::CalculateRetainedSizes() {
3576 // As for the dominators tree we only know parent nodes, not 3318 // As for the dominators tree we only know parent nodes, not
3577 // children, to sum up total sizes we "bubble" node's self size 3319 // children, to sum up total sizes we "bubble" node's self size
3578 // adding it to all of its parents. 3320 // adding it to all of its parents.
3579 List<HeapEntry*>& entries = *snapshot_->entries(); 3321 List<HeapEntry>& entries = snapshot_->entries();
3580 for (int i = 0; i < entries.length(); ++i) { 3322 for (int i = 0; i < entries.length(); ++i) {
3581 HeapEntry* entry = entries[i]; 3323 HeapEntry* entry = &entries[i];
3582 entry->set_retained_size(entry->self_size()); 3324 entry->set_retained_size(entry->self_size());
3583 } 3325 }
3584 for (int i = 0; i < entries.length(); ++i) { 3326 for (int i = 0; i < entries.length(); ++i) {
3585 HeapEntry* entry = entries[i]; 3327 int entry_size = entries[i].self_size();
3586 int entry_size = entry->self_size(); 3328 HeapEntry* current = &entries[i];
3587 for (HeapEntry* dominator = entry->dominator(); 3329 for (HeapEntry* dominator = current->dominator();
3588 dominator != entry; 3330 dominator != current;
3589 entry = dominator, dominator = entry->dominator()) { 3331 current = dominator, dominator = current->dominator()) {
3332 ASSERT(current->dominator() != NULL);
3590 dominator->add_retained_size(entry_size); 3333 dominator->add_retained_size(entry_size);
3591 } 3334 }
3592 } 3335 }
3593 return true; 3336 return true;
3594 } 3337 }
3595 3338
3596 3339
3597 template<int bytes> struct MaxDecimalDigitsIn; 3340 template<int bytes> struct MaxDecimalDigitsIn;
3598 template<> struct MaxDecimalDigitsIn<4> { 3341 template<> struct MaxDecimalDigitsIn<4> {
3599 static const int kSigned = 11; 3342 static const int kSigned = 11;
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
3683 } 3426 }
3684 3427
3685 v8::OutputStream* stream_; 3428 v8::OutputStream* stream_;
3686 int chunk_size_; 3429 int chunk_size_;
3687 ScopedVector<char> chunk_; 3430 ScopedVector<char> chunk_;
3688 int chunk_pos_; 3431 int chunk_pos_;
3689 bool aborted_; 3432 bool aborted_;
3690 }; 3433 };
3691 3434
3692 3435
3436 // type, name|index, to_node.
3437 const int HeapSnapshotJSONSerializer::kEdgeFieldsCount = 3;
3438 // type, name, id, self_size, retained_size, dominator, children_index.
3439 const int HeapSnapshotJSONSerializer::kNodeFieldsCount = 7;
3440
3693 void HeapSnapshotJSONSerializer::Serialize(v8::OutputStream* stream) { 3441 void HeapSnapshotJSONSerializer::Serialize(v8::OutputStream* stream) {
3694 ASSERT(writer_ == NULL); 3442 ASSERT(writer_ == NULL);
3695 writer_ = new OutputStreamWriter(stream); 3443 writer_ = new OutputStreamWriter(stream);
3696 3444
3697 HeapSnapshot* original_snapshot = NULL; 3445 HeapSnapshot* original_snapshot = NULL;
3698 if (snapshot_->raw_entries_size() >= 3446 if (snapshot_->RawSnapshotSize() >=
3699 SnapshotSizeConstants<kPointerSize>::kMaxSerializableSnapshotRawSize) { 3447 SnapshotSizeConstants<kPointerSize>::kMaxSerializableSnapshotRawSize) {
3700 // The snapshot is too big. Serialize a fake snapshot. 3448 // The snapshot is too big. Serialize a fake snapshot.
3701 original_snapshot = snapshot_; 3449 original_snapshot = snapshot_;
3702 snapshot_ = CreateFakeSnapshot(); 3450 snapshot_ = CreateFakeSnapshot();
3703 } 3451 }
3704 // Since nodes graph is cyclic, we need the first pass to enumerate 3452
3705 // them. Strings can be serialized in one pass.
3706 SerializeImpl(); 3453 SerializeImpl();
3707 3454
3708 delete writer_; 3455 delete writer_;
3709 writer_ = NULL; 3456 writer_ = NULL;
3710 3457
3711 if (original_snapshot != NULL) { 3458 if (original_snapshot != NULL) {
3712 delete snapshot_; 3459 delete snapshot_;
3713 snapshot_ = original_snapshot; 3460 snapshot_ = original_snapshot;
3714 } 3461 }
3715 } 3462 }
3716 3463
3717 3464
3718 HeapSnapshot* HeapSnapshotJSONSerializer::CreateFakeSnapshot() { 3465 HeapSnapshot* HeapSnapshotJSONSerializer::CreateFakeSnapshot() {
3719 HeapSnapshot* result = new HeapSnapshot(snapshot_->collection(), 3466 HeapSnapshot* result = new HeapSnapshot(snapshot_->collection(),
3720 HeapSnapshot::kFull, 3467 HeapSnapshot::kFull,
3721 snapshot_->title(), 3468 snapshot_->title(),
3722 snapshot_->uid()); 3469 snapshot_->uid());
3723 result->AllocateEntries(2, 1, 0); 3470 result->AddRootEntry();
3724 HeapEntry* root = result->AddRootEntry(1);
3725 const char* text = snapshot_->collection()->names()->GetFormatted( 3471 const char* text = snapshot_->collection()->names()->GetFormatted(
3726 "The snapshot is too big. " 3472 "The snapshot is too big. "
3727 "Maximum snapshot size is %" V8_PTR_PREFIX "u MB. " 3473 "Maximum snapshot size is %" V8_PTR_PREFIX "u MB. "
3728 "Actual snapshot size is %" V8_PTR_PREFIX "u MB.", 3474 "Actual snapshot size is %" V8_PTR_PREFIX "u MB.",
3729 SnapshotSizeConstants<kPointerSize>::kMaxSerializableSnapshotRawSize / MB, 3475 SnapshotSizeConstants<kPointerSize>::kMaxSerializableSnapshotRawSize / MB,
3730 (snapshot_->raw_entries_size() + MB - 1) / MB); 3476 (snapshot_->RawSnapshotSize() + MB - 1) / MB);
3731 HeapEntry* message = result->AddEntry( 3477 HeapEntry* message = result->AddEntry(HeapEntry::kString, text, 0, 4);
3732 HeapEntry::kString, text, 0, 4, 0, 0); 3478 result->root()->SetIndexedReference(HeapGraphEdge::kElement, 1, message);
3733 root->SetUnidirElementReference(0, 1, message); 3479 result->FillChildrenAndRetainers();
3734 result->SetDominatorsToSelf(); 3480 result->SetDominatorsToSelf();
3735 return result; 3481 return result;
3736 } 3482 }
3737 3483
3738 3484
3739 void HeapSnapshotJSONSerializer::CalculateNodeIndexes(
3740 const List<HeapEntry*>& nodes) {
3741 // type,name,id,self_size,retained_size,dominator,children_index.
3742 const int node_fields_count = 7;
3743 // Root must be the first.
3744 ASSERT(nodes.first() == snapshot_->root());
3745 // Rewrite node indexes, so they refer to actual array positions. Do this
3746 // only once.
3747 if (nodes[0]->entry_index() == -1) {
3748 int index = 0;
3749 for (int i = 0; i < nodes.length(); ++i, index += node_fields_count) {
3750 nodes[i]->set_entry_index(index);
3751 }
3752 }
3753 }
3754
3755
3756 void HeapSnapshotJSONSerializer::SerializeImpl() { 3485 void HeapSnapshotJSONSerializer::SerializeImpl() {
3757 List<HeapEntry*>& nodes = *(snapshot_->entries()); 3486 List<HeapEntry>& nodes = snapshot_->entries();
3758 CalculateNodeIndexes(nodes); 3487 ASSERT(0 == snapshot_->root()->index());
3759 writer_->AddCharacter('{'); 3488 writer_->AddCharacter('{');
3760 writer_->AddString("\"snapshot\":{"); 3489 writer_->AddString("\"snapshot\":{");
3761 SerializeSnapshot(); 3490 SerializeSnapshot();
3762 if (writer_->aborted()) return; 3491 if (writer_->aborted()) return;
3763 writer_->AddString("},\n"); 3492 writer_->AddString("},\n");
3764 writer_->AddString("\"nodes\":["); 3493 writer_->AddString("\"nodes\":[");
3765 SerializeNodes(nodes); 3494 SerializeNodes(nodes);
3766 if (writer_->aborted()) return; 3495 if (writer_->aborted()) return;
3767 writer_->AddString("],\n"); 3496 writer_->AddString("],\n");
3768 writer_->AddString("\"edges\":["); 3497 writer_->AddString("\"edges\":[");
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
3824 || edge->type() == HeapGraphEdge::kWeak 3553 || edge->type() == HeapGraphEdge::kWeak
3825 ? edge->index() : GetStringId(edge->name()); 3554 ? edge->index() : GetStringId(edge->name());
3826 int buffer_pos = 0; 3555 int buffer_pos = 0;
3827 if (!first_edge) { 3556 if (!first_edge) {
3828 buffer[buffer_pos++] = ','; 3557 buffer[buffer_pos++] = ',';
3829 } 3558 }
3830 buffer_pos = itoa(edge->type(), buffer, buffer_pos); 3559 buffer_pos = itoa(edge->type(), buffer, buffer_pos);
3831 buffer[buffer_pos++] = ','; 3560 buffer[buffer_pos++] = ',';
3832 buffer_pos = itoa(edge_name_or_index, buffer, buffer_pos); 3561 buffer_pos = itoa(edge_name_or_index, buffer, buffer_pos);
3833 buffer[buffer_pos++] = ','; 3562 buffer[buffer_pos++] = ',';
3834 buffer_pos = itoa(edge->to()->entry_index(), buffer, buffer_pos); 3563 buffer_pos = itoa(entry_index(edge->to()), buffer, buffer_pos);
3835 buffer[buffer_pos++] = '\0'; 3564 buffer[buffer_pos++] = '\0';
3836 writer_->AddString(buffer.start()); 3565 writer_->AddString(buffer.start());
3837 } 3566 }
3838 3567
3839 3568
3840 void HeapSnapshotJSONSerializer::SerializeEdges(const List<HeapEntry*>& nodes) { 3569 void HeapSnapshotJSONSerializer::SerializeEdges(const List<HeapEntry>& nodes) {
3841 bool first_edge = true; 3570 bool first_edge = true;
3842 for (int i = 0; i < nodes.length(); ++i) { 3571 for (int i = 0; i < nodes.length(); ++i) {
3843 HeapEntry* entry = nodes[i]; 3572 HeapEntry* entry = &nodes[i];
3844 Vector<HeapGraphEdge> children = entry->children(); 3573 Vector<HeapGraphEdge*> children = entry->children();
3845 for (int j = 0; j < children.length(); ++j) { 3574 for (int j = 0; j < children.length(); ++j) {
3846 SerializeEdge(&children[j], first_edge); 3575 SerializeEdge(children[j], first_edge);
3847 first_edge = false; 3576 first_edge = false;
3848 if (writer_->aborted()) return; 3577 if (writer_->aborted()) return;
3849 } 3578 }
3850 } 3579 }
3851 } 3580 }
3852 3581
3853 3582
3854 void HeapSnapshotJSONSerializer::SerializeNode(HeapEntry* entry, 3583 void HeapSnapshotJSONSerializer::SerializeNode(HeapEntry* entry,
3855 int edges_index) { 3584 int edges_index) {
3856 // The buffer needs space for 6 ints, 1 uint32_t, 7 commas, \n and \0 3585 // The buffer needs space for 6 ints, 1 uint32_t, 7 commas, \n and \0
3857 static const int kBufferSize = 3586 static const int kBufferSize =
3858 6 * MaxDecimalDigitsIn<sizeof(int)>::kSigned // NOLINT 3587 6 * MaxDecimalDigitsIn<sizeof(int)>::kSigned // NOLINT
3859 + MaxDecimalDigitsIn<sizeof(uint32_t)>::kUnsigned // NOLINT 3588 + MaxDecimalDigitsIn<sizeof(uint32_t)>::kUnsigned // NOLINT
3860 + 7 + 1 + 1; 3589 + 7 + 1 + 1;
3861 EmbeddedVector<char, kBufferSize> buffer; 3590 EmbeddedVector<char, kBufferSize> buffer;
3862 int buffer_pos = 0; 3591 int buffer_pos = 0;
3863 buffer[buffer_pos++] = '\n'; 3592 buffer[buffer_pos++] = '\n';
3864 if (entry->entry_index() != 0) { 3593 if (entry_index(entry) != 0) {
3865 buffer[buffer_pos++] = ','; 3594 buffer[buffer_pos++] = ',';
3866 } 3595 }
3867 buffer_pos = itoa(entry->type(), buffer, buffer_pos); 3596 buffer_pos = itoa(entry->type(), buffer, buffer_pos);
3868 buffer[buffer_pos++] = ','; 3597 buffer[buffer_pos++] = ',';
3869 buffer_pos = itoa(GetStringId(entry->name()), buffer, buffer_pos); 3598 buffer_pos = itoa(GetStringId(entry->name()), buffer, buffer_pos);
3870 buffer[buffer_pos++] = ','; 3599 buffer[buffer_pos++] = ',';
3871 buffer_pos = itoa(entry->id(), buffer, buffer_pos); 3600 buffer_pos = itoa(entry->id(), buffer, buffer_pos);
3872 buffer[buffer_pos++] = ','; 3601 buffer[buffer_pos++] = ',';
3873 buffer_pos = itoa(entry->self_size(), buffer, buffer_pos); 3602 buffer_pos = itoa(entry->self_size(), buffer, buffer_pos);
3874 buffer[buffer_pos++] = ','; 3603 buffer[buffer_pos++] = ',';
3875 buffer_pos = itoa(entry->retained_size(), buffer, buffer_pos); 3604 buffer_pos = itoa(entry->retained_size(), buffer, buffer_pos);
3876 buffer[buffer_pos++] = ','; 3605 buffer[buffer_pos++] = ',';
3877 buffer_pos = itoa(entry->dominator()->entry_index(), buffer, buffer_pos); 3606 buffer_pos = itoa(entry_index(entry->dominator()), buffer, buffer_pos);
3878 buffer[buffer_pos++] = ','; 3607 buffer[buffer_pos++] = ',';
3879 buffer_pos = itoa(edges_index, buffer, buffer_pos); 3608 buffer_pos = itoa(edges_index, buffer, buffer_pos);
3880 buffer[buffer_pos++] = '\0'; 3609 buffer[buffer_pos++] = '\0';
3881 writer_->AddString(buffer.start()); 3610 writer_->AddString(buffer.start());
3882 } 3611 }
3883 3612
3884 3613
3885 void HeapSnapshotJSONSerializer::SerializeNodes(const List<HeapEntry*>& nodes) { 3614 void HeapSnapshotJSONSerializer::SerializeNodes(const List<HeapEntry>& nodes) {
3886 const int edge_fields_count = 3; // type,name|index,to_node.
3887 int edges_index = 0; 3615 int edges_index = 0;
3888 for (int i = 0; i < nodes.length(); ++i) { 3616 for (int i = 0; i < nodes.length(); ++i) {
3889 HeapEntry* entry = nodes[i]; 3617 HeapEntry* entry = &nodes[i];
3890 SerializeNode(entry, edges_index); 3618 SerializeNode(entry, edges_index);
3891 edges_index += entry->children().length() * edge_fields_count; 3619 edges_index += entry->children().length() * kEdgeFieldsCount;
3892 if (writer_->aborted()) return; 3620 if (writer_->aborted()) return;
3893 } 3621 }
3894 } 3622 }
3895 3623
3896 3624
3897 void HeapSnapshotJSONSerializer::SerializeSnapshot() { 3625 void HeapSnapshotJSONSerializer::SerializeSnapshot() {
3898 writer_->AddString("\"title\":\""); 3626 writer_->AddString("\"title\":\"");
3899 writer_->AddString(snapshot_->title()); 3627 writer_->AddString(snapshot_->title());
3900 writer_->AddString("\""); 3628 writer_->AddString("\"");
3901 writer_->AddString(",\"uid\":"); 3629 writer_->AddString(",\"uid\":");
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
3945 JSON_S("internal") "," 3673 JSON_S("internal") ","
3946 JSON_S("hidden") "," 3674 JSON_S("hidden") ","
3947 JSON_S("shortcut") "," 3675 JSON_S("shortcut") ","
3948 JSON_S("weak")) "," 3676 JSON_S("weak")) ","
3949 JSON_S("string_or_number") "," 3677 JSON_S("string_or_number") ","
3950 JSON_S("node")))); 3678 JSON_S("node"))));
3951 #undef JSON_S 3679 #undef JSON_S
3952 #undef JSON_O 3680 #undef JSON_O
3953 #undef JSON_A 3681 #undef JSON_A
3954 writer_->AddString(",\"node_count\":"); 3682 writer_->AddString(",\"node_count\":");
3955 writer_->AddNumber(snapshot_->entries()->length()); 3683 writer_->AddNumber(snapshot_->entries().length());
3956 writer_->AddString(",\"edge_count\":"); 3684 writer_->AddString(",\"edge_count\":");
3957 writer_->AddNumber(snapshot_->number_of_edges()); 3685 writer_->AddNumber(snapshot_->edges().length());
3958 } 3686 }
3959 3687
3960 3688
3961 static void WriteUChar(OutputStreamWriter* w, unibrow::uchar u) { 3689 static void WriteUChar(OutputStreamWriter* w, unibrow::uchar u) {
3962 static const char hex_chars[] = "0123456789ABCDEF"; 3690 static const char hex_chars[] = "0123456789ABCDEF";
3963 w->AddString("\\u"); 3691 w->AddString("\\u");
3964 w->AddCharacter(hex_chars[(u >> 12) & 0xf]); 3692 w->AddCharacter(hex_chars[(u >> 12) & 0xf]);
3965 w->AddCharacter(hex_chars[(u >> 8) & 0xf]); 3693 w->AddCharacter(hex_chars[(u >> 8) & 0xf]);
3966 w->AddCharacter(hex_chars[(u >> 4) & 0xf]); 3694 w->AddCharacter(hex_chars[(u >> 4) & 0xf]);
3967 w->AddCharacter(hex_chars[u & 0xf]); 3695 w->AddCharacter(hex_chars[u & 0xf]);
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
4045 3773
4046 3774
4047 void HeapSnapshotJSONSerializer::SortHashMap( 3775 void HeapSnapshotJSONSerializer::SortHashMap(
4048 HashMap* map, List<HashMap::Entry*>* sorted_entries) { 3776 HashMap* map, List<HashMap::Entry*>* sorted_entries) {
4049 for (HashMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) 3777 for (HashMap::Entry* p = map->Start(); p != NULL; p = map->Next(p))
4050 sorted_entries->Add(p); 3778 sorted_entries->Add(p);
4051 sorted_entries->Sort(SortUsingEntryValue); 3779 sorted_entries->Sort(SortUsingEntryValue);
4052 } 3780 }
4053 3781
4054 } } // namespace v8::internal 3782 } } // namespace v8::internal
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