Commit 5586ecfc authored by Michael Starzinger's avatar Michael Starzinger Committed by Commit Bot

[turbofan] Better checking of code start register.

This decouples the checking of the {kJavaScriptCallCodeStartRegister}
from the deoptimization checks. We now rely more heavily on the above
register and should check its validity more broadly. Note that there
also is a bug fix for the ARM port contained in this change.

R=mvstanton@chromium.org

Change-Id: I27d8b72cb2b36a85dae4bbbf35e4dbcf150eac01
Reviewed-on: https://chromium-review.googlesource.com/916242
Commit-Queue: Michael Stanton <mvstanton@chromium.org>
Reviewed-by: 's avatarMichael Stanton <mvstanton@chromium.org>
Cr-Commit-Position: refs/heads/master@{#51270}
parent a7402558
......@@ -578,6 +578,17 @@ void CodeGenerator::AssembleTailCallAfterGap(Instruction* instr,
first_unused_stack_slot);
}
// Check that {kJavaScriptCallCodeStartRegister} is correct.
void CodeGenerator::AssembleCodeStartRegisterCheck() {
UseScratchRegisterScope temps(tasm());
Register scratch = temps.Acquire();
int pc_offset = __ pc_offset();
// We can use the register pc - 8 for the address of the current instruction.
__ sub(scratch, pc, Operand(pc_offset + TurboAssembler::kPcLoadDelta));
__ cmp(scratch, kJavaScriptCallCodeStartRegister);
__ Assert(eq, AbortReason::kWrongFunctionCodeStart);
}
// Check if the code object is marked for deoptimization. If it is, then it
// jumps to the CompileLazyDeoptimizedCode builtin. In order to do this we need
// to:
......@@ -588,16 +599,6 @@ void CodeGenerator::AssembleTailCallAfterGap(Instruction* instr,
void CodeGenerator::BailoutIfDeoptimized() {
UseScratchRegisterScope temps(tasm());
Register scratch = temps.Acquire();
if (FLAG_debug_code) {
// Check that {kJavaScriptCallCodeStartRegister} is correct.
int pc_offset = __ pc_offset();
// We can use the register pc - 8 for the address of the current
// instruction.
__ add(scratch, pc, Operand(pc_offset - TurboAssembler::kPcLoadDelta));
__ cmp(scratch, kJavaScriptCallCodeStartRegister);
__ Assert(eq, AbortReason::kWrongFunctionCodeStart);
}
int offset = Code::kCodeDataContainerOffset - Code::kHeaderSize;
__ ldr(scratch, MemOperand(kJavaScriptCallCodeStartRegister, offset));
__ ldr(scratch,
......@@ -612,10 +613,9 @@ void CodeGenerator::GenerateSpeculationPoison() {
UseScratchRegisterScope temps(tasm());
Register scratch = temps.Acquire();
// We can use the register pc - 8 for the address of the current
// instruction.
// We can use the register pc - 8 for the address of the current instruction.
int pc_offset = __ pc_offset();
__ add(scratch, pc, Operand(pc_offset - TurboAssembler::kPcLoadDelta));
__ sub(scratch, pc, Operand(pc_offset + TurboAssembler::kPcLoadDelta));
// Calculate a mask which has all bits set in the normal case, but has all
// bits cleared if we are speculatively executing the wrong PC.
......
......@@ -533,6 +533,16 @@ void CodeGenerator::AssembleTailCallAfterGap(Instruction* instr,
}
}
// Check that {kJavaScriptCallCodeStartRegister} is correct.
void CodeGenerator::AssembleCodeStartRegisterCheck() {
UseScratchRegisterScope temps(tasm());
Register scratch = temps.AcquireX();
int pc_offset = __ pc_offset();
__ adr(scratch, -pc_offset);
__ cmp(scratch, kJavaScriptCallCodeStartRegister);
__ Assert(eq, AbortReason::kWrongFunctionCodeStart);
}
// Check if the code object is marked for deoptimization. If it is, then it
// jumps to the CompileLazyDeoptimizedCode builtin. In order to do this we need
// to:
......@@ -543,14 +553,6 @@ void CodeGenerator::AssembleTailCallAfterGap(Instruction* instr,
void CodeGenerator::BailoutIfDeoptimized() {
UseScratchRegisterScope temps(tasm());
Register scratch = temps.AcquireX();
if (FLAG_debug_code) {
// Check that {kJavaScriptCallCodeStartRegister} is correct.
int pc_offset = __ pc_offset();
__ adr(scratch, -pc_offset);
__ cmp(scratch, kJavaScriptCallCodeStartRegister);
__ Assert(eq, AbortReason::kWrongFunctionCodeStart);
}
int offset = Code::kCodeDataContainerOffset - Code::kHeaderSize;
__ Ldr(scratch, MemOperand(kJavaScriptCallCodeStartRegister, offset));
__ Ldr(scratch,
......
......@@ -148,6 +148,12 @@ void CodeGenerator::AssembleCode() {
ProfileEntryHookStub::MaybeCallEntryHookDelayed(tasm(), zone());
}
// Check that {kJavaScriptCallCodeStartRegister} has been set correctly.
if (FLAG_debug_code & (info->code_kind() == Code::OPTIMIZED_FUNCTION ||
info->code_kind() == Code::BYTECODE_HANDLER)) {
AssembleCodeStartRegisterCheck();
}
if (info->is_speculation_poison_enabled()) {
GenerateSpeculationPoison();
}
......
......@@ -179,6 +179,10 @@ class CodeGenerator final : public GapResolver::Assembler {
void AssembleArchLookupSwitch(Instruction* instr);
void AssembleArchTableSwitch(Instruction* instr);
// Generates code that checks whether the {kJavaScriptCallCodeStartRegister}
// contains the expected pointer to the start of the instruction stream.
void AssembleCodeStartRegisterCheck();
// When entering a code that is marked for deoptimization, rather continuing
// with its execution, we jump to a lazy compiled code. We need to do this
// because this code has already been deoptimized and needs to be unlinked
......
......@@ -495,6 +495,23 @@ void CodeGenerator::AssembleTailCallAfterGap(Instruction* instr,
first_unused_stack_slot);
}
// Check that {kJavaScriptCallCodeStartRegister} is correct.
void CodeGenerator::AssembleCodeStartRegisterCheck() {
__ push(eax); // Push eax so we can use it as a scratch register.
Label current;
__ call(&current);
int pc = __ pc_offset();
__ bind(&current);
// In order to get the address of the current instruction, we first need
// to use a call and then use a pop, thus pushing the return address to
// the stack and then popping it into the register.
__ pop(eax);
__ sub(eax, Immediate(pc));
__ cmp(eax, kJavaScriptCallCodeStartRegister);
__ Assert(equal, AbortReason::kWrongFunctionCodeStart);
__ pop(eax); // Restore eax.
}
// Check if the code object is marked for deoptimization. If it is, then it
// jumps to the CompileLazyDeoptimizedCode builtin. In order to do this we need
// to:
......@@ -503,23 +520,6 @@ void CodeGenerator::AssembleTailCallAfterGap(Instruction* instr,
// 2. test kMarkedForDeoptimizationBit in those flags; and
// 3. if it is not zero then it jumps to the builtin.
void CodeGenerator::BailoutIfDeoptimized() {
if (FLAG_debug_code) {
__ push(eax); // Push eax so we can use it as a scratch register.
// Check that {kJavaScriptCallCodeStartRegister} is correct.
Label current;
__ call(&current);
int pc = __ pc_offset();
__ bind(&current);
// In order to get the address of the current instruction, we first need
// to use a call and then use a pop, thus pushing the return address to
// the stack and then popping it into the register.
__ pop(eax);
__ sub(eax, Immediate(pc));
__ cmp(eax, kJavaScriptCallCodeStartRegister);
__ Assert(equal, AbortReason::kWrongFunctionCodeStart);
__ pop(eax); // Restore eax.
}
int offset = Code::kCodeDataContainerOffset - Code::kHeaderSize;
__ mov(ecx, Operand(kJavaScriptCallCodeStartRegister, offset));
__ test(FieldOperand(ecx, CodeDataContainer::kKindSpecificFlagsOffset),
......
......@@ -618,6 +618,25 @@ void CodeGenerator::AssembleTailCallAfterGap(Instruction* instr,
first_unused_stack_slot);
}
// Check that {kJavaScriptCallCodeStartRegister} is correct.
void CodeGenerator::AssembleCodeStartRegisterCheck() {
Label current;
// This push on ra and the pop below together ensure that we restore the
// register ra, which is needed while computing frames for deoptimization.
__ push(ra);
// The bal instruction puts the address of the current instruction into
// the return address (ra) register, which we can use later on.
__ bal(&current);
__ nop();
int pc = __ pc_offset();
__ bind(&current);
__ li(at, pc);
__ subu(at, ra, at);
__ Assert(eq, AbortReason::kWrongFunctionCodeStart,
kJavaScriptCallCodeStartRegister, Operand(at));
__ pop(ra);
}
// Check if the code object is marked for deoptimization. If it is, then it
// jumps to the CompileLazyDeoptimizedCode builtin. In order to do this we need
// to:
......@@ -626,24 +645,6 @@ void CodeGenerator::AssembleTailCallAfterGap(Instruction* instr,
// 2. test kMarkedForDeoptimizationBit in those flags; and
// 3. if it is not zero then it jumps to the builtin.
void CodeGenerator::BailoutIfDeoptimized() {
if (FLAG_debug_code) {
// Check that {kJavaScriptCallCodeStartRegister} is correct.
Label current;
// This push on ra and the pop below together ensure that we restore the
// register ra, which is needed while computing frames for deoptimization.
__ push(ra);
// The bal instruction puts the address of the current instruction into
// the return address (ra) register, which we can use later on.
__ bal(&current);
__ nop();
int pc = __ pc_offset();
__ bind(&current);
__ li(at, pc);
__ subu(at, ra, at);
__ Assert(eq, AbortReason::kWrongFunctionCodeStart,
kJavaScriptCallCodeStartRegister, Operand(at));
__ pop(ra);
}
int offset = Code::kCodeDataContainerOffset - Code::kHeaderSize;
__ lw(a2, MemOperand(kJavaScriptCallCodeStartRegister, offset));
__ lw(a2, FieldMemOperand(a2, CodeDataContainer::kKindSpecificFlagsOffset));
......
......@@ -634,6 +634,25 @@ void CodeGenerator::AssembleTailCallAfterGap(Instruction* instr,
first_unused_stack_slot);
}
// Check that {kJavaScriptCallCodeStartRegister} is correct.
void CodeGenerator::AssembleCodeStartRegisterCheck() {
Label current;
// This push on ra and the pop below together ensure that we restore the
// register ra, which is needed while computing frames for deoptimization.
__ push(ra);
// The bal instruction puts the address of the current instruction into
// the return address (ra) register, which we can use later on.
__ bal(&current);
__ nop();
int pc = __ pc_offset();
__ bind(&current);
__ li(at, Operand(pc));
__ Dsubu(at, ra, at);
__ Assert(eq, AbortReason::kWrongFunctionCodeStart,
kJavaScriptCallCodeStartRegister, Operand(at));
__ pop(ra);
}
// Check if the code object is marked for deoptimization. If it is, then it
// jumps to the CompileLazyDeoptimizedCode builtin. In order to do this we need
// to:
......@@ -642,24 +661,6 @@ void CodeGenerator::AssembleTailCallAfterGap(Instruction* instr,
// 2. test kMarkedForDeoptimizationBit in those flags; and
// 3. if it is not zero then it jumps to the builtin.
void CodeGenerator::BailoutIfDeoptimized() {
if (FLAG_debug_code) {
// Check that {kJavaScriptCallCodeStartRegister} is correct.
Label current;
// This push on ra and the pop below together ensure that we restore the
// register ra, which is needed while computing frames for deoptimization.
__ push(ra);
// The bal instruction puts the address of the current instruction into
// the return address (ra) register, which we can use later on.
__ bal(&current);
__ nop();
int pc = __ pc_offset();
__ bind(&current);
__ li(at, Operand(pc));
__ Dsubu(at, ra, at);
__ Assert(eq, AbortReason::kWrongFunctionCodeStart,
kJavaScriptCallCodeStartRegister, Operand(at));
__ pop(ra);
}
int offset = Code::kCodeDataContainerOffset - Code::kHeaderSize;
__ Ld(a2, MemOperand(kJavaScriptCallCodeStartRegister, offset));
__ Lw(a2, FieldMemOperand(a2, CodeDataContainer::kKindSpecificFlagsOffset));
......
......@@ -779,6 +779,11 @@ void CodeGenerator::AssembleTailCallAfterGap(Instruction* instr,
first_unused_stack_slot);
}
// Check that {kJavaScriptCallCodeStartRegister} is correct.
void CodeGenerator::AssembleCodeStartRegisterCheck() {
// TODO(mstarzinger): Implement me.
}
// Check if the code object is marked for deoptimization. If it is, then it
// jumps to the CompileLazyDeoptimizedCode builtin. In order to do this we need
// to:
......
......@@ -1028,6 +1028,11 @@ void CodeGenerator::AssembleTailCallAfterGap(Instruction* instr,
first_unused_stack_slot);
}
// Check that {kJavaScriptCallCodeStartRegister} is correct.
void CodeGenerator::AssembleCodeStartRegisterCheck() {
// TODO(mstarzinger): Implement me.
}
// Check if the code object is marked for deoptimization. If it is, then it
// jumps to the CompileLazyDeoptimizedCode builtin. In order to do this we need
// to:
......
......@@ -570,6 +570,18 @@ void CodeGenerator::AssembleTailCallAfterGap(Instruction* instr,
first_unused_stack_slot);
}
// Check that {kJavaScriptCallCodeStartRegister} is correct.
void CodeGenerator::AssembleCodeStartRegisterCheck() {
Label current;
// Load effective address to get the address of the current instruction.
__ leaq(rbx, Operand(&current));
__ bind(&current);
int pc = __ pc_offset();
__ subq(rbx, Immediate(pc));
__ cmpq(rbx, kJavaScriptCallCodeStartRegister);
__ Assert(equal, AbortReason::kWrongFunctionCodeStart);
}
// Check if the code object is marked for deoptimization. If it is, then it
// jumps to CompileLazyDeoptimizedCode builtin. In order to do this we need to:
// 1. read from memory the word that contains that bit, which can be found in
......@@ -577,19 +589,6 @@ void CodeGenerator::AssembleTailCallAfterGap(Instruction* instr,
// 2. test kMarkedForDeoptimizationBit in those flags; and
// 3. if it is not zero then it jumps to the builtin.
void CodeGenerator::BailoutIfDeoptimized() {
if (FLAG_debug_code) {
// Check that {kJavaScriptCallCodeStartRegister} is correct.
Label current;
// Load effective address to get the address of the current instruction into
// rcx.
__ leaq(rbx, Operand(&current));
__ bind(&current);
int pc = __ pc_offset();
__ subq(rbx, Immediate(pc));
__ cmpq(rbx, kJavaScriptCallCodeStartRegister);
__ Assert(equal, AbortReason::kWrongFunctionCodeStart);
}
int offset = Code::kCodeDataContainerOffset - Code::kHeaderSize;
__ movp(rbx, Operand(kJavaScriptCallCodeStartRegister, offset));
__ testl(FieldOperand(rbx, CodeDataContainer::kKindSpecificFlagsOffset),
......
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