Commit 7d2be718 authored by Eric Holk's avatar Eric Holk Committed by Commit Bot

[compiler] Add kRetpoline support for ia32

This is based on https://crrev.com/c/867063.

R=titzer@chromium.org

Bug: chromium:798964
Change-Id: I3b019040da90acd9541b4ec5c88d07ae81007120
Reviewed-on: https://chromium-review.googlesource.com/876989Reviewed-by: 's avatarBen Titzer <titzer@chromium.org>
Commit-Queue: Eric Holk <eholk@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50772}
parent e11c57fe
......@@ -215,6 +215,11 @@ class OutOfLineCode : public ZoneObject {
OutOfLineCode* const next_;
};
inline bool HasCallDescriptorFlag(Instruction* instr,
CallDescriptor::Flag flag) {
return MiscField::decode(instr->opcode()) & flag;
}
} // namespace compiler
} // namespace internal
} // namespace v8
......
......@@ -524,7 +524,11 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
} else {
Register reg = i.InputRegister(0);
__ add(reg, Immediate(Code::kHeaderSize - kHeapObjectTag));
__ call(reg);
if (HasCallDescriptorFlag(instr, CallDescriptor::kRetpoline)) {
__ RetpolineCall(reg);
} else {
__ call(reg);
}
}
RecordCallPosition(instr);
frame_access_state()->ClearSPDelta();
......@@ -537,11 +541,19 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
if (info()->IsWasm()) {
__ wasm_call(wasm_code, RelocInfo::WASM_CALL);
} else {
__ call(wasm_code, RelocInfo::JS_TO_WASM_CALL);
if (HasCallDescriptorFlag(instr, CallDescriptor::kRetpoline)) {
__ RetpolineCall(wasm_code, RelocInfo::JS_TO_WASM_CALL);
} else {
__ call(wasm_code, RelocInfo::JS_TO_WASM_CALL);
}
}
} else {
Register reg = i.InputRegister(0);
__ call(reg);
if (HasCallDescriptorFlag(instr, CallDescriptor::kRetpoline)) {
__ RetpolineCall(reg);
} else {
__ call(reg);
}
}
RecordCallPosition(instr);
frame_access_state()->ClearSPDelta();
......@@ -559,7 +571,11 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
} else {
Register reg = i.InputRegister(0);
__ add(reg, Immediate(Code::kHeaderSize - kHeapObjectTag));
__ jmp(reg);
if (HasCallDescriptorFlag(instr, CallDescriptor::kRetpoline)) {
__ RetpolineJump(reg);
} else {
__ jmp(reg);
}
}
frame_access_state()->ClearSPDelta();
frame_access_state()->SetFrameAccessToDefault();
......@@ -576,7 +592,11 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
}
} else {
Register reg = i.InputRegister(0);
__ jmp(reg);
if (HasCallDescriptorFlag(instr, CallDescriptor::kRetpoline)) {
__ RetpolineJump(reg);
} else {
__ jmp(reg);
}
}
frame_access_state()->ClearSPDelta();
frame_access_state()->SetFrameAccessToDefault();
......@@ -585,7 +605,11 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
case kArchTailCallAddress: {
CHECK(!HasImmediateInput(instr, 0));
Register reg = i.InputRegister(0);
__ jmp(reg);
if (HasCallDescriptorFlag(instr, CallDescriptor::kRetpoline)) {
__ RetpolineJump(reg);
} else {
__ jmp(reg);
}
frame_access_state()->ClearSPDelta();
frame_access_state()->SetFrameAccessToDefault();
break;
......
......@@ -593,11 +593,6 @@ void CodeGenerator::BailoutIfDeoptimized() {
__ j(not_zero, code, RelocInfo::CODE_TARGET);
}
inline bool HasCallDescriptorFlag(Instruction* instr,
CallDescriptor::Flag flag) {
return MiscField::decode(instr->opcode()) & flag;
}
// Assembles an instruction after register allocation, producing machine code.
CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
Instruction* instr) {
......
......@@ -655,6 +655,13 @@ void Assembler::mov(const Operand& dst, const Immediate& x) {
emit(x);
}
void Assembler::mov(const Operand& dst, Address src, RelocInfo::Mode rmode) {
EnsureSpace ensure_space(this);
EMIT(0xC7);
emit_operand(eax, dst);
emit(reinterpret_cast<uint32_t>(src), rmode);
}
void Assembler::mov(const Operand& dst, Handle<HeapObject> handle) {
EnsureSpace ensure_space(this);
EMIT(0xC7);
......@@ -803,6 +810,12 @@ void Assembler::lfence() {
EMIT(0xE8);
}
void Assembler::pause() {
EnsureSpace ensure_space(this);
EMIT(0xF3);
EMIT(0x90);
}
void Assembler::adc(Register dst, int32_t imm32) {
EnsureSpace ensure_space(this);
emit_arith(2, Operand(dst), Immediate(imm32));
......
......@@ -623,6 +623,7 @@ class Assembler : public AssemblerBase {
void mov(const Operand& dst, const Immediate& x);
void mov(const Operand& dst, Handle<HeapObject> handle);
void mov(const Operand& dst, Register src);
void mov(const Operand& dst, Address src, RelocInfo::Mode);
void movsx_b(Register dst, Register src) { movsx_b(dst, Operand(src)); }
void movsx_b(Register dst, const Operand& src);
......@@ -667,6 +668,8 @@ class Assembler : public AssemblerBase {
// Memory Fence
void lfence();
void pause();
// Arithmetics
void adc(Register dst, int32_t imm32);
void adc(Register dst, const Operand& src);
......
......@@ -1547,6 +1547,59 @@ void TurboAssembler::CallCFunction(Register function, int num_arguments) {
}
}
void TurboAssembler::RetpolineCall(Register reg) {
Label setup_return, setup_target, inner_indirect_branch, capture_spec;
jmp(&setup_return); // Jump past the entire retpoline below.
bind(&inner_indirect_branch);
call(&setup_target);
bind(&capture_spec);
pause();
jmp(&capture_spec);
bind(&setup_target);
mov(Operand(esp, 0), reg);
ret(0);
bind(&setup_return);
call(&inner_indirect_branch); // Callee will return after this instruction.
}
void TurboAssembler::RetpolineCall(Address destination, RelocInfo::Mode rmode) {
Label setup_return, setup_target, inner_indirect_branch, capture_spec;
jmp(&setup_return); // Jump past the entire retpoline below.
bind(&inner_indirect_branch);
call(&setup_target);
bind(&capture_spec);
pause();
jmp(&capture_spec);
bind(&setup_target);
mov(Operand(esp, 0), destination, rmode);
ret(0);
bind(&setup_return);
call(&inner_indirect_branch); // Callee will return after this instruction.
}
void TurboAssembler::RetpolineJump(Register reg) {
Label setup_target, capture_spec;
call(&setup_target);
bind(&capture_spec);
pause();
jmp(&capture_spec);
bind(&setup_target);
mov(Operand(esp, 0), reg);
ret(0);
}
#ifdef DEBUG
bool AreAliased(Register reg1,
......
......@@ -113,6 +113,11 @@ class TurboAssembler : public Assembler {
void Call(Handle<Code> target, RelocInfo::Mode rmode) { call(target, rmode); }
void Call(Label* target) { call(target); }
void RetpolineCall(Register reg);
void RetpolineCall(Address destination, RelocInfo::Mode rmode);
void RetpolineJump(Register reg);
void CallForDeoptimization(Address target, RelocInfo::Mode rmode) {
call(target, rmode);
}
......
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