[cpu-profiler] Fix script name when recording inlining info
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 https://github.com/GoogleCloudPlatform/cloud-profiler-nodejs/issues/89 Bug: v8:7203, v8:7241 Change-Id: I8ea31943741770e6611275a9c93375922b934547 Reviewed-on: https://chromium-review.googlesource.com/848093 Reviewed-by: Jaroslav Sevcik <jarin@chromium.org> Commit-Queue: Franziska Hinkelmann <franzih@chromium.org> Cr-Commit-Position: refs/heads/master@{#50339}
This commit is contained in:
parent
10a8ae4173
commit
76c3ac58b0
@ -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());
|
||||
|
@ -1741,6 +1741,85 @@ 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 = FindChild(env, script, "alpha");
|
||||
// Return early if profiling didn't sample alpha.
|
||||
if (!alpha) return;
|
||||
CheckFunctionDetails(env->GetIsolate(), alpha, "alpha", "script_a",
|
||||
script_a->GetUnboundScript()->GetId(), 1, 15);
|
||||
const v8::CpuProfileNode* beta = FindChild(env, alpha, "beta");
|
||||
if (!beta) return;
|
||||
CheckFunctionDetails(env->GetIsolate(), beta, "beta", "script_b",
|
||||
script_b->GetUnboundScript()->GetId(), 0, 0);
|
||||
}
|
||||
|
||||
TEST(DontStopOnFinishedProfileDelete) {
|
||||
v8::HandleScope scope(CcTest::isolate());
|
||||
|
Loading…
Reference in New Issue
Block a user