Commit b00fc8be authored by ulan's avatar ulan Committed by Commit bot

Use std::deque for storing edges and children in heap snapshot.

This patch fixes OOM crash that happens for large heap where
the total size of edges exceeds 2GB, which is the hard limit
for v8::internal::List allocated using tcmalloc.

BUG=chromium:675911

Review-Url: https://codereview.chromium.org/2595003002
Cr-Commit-Position: refs/heads/master@{#42004}
parent a93aab37
......@@ -9549,13 +9549,12 @@ size_t HeapGraphNode::GetShallowSize() const {
int HeapGraphNode::GetChildrenCount() const {
return ToInternal(this)->children().length();
return ToInternal(this)->children_count();
}
const HeapGraphEdge* HeapGraphNode::GetChild(int index) const {
return reinterpret_cast<const HeapGraphEdge*>(
ToInternal(this)->children()[index]);
return reinterpret_cast<const HeapGraphEdge*>(ToInternal(this)->child(index));
}
......
......@@ -38,13 +38,17 @@ int HeapEntry::set_children_index(int index) {
return next_index;
}
HeapGraphEdge** HeapEntry::children_arr() {
std::deque<HeapGraphEdge*>::iterator HeapEntry::children_begin() {
DCHECK(children_index_ >= 0);
SLOW_DCHECK(children_index_ < snapshot_->children().length() ||
(children_index_ == snapshot_->children().length() &&
SLOW_DCHECK(
children_index_ < static_cast<int>(snapshot_->children().size()) ||
(children_index_ == static_cast<int>(snapshot_->children().size()) &&
children_count_ == 0));
return &snapshot_->children().first() + children_index_;
return snapshot_->children().begin() + children_index_;
}
std::deque<HeapGraphEdge*>::iterator HeapEntry::children_end() {
return children_begin() + children_count_;
}
......
......@@ -63,7 +63,7 @@ void HeapEntry::SetNamedReference(HeapGraphEdge::Type type,
const char* name,
HeapEntry* entry) {
HeapGraphEdge edge(type, name, this->index(), entry->index());
snapshot_->edges().Add(edge);
snapshot_->edges().push_back(edge);
++children_count_;
}
......@@ -72,7 +72,7 @@ void HeapEntry::SetIndexedReference(HeapGraphEdge::Type type,
int index,
HeapEntry* entry) {
HeapGraphEdge edge(type, index, this->index(), entry->index());
snapshot_->edges().Add(edge);
snapshot_->edges().push_back(edge);
++children_count_;
}
......@@ -97,9 +97,8 @@ void HeapEntry::Print(
base::OS::Print("\"\n");
}
if (--max_depth == 0) return;
Vector<HeapGraphEdge*> ch = children();
for (int i = 0; i < ch.length(); ++i) {
HeapGraphEdge& edge = *ch[i];
for (auto i = children_begin(); i != children_end(); ++i) {
HeapGraphEdge& edge = **i;
const char* edge_prefix = "";
EmbeddedVector<char, 64> index;
const char* edge_name = index.start();
......@@ -270,15 +269,15 @@ HeapEntry* HeapSnapshot::AddEntry(HeapEntry::Type type,
void HeapSnapshot::FillChildren() {
DCHECK(children().is_empty());
children().Allocate(edges().length());
DCHECK(children().empty());
children().resize(edges().size());
int children_index = 0;
for (int i = 0; i < entries().length(); ++i) {
HeapEntry* entry = &entries()[i];
children_index = entry->set_children_index(children_index);
}
DCHECK(edges().length() == children_index);
for (int i = 0; i < edges().length(); ++i) {
DCHECK_EQ(edges().size(), static_cast<size_t>(children_index));
for (size_t i = 0; i < edges().size(); ++i) {
HeapGraphEdge* edge = &edges()[i];
edge->ReplaceToIndexWithEntry(this);
edge->from()->add_child(edge);
......@@ -335,12 +334,10 @@ void HeapSnapshot::Print(int max_depth) {
size_t HeapSnapshot::RawSnapshotSize() const {
return
sizeof(*this) +
GetMemoryUsedByList(entries_) +
GetMemoryUsedByList(edges_) +
GetMemoryUsedByList(children_) +
GetMemoryUsedByList(sorted_entries_);
return sizeof(*this) + GetMemoryUsedByList(entries_) +
edges_.size() * sizeof(decltype(edges_)::value_type) +
children_.size() * sizeof(decltype(children_)::value_type) +
GetMemoryUsedByList(sorted_entries_);
}
......@@ -2797,8 +2794,8 @@ void HeapSnapshotJSONSerializer::SerializeEdge(HeapGraphEdge* edge,
void HeapSnapshotJSONSerializer::SerializeEdges() {
List<HeapGraphEdge*>& edges = snapshot_->children();
for (int i = 0; i < edges.length(); ++i) {
std::deque<HeapGraphEdge*>& edges = snapshot_->children();
for (size_t i = 0; i < edges.size(); ++i) {
DCHECK(i == 0 ||
edges[i - 1]->from()->index() <= edges[i]->from()->index());
SerializeEdge(edges[i], i == 0);
......@@ -2916,7 +2913,7 @@ void HeapSnapshotJSONSerializer::SerializeSnapshot() {
writer_->AddString(",\"node_count\":");
writer_->AddNumber(snapshot_->entries().length());
writer_->AddString(",\"edge_count\":");
writer_->AddNumber(snapshot_->edges().length());
writer_->AddNumber(static_cast<double>(snapshot_->edges().size()));
writer_->AddString(",\"trace_function_count\":");
uint32_t count = 0;
AllocationTracker* tracker = snapshot_->profiler()->allocation_tracker();
......
......@@ -5,6 +5,7 @@
#ifndef V8_PROFILER_HEAP_SNAPSHOT_GENERATOR_H_
#define V8_PROFILER_HEAP_SNAPSHOT_GENERATOR_H_
#include <deque>
#include <unordered_map>
#include "include/v8-profiler.h"
......@@ -115,10 +116,9 @@ class HeapEntry BASE_EMBEDDED {
int children_count() const { return children_count_; }
INLINE(int set_children_index(int index));
void add_child(HeapGraphEdge* edge) {
children_arr()[children_count_++] = edge;
*(children_begin() + children_count_++) = edge;
}
Vector<HeapGraphEdge*> children() {
return Vector<HeapGraphEdge*>(children_arr(), children_count_); }
HeapGraphEdge* child(int i) { return *(children_begin() + i); }
INLINE(Isolate* isolate() const);
void SetIndexedReference(
......@@ -130,7 +130,8 @@ class HeapEntry BASE_EMBEDDED {
const char* prefix, const char* edge_name, int max_depth, int indent);
private:
INLINE(HeapGraphEdge** children_arr());
INLINE(std::deque<HeapGraphEdge*>::iterator children_begin());
INLINE(std::deque<HeapGraphEdge*>::iterator children_end());
const char* TypeAsString();
unsigned type_: 4;
......@@ -163,8 +164,8 @@ class HeapSnapshot {
return &entries_[gc_subroot_indexes_[index]];
}
List<HeapEntry>& entries() { return entries_; }
List<HeapGraphEdge>& edges() { return edges_; }
List<HeapGraphEdge*>& children() { return children_; }
std::deque<HeapGraphEdge>& edges() { return edges_; }
std::deque<HeapGraphEdge*>& children() { return children_; }
void RememberLastJSObjectId();
SnapshotObjectId max_snapshot_js_object_id() const {
return max_snapshot_js_object_id_;
......@@ -192,8 +193,8 @@ class HeapSnapshot {
int gc_roots_index_;
int gc_subroot_indexes_[VisitorSynchronization::kNumberOfSyncTags];
List<HeapEntry> entries_;
List<HeapGraphEdge> edges_;
List<HeapGraphEdge*> children_;
std::deque<HeapGraphEdge> edges_;
std::deque<HeapGraphEdge*> children_;
List<HeapEntry*> sorted_entries_;
SnapshotObjectId max_snapshot_js_object_id_;
......
......@@ -69,10 +69,10 @@ class NamedEntriesDetector {
CheckEntry(root);
while (!list.is_empty()) {
i::HeapEntry* entry = list.RemoveLast();
i::Vector<i::HeapGraphEdge*> children = entry->children();
for (int i = 0; i < children.length(); ++i) {
if (children[i]->type() == i::HeapGraphEdge::kShortcut) continue;
i::HeapEntry* child = children[i]->to();
for (int i = 0; i < entry->children_count(); ++i) {
i::HeapGraphEdge* edge = entry->child(i);
if (edge->type() == i::HeapGraphEdge::kShortcut) continue;
i::HeapEntry* child = edge->to();
v8::base::HashMap::Entry* entry = visited.LookupOrInsert(
reinterpret_cast<void*>(child),
static_cast<uint32_t>(reinterpret_cast<uintptr_t>(child)));
......@@ -137,8 +137,8 @@ static bool ValidateSnapshot(const v8::HeapSnapshot* snapshot, int depth = 3) {
reinterpret_cast<const i::HeapSnapshot*>(snapshot));
v8::base::HashMap visited;
i::List<i::HeapGraphEdge>& edges = heap_snapshot->edges();
for (int i = 0; i < edges.length(); ++i) {
std::deque<i::HeapGraphEdge>& edges = heap_snapshot->edges();
for (size_t i = 0; i < edges.size(); ++i) {
v8::base::HashMap::Entry* entry = visited.LookupOrInsert(
reinterpret_cast<void*>(edges[i].to()),
static_cast<uint32_t>(reinterpret_cast<uintptr_t>(edges[i].to())));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment