Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
deps: cherry-pick 6ee8345 from upstream V8
Original commit message:

    [heap-profiler] Allow embedder to specify edge names

    This patch adds a variant of EmbedderGraph::AddEdge() which
    allows the embedder to specify the name of an edge. The edges
    added without name are element edges with auto-incremented indexes
    while the edges added with names will be internal edges with
    the specified names for more meaningful output in the heap
    snapshot.

    Refs: #21741
    Bug: v8:7938
    Cq-Include-Trybots: luci.chromium.try:linux_chromium_rel_ng
    Change-Id: I8feefa2cf6911743e24b3b2024e0e849b0c65cd3
    Reviewed-on: https://chromium-review.googlesource.com/1133299
    Commit-Queue: Ulan Degenbaev <ulan@chromium.org>
    Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
    Cr-Commit-Position: refs/heads/master@{#54412}

Refs: v8/v8@6ee8345
  • Loading branch information
joyeecheung committed Aug 17, 2018
commit 2949154a4a279ff636baad0409f219df54b5229f
2 changes: 1 addition & 1 deletion common.gypi
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
9 changes: 6 additions & 3 deletions deps/v8/include/v8-profiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -686,11 +686,14 @@ class V8_EXPORT EmbedderGraph {
virtual Node* AddNode(std::unique_ptr<Node> 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;
};
Expand Down
14 changes: 11 additions & 3 deletions deps/v8/src/profiler/heap-snapshot-generator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1989,6 +1989,7 @@ class EmbedderGraphImpl : public EmbedderGraph {
struct Edge {
Node* from;
Node* to;
const char* name;
};

class V8NodeImpl : public Node {
Expand Down Expand Up @@ -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<std::unique_ptr<Node>>& nodes() { return nodes_; }
const std::vector<Edge>& edges() { return edges_; }
Expand Down Expand Up @@ -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 {
Expand Down
83 changes: 83 additions & 0 deletions deps/v8/test/cctest/test-heap-profiler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,12 @@ static const char* GetName(const v8::HeapGraphNode* node) {
->name();
}

static const char* GetName(const v8::HeapGraphEdge* edge) {
return const_cast<i::HeapGraphEdge*>(
reinterpret_cast<const i::HeapGraphEdge*>(edge))
->name();
}

static size_t GetSize(const v8::HeapGraphNode* node) {
return const_cast<i::HeapEntry*>(reinterpret_cast<const i::HeapEntry*>(node))
->self_size();
Expand All @@ -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);
Expand Down Expand Up @@ -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<Node>(new EmbedderNode("EmbedderNodeA", 10)));
Node* embedder_node_B = graph->AddNode(
std::unique_ptr<Node>(new EmbedderNode("EmbedderNodeB", 20)));
Node* embedder_node_C = graph->AddNode(
std::unique_ptr<Node>(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<i::Isolate*>(env->GetIsolate());
v8::Local<v8::Value> global_object =
v8::Utils::ToLocal(i::Handle<i::JSObject>(
(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;
};
Expand Down