diff options
Diffstat (limited to 'deps/v8/src/profiler/heap-snapshot-generator.cc')
-rw-r--r-- | deps/v8/src/profiler/heap-snapshot-generator.cc | 277 |
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; } |