From e6023c55a8bd3abdb8cc77702670702afa7656a1 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sat, 10 Nov 2018 22:48:20 +0100 Subject: [PATCH] - modify exception checks to jump ahead if the exception is to be thrown as it limits static misprediction --- src/scripting/vm/jit.cpp | 16 ++++-- src/scripting/vm/jit_flow.cpp | 40 +++++++------- src/scripting/vm/jit_load.cpp | 12 ++-- src/scripting/vm/jit_math.cpp | 101 ++++++++++++++-------------------- src/scripting/vm/jitintern.h | 1 + 5 files changed, 77 insertions(+), 93 deletions(-) diff --git a/src/scripting/vm/jit.cpp b/src/scripting/vm/jit.cpp index 767423585..6063ee366 100644 --- a/src/scripting/vm/jit.cpp +++ b/src/scripting/vm/jit.cpp @@ -678,11 +678,9 @@ void JitCompiler::EmitPopFrame() void JitCompiler::EmitNullPointerThrow(int index, EVMAbortException reason) { - auto label = cc.newLabel(); + auto label = EmitThrowExceptionLabel(reason); cc.test(regA[index], regA[index]); - cc.jne(label); - EmitThrowException(reason); - cc.bind(label); + cc.je(label); } void JitCompiler::ThrowException(VMScriptFunction *func, VMOP *line, int reason) @@ -705,6 +703,16 @@ void JitCompiler::EmitThrowException(EVMAbortException 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) { if (r0 != r1) diff --git a/src/scripting/vm/jit_flow.cpp b/src/scripting/vm/jit_flow.cpp index c0359f2ea..482dfe2a9 100644 --- a/src/scripting/vm/jit_flow.cpp +++ b/src/scripting/vm/jit_flow.cpp @@ -50,11 +50,9 @@ void JitCompiler::EmitIJMP() void JitCompiler::EmitVTBL() { - auto notnull = cc.newLabel(); + auto label = EmitThrowExceptionLabel(X_READ_NIL); cc.test(regA[B], regA[B]); - cc.jnz(notnull); - EmitThrowException(X_READ_NIL); - cc.bind(notnull); + cc.jz(label); auto result = newResultIntPtr(); auto call = CreateCall([](DObject *o, int c) -> VMFunction* { @@ -70,11 +68,9 @@ void JitCompiler::EmitVTBL() void JitCompiler::EmitSCOPE() { - auto notnull = cc.newLabel(); + auto label = EmitThrowExceptionLabel(X_READ_NIL); cc.test(regA[A], regA[A]); - cc.jnz(notnull); - EmitThrowException(X_READ_NIL); - cc.bind(notnull); + cc.jz(label); auto f = newTempIntPtr(); cc.mov(f, asmjit::imm_ptr(konsta[C].v)); @@ -355,48 +351,50 @@ void JitCompiler::EmitTHROW() void JitCompiler::EmitBOUND() { + auto cursor = cc.getCursor(); auto label = cc.newLabel(); - - cc.cmp(regD[A], (int)BC); - cc.jb(label); - + cc.bind(label); auto call = CreateCall(&JitCompiler::ThrowArrayOutOfBounds); call->setArg(0, asmjit::imm_ptr(sfunc)); call->setArg(1, asmjit::imm_ptr(pc)); call->setArg(2, regD[A]); 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() { + auto cursor = cc.getCursor(); auto label = cc.newLabel(); - cc.cmp(regD[A], (int)konstd[BC]); - cc.jb(label); - + cc.bind(label); auto call = CreateCall(&JitCompiler::ThrowArrayOutOfBounds); call->setArg(0, asmjit::imm_ptr(sfunc)); call->setArg(1, asmjit::imm_ptr(pc)); call->setArg(2, regD[A]); 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() { + auto cursor = cc.getCursor(); auto label = cc.newLabel(); - cc.cmp(regD[A], regD[B]); - cc.jb(label); - + cc.bind(label); auto call = CreateCall(&JitCompiler::ThrowArrayOutOfBounds); call->setArg(0, asmjit::imm_ptr(sfunc)); call->setArg(1, asmjit::imm_ptr(pc)); call->setArg(2, regD[A]); 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) diff --git a/src/scripting/vm/jit_load.cpp b/src/scripting/vm/jit_load.cpp index 5f0b8d52f..3037a78b5 100644 --- a/src/scripting/vm/jit_load.cpp +++ b/src/scripting/vm/jit_load.cpp @@ -78,11 +78,9 @@ void JitCompiler::EmitLFP() void JitCompiler::EmitMETA() { - auto label = cc.newLabel(); + auto label = EmitThrowExceptionLabel(X_READ_NIL); cc.test(regA[B], regA[B]); - cc.jne(label); - EmitThrowException(X_READ_NIL); - cc.bind(label); + cc.je(label); auto result = newResultIntPtr(); auto call = CreateCall([](DObject *o) { return o->GetClass()->Meta; }); @@ -93,11 +91,9 @@ void JitCompiler::EmitMETA() void JitCompiler::EmitCLSS() { - auto label = cc.newLabel(); + auto label = EmitThrowExceptionLabel(X_READ_NIL); cc.test(regA[B], regA[B]); - cc.jne(label); - EmitThrowException(X_READ_NIL); - cc.bind(label); + cc.je(label); auto result = newResultIntPtr(); auto call = CreateCall([](DObject *o) { return o->GetClass(); }); diff --git a/src/scripting/vm/jit_math.cpp b/src/scripting/vm/jit_math.cpp index c53b76a9c..d88eae471 100644 --- a/src/scripting/vm/jit_math.cpp +++ b/src/scripting/vm/jit_math.cpp @@ -200,14 +200,11 @@ void JitCompiler::EmitDIV_RR() { auto tmp0 = newTempInt32(); auto tmp1 = newTempInt32(); - auto label = cc.newLabel(); + auto label = EmitThrowExceptionLabel(X_DIVISION_BY_ZERO); 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.cdq(tmp1, tmp0); cc.idiv(tmp1, tmp0, regD[C]); @@ -227,21 +224,21 @@ void JitCompiler::EmitDIV_RK() cc.idiv(tmp1, tmp0, asmjit::x86::ptr(konstTmp)); cc.mov(regD[A], tmp0); } - else EmitThrowException(X_DIVISION_BY_ZERO); + else + { + EmitThrowException(X_DIVISION_BY_ZERO); + } } void JitCompiler::EmitDIV_KR() { auto tmp0 = newTempInt32(); auto tmp1 = newTempInt32(); - auto label = cc.newLabel(); + auto label = EmitThrowExceptionLabel(X_DIVISION_BY_ZERO); 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.cdq(tmp1, tmp0); cc.idiv(tmp1, tmp0, regD[C]); @@ -252,14 +249,11 @@ void JitCompiler::EmitDIVU_RR() { auto tmp0 = newTempInt32(); auto tmp1 = newTempInt32(); - auto label = cc.newLabel(); + auto label = EmitThrowExceptionLabel(X_DIVISION_BY_ZERO); 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(tmp1, 0); cc.div(tmp1, tmp0, regD[C]); @@ -279,21 +273,21 @@ void JitCompiler::EmitDIVU_RK() cc.div(tmp1, tmp0, asmjit::x86::ptr(konstTmp)); cc.mov(regD[A], tmp0); } - else EmitThrowException(X_DIVISION_BY_ZERO); + else + { + EmitThrowException(X_DIVISION_BY_ZERO); + } } void JitCompiler::EmitDIVU_KR() { auto tmp0 = newTempInt32(); auto tmp1 = newTempInt32(); - auto label = cc.newLabel(); + auto label = EmitThrowExceptionLabel(X_DIVISION_BY_ZERO); 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(tmp1, 0); cc.div(tmp1, tmp0, regD[C]); @@ -304,14 +298,11 @@ void JitCompiler::EmitMOD_RR() { auto tmp0 = newTempInt32(); auto tmp1 = newTempInt32(); - auto label = cc.newLabel(); + auto label = EmitThrowExceptionLabel(X_DIVISION_BY_ZERO); 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.cdq(tmp1, tmp0); cc.idiv(tmp1, tmp0, regD[C]); @@ -331,21 +322,21 @@ void JitCompiler::EmitMOD_RK() cc.idiv(tmp1, tmp0, asmjit::x86::ptr(konstTmp)); cc.mov(regD[A], tmp1); } - else EmitThrowException(X_DIVISION_BY_ZERO); + else + { + EmitThrowException(X_DIVISION_BY_ZERO); + } } void JitCompiler::EmitMOD_KR() { auto tmp0 = newTempInt32(); auto tmp1 = newTempInt32(); - auto label = cc.newLabel(); + auto label = EmitThrowExceptionLabel(X_DIVISION_BY_ZERO); 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.cdq(tmp1, tmp0); cc.idiv(tmp1, tmp0, regD[C]); @@ -356,14 +347,11 @@ void JitCompiler::EmitMODU_RR() { auto tmp0 = newTempInt32(); auto tmp1 = newTempInt32(); - auto label = cc.newLabel(); + auto label = EmitThrowExceptionLabel(X_DIVISION_BY_ZERO); 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(tmp1, 0); cc.div(tmp1, tmp0, regD[C]); @@ -383,21 +371,21 @@ void JitCompiler::EmitMODU_RK() cc.div(tmp1, tmp0, asmjit::x86::ptr(konstTmp)); cc.mov(regD[A], tmp1); } - else EmitThrowException(X_DIVISION_BY_ZERO); + else + { + EmitThrowException(X_DIVISION_BY_ZERO); + } } void JitCompiler::EmitMODU_KR() { auto tmp0 = newTempInt32(); auto tmp1 = newTempInt32(); - auto label = cc.newLabel(); + auto label = EmitThrowExceptionLabel(X_DIVISION_BY_ZERO); 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(tmp1, 0); cc.div(tmp1, tmp0, regD[C]); @@ -717,11 +705,10 @@ void JitCompiler::EmitMULF_RK() void JitCompiler::EmitDIVF_RR() { - auto label = cc.newLabel(); + auto label = EmitThrowExceptionLabel(X_DIVISION_BY_ZERO); cc.ptest(regF[C], regF[C]); - cc.jne(label); - EmitThrowException(X_DIVISION_BY_ZERO); - cc.bind(label); + cc.je(label); + auto rc = CheckRegF(C, A); cc.movsd(regF[A], regF[B]); cc.divsd(regF[A], rc); @@ -753,11 +740,9 @@ void JitCompiler::EmitDIVF_KR() void JitCompiler::EmitMODF_RR() { - auto label = cc.newLabel(); + auto label = EmitThrowExceptionLabel(X_DIVISION_BY_ZERO); cc.ptest(regF[C], regF[C]); - cc.jne(label); - EmitThrowException(X_DIVISION_BY_ZERO); - cc.bind(label); + cc.je(label); auto result = newResultXmmSd(); auto call = CreateCall([](double a, double b) -> double @@ -772,11 +757,9 @@ void JitCompiler::EmitMODF_RR() void JitCompiler::EmitMODF_RK() { - auto label = cc.newLabel(); + auto label = EmitThrowExceptionLabel(X_DIVISION_BY_ZERO); cc.ptest(regF[C], regF[C]); - cc.jne(label); - EmitThrowException(X_DIVISION_BY_ZERO); - cc.bind(label); + cc.je(label); auto tmp = newTempXmmSd(); cc.movsd(tmp, asmjit::x86::ptr(ToMemAddress(&konstf[C]))); @@ -795,11 +778,9 @@ void JitCompiler::EmitMODF_KR() { using namespace asmjit; - auto label = cc.newLabel(); + auto label = EmitThrowExceptionLabel(X_DIVISION_BY_ZERO); cc.ptest(regF[C], regF[C]); - cc.jne(label); - EmitThrowException(X_DIVISION_BY_ZERO); - cc.bind(label); + cc.je(label); auto tmp = newTempXmmSd(); cc.movsd(tmp, x86::ptr(ToMemAddress(&konstf[B]))); diff --git a/src/scripting/vm/jitintern.h b/src/scripting/vm/jitintern.h index f19c202bf..14a6c995d 100644 --- a/src/scripting/vm/jitintern.h +++ b/src/scripting/vm/jitintern.h @@ -146,6 +146,7 @@ private: void EmitNullPointerThrow(int index, EVMAbortException reason); void EmitThrowException(EVMAbortException reason); + asmjit::Label EmitThrowExceptionLabel(EVMAbortException reason); static void ThrowArrayOutOfBounds(VMScriptFunction *func, VMOP *line, int index, int size); static void ThrowException(VMScriptFunction *func, VMOP *line, int reason);