- modify exception checks to jump ahead if the exception is to be thrown as it limits static misprediction

This commit is contained in:
Magnus Norddahl 2018-11-10 22:48:20 +01:00
parent a7ef178284
commit e6023c55a8
5 changed files with 77 additions and 93 deletions

View file

@ -678,11 +678,9 @@ void JitCompiler::EmitPopFrame()
void JitCompiler::EmitNullPointerThrow(int index, EVMAbortException reason) void JitCompiler::EmitNullPointerThrow(int index, EVMAbortException reason)
{ {
auto label = cc.newLabel(); auto label = EmitThrowExceptionLabel(reason);
cc.test(regA[index], regA[index]); cc.test(regA[index], regA[index]);
cc.jne(label); cc.je(label);
EmitThrowException(reason);
cc.bind(label);
} }
void JitCompiler::ThrowException(VMScriptFunction *func, VMOP *line, int reason) void JitCompiler::ThrowException(VMScriptFunction *func, VMOP *line, int reason)
@ -705,6 +703,16 @@ void JitCompiler::EmitThrowException(EVMAbortException reason)
call->setArg(2, asmjit::imm(reason)); call->setArg(2, asmjit::imm(reason));
} }
asmjit::Label JitCompiler::EmitThrowExceptionLabel(EVMAbortException reason)
{
auto label = cc.newLabel();
auto cursor = cc.getCursor();
cc.bind(label);
EmitThrowException(reason);
cc.setCursor(cursor);
return label;
}
asmjit::X86Gp JitCompiler::CheckRegD(int r0, int r1) asmjit::X86Gp JitCompiler::CheckRegD(int r0, int r1)
{ {
if (r0 != r1) if (r0 != r1)

View file

@ -50,11 +50,9 @@ void JitCompiler::EmitIJMP()
void JitCompiler::EmitVTBL() void JitCompiler::EmitVTBL()
{ {
auto notnull = cc.newLabel(); auto label = EmitThrowExceptionLabel(X_READ_NIL);
cc.test(regA[B], regA[B]); cc.test(regA[B], regA[B]);
cc.jnz(notnull); cc.jz(label);
EmitThrowException(X_READ_NIL);
cc.bind(notnull);
auto result = newResultIntPtr(); auto result = newResultIntPtr();
auto call = CreateCall<VMFunction*, DObject*, int>([](DObject *o, int c) -> VMFunction* { auto call = CreateCall<VMFunction*, DObject*, int>([](DObject *o, int c) -> VMFunction* {
@ -70,11 +68,9 @@ void JitCompiler::EmitVTBL()
void JitCompiler::EmitSCOPE() void JitCompiler::EmitSCOPE()
{ {
auto notnull = cc.newLabel(); auto label = EmitThrowExceptionLabel(X_READ_NIL);
cc.test(regA[A], regA[A]); cc.test(regA[A], regA[A]);
cc.jnz(notnull); cc.jz(label);
EmitThrowException(X_READ_NIL);
cc.bind(notnull);
auto f = newTempIntPtr(); auto f = newTempIntPtr();
cc.mov(f, asmjit::imm_ptr(konsta[C].v)); cc.mov(f, asmjit::imm_ptr(konsta[C].v));
@ -355,48 +351,50 @@ void JitCompiler::EmitTHROW()
void JitCompiler::EmitBOUND() void JitCompiler::EmitBOUND()
{ {
auto cursor = cc.getCursor();
auto label = cc.newLabel(); auto label = cc.newLabel();
cc.bind(label);
cc.cmp(regD[A], (int)BC);
cc.jb(label);
auto call = CreateCall<void, VMScriptFunction *, VMOP *, int, int>(&JitCompiler::ThrowArrayOutOfBounds); auto call = CreateCall<void, VMScriptFunction *, VMOP *, int, int>(&JitCompiler::ThrowArrayOutOfBounds);
call->setArg(0, asmjit::imm_ptr(sfunc)); call->setArg(0, asmjit::imm_ptr(sfunc));
call->setArg(1, asmjit::imm_ptr(pc)); call->setArg(1, asmjit::imm_ptr(pc));
call->setArg(2, regD[A]); call->setArg(2, regD[A]);
call->setArg(3, asmjit::imm(BC)); call->setArg(3, asmjit::imm(BC));
cc.setCursor(cursor);
cc.bind(label); cc.cmp(regD[A], (int)BC);
cc.jae(label);
} }
void JitCompiler::EmitBOUND_K() void JitCompiler::EmitBOUND_K()
{ {
auto cursor = cc.getCursor();
auto label = cc.newLabel(); auto label = cc.newLabel();
cc.cmp(regD[A], (int)konstd[BC]); cc.bind(label);
cc.jb(label);
auto call = CreateCall<void, VMScriptFunction *, VMOP *, int, int>(&JitCompiler::ThrowArrayOutOfBounds); auto call = CreateCall<void, VMScriptFunction *, VMOP *, int, int>(&JitCompiler::ThrowArrayOutOfBounds);
call->setArg(0, asmjit::imm_ptr(sfunc)); call->setArg(0, asmjit::imm_ptr(sfunc));
call->setArg(1, asmjit::imm_ptr(pc)); call->setArg(1, asmjit::imm_ptr(pc));
call->setArg(2, regD[A]); call->setArg(2, regD[A]);
call->setArg(3, asmjit::imm(konstd[BC])); call->setArg(3, asmjit::imm(konstd[BC]));
cc.setCursor(cursor);
cc.bind(label); cc.cmp(regD[A], (int)konstd[BC]);
cc.jae(label);
} }
void JitCompiler::EmitBOUND_R() void JitCompiler::EmitBOUND_R()
{ {
auto cursor = cc.getCursor();
auto label = cc.newLabel(); auto label = cc.newLabel();
cc.cmp(regD[A], regD[B]); cc.bind(label);
cc.jb(label);
auto call = CreateCall<void, VMScriptFunction *, VMOP *, int, int>(&JitCompiler::ThrowArrayOutOfBounds); auto call = CreateCall<void, VMScriptFunction *, VMOP *, int, int>(&JitCompiler::ThrowArrayOutOfBounds);
call->setArg(0, asmjit::imm_ptr(sfunc)); call->setArg(0, asmjit::imm_ptr(sfunc));
call->setArg(1, asmjit::imm_ptr(pc)); call->setArg(1, asmjit::imm_ptr(pc));
call->setArg(2, regD[A]); call->setArg(2, regD[A]);
call->setArg(3, regD[B]); call->setArg(3, regD[B]);
cc.setCursor(cursor);
cc.bind(label); cc.cmp(regD[A], regD[B]);
cc.jae(label);
} }
void JitCompiler::ThrowArrayOutOfBounds(VMScriptFunction *func, VMOP *line, int index, int size) void JitCompiler::ThrowArrayOutOfBounds(VMScriptFunction *func, VMOP *line, int index, int size)

View file

@ -78,11 +78,9 @@ void JitCompiler::EmitLFP()
void JitCompiler::EmitMETA() void JitCompiler::EmitMETA()
{ {
auto label = cc.newLabel(); auto label = EmitThrowExceptionLabel(X_READ_NIL);
cc.test(regA[B], regA[B]); cc.test(regA[B], regA[B]);
cc.jne(label); cc.je(label);
EmitThrowException(X_READ_NIL);
cc.bind(label);
auto result = newResultIntPtr(); auto result = newResultIntPtr();
auto call = CreateCall<uint8_t*, DObject*>([](DObject *o) { return o->GetClass()->Meta; }); auto call = CreateCall<uint8_t*, DObject*>([](DObject *o) { return o->GetClass()->Meta; });
@ -93,11 +91,9 @@ void JitCompiler::EmitMETA()
void JitCompiler::EmitCLSS() void JitCompiler::EmitCLSS()
{ {
auto label = cc.newLabel(); auto label = EmitThrowExceptionLabel(X_READ_NIL);
cc.test(regA[B], regA[B]); cc.test(regA[B], regA[B]);
cc.jne(label); cc.je(label);
EmitThrowException(X_READ_NIL);
cc.bind(label);
auto result = newResultIntPtr(); auto result = newResultIntPtr();
auto call = CreateCall<PClass*, DObject*>([](DObject *o) { return o->GetClass(); }); auto call = CreateCall<PClass*, DObject*>([](DObject *o) { return o->GetClass(); });

View file

@ -200,14 +200,11 @@ void JitCompiler::EmitDIV_RR()
{ {
auto tmp0 = newTempInt32(); auto tmp0 = newTempInt32();
auto tmp1 = newTempInt32(); auto tmp1 = newTempInt32();
auto label = cc.newLabel();
auto label = EmitThrowExceptionLabel(X_DIVISION_BY_ZERO);
cc.test(regD[C], regD[C]); cc.test(regD[C], regD[C]);
cc.jne(label); cc.je(label);
EmitThrowException(X_DIVISION_BY_ZERO);
cc.bind(label);
cc.mov(tmp0, regD[B]); cc.mov(tmp0, regD[B]);
cc.cdq(tmp1, tmp0); cc.cdq(tmp1, tmp0);
cc.idiv(tmp1, tmp0, regD[C]); cc.idiv(tmp1, tmp0, regD[C]);
@ -227,21 +224,21 @@ void JitCompiler::EmitDIV_RK()
cc.idiv(tmp1, tmp0, asmjit::x86::ptr(konstTmp)); cc.idiv(tmp1, tmp0, asmjit::x86::ptr(konstTmp));
cc.mov(regD[A], tmp0); cc.mov(regD[A], tmp0);
} }
else EmitThrowException(X_DIVISION_BY_ZERO); else
{
EmitThrowException(X_DIVISION_BY_ZERO);
}
} }
void JitCompiler::EmitDIV_KR() void JitCompiler::EmitDIV_KR()
{ {
auto tmp0 = newTempInt32(); auto tmp0 = newTempInt32();
auto tmp1 = newTempInt32(); auto tmp1 = newTempInt32();
auto label = cc.newLabel();
auto label = EmitThrowExceptionLabel(X_DIVISION_BY_ZERO);
cc.test(regD[C], regD[C]); cc.test(regD[C], regD[C]);
cc.jne(label); cc.je(label);
EmitThrowException(X_DIVISION_BY_ZERO);
cc.bind(label);
cc.mov(tmp0, konstd[B]); cc.mov(tmp0, konstd[B]);
cc.cdq(tmp1, tmp0); cc.cdq(tmp1, tmp0);
cc.idiv(tmp1, tmp0, regD[C]); cc.idiv(tmp1, tmp0, regD[C]);
@ -252,14 +249,11 @@ void JitCompiler::EmitDIVU_RR()
{ {
auto tmp0 = newTempInt32(); auto tmp0 = newTempInt32();
auto tmp1 = newTempInt32(); auto tmp1 = newTempInt32();
auto label = cc.newLabel();
auto label = EmitThrowExceptionLabel(X_DIVISION_BY_ZERO);
cc.test(regD[C], regD[C]); cc.test(regD[C], regD[C]);
cc.jne(label); cc.je(label);
EmitThrowException(X_DIVISION_BY_ZERO);
cc.bind(label);
cc.mov(tmp0, regD[B]); cc.mov(tmp0, regD[B]);
cc.mov(tmp1, 0); cc.mov(tmp1, 0);
cc.div(tmp1, tmp0, regD[C]); cc.div(tmp1, tmp0, regD[C]);
@ -279,21 +273,21 @@ void JitCompiler::EmitDIVU_RK()
cc.div(tmp1, tmp0, asmjit::x86::ptr(konstTmp)); cc.div(tmp1, tmp0, asmjit::x86::ptr(konstTmp));
cc.mov(regD[A], tmp0); cc.mov(regD[A], tmp0);
} }
else EmitThrowException(X_DIVISION_BY_ZERO); else
{
EmitThrowException(X_DIVISION_BY_ZERO);
}
} }
void JitCompiler::EmitDIVU_KR() void JitCompiler::EmitDIVU_KR()
{ {
auto tmp0 = newTempInt32(); auto tmp0 = newTempInt32();
auto tmp1 = newTempInt32(); auto tmp1 = newTempInt32();
auto label = cc.newLabel();
auto label = EmitThrowExceptionLabel(X_DIVISION_BY_ZERO);
cc.test(regD[C], regD[C]); cc.test(regD[C], regD[C]);
cc.jne(label); cc.je(label);
EmitThrowException(X_DIVISION_BY_ZERO);
cc.bind(label);
cc.mov(tmp0, konstd[B]); cc.mov(tmp0, konstd[B]);
cc.mov(tmp1, 0); cc.mov(tmp1, 0);
cc.div(tmp1, tmp0, regD[C]); cc.div(tmp1, tmp0, regD[C]);
@ -304,14 +298,11 @@ void JitCompiler::EmitMOD_RR()
{ {
auto tmp0 = newTempInt32(); auto tmp0 = newTempInt32();
auto tmp1 = newTempInt32(); auto tmp1 = newTempInt32();
auto label = cc.newLabel();
auto label = EmitThrowExceptionLabel(X_DIVISION_BY_ZERO);
cc.test(regD[C], regD[C]); cc.test(regD[C], regD[C]);
cc.jne(label); cc.je(label);
EmitThrowException(X_DIVISION_BY_ZERO);
cc.bind(label);
cc.mov(tmp0, regD[B]); cc.mov(tmp0, regD[B]);
cc.cdq(tmp1, tmp0); cc.cdq(tmp1, tmp0);
cc.idiv(tmp1, tmp0, regD[C]); cc.idiv(tmp1, tmp0, regD[C]);
@ -331,21 +322,21 @@ void JitCompiler::EmitMOD_RK()
cc.idiv(tmp1, tmp0, asmjit::x86::ptr(konstTmp)); cc.idiv(tmp1, tmp0, asmjit::x86::ptr(konstTmp));
cc.mov(regD[A], tmp1); cc.mov(regD[A], tmp1);
} }
else EmitThrowException(X_DIVISION_BY_ZERO); else
{
EmitThrowException(X_DIVISION_BY_ZERO);
}
} }
void JitCompiler::EmitMOD_KR() void JitCompiler::EmitMOD_KR()
{ {
auto tmp0 = newTempInt32(); auto tmp0 = newTempInt32();
auto tmp1 = newTempInt32(); auto tmp1 = newTempInt32();
auto label = cc.newLabel();
auto label = EmitThrowExceptionLabel(X_DIVISION_BY_ZERO);
cc.test(regD[C], regD[C]); cc.test(regD[C], regD[C]);
cc.jne(label); cc.je(label);
EmitThrowException(X_DIVISION_BY_ZERO);
cc.bind(label);
cc.mov(tmp0, konstd[B]); cc.mov(tmp0, konstd[B]);
cc.cdq(tmp1, tmp0); cc.cdq(tmp1, tmp0);
cc.idiv(tmp1, tmp0, regD[C]); cc.idiv(tmp1, tmp0, regD[C]);
@ -356,14 +347,11 @@ void JitCompiler::EmitMODU_RR()
{ {
auto tmp0 = newTempInt32(); auto tmp0 = newTempInt32();
auto tmp1 = newTempInt32(); auto tmp1 = newTempInt32();
auto label = cc.newLabel();
auto label = EmitThrowExceptionLabel(X_DIVISION_BY_ZERO);
cc.test(regD[C], regD[C]); cc.test(regD[C], regD[C]);
cc.jne(label); cc.je(label);
EmitThrowException(X_DIVISION_BY_ZERO);
cc.bind(label);
cc.mov(tmp0, regD[B]); cc.mov(tmp0, regD[B]);
cc.mov(tmp1, 0); cc.mov(tmp1, 0);
cc.div(tmp1, tmp0, regD[C]); cc.div(tmp1, tmp0, regD[C]);
@ -383,21 +371,21 @@ void JitCompiler::EmitMODU_RK()
cc.div(tmp1, tmp0, asmjit::x86::ptr(konstTmp)); cc.div(tmp1, tmp0, asmjit::x86::ptr(konstTmp));
cc.mov(regD[A], tmp1); cc.mov(regD[A], tmp1);
} }
else EmitThrowException(X_DIVISION_BY_ZERO); else
{
EmitThrowException(X_DIVISION_BY_ZERO);
}
} }
void JitCompiler::EmitMODU_KR() void JitCompiler::EmitMODU_KR()
{ {
auto tmp0 = newTempInt32(); auto tmp0 = newTempInt32();
auto tmp1 = newTempInt32(); auto tmp1 = newTempInt32();
auto label = cc.newLabel();
auto label = EmitThrowExceptionLabel(X_DIVISION_BY_ZERO);
cc.test(regD[C], regD[C]); cc.test(regD[C], regD[C]);
cc.jne(label); cc.je(label);
EmitThrowException(X_DIVISION_BY_ZERO);
cc.bind(label);
cc.mov(tmp0, konstd[B]); cc.mov(tmp0, konstd[B]);
cc.mov(tmp1, 0); cc.mov(tmp1, 0);
cc.div(tmp1, tmp0, regD[C]); cc.div(tmp1, tmp0, regD[C]);
@ -717,11 +705,10 @@ void JitCompiler::EmitMULF_RK()
void JitCompiler::EmitDIVF_RR() void JitCompiler::EmitDIVF_RR()
{ {
auto label = cc.newLabel(); auto label = EmitThrowExceptionLabel(X_DIVISION_BY_ZERO);
cc.ptest(regF[C], regF[C]); cc.ptest(regF[C], regF[C]);
cc.jne(label); cc.je(label);
EmitThrowException(X_DIVISION_BY_ZERO);
cc.bind(label);
auto rc = CheckRegF(C, A); auto rc = CheckRegF(C, A);
cc.movsd(regF[A], regF[B]); cc.movsd(regF[A], regF[B]);
cc.divsd(regF[A], rc); cc.divsd(regF[A], rc);
@ -753,11 +740,9 @@ void JitCompiler::EmitDIVF_KR()
void JitCompiler::EmitMODF_RR() void JitCompiler::EmitMODF_RR()
{ {
auto label = cc.newLabel(); auto label = EmitThrowExceptionLabel(X_DIVISION_BY_ZERO);
cc.ptest(regF[C], regF[C]); cc.ptest(regF[C], regF[C]);
cc.jne(label); cc.je(label);
EmitThrowException(X_DIVISION_BY_ZERO);
cc.bind(label);
auto result = newResultXmmSd(); auto result = newResultXmmSd();
auto call = CreateCall<double, double, double>([](double a, double b) -> double auto call = CreateCall<double, double, double>([](double a, double b) -> double
@ -772,11 +757,9 @@ void JitCompiler::EmitMODF_RR()
void JitCompiler::EmitMODF_RK() void JitCompiler::EmitMODF_RK()
{ {
auto label = cc.newLabel(); auto label = EmitThrowExceptionLabel(X_DIVISION_BY_ZERO);
cc.ptest(regF[C], regF[C]); cc.ptest(regF[C], regF[C]);
cc.jne(label); cc.je(label);
EmitThrowException(X_DIVISION_BY_ZERO);
cc.bind(label);
auto tmp = newTempXmmSd(); auto tmp = newTempXmmSd();
cc.movsd(tmp, asmjit::x86::ptr(ToMemAddress(&konstf[C]))); cc.movsd(tmp, asmjit::x86::ptr(ToMemAddress(&konstf[C])));
@ -795,11 +778,9 @@ void JitCompiler::EmitMODF_KR()
{ {
using namespace asmjit; using namespace asmjit;
auto label = cc.newLabel(); auto label = EmitThrowExceptionLabel(X_DIVISION_BY_ZERO);
cc.ptest(regF[C], regF[C]); cc.ptest(regF[C], regF[C]);
cc.jne(label); cc.je(label);
EmitThrowException(X_DIVISION_BY_ZERO);
cc.bind(label);
auto tmp = newTempXmmSd(); auto tmp = newTempXmmSd();
cc.movsd(tmp, x86::ptr(ToMemAddress(&konstf[B]))); cc.movsd(tmp, x86::ptr(ToMemAddress(&konstf[B])));

View file

@ -146,6 +146,7 @@ private:
void EmitNullPointerThrow(int index, EVMAbortException reason); void EmitNullPointerThrow(int index, EVMAbortException reason);
void EmitThrowException(EVMAbortException reason); void EmitThrowException(EVMAbortException reason);
asmjit::Label EmitThrowExceptionLabel(EVMAbortException reason);
static void ThrowArrayOutOfBounds(VMScriptFunction *func, VMOP *line, int index, int size); static void ThrowArrayOutOfBounds(VMScriptFunction *func, VMOP *line, int index, int size);
static void ThrowException(VMScriptFunction *func, VMOP *line, int reason); static void ThrowException(VMScriptFunction *func, VMOP *line, int reason);