From d47988202ab618478995dce40d605aa3c1a045ef Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sun, 7 Oct 2018 06:29:54 +0200 Subject: [PATCH] - workaround bug in asmjit's register allocator for calls where the return register is already allocated in a physical register needed by one of the call arguments --- src/scripting/vm/jit.cpp | 2 +- src/scripting/vm/jit_flow.cpp | 4 +++- src/scripting/vm/jit_load.cpp | 16 +++++++++---- src/scripting/vm/jit_math.cpp | 40 ++++++++++++++++++++++++-------- src/scripting/vm/jit_move.cpp | 43 ++++++++++++++++++++++++++--------- 5 files changed, 78 insertions(+), 27 deletions(-) diff --git a/src/scripting/vm/jit.cpp b/src/scripting/vm/jit.cpp index b802ecd8e0..0b70f8398f 100644 --- a/src/scripting/vm/jit.cpp +++ b/src/scripting/vm/jit.cpp @@ -47,7 +47,7 @@ static void OutputJitLog(const asmjit::StringLogger &logger) JitFuncPtr JitCompile(VMScriptFunction *sfunc) { #if defined(DEBUG_JIT) - if (strcmp(sfunc->PrintableName.GetChars(), "Key.ShouldStay") != 0) + if (strcmp(sfunc->PrintableName.GetChars(), "StatusScreen.drawNum") != 0) return nullptr; #else if (!JitCompiler::CanJit(sfunc)) diff --git a/src/scripting/vm/jit_flow.cpp b/src/scripting/vm/jit_flow.cpp index 0884a9e006..41c8015586 100644 --- a/src/scripting/vm/jit_flow.cpp +++ b/src/scripting/vm/jit_flow.cpp @@ -56,14 +56,16 @@ void JitCompiler::EmitVTBL() EmitThrowException(X_READ_NIL); cc.bind(notnull); + auto result = cc.newIntPtr(); auto call = CreateCall([](DObject *o, int c) -> VMFunction* { auto p = o->GetClass(); assert(c < (int)p->Virtuals.Size()); return p->Virtuals[c]; }); - call->setRet(0, regA[A]); + call->setRet(0, result); call->setArg(0, regA[B]); call->setArg(1, asmjit::Imm(C)); + cc.mov(regA[A], result); } void JitCompiler::EmitSCOPE() diff --git a/src/scripting/vm/jit_load.cpp b/src/scripting/vm/jit_load.cpp index 352e639b28..aca9510906 100644 --- a/src/scripting/vm/jit_load.cpp +++ b/src/scripting/vm/jit_load.cpp @@ -90,9 +90,11 @@ void JitCompiler::EmitMETA() EmitThrowException(X_READ_NIL); cc.bind(label); + auto result = cc.newIntPtr(); auto call = CreateCall([](DObject *o) { return o->GetClass()->Meta; }); - call->setRet(0, regA[A]); + call->setRet(0, result); call->setArg(0, regA[B]); + cc.mov(regA[A], result); } void JitCompiler::EmitCLSS() @@ -103,9 +105,11 @@ void JitCompiler::EmitCLSS() EmitThrowException(X_READ_NIL); cc.bind(label); + auto result = cc.newIntPtr(); auto call = CreateCall([](DObject *o) { return o->GetClass(); }); - call->setRet(0, regA[A]); + call->setRet(0, result); call->setArg(0, regA[B]); + cc.mov(regA[A], result); } ///////////////////////////////////////////////////////////////////////////// @@ -222,9 +226,11 @@ void JitCompiler::EmitLO() auto ptr = cc.newIntPtr(); cc.mov(ptr, asmjit::x86::ptr(regA[B], konstd[C])); + auto result = cc.newIntPtr(); auto call = CreateCall([](DObject *p) { return GC::ReadBarrier(p); }); - call->setRet(0, regA[A]); + call->setRet(0, result); call->setArg(0, ptr); + cc.mov(regA[A], result); } void JitCompiler::EmitLO_R() @@ -234,9 +240,11 @@ void JitCompiler::EmitLO_R() auto ptr = cc.newIntPtr(); cc.mov(ptr, asmjit::x86::ptr(regA[B], regD[C])); + auto result = cc.newIntPtr(); auto call = CreateCall([](DObject *p) { return GC::ReadBarrier(p); }); - call->setRet(0, regA[A]); + call->setRet(0, result); call->setArg(0, ptr); + cc.mov(regA[A], result); } void JitCompiler::EmitLP() diff --git a/src/scripting/vm/jit_math.cpp b/src/scripting/vm/jit_math.cpp index 98278e505c..3f7ac5d9af 100644 --- a/src/scripting/vm/jit_math.cpp +++ b/src/scripting/vm/jit_math.cpp @@ -17,11 +17,13 @@ void JitCompiler::EmitCONCAT() void JitCompiler::EmitLENS() { + auto result = cc.newInt32(); auto call = CreateCall([](FString* str) -> int { return static_cast(str->Len()); }); - call->setRet(0, regD[A]); + call->setRet(0, result); call->setArg(0, regS[B]); + cc.mov(regD[A], result); } void JitCompiler::EmitCMPS() @@ -757,13 +759,15 @@ void JitCompiler::EmitMODF_RR() EmitThrowException(X_DIVISION_BY_ZERO); cc.bind(label); + auto result = cc.newXmmSd(); auto call = CreateCall([](double a, double b) -> double { return a - floor(a / b) * b; }); - call->setRet(0, regF[A]); + call->setRet(0, result); call->setArg(0, regF[B]); call->setArg(1, regF[C]); + cc.movsd(regF[A], result); } void JitCompiler::EmitMODF_RK() @@ -777,12 +781,14 @@ void JitCompiler::EmitMODF_RK() auto tmp = cc.newXmm(); cc.movsd(tmp, asmjit::x86::ptr(ToMemAddress(&konstf[C]))); + auto result = cc.newXmmSd(); auto call = CreateCall([](double a, double b) -> double { return a - floor(a / b) * b; }); - call->setRet(0, regF[A]); + call->setRet(0, result); call->setArg(0, regF[B]); call->setArg(1, tmp); + cc.movsd(regF[A], result); } void JitCompiler::EmitMODF_KR() @@ -798,20 +804,24 @@ void JitCompiler::EmitMODF_KR() auto tmp = cc.newXmm(); cc.movsd(tmp, x86::ptr(ToMemAddress(&konstf[B]))); + auto result = cc.newXmmSd(); auto call = CreateCall([](double a, double b) -> double { return a - floor(a / b) * b; }); - call->setRet(0, regF[A]); + call->setRet(0, result); call->setArg(0, tmp); call->setArg(1, regF[C]); + cc.movsd(regF[A], result); } void JitCompiler::EmitPOWF_RR() { + auto result = cc.newXmmSd(); auto call = CreateCall(g_pow); - call->setRet(0, regF[A]); + call->setRet(0, result); call->setArg(0, regF[B]); call->setArg(1, regF[C]); + cc.movsd(regF[A], result); } void JitCompiler::EmitPOWF_RK() @@ -821,10 +831,12 @@ void JitCompiler::EmitPOWF_RK() cc.mov(tmp, asmjit::imm_ptr(&konstf[C])); cc.movsd(tmp2, asmjit::x86::qword_ptr(tmp)); + auto result = cc.newXmmSd(); auto call = CreateCall(g_pow); - call->setRet(0, regF[A]); + call->setRet(0, result); call->setArg(0, regF[B]); call->setArg(1, tmp2); + cc.movsd(regF[A], result); } void JitCompiler::EmitPOWF_KR() @@ -834,10 +846,12 @@ void JitCompiler::EmitPOWF_KR() cc.mov(tmp, asmjit::imm_ptr(&konstf[B])); cc.movsd(tmp2, asmjit::x86::qword_ptr(tmp)); + auto result = cc.newXmmSd(); auto call = CreateCall(g_pow); - call->setRet(0, regF[A]); + call->setRet(0, result); call->setArg(0, tmp2); call->setArg(1, regF[C]); + cc.movsd(regF[A], result); } void JitCompiler::EmitMINF_RR() @@ -876,10 +890,12 @@ void JitCompiler::EmitMAXF_RK() void JitCompiler::EmitATAN2() { + auto result = cc.newXmmSd(); auto call = CreateCall(g_atan2); - call->setRet(0, regF[A]); + call->setRet(0, result); call->setArg(0, regF[B]); call->setArg(1, regF[C]); + cc.movsd(regF[A], result); static const double constant = 180 / M_PI; auto tmp = cc.newIntPtr(); @@ -940,9 +956,11 @@ void JitCompiler::EmitFLOP() case FLOP_TANH: func = g_tanh; break; } + auto result = cc.newXmmSd(); auto call = CreateCall(func); - call->setRet(0, regF[A]); + call->setRet(0, result); call->setArg(0, v); + cc.movsd(regF[A], result); if (C == FLOP_ACOS_DEG || C == FLOP_ASIN_DEG || C == FLOP_ATAN_DEG) { @@ -1515,7 +1533,9 @@ void JitCompiler::EmitEQA_K() void JitCompiler::CallSqrt(const asmjit::X86Xmm &a, const asmjit::X86Xmm &b) { + auto result = cc.newXmmSd(); auto call = CreateCall(g_sqrt); - call->setRet(0, a); + call->setRet(0, result); call->setArg(0, b); + cc.movsd(a, result); } diff --git a/src/scripting/vm/jit_move.cpp b/src/scripting/vm/jit_move.cpp index c3bc215d60..e94b73d0e8 100644 --- a/src/scripting/vm/jit_move.cpp +++ b/src/scripting/vm/jit_move.cpp @@ -40,7 +40,8 @@ void JitCompiler::EmitMOVEV3() void JitCompiler::EmitCAST() { - asmjit::X86Gp tmp; + asmjit::X86Gp tmp, resultD; + asmjit::X86Xmm resultF; asmjit::CCFuncCall *call = nullptr; switch (C) @@ -96,19 +97,25 @@ void JitCompiler::EmitCAST() call->setArg(1, regA[B]); break; case CAST_S2I: + resultD = cc.newInt32(); call = CreateCall([](FString *b) -> int { return (VM_SWORD)b->ToLong(); }); - call->setRet(0, regD[A]); + call->setRet(0, resultD); call->setArg(0, regS[B]); + cc.mov(regD[A], resultD); break; case CAST_S2F: + resultF = cc.newXmmSd(); call = CreateCall([](FString *b) -> double { return b->ToDouble(); }); - call->setRet(0, regF[A]); + call->setRet(0, resultF); call->setArg(0, regS[B]); + cc.movsd(regF[A], resultF); break; case CAST_S2N: + resultD = cc.newInt32(); call = CreateCall([](FString *b) -> int { return b->Len() == 0 ? FName(NAME_None) : FName(*b); }); - call->setRet(0, regD[A]); + call->setRet(0, resultD); call->setArg(0, regS[B]); + cc.mov(regD[A], resultD); break; case CAST_N2S: call = CreateCall([](FString *a, int b) { FName name = FName(ENamedName(b)); *a = name.IsValidName() ? name.GetChars() : ""; }); @@ -116,9 +123,11 @@ void JitCompiler::EmitCAST() call->setArg(1, regD[B]); break; case CAST_S2Co: + resultD = cc.newInt32(); call = CreateCall([](FString *b) -> int { return V_GetColor(nullptr, *b); }); - call->setRet(0, regD[A]); + call->setRet(0, resultD); call->setArg(0, regS[B]); + cc.mov(regD[A], resultD); break; case CAST_Co2S: call = CreateCall([](FString *a, int b) { PalEntry c(b); a->Format("%02x %02x %02x", c.r, c.g, c.b); }); @@ -126,9 +135,11 @@ void JitCompiler::EmitCAST() call->setArg(1, regD[B]); break; case CAST_S2So: + resultD = cc.newInt32(); call = CreateCall([](FString *b) -> int { return FSoundID(*b); }); - call->setRet(0, regD[A]); + call->setRet(0, resultD); call->setArg(0, regS[B]); + cc.mov(regD[A], resultD); break; case CAST_So2S: call = CreateCall([](FString *a, int b) { *a = S_sfx[b].name; }); @@ -174,54 +185,64 @@ void JitCompiler::EmitCASTB() } else { + auto result = cc.newInt32(); auto call = CreateCall([](FString *s) -> int { return s->Len() > 0; }); - call->setRet(0, regD[A]); + call->setRet(0, result); call->setArg(0, regS[B]); + cc.mov(regD[A], result); } } void JitCompiler::EmitDYNCAST_R() { + auto result = cc.newIntPtr(); auto call = CreateCall([](DObject *obj, PClass *cls) -> DObject* { return (obj && obj->IsKindOf(cls)) ? obj : nullptr; }); - call->setRet(0, regA[A]); + call->setRet(0, result); call->setArg(0, regA[B]); call->setArg(1, regA[C]); + cc.mov(regA[A], result); } void JitCompiler::EmitDYNCAST_K() { + auto result = cc.newIntPtr(); auto c = cc.newIntPtr(); cc.mov(c, asmjit::imm_ptr(konsta[C].o)); auto call = CreateCall([](DObject *obj, PClass *cls) -> DObject* { return (obj && obj->IsKindOf(cls)) ? obj : nullptr; }); - call->setRet(0, regA[A]); + call->setRet(0, result); call->setArg(0, regA[B]); call->setArg(1, c); + cc.mov(regA[A], result); } void JitCompiler::EmitDYNCASTC_R() { + auto result = cc.newIntPtr(); auto call = CreateCall([](PClass *cls1, PClass *cls2) -> PClass* { return (cls1 && cls1->IsDescendantOf(cls2)) ? cls1 : nullptr; }); - call->setRet(0, regA[A]); + call->setRet(0, result); call->setArg(0, regA[B]); call->setArg(1, regA[C]); + cc.mov(regA[A], result); } void JitCompiler::EmitDYNCASTC_K() { using namespace asmjit; + auto result = cc.newIntPtr(); auto c = cc.newIntPtr(); cc.mov(c, asmjit::imm_ptr(konsta[C].o)); typedef PClass*(*FuncPtr)(PClass*, PClass*); auto call = CreateCall([](PClass *cls1, PClass *cls2) -> PClass* { return (cls1 && cls1->IsDescendantOf(cls2)) ? cls1 : nullptr; }); - call->setRet(0, regA[A]); + call->setRet(0, result); call->setArg(0, regA[B]); call->setArg(1, c); + cc.mov(regA[A], result); }