aboutsummaryrefslogtreecommitdiff
path: root/deps/v8/src/profiler/heap-snapshot-generator.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/profiler/heap-snapshot-generator.cc')
-rw-r--r--deps/v8/src/profiler/heap-snapshot-generator.cc277
1 files changed, 17 insertions, 260 deletions
diff --git a/deps/v8/src/profiler/heap-snapshot-generator.cc b/deps/v8/src/profiler/heap-snapshot-generator.cc
index 17daea1964..4d6aa029f7 100644
--- a/deps/v8/src/profiler/heap-snapshot-generator.cc
+++ b/deps/v8/src/profiler/heap-snapshot-generator.cc
@@ -14,6 +14,7 @@
#include "src/layout-descriptor.h"
#include "src/objects-body-descriptors.h"
#include "src/objects-inl.h"
+#include "src/objects/allocation-site-inl.h"
#include "src/objects/api-callbacks.h"
#include "src/objects/cell-inl.h"
#include "src/objects/feedback-cell-inl.h"
@@ -31,7 +32,8 @@
#include "src/profiler/heap-profiler.h"
#include "src/profiler/heap-snapshot-generator-inl.h"
#include "src/prototype.h"
-#include "src/transitions.h"
+#include "src/transitions-inl.h"
+#include "src/vector.h"
#include "src/visitors.h"
namespace v8 {
@@ -181,10 +183,10 @@ const char* HeapEntry::TypeAsString() {
HeapSnapshot::HeapSnapshot(HeapProfiler* profiler) : profiler_(profiler) {
// It is very important to keep objects that form a heap snapshot
// as small as possible. Check assumptions about data structure sizes.
- STATIC_ASSERT((kTaggedSize == 4 && sizeof(HeapGraphEdge) == 12) ||
- (kTaggedSize == 8 && sizeof(HeapGraphEdge) == 24));
- STATIC_ASSERT((kTaggedSize == 4 && sizeof(HeapEntry) == 28) ||
- (kTaggedSize == 8 && sizeof(HeapEntry) == 40));
+ STATIC_ASSERT((kSystemPointerSize == 4 && sizeof(HeapGraphEdge) == 12) ||
+ (kSystemPointerSize == 8 && sizeof(HeapGraphEdge) == 24));
+ STATIC_ASSERT((kSystemPointerSize == 4 && sizeof(HeapEntry) == 28) ||
+ (kSystemPointerSize == 8 && sizeof(HeapEntry) == 40));
memset(&gc_subroot_entries_, 0, sizeof(gc_subroot_entries_));
}
@@ -489,20 +491,6 @@ void HeapObjectsMap::RemoveDeadEntries() {
entries_map_.occupancy());
}
-
-SnapshotObjectId HeapObjectsMap::GenerateId(v8::RetainedObjectInfo* info) {
- SnapshotObjectId id = static_cast<SnapshotObjectId>(info->GetHash());
- const char* label = info->GetLabel();
- id ^= StringHasher::HashSequentialString(label,
- static_cast<int>(strlen(label)),
- heap_->HashSeed());
- intptr_t element_count = info->GetElementCount();
- if (element_count != -1) {
- id ^= ComputeUnseededHash(static_cast<uint32_t>(element_count));
- }
- return id << 1;
-}
-
V8HeapExplorer::V8HeapExplorer(HeapSnapshot* snapshot,
SnapshottingProgressReportingInterface* progress,
v8::HeapProfiler::ObjectNameResolver* resolver)
@@ -802,8 +790,9 @@ void V8HeapExplorer::ExtractJSObjectReferences(HeapEntry* entry,
ExtractPropertyReferences(js_obj, entry);
ExtractElementReferences(js_obj, entry);
ExtractInternalReferences(js_obj, entry);
- PrototypeIterator iter(heap_->isolate(), js_obj);
- ReadOnlyRoots roots(heap_);
+ Isolate* isolate = Isolate::FromHeap(heap_);
+ PrototypeIterator iter(isolate, js_obj);
+ ReadOnlyRoots roots(isolate);
SetPropertyReference(entry, roots.proto_string(), iter.GetCurrent());
if (obj->IsJSBoundFunction()) {
JSBoundFunction js_fun = JSBoundFunction::cast(obj);
@@ -824,7 +813,7 @@ void V8HeapExplorer::ExtractJSObjectReferences(HeapEntry* entry,
JSFunction js_fun = JSFunction::cast(js_obj);
if (js_fun->has_prototype_slot()) {
Object proto_or_map = js_fun->prototype_or_initial_map();
- if (!proto_or_map->IsTheHole(heap_->isolate())) {
+ if (!proto_or_map->IsTheHole(isolate)) {
if (!proto_or_map->IsMap()) {
SetPropertyReference(entry, roots.prototype_string(), proto_or_map,
nullptr,
@@ -1708,7 +1697,7 @@ void V8HeapExplorer::SetGcSubrootReference(Root root, const char* description,
const char* V8HeapExplorer::GetStrongGcSubrootName(Object object) {
if (strong_gc_subroot_names_.empty()) {
- Isolate* isolate = heap_->isolate();
+ Isolate* isolate = Isolate::FromHeap(heap_);
for (RootIndex root_index = RootIndex::kFirstStrongOrReadOnlyRoot;
root_index <= RootIndex::kLastStrongOrReadOnlyRoot; ++root_index) {
const char* name = RootsTable::name(root_index);
@@ -1753,7 +1742,7 @@ class GlobalObjectsEnumerator : public RootVisitor {
// Modifies heap. Must not be run during heap traversal.
void V8HeapExplorer::TagGlobalObjects() {
- Isolate* isolate = heap_->isolate();
+ Isolate* isolate = Isolate::FromHeap(heap_);
HandleScope scope(isolate);
GlobalObjectsEnumerator enumerator;
isolate->global_handles()->IterateAllRoots(&enumerator);
@@ -1825,57 +1814,6 @@ class EmbedderGraphImpl : public EmbedderGraph {
std::vector<Edge> edges_;
};
-class GlobalHandlesExtractor : public PersistentHandleVisitor {
- public:
- explicit GlobalHandlesExtractor(NativeObjectsExplorer* explorer)
- : explorer_(explorer) {}
- ~GlobalHandlesExtractor() override = default;
- void VisitPersistentHandle(Persistent<Value>* value,
- uint16_t class_id) override {
- Handle<Object> object = Utils::OpenPersistent(value);
- explorer_->VisitSubtreeWrapper(object, class_id);
- }
-
- private:
- NativeObjectsExplorer* explorer_;
-};
-
-
-class BasicHeapEntriesAllocator : public HeapEntriesAllocator {
- public:
- BasicHeapEntriesAllocator(
- HeapSnapshot* snapshot,
- HeapEntry::Type entries_type)
- : snapshot_(snapshot),
- names_(snapshot_->profiler()->names()),
- heap_object_map_(snapshot_->profiler()->heap_object_map()),
- entries_type_(entries_type) {
- }
- HeapEntry* AllocateEntry(HeapThing ptr) override;
- private:
- HeapSnapshot* snapshot_;
- StringsStorage* names_;
- HeapObjectsMap* heap_object_map_;
- HeapEntry::Type entries_type_;
-};
-
-
-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
- ? names_->GetFormatted("%s / %" V8PRIdPTR " entries",
- info->GetLabel(), elements)
- : names_->GetCopy(info->GetLabel());
- return snapshot_->AddEntry(
- entries_type_,
- name,
- heap_object_map_->GenerateId(info),
- size != -1 ? static_cast<int>(size) : 0,
- 0);
-}
-
class EmbedderGraphEntriesAllocator : public HeapEntriesAllocator {
public:
explicit EmbedderGraphEntriesAllocator(HeapSnapshot* snapshot)
@@ -1927,125 +1865,15 @@ HeapEntry* EmbedderGraphEntriesAllocator::AllocateEntry(HeapThing ptr) {
static_cast<int>(size), 0);
}
-class NativeGroupRetainedObjectInfo : public v8::RetainedObjectInfo {
- public:
- explicit NativeGroupRetainedObjectInfo(const char* label)
- : disposed_(false),
- hash_(reinterpret_cast<intptr_t>(label)),
- label_(label) {}
-
- ~NativeGroupRetainedObjectInfo() override = default;
- void Dispose() override {
- CHECK(!disposed_);
- disposed_ = true;
- delete this;
- }
- bool IsEquivalent(RetainedObjectInfo* other) override {
- return hash_ == other->GetHash() && !strcmp(label_, other->GetLabel());
- }
- intptr_t GetHash() override { return hash_; }
- const char* GetLabel() override { return label_; }
-
- private:
- bool disposed_;
- intptr_t hash_;
- const char* label_;
-};
-
NativeObjectsExplorer::NativeObjectsExplorer(
HeapSnapshot* snapshot, SnapshottingProgressReportingInterface* progress)
- : isolate_(snapshot->profiler()->heap_object_map()->heap()->isolate()),
+ : isolate_(
+ Isolate::FromHeap(snapshot->profiler()->heap_object_map()->heap())),
snapshot_(snapshot),
names_(snapshot_->profiler()->names()),
- embedder_queried_(false),
- native_groups_(0, SeededStringHasher(isolate_->heap()->HashSeed())),
- synthetic_entries_allocator_(
- new BasicHeapEntriesAllocator(snapshot, HeapEntry::kSynthetic)),
- native_entries_allocator_(
- new BasicHeapEntriesAllocator(snapshot, HeapEntry::kNative)),
embedder_graph_entries_allocator_(
new EmbedderGraphEntriesAllocator(snapshot)) {}
-NativeObjectsExplorer::~NativeObjectsExplorer() {
- for (auto map_entry : objects_by_info_) {
- v8::RetainedObjectInfo* info = map_entry.first;
- info->Dispose();
- std::vector<HeapObject>* objects = map_entry.second;
- delete objects;
- }
- for (auto map_entry : native_groups_) {
- NativeGroupRetainedObjectInfo* info = map_entry.second;
- info->Dispose();
- }
-}
-
-
-int NativeObjectsExplorer::EstimateObjectsCount() {
- FillRetainedObjects();
- return static_cast<int>(objects_by_info_.size());
-}
-
-
-void NativeObjectsExplorer::FillRetainedObjects() {
- if (embedder_queried_) return;
- v8::HandleScope scope(reinterpret_cast<v8::Isolate*>(isolate_));
- v8::HeapProfiler::RetainerInfos infos =
- snapshot_->profiler()->GetRetainerInfos(isolate_);
- for (auto& pair : infos.groups) {
- std::vector<HeapObject>* info = GetVectorMaybeDisposeInfo(pair.first);
- for (auto& persistent : pair.second) {
- if (persistent->IsEmpty()) continue;
-
- Handle<Object> object = v8::Utils::OpenHandle(
- *persistent->Get(reinterpret_cast<v8::Isolate*>(isolate_)));
- DCHECK(!object.is_null());
- HeapObject heap_object = HeapObject::cast(*object);
- info->push_back(heap_object);
- in_groups_.insert(heap_object);
- }
- }
-
- // Record objects that are not in ObjectGroups, but have class ID.
- GlobalHandlesExtractor extractor(this);
- isolate_->global_handles()->IterateAllRootsWithClassIds(&extractor);
-
- edges_ = std::move(infos.edges);
- embedder_queried_ = true;
-}
-
-void NativeObjectsExplorer::FillEdges() {
- v8::HandleScope scope(reinterpret_cast<v8::Isolate*>(isolate_));
- // Fill in actual edges found.
- for (auto& pair : edges_) {
- if (pair.first->IsEmpty() || pair.second->IsEmpty()) continue;
-
- Handle<Object> parent_object = v8::Utils::OpenHandle(
- *pair.first->Get(reinterpret_cast<v8::Isolate*>(isolate_)));
- HeapObject parent = HeapObject::cast(*parent_object);
- HeapEntry* parent_entry = generator_->FindOrAddEntry(
- reinterpret_cast<void*>(parent.ptr()), native_entries_allocator_.get());
- DCHECK_NOT_NULL(parent_entry);
- Handle<Object> child_object = v8::Utils::OpenHandle(
- *pair.second->Get(reinterpret_cast<v8::Isolate*>(isolate_)));
- HeapObject child = HeapObject::cast(*child_object);
- HeapEntry* child_entry = generator_->FindOrAddEntry(
- reinterpret_cast<void*>(child.ptr()), native_entries_allocator_.get());
- parent_entry->SetNamedReference(HeapGraphEdge::kInternal, "native",
- child_entry);
- }
- edges_.clear();
-}
-
-std::vector<HeapObject>* NativeObjectsExplorer::GetVectorMaybeDisposeInfo(
- v8::RetainedObjectInfo* info) {
- if (objects_by_info_.count(info)) {
- info->Dispose();
- } else {
- objects_by_info_[info] = new std::vector<HeapObject>();
- }
- return objects_by_info_[info];
-}
-
HeapEntry* NativeObjectsExplorer::EntryForEmbedderGraphNode(
EmbedderGraphImpl::Node* node) {
EmbedderGraphImpl::Node* wrapper = node->WrapperNode();
@@ -2104,81 +1932,11 @@ bool NativeObjectsExplorer::IterateAndExtractReferences(
from->SetNamedReference(HeapGraphEdge::kInternal, edge.name, to);
}
}
- } else {
- FillRetainedObjects();
- FillEdges();
- if (EstimateObjectsCount() > 0) {
- for (auto map_entry : objects_by_info_) {
- v8::RetainedObjectInfo* info = map_entry.first;
- SetNativeRootReference(info);
- std::vector<HeapObject>* objects = map_entry.second;
- for (HeapObject object : *objects) {
- SetWrapperNativeReferences(object, info);
- }
- }
- SetRootNativeRootsReference();
- }
}
generator_ = nullptr;
return true;
}
-NativeGroupRetainedObjectInfo* NativeObjectsExplorer::FindOrAddGroupInfo(
- const char* label) {
- const char* label_copy = names_->GetCopy(label);
- if (!native_groups_.count(label_copy)) {
- native_groups_[label_copy] = new NativeGroupRetainedObjectInfo(label);
- }
- return native_groups_[label_copy];
-}
-
-void NativeObjectsExplorer::SetNativeRootReference(
- v8::RetainedObjectInfo* info) {
- HeapEntry* child_entry =
- generator_->FindOrAddEntry(info, native_entries_allocator_.get());
- DCHECK_NOT_NULL(child_entry);
- NativeGroupRetainedObjectInfo* group_info =
- FindOrAddGroupInfo(info->GetGroupLabel());
- HeapEntry* group_entry = generator_->FindOrAddEntry(
- group_info, synthetic_entries_allocator_.get());
- group_entry->SetNamedAutoIndexReference(HeapGraphEdge::kInternal, nullptr,
- child_entry, names_);
-}
-
-void NativeObjectsExplorer::SetWrapperNativeReferences(
- HeapObject wrapper, v8::RetainedObjectInfo* info) {
- HeapEntry* wrapper_entry =
- generator_->FindEntry(reinterpret_cast<void*>(wrapper.ptr()));
- DCHECK_NOT_NULL(wrapper_entry);
- HeapEntry* info_entry =
- generator_->FindOrAddEntry(info, native_entries_allocator_.get());
- DCHECK_NOT_NULL(info_entry);
- wrapper_entry->SetNamedReference(HeapGraphEdge::kInternal, "native",
- info_entry);
- info_entry->SetIndexedAutoIndexReference(HeapGraphEdge::kElement,
- wrapper_entry);
-}
-
-void NativeObjectsExplorer::SetRootNativeRootsReference() {
- for (auto map_entry : native_groups_) {
- NativeGroupRetainedObjectInfo* group_info = map_entry.second;
- HeapEntry* group_entry =
- generator_->FindOrAddEntry(group_info, native_entries_allocator_.get());
- DCHECK_NOT_NULL(group_entry);
- snapshot_->root()->SetIndexedAutoIndexReference(HeapGraphEdge::kElement,
- group_entry);
- }
-}
-
-void NativeObjectsExplorer::VisitSubtreeWrapper(Handle<Object> p,
- uint16_t class_id) {
- if (in_groups_.count(*p)) return;
- v8::RetainedObjectInfo* info =
- isolate_->heap_profiler()->ExecuteWrapperClassCallback(class_id, p);
- if (info == nullptr) return;
- GetVectorMaybeDisposeInfo(info)->push_back(HeapObject::cast(*p));
-}
-
HeapSnapshotGenerator::HeapSnapshotGenerator(
HeapSnapshot* snapshot,
v8::ActivityControl* control,
@@ -2218,7 +1976,7 @@ bool HeapSnapshotGenerator::GenerateSnapshot() {
heap_->PreciseCollectAllGarbage(Heap::kNoGCFlags,
GarbageCollectionReason::kHeapProfiler);
- NullContextScope null_context_scope(heap_->isolate());
+ NullContextScope null_context_scope(Isolate::FromHeap(heap_));
#ifdef VERIFY_HEAP
Heap* debug_heap = heap_;
@@ -2268,8 +2026,7 @@ void HeapSnapshotGenerator::InitProgressCounter() {
// Only the forced ProgressReport() at the end of GenerateSnapshot()
// should signal that the work is finished because signalling finished twice
// breaks the DevTools frontend.
- progress_total_ = v8_heap_explorer_.EstimateObjectsCount() +
- dom_explorer_.EstimateObjectsCount() + 1;
+ progress_total_ = v8_heap_explorer_.EstimateObjectsCount() + 1;
progress_counter_ = 0;
}