OLD | NEW |
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 953 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
964 | 964 |
965 void HeapEntry::Init(HeapSnapshot* snapshot, | 965 void HeapEntry::Init(HeapSnapshot* snapshot, |
966 Type type, | 966 Type type, |
967 const char* name, | 967 const char* name, |
968 uint64_t id, | 968 uint64_t id, |
969 int self_size, | 969 int self_size, |
970 int children_count, | 970 int children_count, |
971 int retainers_count) { | 971 int retainers_count) { |
972 snapshot_ = snapshot; | 972 snapshot_ = snapshot; |
973 type_ = type; | 973 type_ = type; |
974 painted_ = kUnpainted; | 974 painted_ = false; |
975 name_ = name; | 975 name_ = name; |
976 self_size_ = self_size; | 976 self_size_ = self_size; |
977 retained_size_ = 0; | 977 retained_size_ = 0; |
978 children_count_ = children_count; | 978 children_count_ = children_count; |
979 retainers_count_ = retainers_count; | 979 retainers_count_ = retainers_count; |
980 dominator_ = NULL; | 980 dominator_ = NULL; |
981 | 981 |
982 union { | 982 union { |
983 uint64_t set_id; | 983 uint64_t set_id; |
984 Id stored_id; | 984 Id stored_id; |
(...skipping 21 matching lines...) Expand all Loading... |
1006 entry->retainers_arr()[retainer_index] = children_arr() + child_index; | 1006 entry->retainers_arr()[retainer_index] = children_arr() + child_index; |
1007 } | 1007 } |
1008 | 1008 |
1009 | 1009 |
1010 void HeapEntry::SetUnidirElementReference( | 1010 void HeapEntry::SetUnidirElementReference( |
1011 int child_index, int index, HeapEntry* entry) { | 1011 int child_index, int index, HeapEntry* entry) { |
1012 children_arr()[child_index].Init(child_index, index, entry); | 1012 children_arr()[child_index].Init(child_index, index, entry); |
1013 } | 1013 } |
1014 | 1014 |
1015 | 1015 |
1016 int HeapEntry::RetainedSize(bool exact) { | |
1017 if (exact && (retained_size_ & kExactRetainedSizeTag) == 0) { | |
1018 CalculateExactRetainedSize(); | |
1019 } | |
1020 return retained_size_ & (~kExactRetainedSizeTag); | |
1021 } | |
1022 | |
1023 | |
1024 Handle<HeapObject> HeapEntry::GetHeapObject() { | 1016 Handle<HeapObject> HeapEntry::GetHeapObject() { |
1025 return snapshot_->collection()->FindHeapObjectById(id()); | 1017 return snapshot_->collection()->FindHeapObjectById(id()); |
1026 } | 1018 } |
1027 | 1019 |
1028 | 1020 |
1029 template<class Visitor> | |
1030 void HeapEntry::ApplyAndPaintAllReachable(Visitor* visitor) { | |
1031 List<HeapEntry*> list(10); | |
1032 list.Add(this); | |
1033 this->paint_reachable(); | |
1034 visitor->Apply(this); | |
1035 while (!list.is_empty()) { | |
1036 HeapEntry* entry = list.RemoveLast(); | |
1037 Vector<HeapGraphEdge> children = entry->children(); | |
1038 for (int i = 0; i < children.length(); ++i) { | |
1039 if (children[i].type() == HeapGraphEdge::kShortcut) continue; | |
1040 HeapEntry* child = children[i].to(); | |
1041 if (!child->painted_reachable()) { | |
1042 list.Add(child); | |
1043 child->paint_reachable(); | |
1044 visitor->Apply(child); | |
1045 } | |
1046 } | |
1047 } | |
1048 } | |
1049 | |
1050 | |
1051 class NullClass { | |
1052 public: | |
1053 void Apply(HeapEntry* entry) { } | |
1054 }; | |
1055 | |
1056 void HeapEntry::PaintAllReachable() { | |
1057 NullClass null; | |
1058 ApplyAndPaintAllReachable(&null); | |
1059 } | |
1060 | |
1061 | |
1062 void HeapEntry::Print( | 1021 void HeapEntry::Print( |
1063 const char* prefix, const char* edge_name, int max_depth, int indent) { | 1022 const char* prefix, const char* edge_name, int max_depth, int indent) { |
1064 OS::Print("%6d %7d @%6llu %*c %s%s: ", | 1023 OS::Print("%6d %7d @%6llu %*c %s%s: ", |
1065 self_size(), RetainedSize(false), id(), | 1024 self_size(), retained_size(), id(), |
1066 indent, ' ', prefix, edge_name); | 1025 indent, ' ', prefix, edge_name); |
1067 if (type() != kString) { | 1026 if (type() != kString) { |
1068 OS::Print("%s %.40s\n", TypeAsString(), name_); | 1027 OS::Print("%s %.40s\n", TypeAsString(), name_); |
1069 } else { | 1028 } else { |
1070 OS::Print("\""); | 1029 OS::Print("\""); |
1071 const char* c = name_; | 1030 const char* c = name_; |
1072 while (*c && (c - name_) <= 40) { | 1031 while (*c && (c - name_) <= 40) { |
1073 if (*c != '\n') | 1032 if (*c != '\n') |
1074 OS::Print("%c", *c); | 1033 OS::Print("%c", *c); |
1075 else | 1034 else |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1139 | 1098 |
1140 int HeapEntry::EntriesSize(int entries_count, | 1099 int HeapEntry::EntriesSize(int entries_count, |
1141 int children_count, | 1100 int children_count, |
1142 int retainers_count) { | 1101 int retainers_count) { |
1143 return sizeof(HeapEntry) * entries_count // NOLINT | 1102 return sizeof(HeapEntry) * entries_count // NOLINT |
1144 + sizeof(HeapGraphEdge) * children_count // NOLINT | 1103 + sizeof(HeapGraphEdge) * children_count // NOLINT |
1145 + sizeof(HeapGraphEdge*) * retainers_count; // NOLINT | 1104 + sizeof(HeapGraphEdge*) * retainers_count; // NOLINT |
1146 } | 1105 } |
1147 | 1106 |
1148 | 1107 |
1149 class RetainedSizeCalculator { | |
1150 public: | |
1151 RetainedSizeCalculator() | |
1152 : retained_size_(0) { | |
1153 } | |
1154 | |
1155 int retained_size() const { return retained_size_; } | |
1156 | |
1157 void Apply(HeapEntry** entry_ptr) { | |
1158 if ((*entry_ptr)->painted_reachable()) { | |
1159 retained_size_ += (*entry_ptr)->self_size(); | |
1160 } | |
1161 } | |
1162 | |
1163 private: | |
1164 int retained_size_; | |
1165 }; | |
1166 | |
1167 | |
1168 void HeapEntry::CalculateExactRetainedSize() { | |
1169 // To calculate retained size, first we paint all reachable nodes in | |
1170 // one color, then we paint (or re-paint) all nodes reachable from | |
1171 // other nodes with a different color. Then we sum up self sizes of | |
1172 // nodes painted with the first color. | |
1173 snapshot()->ClearPaint(); | |
1174 PaintAllReachable(); | |
1175 | |
1176 List<HeapEntry*> list(10); | |
1177 HeapEntry* root = snapshot()->root(); | |
1178 if (this != root) { | |
1179 list.Add(root); | |
1180 root->paint_reachable_from_others(); | |
1181 } | |
1182 while (!list.is_empty()) { | |
1183 HeapEntry* curr = list.RemoveLast(); | |
1184 Vector<HeapGraphEdge> children = curr->children(); | |
1185 for (int i = 0; i < children.length(); ++i) { | |
1186 if (children[i].type() == HeapGraphEdge::kShortcut) continue; | |
1187 HeapEntry* child = children[i].to(); | |
1188 if (child != this && child->not_painted_reachable_from_others()) { | |
1189 list.Add(child); | |
1190 child->paint_reachable_from_others(); | |
1191 } | |
1192 } | |
1193 } | |
1194 | |
1195 RetainedSizeCalculator ret_size_calc; | |
1196 snapshot()->IterateEntries(&ret_size_calc); | |
1197 retained_size_ = ret_size_calc.retained_size(); | |
1198 ASSERT((retained_size_ & kExactRetainedSizeTag) == 0); | |
1199 retained_size_ |= kExactRetainedSizeTag; | |
1200 } | |
1201 | |
1202 | |
1203 // It is very important to keep objects that form a heap snapshot | 1108 // It is very important to keep objects that form a heap snapshot |
1204 // as small as possible. | 1109 // as small as possible. |
1205 namespace { // Avoid littering the global namespace. | 1110 namespace { // Avoid littering the global namespace. |
1206 | 1111 |
1207 template <size_t ptr_size> struct SnapshotSizeConstants; | 1112 template <size_t ptr_size> struct SnapshotSizeConstants; |
1208 | 1113 |
1209 template <> struct SnapshotSizeConstants<4> { | 1114 template <> struct SnapshotSizeConstants<4> { |
1210 static const int kExpectedHeapGraphEdgeSize = 12; | 1115 static const int kExpectedHeapGraphEdgeSize = 12; |
1211 static const int kExpectedHeapEntrySize = 36; | 1116 static const int kExpectedHeapEntrySize = 36; |
1212 static const int kMaxSerializableSnapshotRawSize = 256 * MB; | 1117 static const int kMaxSerializableSnapshotRawSize = 256 * MB; |
(...skipping 1969 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3182 // Allocate and fill entries in the snapshot, allocate references. | 3087 // Allocate and fill entries in the snapshot, allocate references. |
3183 snapshot_->AllocateEntries(entries_.entries_count(), | 3088 snapshot_->AllocateEntries(entries_.entries_count(), |
3184 entries_.total_children_count(), | 3089 entries_.total_children_count(), |
3185 entries_.total_retainers_count()); | 3090 entries_.total_retainers_count()); |
3186 entries_.AllocateEntries(); | 3091 entries_.AllocateEntries(); |
3187 | 3092 |
3188 // Pass 2. Fill references. | 3093 // Pass 2. Fill references. |
3189 if (!FillReferences()) return false; | 3094 if (!FillReferences()) return false; |
3190 | 3095 |
3191 if (!SetEntriesDominators()) return false; | 3096 if (!SetEntriesDominators()) return false; |
3192 if (!ApproximateRetainedSizes()) return false; | 3097 if (!CalculateRetainedSizes()) return false; |
3193 | 3098 |
3194 progress_counter_ = progress_total_; | 3099 progress_counter_ = progress_total_; |
3195 if (!ProgressReport(true)) return false; | 3100 if (!ProgressReport(true)) return false; |
3196 return true; | 3101 return true; |
3197 } | 3102 } |
3198 | 3103 |
3199 | 3104 |
3200 void HeapSnapshotGenerator::ProgressStep() { | 3105 void HeapSnapshotGenerator::ProgressStep() { |
3201 ++progress_counter_; | 3106 ++progress_counter_; |
3202 } | 3107 } |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3240 dom_explorer_.IterateAndExtractReferences(&filler); | 3145 dom_explorer_.IterateAndExtractReferences(&filler); |
3241 } | 3146 } |
3242 | 3147 |
3243 | 3148 |
3244 void HeapSnapshotGenerator::FillReversePostorderIndexes( | 3149 void HeapSnapshotGenerator::FillReversePostorderIndexes( |
3245 Vector<HeapEntry*>* entries) { | 3150 Vector<HeapEntry*>* entries) { |
3246 snapshot_->ClearPaint(); | 3151 snapshot_->ClearPaint(); |
3247 int current_entry = 0; | 3152 int current_entry = 0; |
3248 List<HeapEntry*> nodes_to_visit; | 3153 List<HeapEntry*> nodes_to_visit; |
3249 nodes_to_visit.Add(snapshot_->root()); | 3154 nodes_to_visit.Add(snapshot_->root()); |
3250 snapshot_->root()->paint_reachable(); | 3155 snapshot_->root()->paint(); |
3251 while (!nodes_to_visit.is_empty()) { | 3156 while (!nodes_to_visit.is_empty()) { |
3252 HeapEntry* entry = nodes_to_visit.last(); | 3157 HeapEntry* entry = nodes_to_visit.last(); |
3253 Vector<HeapGraphEdge> children = entry->children(); | 3158 Vector<HeapGraphEdge> children = entry->children(); |
3254 bool has_new_edges = false; | 3159 bool has_new_edges = false; |
3255 for (int i = 0; i < children.length(); ++i) { | 3160 for (int i = 0; i < children.length(); ++i) { |
3256 if (children[i].type() == HeapGraphEdge::kShortcut) continue; | 3161 if (children[i].type() == HeapGraphEdge::kShortcut) continue; |
3257 HeapEntry* child = children[i].to(); | 3162 HeapEntry* child = children[i].to(); |
3258 if (!child->painted_reachable()) { | 3163 if (!child->painted()) { |
3259 nodes_to_visit.Add(child); | 3164 nodes_to_visit.Add(child); |
3260 child->paint_reachable(); | 3165 child->paint(); |
3261 has_new_edges = true; | 3166 has_new_edges = true; |
3262 } | 3167 } |
3263 } | 3168 } |
3264 if (!has_new_edges) { | 3169 if (!has_new_edges) { |
3265 entry->set_ordered_index(current_entry); | 3170 entry->set_ordered_index(current_entry); |
3266 (*entries)[current_entry++] = entry; | 3171 (*entries)[current_entry++] = entry; |
3267 nodes_to_visit.RemoveLast(); | 3172 nodes_to_visit.RemoveLast(); |
3268 } | 3173 } |
3269 } | 3174 } |
3270 ASSERT_EQ(current_entry, entries->length()); | 3175 ASSERT_EQ(current_entry, entries->length()); |
(...skipping 15 matching lines...) Expand all Loading... |
3286 // Softw. Pract. Exper. 4 (2001), pp. 1-10. | 3191 // Softw. Pract. Exper. 4 (2001), pp. 1-10. |
3287 bool HeapSnapshotGenerator::BuildDominatorTree( | 3192 bool HeapSnapshotGenerator::BuildDominatorTree( |
3288 const Vector<HeapEntry*>& entries, | 3193 const Vector<HeapEntry*>& entries, |
3289 Vector<int>* dominators) { | 3194 Vector<int>* dominators) { |
3290 if (entries.length() == 0) return true; | 3195 if (entries.length() == 0) return true; |
3291 const int entries_length = entries.length(), root_index = entries_length - 1; | 3196 const int entries_length = entries.length(), root_index = entries_length - 1; |
3292 static const int kNoDominator = -1; | 3197 static const int kNoDominator = -1; |
3293 for (int i = 0; i < root_index; ++i) (*dominators)[i] = kNoDominator; | 3198 for (int i = 0; i < root_index; ++i) (*dominators)[i] = kNoDominator; |
3294 (*dominators)[root_index] = root_index; | 3199 (*dominators)[root_index] = root_index; |
3295 | 3200 |
3296 // The affected array is used to mark those entries that may | 3201 // The painted flag is used to mark entries that need to be recalculated |
3297 // be affected because of dominators change among their retainers. | 3202 // because of dominators change among their retainers. |
3298 ScopedVector<bool> affected(entries_length); | 3203 for (int i = 0; i < entries_length; ++i) entries[i]->clear_paint(); |
3299 for (int i = 0; i < entries_length; ++i) affected[i] = false; | 3204 |
| 3205 // Mark the root direct children as affected. |
3300 Vector<HeapGraphEdge> children = entries[root_index]->children(); | 3206 Vector<HeapGraphEdge> children = entries[root_index]->children(); |
3301 for (int i = 0; i < children.length(); ++i) { | 3207 for (int i = 0; i < children.length(); ++i) children[i].to()->paint(); |
3302 // Mark the root direct children as affected. | |
3303 affected[children[i].to()->ordered_index()] = true; | |
3304 } | |
3305 | 3208 |
3306 bool changed = true; | 3209 bool changed = true; |
3307 while (changed) { | 3210 while (changed) { |
3308 changed = false; | 3211 changed = false; |
3309 for (int i = root_index - 1; i >= 0; --i) { | 3212 for (int i = root_index - 1; i >= 0; --i) { |
3310 // If dominator of the entry has already been set to root, | 3213 // If dominator of the entry has already been set to root, |
3311 // then it can't propagate any further. | 3214 // then it can't propagate any further. |
3312 if ((*dominators)[i] == root_index) continue; | 3215 if ((*dominators)[i] == root_index) continue; |
3313 if (!affected[i]) continue; | 3216 HeapEntry* entry = entries[i]; |
3314 affected[i] = false; | 3217 if (!entry->painted()) continue; |
| 3218 entry->clear_paint(); |
3315 int new_idom_index = kNoDominator; | 3219 int new_idom_index = kNoDominator; |
3316 Vector<HeapGraphEdge*> rets = entries[i]->retainers(); | 3220 Vector<HeapGraphEdge*> rets = entry->retainers(); |
3317 for (int j = 0; j < rets.length(); ++j) { | 3221 for (int j = 0; j < rets.length(); ++j) { |
3318 if (rets[j]->type() == HeapGraphEdge::kShortcut) continue; | 3222 if (rets[j]->type() == HeapGraphEdge::kShortcut) continue; |
3319 int ret_index = rets[j]->From()->ordered_index(); | 3223 int ret_index = rets[j]->From()->ordered_index(); |
3320 if (dominators->at(ret_index) != kNoDominator) { | 3224 if (dominators->at(ret_index) != kNoDominator) { |
3321 new_idom_index = new_idom_index == kNoDominator | 3225 new_idom_index = new_idom_index == kNoDominator |
3322 ? ret_index | 3226 ? ret_index |
3323 : Intersect(ret_index, new_idom_index, *dominators); | 3227 : Intersect(ret_index, new_idom_index, *dominators); |
3324 // If idom has already reached the root, it doesn't make sense | 3228 // If idom has already reached the root, it doesn't make sense |
3325 // to check other retainers. | 3229 // to check other retainers. |
3326 if (new_idom_index == root_index) break; | 3230 if (new_idom_index == root_index) break; |
3327 } | 3231 } |
3328 } | 3232 } |
3329 if (new_idom_index != kNoDominator | 3233 if (new_idom_index != kNoDominator |
3330 && dominators->at(i) != new_idom_index) { | 3234 && dominators->at(i) != new_idom_index) { |
3331 (*dominators)[i] = new_idom_index; | 3235 (*dominators)[i] = new_idom_index; |
3332 changed = true; | 3236 changed = true; |
3333 Vector<HeapGraphEdge> children = entries[i]->children(); | 3237 Vector<HeapGraphEdge> children = entries[i]->children(); |
3334 for (int j = 0; j < children.length(); ++j) { | 3238 for (int j = 0; j < children.length(); ++j) children[j].to()->paint(); |
3335 affected[children[j].to()->ordered_index()] = true; | |
3336 } | |
3337 } | 3239 } |
3338 } | 3240 } |
3339 } | 3241 } |
3340 return true; | 3242 return true; |
3341 } | 3243 } |
3342 | 3244 |
3343 | 3245 |
3344 bool HeapSnapshotGenerator::SetEntriesDominators() { | 3246 bool HeapSnapshotGenerator::SetEntriesDominators() { |
3345 // This array is used for maintaining reverse postorder of nodes. | 3247 // This array is used for maintaining reverse postorder of nodes. |
3346 ScopedVector<HeapEntry*> ordered_entries(snapshot_->entries()->length()); | 3248 ScopedVector<HeapEntry*> ordered_entries(snapshot_->entries()->length()); |
3347 FillReversePostorderIndexes(&ordered_entries); | 3249 FillReversePostorderIndexes(&ordered_entries); |
3348 ScopedVector<int> dominators(ordered_entries.length()); | 3250 ScopedVector<int> dominators(ordered_entries.length()); |
3349 if (!BuildDominatorTree(ordered_entries, &dominators)) return false; | 3251 if (!BuildDominatorTree(ordered_entries, &dominators)) return false; |
3350 for (int i = 0; i < ordered_entries.length(); ++i) { | 3252 for (int i = 0; i < ordered_entries.length(); ++i) { |
3351 ASSERT(dominators[i] >= 0); | 3253 ASSERT(dominators[i] >= 0); |
3352 ordered_entries[i]->set_dominator(ordered_entries[dominators[i]]); | 3254 ordered_entries[i]->set_dominator(ordered_entries[dominators[i]]); |
3353 } | 3255 } |
3354 return true; | 3256 return true; |
3355 } | 3257 } |
3356 | 3258 |
3357 | 3259 |
3358 bool HeapSnapshotGenerator::ApproximateRetainedSizes() { | 3260 bool HeapSnapshotGenerator::CalculateRetainedSizes() { |
3359 // As for the dominators tree we only know parent nodes, not | 3261 // As for the dominators tree we only know parent nodes, not |
3360 // children, to sum up total sizes we "bubble" node's self size | 3262 // children, to sum up total sizes we "bubble" node's self size |
3361 // adding it to all of its parents. | 3263 // adding it to all of its parents. |
3362 List<HeapEntry*>& entries = *snapshot_->entries(); | 3264 List<HeapEntry*>& entries = *snapshot_->entries(); |
3363 for (int i = 0; i < entries.length(); ++i) { | 3265 for (int i = 0; i < entries.length(); ++i) { |
3364 HeapEntry* entry = entries[i]; | 3266 HeapEntry* entry = entries[i]; |
3365 entry->set_retained_size(entry->self_size()); | 3267 entry->set_retained_size(entry->self_size()); |
3366 } | 3268 } |
3367 for (int i = 0; i < entries.length(); ++i) { | 3269 for (int i = 0; i < entries.length(); ++i) { |
3368 HeapEntry* entry = entries[i]; | 3270 HeapEntry* entry = entries[i]; |
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3600 // The buffer needs space for 7 ints, 7 commas, \n and \0 | 3502 // The buffer needs space for 7 ints, 7 commas, \n and \0 |
3601 static const int kBufferSize = | 3503 static const int kBufferSize = |
3602 MaxDecimalDigitsIn<sizeof(int)>::kSigned * 7 + 7 + 1 + 1; // NOLINT | 3504 MaxDecimalDigitsIn<sizeof(int)>::kSigned * 7 + 7 + 1 + 1; // NOLINT |
3603 EmbeddedVector<char, kBufferSize> buffer; | 3505 EmbeddedVector<char, kBufferSize> buffer; |
3604 Vector<HeapGraphEdge> children = entry->children(); | 3506 Vector<HeapGraphEdge> children = entry->children(); |
3605 int result = OS::SNPrintF(buffer, "\n,%d,%d,%d,%d,%d,%d,%d", | 3507 int result = OS::SNPrintF(buffer, "\n,%d,%d,%d,%d,%d,%d,%d", |
3606 entry->type(), | 3508 entry->type(), |
3607 GetStringId(entry->name()), | 3509 GetStringId(entry->name()), |
3608 entry->id(), | 3510 entry->id(), |
3609 entry->self_size(), | 3511 entry->self_size(), |
3610 entry->RetainedSize(false), | 3512 entry->retained_size(), |
3611 GetNodeId(entry->dominator()), | 3513 GetNodeId(entry->dominator()), |
3612 children.length()); | 3514 children.length()); |
3613 USE(result); | 3515 USE(result); |
3614 ASSERT(result != -1); | 3516 ASSERT(result != -1); |
3615 writer_->AddString(buffer.start()); | 3517 writer_->AddString(buffer.start()); |
3616 for (int i = 0; i < children.length(); ++i) { | 3518 for (int i = 0; i < children.length(); ++i) { |
3617 SerializeEdge(&children[i]); | 3519 SerializeEdge(&children[i]); |
3618 if (writer_->aborted()) return; | 3520 if (writer_->aborted()) return; |
3619 } | 3521 } |
3620 } | 3522 } |
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3796 | 3698 |
3797 | 3699 |
3798 void HeapSnapshotJSONSerializer::SortHashMap( | 3700 void HeapSnapshotJSONSerializer::SortHashMap( |
3799 HashMap* map, List<HashMap::Entry*>* sorted_entries) { | 3701 HashMap* map, List<HashMap::Entry*>* sorted_entries) { |
3800 for (HashMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) | 3702 for (HashMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) |
3801 sorted_entries->Add(p); | 3703 sorted_entries->Add(p); |
3802 sorted_entries->Sort(SortUsingEntryValue); | 3704 sorted_entries->Sort(SortUsingEntryValue); |
3803 } | 3705 } |
3804 | 3706 |
3805 } } // namespace v8::internal | 3707 } } // namespace v8::internal |
OLD | NEW |