Simplify synthetic roots creation in heap snapshot
The synthetic roots exist in every snapshot and there are no actual objects corresponding to them (there was attempt to create some virtual objects to reuse existing snapshot builder but it just complicated the things). Previously synthetic root wouldn't have been added if it was empty. Current implementation always adds all synthetic roots in the snapshot no matter if they are empty or not. BUG=None LOG=N R=alph@chromium.org, mstarzinger@chromium.org Review URL: https://codereview.chromium.org/590833002 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24124 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
7384467552
commit
269c46ee80
@ -43,25 +43,6 @@ HeapGraphEdge** HeapEntry::children_arr() {
|
||||
}
|
||||
|
||||
|
||||
SnapshotObjectId HeapObjectsMap::GetNthGcSubrootId(int delta) {
|
||||
return kGcRootsFirstSubrootId + delta * kObjectIdStep;
|
||||
}
|
||||
|
||||
|
||||
HeapObject* V8HeapExplorer::GetNthGcSubrootObject(int delta) {
|
||||
return reinterpret_cast<HeapObject*>(
|
||||
reinterpret_cast<char*>(kFirstGcSubrootObject) +
|
||||
delta * HeapObjectsMap::kObjectIdStep);
|
||||
}
|
||||
|
||||
|
||||
int V8HeapExplorer::GetGcSubrootOrder(HeapObject* subroot) {
|
||||
return static_cast<int>(
|
||||
(reinterpret_cast<char*>(subroot) -
|
||||
reinterpret_cast<char*>(kFirstGcSubrootObject)) /
|
||||
HeapObjectsMap::kObjectIdStep);
|
||||
}
|
||||
|
||||
} } // namespace v8::internal
|
||||
|
||||
#endif // V8_HEAP_SNAPSHOT_GENERATOR_INL_H_
|
||||
|
@ -188,7 +188,6 @@ HeapSnapshot::HeapSnapshot(HeapProfiler* profiler,
|
||||
uid_(uid),
|
||||
root_index_(HeapEntry::kNoEntry),
|
||||
gc_roots_index_(HeapEntry::kNoEntry),
|
||||
natives_root_index_(HeapEntry::kNoEntry),
|
||||
max_snapshot_js_object_id_(0) {
|
||||
STATIC_ASSERT(
|
||||
sizeof(HeapGraphEdge) ==
|
||||
@ -217,6 +216,18 @@ void HeapSnapshot::RememberLastJSObjectId() {
|
||||
}
|
||||
|
||||
|
||||
void HeapSnapshot::AddSyntheticRootEntries() {
|
||||
AddRootEntry();
|
||||
AddGcRootsEntry();
|
||||
SnapshotObjectId id = HeapObjectsMap::kGcRootsFirstSubrootId;
|
||||
for (int tag = 0; tag < VisitorSynchronization::kNumberOfSyncTags; tag++) {
|
||||
AddGcSubrootEntry(tag, id);
|
||||
id += HeapObjectsMap::kObjectIdStep;
|
||||
}
|
||||
DCHECK(HeapObjectsMap::kFirstAvailableObjectId == id);
|
||||
}
|
||||
|
||||
|
||||
HeapEntry* HeapSnapshot::AddRootEntry() {
|
||||
DCHECK(root_index_ == HeapEntry::kNoEntry);
|
||||
DCHECK(entries_.is_empty()); // Root entry must be the first one.
|
||||
@ -243,15 +254,11 @@ HeapEntry* HeapSnapshot::AddGcRootsEntry() {
|
||||
}
|
||||
|
||||
|
||||
HeapEntry* HeapSnapshot::AddGcSubrootEntry(int tag) {
|
||||
HeapEntry* HeapSnapshot::AddGcSubrootEntry(int tag, SnapshotObjectId id) {
|
||||
DCHECK(gc_subroot_indexes_[tag] == HeapEntry::kNoEntry);
|
||||
DCHECK(0 <= tag && tag < VisitorSynchronization::kNumberOfSyncTags);
|
||||
HeapEntry* entry = AddEntry(
|
||||
HeapEntry::kSynthetic,
|
||||
VisitorSynchronization::kTagNames[tag],
|
||||
HeapObjectsMap::GetNthGcSubrootId(tag),
|
||||
0,
|
||||
0);
|
||||
HeapEntry* entry = AddEntry(HeapEntry::kSynthetic,
|
||||
VisitorSynchronization::kTagNames[tag], id, 0, 0);
|
||||
gc_subroot_indexes_[tag] = entry->index();
|
||||
return entry;
|
||||
}
|
||||
@ -771,20 +778,6 @@ void HeapObjectsSet::SetTag(Object* obj, const char* tag) {
|
||||
}
|
||||
|
||||
|
||||
HeapObject* const V8HeapExplorer::kInternalRootObject =
|
||||
reinterpret_cast<HeapObject*>(
|
||||
static_cast<intptr_t>(HeapObjectsMap::kInternalRootObjectId));
|
||||
HeapObject* const V8HeapExplorer::kGcRootsObject =
|
||||
reinterpret_cast<HeapObject*>(
|
||||
static_cast<intptr_t>(HeapObjectsMap::kGcRootsObjectId));
|
||||
HeapObject* const V8HeapExplorer::kFirstGcSubrootObject =
|
||||
reinterpret_cast<HeapObject*>(
|
||||
static_cast<intptr_t>(HeapObjectsMap::kGcRootsFirstSubrootId));
|
||||
HeapObject* const V8HeapExplorer::kLastGcSubrootObject =
|
||||
reinterpret_cast<HeapObject*>(
|
||||
static_cast<intptr_t>(HeapObjectsMap::kFirstAvailableObjectId));
|
||||
|
||||
|
||||
V8HeapExplorer::V8HeapExplorer(
|
||||
HeapSnapshot* snapshot,
|
||||
SnapshottingProgressReportingInterface* progress,
|
||||
@ -809,16 +802,7 @@ HeapEntry* V8HeapExplorer::AllocateEntry(HeapThing ptr) {
|
||||
|
||||
|
||||
HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object) {
|
||||
if (object == kInternalRootObject) {
|
||||
snapshot_->AddRootEntry();
|
||||
return snapshot_->root();
|
||||
} else if (object == kGcRootsObject) {
|
||||
HeapEntry* entry = snapshot_->AddGcRootsEntry();
|
||||
return entry;
|
||||
} else if (object >= kFirstGcSubrootObject && object < kLastGcSubrootObject) {
|
||||
HeapEntry* entry = snapshot_->AddGcSubrootEntry(GetGcSubrootOrder(object));
|
||||
return entry;
|
||||
} else if (object->IsJSFunction()) {
|
||||
if (object->IsJSFunction()) {
|
||||
JSFunction* func = JSFunction::cast(object);
|
||||
SharedFunctionInfo* shared = func->shared();
|
||||
const char* name = shared->bound() ? "native_bind" :
|
||||
@ -965,41 +949,6 @@ class SnapshotFiller {
|
||||
};
|
||||
|
||||
|
||||
class GcSubrootsEnumerator : public ObjectVisitor {
|
||||
public:
|
||||
GcSubrootsEnumerator(
|
||||
SnapshotFiller* filler, V8HeapExplorer* explorer)
|
||||
: filler_(filler),
|
||||
explorer_(explorer),
|
||||
previous_object_count_(0),
|
||||
object_count_(0) {
|
||||
}
|
||||
void VisitPointers(Object** start, Object** end) {
|
||||
object_count_ += end - start;
|
||||
}
|
||||
void Synchronize(VisitorSynchronization::SyncTag tag) {
|
||||
// Skip empty subroots.
|
||||
if (previous_object_count_ != object_count_) {
|
||||
previous_object_count_ = object_count_;
|
||||
filler_->AddEntry(V8HeapExplorer::GetNthGcSubrootObject(tag), explorer_);
|
||||
}
|
||||
}
|
||||
private:
|
||||
SnapshotFiller* filler_;
|
||||
V8HeapExplorer* explorer_;
|
||||
intptr_t previous_object_count_;
|
||||
intptr_t object_count_;
|
||||
};
|
||||
|
||||
|
||||
void V8HeapExplorer::AddRootEntries(SnapshotFiller* filler) {
|
||||
filler->AddEntry(kInternalRootObject, this);
|
||||
filler->AddEntry(kGcRootsObject, this);
|
||||
GcSubrootsEnumerator enumerator(filler, this);
|
||||
heap_->IterateRoots(&enumerator, VISIT_ALL);
|
||||
}
|
||||
|
||||
|
||||
const char* V8HeapExplorer::GetSystemEntryName(HeapObject* object) {
|
||||
switch (object->map()->instance_type()) {
|
||||
case MAP_TYPE:
|
||||
@ -1855,9 +1804,6 @@ class RootsReferencesExtractor : public ObjectVisitor {
|
||||
void FillReferences(V8HeapExplorer* explorer) {
|
||||
DCHECK(strong_references_.length() <= all_references_.length());
|
||||
Builtins* builtins = heap_->isolate()->builtins();
|
||||
for (int i = 0; i < reference_tags_.length(); ++i) {
|
||||
explorer->SetGcRootsReference(reference_tags_[i].tag);
|
||||
}
|
||||
int strong_index = 0, all_index = 0, tags_index = 0, builtin_index = 0;
|
||||
while (all_index < all_references_.length()) {
|
||||
bool is_strong = strong_index < strong_references_.length()
|
||||
@ -1900,10 +1846,15 @@ bool V8HeapExplorer::IterateAndExtractReferences(
|
||||
SnapshotFiller* filler) {
|
||||
filler_ = filler;
|
||||
|
||||
// Create references to the synthetic roots.
|
||||
SetRootGcRootsReference();
|
||||
for (int tag = 0; tag < VisitorSynchronization::kNumberOfSyncTags; tag++) {
|
||||
SetGcRootsReference(static_cast<VisitorSynchronization::SyncTag>(tag));
|
||||
}
|
||||
|
||||
// Make sure builtin code objects get their builtin tags
|
||||
// first. Otherwise a particular JSFunction object could set
|
||||
// its custom name to a generic builtin.
|
||||
SetRootGcRootsReference();
|
||||
RootsReferencesExtractor extractor(heap_);
|
||||
heap_->IterateRoots(&extractor, VISIT_ONLY_STRONG);
|
||||
extractor.SetCollectingAllReferences();
|
||||
@ -2619,6 +2570,8 @@ bool HeapSnapshotGenerator::GenerateSnapshot() {
|
||||
debug_heap->Verify();
|
||||
#endif
|
||||
|
||||
snapshot_->AddSyntheticRootEntries();
|
||||
|
||||
if (!FillReferences()) return false;
|
||||
|
||||
snapshot_->FillChildren();
|
||||
@ -2659,7 +2612,6 @@ void HeapSnapshotGenerator::SetProgressTotal(int iterations_count) {
|
||||
|
||||
bool HeapSnapshotGenerator::FillReferences() {
|
||||
SnapshotFiller filler(snapshot_, &entries_);
|
||||
v8_heap_explorer_.AddRootEntries(&filler);
|
||||
return v8_heap_explorer_.IterateAndExtractReferences(&filler)
|
||||
&& dom_explorer_.IterateAndExtractReferences(&filler);
|
||||
}
|
||||
|
@ -100,7 +100,7 @@ class HeapEntry BASE_EMBEDDED {
|
||||
Type type() { return static_cast<Type>(type_); }
|
||||
const char* name() { return name_; }
|
||||
void set_name(const char* name) { name_ = name; }
|
||||
inline SnapshotObjectId id() { return id_; }
|
||||
SnapshotObjectId id() { return id_; }
|
||||
size_t self_size() { return self_size_; }
|
||||
unsigned trace_node_id() const { return trace_node_id_; }
|
||||
INLINE(int index() const);
|
||||
@ -154,7 +154,6 @@ class HeapSnapshot {
|
||||
size_t RawSnapshotSize() const;
|
||||
HeapEntry* root() { return &entries_[root_index_]; }
|
||||
HeapEntry* gc_roots() { return &entries_[gc_roots_index_]; }
|
||||
HeapEntry* natives_root() { return &entries_[natives_root_index_]; }
|
||||
HeapEntry* gc_subroot(int index) {
|
||||
return &entries_[gc_subroot_indexes_[index]];
|
||||
}
|
||||
@ -171,10 +170,7 @@ class HeapSnapshot {
|
||||
SnapshotObjectId id,
|
||||
size_t size,
|
||||
unsigned trace_node_id);
|
||||
HeapEntry* AddRootEntry();
|
||||
HeapEntry* AddGcRootsEntry();
|
||||
HeapEntry* AddGcSubrootEntry(int tag);
|
||||
HeapEntry* AddNativesRootEntry();
|
||||
void AddSyntheticRootEntries();
|
||||
HeapEntry* GetEntryById(SnapshotObjectId id);
|
||||
List<HeapEntry*>* GetSortedEntriesList();
|
||||
void FillChildren();
|
||||
@ -183,12 +179,15 @@ class HeapSnapshot {
|
||||
void PrintEntriesSize();
|
||||
|
||||
private:
|
||||
HeapEntry* AddRootEntry();
|
||||
HeapEntry* AddGcRootsEntry();
|
||||
HeapEntry* AddGcSubrootEntry(int tag, SnapshotObjectId id);
|
||||
|
||||
HeapProfiler* profiler_;
|
||||
const char* title_;
|
||||
unsigned uid_;
|
||||
int root_index_;
|
||||
int gc_roots_index_;
|
||||
int natives_root_index_;
|
||||
int gc_subroot_indexes_[VisitorSynchronization::kNumberOfSyncTags];
|
||||
List<HeapEntry> entries_;
|
||||
List<HeapGraphEdge> edges_;
|
||||
@ -223,12 +222,10 @@ class HeapObjectsMap {
|
||||
size_t GetUsedMemorySize() const;
|
||||
|
||||
SnapshotObjectId GenerateId(v8::RetainedObjectInfo* info);
|
||||
static inline SnapshotObjectId GetNthGcSubrootId(int delta);
|
||||
|
||||
static const int kObjectIdStep = 2;
|
||||
static const SnapshotObjectId kInternalRootObjectId;
|
||||
static const SnapshotObjectId kGcRootsObjectId;
|
||||
static const SnapshotObjectId kNativesRootObjectId;
|
||||
static const SnapshotObjectId kGcRootsFirstSubrootId;
|
||||
static const SnapshotObjectId kFirstAvailableObjectId;
|
||||
|
||||
@ -348,8 +345,6 @@ class V8HeapExplorer : public HeapEntriesAllocator {
|
||||
|
||||
static String* GetConstructorName(JSObject* object);
|
||||
|
||||
static HeapObject* const kInternalRootObject;
|
||||
|
||||
private:
|
||||
typedef bool (V8HeapExplorer::*ExtractReferencesMethod)(int entry,
|
||||
HeapObject* object);
|
||||
@ -450,9 +445,6 @@ class V8HeapExplorer : public HeapEntriesAllocator {
|
||||
|
||||
HeapEntry* GetEntry(Object* obj);
|
||||
|
||||
static inline HeapObject* GetNthGcSubrootObject(int delta);
|
||||
static inline int GetGcSubrootOrder(HeapObject* subroot);
|
||||
|
||||
Heap* heap_;
|
||||
HeapSnapshot* snapshot_;
|
||||
StringsStorage* names_;
|
||||
@ -465,12 +457,7 @@ class V8HeapExplorer : public HeapEntriesAllocator {
|
||||
HeapObjectsSet weak_containers_;
|
||||
v8::HeapProfiler::ObjectNameResolver* global_object_name_resolver_;
|
||||
|
||||
static HeapObject* const kGcRootsObject;
|
||||
static HeapObject* const kFirstGcSubrootObject;
|
||||
static HeapObject* const kLastGcSubrootObject;
|
||||
|
||||
friend class IndexedReferencesExtractor;
|
||||
friend class GcSubrootsEnumerator;
|
||||
friend class RootsReferencesExtractor;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(V8HeapExplorer);
|
||||
|
Loading…
Reference in New Issue
Block a user