[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:
Ulan Degenbaev 2019-01-22 18:55:52 +01:00 committed by Commit Bot
parent e2846ea6e4
commit ab10dae929
7 changed files with 2 additions and 463 deletions

View File

@ -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.

View File

@ -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.
*

View File

@ -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(

View File

@ -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});

View File

@ -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_;

View File

@ -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;
}

View File

@ -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;