[heap-profiler] Remove the old RetainerInfo mechanism.
Bug: chromium:749490 Cq-Include-Trybots: luci.chromium.try:linux_chromium_rel_ng Change-Id: I4ae6883dd5ed5f313e21af20c29e560c73c33675 Reviewed-on: https://chromium-review.googlesource.com/c/948903 Commit-Queue: Ulan Degenbaev <ulan@chromium.org> Reviewed-by: Alexei Filippov <alph@chromium.org> Cr-Commit-Position: refs/heads/master@{#59076}
This commit is contained in:
parent
e2846ea6e4
commit
ab10dae929
@ -746,33 +746,6 @@ class V8_EXPORT HeapProfiler {
|
||||
kSamplingForceGC = 1 << 0,
|
||||
};
|
||||
|
||||
typedef std::unordered_set<const v8::PersistentBase<v8::Value>*>
|
||||
RetainerChildren;
|
||||
typedef std::vector<std::pair<v8::RetainedObjectInfo*, RetainerChildren>>
|
||||
RetainerGroups;
|
||||
typedef std::vector<std::pair<const v8::PersistentBase<v8::Value>*,
|
||||
const v8::PersistentBase<v8::Value>*>>
|
||||
RetainerEdges;
|
||||
|
||||
struct RetainerInfos {
|
||||
RetainerGroups groups;
|
||||
RetainerEdges edges;
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback function invoked to retrieve all RetainerInfos from the embedder.
|
||||
*/
|
||||
typedef RetainerInfos (*GetRetainerInfosCallback)(v8::Isolate* isolate);
|
||||
|
||||
/**
|
||||
* Callback function invoked for obtaining RetainedObjectInfo for
|
||||
* the given JavaScript wrapper object. It is prohibited to enter V8
|
||||
* while the callback is running: only getters on the handle and
|
||||
* GetPointerFromInternalField on the objects are allowed.
|
||||
*/
|
||||
typedef RetainedObjectInfo* (*WrapperInfoCallback)(uint16_t class_id,
|
||||
Local<Value> wrapper);
|
||||
|
||||
/**
|
||||
* Callback function invoked during heap snapshot generation to retrieve
|
||||
* the embedder object graph. The callback should use graph->AddEdge(..) to
|
||||
@ -925,16 +898,6 @@ class V8_EXPORT HeapProfiler {
|
||||
*/
|
||||
void DeleteAllHeapSnapshots();
|
||||
|
||||
/** Binds a callback to embedder's class ID. */
|
||||
V8_DEPRECATED(
|
||||
"Use AddBuildEmbedderGraphCallback to provide info about embedder nodes",
|
||||
void SetWrapperClassInfoProvider(uint16_t class_id,
|
||||
WrapperInfoCallback callback));
|
||||
|
||||
V8_DEPRECATED(
|
||||
"Use AddBuildEmbedderGraphCallback to provide info about embedder nodes",
|
||||
void SetGetRetainerInfosCallback(GetRetainerInfosCallback callback));
|
||||
|
||||
V8_DEPRECATED(
|
||||
"Use AddBuildEmbedderGraphCallback to provide info about embedder nodes",
|
||||
void SetBuildEmbedderGraphCallback(
|
||||
@ -958,80 +921,6 @@ class V8_EXPORT HeapProfiler {
|
||||
HeapProfiler& operator=(const HeapProfiler&);
|
||||
};
|
||||
|
||||
/**
|
||||
* Interface for providing information about embedder's objects
|
||||
* held by global handles. This information is reported in two ways:
|
||||
*
|
||||
* 1. When calling AddObjectGroup, an embedder may pass
|
||||
* RetainedObjectInfo instance describing the group. To collect
|
||||
* this information while taking a heap snapshot, V8 calls GC
|
||||
* prologue and epilogue callbacks.
|
||||
*
|
||||
* 2. When a heap snapshot is collected, V8 additionally
|
||||
* requests RetainedObjectInfos for persistent handles that
|
||||
* were not previously reported via AddObjectGroup.
|
||||
*
|
||||
* Thus, if an embedder wants to provide information about native
|
||||
* objects for heap snapshots, it can do it in a GC prologue
|
||||
* handler, and / or by assigning wrapper class ids in the following way:
|
||||
*
|
||||
* 1. Bind a callback to class id by calling SetWrapperClassInfoProvider.
|
||||
* 2. Call SetWrapperClassId on certain persistent handles.
|
||||
*
|
||||
* V8 takes ownership of RetainedObjectInfo instances passed to it and
|
||||
* keeps them alive only during snapshot collection. Afterwards, they
|
||||
* are freed by calling the Dispose class function.
|
||||
*/
|
||||
class V8_EXPORT RetainedObjectInfo { // NOLINT
|
||||
public:
|
||||
/** Called by V8 when it no longer needs an instance. */
|
||||
virtual void Dispose() = 0;
|
||||
|
||||
/** Returns whether two instances are equivalent. */
|
||||
virtual bool IsEquivalent(RetainedObjectInfo* other) = 0;
|
||||
|
||||
/**
|
||||
* Returns hash value for the instance. Equivalent instances
|
||||
* must have the same hash value.
|
||||
*/
|
||||
virtual intptr_t GetHash() = 0;
|
||||
|
||||
/**
|
||||
* Returns human-readable label. It must be a null-terminated UTF-8
|
||||
* encoded string. V8 copies its contents during a call to GetLabel.
|
||||
*/
|
||||
virtual const char* GetLabel() = 0;
|
||||
|
||||
/**
|
||||
* Returns human-readable group label. It must be a null-terminated UTF-8
|
||||
* encoded string. V8 copies its contents during a call to GetGroupLabel.
|
||||
* Heap snapshot generator will collect all the group names, create
|
||||
* top level entries with these names and attach the objects to the
|
||||
* corresponding top level group objects. There is a default
|
||||
* implementation which is required because embedders don't have their
|
||||
* own implementation yet.
|
||||
*/
|
||||
virtual const char* GetGroupLabel() { return GetLabel(); }
|
||||
|
||||
/**
|
||||
* Returns element count in case if a global handle retains
|
||||
* a subgraph by holding one of its nodes.
|
||||
*/
|
||||
virtual intptr_t GetElementCount() { return -1; }
|
||||
|
||||
/** Returns embedder's object size in bytes. */
|
||||
virtual intptr_t GetSizeInBytes() { return -1; }
|
||||
|
||||
protected:
|
||||
RetainedObjectInfo() = default;
|
||||
virtual ~RetainedObjectInfo() = default;
|
||||
|
||||
private:
|
||||
RetainedObjectInfo(const RetainedObjectInfo&);
|
||||
RetainedObjectInfo& operator=(const RetainedObjectInfo&);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A struct for exporting HeapStats data from V8, using "push" model.
|
||||
* See HeapProfiler::GetHeapStats.
|
||||
|
@ -576,8 +576,7 @@ template <class T> class PersistentBase {
|
||||
V8_INLINE bool IsWeak() const;
|
||||
|
||||
/**
|
||||
* Assigns a wrapper class ID to the handle. See RetainedObjectInfo interface
|
||||
* description in v8-profiler.h for details.
|
||||
* Assigns a wrapper class ID to the handle.
|
||||
*/
|
||||
V8_INLINE void SetWrapperClassId(uint16_t class_id);
|
||||
|
||||
@ -6870,8 +6869,6 @@ class V8_EXPORT HeapCodeStatistics {
|
||||
friend class Isolate;
|
||||
};
|
||||
|
||||
class RetainedObjectInfo;
|
||||
|
||||
/**
|
||||
* A JIT code event is issued each time code is added, moved or removed.
|
||||
*
|
||||
|
13
src/api.cc
13
src/api.cc
@ -10369,19 +10369,6 @@ void HeapProfiler::DeleteAllHeapSnapshots() {
|
||||
reinterpret_cast<i::HeapProfiler*>(this)->DeleteAllSnapshots();
|
||||
}
|
||||
|
||||
|
||||
void HeapProfiler::SetWrapperClassInfoProvider(uint16_t class_id,
|
||||
WrapperInfoCallback callback) {
|
||||
reinterpret_cast<i::HeapProfiler*>(this)->DefineWrapperClass(class_id,
|
||||
callback);
|
||||
}
|
||||
|
||||
void HeapProfiler::SetGetRetainerInfosCallback(
|
||||
GetRetainerInfosCallback callback) {
|
||||
reinterpret_cast<i::HeapProfiler*>(this)->SetGetRetainerInfosCallback(
|
||||
callback);
|
||||
}
|
||||
|
||||
void HeapProfiler::SetBuildEmbedderGraphCallback(
|
||||
LegacyBuildEmbedderGraphCallback callback) {
|
||||
reinterpret_cast<i::HeapProfiler*>(this)->AddBuildEmbedderGraphCallback(
|
||||
|
@ -40,38 +40,6 @@ void HeapProfiler::RemoveSnapshot(HeapSnapshot* snapshot) {
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
void HeapProfiler::DefineWrapperClass(
|
||||
uint16_t class_id, v8::HeapProfiler::WrapperInfoCallback callback) {
|
||||
DCHECK_NE(class_id, v8::HeapProfiler::kPersistentHandleNoClassId);
|
||||
if (wrapper_callbacks_.size() <= class_id) {
|
||||
wrapper_callbacks_.insert(wrapper_callbacks_.end(),
|
||||
class_id - wrapper_callbacks_.size() + 1,
|
||||
nullptr);
|
||||
}
|
||||
wrapper_callbacks_[class_id] = callback;
|
||||
}
|
||||
|
||||
v8::RetainedObjectInfo* HeapProfiler::ExecuteWrapperClassCallback(
|
||||
uint16_t class_id, Handle<Object> wrapper) {
|
||||
if (wrapper_callbacks_.size() <= class_id) return nullptr;
|
||||
return wrapper_callbacks_[class_id](class_id, Utils::ToLocal(wrapper));
|
||||
}
|
||||
|
||||
void HeapProfiler::SetGetRetainerInfosCallback(
|
||||
v8::HeapProfiler::GetRetainerInfosCallback callback) {
|
||||
get_retainer_infos_callback_ = callback;
|
||||
}
|
||||
|
||||
v8::HeapProfiler::RetainerInfos HeapProfiler::GetRetainerInfos(
|
||||
Isolate* isolate) {
|
||||
v8::HeapProfiler::RetainerInfos infos;
|
||||
if (get_retainer_infos_callback_ != nullptr)
|
||||
infos =
|
||||
get_retainer_infos_callback_(reinterpret_cast<v8::Isolate*>(isolate));
|
||||
return infos;
|
||||
}
|
||||
|
||||
void HeapProfiler::AddBuildEmbedderGraphCallback(
|
||||
v8::HeapProfiler::BuildEmbedderGraphCallback callback, void* data) {
|
||||
build_embedder_graph_callbacks_.push_back({callback, data});
|
||||
|
@ -61,16 +61,6 @@ class HeapProfiler : public HeapObjectAllocationTracker {
|
||||
|
||||
void UpdateObjectSizeEvent(Address addr, int size) override;
|
||||
|
||||
void DefineWrapperClass(
|
||||
uint16_t class_id, v8::HeapProfiler::WrapperInfoCallback callback);
|
||||
|
||||
v8::RetainedObjectInfo* ExecuteWrapperClassCallback(uint16_t class_id,
|
||||
Handle<Object> wrapper);
|
||||
|
||||
void SetGetRetainerInfosCallback(
|
||||
v8::HeapProfiler::GetRetainerInfosCallback callback);
|
||||
v8::HeapProfiler::RetainerInfos GetRetainerInfos(Isolate* isolate);
|
||||
|
||||
void AddBuildEmbedderGraphCallback(
|
||||
v8::HeapProfiler::BuildEmbedderGraphCallback callback, void* data);
|
||||
void RemoveBuildEmbedderGraphCallback(
|
||||
@ -100,13 +90,10 @@ class HeapProfiler : public HeapObjectAllocationTracker {
|
||||
std::unique_ptr<HeapObjectsMap> ids_;
|
||||
std::vector<std::unique_ptr<HeapSnapshot>> snapshots_;
|
||||
std::unique_ptr<StringsStorage> names_;
|
||||
std::vector<v8::HeapProfiler::WrapperInfoCallback> wrapper_callbacks_;
|
||||
std::unique_ptr<AllocationTracker> allocation_tracker_;
|
||||
bool is_tracking_object_moves_;
|
||||
base::Mutex profiler_mutex_;
|
||||
std::unique_ptr<SamplingHeapProfiler> sampling_heap_profiler_;
|
||||
v8::HeapProfiler::GetRetainerInfosCallback get_retainer_infos_callback_ =
|
||||
nullptr;
|
||||
std::vector<std::pair<v8::HeapProfiler::BuildEmbedderGraphCallback, void*>>
|
||||
build_embedder_graph_callbacks_;
|
||||
|
||||
|
@ -489,20 +489,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)
|
||||
@ -1825,57 +1811,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,124 +1862,14 @@ 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()),
|
||||
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) {
|
||||
@ -2104,81 +1929,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,
|
||||
@ -2268,8 +2023,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;
|
||||
}
|
||||
|
||||
|
@ -262,8 +262,6 @@ class HeapObjectsMap {
|
||||
int64_t* timestamp_us);
|
||||
const std::vector<TimeInterval>& samples() const { return time_intervals_; }
|
||||
|
||||
SnapshotObjectId GenerateId(v8::RetainedObjectInfo* info);
|
||||
|
||||
static const int kObjectIdStep = 2;
|
||||
static const SnapshotObjectId kInternalRootObjectId;
|
||||
static const SnapshotObjectId kGcRootsObjectId;
|
||||
@ -444,63 +442,22 @@ class V8HeapExplorer : public HeapEntriesAllocator {
|
||||
DISALLOW_COPY_AND_ASSIGN(V8HeapExplorer);
|
||||
};
|
||||
|
||||
|
||||
class NativeGroupRetainedObjectInfo;
|
||||
|
||||
|
||||
// An implementation of retained native objects extractor.
|
||||
class NativeObjectsExplorer {
|
||||
public:
|
||||
NativeObjectsExplorer(HeapSnapshot* snapshot,
|
||||
SnapshottingProgressReportingInterface* progress);
|
||||
virtual ~NativeObjectsExplorer();
|
||||
int EstimateObjectsCount();
|
||||
bool IterateAndExtractReferences(HeapSnapshotGenerator* generator);
|
||||
|
||||
private:
|
||||
void FillRetainedObjects();
|
||||
void FillEdges();
|
||||
std::vector<HeapObject>* GetVectorMaybeDisposeInfo(
|
||||
v8::RetainedObjectInfo* info);
|
||||
void SetNativeRootReference(v8::RetainedObjectInfo* info);
|
||||
void SetRootNativeRootsReference();
|
||||
void SetWrapperNativeReferences(HeapObject wrapper,
|
||||
v8::RetainedObjectInfo* info);
|
||||
void VisitSubtreeWrapper(Handle<Object> p, uint16_t class_id);
|
||||
|
||||
struct RetainedInfoHasher {
|
||||
std::size_t operator()(v8::RetainedObjectInfo* info) const {
|
||||
return ComputeUnseededHash(static_cast<uint32_t>(info->GetHash()));
|
||||
}
|
||||
};
|
||||
struct RetainedInfoEquals {
|
||||
bool operator()(v8::RetainedObjectInfo* info1,
|
||||
v8::RetainedObjectInfo* info2) const {
|
||||
return info1 == info2 || info1->IsEquivalent(info2);
|
||||
}
|
||||
};
|
||||
|
||||
NativeGroupRetainedObjectInfo* FindOrAddGroupInfo(const char* label);
|
||||
|
||||
HeapEntry* EntryForEmbedderGraphNode(EmbedderGraph::Node* node);
|
||||
|
||||
Isolate* isolate_;
|
||||
HeapSnapshot* snapshot_;
|
||||
StringsStorage* names_;
|
||||
bool embedder_queried_;
|
||||
std::unordered_set<Object, Object::Hasher> in_groups_;
|
||||
std::unordered_map<v8::RetainedObjectInfo*, std::vector<HeapObject>*,
|
||||
RetainedInfoHasher, RetainedInfoEquals>
|
||||
objects_by_info_;
|
||||
std::unordered_map<const char*, NativeGroupRetainedObjectInfo*,
|
||||
SeededStringHasher, StringEquals>
|
||||
native_groups_;
|
||||
std::unique_ptr<HeapEntriesAllocator> synthetic_entries_allocator_;
|
||||
std::unique_ptr<HeapEntriesAllocator> native_entries_allocator_;
|
||||
std::unique_ptr<HeapEntriesAllocator> embedder_graph_entries_allocator_;
|
||||
// Used during references extraction.
|
||||
HeapSnapshotGenerator* generator_ = nullptr;
|
||||
v8::HeapProfiler::RetainerEdges edges_;
|
||||
|
||||
static HeapThing const kNativesRootObject;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user