Chromium Code Reviews

Unified 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.
Jump to:
View side-by-side diff with in-line comments
« src/profile-generator.h ('K') | « src/profile-generator.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/profile-generator.cc
diff --git a/src/profile-generator.cc b/src/profile-generator.cc
index 14349ccaa9137be6b6ad95dc3c2133daf378f96c..5591a01c9ddb107cfc34161135190bf543062f1c 100644
--- a/src/profile-generator.cc
+++ b/src/profile-generator.cc
@@ -1096,12 +1096,12 @@ const char* HeapEntry::TypeAsString() {
}
-int HeapEntry::EntriesSize(int entries_count,
+uint64_t HeapEntry::EntriesSize(int entries_count,
int children_count,
int retainers_count) {
- return sizeof(HeapEntry) * entries_count // NOLINT
- + sizeof(HeapGraphEdge) * children_count // NOLINT
- + sizeof(HeapGraphEdge*) * retainers_count; // NOLINT
+ 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
+ + (uint64_t)sizeof(HeapGraphEdge) * children_count // NOLINT
+ + (uint64_t)sizeof(HeapGraphEdge*) * retainers_count; // NOLINT
}
@@ -1114,17 +1114,51 @@ template <size_t ptr_size> struct SnapshotSizeConstants;
template <> struct SnapshotSizeConstants<4> {
static const int kExpectedHeapGraphEdgeSize = 12;
static const int kExpectedHeapEntrySize = 36;
- static const int kMaxSerializableSnapshotRawSize = 256 * MB;
+ static const size_t kMaxSerializableSnapshotRawSize = 256 * MB;
};
template <> struct SnapshotSizeConstants<8> {
static const int kExpectedHeapGraphEdgeSize = 24;
static const int kExpectedHeapEntrySize = 48;
- static const int kMaxSerializableSnapshotRawSize = 768 * MB;
+ static const size_t kMaxSerializableSnapshotRawSize = 6000ul * MB;
};
} // namespace
+class RawEntriesStorage {
+ public:
+ explicit RawEntriesStorage(size_t size) : size_(size) { }
+ ~RawEntriesStorage() {
+ for (int i = 0; i < raw_data_.length(); ++i)
+ DeleteArray(raw_data_[i]);
+ }
+ char* FirstAddress(size_t minimum_size) {
mnaganov (inactive) 2012/03/08 15:25:10 I think, you should use Address type.
+ ASSERT(raw_data_.length() == 0);
+ return AllocateNextChunk(minimum_size);
+ }
+ char* NextAddress(char* next_entry_candidate, size_t minimum_size) {
+ ASSERT(raw_data_.length());
mnaganov (inactive) 2012/03/08 15:25:10 != 0
+ 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
+ return AllocateNextChunk(minimum_size);
+ }
+ return next_entry_candidate;
+ }
+
+ private:
+ char* AllocateNextChunk(size_t minimum_size) {
+ last_chunk_size_ =
+ default_chunk_size_ > minimum_size ? default_chunk_size_ : minimum_size;
+ last_chunk_ = NewArray<char>(last_chunk_size_);
alexeif 2012/03/10 10:32:02 Can't we just change the NewArray argument to size
+ raw_data_.Add(last_chunk_);
+ return last_chunk_;
+ }
+ size_t size_;
+ size_t last_chunk_size_;
+ char* last_chunk_;
+ List<char*> raw_data_;
+ static const size_t default_chunk_size_ = 256 * MB;
+};
+
HeapSnapshot::HeapSnapshot(HeapSnapshotsCollection* collection,
HeapSnapshot::Type type,
const char* title,
@@ -1151,7 +1185,7 @@ HeapSnapshot::HeapSnapshot(HeapSnapshotsCollection* collection,
HeapSnapshot::~HeapSnapshot() {
- DeleteArray(raw_entries_);
+ delete raw_entries_;
}
@@ -1167,7 +1201,7 @@ void HeapSnapshot::AllocateEntries(int entries_count,
ASSERT(raw_entries_ == NULL);
raw_entries_size_ =
HeapEntry::EntriesSize(entries_count, children_count, retainers_count);
- raw_entries_ = NewArray<char>(raw_entries_size_);
+ raw_entries_ = new RawEntriesStorage(raw_entries_size_);
}
@@ -1225,7 +1259,8 @@ HeapEntry* HeapSnapshot::AddEntry(HeapEntry::Type type,
int size,
int children_count,
int retainers_count) {
- HeapEntry* entry = GetNextEntryToInit();
+ HeapEntry* entry = GetNextEntryToInit(
+ HeapEntry::EntriesSize(1, children_count, retainers_count));
entry->Init(this, type, name, id, size, children_count, retainers_count);
return entry;
}
@@ -1239,16 +1274,17 @@ void HeapSnapshot::SetDominatorsToSelf() {
}
-HeapEntry* HeapSnapshot::GetNextEntryToInit() {
+HeapEntry* HeapSnapshot::GetNextEntryToInit(size_t size) {
if (entries_.length() > 0) {
HeapEntry* last_entry = entries_.last();
- entries_.Add(reinterpret_cast<HeapEntry*>(
- reinterpret_cast<char*>(last_entry) + last_entry->EntrySize()));
+ HeapEntry* next_entry = reinterpret_cast<HeapEntry*>(
+ raw_entries_->NextAddress(reinterpret_cast<char*>(last_entry)
+ + last_entry->EntrySize(), size));
+ entries_.Add(next_entry);
} else {
- entries_.Add(reinterpret_cast<HeapEntry*>(raw_entries_));
+ entries_.Add(reinterpret_cast<HeapEntry*>(
+ raw_entries_->FirstAddress(size)));
}
- ASSERT(reinterpret_cast<char*>(entries_.last()) <
- (raw_entries_ + raw_entries_size_));
return entries_.last();
}
@@ -3437,7 +3473,7 @@ HeapSnapshot* HeapSnapshotJSONSerializer::CreateFakeSnapshot() {
const char* text = snapshot_->collection()->names()->GetFormatted(
"The snapshot is too big. "
"Maximum snapshot size is %d MB. "
mnaganov (inactive) 2012/03/08 15:25:10 Is %d the correct type?
- "Actual snapshot size is %d MB.",
+ "Actual snapshot size is %u MB.",
alexeif 2012/03/10 10:32:02 if raw_entries_size() is uint64_t then it should b
SnapshotSizeConstants<kPointerSize>::kMaxSerializableSnapshotRawSize / MB,
(snapshot_->raw_entries_size() + MB - 1) / MB);
HeapEntry* message = result->AddEntry(
« src/profile-generator.h ('K') | « src/profile-generator.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine