Commit efa249a8 authored by Andrew Comminos's avatar Andrew Comminos Committed by Commit Bot

[cpu-profiler] Expose parent pointer in a CpuProfileNode

Consumers can use this to derive the full stack from sampled leaf nodes
without having to flatten the tree.

Bug: v8:8999
Change-Id: I42c638dd2c757837b0c03514c204be0182653291
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1525877Reviewed-by: 's avatarPeter Marshall <petermarshall@chromium.org>
Reviewed-by: 's avatarAlexei Filippov <alph@chromium.org>
Reviewed-by: 's avatarYang Guo <yangguo@chromium.org>
Commit-Queue: Peter Marshall <petermarshall@chromium.org>
Cr-Commit-Position: refs/heads/master@{#60309}
parent f0446262
...@@ -206,6 +206,9 @@ class V8_EXPORT CpuProfileNode { ...@@ -206,6 +206,9 @@ class V8_EXPORT CpuProfileNode {
/** Retrieves a child node by index. */ /** Retrieves a child node by index. */
const CpuProfileNode* GetChild(int index) const; const CpuProfileNode* GetChild(int index) const;
/** Retrieves the ancestor node, or null if the root. */
const CpuProfileNode* GetParent() const;
/** Retrieves deopt infos for the node. */ /** Retrieves deopt infos for the node. */
const std::vector<CpuProfileDeoptInfo>& GetDeoptInfos() const; const std::vector<CpuProfileDeoptInfo>& GetDeoptInfos() const;
......
...@@ -10038,6 +10038,11 @@ const CpuProfileNode* CpuProfileNode::GetChild(int index) const { ...@@ -10038,6 +10038,11 @@ const CpuProfileNode* CpuProfileNode::GetChild(int index) const {
return reinterpret_cast<const CpuProfileNode*>(child); return reinterpret_cast<const CpuProfileNode*>(child);
} }
const CpuProfileNode* CpuProfileNode::GetParent() const {
const i::ProfileNode* parent =
reinterpret_cast<const i::ProfileNode*>(this)->parent();
return reinterpret_cast<const CpuProfileNode*>(parent);
}
const std::vector<CpuProfileDeoptInfo>& CpuProfileNode::GetDeoptInfos() const { const std::vector<CpuProfileDeoptInfo>& CpuProfileNode::GetDeoptInfos() const {
const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this); const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
......
...@@ -1880,7 +1880,8 @@ static void CheckFunctionDetails(v8::Isolate* isolate, ...@@ -1880,7 +1880,8 @@ static void CheckFunctionDetails(v8::Isolate* isolate,
const v8::CpuProfileNode* node, const v8::CpuProfileNode* node,
const char* name, const char* script_name, const char* name, const char* script_name,
bool is_shared_cross_origin, int script_id, bool is_shared_cross_origin, int script_id,
int line, int column) { int line, int column,
const v8::CpuProfileNode* parent) {
v8::Local<v8::Context> context = isolate->GetCurrentContext(); v8::Local<v8::Context> context = isolate->GetCurrentContext();
CHECK(v8_str(name)->Equals(context, node->GetFunctionName()).FromJust()); CHECK(v8_str(name)->Equals(context, node->GetFunctionName()).FromJust());
CHECK_EQ(0, strcmp(name, node->GetFunctionNameStr())); CHECK_EQ(0, strcmp(name, node->GetFunctionNameStr()));
...@@ -1891,6 +1892,7 @@ static void CheckFunctionDetails(v8::Isolate* isolate, ...@@ -1891,6 +1892,7 @@ static void CheckFunctionDetails(v8::Isolate* isolate,
CHECK_EQ(script_id, node->GetScriptId()); CHECK_EQ(script_id, node->GetScriptId());
CHECK_EQ(line, node->GetLineNumber()); CHECK_EQ(line, node->GetLineNumber());
CHECK_EQ(column, node->GetColumnNumber()); CHECK_EQ(column, node->GetColumnNumber());
CHECK_EQ(parent, node->GetParent());
} }
TEST(FunctionDetails) { TEST(FunctionDetails) {
...@@ -1925,18 +1927,19 @@ TEST(FunctionDetails) { ...@@ -1925,18 +1927,19 @@ TEST(FunctionDetails) {
// 0 foo 18 #4 TryCatchStatement script_a:2 // 0 foo 18 #4 TryCatchStatement script_a:2
// 1 bar 18 #5 no reason script_a:3 // 1 bar 18 #5 no reason script_a:3
const v8::CpuProfileNode* root = profile->GetTopDownRoot(); const v8::CpuProfileNode* root = profile->GetTopDownRoot();
CHECK_EQ(root->GetParent(), nullptr);
const v8::CpuProfileNode* script = GetChild(env, root, ""); const v8::CpuProfileNode* script = GetChild(env, root, "");
CheckFunctionDetails(env->GetIsolate(), script, "", "script_b", true, CheckFunctionDetails(env->GetIsolate(), script, "", "script_b", true,
script_b->GetUnboundScript()->GetId(), 1, 1); script_b->GetUnboundScript()->GetId(), 1, 1, root);
const v8::CpuProfileNode* baz = GetChild(env, script, "baz"); const v8::CpuProfileNode* baz = GetChild(env, script, "baz");
CheckFunctionDetails(env->GetIsolate(), baz, "baz", "script_b", true, CheckFunctionDetails(env->GetIsolate(), baz, "baz", "script_b", true,
script_b->GetUnboundScript()->GetId(), 3, 16); script_b->GetUnboundScript()->GetId(), 3, 16, script);
const v8::CpuProfileNode* foo = GetChild(env, baz, "foo"); const v8::CpuProfileNode* foo = GetChild(env, baz, "foo");
CheckFunctionDetails(env->GetIsolate(), foo, "foo", "script_a", false, CheckFunctionDetails(env->GetIsolate(), foo, "foo", "script_a", false,
script_a->GetUnboundScript()->GetId(), 4, 1); script_a->GetUnboundScript()->GetId(), 4, 1, baz);
const v8::CpuProfileNode* bar = GetChild(env, foo, "bar"); const v8::CpuProfileNode* bar = GetChild(env, foo, "bar");
CheckFunctionDetails(env->GetIsolate(), bar, "bar", "script_a", false, CheckFunctionDetails(env->GetIsolate(), bar, "bar", "script_a", false,
script_a->GetUnboundScript()->GetId(), 5, 14); script_a->GetUnboundScript()->GetId(), 5, 14, foo);
} }
TEST(FunctionDetailsInlining) { TEST(FunctionDetailsInlining) {
...@@ -2005,18 +2008,19 @@ TEST(FunctionDetailsInlining) { ...@@ -2005,18 +2008,19 @@ TEST(FunctionDetailsInlining) {
// 0 startProfiling 0 #3 // 0 startProfiling 0 #3
const v8::CpuProfileNode* root = profile->GetTopDownRoot(); const v8::CpuProfileNode* root = profile->GetTopDownRoot();
CHECK_EQ(root->GetParent(), nullptr);
const v8::CpuProfileNode* script = GetChild(env, root, ""); const v8::CpuProfileNode* script = GetChild(env, root, "");
CheckFunctionDetails(env->GetIsolate(), script, "", "script_a", false, CheckFunctionDetails(env->GetIsolate(), script, "", "script_a", false,
script_a->GetUnboundScript()->GetId(), 1, 1); script_a->GetUnboundScript()->GetId(), 1, 1, root);
const v8::CpuProfileNode* alpha = FindChild(env, script, "alpha"); const v8::CpuProfileNode* alpha = FindChild(env, script, "alpha");
// Return early if profiling didn't sample alpha. // Return early if profiling didn't sample alpha.
if (!alpha) return; if (!alpha) return;
CheckFunctionDetails(env->GetIsolate(), alpha, "alpha", "script_a", false, CheckFunctionDetails(env->GetIsolate(), alpha, "alpha", "script_a", false,
script_a->GetUnboundScript()->GetId(), 1, 15); script_a->GetUnboundScript()->GetId(), 1, 15, script);
const v8::CpuProfileNode* beta = FindChild(env, alpha, "beta"); const v8::CpuProfileNode* beta = FindChild(env, alpha, "beta");
if (!beta) return; if (!beta) return;
CheckFunctionDetails(env->GetIsolate(), beta, "beta", "script_b", true, CheckFunctionDetails(env->GetIsolate(), beta, "beta", "script_b", true,
script_b->GetUnboundScript()->GetId(), 1, 14); script_b->GetUnboundScript()->GetId(), 1, 14, alpha);
} }
TEST(DontStopOnFinishedProfileDelete) { TEST(DontStopOnFinishedProfileDelete) {
......
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