Commit 66ab309e authored by loislo's avatar loislo Committed by Commit bot

CpuProfiler: fix for GetDeoptReason code.

The original code always returned the first entry from RelocInfo that matched with
bailout_id. But we may have a few different deopt reasons for one bailout_id.
So we need to get the one which matches with a particular call from JumpTable.

We can do this by checking not 'target_address' (it maps to bailout_id)
but 'from' address which maps to a particular JumpTable entry.

The test was reworked so it tests identical functions against different reasons.

BUG=chromium:452067
LOG=n

Review URL: https://codereview.chromium.org/984773003

Cr-Commit-Position: refs/heads/master@{#27076}
parent 4a709dd6
...@@ -329,11 +329,10 @@ void CpuProfiler::CodeDisableOptEvent(Code* code, SharedFunctionInfo* shared) { ...@@ -329,11 +329,10 @@ void CpuProfiler::CodeDisableOptEvent(Code* code, SharedFunctionInfo* shared) {
} }
void CpuProfiler::CodeDeoptEvent(Code* code, int bailout_id, Address pc, void CpuProfiler::CodeDeoptEvent(Code* code, Address pc, int fp_to_sp_delta) {
int fp_to_sp_delta) {
CodeEventsContainer evt_rec(CodeEventRecord::CODE_DEOPT); CodeEventsContainer evt_rec(CodeEventRecord::CODE_DEOPT);
CodeDeoptEventRecord* rec = &evt_rec.CodeDeoptEventRecord_; CodeDeoptEventRecord* rec = &evt_rec.CodeDeoptEventRecord_;
Deoptimizer::DeoptInfo info = Deoptimizer::GetDeoptInfo(code, bailout_id); Deoptimizer::DeoptInfo info = Deoptimizer::GetDeoptInfo(code, pc);
rec->start = code->address(); rec->start = code->address();
rec->deopt_reason = Deoptimizer::GetDeoptReason(info.deopt_reason); rec->deopt_reason = Deoptimizer::GetDeoptReason(info.deopt_reason);
rec->position = info.position; rec->position = info.position;
......
...@@ -235,8 +235,7 @@ class CpuProfiler : public CodeEventListener { ...@@ -235,8 +235,7 @@ class CpuProfiler : public CodeEventListener {
virtual void CodeMovingGCEvent() {} virtual void CodeMovingGCEvent() {}
virtual void CodeMoveEvent(Address from, Address to); virtual void CodeMoveEvent(Address from, Address to);
virtual void CodeDisableOptEvent(Code* code, SharedFunctionInfo* shared); virtual void CodeDisableOptEvent(Code* code, SharedFunctionInfo* shared);
virtual void CodeDeoptEvent(Code* code, int bailout_id, Address pc, virtual void CodeDeoptEvent(Code* code, Address pc, int fp_to_sp_delta);
int fp_to_sp_delta);
virtual void CodeDeleteEvent(Address from); virtual void CodeDeleteEvent(Address from);
virtual void GetterCallbackEvent(Name* name, Address entry_point); virtual void GetterCallbackEvent(Name* name, Address entry_point);
virtual void RegExpCodeCreateEvent(Code* code, String* source); virtual void RegExpCodeCreateEvent(Code* code, String* source);
......
...@@ -610,8 +610,7 @@ Deoptimizer::Deoptimizer(Isolate* isolate, ...@@ -610,8 +610,7 @@ Deoptimizer::Deoptimizer(Isolate* isolate,
disallow_heap_allocation_ = new DisallowHeapAllocation(); disallow_heap_allocation_ = new DisallowHeapAllocation();
#endif // DEBUG #endif // DEBUG
if (compiled_code_->kind() == Code::OPTIMIZED_FUNCTION) { if (compiled_code_->kind() == Code::OPTIMIZED_FUNCTION) {
PROFILE(isolate_, CodeDeoptEvent(compiled_code_, bailout_id_, from_, PROFILE(isolate_, CodeDeoptEvent(compiled_code_, from_, fp_to_sp_delta_));
fp_to_sp_delta_));
} }
unsigned size = ComputeInputFrameSize(); unsigned size = ComputeInputFrameSize();
input_ = new(size) FrameDescription(size, function); input_ = new(size) FrameDescription(size, function);
...@@ -770,7 +769,7 @@ void Deoptimizer::DoComputeOutputFrames() { ...@@ -770,7 +769,7 @@ void Deoptimizer::DoComputeOutputFrames() {
fp_to_sp_delta_); fp_to_sp_delta_);
if (bailout_type_ == EAGER || bailout_type_ == SOFT || if (bailout_type_ == EAGER || bailout_type_ == SOFT ||
(compiled_code_->is_hydrogen_stub())) { (compiled_code_->is_hydrogen_stub())) {
compiled_code_->PrintDeoptLocation(trace_scope_->file(), bailout_id_); compiled_code_->PrintDeoptLocation(trace_scope_->file(), from_);
} }
} }
...@@ -3649,34 +3648,20 @@ const char* Deoptimizer::GetDeoptReason(DeoptReason deopt_reason) { ...@@ -3649,34 +3648,20 @@ const char* Deoptimizer::GetDeoptReason(DeoptReason deopt_reason) {
} }
Deoptimizer::DeoptInfo Deoptimizer::GetDeoptInfo(Code* code, int bailout_id) { Deoptimizer::DeoptInfo Deoptimizer::GetDeoptInfo(Code* code, Address pc) {
SourcePosition last_position = SourcePosition::Unknown(); SourcePosition last_position = SourcePosition::Unknown();
Isolate* isolate = code->GetIsolate();
Deoptimizer::DeoptReason last_reason = Deoptimizer::kNoReason; Deoptimizer::DeoptReason last_reason = Deoptimizer::kNoReason;
int mask = RelocInfo::ModeMask(RelocInfo::DEOPT_REASON) | int mask = RelocInfo::ModeMask(RelocInfo::DEOPT_REASON) |
RelocInfo::ModeMask(RelocInfo::POSITION) | RelocInfo::ModeMask(RelocInfo::POSITION);
RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY);
for (RelocIterator it(code, mask); !it.done(); it.next()) { for (RelocIterator it(code, mask); !it.done(); it.next()) {
RelocInfo* info = it.rinfo(); RelocInfo* info = it.rinfo();
if (info->pc() >= pc) return DeoptInfo(last_position, NULL, last_reason);
if (info->rmode() == RelocInfo::POSITION) { if (info->rmode() == RelocInfo::POSITION) {
int raw_position = static_cast<int>(info->data()); int raw_position = static_cast<int>(info->data());
last_position = raw_position ? SourcePosition::FromRaw(raw_position) last_position = raw_position ? SourcePosition::FromRaw(raw_position)
: SourcePosition::Unknown(); : SourcePosition::Unknown();
} else if (info->rmode() == RelocInfo::DEOPT_REASON) { } else if (info->rmode() == RelocInfo::DEOPT_REASON) {
last_reason = static_cast<Deoptimizer::DeoptReason>(info->data()); last_reason = static_cast<Deoptimizer::DeoptReason>(info->data());
} else if (last_reason != Deoptimizer::kNoReason) {
if ((bailout_id ==
Deoptimizer::GetDeoptimizationId(isolate, info->target_address(),
Deoptimizer::EAGER)) ||
(bailout_id ==
Deoptimizer::GetDeoptimizationId(isolate, info->target_address(),
Deoptimizer::SOFT)) ||
(bailout_id ==
Deoptimizer::GetDeoptimizationId(isolate, info->target_address(),
Deoptimizer::LAZY))) {
CHECK(RelocInfo::IsRuntimeEntry(info->rmode()));
return DeoptInfo(last_position, NULL, last_reason);
}
} }
} }
return DeoptInfo(SourcePosition::Unknown(), NULL, Deoptimizer::kNoReason); return DeoptInfo(SourcePosition::Unknown(), NULL, Deoptimizer::kNoReason);
......
...@@ -192,7 +192,7 @@ class Deoptimizer : public Malloced { ...@@ -192,7 +192,7 @@ class Deoptimizer : public Malloced {
DeoptReason deopt_reason; DeoptReason deopt_reason;
}; };
static DeoptInfo GetDeoptInfo(Code* code, int bailout_id); static DeoptInfo GetDeoptInfo(Code* code, byte* from);
struct JumpTableEntry : public ZoneObject { struct JumpTableEntry : public ZoneObject {
inline JumpTableEntry(Address entry, const DeoptInfo& deopt_info, inline JumpTableEntry(Address entry, const DeoptInfo& deopt_info,
......
...@@ -893,9 +893,8 @@ void Logger::SharedLibraryEvent(const std::string& library_path, ...@@ -893,9 +893,8 @@ void Logger::SharedLibraryEvent(const std::string& library_path,
} }
void Logger::CodeDeoptEvent(Code* code, int bailout_id, Address from, void Logger::CodeDeoptEvent(Code* code, Address pc, int fp_to_sp_delta) {
int fp_to_sp_delta) { PROFILER_LOG(CodeDeoptEvent(code, pc, fp_to_sp_delta));
PROFILER_LOG(CodeDeoptEvent(code, bailout_id, from, fp_to_sp_delta));
if (!log_->IsEnabled() || !FLAG_log_internal_timer_events) return; if (!log_->IsEnabled() || !FLAG_log_internal_timer_events) return;
Log::MessageBuilder msg(log_); Log::MessageBuilder msg(log_);
int since_epoch = static_cast<int>(timer_.Elapsed().InMicroseconds()); int since_epoch = static_cast<int>(timer_.Elapsed().InMicroseconds());
......
...@@ -291,8 +291,7 @@ class Logger { ...@@ -291,8 +291,7 @@ class Logger {
uintptr_t start, uintptr_t start,
uintptr_t end); uintptr_t end);
void CodeDeoptEvent(Code* code, int bailout_id, Address from, void CodeDeoptEvent(Code* code, Address pc, int fp_to_sp_delta);
int fp_to_sp_delta);
void CurrentTimeEvent(); void CurrentTimeEvent();
void TimerEvent(StartEnd se, const char* name); void TimerEvent(StartEnd se, const char* name);
......
...@@ -11238,8 +11238,8 @@ Code* Code::GetCodeAgeStub(Isolate* isolate, Age age, MarkingParity parity) { ...@@ -11238,8 +11238,8 @@ Code* Code::GetCodeAgeStub(Isolate* isolate, Age age, MarkingParity parity) {
} }
void Code::PrintDeoptLocation(FILE* out, int bailout_id) { void Code::PrintDeoptLocation(FILE* out, Address pc) {
Deoptimizer::DeoptInfo info = Deoptimizer::GetDeoptInfo(this, bailout_id); Deoptimizer::DeoptInfo info = Deoptimizer::GetDeoptInfo(this, pc);
class SourcePosition pos = info.position; class SourcePosition pos = info.position;
if (info.deopt_reason != Deoptimizer::kNoReason || !pos.IsUnknown()) { if (info.deopt_reason != Deoptimizer::kNoReason || !pos.IsUnknown()) {
if (FLAG_hydrogen_track_positions) { if (FLAG_hydrogen_track_positions) {
......
...@@ -5417,7 +5417,7 @@ class Code: public HeapObject { ...@@ -5417,7 +5417,7 @@ class Code: public HeapObject {
return GetCodeAgeStub(isolate, kNotExecutedCodeAge, NO_MARKING_PARITY); return GetCodeAgeStub(isolate, kNotExecutedCodeAge, NO_MARKING_PARITY);
} }
void PrintDeoptLocation(FILE* out, int bailout_id); void PrintDeoptLocation(FILE* out, Address pc);
bool CanDeoptAt(Address pc); bool CanDeoptAt(Address pc);
#ifdef VERIFY_HEAP #ifdef VERIFY_HEAP
......
...@@ -1696,6 +1696,16 @@ TEST(DontStopOnFinishedProfileDelete) { ...@@ -1696,6 +1696,16 @@ TEST(DontStopOnFinishedProfileDelete) {
} }
const char* GetBranchDeoptReason(i::CpuProfile* iprofile, const char* branch[],
int length) {
v8::CpuProfile* profile = reinterpret_cast<v8::CpuProfile*>(iprofile);
const ProfileNode* iopt_function = NULL;
iopt_function = GetSimpleBranch(profile, branch, length);
CHECK_EQ(1, iopt_function->deopt_infos().length());
return iopt_function->deopt_infos()[0].deopt_reason;
}
// deopt at top function // deopt at top function
TEST(CollectDeoptEvents) { TEST(CollectDeoptEvents) {
if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return; if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return;
...@@ -1707,34 +1717,46 @@ TEST(CollectDeoptEvents) { ...@@ -1707,34 +1717,46 @@ TEST(CollectDeoptEvents) {
v8::CpuProfiler* profiler = isolate->GetCpuProfiler(); v8::CpuProfiler* profiler = isolate->GetCpuProfiler();
i::CpuProfiler* iprofiler = reinterpret_cast<i::CpuProfiler*>(profiler); i::CpuProfiler* iprofiler = reinterpret_cast<i::CpuProfiler*>(profiler);
const char* source = const char opt_source[] =
"function opt_function(left, right, depth) {\n" "function opt_function%d(value, depth) {\n"
" if (depth) return opt_function(left, right, depth - 1);\n" " if (depth) return opt_function%d(value, depth - 1);\n"
"\n" "\n"
" var k = left / 10;\n" " return 10 / value;\n"
" var r = 10 / right;\n"
" return k + r;"
"}\n" "}\n"
"\n";
for (int i = 0; i < 3; ++i) {
i::EmbeddedVector<char, sizeof(opt_source) + 100> buffer;
i::SNPrintF(buffer, opt_source, i, i);
v8::Script::Compile(v8_str(buffer.start()))->Run();
}
const char* source =
"startProfiling();\n"
"\n" "\n"
"function test(left, right) {\n" "opt_function0(1, 1);\n"
" return opt_function(left, right, 1);\n"
"}\n"
"\n" "\n"
"startProfiling();\n" "%OptimizeFunctionOnNextCall(opt_function0)\n"
"\n"
"opt_function0(1, 1);\n"
"\n"
"opt_function0(undefined, 1);\n"
"\n" "\n"
"test(10, 10);\n" "opt_function1(1, 1);\n"
"\n" "\n"
"%OptimizeFunctionOnNextCall(opt_function)\n" "%OptimizeFunctionOnNextCall(opt_function1)\n"
"\n" "\n"
"test(10, 10);\n" "opt_function1(1, 1);\n"
"\n" "\n"
"test(undefined, 10);\n" "opt_function1(NaN, 1);\n"
"\n" "\n"
"%OptimizeFunctionOnNextCall(opt_function)\n" "opt_function2(1, 1);\n"
"\n" "\n"
"test(10, 10);\n" "%OptimizeFunctionOnNextCall(opt_function2)\n"
"\n" "\n"
"test(10, 0);\n" "opt_function2(1, 1);\n"
"\n"
"opt_function2(0, 1);\n"
"\n" "\n"
"stopProfiling();\n" "stopProfiling();\n"
"\n"; "\n";
...@@ -1742,15 +1764,21 @@ TEST(CollectDeoptEvents) { ...@@ -1742,15 +1764,21 @@ TEST(CollectDeoptEvents) {
v8::Script::Compile(v8_str(source))->Run(); v8::Script::Compile(v8_str(source))->Run();
i::CpuProfile* iprofile = iprofiler->GetProfile(0); i::CpuProfile* iprofile = iprofiler->GetProfile(0);
iprofile->Print(); iprofile->Print();
v8::CpuProfile* profile = reinterpret_cast<v8::CpuProfile*>(iprofile); {
const char* branch[] = {"", "test", "opt_function", "opt_function"}; const char* branch[] = {"", "opt_function0", "opt_function0"};
const ProfileNode* iopt_function = CHECK_EQ(reason(i::Deoptimizer::kNotAHeapNumber),
GetSimpleBranch(profile, branch, arraysize(branch)); GetBranchDeoptReason(iprofile, branch, arraysize(branch)));
CHECK_EQ(2, iopt_function->deopt_infos().length()); }
CHECK_EQ(reason(i::Deoptimizer::kNotAHeapNumber), {
iopt_function->deopt_infos()[0].deopt_reason); const char* branch[] = {"", "opt_function1", "opt_function1"};
CHECK_EQ(reason(i::Deoptimizer::kDivisionByZero), CHECK_EQ(reason(i::Deoptimizer::kNaN),
iopt_function->deopt_infos()[1].deopt_reason); GetBranchDeoptReason(iprofile, branch, arraysize(branch)));
}
{
const char* branch[] = {"", "opt_function2", "opt_function2"};
CHECK_EQ(reason(i::Deoptimizer::kDivisionByZero),
GetBranchDeoptReason(iprofile, branch, arraysize(branch)));
}
iprofiler->DeleteProfile(iprofile); iprofiler->DeleteProfile(iprofile);
} }
......
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