[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: Michael Stanton <mvstanton@chromium.org> Cr-Commit-Position: refs/heads/master@{#51270}
This commit is contained in:
parent
a740255899
commit
5586ecfc68
@ -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(¤t);
|
||||
int pc = __ pc_offset();
|
||||
__ bind(¤t);
|
||||
// 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(¤t);
|
||||
int pc = __ pc_offset();
|
||||
__ bind(¤t);
|
||||
// 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(¤t);
|
||||
__ nop();
|
||||
int pc = __ pc_offset();
|
||||
__ bind(¤t);
|
||||
__ 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(¤t);
|
||||
__ nop();
|
||||
int pc = __ pc_offset();
|
||||
__ bind(¤t);
|
||||
__ 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(¤t);
|
||||
__ nop();
|
||||
int pc = __ pc_offset();
|
||||
__ bind(¤t);
|
||||
__ 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(¤t);
|
||||
__ nop();
|
||||
int pc = __ pc_offset();
|
||||
__ bind(¤t);
|
||||
__ 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(¤t));
|
||||
__ bind(¤t);
|
||||
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(¤t));
|
||||
__ bind(¤t);
|
||||
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),
|
||||
|
Loading…
Reference in New Issue
Block a user