Commit abac06aa authored by Junliang Yan's avatar Junliang Yan Committed by Commit Bot

PPC/s390: [Ignition] [TurboFan] Generate speculation poison in code generator.

Port a021b6c4

Original Commit Message:

    Moves generation of speculation poison to be based on the PC target vs the
    actual PC being executed. The speculation poison is generated in the prologue
    of the generated code if CompilationInfo::kGenerateSpeculationPoison is set.
    The result is stored in a known register, which can then be read using the
    SpeculationPoison machine node.

    Currently we need to ensure the SpeculationPoison node is scheduled right after
    the code prologue so that the poison register doesn't get clobbered. This is
    currently not verified, however it's only use is in RawMachineAssembler where
    it is manually scheduled early.

    The Ignition bytecode handlers are updated to use this speculation poison
    rather than one generated by comparing the target bytecode.

R=rmcilroy@chromium.org, joransiu@ca.ibm.com, michael_dawson@ca.ibm.com
BUG=chromium:798964
LOG=N

Change-Id: I4b9a1b0865b6164171cf83f0e45c36c69ac08a18
Reviewed-on: https://chromium-review.googlesource.com/914848Reviewed-by: 's avatarJoran Siu <joransiu@ca.ibm.com>
Commit-Queue: Junliang Yan <jyan@ca.ibm.com>
Cr-Commit-Position: refs/heads/master@{#51273}
parent 8f489e73
......@@ -1034,13 +1034,12 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
__ mov(kInterpreterDispatchTableRegister,
Operand(ExternalReference::interpreter_dispatch_table_address(
masm->isolate())));
__ lbzx(kInterpreterTargetBytecodeRegister,
MemOperand(kInterpreterBytecodeArrayRegister,
kInterpreterBytecodeOffsetRegister));
__ ShiftLeftImm(ip, kInterpreterTargetBytecodeRegister,
Operand(kPointerSizeLog2));
__ LoadPX(ip, MemOperand(kInterpreterDispatchTableRegister, ip));
__ Call(ip);
__ lbzx(r6, MemOperand(kInterpreterBytecodeArrayRegister,
kInterpreterBytecodeOffsetRegister));
__ ShiftLeftImm(r6, r6, Operand(kPointerSizeLog2));
__ LoadPX(kJavaScriptCallCodeStartRegister,
MemOperand(kInterpreterDispatchTableRegister, r6));
__ Call(kJavaScriptCallCodeStartRegister);
masm->isolate()->heap()->SetInterpreterEntryReturnPCOffset(masm->pc_offset());
......@@ -1263,13 +1262,12 @@ static void Generate_InterpreterEnterBytecode(MacroAssembler* masm) {
__ SmiUntag(kInterpreterBytecodeOffsetRegister);
// Dispatch to the target bytecode.
__ lbzx(kInterpreterTargetBytecodeRegister,
MemOperand(kInterpreterBytecodeArrayRegister,
kInterpreterBytecodeOffsetRegister));
__ ShiftLeftImm(ip, kInterpreterTargetBytecodeRegister,
Operand(kPointerSizeLog2));
__ LoadPX(ip, MemOperand(kInterpreterDispatchTableRegister, ip));
__ Jump(ip);
__ lbzx(ip, MemOperand(kInterpreterBytecodeArrayRegister,
kInterpreterBytecodeOffsetRegister));
__ ShiftLeftImm(ip, ip, Operand(kPointerSizeLog2));
__ LoadPX(kJavaScriptCallCodeStartRegister,
MemOperand(kInterpreterDispatchTableRegister, ip));
__ Jump(kJavaScriptCallCodeStartRegister);
}
void Builtins::Generate_InterpreterEnterBytecodeAdvance(MacroAssembler* masm) {
......
......@@ -1033,13 +1033,12 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
Operand(ExternalReference::interpreter_dispatch_table_address(
masm->isolate())));
__ LoadlB(kInterpreterTargetBytecodeRegister,
MemOperand(kInterpreterBytecodeArrayRegister,
kInterpreterBytecodeOffsetRegister));
__ ShiftLeftP(ip, kInterpreterTargetBytecodeRegister,
Operand(kPointerSizeLog2));
__ LoadP(ip, MemOperand(kInterpreterDispatchTableRegister, ip));
__ Call(ip);
__ LoadlB(r5, MemOperand(kInterpreterBytecodeArrayRegister,
kInterpreterBytecodeOffsetRegister));
__ ShiftLeftP(r5, r5, Operand(kPointerSizeLog2));
__ LoadP(kJavaScriptCallCodeStartRegister,
MemOperand(kInterpreterDispatchTableRegister, r5));
__ Call(kJavaScriptCallCodeStartRegister);
masm->isolate()->heap()->SetInterpreterEntryReturnPCOffset(masm->pc_offset());
......@@ -1260,13 +1259,12 @@ static void Generate_InterpreterEnterBytecode(MacroAssembler* masm) {
__ SmiUntag(kInterpreterBytecodeOffsetRegister);
// Dispatch to the target bytecode.
__ LoadlB(kInterpreterTargetBytecodeRegister,
MemOperand(kInterpreterBytecodeArrayRegister,
kInterpreterBytecodeOffsetRegister));
__ ShiftLeftP(ip, kInterpreterTargetBytecodeRegister,
Operand(kPointerSizeLog2));
__ LoadP(ip, MemOperand(kInterpreterDispatchTableRegister, ip));
__ Jump(ip);
__ LoadlB(ip, MemOperand(kInterpreterBytecodeArrayRegister,
kInterpreterBytecodeOffsetRegister));
__ ShiftLeftP(ip, ip, Operand(kPointerSizeLog2));
__ LoadP(kJavaScriptCallCodeStartRegister,
MemOperand(kInterpreterDispatchTableRegister, ip));
__ Jump(kJavaScriptCallCodeStartRegister);
}
void Builtins::Generate_InterpreterEnterBytecodeAdvance(MacroAssembler* masm) {
......
......@@ -807,6 +807,31 @@ void CodeGenerator::BailoutIfDeoptimized() {
__ Jump(code, RelocInfo::CODE_TARGET, ne, cr0);
}
void CodeGenerator::GenerateSpeculationPoison() {
Register scratch = kScratchReg;
Label current_pc;
__ mov_label_addr(scratch, &current_pc);
__ bind(&current_pc);
__ subi(scratch, scratch, Operand(__ pc_offset()));
// 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.
// difference = (current - expected) | (expected - current)
// poison = ~(difference >> (kBitsPerPointer - 1))
__ mr(kSpeculationPoisonRegister, scratch);
__ sub(kSpeculationPoisonRegister, kSpeculationPoisonRegister,
kJavaScriptCallCodeStartRegister);
__ sub(kJavaScriptCallCodeStartRegister, kJavaScriptCallCodeStartRegister,
scratch);
__ orx(kSpeculationPoisonRegister, kSpeculationPoisonRegister,
kJavaScriptCallCodeStartRegister);
__ ShiftRightArithImm(kSpeculationPoisonRegister, kSpeculationPoisonRegister,
kBitsPerPointer - 1);
__ notx(kSpeculationPoisonRegister, kSpeculationPoisonRegister);
}
// Assembles an instruction after register allocation, producing machine code.
CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
Instruction* instr) {
......
......@@ -1056,6 +1056,31 @@ void CodeGenerator::BailoutIfDeoptimized() {
__ Jump(code, RelocInfo::CODE_TARGET, ne);
}
void CodeGenerator::GenerateSpeculationPoison() {
Register scratch = r1;
Label current_pc;
__ larl(scratch, &current_pc);
__ bind(&current_pc);
__ SubP(scratch, Operand(__ pc_offset()));
// 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.
// difference = (current - expected) | (expected - current)
// poison = ~(difference >> (kBitsPerPointer - 1))
__ LoadRR(kSpeculationPoisonRegister, scratch);
__ SubP(kSpeculationPoisonRegister, kSpeculationPoisonRegister,
kJavaScriptCallCodeStartRegister);
__ SubP(kJavaScriptCallCodeStartRegister, kJavaScriptCallCodeStartRegister,
scratch);
__ OrP(kSpeculationPoisonRegister, kSpeculationPoisonRegister,
kJavaScriptCallCodeStartRegister);
__ ShiftRightArithP(kSpeculationPoisonRegister, kSpeculationPoisonRegister,
Operand(kBitsPerPointer - 1));
__ NotP(kSpeculationPoisonRegister, kSpeculationPoisonRegister);
}
// Assembles an instruction after register allocation, producing machine code.
CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
Instruction* instr) {
......
......@@ -291,8 +291,7 @@ void InterpreterDispatchDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {
kInterpreterAccumulatorRegister, kInterpreterBytecodeOffsetRegister,
kInterpreterBytecodeArrayRegister, kInterpreterDispatchTableRegister,
kInterpreterTargetBytecodeRegister};
kInterpreterBytecodeArrayRegister, kInterpreterDispatchTableRegister};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
......
......@@ -15,22 +15,23 @@ namespace v8 {
namespace internal {
// Give alias names to registers for calling conventions.
const Register kReturnRegister0 = r3;
const Register kReturnRegister1 = r4;
const Register kReturnRegister2 = r5;
const Register kJSFunctionRegister = r4;
const Register kContextRegister = r30;
const Register kAllocateSizeRegister = r4;
const Register kInterpreterAccumulatorRegister = r3;
const Register kInterpreterBytecodeOffsetRegister = r15;
const Register kInterpreterBytecodeArrayRegister = r16;
const Register kInterpreterDispatchTableRegister = r17;
const Register kInterpreterTargetBytecodeRegister = r14;
const Register kJavaScriptCallArgCountRegister = r3;
const Register kJavaScriptCallNewTargetRegister = r6;
const Register kOffHeapTrampolineRegister = ip;
const Register kRuntimeCallFunctionRegister = r4;
const Register kRuntimeCallArgCountRegister = r3;
constexpr Register kReturnRegister0 = r3;
constexpr Register kReturnRegister1 = r4;
constexpr Register kReturnRegister2 = r5;
constexpr Register kJSFunctionRegister = r4;
constexpr Register kContextRegister = r30;
constexpr Register kAllocateSizeRegister = r4;
constexpr Register kSpeculationPoisonRegister = r14;
constexpr Register kInterpreterAccumulatorRegister = r3;
constexpr Register kInterpreterBytecodeOffsetRegister = r15;
constexpr Register kInterpreterBytecodeArrayRegister = r16;
constexpr Register kInterpreterDispatchTableRegister = r17;
constexpr Register kJavaScriptCallArgCountRegister = r3;
constexpr Register kJavaScriptCallNewTargetRegister = r6;
constexpr Register kJavaScriptCallCodeStartRegister = r5;
constexpr Register kOffHeapTrampolineRegister = ip;
constexpr Register kRuntimeCallFunctionRegister = r4;
constexpr Register kRuntimeCallArgCountRegister = r3;
// ----------------------------------------------------------------------------
// Static helper functions
......
......@@ -285,8 +285,7 @@ void InterpreterDispatchDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {
kInterpreterAccumulatorRegister, kInterpreterBytecodeOffsetRegister,
kInterpreterBytecodeArrayRegister, kInterpreterDispatchTableRegister,
kInterpreterTargetBytecodeRegister};
kInterpreterBytecodeArrayRegister, kInterpreterDispatchTableRegister};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
......
......@@ -14,22 +14,23 @@ namespace v8 {
namespace internal {
// Give alias names to registers for calling conventions.
const Register kReturnRegister0 = r2;
const Register kReturnRegister1 = r3;
const Register kReturnRegister2 = r4;
const Register kJSFunctionRegister = r3;
const Register kContextRegister = r13;
const Register kAllocateSizeRegister = r3;
const Register kInterpreterAccumulatorRegister = r2;
const Register kInterpreterBytecodeOffsetRegister = r6;
const Register kInterpreterBytecodeArrayRegister = r7;
const Register kInterpreterDispatchTableRegister = r8;
const Register kInterpreterTargetBytecodeRegister = r5;
const Register kJavaScriptCallArgCountRegister = r2;
const Register kJavaScriptCallNewTargetRegister = r5;
const Register kOffHeapTrampolineRegister = ip;
const Register kRuntimeCallFunctionRegister = r3;
const Register kRuntimeCallArgCountRegister = r2;
constexpr Register kReturnRegister0 = r2;
constexpr Register kReturnRegister1 = r3;
constexpr Register kReturnRegister2 = r4;
constexpr Register kJSFunctionRegister = r3;
constexpr Register kContextRegister = r13;
constexpr Register kAllocateSizeRegister = r3;
constexpr Register kSpeculationPoisonRegister = r5;
constexpr Register kInterpreterAccumulatorRegister = r2;
constexpr Register kInterpreterBytecodeOffsetRegister = r6;
constexpr Register kInterpreterBytecodeArrayRegister = r7;
constexpr Register kInterpreterDispatchTableRegister = r8;
constexpr Register kJavaScriptCallArgCountRegister = r2;
constexpr Register kJavaScriptCallNewTargetRegister = r5;
constexpr Register kJavaScriptCallCodeStartRegister = r4;
constexpr Register kOffHeapTrampolineRegister = ip;
constexpr Register kRuntimeCallFunctionRegister = r3;
constexpr Register kRuntimeCallArgCountRegister = r2;
// ----------------------------------------------------------------------------
// Static helper functions
......
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