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 { ...@@ -215,6 +215,11 @@ class OutOfLineCode : public ZoneObject {
OutOfLineCode* const next_; OutOfLineCode* const next_;
}; };
inline bool HasCallDescriptorFlag(Instruction* instr,
CallDescriptor::Flag flag) {
return MiscField::decode(instr->opcode()) & flag;
}
} // namespace compiler } // namespace compiler
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
......
...@@ -524,7 +524,11 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ...@@ -524,7 +524,11 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
} else { } else {
Register reg = i.InputRegister(0); Register reg = i.InputRegister(0);
__ add(reg, Immediate(Code::kHeaderSize - kHeapObjectTag)); __ add(reg, Immediate(Code::kHeaderSize - kHeapObjectTag));
__ call(reg); if (HasCallDescriptorFlag(instr, CallDescriptor::kRetpoline)) {
__ RetpolineCall(reg);
} else {
__ call(reg);
}
} }
RecordCallPosition(instr); RecordCallPosition(instr);
frame_access_state()->ClearSPDelta(); frame_access_state()->ClearSPDelta();
...@@ -537,11 +541,19 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ...@@ -537,11 +541,19 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
if (info()->IsWasm()) { if (info()->IsWasm()) {
__ wasm_call(wasm_code, RelocInfo::WASM_CALL); __ wasm_call(wasm_code, RelocInfo::WASM_CALL);
} else { } 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 { } else {
Register reg = i.InputRegister(0); Register reg = i.InputRegister(0);
__ call(reg); if (HasCallDescriptorFlag(instr, CallDescriptor::kRetpoline)) {
__ RetpolineCall(reg);
} else {
__ call(reg);
}
} }
RecordCallPosition(instr); RecordCallPosition(instr);
frame_access_state()->ClearSPDelta(); frame_access_state()->ClearSPDelta();
...@@ -559,7 +571,11 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ...@@ -559,7 +571,11 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
} else { } else {
Register reg = i.InputRegister(0); Register reg = i.InputRegister(0);
__ add(reg, Immediate(Code::kHeaderSize - kHeapObjectTag)); __ 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()->ClearSPDelta();
frame_access_state()->SetFrameAccessToDefault(); frame_access_state()->SetFrameAccessToDefault();
...@@ -576,7 +592,11 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ...@@ -576,7 +592,11 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
} }
} else { } else {
Register reg = i.InputRegister(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()->ClearSPDelta();
frame_access_state()->SetFrameAccessToDefault(); frame_access_state()->SetFrameAccessToDefault();
...@@ -585,7 +605,11 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ...@@ -585,7 +605,11 @@ 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);
__ jmp(reg); if (HasCallDescriptorFlag(instr, CallDescriptor::kRetpoline)) {
__ RetpolineJump(reg);
} else {
__ jmp(reg);
}
frame_access_state()->ClearSPDelta(); frame_access_state()->ClearSPDelta();
frame_access_state()->SetFrameAccessToDefault(); frame_access_state()->SetFrameAccessToDefault();
break; break;
......
...@@ -593,11 +593,6 @@ void CodeGenerator::BailoutIfDeoptimized() { ...@@ -593,11 +593,6 @@ void CodeGenerator::BailoutIfDeoptimized() {
__ j(not_zero, code, RelocInfo::CODE_TARGET); __ 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. // Assembles an instruction after register allocation, producing machine code.
CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
Instruction* instr) { Instruction* instr) {
......
...@@ -655,6 +655,13 @@ void Assembler::mov(const Operand& dst, const Immediate& x) { ...@@ -655,6 +655,13 @@ void Assembler::mov(const Operand& dst, const Immediate& x) {
emit(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) { void Assembler::mov(const Operand& dst, Handle<HeapObject> handle) {
EnsureSpace ensure_space(this); EnsureSpace ensure_space(this);
EMIT(0xC7); EMIT(0xC7);
...@@ -803,6 +810,12 @@ void Assembler::lfence() { ...@@ -803,6 +810,12 @@ void Assembler::lfence() {
EMIT(0xE8); EMIT(0xE8);
} }
void Assembler::pause() {
EnsureSpace ensure_space(this);
EMIT(0xF3);
EMIT(0x90);
}
void Assembler::adc(Register dst, int32_t imm32) { void Assembler::adc(Register dst, int32_t imm32) {
EnsureSpace ensure_space(this); EnsureSpace ensure_space(this);
emit_arith(2, Operand(dst), Immediate(imm32)); emit_arith(2, Operand(dst), Immediate(imm32));
......
...@@ -623,6 +623,7 @@ class Assembler : public AssemblerBase { ...@@ -623,6 +623,7 @@ class Assembler : public AssemblerBase {
void mov(const Operand& dst, const Immediate& x); void mov(const Operand& dst, const Immediate& x);
void mov(const Operand& dst, Handle<HeapObject> handle); void mov(const Operand& dst, Handle<HeapObject> handle);
void mov(const Operand& dst, Register src); 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, Register src) { movsx_b(dst, Operand(src)); }
void movsx_b(Register dst, const Operand& src); void movsx_b(Register dst, const Operand& src);
...@@ -667,6 +668,8 @@ class Assembler : public AssemblerBase { ...@@ -667,6 +668,8 @@ class Assembler : public AssemblerBase {
// Memory Fence // Memory Fence
void lfence(); void lfence();
void pause();
// Arithmetics // Arithmetics
void adc(Register dst, int32_t imm32); void adc(Register dst, int32_t imm32);
void adc(Register dst, const Operand& src); void adc(Register dst, const Operand& src);
......
...@@ -1547,6 +1547,59 @@ void TurboAssembler::CallCFunction(Register function, int num_arguments) { ...@@ -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 #ifdef DEBUG
bool AreAliased(Register reg1, bool AreAliased(Register reg1,
......
...@@ -113,6 +113,11 @@ class TurboAssembler : public Assembler { ...@@ -113,6 +113,11 @@ class TurboAssembler : public Assembler {
void Call(Handle<Code> target, RelocInfo::Mode rmode) { call(target, rmode); } void Call(Handle<Code> target, RelocInfo::Mode rmode) { call(target, rmode); }
void Call(Label* target) { call(target); } 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) { void CallForDeoptimization(Address target, RelocInfo::Mode rmode) {
call(target, 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