From 355c5e3c955cf9f5ad4a2cfcdebbc7db2f945c9a Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Sat, 30 Jun 2018 21:09:21 +0200 Subject: [PATCH] deps: cherry-pick 555c811 from upstream V8 Original commit message: [api] Switch from `SetBuildEmbedderGraphCallback` to `AddBuildEmbedderGraphCallback` `SetBuildEmbedderGraphCallback`, unlike `SetWrapperClassInfoProvider`, assumes a monolithic embedder that can provide all necessary information. That is not the case for e.g. Node.js, which can e.g. provide multiple Node.js instances per V8 Isolate, as well as native addons that may allocate resources on their own. Cq-Include-Trybots: luci.chromium.try:linux_chromium_rel_ng Change-Id: Ib53dfde82416dd69934b08623e27d674a483ac2d Reviewed-on: https://chromium-review.googlesource.com/1082441 Commit-Queue: Ulan Degenbaev Reviewed-by: Ulan Degenbaev Reviewed-by: Yang Guo Cr-Commit-Position: refs/heads/master@{#53545} Refs: https://github.com/v8/v8/commit/555c811c0d44d9aaaccf8e76059ed24537b3f012 PR-URL: https://github.com/nodejs/node/pull/21741 Reviewed-By: James M Snell Reviewed-By: Joyee Cheung Reviewed-By: Refael Ackermann --- common.gypi | 2 +- deps/v8/include/v8-profiler.h | 22 +++-- deps/v8/src/api.cc | 22 ++++- deps/v8/src/profiler/heap-profiler.cc | 21 +++-- deps/v8/src/profiler/heap-profiler.h | 12 +-- deps/v8/test/cctest/test-heap-profiler.cc | 104 +++++++++++++++++++--- 6 files changed, 152 insertions(+), 31 deletions(-) diff --git a/common.gypi b/common.gypi index 9d74b46a8d5c70..a782cfbecb85e2 100644 --- a/common.gypi +++ b/common.gypi @@ -28,7 +28,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.14', + 'v8_embedder_string': '-node.15', # 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 5df9b2a217ea8e..c61027b3b94e45 100644 --- a/deps/v8/include/v8-profiler.h +++ b/deps/v8/include/v8-profiler.h @@ -636,7 +636,7 @@ class V8_EXPORT AllocationProfile { * Usage: * 1) Define derived class of EmbedderGraph::Node for embedder objects. * 2) Set the build embedder graph callback on the heap profiler using - * HeapProfiler::SetBuildEmbedderGraphCallback. + * HeapProfiler::AddBuildEmbedderGraphCallback. * 3) In the callback use graph->AddEdge(node1, node2) to add an edge from * node1 to node2. * 4) To represent references from/to V8 object, construct V8 nodes using @@ -736,7 +736,12 @@ class V8_EXPORT HeapProfiler { * The callback must not trigger garbage collection in V8. */ typedef void (*BuildEmbedderGraphCallback)(v8::Isolate* isolate, - v8::EmbedderGraph* graph); + v8::EmbedderGraph* graph, + void* data); + + /** TODO(addaleax): Remove */ + typedef void (*LegacyBuildEmbedderGraphCallback)(v8::Isolate* isolate, + v8::EmbedderGraph* graph); /** Returns the number of snapshots taken. */ int GetSnapshotCount(); @@ -878,15 +883,22 @@ class V8_EXPORT HeapProfiler { /** Binds a callback to embedder's class ID. */ V8_DEPRECATED( - "Use SetBuildEmbedderGraphCallback to provide info about embedder nodes", + "Use AddBuildEmbedderGraphCallback to provide info about embedder nodes", void SetWrapperClassInfoProvider(uint16_t class_id, WrapperInfoCallback callback)); V8_DEPRECATED( - "Use SetBuildEmbedderGraphCallback to provide info about embedder nodes", + "Use AddBuildEmbedderGraphCallback to provide info about embedder nodes", void SetGetRetainerInfosCallback(GetRetainerInfosCallback callback)); - void SetBuildEmbedderGraphCallback(BuildEmbedderGraphCallback callback); + V8_DEPRECATE_SOON( + "Use AddBuildEmbedderGraphCallback to provide info about embedder nodes", + void SetBuildEmbedderGraphCallback( + LegacyBuildEmbedderGraphCallback callback)); + void AddBuildEmbedderGraphCallback(BuildEmbedderGraphCallback callback, + void* data); + void RemoveBuildEmbedderGraphCallback(BuildEmbedderGraphCallback callback, + void* data); /** * Default value of persistent handle class ID. Must not be used to diff --git a/deps/v8/src/api.cc b/deps/v8/src/api.cc index a7f6d00f6fabf7..192ad90f83e55c 100644 --- a/deps/v8/src/api.cc +++ b/deps/v8/src/api.cc @@ -10558,9 +10558,25 @@ void HeapProfiler::SetGetRetainerInfosCallback( } void HeapProfiler::SetBuildEmbedderGraphCallback( - BuildEmbedderGraphCallback callback) { - reinterpret_cast(this)->SetBuildEmbedderGraphCallback( - callback); + LegacyBuildEmbedderGraphCallback callback) { + reinterpret_cast(this)->AddBuildEmbedderGraphCallback( + [](v8::Isolate* isolate, v8::EmbedderGraph* graph, void* data) { + reinterpret_cast(data)(isolate, + graph); + }, + reinterpret_cast(callback)); +} + +void HeapProfiler::AddBuildEmbedderGraphCallback( + BuildEmbedderGraphCallback callback, void* data) { + reinterpret_cast(this)->AddBuildEmbedderGraphCallback( + callback, data); +} + +void HeapProfiler::RemoveBuildEmbedderGraphCallback( + BuildEmbedderGraphCallback callback, void* data) { + reinterpret_cast(this)->RemoveBuildEmbedderGraphCallback( + callback, data); } v8::Testing::StressType internal::Testing::stress_type_ = diff --git a/deps/v8/src/profiler/heap-profiler.cc b/deps/v8/src/profiler/heap-profiler.cc index 7e0bcec97ae75e..2496e24b91cf18 100644 --- a/deps/v8/src/profiler/heap-profiler.cc +++ b/deps/v8/src/profiler/heap-profiler.cc @@ -69,16 +69,25 @@ v8::HeapProfiler::RetainerInfos HeapProfiler::GetRetainerInfos( return infos; } -void HeapProfiler::SetBuildEmbedderGraphCallback( - v8::HeapProfiler::BuildEmbedderGraphCallback callback) { - build_embedder_graph_callback_ = callback; +void HeapProfiler::AddBuildEmbedderGraphCallback( + v8::HeapProfiler::BuildEmbedderGraphCallback callback, void* data) { + build_embedder_graph_callbacks_.push_back({callback, data}); +} + +void HeapProfiler::RemoveBuildEmbedderGraphCallback( + v8::HeapProfiler::BuildEmbedderGraphCallback callback, void* data) { + auto it = std::find(build_embedder_graph_callbacks_.begin(), + build_embedder_graph_callbacks_.end(), + std::make_pair(callback, data)); + if (it != build_embedder_graph_callbacks_.end()) + build_embedder_graph_callbacks_.erase(it); } void HeapProfiler::BuildEmbedderGraph(Isolate* isolate, v8::EmbedderGraph* graph) { - if (build_embedder_graph_callback_ != nullptr) - build_embedder_graph_callback_(reinterpret_cast(isolate), - graph); + for (const auto& cb : build_embedder_graph_callbacks_) { + cb.first(reinterpret_cast(isolate), graph, cb.second); + } } HeapSnapshot* HeapProfiler::TakeSnapshot( diff --git a/deps/v8/src/profiler/heap-profiler.h b/deps/v8/src/profiler/heap-profiler.h index 507dd579bffb65..fc0b005e1c67ce 100644 --- a/deps/v8/src/profiler/heap-profiler.h +++ b/deps/v8/src/profiler/heap-profiler.h @@ -71,11 +71,13 @@ class HeapProfiler : public HeapObjectAllocationTracker { v8::HeapProfiler::GetRetainerInfosCallback callback); v8::HeapProfiler::RetainerInfos GetRetainerInfos(Isolate* isolate); - void SetBuildEmbedderGraphCallback( - v8::HeapProfiler::BuildEmbedderGraphCallback callback); + void AddBuildEmbedderGraphCallback( + v8::HeapProfiler::BuildEmbedderGraphCallback callback, void* data); + void RemoveBuildEmbedderGraphCallback( + v8::HeapProfiler::BuildEmbedderGraphCallback callback, void* data); void BuildEmbedderGraph(Isolate* isolate, v8::EmbedderGraph* graph); bool HasBuildEmbedderGraphCallback() { - return build_embedder_graph_callback_ != nullptr; + return !build_embedder_graph_callbacks_.empty(); } bool is_tracking_object_moves() const { return is_tracking_object_moves_; } @@ -103,8 +105,8 @@ class HeapProfiler : public HeapObjectAllocationTracker { std::unique_ptr sampling_heap_profiler_; v8::HeapProfiler::GetRetainerInfosCallback get_retainer_infos_callback_ = nullptr; - v8::HeapProfiler::BuildEmbedderGraphCallback build_embedder_graph_callback_ = - nullptr; + std::vector> + build_embedder_graph_callbacks_; DISALLOW_COPY_AND_ASSIGN(HeapProfiler); }; diff --git a/deps/v8/test/cctest/test-heap-profiler.cc b/deps/v8/test/cctest/test-heap-profiler.cc index 4372aa3d2e5205..eec739d109dcf1 100644 --- a/deps/v8/test/cctest/test-heap-profiler.cc +++ b/deps/v8/test/cctest/test-heap-profiler.cc @@ -1541,8 +1541,8 @@ class EmbedderGraphBuilder : public v8::PersistentHandleVisitor { graph->AddNode(std::unique_ptr(new Group("ccc-group"))); } - static void BuildEmbedderGraph(v8::Isolate* isolate, - v8::EmbedderGraph* graph) { + static void BuildEmbedderGraph(v8::Isolate* isolate, v8::EmbedderGraph* graph, + void* data) { EmbedderGraphBuilder builder(isolate, graph); isolate->VisitHandlesWithClassIds(&builder); } @@ -1604,8 +1604,8 @@ TEST(HeapSnapshotRetainedObjectInfo) { v8::HandleScope scope(isolate); v8::HeapProfiler* heap_profiler = isolate->GetHeapProfiler(); - heap_profiler->SetBuildEmbedderGraphCallback( - EmbedderGraphBuilder::BuildEmbedderGraph); + heap_profiler->AddBuildEmbedderGraphCallback( + EmbedderGraphBuilder::BuildEmbedderGraph, nullptr); v8::Persistent p_AAA(isolate, v8_str("AAA")); p_AAA.SetWrapperClassId(1); v8::Persistent p_BBB(isolate, v8_str("BBB")); @@ -2932,7 +2932,8 @@ class EmbedderRootNode : public EmbedderNode { // global object. v8::Local* global_object_pointer; -void BuildEmbedderGraph(v8::Isolate* v8_isolate, v8::EmbedderGraph* graph) { +void BuildEmbedderGraph(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( @@ -2979,12 +2980,92 @@ TEST(EmbedderGraph) { (isolate->context()->native_context()->global_object()))); global_object_pointer = &global_object; v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler(); - heap_profiler->SetBuildEmbedderGraphCallback(BuildEmbedderGraph); + heap_profiler->AddBuildEmbedderGraphCallback(BuildEmbedderGraph, nullptr); const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot(); CHECK(ValidateSnapshot(snapshot)); CheckEmbedderGraphSnapshot(env->GetIsolate(), snapshot); } +struct GraphBuildingContext { + int counter = 0; +}; + +void CheckEmbedderGraphSnapshotWithContext( + v8::Isolate* isolate, const v8::HeapSnapshot* snapshot, + const GraphBuildingContext* context) { + const v8::HeapGraphNode* global = GetGlobalObject(snapshot); + CHECK_GE(context->counter, 1); + CHECK_LE(context->counter, 2); + + const v8::HeapGraphNode* embedder_node_A = + GetChildByName(global, "EmbedderNodeA"); + CHECK_EQ(10, GetSize(embedder_node_A)); + + const v8::HeapGraphNode* embedder_node_B = + GetChildByName(global, "EmbedderNodeB"); + if (context->counter == 2) { + CHECK_NOT_NULL(embedder_node_B); + CHECK_EQ(20, GetSize(embedder_node_B)); + } else { + CHECK_NULL(embedder_node_B); + } +} + +void BuildEmbedderGraphWithContext(v8::Isolate* v8_isolate, + v8::EmbedderGraph* graph, void* data) { + using Node = v8::EmbedderGraph::Node; + GraphBuildingContext* context = static_cast(data); + Node* global_node = graph->V8Node(*global_object_pointer); + + CHECK_GE(context->counter, 0); + CHECK_LE(context->counter, 1); + switch (context->counter++) { + case 0: { + Node* embedder_node_A = graph->AddNode( + std::unique_ptr(new EmbedderNode("EmbedderNodeA", 10))); + graph->AddEdge(global_node, embedder_node_A); + break; + } + case 1: { + Node* embedder_node_B = graph->AddNode( + std::unique_ptr(new EmbedderNode("EmbedderNodeB", 20))); + graph->AddEdge(global_node, embedder_node_B); + break; + } + } +} + +TEST(EmbedderGraphMultipleCallbacks) { + 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()))); + global_object_pointer = &global_object; + v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler(); + GraphBuildingContext context; + + heap_profiler->AddBuildEmbedderGraphCallback(BuildEmbedderGraphWithContext, + &context); + heap_profiler->AddBuildEmbedderGraphCallback(BuildEmbedderGraphWithContext, + &context); + const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot(); + CHECK_EQ(context.counter, 2); + CHECK(ValidateSnapshot(snapshot)); + CheckEmbedderGraphSnapshotWithContext(env->GetIsolate(), snapshot, &context); + + heap_profiler->RemoveBuildEmbedderGraphCallback(BuildEmbedderGraphWithContext, + &context); + context.counter = 0; + + snapshot = heap_profiler->TakeHeapSnapshot(); + CHECK_EQ(context.counter, 1); + CHECK(ValidateSnapshot(snapshot)); + CheckEmbedderGraphSnapshotWithContext(env->GetIsolate(), snapshot, &context); +} + TEST(StrongHandleAnnotation) { LocalContext env; v8::HandleScope scope(env->GetIsolate()); @@ -3010,7 +3091,7 @@ TEST(StrongHandleAnnotation) { } void BuildEmbedderGraphWithWrapperNode(v8::Isolate* v8_isolate, - v8::EmbedderGraph* graph) { + v8::EmbedderGraph* graph, void* data) { using Node = v8::EmbedderGraph::Node; Node* global_node = graph->V8Node(*global_object_pointer); Node* wrapper_node = graph->AddNode( @@ -3041,8 +3122,8 @@ TEST(EmbedderGraphWithWrapperNode) { (isolate->context()->native_context()->global_object()))); global_object_pointer = &global_object; v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler(); - heap_profiler->SetBuildEmbedderGraphCallback( - BuildEmbedderGraphWithWrapperNode); + heap_profiler->AddBuildEmbedderGraphCallback( + BuildEmbedderGraphWithWrapperNode, nullptr); const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot(); CHECK(ValidateSnapshot(snapshot)); const v8::HeapGraphNode* global = GetGlobalObject(snapshot); @@ -3080,7 +3161,7 @@ class EmbedderNodeWithPrefix : public v8::EmbedderGraph::Node { }; void BuildEmbedderGraphWithPrefix(v8::Isolate* v8_isolate, - v8::EmbedderGraph* graph) { + v8::EmbedderGraph* graph, void* data) { using Node = v8::EmbedderGraph::Node; Node* global_node = graph->V8Node(*global_object_pointer); Node* node = graph->AddNode( @@ -3098,7 +3179,8 @@ TEST(EmbedderGraphWithPrefix) { (isolate->context()->native_context()->global_object()))); global_object_pointer = &global_object; v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler(); - heap_profiler->SetBuildEmbedderGraphCallback(BuildEmbedderGraphWithPrefix); + heap_profiler->AddBuildEmbedderGraphCallback(BuildEmbedderGraphWithPrefix, + nullptr); const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot(); CHECK(ValidateSnapshot(snapshot)); const v8::HeapGraphNode* global = GetGlobalObject(snapshot);