diff --git a/common.gypi b/common.gypi index 1940e3fabbced4..ec877db9900e0e 100644 --- a/common.gypi +++ b/common.gypi @@ -29,7 +29,7 @@ # Reset this number to 0 on major V8 upgrades. # Increment by one for each non-official patch applied to deps/v8. - 'v8_embedder_string': '-node.15', + 'v8_embedder_string': '-node.16', # Enable disassembler for `--print-code` v8 options 'v8_enable_disassembler': 1, diff --git a/deps/v8/include/v8-profiler.h b/deps/v8/include/v8-profiler.h index 0e09d8732f2b72..bcb53f1446004a 100644 --- a/deps/v8/include/v8-profiler.h +++ b/deps/v8/include/v8-profiler.h @@ -686,11 +686,14 @@ class V8_EXPORT EmbedderGraph { virtual Node* AddNode(std::unique_ptr node) = 0; /** - * Adds an edge that represents a strong reference from the given node - * |from| to the given node |to|. The nodes must be added to the graph + * Adds an edge that represents a strong reference from the given + * node |from| to the given node |to|. The nodes must be added to the graph * before calling this function. + * + * If name is nullptr, the edge will have auto-increment indexes, otherwise + * it will be named accordingly. */ - virtual void AddEdge(Node* from, Node* to) = 0; + virtual void AddEdge(Node* from, Node* to, const char* name = nullptr) = 0; virtual ~EmbedderGraph() = default; }; diff --git a/deps/v8/src/profiler/heap-snapshot-generator.cc b/deps/v8/src/profiler/heap-snapshot-generator.cc index 841d4e16e57209..6564250d2e6672 100644 --- a/deps/v8/src/profiler/heap-snapshot-generator.cc +++ b/deps/v8/src/profiler/heap-snapshot-generator.cc @@ -1989,6 +1989,7 @@ class EmbedderGraphImpl : public EmbedderGraph { struct Edge { Node* from; Node* to; + const char* name; }; class V8NodeImpl : public Node { @@ -2025,7 +2026,9 @@ class EmbedderGraphImpl : public EmbedderGraph { return result; } - void AddEdge(Node* from, Node* to) final { edges_.push_back({from, to}); } + void AddEdge(Node* from, Node* to, const char* name) final { + edges_.push_back({from, to, name}); + } const std::vector>& nodes() { return nodes_; } const std::vector& edges() { return edges_; } @@ -2318,8 +2321,13 @@ bool NativeObjectsExplorer::IterateAndExtractReferences( int from_index = from->index(); HeapEntry* to = EntryForEmbedderGraphNode(edge.to); if (to) { - filler_->SetIndexedAutoIndexReference(HeapGraphEdge::kElement, - from_index, to); + if (edge.name == nullptr) { + filler_->SetIndexedAutoIndexReference(HeapGraphEdge::kElement, + from_index, to); + } else { + filler_->SetNamedReference(HeapGraphEdge::kInternal, from_index, + edge.name, to); + } } } } else { diff --git a/deps/v8/test/cctest/test-heap-profiler.cc b/deps/v8/test/cctest/test-heap-profiler.cc index 70dc07d3dc872e..f164355bf8c25f 100644 --- a/deps/v8/test/cctest/test-heap-profiler.cc +++ b/deps/v8/test/cctest/test-heap-profiler.cc @@ -112,6 +112,12 @@ static const char* GetName(const v8::HeapGraphNode* node) { ->name(); } +static const char* GetName(const v8::HeapGraphEdge* edge) { + return const_cast( + reinterpret_cast(edge)) + ->name(); +} + static size_t GetSize(const v8::HeapGraphNode* node) { return const_cast(reinterpret_cast(node)) ->self_size(); @@ -128,6 +134,18 @@ static const v8::HeapGraphNode* GetChildByName(const v8::HeapGraphNode* node, return nullptr; } +static const v8::HeapGraphEdge* GetEdgeByChildName( + const v8::HeapGraphNode* node, const char* name) { + for (int i = 0, count = node->GetChildrenCount(); i < count; ++i) { + const v8::HeapGraphEdge* edge = node->GetChild(i); + const v8::HeapGraphNode* child = edge->GetToNode(); + if (!strcmp(name, GetName(child))) { + return edge; + } + } + return nullptr; +} + static const v8::HeapGraphNode* GetRootChild(const v8::HeapSnapshot* snapshot, const char* name) { return GetChildByName(snapshot->GetRoot(), name); @@ -2986,6 +3004,71 @@ TEST(EmbedderGraph) { CheckEmbedderGraphSnapshot(env->GetIsolate(), snapshot); } +void BuildEmbedderGraphWithNamedEdges(v8::Isolate* v8_isolate, + v8::EmbedderGraph* graph, void* data) { + using Node = v8::EmbedderGraph::Node; + Node* global_node = graph->V8Node(*global_object_pointer); + Node* embedder_node_A = graph->AddNode( + std::unique_ptr(new EmbedderNode("EmbedderNodeA", 10))); + Node* embedder_node_B = graph->AddNode( + std::unique_ptr(new EmbedderNode("EmbedderNodeB", 20))); + Node* embedder_node_C = graph->AddNode( + std::unique_ptr(new EmbedderNode("EmbedderNodeC", 30))); + graph->AddEdge(global_node, embedder_node_A, "global_to_a"); + graph->AddEdge(embedder_node_A, embedder_node_B, "a_to_b"); + graph->AddEdge(embedder_node_B, embedder_node_C); +} + +void CheckEmbedderGraphWithNamedEdges(v8::Isolate* isolate, + const v8::HeapSnapshot* snapshot) { + const v8::HeapGraphNode* global = GetGlobalObject(snapshot); + const v8::HeapGraphEdge* global_to_a = + GetEdgeByChildName(global, "EmbedderNodeA"); + CHECK(global_to_a); + CHECK_EQ(v8::HeapGraphEdge::kInternal, global_to_a->GetType()); + CHECK(global_to_a->GetName()->IsString()); + CHECK_EQ(0, strcmp("global_to_a", GetName(global_to_a))); + const v8::HeapGraphNode* embedder_node_A = global_to_a->GetToNode(); + CHECK_EQ(0, strcmp("EmbedderNodeA", GetName(embedder_node_A))); + CHECK_EQ(10, GetSize(embedder_node_A)); + + const v8::HeapGraphEdge* a_to_b = + GetEdgeByChildName(embedder_node_A, "EmbedderNodeB"); + CHECK(a_to_b); + CHECK(a_to_b->GetName()->IsString()); + CHECK_EQ(0, strcmp("a_to_b", GetName(a_to_b))); + CHECK_EQ(v8::HeapGraphEdge::kInternal, a_to_b->GetType()); + const v8::HeapGraphNode* embedder_node_B = a_to_b->GetToNode(); + CHECK_EQ(0, strcmp("EmbedderNodeB", GetName(embedder_node_B))); + CHECK_EQ(20, GetSize(embedder_node_B)); + + const v8::HeapGraphEdge* b_to_c = + GetEdgeByChildName(embedder_node_B, "EmbedderNodeC"); + CHECK(b_to_c); + CHECK(b_to_c->GetName()->IsNumber()); + CHECK_EQ(v8::HeapGraphEdge::kElement, b_to_c->GetType()); + const v8::HeapGraphNode* embedder_node_C = b_to_c->GetToNode(); + CHECK_EQ(0, strcmp("EmbedderNodeC", GetName(embedder_node_C))); + CHECK_EQ(30, GetSize(embedder_node_C)); +} + +TEST(EmbedderGraphWithNamedEdges) { + i::FLAG_heap_profiler_use_embedder_graph = true; + LocalContext env; + v8::HandleScope scope(env->GetIsolate()); + i::Isolate* isolate = reinterpret_cast(env->GetIsolate()); + v8::Local global_object = + v8::Utils::ToLocal(i::Handle( + (isolate->context()->native_context()->global_object()), isolate)); + global_object_pointer = &global_object; + v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler(); + heap_profiler->AddBuildEmbedderGraphCallback(BuildEmbedderGraphWithNamedEdges, + nullptr); + const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot(); + CHECK(ValidateSnapshot(snapshot)); + CheckEmbedderGraphWithNamedEdges(env->GetIsolate(), snapshot); +} + struct GraphBuildingContext { int counter = 0; };