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

Unified 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: Addressing comments. 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/profile-generator.h ('k') | src/profile-generator-inl.h » ('j') | 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 c91e83bb78fe37cc2c75933e297e2f70a1c788d6..2c6c6e395c2793f84cf1fee8f328b8cd72ae5ed5 100644
--- a/src/profile-generator.cc
+++ b/src/profile-generator.cc
@@ -931,78 +931,72 @@ void ProfileGenerator::RecordTickSample(const TickSample& sample) {
}
-void HeapGraphEdge::Init(
- int child_index, Type type, const char* name, HeapEntry* to) {
+HeapGraphEdge::HeapGraphEdge(
+ Type type, const char* name, int from, int to) :
+ type_(type),
+ from_index_(from),
+ to_index_(to),
+ name_(name) {
ASSERT(type == kContextVariable
- || type == kProperty
- || type == kInternal
- || type == kShortcut);
- child_index_ = child_index;
- type_ = type;
- name_ = name;
- to_ = to;
+ || type == kProperty
+ || type == kInternal
+ || type == kShortcut);
}
-void HeapGraphEdge::Init(int child_index, Type type, int index, HeapEntry* to) {
+HeapGraphEdge::HeapGraphEdge(Type type, int index, int from, int to) :
+ type_(type),
+ from_index_(from),
+ to_index_(to),
+ index_(index) {
ASSERT(type == kElement || type == kHidden || type == kWeak);
- child_index_ = child_index;
- type_ = type;
- index_ = index;
- to_ = to;
}
-void HeapGraphEdge::Init(int child_index, int index, HeapEntry* to) {
- Init(child_index, kElement, index, to);
+void HeapGraphEdge::ReplaceToIndexWithEntry(HeapSnapshot* snapshot) {
+ to_entry_ = &snapshot->entries()[to_index_];
}
-void HeapEntry::Init(HeapSnapshot* snapshot,
+const int HeapEntry::kNoEntry = -1;
+
+HeapEntry::HeapEntry(HeapSnapshot* snapshot,
Type type,
const char* name,
SnapshotObjectId id,
- int self_size,
- int children_count,
- int retainers_count) {
- snapshot_ = snapshot;
- type_ = type;
- painted_ = false;
- user_reachable_ = false;
- name_ = name;
- self_size_ = self_size;
- retained_size_ = 0;
- entry_index_ = -1;
- children_count_ = children_count;
- retainers_count_ = retainers_count;
- dominator_ = NULL;
- id_ = id;
-}
+ int self_size) :
+ painted_(false),
+ user_reachable_(false),
+ dominator_(kNoEntry),
+ type_(type),
+ retainers_count_(0),
+ retainers_index_(-1),
+ children_count_(0),
+ children_index_(-1),
+ self_size_(self_size),
+ retained_size_(0),
+ id_(id),
+ snapshot_(snapshot),
+ name_(name) { }
void HeapEntry::SetNamedReference(HeapGraphEdge::Type type,
- int child_index,
const char* name,
- HeapEntry* entry,
- int retainer_index) {
- children()[child_index].Init(child_index, type, name, entry);
- entry->retainers()[retainer_index] = children_arr() + child_index;
+ HeapEntry* entry) {
+ HeapGraphEdge edge(type, name, this->index(), entry->index());
+ snapshot_->edges().Add(edge);
+ ++children_count_;
+ ++entry->retainers_count_;
}
void HeapEntry::SetIndexedReference(HeapGraphEdge::Type type,
- int child_index,
int index,
- HeapEntry* entry,
- int retainer_index) {
- children()[child_index].Init(child_index, type, index, entry);
- entry->retainers()[retainer_index] = children_arr() + child_index;
-}
-
-
-void HeapEntry::SetUnidirElementReference(
- int child_index, int index, HeapEntry* entry) {
- children()[child_index].Init(child_index, index, entry);
+ HeapEntry* entry) {
+ HeapGraphEdge edge(type, index, this->index(), entry->index());
+ snapshot_->edges().Add(edge);
+ ++children_count_;
+ ++entry->retainers_count_;
}
@@ -1013,7 +1007,8 @@ Handle<HeapObject> HeapEntry::GetHeapObject() {
void HeapEntry::Print(
const char* prefix, const char* edge_name, int max_depth, int indent) {
- OS::Print("%6d %7d @%6llu %*c %s%s: ",
+ STATIC_CHECK(sizeof(unsigned) == sizeof(id()));
+ OS::Print("%6d %7d @%6u %*c %s%s: ",
self_size(), retained_size(), id(),
indent, ' ', prefix, edge_name);
if (type() != kString) {
@@ -1031,9 +1026,9 @@ void HeapEntry::Print(
OS::Print("\"\n");
}
if (--max_depth == 0) return;
- Vector<HeapGraphEdge> ch = children();
+ Vector<HeapGraphEdge*> ch = children();
for (int i = 0; i < ch.length(); ++i) {
- HeapGraphEdge& edge = ch[i];
+ HeapGraphEdge& edge = *ch[i];
const char* edge_prefix = "";
EmbeddedVector<char, 64> index;
const char* edge_name = index.start();
@@ -1089,15 +1084,6 @@ const char* HeapEntry::TypeAsString() {
}
-size_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
-}
-
-
// It is very important to keep objects that form a heap snapshot
// as small as possible.
namespace { // Avoid littering the global namespace.
@@ -1106,7 +1092,7 @@ template <size_t ptr_size> struct SnapshotSizeConstants;
template <> struct SnapshotSizeConstants<4> {
static const int kExpectedHeapGraphEdgeSize = 12;
- static const int kExpectedHeapEntrySize = 36;
+ static const int kExpectedHeapEntrySize = 40;
static const size_t kMaxSerializableSnapshotRawSize = 256 * MB;
};
@@ -1127,11 +1113,9 @@ HeapSnapshot::HeapSnapshot(HeapSnapshotsCollection* collection,
type_(type),
title_(title),
uid_(uid),
- root_entry_(NULL),
- gc_roots_entry_(NULL),
- natives_root_entry_(NULL),
- raw_entries_(NULL),
- number_of_edges_(0),
+ root_index_(HeapEntry::kNoEntry),
+ gc_roots_index_(HeapEntry::kNoEntry),
+ natives_root_index_(HeapEntry::kNoEntry),
max_snapshot_js_object_id_(0) {
STATIC_CHECK(
sizeof(HeapGraphEdge) ==
@@ -1140,16 +1124,11 @@ HeapSnapshot::HeapSnapshot(HeapSnapshotsCollection* collection,
sizeof(HeapEntry) ==
SnapshotSizeConstants<kPointerSize>::kExpectedHeapEntrySize);
for (int i = 0; i < VisitorSynchronization::kNumberOfSyncTags; ++i) {
- gc_subroot_entries_[i] = NULL;
+ gc_subroot_indexes_[i] = HeapEntry::kNoEntry;
}
}
-HeapSnapshot::~HeapSnapshot() {
- DeleteArray(raw_entries_);
-}
-
-
void HeapSnapshot::Delete() {
collection_->RemoveSnapshot(this);
delete this;
@@ -1161,19 +1140,8 @@ void HeapSnapshot::RememberLastJSObjectId() {
}
-void HeapSnapshot::AllocateEntries(int entries_count,
- int children_count,
- int retainers_count) {
- ASSERT(raw_entries_ == NULL);
- number_of_edges_ = children_count;
- raw_entries_size_ =
- HeapEntry::EntriesSize(entries_count, children_count, retainers_count);
- raw_entries_ = NewArray<char>(raw_entries_size_);
-}
-
-
-static void HeapEntryClearPaint(HeapEntry** entry_ptr) {
- (*entry_ptr)->clear_paint();
+static void HeapEntryClearPaint(HeapEntry* entry_ptr) {
+ entry_ptr->clear_paint();
}
@@ -1182,76 +1150,80 @@ void HeapSnapshot::ClearPaint() {
}
-HeapEntry* HeapSnapshot::AddRootEntry(int children_count) {
- ASSERT(root_entry_ == NULL);
+HeapEntry* HeapSnapshot::AddRootEntry() {
+ ASSERT(root_index_ == HeapEntry::kNoEntry);
ASSERT(entries_.is_empty()); // Root entry must be the first one.
- return (root_entry_ = AddEntry(HeapEntry::kObject,
- "",
- HeapObjectsMap::kInternalRootObjectId,
- 0,
- children_count,
- 0));
+ HeapEntry* entry = AddEntry(HeapEntry::kObject,
+ "",
+ HeapObjectsMap::kInternalRootObjectId,
+ 0);
+ root_index_ = entry->index();
+ ASSERT(root_index_ == 0);
+ return entry;
}
-HeapEntry* HeapSnapshot::AddGcRootsEntry(int children_count,
- int retainers_count) {
- ASSERT(gc_roots_entry_ == NULL);
- return (gc_roots_entry_ = AddEntry(HeapEntry::kObject,
- "(GC roots)",
- HeapObjectsMap::kGcRootsObjectId,
- 0,
- children_count,
- retainers_count));
+HeapEntry* HeapSnapshot::AddGcRootsEntry() {
+ ASSERT(gc_roots_index_ == HeapEntry::kNoEntry);
+ HeapEntry* entry = AddEntry(HeapEntry::kObject,
+ "(GC roots)",
+ HeapObjectsMap::kGcRootsObjectId,
+ 0);
+ gc_roots_index_ = entry->index();
+ return entry;
}
-HeapEntry* HeapSnapshot::AddGcSubrootEntry(int tag,
- int children_count,
- int retainers_count) {
- ASSERT(gc_subroot_entries_[tag] == NULL);
+HeapEntry* HeapSnapshot::AddGcSubrootEntry(int tag) {
+ ASSERT(gc_subroot_indexes_[tag] == HeapEntry::kNoEntry);
ASSERT(0 <= tag && tag < VisitorSynchronization::kNumberOfSyncTags);
- return (gc_subroot_entries_[tag] = AddEntry(
+ HeapEntry* entry = AddEntry(
HeapEntry::kObject,
VisitorSynchronization::kTagNames[tag],
HeapObjectsMap::GetNthGcSubrootId(tag),
- 0,
- children_count,
- retainers_count));
+ 0);
+ gc_subroot_indexes_[tag] = entry->index();
+ return entry;
}
HeapEntry* HeapSnapshot::AddEntry(HeapEntry::Type type,
const char* name,
SnapshotObjectId id,
- int size,
- int children_count,
- int retainers_count) {
- HeapEntry* entry = GetNextEntryToInit();
- entry->Init(this, type, name, id, size, children_count, retainers_count);
- return entry;
+ int size) {
+ HeapEntry entry(this, type, name, id, size);
+ entries_.Add(entry);
+ return &entries_.last();
}
-void HeapSnapshot::SetDominatorsToSelf() {
- for (int i = 0; i < entries_.length(); ++i) {
- HeapEntry* entry = entries_[i];
- if (entry->dominator() == NULL) entry->set_dominator(entry);
+void HeapSnapshot::FillChildrenAndRetainers() {
+ ASSERT(children().is_empty());
+ children().Allocate(edges().length());
+ ASSERT(retainers().is_empty());
+ retainers().Allocate(edges().length());
+ int children_index = 0;
+ int retainers_index = 0;
+ for (int i = 0; i < entries().length(); ++i) {
+ HeapEntry* entry = &entries()[i];
+ children_index = entry->set_children_index(children_index);
+ retainers_index = entry->set_retainers_index(retainers_index);
+ }
+ ASSERT(edges().length() == children_index);
+ ASSERT(edges().length() == retainers_index);
+ for (int i = 0; i < edges().length(); ++i) {
+ HeapGraphEdge* edge = &edges()[i];
+ edge->ReplaceToIndexWithEntry(this);
+ edge->from()->add_child(edge);
+ edge->to()->add_retainer(edge);
}
}
-HeapEntry* HeapSnapshot::GetNextEntryToInit() {
- if (entries_.length() > 0) {
- HeapEntry* last_entry = entries_.last();
- entries_.Add(reinterpret_cast<HeapEntry*>(
- reinterpret_cast<char*>(last_entry) + last_entry->EntrySize()));
- } else {
- entries_.Add(reinterpret_cast<HeapEntry*>(raw_entries_));
+void HeapSnapshot::SetDominatorsToSelf() {
+ for (int i = 0; i < entries_.length(); ++i) {
+ entries_[i].set_dominator(&entries_[i]);
}
- ASSERT(reinterpret_cast<char*>(entries_.last()) <
- (raw_entries_ + raw_entries_size_));
- return entries_.last();
}
@@ -1287,7 +1259,10 @@ static int SortByIds(const T* entry1_ptr,
List<HeapEntry*>* HeapSnapshot::GetSortedEntriesList() {
if (sorted_entries_.is_empty()) {
- sorted_entries_.AddAll(entries_);
+ sorted_entries_.Allocate(entries_.length());
+ for (int i = 0; i < entries_.length(); ++i) {
+ sorted_entries_[i] = &entries_[i];
+ }
sorted_entries_.Sort(SortByIds);
}
return &sorted_entries_;
@@ -1299,6 +1274,22 @@ void HeapSnapshot::Print(int max_depth) {
}
+template<typename T, class P>
+static size_t GetMemoryUsedByList(const List<T,P>& list) {
+ return list.capacity() * sizeof(T);
+}
+
+
+size_t HeapSnapshot::RawSnapshotSize() const {
+ return
+ GetMemoryUsedByList(entries_) +
+ GetMemoryUsedByList(edges_) +
+ GetMemoryUsedByList(children_) +
+ GetMemoryUsedByList(retainers_) +
+ GetMemoryUsedByList(sorted_entries_);
+}
+
+
// We split IDs on evens for embedder objects (see
// HeapObjectsMap::GenerateId) and odds for native objects.
const SnapshotObjectId HeapObjectsMap::kInternalRootObjectId = 1;
@@ -1567,99 +1558,22 @@ Handle<HeapObject> HeapSnapshotsCollection::FindHeapObjectById(
}
-HeapEntry* const HeapEntriesMap::kHeapEntryPlaceholder =
- reinterpret_cast<HeapEntry*>(1);
-
HeapEntriesMap::HeapEntriesMap()
- : entries_(HeapThingsMatch),
- entries_count_(0),
- total_children_count_(0),
- total_retainers_count_(0) {
-}
-
-
-HeapEntriesMap::~HeapEntriesMap() {
- for (HashMap::Entry* p = entries_.Start(); p != NULL; p = entries_.Next(p)) {
- delete reinterpret_cast<EntryInfo*>(p->value);
- }
-}
-
-
-void HeapEntriesMap::AllocateHeapEntryForMapEntry(HashMap::Entry* map_entry) {
- EntryInfo* entry_info = reinterpret_cast<EntryInfo*>(map_entry->value);
- entry_info->entry = entry_info->allocator->AllocateEntry(
- map_entry->key,
- entry_info->children_count,
- entry_info->retainers_count);
- ASSERT(entry_info->entry != NULL);
- ASSERT(entry_info->entry != kHeapEntryPlaceholder);
- entry_info->children_count = 0;
- entry_info->retainers_count = 0;
-}
-
-
-void HeapEntriesMap::AllocateEntries(HeapThing root_object) {
- HashMap::Entry* root_entry =
- entries_.Lookup(root_object, Hash(root_object), false);
- ASSERT(root_entry != NULL);
- // Make sure root entry is allocated first.
- AllocateHeapEntryForMapEntry(root_entry);
- void* root_entry_value = root_entry->value;
- // Remove the root object from map while iterating through other entries.
- entries_.Remove(root_object, Hash(root_object));
- root_entry = NULL;
-
- for (HashMap::Entry* p = entries_.Start();
- p != NULL;
- p = entries_.Next(p)) {
- AllocateHeapEntryForMapEntry(p);
- }
-
- // Insert root entry back.
- root_entry = entries_.Lookup(root_object, Hash(root_object), true);
- root_entry->value = root_entry_value;
+ : entries_(HeapThingsMatch) {
}
-HeapEntry* HeapEntriesMap::Map(HeapThing thing) {
+int HeapEntriesMap::Map(HeapThing thing) {
HashMap::Entry* cache_entry = entries_.Lookup(thing, Hash(thing), false);
- if (cache_entry != NULL) {
- EntryInfo* entry_info = reinterpret_cast<EntryInfo*>(cache_entry->value);
- return entry_info->entry;
- } else {
- return NULL;
- }
+ if (cache_entry == NULL) return HeapEntry::kNoEntry;
+ return static_cast<int>(reinterpret_cast<intptr_t>(cache_entry->value));
}
-void HeapEntriesMap::Pair(
- HeapThing thing, HeapEntriesAllocator* allocator, HeapEntry* entry) {
+void HeapEntriesMap::Pair(HeapThing thing, int entry) {
HashMap::Entry* cache_entry = entries_.Lookup(thing, Hash(thing), true);
ASSERT(cache_entry->value == NULL);
- cache_entry->value = new EntryInfo(entry, allocator);
- ++entries_count_;
-}
-
-
-void HeapEntriesMap::CountReference(HeapThing from, HeapThing to,
- int* prev_children_count,
- int* prev_retainers_count) {
- HashMap::Entry* from_cache_entry = entries_.Lookup(from, Hash(from), false);
- HashMap::Entry* to_cache_entry = entries_.Lookup(to, Hash(to), false);
- ASSERT(from_cache_entry != NULL);
- ASSERT(to_cache_entry != NULL);
- EntryInfo* from_entry_info =
- reinterpret_cast<EntryInfo*>(from_cache_entry->value);
- EntryInfo* to_entry_info =
- reinterpret_cast<EntryInfo*>(to_cache_entry->value);
- if (prev_children_count)
- *prev_children_count = from_entry_info->children_count;
- if (prev_retainers_count)
- *prev_retainers_count = to_entry_info->retainers_count;
- ++from_entry_info->children_count;
- ++to_entry_info->retainers_count;
- ++total_children_count_;
- ++total_retainers_count_;
+ cache_entry->value = reinterpret_cast<void*>(static_cast<intptr_t>(entry));
}
@@ -1676,20 +1590,14 @@ void HeapObjectsSet::Clear() {
bool HeapObjectsSet::Contains(Object* obj) {
if (!obj->IsHeapObject()) return false;
HeapObject* object = HeapObject::cast(obj);
- HashMap::Entry* cache_entry =
- entries_.Lookup(object, HeapEntriesMap::Hash(object), false);
- return cache_entry != NULL;
+ return entries_.Lookup(object, HeapEntriesMap::Hash(object), false) != NULL;
}
void HeapObjectsSet::Insert(Object* obj) {
if (!obj->IsHeapObject()) return;
HeapObject* object = HeapObject::cast(obj);
- HashMap::Entry* cache_entry =
- entries_.Lookup(object, HeapEntriesMap::Hash(object), true);
- if (cache_entry->value == NULL) {
- cache_entry->value = HeapEntriesMap::kHeapEntryPlaceholder;
- }
+ entries_.Lookup(object, HeapEntriesMap::Hash(object), true);
}
@@ -1697,12 +1605,9 @@ const char* HeapObjectsSet::GetTag(Object* obj) {
HeapObject* object = HeapObject::cast(obj);
HashMap::Entry* cache_entry =
entries_.Lookup(object, HeapEntriesMap::Hash(object), false);
- if (cache_entry != NULL
- && cache_entry->value != HeapEntriesMap::kHeapEntryPlaceholder) {
- return reinterpret_cast<const char*>(cache_entry->value);
- } else {
- return NULL;
- }
+ return cache_entry != NULL
+ ? reinterpret_cast<const char*>(cache_entry->value)
+ : NULL;
}
@@ -1744,129 +1649,76 @@ V8HeapExplorer::~V8HeapExplorer() {
}
-HeapEntry* V8HeapExplorer::AllocateEntry(
- HeapThing ptr, int children_count, int retainers_count) {
- return AddEntry(
- reinterpret_cast<HeapObject*>(ptr), children_count, retainers_count);
+HeapEntry* V8HeapExplorer::AllocateEntry(HeapThing ptr) {
+ return AddEntry(reinterpret_cast<HeapObject*>(ptr));
}
-HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object,
- int children_count,
- int retainers_count) {
+HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object) {
if (object == kInternalRootObject) {
- ASSERT(retainers_count == 0);
- return snapshot_->AddRootEntry(children_count);
+ snapshot_->AddRootEntry();
+ return snapshot_->root();
} else if (object == kGcRootsObject) {
- return snapshot_->AddGcRootsEntry(children_count, retainers_count);
+ HeapEntry* entry = snapshot_->AddGcRootsEntry();
+ return entry;
} else if (object >= kFirstGcSubrootObject && object < kLastGcSubrootObject) {
- return snapshot_->AddGcSubrootEntry(
- GetGcSubrootOrder(object),
- children_count,
- retainers_count);
+ HeapEntry* entry = snapshot_->AddGcSubrootEntry(GetGcSubrootOrder(object));
+ return entry;
} else if (object->IsJSFunction()) {
JSFunction* func = JSFunction::cast(object);
SharedFunctionInfo* shared = func->shared();
const char* name = shared->bound() ? "native_bind" :
collection_->names()->GetName(String::cast(shared->name()));
- return AddEntry(object,
- HeapEntry::kClosure,
- name,
- children_count,
- retainers_count);
+ return AddEntry(object, HeapEntry::kClosure, name);
} else if (object->IsJSRegExp()) {
JSRegExp* re = JSRegExp::cast(object);
return AddEntry(object,
HeapEntry::kRegExp,
- collection_->names()->GetName(re->Pattern()),
- children_count,
- retainers_count);
+ collection_->names()->GetName(re->Pattern()));
} else if (object->IsJSObject()) {
- return AddEntry(object,
- HeapEntry::kObject,
- "",
- children_count,
- retainers_count);
+ return AddEntry(object, HeapEntry::kObject, "");
} else if (object->IsString()) {
return AddEntry(object,
HeapEntry::kString,
- collection_->names()->GetName(String::cast(object)),
- children_count,
- retainers_count);
+ collection_->names()->GetName(String::cast(object)));
} else if (object->IsCode()) {
- return AddEntry(object,
- HeapEntry::kCode,
- "",
- children_count,
- retainers_count);
+ return AddEntry(object, HeapEntry::kCode, "");
} else if (object->IsSharedFunctionInfo()) {
- SharedFunctionInfo* shared = SharedFunctionInfo::cast(object);
+ String* name = String::cast(SharedFunctionInfo::cast(object)->name());
return AddEntry(object,
HeapEntry::kCode,
- collection_->names()->GetName(String::cast(shared->name())),
- children_count,
- retainers_count);
+ collection_->names()->GetName(name));
} else if (object->IsScript()) {
- Script* script = Script::cast(object);
+ Object* name = Script::cast(object)->name();
return AddEntry(object,
HeapEntry::kCode,
- script->name()->IsString() ?
- collection_->names()->GetName(
- String::cast(script->name()))
- : "",
- children_count,
- retainers_count);
+ name->IsString()
+ ? collection_->names()->GetName(String::cast(name))
+ : "");
} else if (object->IsGlobalContext()) {
- return AddEntry(object,
- HeapEntry::kHidden,
- "system / GlobalContext",
- children_count,
- retainers_count);
+ return AddEntry(object, HeapEntry::kHidden, "system / GlobalContext");
} else if (object->IsContext()) {
- return AddEntry(object,
- HeapEntry::kHidden,
- "system / Context",
- children_count,
- retainers_count);
+ return AddEntry(object, HeapEntry::kHidden, "system / Context");
} else if (object->IsFixedArray() ||
object->IsFixedDoubleArray() ||
object->IsByteArray() ||
object->IsExternalArray()) {
const char* tag = objects_tags_.GetTag(object);
- return AddEntry(object,
- HeapEntry::kArray,
- tag != NULL ? tag : "",
- children_count,
- retainers_count);
+ return AddEntry(object, HeapEntry::kArray, tag != NULL ? tag : "");
} else if (object->IsHeapNumber()) {
- return AddEntry(object,
- HeapEntry::kHeapNumber,
- "number",
- children_count,
- retainers_count);
+ return AddEntry(object, HeapEntry::kHeapNumber, "number");
}
- return AddEntry(object,
- HeapEntry::kHidden,
- GetSystemEntryName(object),
- children_count,
- retainers_count);
+ return AddEntry(object, HeapEntry::kHidden, GetSystemEntryName(object));
}
HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object,
HeapEntry::Type type,
- const char* name,
- int children_count,
- int retainers_count) {
+ const char* name) {
int object_size = object->Size();
SnapshotObjectId object_id =
collection_->GetObjectId(object->address(), object_size);
- return snapshot_->AddEntry(type,
- name,
- object_id,
- object_size,
- children_count,
- retainers_count);
+ return snapshot_->AddEntry(type, name, object_id, object_size);
}
@@ -1935,10 +1787,10 @@ class IndexedReferencesExtractor : public ObjectVisitor {
public:
IndexedReferencesExtractor(V8HeapExplorer* generator,
HeapObject* parent_obj,
- HeapEntry* parent_entry)
+ int parent)
: generator_(generator),
parent_obj_(parent_obj),
- parent_(parent_entry),
+ parent_(parent),
next_index_(1) {
}
void VisitPointers(Object** start, Object** end) {
@@ -1967,14 +1819,15 @@ class IndexedReferencesExtractor : public ObjectVisitor {
}
V8HeapExplorer* generator_;
HeapObject* parent_obj_;
- HeapEntry* parent_;
+ int parent_;
int next_index_;
};
void V8HeapExplorer::ExtractReferences(HeapObject* obj) {
- HeapEntry* entry = GetEntry(obj);
- if (entry == NULL) return; // No interest in this object.
+ HeapEntry* heap_entry = GetEntry(obj);
+ if (heap_entry == NULL) return; // No interest in this object.
+ int entry = heap_entry->index();
bool extract_indexed_refs = true;
if (obj->IsJSGlobalProxy()) {
@@ -2026,7 +1879,7 @@ void V8HeapExplorer::ExtractJSGlobalProxyReferences(JSGlobalProxy* proxy) {
void V8HeapExplorer::ExtractJSObjectReferences(
- HeapEntry* entry, JSObject* js_obj) {
+ int entry, JSObject* js_obj) {
HeapObject* obj = js_obj;
ExtractClosureReferences(js_obj, entry);
ExtractPropertyReferences(js_obj, entry);
@@ -2095,7 +1948,7 @@ void V8HeapExplorer::ExtractJSObjectReferences(
}
-void V8HeapExplorer::ExtractStringReferences(HeapEntry* entry, String* string) {
+void V8HeapExplorer::ExtractStringReferences(int entry, String* string) {
if (string->IsConsString()) {
ConsString* cs = ConsString::cast(string);
SetInternalReference(cs, entry, "first", cs->first());
@@ -2107,8 +1960,7 @@ void V8HeapExplorer::ExtractStringReferences(HeapEntry* entry, String* string) {
}
-void V8HeapExplorer::ExtractContextReferences(
- HeapEntry* entry, Context* context) {
+void V8HeapExplorer::ExtractContextReferences(int entry, Context* context) {
#define EXTRACT_CONTEXT_FIELD(index, type, name) \
SetInternalReference(context, entry, #name, context->get(Context::index), \
FixedArray::OffsetOfElementAt(Context::index));
@@ -2134,7 +1986,7 @@ void V8HeapExplorer::ExtractContextReferences(
}
-void V8HeapExplorer::ExtractMapReferences(HeapEntry* entry, Map* map) {
+void V8HeapExplorer::ExtractMapReferences(int entry, Map* map) {
SetInternalReference(map, entry,
"prototype", map->prototype(), Map::kPrototypeOffset);
SetInternalReference(map, entry,
@@ -2157,7 +2009,7 @@ void V8HeapExplorer::ExtractMapReferences(HeapEntry* entry, Map* map) {
void V8HeapExplorer::ExtractSharedFunctionInfoReferences(
- HeapEntry* entry, SharedFunctionInfo* shared) {
+ int entry, SharedFunctionInfo* shared) {
HeapObject* obj = shared;
SetInternalReference(obj, entry,
"name", shared->name(),
@@ -2199,7 +2051,7 @@ void V8HeapExplorer::ExtractSharedFunctionInfoReferences(
}
-void V8HeapExplorer::ExtractScriptReferences(HeapEntry* entry, Script* script) {
+void V8HeapExplorer::ExtractScriptReferences(int entry, Script* script) {
HeapObject* obj = script;
SetInternalReference(obj, entry,
"source", script->source(),
@@ -2221,7 +2073,7 @@ void V8HeapExplorer::ExtractScriptReferences(HeapEntry* entry, Script* script) {
void V8HeapExplorer::ExtractCodeCacheReferences(
- HeapEntry* entry, CodeCache* code_cache) {
+ int entry, CodeCache* code_cache) {
TagObject(code_cache->default_cache(), "(default code cache)");
SetInternalReference(code_cache, entry,
"default_cache", code_cache->default_cache(),
@@ -2233,7 +2085,7 @@ void V8HeapExplorer::ExtractCodeCacheReferences(
}
-void V8HeapExplorer::ExtractCodeReferences(HeapEntry* entry, Code* code) {
+void V8HeapExplorer::ExtractCodeReferences(int entry, Code* code) {
TagObject(code->relocation_info(), "(code relocation info)");
SetInternalReference(code, entry,
"relocation_info", code->relocation_info(),
@@ -2255,13 +2107,12 @@ void V8HeapExplorer::ExtractCodeReferences(HeapEntry* entry, Code* code) {
void V8HeapExplorer::ExtractJSGlobalPropertyCellReferences(
- HeapEntry* entry, JSGlobalPropertyCell* cell) {
+ int entry, JSGlobalPropertyCell* cell) {
SetInternalReference(cell, entry, "value", cell->value());
}
-void V8HeapExplorer::ExtractClosureReferences(JSObject* js_obj,
- HeapEntry* entry) {
+void V8HeapExplorer::ExtractClosureReferences(JSObject* js_obj, int entry) {
if (!js_obj->IsJSFunction()) return;
JSFunction* func = JSFunction::cast(js_obj);
@@ -2303,8 +2154,7 @@ void V8HeapExplorer::ExtractClosureReferences(JSObject* js_obj,
}
-void V8HeapExplorer::ExtractPropertyReferences(JSObject* js_obj,
- HeapEntry* entry) {
+void V8HeapExplorer::ExtractPropertyReferences(JSObject* js_obj, int entry) {
if (js_obj->HasFastProperties()) {
DescriptorArray* descs = js_obj->map()->instance_descriptors();
for (int i = 0; i < descs->number_of_descriptors(); i++) {
@@ -2377,8 +2227,7 @@ void V8HeapExplorer::ExtractPropertyReferences(JSObject* js_obj,
}
-void V8HeapExplorer::ExtractElementReferences(JSObject* js_obj,
- HeapEntry* entry) {
+void V8HeapExplorer::ExtractElementReferences(JSObject* js_obj, int entry) {
if (js_obj->HasFastElements()) {
FixedArray* elements = FixedArray::cast(js_obj->elements());
int length = js_obj->IsJSArray() ?
@@ -2404,8 +2253,7 @@ void V8HeapExplorer::ExtractElementReferences(JSObject* js_obj,
}
-void V8HeapExplorer::ExtractInternalReferences(JSObject* js_obj,
- HeapEntry* entry) {
+void V8HeapExplorer::ExtractInternalReferences(JSObject* js_obj, int entry) {
int length = js_obj->GetInternalFieldCount();
for (int i = 0; i < length; ++i) {
Object* o = js_obj->GetInternalField(i);
@@ -2531,6 +2379,7 @@ bool V8HeapExplorer::IterateAndExtractReferences(
filler_ = NULL;
return false;
}
+
SetRootGcRootsReference();
RootsReferencesExtractor extractor;
heap_->IterateRoots(&extractor, VISIT_ONLY_STRONG);
@@ -2538,7 +2387,7 @@ bool V8HeapExplorer::IterateAndExtractReferences(
heap_->IterateRoots(&extractor, VISIT_ALL);
extractor.FillReferences(this);
filler_ = NULL;
- return progress_->ProgressReport(false);
+ return progress_->ProgressReport(true);
}
@@ -2586,55 +2435,49 @@ bool V8HeapExplorer::IsEssentialObject(Object* object) {
void V8HeapExplorer::SetClosureReference(HeapObject* parent_obj,
- HeapEntry* parent_entry,
+ int parent_entry,
String* reference_name,
Object* child_obj) {
HeapEntry* child_entry = GetEntry(child_obj);
if (child_entry != NULL) {
filler_->SetNamedReference(HeapGraphEdge::kContextVariable,
- parent_obj,
parent_entry,
collection_->names()->GetName(reference_name),
- child_obj,
child_entry);
}
}
void V8HeapExplorer::SetNativeBindReference(HeapObject* parent_obj,
- HeapEntry* parent_entry,
+ int parent_entry,
const char* reference_name,
Object* child_obj) {
HeapEntry* child_entry = GetEntry(child_obj);
if (child_entry != NULL) {
filler_->SetNamedReference(HeapGraphEdge::kShortcut,
- parent_obj,
parent_entry,
reference_name,
- child_obj,
child_entry);
}
}
void V8HeapExplorer::SetElementReference(HeapObject* parent_obj,
- HeapEntry* parent_entry,
+ int parent_entry,
int index,
Object* child_obj) {
HeapEntry* child_entry = GetEntry(child_obj);
if (child_entry != NULL) {
filler_->SetIndexedReference(HeapGraphEdge::kElement,
- parent_obj,
parent_entry,
index,
- child_obj,
child_entry);
}
}
void V8HeapExplorer::SetInternalReference(HeapObject* parent_obj,
- HeapEntry* parent_entry,
+ int parent_entry,
const char* reference_name,
Object* child_obj,
int field_offset) {
@@ -2642,16 +2485,16 @@ void V8HeapExplorer::SetInternalReference(HeapObject* parent_obj,
if (child_entry == NULL) return;
if (IsEssentialObject(child_obj)) {
filler_->SetNamedReference(HeapGraphEdge::kInternal,
- parent_obj, parent_entry,
+ parent_entry,
reference_name,
- child_obj, child_entry);
+ child_entry);
}
IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset);
}
void V8HeapExplorer::SetInternalReference(HeapObject* parent_obj,
- HeapEntry* parent_entry,
+ int parent_entry,
int index,
Object* child_obj,
int field_offset) {
@@ -2659,42 +2502,38 @@ void V8HeapExplorer::SetInternalReference(HeapObject* parent_obj,
if (child_entry == NULL) return;
if (IsEssentialObject(child_obj)) {
filler_->SetNamedReference(HeapGraphEdge::kInternal,
- parent_obj, parent_entry,
+ parent_entry,
collection_->names()->GetName(index),
- child_obj, child_entry);
+ child_entry);
}
IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset);
}
void V8HeapExplorer::SetHiddenReference(HeapObject* parent_obj,
- HeapEntry* parent_entry,
+ int parent_entry,
int index,
Object* child_obj) {
HeapEntry* child_entry = GetEntry(child_obj);
if (child_entry != NULL && IsEssentialObject(child_obj)) {
filler_->SetIndexedReference(HeapGraphEdge::kHidden,
- parent_obj,
parent_entry,
index,
- child_obj,
child_entry);
}
}
void V8HeapExplorer::SetWeakReference(HeapObject* parent_obj,
- HeapEntry* parent_entry,
+ int parent_entry,
int index,
Object* child_obj,
int field_offset) {
HeapEntry* child_entry = GetEntry(child_obj);
if (child_entry != NULL) {
filler_->SetIndexedReference(HeapGraphEdge::kWeak,
- parent_obj,
parent_entry,
index,
- child_obj,
child_entry);
IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset);
}
@@ -2702,7 +2541,7 @@ void V8HeapExplorer::SetWeakReference(HeapObject* parent_obj,
void V8HeapExplorer::SetPropertyReference(HeapObject* parent_obj,
- HeapEntry* parent_entry,
+ int parent_entry,
String* reference_name,
Object* child_obj,
const char* name_format_string,
@@ -2719,10 +2558,8 @@ void V8HeapExplorer::SetPropertyReference(HeapObject* parent_obj,
collection_->names()->GetName(reference_name);
filler_->SetNamedReference(type,
- parent_obj,
parent_entry,
name,
- child_obj,
child_entry);
IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset);
}
@@ -2730,16 +2567,14 @@ void V8HeapExplorer::SetPropertyReference(HeapObject* parent_obj,
void V8HeapExplorer::SetPropertyShortcutReference(HeapObject* parent_obj,
- HeapEntry* parent_entry,
+ int parent_entry,
String* reference_name,
Object* child_obj) {
HeapEntry* child_entry = GetEntry(child_obj);
if (child_entry != NULL) {
filler_->SetNamedReference(HeapGraphEdge::kShortcut,
- parent_obj,
parent_entry,
collection_->names()->GetName(reference_name),
- child_obj,
child_entry);
}
}
@@ -2748,8 +2583,8 @@ void V8HeapExplorer::SetPropertyShortcutReference(HeapObject* parent_obj,
void V8HeapExplorer::SetRootGcRootsReference() {
filler_->SetIndexedAutoIndexReference(
HeapGraphEdge::kElement,
- kInternalRootObject, snapshot_->root(),
- kGcRootsObject, snapshot_->gc_roots());
+ snapshot_->root()->index(),
+ snapshot_->gc_roots());
}
@@ -2758,16 +2593,16 @@ void V8HeapExplorer::SetUserGlobalReference(Object* child_obj) {
ASSERT(child_entry != NULL);
filler_->SetNamedAutoIndexReference(
HeapGraphEdge::kShortcut,
- kInternalRootObject, snapshot_->root(),
- child_obj, child_entry);
+ snapshot_->root()->index(),
+ child_entry);
}
void V8HeapExplorer::SetGcRootsReference(VisitorSynchronization::SyncTag tag) {
filler_->SetIndexedAutoIndexReference(
HeapGraphEdge::kElement,
- kGcRootsObject, snapshot_->gc_roots(),
- GetNthGcSubrootObject(tag), snapshot_->gc_subroot(tag));
+ snapshot_->gc_roots()->index(),
+ snapshot_->gc_subroot(tag));
}
@@ -2779,14 +2614,14 @@ void V8HeapExplorer::SetGcSubrootReference(
if (name != NULL) {
filler_->SetNamedReference(
HeapGraphEdge::kInternal,
- GetNthGcSubrootObject(tag), snapshot_->gc_subroot(tag),
+ snapshot_->gc_subroot(tag)->index(),
name,
- child_obj, child_entry);
+ child_entry);
} else {
filler_->SetIndexedAutoIndexReference(
is_weak ? HeapGraphEdge::kWeak : HeapGraphEdge::kElement,
- GetNthGcSubrootObject(tag), snapshot_->gc_subroot(tag),
- child_obj, child_entry);
+ snapshot_->gc_subroot(tag)->index(),
+ child_entry);
}
}
}
@@ -2903,8 +2738,7 @@ class BasicHeapEntriesAllocator : public HeapEntriesAllocator {
collection_(snapshot_->collection()),
entries_type_(entries_type) {
}
- virtual HeapEntry* AllocateEntry(
- HeapThing ptr, int children_count, int retainers_count);
+ virtual HeapEntry* AllocateEntry(HeapThing ptr);
private:
HeapSnapshot* snapshot_;
HeapSnapshotsCollection* collection_;
@@ -2912,23 +2746,19 @@ class BasicHeapEntriesAllocator : public HeapEntriesAllocator {
};
-HeapEntry* BasicHeapEntriesAllocator::AllocateEntry(
- HeapThing ptr, int children_count, int retainers_count) {
+HeapEntry* BasicHeapEntriesAllocator::AllocateEntry(HeapThing ptr) {
v8::RetainedObjectInfo* info = reinterpret_cast<v8::RetainedObjectInfo*>(ptr);
intptr_t elements = info->GetElementCount();
intptr_t size = info->GetSizeInBytes();
+ const char* name = elements != -1
+ ? collection_->names()->GetFormatted(
+ "%s / %" V8_PTR_PREFIX "d entries", info->GetLabel(), elements)
+ : collection_->names()->GetCopy(info->GetLabel());
return snapshot_->AddEntry(
entries_type_,
- elements != -1 ?
- collection_->names()->GetFormatted(
- "%s / %" V8_PTR_PREFIX "d entries",
- info->GetLabel(),
- info->GetElementCount()) :
- collection_->names()->GetCopy(info->GetLabel()),
+ name,
HeapObjectsMap::GenerateId(info),
- size != -1 ? static_cast<int>(size) : 0,
- children_count,
- retainers_count);
+ size != -1 ? static_cast<int>(size) : 0);
}
@@ -3009,9 +2839,9 @@ void NativeObjectsExplorer::FillImplicitReferences() {
for (int i = 0; i < groups->length(); ++i) {
ImplicitRefGroup* group = groups->at(i);
HeapObject* parent = *group->parent_;
- HeapEntry* parent_entry =
- filler_->FindOrAddEntry(parent, native_entries_allocator_);
- ASSERT(parent_entry != NULL);
+ int parent_entry =
+ filler_->FindOrAddEntry(parent, native_entries_allocator_)->index();
+ ASSERT(parent_entry != HeapEntry::kNoEntry);
Object*** children = group->children_;
for (size_t j = 0; j < group->length_; ++j) {
Object* child = *children[j];
@@ -3019,9 +2849,9 @@ void NativeObjectsExplorer::FillImplicitReferences() {
filler_->FindOrAddEntry(child, native_entries_allocator_);
filler_->SetNamedReference(
HeapGraphEdge::kInternal,
- parent, parent_entry,
+ parent_entry,
"native",
- child, child_entry);
+ child_entry);
}
}
}
@@ -3099,8 +2929,9 @@ NativeGroupRetainedObjectInfo* NativeObjectsExplorer::FindOrAddGroupInfo(
HEAP->HashSeed());
HashMap::Entry* entry = native_groups_.Lookup(const_cast<char*>(label_copy),
hash, true);
- if (entry->value == NULL)
+ if (entry->value == NULL) {
entry->value = new NativeGroupRetainedObjectInfo(label);
+ }
return static_cast<NativeGroupRetainedObjectInfo*>(entry->value);
}
@@ -3116,8 +2947,8 @@ void NativeObjectsExplorer::SetNativeRootReference(
filler_->FindOrAddEntry(group_info, synthetic_entries_allocator_);
filler_->SetNamedAutoIndexReference(
HeapGraphEdge::kInternal,
- group_info, group_entry,
- info, child_entry);
+ group_entry->index(),
+ child_entry);
}
@@ -3129,12 +2960,12 @@ void NativeObjectsExplorer::SetWrapperNativeReferences(
filler_->FindOrAddEntry(info, native_entries_allocator_);
ASSERT(info_entry != NULL);
filler_->SetNamedReference(HeapGraphEdge::kInternal,
- wrapper, wrapper_entry,
+ wrapper_entry->index(),
"native",
- info, info_entry);
+ info_entry);
filler_->SetIndexedAutoIndexReference(HeapGraphEdge::kElement,
- info, info_entry,
- wrapper, wrapper_entry);
+ info_entry->index(),
+ wrapper_entry);
}
@@ -3149,8 +2980,8 @@ void NativeObjectsExplorer::SetRootNativeRootsReference() {
ASSERT(group_entry != NULL);
filler_->SetIndexedAutoIndexReference(
HeapGraphEdge::kElement,
- V8HeapExplorer::kInternalRootObject, snapshot_->root(),
- group_info, group_entry);
+ snapshot_->root()->index(),
+ group_entry);
}
}
@@ -3165,56 +2996,6 @@ void NativeObjectsExplorer::VisitSubtreeWrapper(Object** p, uint16_t class_id) {
}
-class SnapshotCounter : public SnapshotFillerInterface {
- public:
- explicit SnapshotCounter(HeapEntriesMap* entries) : entries_(entries) { }
- HeapEntry* AddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) {
- entries_->Pair(ptr, allocator, HeapEntriesMap::kHeapEntryPlaceholder);
- return HeapEntriesMap::kHeapEntryPlaceholder;
- }
- HeapEntry* FindEntry(HeapThing ptr) {
- return entries_->Map(ptr);
- }
- HeapEntry* FindOrAddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) {
- HeapEntry* entry = FindEntry(ptr);
- return entry != NULL ? entry : AddEntry(ptr, allocator);
- }
- void SetIndexedReference(HeapGraphEdge::Type,
- HeapThing parent_ptr,
- HeapEntry*,
- int,
- HeapThing child_ptr,
- HeapEntry*) {
- entries_->CountReference(parent_ptr, child_ptr);
- }
- void SetIndexedAutoIndexReference(HeapGraphEdge::Type,
- HeapThing parent_ptr,
- HeapEntry*,
- HeapThing child_ptr,
- HeapEntry*) {
- entries_->CountReference(parent_ptr, child_ptr);
- }
- void SetNamedReference(HeapGraphEdge::Type,
- HeapThing parent_ptr,
- HeapEntry*,
- const char*,
- HeapThing child_ptr,
- HeapEntry*) {
- entries_->CountReference(parent_ptr, child_ptr);
- }
- void SetNamedAutoIndexReference(HeapGraphEdge::Type,
- HeapThing parent_ptr,
- HeapEntry*,
- HeapThing child_ptr,
- HeapEntry*) {
- entries_->CountReference(parent_ptr, child_ptr);
- }
-
- private:
- HeapEntriesMap* entries_;
-};
-
-
class SnapshotFiller : public SnapshotFillerInterface {
public:
explicit SnapshotFiller(HeapSnapshot* snapshot, HeapEntriesMap* entries)
@@ -3222,64 +3003,48 @@ class SnapshotFiller : public SnapshotFillerInterface {
collection_(snapshot->collection()),
entries_(entries) { }
HeapEntry* AddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) {
- UNREACHABLE();
- return NULL;
+ HeapEntry* entry = allocator->AllocateEntry(ptr);
+ entries_->Pair(ptr, entry->index());
+ return entry;
}
HeapEntry* FindEntry(HeapThing ptr) {
- return entries_->Map(ptr);
+ int index = entries_->Map(ptr);
+ return index != HeapEntry::kNoEntry ? &snapshot_->entries()[index] : NULL;
}
HeapEntry* FindOrAddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) {
HeapEntry* entry = FindEntry(ptr);
return entry != NULL ? entry : AddEntry(ptr, allocator);
}
void SetIndexedReference(HeapGraphEdge::Type type,
- HeapThing parent_ptr,
- HeapEntry* parent_entry,
+ int parent,
int index,
- HeapThing child_ptr,
HeapEntry* child_entry) {
- int child_index, retainer_index;
- entries_->CountReference(
- parent_ptr, child_ptr, &child_index, &retainer_index);
- parent_entry->SetIndexedReference(
- type, child_index, index, child_entry, retainer_index);
+ HeapEntry* parent_entry = &snapshot_->entries()[parent];
+ parent_entry->SetIndexedReference(type, index, child_entry);
}
void SetIndexedAutoIndexReference(HeapGraphEdge::Type type,
- HeapThing parent_ptr,
- HeapEntry* parent_entry,
- HeapThing child_ptr,
+ int parent,
HeapEntry* child_entry) {
- int child_index, retainer_index;
- entries_->CountReference(
- parent_ptr, child_ptr, &child_index, &retainer_index);
- parent_entry->SetIndexedReference(
- type, child_index, child_index + 1, child_entry, retainer_index);
+ HeapEntry* parent_entry = &snapshot_->entries()[parent];
+ int index = parent_entry->children_count() + 1;
+ parent_entry->SetIndexedReference(type, index, child_entry);
}
void SetNamedReference(HeapGraphEdge::Type type,
- HeapThing parent_ptr,
- HeapEntry* parent_entry,
+ int parent,
const char* reference_name,
- HeapThing child_ptr,
HeapEntry* child_entry) {
- int child_index, retainer_index;
- entries_->CountReference(
- parent_ptr, child_ptr, &child_index, &retainer_index);
- parent_entry->SetNamedReference(
- type, child_index, reference_name, child_entry, retainer_index);
+ HeapEntry* parent_entry = &snapshot_->entries()[parent];
+ parent_entry->SetNamedReference(type, reference_name, child_entry);
}
void SetNamedAutoIndexReference(HeapGraphEdge::Type type,
- HeapThing parent_ptr,
- HeapEntry* parent_entry,
- HeapThing child_ptr,
+ int parent,
HeapEntry* child_entry) {
- int child_index, retainer_index;
- entries_->CountReference(
- parent_ptr, child_ptr, &child_index, &retainer_index);
- parent_entry->SetNamedReference(type,
- child_index,
- collection_->names()->GetName(child_index + 1),
- child_entry,
- retainer_index);
+ HeapEntry* parent_entry = &snapshot_->entries()[parent];
+ int index = parent_entry->children_count() + 1;
+ parent_entry->SetNamedReference(
+ type,
+ collection_->names()->GetName(index),
+ child_entry);
}
private:
@@ -3329,30 +3094,15 @@ bool HeapSnapshotGenerator::GenerateSnapshot() {
debug_heap->Verify();
#endif
- SetProgressTotal(2); // 2 passes.
-
-#ifdef DEBUG
- debug_heap->Verify();
-#endif
-
- // Pass 1. Iterate heap contents to count entries and references.
- if (!CountEntriesAndReferences()) return false;
+ SetProgressTotal(1); // 1 pass.
#ifdef DEBUG
debug_heap->Verify();
#endif
- // Allocate memory for entries and references.
- snapshot_->AllocateEntries(entries_.entries_count(),
- entries_.total_children_count(),
- entries_.total_retainers_count());
-
- // Allocate heap objects to entries hash map.
- entries_.AllocateEntries(V8HeapExplorer::kInternalRootObject);
-
- // Pass 2. Fill references.
if (!FillReferences()) return false;
+ snapshot_->FillChildrenAndRetainers();
snapshot_->RememberLastJSObjectId();
if (!SetEntriesDominators()) return false;
@@ -3384,23 +3134,16 @@ bool HeapSnapshotGenerator::ProgressReport(bool force) {
void HeapSnapshotGenerator::SetProgressTotal(int iterations_count) {
if (control_ == NULL) return;
HeapIterator iterator(HeapIterator::kFilterUnreachable);
- progress_total_ = (
+ progress_total_ = iterations_count * (
v8_heap_explorer_.EstimateObjectsCount(&iterator) +
- dom_explorer_.EstimateObjectsCount()) * iterations_count;
+ dom_explorer_.EstimateObjectsCount());
progress_counter_ = 0;
}
-bool HeapSnapshotGenerator::CountEntriesAndReferences() {
- SnapshotCounter counter(&entries_);
- v8_heap_explorer_.AddRootEntries(&counter);
- return v8_heap_explorer_.IterateAndExtractReferences(&counter)
- && dom_explorer_.IterateAndExtractReferences(&counter);
-}
-
-
bool HeapSnapshotGenerator::FillReferences() {
SnapshotFiller filler(snapshot_, &entries_);
+ v8_heap_explorer_.AddRootEntries(&filler);
// IterateAndExtractReferences cannot set object names because
// it makes call to JSObject::LocalLookupRealNamedProperty which
// in turn may relocate objects in property maps thus changing the heap
@@ -3413,19 +3156,19 @@ bool HeapSnapshotGenerator::FillReferences() {
}
-bool HeapSnapshotGenerator::IsUserGlobalReference(const HeapGraphEdge& edge) {
- ASSERT(edge.from() == snapshot_->root());
- return edge.type() == HeapGraphEdge::kShortcut;
+bool HeapSnapshotGenerator::IsUserGlobalReference(const HeapGraphEdge* edge) {
+ ASSERT(edge->from() == snapshot_->root());
+ return edge->type() == HeapGraphEdge::kShortcut;
}
void HeapSnapshotGenerator::MarkUserReachableObjects() {
List<HeapEntry*> worklist;
- Vector<HeapGraphEdge> children = snapshot_->root()->children();
+ Vector<HeapGraphEdge*> children = snapshot_->root()->children();
for (int i = 0; i < children.length(); ++i) {
if (IsUserGlobalReference(children[i])) {
- worklist.Add(children[i].to());
+ worklist.Add(children[i]->to());
}
}
@@ -3433,9 +3176,9 @@ void HeapSnapshotGenerator::MarkUserReachableObjects() {
HeapEntry* entry = worklist.RemoveLast();
if (entry->user_reachable()) continue;
entry->set_user_reachable();
- Vector<HeapGraphEdge> children = entry->children();
+ Vector<HeapGraphEdge*> children = entry->children();
for (int i = 0; i < children.length(); ++i) {
- HeapEntry* child = children[i].to();
+ HeapEntry* child = children[i]->to();
if (!child->user_reachable()) {
worklist.Add(child);
}
@@ -3464,11 +3207,11 @@ void HeapSnapshotGenerator::FillPostorderIndexes(
snapshot_->root()->paint();
while (!nodes_to_visit.is_empty()) {
HeapEntry* entry = nodes_to_visit.last();
- Vector<HeapGraphEdge> children = entry->children();
+ Vector<HeapGraphEdge*> children = entry->children();
bool has_new_edges = false;
for (int i = 0; i < children.length(); ++i) {
- if (entry != root && !IsRetainingEdge(&children[i])) continue;
- HeapEntry* child = children[i].to();
+ if (entry != root && !IsRetainingEdge(children[i])) continue;
+ HeapEntry* child = children[i]->to();
if (!child->painted()) {
nodes_to_visit.Add(child);
child->paint();
@@ -3476,7 +3219,7 @@ void HeapSnapshotGenerator::FillPostorderIndexes(
}
}
if (!has_new_edges) {
- entry->set_ordered_index(current_entry);
+ entry->set_postorder_index(current_entry);
(*entries)[current_entry++] = entry;
nodes_to_visit.RemoveLast();
}
@@ -3504,8 +3247,7 @@ bool HeapSnapshotGenerator::BuildDominatorTree(
if (entries.length() == 0) return true;
HeapEntry* root = snapshot_->root();
const int entries_length = entries.length(), root_index = entries_length - 1;
- static const int kNoDominator = -1;
- for (int i = 0; i < root_index; ++i) (*dominators)[i] = kNoDominator;
+ for (int i = 0; i < root_index; ++i) (*dominators)[i] = HeapEntry::kNoEntry;
(*dominators)[root_index] = root_index;
// The affected array is used to mark entries which dominators
@@ -3513,28 +3255,28 @@ bool HeapSnapshotGenerator::BuildDominatorTree(
ScopedVector<bool> affected(entries_length);
for (int i = 0; i < affected.length(); ++i) affected[i] = false;
// Mark the root direct children as affected.
- Vector<HeapGraphEdge> children = entries[root_index]->children();
+ Vector<HeapGraphEdge*> children = entries[root_index]->children();
for (int i = 0; i < children.length(); ++i) {
- affected[children[i].to()->ordered_index()] = true;
+ affected[children[i]->to()->postorder_index()] = true;
}
bool changed = true;
while (changed) {
changed = false;
- if (!ProgressReport(true)) return false;
+ if (!ProgressReport(false)) return false;
for (int i = root_index - 1; i >= 0; --i) {
if (!affected[i]) continue;
affected[i] = false;
// If dominator of the entry has already been set to root,
// then it can't propagate any further.
if ((*dominators)[i] == root_index) continue;
- int new_idom_index = kNoDominator;
+ int new_idom_index = HeapEntry::kNoEntry;
Vector<HeapGraphEdge*> rets = entries[i]->retainers();
for (int j = 0; j < rets.length(); ++j) {
if (rets[j]->from() != root && !IsRetainingEdge(rets[j])) continue;
- int ret_index = rets[j]->from()->ordered_index();
- if (dominators->at(ret_index) != kNoDominator) {
- new_idom_index = new_idom_index == kNoDominator
+ int ret_index = rets[j]->from()->postorder_index();
+ if (dominators->at(ret_index) != HeapEntry::kNoEntry) {
+ new_idom_index = new_idom_index == HeapEntry::kNoEntry
? ret_index
: Intersect(ret_index, new_idom_index, *dominators);
// If idom has already reached the root, it doesn't make sense
@@ -3542,13 +3284,13 @@ bool HeapSnapshotGenerator::BuildDominatorTree(
if (new_idom_index == root_index) break;
}
}
- if (new_idom_index != kNoDominator
+ if (new_idom_index != HeapEntry::kNoEntry
&& dominators->at(i) != new_idom_index) {
(*dominators)[i] = new_idom_index;
changed = true;
- Vector<HeapGraphEdge> children = entries[i]->children();
+ Vector<HeapGraphEdge*> children = entries[i]->children();
for (int j = 0; j < children.length(); ++j) {
- affected[children[j].to()->ordered_index()] = true;
+ affected[children[j]->to()->postorder_index()] = true;
}
}
}
@@ -3560,12 +3302,12 @@ bool HeapSnapshotGenerator::BuildDominatorTree(
bool HeapSnapshotGenerator::SetEntriesDominators() {
MarkUserReachableObjects();
// This array is used for maintaining postorder of nodes.
- ScopedVector<HeapEntry*> ordered_entries(snapshot_->entries()->length());
+ ScopedVector<HeapEntry*> ordered_entries(snapshot_->entries().length());
FillPostorderIndexes(&ordered_entries);
ScopedVector<int> dominators(ordered_entries.length());
if (!BuildDominatorTree(ordered_entries, &dominators)) return false;
for (int i = 0; i < ordered_entries.length(); ++i) {
- ASSERT(dominators[i] >= 0);
+ ASSERT(dominators[i] != HeapEntry::kNoEntry);
ordered_entries[i]->set_dominator(ordered_entries[dominators[i]]);
}
return true;
@@ -3576,17 +3318,18 @@ bool HeapSnapshotGenerator::CalculateRetainedSizes() {
// As for the dominators tree we only know parent nodes, not
// children, to sum up total sizes we "bubble" node's self size
// adding it to all of its parents.
- List<HeapEntry*>& entries = *snapshot_->entries();
+ List<HeapEntry>& entries = snapshot_->entries();
for (int i = 0; i < entries.length(); ++i) {
- HeapEntry* entry = entries[i];
+ HeapEntry* entry = &entries[i];
entry->set_retained_size(entry->self_size());
}
for (int i = 0; i < entries.length(); ++i) {
- HeapEntry* entry = entries[i];
- int entry_size = entry->self_size();
- for (HeapEntry* dominator = entry->dominator();
- dominator != entry;
- entry = dominator, dominator = entry->dominator()) {
+ int entry_size = entries[i].self_size();
+ HeapEntry* current = &entries[i];
+ for (HeapEntry* dominator = current->dominator();
+ dominator != current;
+ current = dominator, dominator = current->dominator()) {
+ ASSERT(current->dominator() != NULL);
dominator->add_retained_size(entry_size);
}
}
@@ -3690,19 +3433,23 @@ class OutputStreamWriter {
};
+// type, name|index, to_node.
+const int HeapSnapshotJSONSerializer::kEdgeFieldsCount = 3;
+// type, name, id, self_size, retained_size, dominator, children_index.
+const int HeapSnapshotJSONSerializer::kNodeFieldsCount = 7;
+
void HeapSnapshotJSONSerializer::Serialize(v8::OutputStream* stream) {
ASSERT(writer_ == NULL);
writer_ = new OutputStreamWriter(stream);
HeapSnapshot* original_snapshot = NULL;
- if (snapshot_->raw_entries_size() >=
+ if (snapshot_->RawSnapshotSize() >=
SnapshotSizeConstants<kPointerSize>::kMaxSerializableSnapshotRawSize) {
// The snapshot is too big. Serialize a fake snapshot.
original_snapshot = snapshot_;
snapshot_ = CreateFakeSnapshot();
}
- // Since nodes graph is cyclic, we need the first pass to enumerate
- // them. Strings can be serialized in one pass.
+
SerializeImpl();
delete writer_;
@@ -3720,42 +3467,24 @@ HeapSnapshot* HeapSnapshotJSONSerializer::CreateFakeSnapshot() {
HeapSnapshot::kFull,
snapshot_->title(),
snapshot_->uid());
- result->AllocateEntries(2, 1, 0);
- HeapEntry* root = result->AddRootEntry(1);
+ result->AddRootEntry();
const char* text = snapshot_->collection()->names()->GetFormatted(
"The snapshot is too big. "
"Maximum snapshot size is %" V8_PTR_PREFIX "u MB. "
"Actual snapshot size is %" V8_PTR_PREFIX "u MB.",
SnapshotSizeConstants<kPointerSize>::kMaxSerializableSnapshotRawSize / MB,
- (snapshot_->raw_entries_size() + MB - 1) / MB);
- HeapEntry* message = result->AddEntry(
- HeapEntry::kString, text, 0, 4, 0, 0);
- root->SetUnidirElementReference(0, 1, message);
+ (snapshot_->RawSnapshotSize() + MB - 1) / MB);
+ HeapEntry* message = result->AddEntry(HeapEntry::kString, text, 0, 4);
+ result->root()->SetIndexedReference(HeapGraphEdge::kElement, 1, message);
+ result->FillChildrenAndRetainers();
result->SetDominatorsToSelf();
return result;
}
-void HeapSnapshotJSONSerializer::CalculateNodeIndexes(
- const List<HeapEntry*>& nodes) {
- // type,name,id,self_size,retained_size,dominator,children_index.
- const int node_fields_count = 7;
- // Root must be the first.
- ASSERT(nodes.first() == snapshot_->root());
- // Rewrite node indexes, so they refer to actual array positions. Do this
- // only once.
- if (nodes[0]->entry_index() == -1) {
- int index = 0;
- for (int i = 0; i < nodes.length(); ++i, index += node_fields_count) {
- nodes[i]->set_entry_index(index);
- }
- }
-}
-
-
void HeapSnapshotJSONSerializer::SerializeImpl() {
- List<HeapEntry*>& nodes = *(snapshot_->entries());
- CalculateNodeIndexes(nodes);
+ List<HeapEntry>& nodes = snapshot_->entries();
+ ASSERT(0 == snapshot_->root()->index());
writer_->AddCharacter('{');
writer_->AddString("\"snapshot\":{");
SerializeSnapshot();
@@ -3831,19 +3560,19 @@ void HeapSnapshotJSONSerializer::SerializeEdge(HeapGraphEdge* edge,
buffer[buffer_pos++] = ',';
buffer_pos = itoa(edge_name_or_index, buffer, buffer_pos);
buffer[buffer_pos++] = ',';
- buffer_pos = itoa(edge->to()->entry_index(), buffer, buffer_pos);
+ buffer_pos = itoa(entry_index(edge->to()), buffer, buffer_pos);
buffer[buffer_pos++] = '\0';
writer_->AddString(buffer.start());
}
-void HeapSnapshotJSONSerializer::SerializeEdges(const List<HeapEntry*>& nodes) {
+void HeapSnapshotJSONSerializer::SerializeEdges(const List<HeapEntry>& nodes) {
bool first_edge = true;
for (int i = 0; i < nodes.length(); ++i) {
- HeapEntry* entry = nodes[i];
- Vector<HeapGraphEdge> children = entry->children();
+ HeapEntry* entry = &nodes[i];
+ Vector<HeapGraphEdge*> children = entry->children();
for (int j = 0; j < children.length(); ++j) {
- SerializeEdge(&children[j], first_edge);
+ SerializeEdge(children[j], first_edge);
first_edge = false;
if (writer_->aborted()) return;
}
@@ -3861,7 +3590,7 @@ void HeapSnapshotJSONSerializer::SerializeNode(HeapEntry* entry,
EmbeddedVector<char, kBufferSize> buffer;
int buffer_pos = 0;
buffer[buffer_pos++] = '\n';
- if (entry->entry_index() != 0) {
+ if (entry_index(entry) != 0) {
buffer[buffer_pos++] = ',';
}
buffer_pos = itoa(entry->type(), buffer, buffer_pos);
@@ -3874,7 +3603,7 @@ void HeapSnapshotJSONSerializer::SerializeNode(HeapEntry* entry,
buffer[buffer_pos++] = ',';
buffer_pos = itoa(entry->retained_size(), buffer, buffer_pos);
buffer[buffer_pos++] = ',';
- buffer_pos = itoa(entry->dominator()->entry_index(), buffer, buffer_pos);
+ buffer_pos = itoa(entry_index(entry->dominator()), buffer, buffer_pos);
buffer[buffer_pos++] = ',';
buffer_pos = itoa(edges_index, buffer, buffer_pos);
buffer[buffer_pos++] = '\0';
@@ -3882,13 +3611,12 @@ void HeapSnapshotJSONSerializer::SerializeNode(HeapEntry* entry,
}
-void HeapSnapshotJSONSerializer::SerializeNodes(const List<HeapEntry*>& nodes) {
- const int edge_fields_count = 3; // type,name|index,to_node.
+void HeapSnapshotJSONSerializer::SerializeNodes(const List<HeapEntry>& nodes) {
int edges_index = 0;
for (int i = 0; i < nodes.length(); ++i) {
- HeapEntry* entry = nodes[i];
+ HeapEntry* entry = &nodes[i];
SerializeNode(entry, edges_index);
- edges_index += entry->children().length() * edge_fields_count;
+ edges_index += entry->children().length() * kEdgeFieldsCount;
if (writer_->aborted()) return;
}
}
@@ -3952,9 +3680,9 @@ void HeapSnapshotJSONSerializer::SerializeSnapshot() {
#undef JSON_O
#undef JSON_A
writer_->AddString(",\"node_count\":");
- writer_->AddNumber(snapshot_->entries()->length());
+ writer_->AddNumber(snapshot_->entries().length());
writer_->AddString(",\"edge_count\":");
- writer_->AddNumber(snapshot_->number_of_edges());
+ writer_->AddNumber(snapshot_->edges().length());
}
« no previous file with comments | « src/profile-generator.h ('k') | src/profile-generator-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698