[turbofan] Support CallDescriptor::kFixedTargetRegister for [tail]calls to code objects.

In order to port CompileLazy and DeserializeLazy builtins to CSA we need to
support this mode to be able to tail call to compiled or deserialized JS code
object.

Bug: v8:5269, v8:7703
Change-Id: I6abdc989af16774f6454b2ea0a97b1ce5ece5125
Reviewed-on: https://chromium-review.googlesource.com/1087452
Reviewed-by: Michael Starzinger <mstarzinger@chromium.org>
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#53543}
This commit is contained in:
Igor Sheludko 2018-06-05 20:56:14 +02:00 committed by Commit Bot
parent 1c40429844
commit 9c07c61c92
8 changed files with 118 additions and 48 deletions

View File

@ -677,11 +677,12 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
if (instr->InputAt(0)->IsImmediate()) { if (instr->InputAt(0)->IsImmediate()) {
__ Call(i.InputCode(0), RelocInfo::CODE_TARGET); __ Call(i.InputCode(0), RelocInfo::CODE_TARGET);
} else { } else {
UseScratchRegisterScope temps(tasm()); Register reg = i.InputRegister(0);
Register scratch = temps.Acquire(); DCHECK_IMPLIES(
__ add(scratch, i.InputRegister(0), HasCallDescriptorFlag(instr, CallDescriptor::kFixedTargetRegister),
Operand(Code::kHeaderSize - kHeapObjectTag)); reg == kJavaScriptCallCodeStartRegister);
__ Call(scratch); __ add(reg, reg, Operand(Code::kHeaderSize - kHeapObjectTag));
__ Call(reg);
} }
RecordCallPosition(instr); RecordCallPosition(instr);
DCHECK_EQ(LeaveCC, i.OutputSBit()); DCHECK_EQ(LeaveCC, i.OutputSBit());
@ -721,11 +722,12 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
if (instr->InputAt(0)->IsImmediate()) { if (instr->InputAt(0)->IsImmediate()) {
__ Jump(i.InputCode(0), RelocInfo::CODE_TARGET); __ Jump(i.InputCode(0), RelocInfo::CODE_TARGET);
} else { } else {
UseScratchRegisterScope temps(tasm()); Register reg = i.InputRegister(0);
Register scratch = temps.Acquire(); DCHECK_IMPLIES(
__ add(scratch, i.InputRegister(0), HasCallDescriptorFlag(instr, CallDescriptor::kFixedTargetRegister),
Operand(Code::kHeaderSize - kHeapObjectTag)); reg == kJavaScriptCallCodeStartRegister);
__ Jump(scratch); __ add(reg, reg, Operand(Code::kHeaderSize - kHeapObjectTag));
__ Jump(reg);
} }
DCHECK_EQ(LeaveCC, i.OutputSBit()); DCHECK_EQ(LeaveCC, i.OutputSBit());
unwinding_info_writer_.MarkBlockWillExit(); unwinding_info_writer_.MarkBlockWillExit();
@ -754,7 +756,11 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
} }
case kArchTailCallAddress: { case kArchTailCallAddress: {
CHECK(!instr->InputAt(0)->IsImmediate()); CHECK(!instr->InputAt(0)->IsImmediate());
__ Jump(i.InputRegister(0)); Register reg = i.InputRegister(0);
DCHECK_IMPLIES(
HasCallDescriptorFlag(instr, CallDescriptor::kFixedTargetRegister),
reg == kJavaScriptCallCodeStartRegister);
__ Jump(reg);
unwinding_info_writer_.MarkBlockWillExit(); unwinding_info_writer_.MarkBlockWillExit();
frame_access_state()->ClearSPDelta(); frame_access_state()->ClearSPDelta();
frame_access_state()->SetFrameAccessToDefault(); frame_access_state()->SetFrameAccessToDefault();

View File

@ -609,9 +609,12 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
if (instr->InputAt(0)->IsImmediate()) { if (instr->InputAt(0)->IsImmediate()) {
__ Call(i.InputCode(0), RelocInfo::CODE_TARGET); __ Call(i.InputCode(0), RelocInfo::CODE_TARGET);
} else { } else {
Register target = i.InputRegister(0); Register reg = i.InputRegister(0);
__ Add(target, target, Code::kHeaderSize - kHeapObjectTag); DCHECK_IMPLIES(
__ Call(target); HasCallDescriptorFlag(instr, CallDescriptor::kFixedTargetRegister),
reg == kJavaScriptCallCodeStartRegister);
__ Add(reg, reg, Code::kHeaderSize - kHeapObjectTag);
__ Call(reg);
} }
RecordCallPosition(instr); RecordCallPosition(instr);
frame_access_state()->ClearSPDelta(); frame_access_state()->ClearSPDelta();
@ -645,9 +648,12 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
if (instr->InputAt(0)->IsImmediate()) { if (instr->InputAt(0)->IsImmediate()) {
__ Jump(i.InputCode(0), RelocInfo::CODE_TARGET); __ Jump(i.InputCode(0), RelocInfo::CODE_TARGET);
} else { } else {
Register target = i.InputRegister(0); Register reg = i.InputRegister(0);
__ Add(target, target, Code::kHeaderSize - kHeapObjectTag); DCHECK_IMPLIES(
__ Jump(target); HasCallDescriptorFlag(instr, CallDescriptor::kFixedTargetRegister),
reg == kJavaScriptCallCodeStartRegister);
__ Add(reg, reg, Code::kHeaderSize - kHeapObjectTag);
__ Jump(reg);
} }
unwinding_info_writer_.MarkBlockWillExit(); unwinding_info_writer_.MarkBlockWillExit();
frame_access_state()->ClearSPDelta(); frame_access_state()->ClearSPDelta();
@ -670,7 +676,11 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
} }
case kArchTailCallAddress: { case kArchTailCallAddress: {
CHECK(!instr->InputAt(0)->IsImmediate()); CHECK(!instr->InputAt(0)->IsImmediate());
__ Jump(i.InputRegister(0)); Register reg = i.InputRegister(0);
DCHECK_IMPLIES(
HasCallDescriptorFlag(instr, CallDescriptor::kFixedTargetRegister),
reg == kJavaScriptCallCodeStartRegister);
__ Jump(reg);
unwinding_info_writer_.MarkBlockWillExit(); unwinding_info_writer_.MarkBlockWillExit();
frame_access_state()->ClearSPDelta(); frame_access_state()->ClearSPDelta();
frame_access_state()->SetFrameAccessToDefault(); frame_access_state()->SetFrameAccessToDefault();

View File

@ -587,6 +587,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
__ call(code, RelocInfo::CODE_TARGET); __ call(code, RelocInfo::CODE_TARGET);
} else { } else {
Register reg = i.InputRegister(0); Register reg = i.InputRegister(0);
DCHECK_IMPLIES(
HasCallDescriptorFlag(instr, CallDescriptor::kFixedTargetRegister),
reg == kJavaScriptCallCodeStartRegister);
__ add(reg, Immediate(Code::kHeaderSize - kHeapObjectTag)); __ add(reg, Immediate(Code::kHeaderSize - kHeapObjectTag));
if (HasCallDescriptorFlag(instr, CallDescriptor::kRetpoline)) { if (HasCallDescriptorFlag(instr, CallDescriptor::kRetpoline)) {
__ RetpolineCall(reg); __ RetpolineCall(reg);
@ -636,6 +639,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
__ jmp(code, RelocInfo::CODE_TARGET); __ jmp(code, RelocInfo::CODE_TARGET);
} else { } else {
Register reg = i.InputRegister(0); Register reg = i.InputRegister(0);
DCHECK_IMPLIES(
HasCallDescriptorFlag(instr, CallDescriptor::kFixedTargetRegister),
reg == kJavaScriptCallCodeStartRegister);
__ add(reg, Immediate(Code::kHeaderSize - kHeapObjectTag)); __ add(reg, Immediate(Code::kHeaderSize - kHeapObjectTag));
if (HasCallDescriptorFlag(instr, CallDescriptor::kRetpoline)) { if (HasCallDescriptorFlag(instr, CallDescriptor::kRetpoline)) {
__ RetpolineJump(reg); __ RetpolineJump(reg);
@ -669,6 +675,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
MoveOperandIfAliasedWithPoisonRegister(instr, this); MoveOperandIfAliasedWithPoisonRegister(instr, this);
CHECK(!HasImmediateInput(instr, 0)); CHECK(!HasImmediateInput(instr, 0));
Register reg = i.InputRegister(0); Register reg = i.InputRegister(0);
DCHECK_IMPLIES(
HasCallDescriptorFlag(instr, CallDescriptor::kFixedTargetRegister),
reg == kJavaScriptCallCodeStartRegister);
if (HasCallDescriptorFlag(instr, CallDescriptor::kRetpoline)) { if (HasCallDescriptorFlag(instr, CallDescriptor::kRetpoline)) {
__ RetpolineJump(reg); __ RetpolineJump(reg);
} else { } else {

View File

@ -605,8 +605,11 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
if (instr->InputAt(0)->IsImmediate()) { if (instr->InputAt(0)->IsImmediate()) {
__ Call(i.InputCode(0), RelocInfo::CODE_TARGET); __ Call(i.InputCode(0), RelocInfo::CODE_TARGET);
} else { } else {
__ Call(kScratchReg, i.InputRegister(0), Register reg = i.InputRegister(0);
Code::kHeaderSize - kHeapObjectTag); DCHECK_IMPLIES(
HasCallDescriptorFlag(instr, CallDescriptor::kFixedTargetRegister),
reg == kJavaScriptCallCodeStartRegister);
__ Call(reg, reg, Code::kHeaderSize - kHeapObjectTag);
} }
RecordCallPosition(instr); RecordCallPosition(instr);
frame_access_state()->ClearSPDelta(); frame_access_state()->ClearSPDelta();
@ -634,8 +637,11 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
if (instr->InputAt(0)->IsImmediate()) { if (instr->InputAt(0)->IsImmediate()) {
__ Jump(i.InputCode(0), RelocInfo::CODE_TARGET); __ Jump(i.InputCode(0), RelocInfo::CODE_TARGET);
} else { } else {
__ Jump(kScratchReg, i.InputRegister(0), Register reg = i.InputRegister(0);
Code::kHeaderSize - kHeapObjectTag); DCHECK_IMPLIES(
HasCallDescriptorFlag(instr, CallDescriptor::kFixedTargetRegister),
reg == kJavaScriptCallCodeStartRegister);
__ Jump(reg, reg, Code::kHeaderSize - kHeapObjectTag);
} }
frame_access_state()->ClearSPDelta(); frame_access_state()->ClearSPDelta();
frame_access_state()->SetFrameAccessToDefault(); frame_access_state()->SetFrameAccessToDefault();
@ -655,7 +661,11 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
} }
case kArchTailCallAddress: { case kArchTailCallAddress: {
CHECK(!instr->InputAt(0)->IsImmediate()); CHECK(!instr->InputAt(0)->IsImmediate());
__ Jump(i.InputRegister(0)); Register reg = i.InputRegister(0);
DCHECK_IMPLIES(
HasCallDescriptorFlag(instr, CallDescriptor::kFixedTargetRegister),
reg == kJavaScriptCallCodeStartRegister);
__ Jump(reg);
frame_access_state()->ClearSPDelta(); frame_access_state()->ClearSPDelta();
frame_access_state()->SetFrameAccessToDefault(); frame_access_state()->SetFrameAccessToDefault();
break; break;

View File

@ -618,9 +618,12 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
if (instr->InputAt(0)->IsImmediate()) { if (instr->InputAt(0)->IsImmediate()) {
__ Call(i.InputCode(0), RelocInfo::CODE_TARGET); __ Call(i.InputCode(0), RelocInfo::CODE_TARGET);
} else { } else {
__ daddiu(kScratchReg, i.InputRegister(0), Register reg = i.InputRegister(0);
Code::kHeaderSize - kHeapObjectTag); DCHECK_IMPLIES(
__ Call(kScratchReg); HasCallDescriptorFlag(instr, CallDescriptor::kFixedTargetRegister),
reg == kJavaScriptCallCodeStartRegister);
__ daddiu(reg, reg, Code::kHeaderSize - kHeapObjectTag);
__ Call(reg);
} }
RecordCallPosition(instr); RecordCallPosition(instr);
frame_access_state()->ClearSPDelta(); frame_access_state()->ClearSPDelta();
@ -654,9 +657,12 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
if (instr->InputAt(0)->IsImmediate()) { if (instr->InputAt(0)->IsImmediate()) {
__ Jump(i.InputCode(0), RelocInfo::CODE_TARGET); __ Jump(i.InputCode(0), RelocInfo::CODE_TARGET);
} else { } else {
__ daddiu(kScratchReg, i.InputRegister(0), Register reg = i.InputRegister(0);
Code::kHeaderSize - kHeapObjectTag); DCHECK_IMPLIES(
__ Jump(kScratchReg); HasCallDescriptorFlag(instr, CallDescriptor::kFixedTargetRegister),
reg == kJavaScriptCallCodeStartRegister);
__ daddiu(reg, reg, Code::kHeaderSize - kHeapObjectTag);
__ Jump(reg);
} }
frame_access_state()->ClearSPDelta(); frame_access_state()->ClearSPDelta();
frame_access_state()->SetFrameAccessToDefault(); frame_access_state()->SetFrameAccessToDefault();
@ -677,7 +683,11 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
} }
case kArchTailCallAddress: { case kArchTailCallAddress: {
CHECK(!instr->InputAt(0)->IsImmediate()); CHECK(!instr->InputAt(0)->IsImmediate());
__ Jump(i.InputRegister(0)); Register reg = i.InputRegister(0);
DCHECK_IMPLIES(
HasCallDescriptorFlag(instr, CallDescriptor::kFixedTargetRegister),
reg == kJavaScriptCallCodeStartRegister);
__ Jump(reg);
frame_access_state()->ClearSPDelta(); frame_access_state()->ClearSPDelta();
frame_access_state()->SetFrameAccessToDefault(); frame_access_state()->SetFrameAccessToDefault();
break; break;

View File

@ -913,9 +913,12 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
v8::internal::Assembler::BlockTrampolinePoolScope block_trampoline_pool( v8::internal::Assembler::BlockTrampolinePoolScope block_trampoline_pool(
tasm()); tasm());
if (HasRegisterInput(instr, 0)) { if (HasRegisterInput(instr, 0)) {
__ addi(ip, i.InputRegister(0), Register reg = i.InputRegister(0);
Operand(Code::kHeaderSize - kHeapObjectTag)); DCHECK_IMPLIES(
__ Call(ip); HasCallDescriptorFlag(instr, CallDescriptor::kFixedTargetRegister),
reg == kJavaScriptCallCodeStartRegister);
__ addi(reg, reg, Operand(Code::kHeaderSize - kHeapObjectTag));
__ Call(reg);
} else { } else {
__ Call(i.InputCode(0), RelocInfo::CODE_TARGET); __ Call(i.InputCode(0), RelocInfo::CODE_TARGET);
} }
@ -951,9 +954,12 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
i.TempRegister(2)); i.TempRegister(2));
} }
if (HasRegisterInput(instr, 0)) { if (HasRegisterInput(instr, 0)) {
__ addi(ip, i.InputRegister(0), Register reg = i.InputRegister(0);
Operand(Code::kHeaderSize - kHeapObjectTag)); DCHECK_IMPLIES(
__ Jump(ip); HasCallDescriptorFlag(instr, CallDescriptor::kFixedTargetRegister),
reg == kJavaScriptCallCodeStartRegister);
__ addi(reg, reg, Operand(Code::kHeaderSize - kHeapObjectTag));
__ Jump(reg);
} else { } else {
// We cannot use the constant pool to load the target since // We cannot use the constant pool to load the target since
// we've already restored the caller's frame. // we've already restored the caller's frame.
@ -986,7 +992,11 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
} }
case kArchTailCallAddress: { case kArchTailCallAddress: {
CHECK(!instr->InputAt(0)->IsImmediate()); CHECK(!instr->InputAt(0)->IsImmediate());
__ Jump(i.InputRegister(0)); Register reg = i.InputRegister(0);
DCHECK_IMPLIES(
HasCallDescriptorFlag(instr, CallDescriptor::kFixedTargetRegister),
reg == kJavaScriptCallCodeStartRegister);
__ Jump(reg);
frame_access_state()->ClearSPDelta(); frame_access_state()->ClearSPDelta();
frame_access_state()->SetFrameAccessToDefault(); frame_access_state()->SetFrameAccessToDefault();
break; break;

View File

@ -1354,9 +1354,12 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
} }
case kArchCallCodeObject: { case kArchCallCodeObject: {
if (HasRegisterInput(instr, 0)) { if (HasRegisterInput(instr, 0)) {
__ AddP(ip, i.InputRegister(0), Register reg = i.InputRegister(0);
Operand(Code::kHeaderSize - kHeapObjectTag)); DCHECK_IMPLIES(
__ Call(ip); HasCallDescriptorFlag(instr, CallDescriptor::kFixedTargetRegister),
reg == kJavaScriptCallCodeStartRegister);
__ AddP(reg, reg, Operand(Code::kHeaderSize - kHeapObjectTag));
__ Call(reg);
} else { } else {
__ Call(i.InputCode(0), RelocInfo::CODE_TARGET); __ Call(i.InputCode(0), RelocInfo::CODE_TARGET);
} }
@ -1390,9 +1393,12 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
i.TempRegister(2)); i.TempRegister(2));
} }
if (HasRegisterInput(instr, 0)) { if (HasRegisterInput(instr, 0)) {
__ AddP(ip, i.InputRegister(0), Register reg = i.InputRegister(0);
Operand(Code::kHeaderSize - kHeapObjectTag)); DCHECK_IMPLIES(
__ Jump(ip); HasCallDescriptorFlag(instr, CallDescriptor::kFixedTargetRegister),
reg == kJavaScriptCallCodeStartRegister);
__ AddP(reg, reg, Operand(Code::kHeaderSize - kHeapObjectTag));
__ Jump(reg);
} else { } else {
// We cannot use the constant pool to load the target since // We cannot use the constant pool to load the target since
// we've already restored the caller's frame. // we've already restored the caller's frame.
@ -1423,7 +1429,11 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
} }
case kArchTailCallAddress: { case kArchTailCallAddress: {
CHECK(!instr->InputAt(0)->IsImmediate()); CHECK(!instr->InputAt(0)->IsImmediate());
__ Jump(i.InputRegister(0)); Register reg = i.InputRegister(0);
DCHECK_IMPLIES(
HasCallDescriptorFlag(instr, CallDescriptor::kFixedTargetRegister),
reg == kJavaScriptCallCodeStartRegister);
__ Jump(reg);
frame_access_state()->ClearSPDelta(); frame_access_state()->ClearSPDelta();
frame_access_state()->SetFrameAccessToDefault(); frame_access_state()->SetFrameAccessToDefault();
break; break;

View File

@ -676,6 +676,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
__ Call(code, RelocInfo::CODE_TARGET); __ Call(code, RelocInfo::CODE_TARGET);
} else { } else {
Register reg = i.InputRegister(0); Register reg = i.InputRegister(0);
DCHECK_IMPLIES(
HasCallDescriptorFlag(instr, CallDescriptor::kFixedTargetRegister),
reg == kJavaScriptCallCodeStartRegister);
__ addp(reg, Immediate(Code::kHeaderSize - kHeapObjectTag)); __ addp(reg, Immediate(Code::kHeaderSize - kHeapObjectTag));
if (HasCallDescriptorFlag(instr, CallDescriptor::kRetpoline)) { if (HasCallDescriptorFlag(instr, CallDescriptor::kRetpoline)) {
__ RetpolineCall(reg); __ RetpolineCall(reg);
@ -724,6 +727,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
__ Jump(code, RelocInfo::CODE_TARGET); __ Jump(code, RelocInfo::CODE_TARGET);
} else { } else {
Register reg = i.InputRegister(0); Register reg = i.InputRegister(0);
DCHECK_IMPLIES(
HasCallDescriptorFlag(instr, CallDescriptor::kFixedTargetRegister),
reg == kJavaScriptCallCodeStartRegister);
__ addp(reg, Immediate(Code::kHeaderSize - kHeapObjectTag)); __ addp(reg, Immediate(Code::kHeaderSize - kHeapObjectTag));
if (HasCallDescriptorFlag(instr, CallDescriptor::kRetpoline)) { if (HasCallDescriptorFlag(instr, CallDescriptor::kRetpoline)) {
__ RetpolineJump(reg); __ RetpolineJump(reg);
@ -762,10 +768,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
case kArchTailCallAddress: { case kArchTailCallAddress: {
CHECK(!HasImmediateInput(instr, 0)); CHECK(!HasImmediateInput(instr, 0));
Register reg = i.InputRegister(0); Register reg = i.InputRegister(0);
if (HasCallDescriptorFlag(instr, CallDescriptor::kFixedTargetRegister)) { DCHECK_IMPLIES(
static_assert(kJavaScriptCallCodeStartRegister == rcx, "ABI mismatch"); HasCallDescriptorFlag(instr, CallDescriptor::kFixedTargetRegister),
DCHECK_EQ(rcx, reg); reg == kJavaScriptCallCodeStartRegister);
}
if (HasCallDescriptorFlag(instr, CallDescriptor::kRetpoline)) { if (HasCallDescriptorFlag(instr, CallDescriptor::kRetpoline)) {
__ RetpolineJump(reg); __ RetpolineJump(reg);
} else { } else {