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

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

Powered by Google App Engine
This is Rietveld 408576698