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

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

Issue 9632020: V8 crashes when profile generator is trying to allocate a raw_entries_ buffer more than 2Gb. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 8 years, 9 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
« src/profile-generator.h ('K') | « src/profile-generator.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 1078 matching lines...) Expand 10 before | Expand all | Expand 10 after
1089 case kArray: return "/array/"; 1089 case kArray: return "/array/";
1090 case kRegExp: return "/regexp/"; 1090 case kRegExp: return "/regexp/";
1091 case kHeapNumber: return "/number/"; 1091 case kHeapNumber: return "/number/";
1092 case kNative: return "/native/"; 1092 case kNative: return "/native/";
1093 case kSynthetic: return "/synthetic/"; 1093 case kSynthetic: return "/synthetic/";
1094 default: return "???"; 1094 default: return "???";
1095 } 1095 }
1096 } 1096 }
1097 1097
1098 1098
1099 int HeapEntry::EntriesSize(int entries_count, 1099 uint64_t HeapEntry::EntriesSize(int entries_count,
1100 int children_count, 1100 int children_count,
1101 int retainers_count) { 1101 int retainers_count) {
1102 return sizeof(HeapEntry) * entries_count // NOLINT 1102 return (uint64_t)sizeof(HeapEntry) * entries_count // NOLINT
mnaganov (inactive) 2012/03/08 15:25:10 Please, use static_cast.
alexeif 2012/03/10 10:32:02 There's no need to use casts here. sizeof has the
1103 + sizeof(HeapGraphEdge) * children_count // NOLINT 1103 + (uint64_t)sizeof(HeapGraphEdge) * children_count // NOLINT
1104 + sizeof(HeapGraphEdge*) * retainers_count; // NOLINT 1104 + (uint64_t)sizeof(HeapGraphEdge*) * retainers_count; // NOLINT
1105 } 1105 }
1106 1106
1107 1107
1108 // 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
1109 // as small as possible. 1109 // as small as possible.
1110 namespace { // Avoid littering the global namespace. 1110 namespace { // Avoid littering the global namespace.
1111 1111
1112 template <size_t ptr_size> struct SnapshotSizeConstants; 1112 template <size_t ptr_size> struct SnapshotSizeConstants;
1113 1113
1114 template <> struct SnapshotSizeConstants<4> { 1114 template <> struct SnapshotSizeConstants<4> {
1115 static const int kExpectedHeapGraphEdgeSize = 12; 1115 static const int kExpectedHeapGraphEdgeSize = 12;
1116 static const int kExpectedHeapEntrySize = 36; 1116 static const int kExpectedHeapEntrySize = 36;
1117 static const int kMaxSerializableSnapshotRawSize = 256 * MB; 1117 static const size_t kMaxSerializableSnapshotRawSize = 256 * MB;
1118 }; 1118 };
1119 1119
1120 template <> struct SnapshotSizeConstants<8> { 1120 template <> struct SnapshotSizeConstants<8> {
1121 static const int kExpectedHeapGraphEdgeSize = 24; 1121 static const int kExpectedHeapGraphEdgeSize = 24;
1122 static const int kExpectedHeapEntrySize = 48; 1122 static const int kExpectedHeapEntrySize = 48;
1123 static const int kMaxSerializableSnapshotRawSize = 768 * MB; 1123 static const size_t kMaxSerializableSnapshotRawSize = 6000ul * MB;
1124 }; 1124 };
1125 1125
1126 } // namespace 1126 } // namespace
1127 1127
1128 class RawEntriesStorage {
1129 public:
1130 explicit RawEntriesStorage(size_t size) : size_(size) { }
1131 ~RawEntriesStorage() {
1132 for (int i = 0; i < raw_data_.length(); ++i)
1133 DeleteArray(raw_data_[i]);
1134 }
1135 char* FirstAddress(size_t minimum_size) {
mnaganov (inactive) 2012/03/08 15:25:10 I think, you should use Address type.
1136 ASSERT(raw_data_.length() == 0);
1137 return AllocateNextChunk(minimum_size);
1138 }
1139 char* NextAddress(char* next_entry_candidate, size_t minimum_size) {
1140 ASSERT(raw_data_.length());
mnaganov (inactive) 2012/03/08 15:25:10 != 0
1141 if (next_entry_candidate - last_chunk_ + minimum_size > last_chunk_size_) {
mnaganov (inactive) 2012/03/08 15:25:10 Note: Please verify that expressions like these co
1142 return AllocateNextChunk(minimum_size);
1143 }
1144 return next_entry_candidate;
1145 }
1146
1147 private:
1148 char* AllocateNextChunk(size_t minimum_size) {
1149 last_chunk_size_ =
1150 default_chunk_size_ > minimum_size ? default_chunk_size_ : minimum_size;
1151 last_chunk_ = NewArray<char>(last_chunk_size_);
alexeif 2012/03/10 10:32:02 Can't we just change the NewArray argument to size
1152 raw_data_.Add(last_chunk_);
1153 return last_chunk_;
1154 }
1155 size_t size_;
1156 size_t last_chunk_size_;
1157 char* last_chunk_;
1158 List<char*> raw_data_;
1159 static const size_t default_chunk_size_ = 256 * MB;
1160 };
1161
1128 HeapSnapshot::HeapSnapshot(HeapSnapshotsCollection* collection, 1162 HeapSnapshot::HeapSnapshot(HeapSnapshotsCollection* collection,
1129 HeapSnapshot::Type type, 1163 HeapSnapshot::Type type,
1130 const char* title, 1164 const char* title,
1131 unsigned uid) 1165 unsigned uid)
1132 : collection_(collection), 1166 : collection_(collection),
1133 type_(type), 1167 type_(type),
1134 title_(title), 1168 title_(title),
1135 uid_(uid), 1169 uid_(uid),
1136 root_entry_(NULL), 1170 root_entry_(NULL),
1137 gc_roots_entry_(NULL), 1171 gc_roots_entry_(NULL),
1138 natives_root_entry_(NULL), 1172 natives_root_entry_(NULL),
1139 raw_entries_(NULL), 1173 raw_entries_(NULL),
1140 entries_sorted_(false) { 1174 entries_sorted_(false) {
1141 STATIC_ASSERT( 1175 STATIC_ASSERT(
1142 sizeof(HeapGraphEdge) == 1176 sizeof(HeapGraphEdge) ==
1143 SnapshotSizeConstants<kPointerSize>::kExpectedHeapGraphEdgeSize); 1177 SnapshotSizeConstants<kPointerSize>::kExpectedHeapGraphEdgeSize);
1144 STATIC_ASSERT( 1178 STATIC_ASSERT(
1145 sizeof(HeapEntry) == 1179 sizeof(HeapEntry) ==
1146 SnapshotSizeConstants<kPointerSize>::kExpectedHeapEntrySize); 1180 SnapshotSizeConstants<kPointerSize>::kExpectedHeapEntrySize);
1147 for (int i = 0; i < VisitorSynchronization::kNumberOfSyncTags; ++i) { 1181 for (int i = 0; i < VisitorSynchronization::kNumberOfSyncTags; ++i) {
1148 gc_subroot_entries_[i] = NULL; 1182 gc_subroot_entries_[i] = NULL;
1149 } 1183 }
1150 } 1184 }
1151 1185
1152 1186
1153 HeapSnapshot::~HeapSnapshot() { 1187 HeapSnapshot::~HeapSnapshot() {
1154 DeleteArray(raw_entries_); 1188 delete raw_entries_;
1155 } 1189 }
1156 1190
1157 1191
1158 void HeapSnapshot::Delete() { 1192 void HeapSnapshot::Delete() {
1159 collection_->RemoveSnapshot(this); 1193 collection_->RemoveSnapshot(this);
1160 delete this; 1194 delete this;
1161 } 1195 }
1162 1196
1163 1197
1164 void HeapSnapshot::AllocateEntries(int entries_count, 1198 void HeapSnapshot::AllocateEntries(int entries_count,
1165 int children_count, 1199 int children_count,
1166 int retainers_count) { 1200 int retainers_count) {
1167 ASSERT(raw_entries_ == NULL); 1201 ASSERT(raw_entries_ == NULL);
1168 raw_entries_size_ = 1202 raw_entries_size_ =
1169 HeapEntry::EntriesSize(entries_count, children_count, retainers_count); 1203 HeapEntry::EntriesSize(entries_count, children_count, retainers_count);
1170 raw_entries_ = NewArray<char>(raw_entries_size_); 1204 raw_entries_ = new RawEntriesStorage(raw_entries_size_);
1171 } 1205 }
1172 1206
1173 1207
1174 static void HeapEntryClearPaint(HeapEntry** entry_ptr) { 1208 static void HeapEntryClearPaint(HeapEntry** entry_ptr) {
1175 (*entry_ptr)->clear_paint(); 1209 (*entry_ptr)->clear_paint();
1176 } 1210 }
1177 1211
1178 1212
1179 void HeapSnapshot::ClearPaint() { 1213 void HeapSnapshot::ClearPaint() {
1180 entries_.Iterate(HeapEntryClearPaint); 1214 entries_.Iterate(HeapEntryClearPaint);
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
1218 retainers_count)); 1252 retainers_count));
1219 } 1253 }
1220 1254
1221 1255
1222 HeapEntry* HeapSnapshot::AddEntry(HeapEntry::Type type, 1256 HeapEntry* HeapSnapshot::AddEntry(HeapEntry::Type type,
1223 const char* name, 1257 const char* name,
1224 uint64_t id, 1258 uint64_t id,
1225 int size, 1259 int size,
1226 int children_count, 1260 int children_count,
1227 int retainers_count) { 1261 int retainers_count) {
1228 HeapEntry* entry = GetNextEntryToInit(); 1262 HeapEntry* entry = GetNextEntryToInit(
1263 HeapEntry::EntriesSize(1, children_count, retainers_count));
1229 entry->Init(this, type, name, id, size, children_count, retainers_count); 1264 entry->Init(this, type, name, id, size, children_count, retainers_count);
1230 return entry; 1265 return entry;
1231 } 1266 }
1232 1267
1233 1268
1234 void HeapSnapshot::SetDominatorsToSelf() { 1269 void HeapSnapshot::SetDominatorsToSelf() {
1235 for (int i = 0; i < entries_.length(); ++i) { 1270 for (int i = 0; i < entries_.length(); ++i) {
1236 HeapEntry* entry = entries_[i]; 1271 HeapEntry* entry = entries_[i];
1237 if (entry->dominator() == NULL) entry->set_dominator(entry); 1272 if (entry->dominator() == NULL) entry->set_dominator(entry);
1238 } 1273 }
1239 } 1274 }
1240 1275
1241 1276
1242 HeapEntry* HeapSnapshot::GetNextEntryToInit() { 1277 HeapEntry* HeapSnapshot::GetNextEntryToInit(size_t size) {
1243 if (entries_.length() > 0) { 1278 if (entries_.length() > 0) {
1244 HeapEntry* last_entry = entries_.last(); 1279 HeapEntry* last_entry = entries_.last();
1280 HeapEntry* next_entry = reinterpret_cast<HeapEntry*>(
1281 raw_entries_->NextAddress(reinterpret_cast<char*>(last_entry)
1282 + last_entry->EntrySize(), size));
1283 entries_.Add(next_entry);
1284 } else {
1245 entries_.Add(reinterpret_cast<HeapEntry*>( 1285 entries_.Add(reinterpret_cast<HeapEntry*>(
1246 reinterpret_cast<char*>(last_entry) + last_entry->EntrySize())); 1286 raw_entries_->FirstAddress(size)));
1247 } else {
1248 entries_.Add(reinterpret_cast<HeapEntry*>(raw_entries_));
1249 } 1287 }
1250 ASSERT(reinterpret_cast<char*>(entries_.last()) <
1251 (raw_entries_ + raw_entries_size_));
1252 return entries_.last(); 1288 return entries_.last();
1253 } 1289 }
1254 1290
1255 1291
1256 HeapEntry* HeapSnapshot::GetEntryById(uint64_t id) { 1292 HeapEntry* HeapSnapshot::GetEntryById(uint64_t id) {
1257 List<HeapEntry*>* entries_by_id = GetSortedEntriesList(); 1293 List<HeapEntry*>* entries_by_id = GetSortedEntriesList();
1258 1294
1259 // Perform a binary search by id. 1295 // Perform a binary search by id.
1260 int low = 0; 1296 int low = 0;
1261 int high = entries_by_id->length() - 1; 1297 int high = entries_by_id->length() - 1;
(...skipping 2167 matching lines...) Expand 10 before | Expand all | Expand 10 after
3429 3465
3430 HeapSnapshot* HeapSnapshotJSONSerializer::CreateFakeSnapshot() { 3466 HeapSnapshot* HeapSnapshotJSONSerializer::CreateFakeSnapshot() {
3431 HeapSnapshot* result = new HeapSnapshot(snapshot_->collection(), 3467 HeapSnapshot* result = new HeapSnapshot(snapshot_->collection(),
3432 HeapSnapshot::kFull, 3468 HeapSnapshot::kFull,
3433 snapshot_->title(), 3469 snapshot_->title(),
3434 snapshot_->uid()); 3470 snapshot_->uid());
3435 result->AllocateEntries(2, 1, 0); 3471 result->AllocateEntries(2, 1, 0);
3436 HeapEntry* root = result->AddRootEntry(1); 3472 HeapEntry* root = result->AddRootEntry(1);
3437 const char* text = snapshot_->collection()->names()->GetFormatted( 3473 const char* text = snapshot_->collection()->names()->GetFormatted(
3438 "The snapshot is too big. " 3474 "The snapshot is too big. "
3439 "Maximum snapshot size is %d MB. " 3475 "Maximum snapshot size is %d MB. "
mnaganov (inactive) 2012/03/08 15:25:10 Is %d the correct type?
3440 "Actual snapshot size is %d MB.", 3476 "Actual snapshot size is %u MB.",
alexeif 2012/03/10 10:32:02 if raw_entries_size() is uint64_t then it should b
3441 SnapshotSizeConstants<kPointerSize>::kMaxSerializableSnapshotRawSize / MB, 3477 SnapshotSizeConstants<kPointerSize>::kMaxSerializableSnapshotRawSize / MB,
3442 (snapshot_->raw_entries_size() + MB - 1) / MB); 3478 (snapshot_->raw_entries_size() + MB - 1) / MB);
3443 HeapEntry* message = result->AddEntry( 3479 HeapEntry* message = result->AddEntry(
3444 HeapEntry::kString, text, 0, 4, 0, 0); 3480 HeapEntry::kString, text, 0, 4, 0, 0);
3445 root->SetUnidirElementReference(0, 1, message); 3481 root->SetUnidirElementReference(0, 1, message);
3446 result->SetDominatorsToSelf(); 3482 result->SetDominatorsToSelf();
3447 return result; 3483 return result;
3448 } 3484 }
3449 3485
3450 3486
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after
3734 3770
3735 3771
3736 void HeapSnapshotJSONSerializer::SortHashMap( 3772 void HeapSnapshotJSONSerializer::SortHashMap(
3737 HashMap* map, List<HashMap::Entry*>* sorted_entries) { 3773 HashMap* map, List<HashMap::Entry*>* sorted_entries) {
3738 for (HashMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) 3774 for (HashMap::Entry* p = map->Start(); p != NULL; p = map->Next(p))
3739 sorted_entries->Add(p); 3775 sorted_entries->Add(p);
3740 sorted_entries->Sort(SortUsingEntryValue); 3776 sorted_entries->Sort(SortUsingEntryValue);
3741 } 3777 }
3742 3778
3743 } } // namespace v8::internal 3779 } } // namespace v8::internal
OLDNEW
« src/profile-generator.h ('K') | « src/profile-generator.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698