Commit 4186d8a5 authored by Leszek Swirski's avatar Leszek Swirski Committed by Commit Bot

[heap-profiler] Use handles for global object tags

Split GlobalObject tagging into collecting pairs of tags, followed by
writing those tags into an unordered_map after entering a safepoint
scope. This ensures that we follow moved global objects if they move
in the GCs between the tagging and the safepoint.

Bug: v8:11050
Change-Id: I333d50d000ec49e6c4218e71f0cc84a49b460ecf
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2494932
Auto-Submit: Leszek Swirski <leszeks@chromium.org>
Reviewed-by: 's avatarUlan Degenbaev <ulan@chromium.org>
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Cr-Commit-Position: refs/heads/master@{#70749}
parent 9cb14242
......@@ -7,6 +7,7 @@
#include <utility>
#include "src/api/api-inl.h"
#include "src/base/optional.h"
#include "src/codegen/assembler-inl.h"
#include "src/common/globals.h"
#include "src/debug/debug.h"
......@@ -598,8 +599,8 @@ HeapEntry* V8HeapExplorer::AddEntry(HeapObject object) {
const char* name = names_->GetName(
GetConstructorName(JSObject::cast(object)));
if (object.IsJSGlobalObject()) {
auto it = objects_tags_.find(JSGlobalObject::cast(object));
if (it != objects_tags_.end()) {
auto it = global_object_tag_map_.find(JSGlobalObject::cast(object));
if (it != global_object_tag_map_.end()) {
name = names_->GetFormatted("%s / %s", name, it->second);
}
}
......@@ -1822,22 +1823,26 @@ class GlobalObjectsEnumerator : public RootVisitor {
// Modifies heap. Must not be run during heap traversal.
void V8HeapExplorer::TagGlobalObjects() {
void V8HeapExplorer::CollectGlobalObjectsTags() {
if (!global_object_name_resolver_) return;
Isolate* isolate = Isolate::FromHeap(heap_);
HandleScope scope(isolate);
GlobalObjectsEnumerator enumerator(isolate);
isolate->global_handles()->IterateAllRoots(&enumerator);
std::vector<const char*> urls(enumerator.count());
for (int i = 0, l = enumerator.count(); i < l; ++i) {
urls[i] = global_object_name_resolver_
? global_object_name_resolver_->GetName(Utils::ToLocal(
Handle<JSObject>::cast(enumerator.at(i))))
: nullptr;
Handle<JSGlobalObject> obj = enumerator.at(i);
const char* tag = global_object_name_resolver_->GetName(
Utils::ToLocal(Handle<JSObject>::cast(obj)));
if (tag) {
global_object_tag_pairs_.emplace_back(obj, tag);
}
}
}
DisallowHeapAllocation no_allocation;
for (int i = 0, l = enumerator.count(); i < l; ++i) {
if (urls[i]) objects_tags_.emplace(*enumerator.at(i), urls[i]);
void V8HeapExplorer::MakeGlobalObjectTagMap(
const SafepointScope& safepoint_scope) {
for (const auto& pair : global_object_tag_pairs_) {
global_object_tag_map_.emplace(*pair.first, pair.second);
}
}
......@@ -2080,7 +2085,9 @@ class NullContextForSnapshotScope {
} // namespace
bool HeapSnapshotGenerator::GenerateSnapshot() {
v8_heap_explorer_.TagGlobalObjects();
Isolate* isolate = Isolate::FromHeap(heap_);
base::Optional<HandleScope> handle_scope(base::in_place, isolate);
v8_heap_explorer_.CollectGlobalObjectsTags();
// TODO(1562) Profiler assumes that any object that is in the heap after
// full GC is reachable from the root when computing dominators.
......@@ -2091,8 +2098,10 @@ bool HeapSnapshotGenerator::GenerateSnapshot() {
heap_->PreciseCollectAllGarbage(Heap::kNoGCFlags,
GarbageCollectionReason::kHeapProfiler);
NullContextForSnapshotScope null_context_scope(Isolate::FromHeap(heap_));
NullContextForSnapshotScope null_context_scope(isolate);
SafepointScope scope(heap_);
v8_heap_explorer_.MakeGlobalObjectTagMap(scope);
handle_scope.reset();
#ifdef VERIFY_HEAP
Heap* debug_heap = heap_;
......
......@@ -38,6 +38,7 @@ class JSGlobalObject;
class JSGlobalProxy;
class JSPromise;
class JSWeakCollection;
class SafepointScope;
struct SourceLocation {
SourceLocation(int entry_index, int scriptId, int line, int col)
......@@ -340,7 +341,8 @@ class V8_EXPORT_PRIVATE V8HeapExplorer : public HeapEntriesAllocator {
HeapEntry* AllocateEntry(HeapThing ptr) override;
int EstimateObjectsCount();
bool IterateAndExtractReferences(HeapSnapshotGenerator* generator);
void TagGlobalObjects();
void CollectGlobalObjectsTags();
void MakeGlobalObjectTagMap(const SafepointScope& safepoint_scope);
void TagBuiltinCodeObject(Code code, const char* name);
HeapEntry* AddEntry(Address address,
HeapEntry::Type type,
......@@ -447,7 +449,10 @@ class V8_EXPORT_PRIVATE V8HeapExplorer : public HeapEntriesAllocator {
HeapObjectsMap* heap_object_map_;
SnapshottingProgressReportingInterface* progress_;
HeapSnapshotGenerator* generator_ = nullptr;
std::unordered_map<JSGlobalObject, const char*, Object::Hasher> objects_tags_;
std::vector<std::pair<Handle<JSGlobalObject>, const char*>>
global_object_tag_pairs_;
std::unordered_map<JSGlobalObject, const char*, Object::Hasher>
global_object_tag_map_;
std::unordered_map<Object, const char*, Object::Hasher>
strong_gc_subroot_names_;
std::unordered_set<JSGlobalObject, Object::Hasher> user_roots_;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment