Commit 82e6824e authored by loislo's avatar loislo Committed by Commit bot

CpuProfiler: fix for CollectDeoptEvents test on arm64

We use slightly different schema for JumpTable on arm64 than for x64.

We do a branch (B) to the JumpTable from the code,
then a branch (B) to the end of jump table code
and then branch to the deoptimizer code with putting
the return address into lr register (Call which is actually Blr).

As a result the 'from' address in Deoptimizer always points to
the end of JumpTable code and we can get nothing from this information.

0) I moved save_doubles and needs_frame code out of for_loop.

1) I replaced B commands with Bl so we put different return addresses
to lr register for the different jump table entries and replaced
the final Call with Br which do not touch lr register.

Also I removed the last_entry check so we will always do the Bl
even for the last entry because we need the right address in lr.
I don't think that this will affect the performance because it
just one more branch for entire deopt mechanics.

BUG=chromium:452067
LOG=n

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

Cr-Commit-Position: refs/heads/master@{#27094}
parent 3ed5dea6
......@@ -864,55 +864,55 @@ bool LCodeGen::GenerateJumpTable() {
// address and add an immediate offset.
__ Mov(entry_offset, entry - base);
// The last entry can fall through into `call_deopt_entry`, avoiding a
// branch.
bool last_entry = (i + 1) == length;
if (table_entry->needs_frame) {
DCHECK(!info()->saves_caller_doubles());
if (!needs_frame.is_bound()) {
// This variant of deopt can only be used with stubs. Since we don't
// have a function pointer to install in the stack frame that we're
// building, install a special marker there instead.
DCHECK(info()->IsStub());
UseScratchRegisterScope temps(masm());
Register stub_marker = temps.AcquireX();
__ Bind(&needs_frame);
__ Mov(stub_marker, Smi::FromInt(StackFrame::STUB));
__ Push(lr, fp, cp, stub_marker);
__ Add(fp, __ StackPointer(), 2 * kPointerSize);
if (!last_entry) __ B(&call_deopt_entry);
} else {
// Reuse the existing needs_frame code.
__ B(&needs_frame);
}
// Save lr before Bl, fp will be adjusted in the needs_frame code.
__ Push(lr, fp, cp);
// Reuse the existing needs_frame code.
__ Bl(&needs_frame);
} else if (info()->saves_caller_doubles()) {
DCHECK(info()->IsStub());
if (!restore_caller_doubles.is_bound()) {
__ Bind(&restore_caller_doubles);
RestoreCallerDoubles();
if (!last_entry) __ B(&call_deopt_entry);
} else {
// Reuse the existing restore_caller_doubles code.
__ B(&restore_caller_doubles);
}
// Reuse the existing restore_caller_doubles code.
__ Bl(&restore_caller_doubles);
} else {
// There is nothing special to do, so just continue to the second-level
// table.
if (!last_entry) __ B(&call_deopt_entry);
__ Bl(&call_deopt_entry);
}
bool last_entry = (i + 1) == length;
masm()->CheckConstPool(false, last_entry);
}
if (needs_frame.is_linked()) {
// This variant of deopt can only be used with stubs. Since we don't
// have a function pointer to install in the stack frame that we're
// building, install a special marker there instead.
DCHECK(info()->IsStub());
UseScratchRegisterScope temps(masm());
Register stub_marker = temps.AcquireX();
__ Bind(&needs_frame);
__ Mov(stub_marker, Smi::FromInt(StackFrame::STUB));
__ Push(stub_marker);
__ Add(fp, __ StackPointer(), 2 * kPointerSize);
if (restore_caller_doubles.is_linked()) {
__ B(&call_deopt_entry);
}
}
if (restore_caller_doubles.is_linked()) {
__ Bind(&restore_caller_doubles);
RestoreCallerDoubles();
}
// Generate common code for calling the second-level deopt table.
Register deopt_entry = temps.AcquireX();
__ Bind(&call_deopt_entry);
__ Mov(deopt_entry, Operand(reinterpret_cast<uint64_t>(base),
RelocInfo::RUNTIME_ENTRY));
__ Add(deopt_entry, deopt_entry, entry_offset);
__ Call(deopt_entry);
__ Br(deopt_entry);
}
// Force constant pool emission at the end of the deopt jump table to make
......@@ -1152,7 +1152,7 @@ void LCodeGen::DeoptimizeIfMinusZero(DoubleRegister input, LInstruction* instr,
void LCodeGen::DeoptimizeIfNotHeapNumber(Register object, LInstruction* instr) {
__ CompareObjectMap(object, Heap::kHeapNumberMapRootIndex);
DeoptimizeIf(ne, instr, Deoptimizer::kNotHeapNumber);
DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumber);
}
......
......@@ -132,7 +132,6 @@ class OptimizedFunctionVisitor BASE_EMBEDDED {
V(kNotAHeapNumberUndefined, "not a heap number/undefined") \
V(kNotAJavaScriptObject, "not a JavaScript object") \
V(kNotASmi, "not a Smi") \
V(kNotHeapNumber, "not heap number") \
V(kNull, "null") \
V(kOutOfBounds, "out of bounds") \
V(kOutsideOfRange, "Outside of range") \
......
......@@ -1771,8 +1771,12 @@ TEST(CollectDeoptEvents) {
}
{
const char* branch[] = {"", "opt_function1", "opt_function1"};
CHECK_EQ(reason(i::Deoptimizer::kNaN),
GetBranchDeoptReason(iprofile, branch, arraysize(branch)));
const char* deopt_reason =
GetBranchDeoptReason(iprofile, branch, arraysize(branch));
if (deopt_reason != reason(i::Deoptimizer::kNaN) &&
deopt_reason != reason(i::Deoptimizer::kLostPrecisionOrNaN)) {
FATAL(deopt_reason);
}
}
{
const char* branch[] = {"", "opt_function2", "opt_function2"};
......
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