Skip to content

Commit

Permalink
[cpu-profiler] Fix script name when recording inlining info
Browse files Browse the repository at this point in the history
Use the script name from the shared function info to create an
inline entry. Otherwise functions are attributed to the wrong file
in the CpuProfileNode.

See googleapis/cloud-profiler-nodejs#89


Bug: v8:7203, v8:7241
Change-Id: I7a7524ad68a295efd35ef94295cd48f823376e07
Reviewed-on: https://chromium-review.googlesource.com/845624
Reviewed-by: Jaroslav Sevcik <[email protected]>
Commit-Queue: Franziska Hinkelmann <[email protected]>
Cr-Commit-Position: refs/heads/master@{#50324}
  • Loading branch information
fhinkel authored and Commit Bot committed Jan 2, 2018
1 parent 0f5328a commit c500aa9
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 1 deletion.
9 changes: 8 additions & 1 deletion src/profiler/profiler-listener.cc
Original file line number Diff line number Diff line change
Expand Up @@ -213,9 +213,16 @@ void ProfilerListener::RecordInliningInfo(CodeEntry* entry,
SharedFunctionInfo* shared_info = SharedFunctionInfo::cast(
deopt_input_data->LiteralArray()->get(shared_info_id));
if (!depth++) continue; // Skip the current function itself.

const char* resource_name =
(shared_info->script()->IsScript() &&
Script::cast(shared_info->script())->name()->IsName())
? GetName(Name::cast(Script::cast(shared_info->script())->name()))
: CodeEntry::kEmptyResourceName;

CodeEntry* inline_entry =
new CodeEntry(entry->tag(), GetFunctionName(shared_info->DebugName()),
CodeEntry::kEmptyNamePrefix, entry->resource_name(),
CodeEntry::kEmptyNamePrefix, resource_name,
CpuProfileNode::kNoLineNumberInfo,
CpuProfileNode::kNoColumnNumberInfo, nullptr,
code->instruction_start());
Expand Down
76 changes: 76 additions & 0 deletions test/cctest/test-cpu-profiler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1741,6 +1741,82 @@ TEST(FunctionDetails) {
script_a->GetUnboundScript()->GetId(), 5, 14);
}

TEST(FunctionDetailsInlining) {
if (!CcTest::i_isolate()->use_optimizer() || i::FLAG_always_opt) return;
i::FLAG_allow_natives_syntax = true;
v8::HandleScope scope(CcTest::isolate());
v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION);
v8::Context::Scope context_scope(env);
ProfilerHelper helper(env);

// alpha is in a_script, beta in b_script. beta is
// inlined in alpha, but it should be attributed to b_script.

v8::Local<v8::Script> script_b = CompileWithOrigin(
"function beta(k) {\n"
" let sum = 2;\n"
" for(let i = 0; i < k; i ++) {\n"
" sum += i;\n"
" sum = sum + 'a';\n"
" }\n"
" return sum;\n"
"}\n"
"\n",
"script_b");

v8::Local<v8::Script> script_a = CompileWithOrigin(
"function alpha(p) {\n"
" let res = beta(p);\n"
" res = res + res;\n"
" return res;\n"
"}\n"
"let p = 2;\n"
"\n"
"\n"
"// Warm up before profiling or the inlining doesn't happen.\n"
"p = alpha(p);\n"
"p = alpha(p);\n"
"%OptimizeFunctionOnNextCall(alpha);\n"
"p = alpha(p);\n"
"\n"
"\n"
"startProfiling();\n"
"for(let i = 0; i < 10000; i++) {\n"
" p = alpha(p);\n"
"}\n"
"stopProfiling();\n"
"\n"
"\n",
"script_a");

script_b->Run(env).ToLocalChecked();
script_a->Run(env).ToLocalChecked();

const v8::CpuProfile* profile = i::ProfilerExtension::last_profile;
const v8::CpuProfileNode* current = profile->GetTopDownRoot();
reinterpret_cast<ProfileNode*>(const_cast<v8::CpuProfileNode*>(current))
->Print(0);
// The tree should look like this:
// 0 (root) 0 #1
// 5 (program) 0 #6
// 2 14 #2 script_a:1
// ;;; deopted at script_id: 14 position: 299 with reason 'Insufficient
// type feedback for call'.
// 1 alpha 14 #4 script_a:1
// 9 beta 13 #5 script_b:0
// 0 startProfiling 0 #3

const v8::CpuProfileNode* root = profile->GetTopDownRoot();
const v8::CpuProfileNode* script = GetChild(env, root, "");
CheckFunctionDetails(env->GetIsolate(), script, "", "script_a",
script_a->GetUnboundScript()->GetId(), 1, 1);
const v8::CpuProfileNode* alpha = GetChild(env, script, "alpha");
CheckFunctionDetails(env->GetIsolate(), alpha, "alpha", "script_a",
script_a->GetUnboundScript()->GetId(), 1, 15);
const v8::CpuProfileNode* beta = GetChild(env, alpha, "beta");
CheckFunctionDetails(env->GetIsolate(), beta, "beta", "script_b",
script_b->GetUnboundScript()->GetId(), 0, 0);
}

TEST(DontStopOnFinishedProfileDelete) {
v8::HandleScope scope(CcTest::isolate());
Expand Down

0 comments on commit c500aa9

Please sign in to comment.