From f99bba48dcacf0a6cfa5ee412816012e529626e7 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sat, 17 Nov 2018 05:12:47 +0100 Subject: [PATCH] - stop using lambda functions for CreateCall because MSVC lambas use a different calling convention and "converts" them to the right one by generating a thunk function --- src/scripting/vm/jit.cpp | 58 +++++++----- src/scripting/vm/jit_flow.cpp | 172 +++++++++++++++++++--------------- src/scripting/vm/jit_load.cpp | 32 +++++-- src/scripting/vm/jit_math.cpp | 56 ++++++----- src/scripting/vm/jit_move.cpp | 79 ++++++++++------ 5 files changed, 234 insertions(+), 163 deletions(-) diff --git a/src/scripting/vm/jit.cpp b/src/scripting/vm/jit.cpp index ad57bdf8c..143aa90a7 100644 --- a/src/scripting/vm/jit.cpp +++ b/src/scripting/vm/jit.cpp @@ -560,26 +560,29 @@ void JitCompiler::SetupSimpleFrame() cc.xor_(regA[i], regA[i]); } +static VMFrameStack *CreateFullVMFrame(VMScriptFunction *func, VMValue *args, int numargs) +{ + try + { + VMFrameStack *stack = &GlobalVMStack; + VMFrame *newf = stack->AllocFrame(func); + CurrentJitExceptInfo->vmframes++; + VMFillParams(args, newf, numargs); + return stack; + } + catch (...) + { + VMThrowException(std::current_exception()); + return nullptr; + } +} + void JitCompiler::SetupFullVMFrame() { using namespace asmjit; stack = cc.newIntPtr("stack"); - auto allocFrame = CreateCall([](VMScriptFunction *func, VMValue *args, int numargs) -> VMFrameStack* { - try - { - VMFrameStack *stack = &GlobalVMStack; - VMFrame *newf = stack->AllocFrame(func); - CurrentJitExceptInfo->vmframes++; - VMFillParams(args, newf, numargs); - return stack; - } - catch (...) - { - VMThrowException(std::current_exception()); - return nullptr; - } - }); + auto allocFrame = CreateCall(CreateFullVMFrame); allocFrame->setRet(0, stack); allocFrame->setArg(0, imm_ptr(sfunc)); allocFrame->setArg(1, args); @@ -601,21 +604,24 @@ void JitCompiler::SetupFullVMFrame() cc.mov(regA[i], x86::ptr(vmframe, offsetA + i * sizeof(void*))); } +static void PopFullVMFrame(VMFrameStack *stack) +{ + try + { + stack->PopFrame(); + CurrentJitExceptInfo->vmframes--; + } + catch (...) + { + VMThrowException(std::current_exception()); + } +} + void JitCompiler::EmitPopFrame() { if (sfunc->SpecialInits.Size() != 0 || sfunc->NumRegS != 0) { - auto popFrame = CreateCall([](VMFrameStack *stack) { - try - { - stack->PopFrame(); - CurrentJitExceptInfo->vmframes--; - } - catch (...) - { - VMThrowException(std::current_exception()); - } - }); + auto popFrame = CreateCall(PopFullVMFrame); popFrame->setArg(0, stack); } } diff --git a/src/scripting/vm/jit_flow.cpp b/src/scripting/vm/jit_flow.cpp index 482dfe2a9..1a31b5d02 100644 --- a/src/scripting/vm/jit_flow.cpp +++ b/src/scripting/vm/jit_flow.cpp @@ -48,6 +48,13 @@ void JitCompiler::EmitIJMP() EmitThrowException(X_OTHER); } +static VMFunction *GetVirtual(DObject *o, int c) +{ + auto p = o->GetClass(); + assert(c < (int)p->Virtuals.Size()); + return p->Virtuals[c]; +} + void JitCompiler::EmitVTBL() { auto label = EmitThrowExceptionLabel(X_READ_NIL); @@ -55,17 +62,25 @@ void JitCompiler::EmitVTBL() cc.jz(label); auto result = newResultIntPtr(); - auto call = CreateCall([](DObject *o, int c) -> VMFunction* { - auto p = o->GetClass(); - assert(c < (int)p->Virtuals.Size()); - return p->Virtuals[c]; - }); + auto call = CreateCall(GetVirtual); call->setRet(0, result); call->setArg(0, regA[B]); call->setArg(1, asmjit::Imm(C)); cc.mov(regA[A], result); } +static void ValidateCall(DObject *o, VMFunction *f, int b) +{ + try + { + FScopeBarrier::ValidateCall(o->GetClass(), f, b - 1); + } + catch (...) + { + VMThrowException(std::current_exception()); + } +} + void JitCompiler::EmitSCOPE() { auto label = EmitThrowExceptionLabel(X_READ_NIL); @@ -76,21 +91,17 @@ void JitCompiler::EmitSCOPE() cc.mov(f, asmjit::imm_ptr(konsta[C].v)); typedef int(*FuncPtr)(DObject*, VMFunction*, int); - auto call = CreateCall([](DObject *o, VMFunction *f, int b) { - try - { - FScopeBarrier::ValidateCall(o->GetClass(), f, b - 1); - } - catch (...) - { - VMThrowException(std::current_exception()); - } - }); + auto call = CreateCall(ValidateCall); call->setArg(0, regA[A]); call->setArg(1, f); call->setArg(2, asmjit::Imm(B)); } +static void SetString(VMReturn* ret, FString* str) +{ + ret->SetString(*str); +} + void JitCompiler::EmitRET() { using namespace asmjit; @@ -179,9 +190,7 @@ void JitCompiler::EmitRET() auto ptr = newTempIntPtr(); cc.mov(ptr, ret); cc.add(ptr, (int)(retnum * sizeof(VMReturn))); - auto call = CreateCall([](VMReturn* ret, FString* str) -> void { - ret->SetString(*str); - }); + auto call = CreateCall(SetString); call->setArg(0, ptr); if (regtype & REGT_KONST) call->setArg(1, asmjit::imm_ptr(&konsts[regnum])); else call->setArg(1, regS[regnum]); @@ -254,35 +263,38 @@ void JitCompiler::EmitRETI() } } +static DObject* CreateNew(PClass *cls, int c) +{ + try + { + if (!cls->ConstructNative) + { + ThrowAbortException(X_OTHER, "Class %s requires native construction", cls->TypeName.GetChars()); + } + else if (cls->bAbstract) + { + ThrowAbortException(X_OTHER, "Cannot instantiate abstract class %s", cls->TypeName.GetChars()); + } + else if (cls->IsDescendantOf(NAME_Actor)) // Creating actors here must be outright prohibited + { + ThrowAbortException(X_OTHER, "Cannot create actors with 'new'"); + } + + // [ZZ] validate readonly and between scope construction + if (c) FScopeBarrier::ValidateNew(cls, c - 1); + return cls->CreateNew(); + } + catch (...) + { + VMThrowException(std::current_exception()); + return nullptr; + } +} + void JitCompiler::EmitNEW() { auto result = newResultIntPtr(); - auto call = CreateCall([](PClass *cls, int c) -> DObject* { - try - { - if (!cls->ConstructNative) - { - ThrowAbortException(X_OTHER, "Class %s requires native construction", cls->TypeName.GetChars()); - } - else if (cls->bAbstract) - { - ThrowAbortException(X_OTHER, "Cannot instantiate abstract class %s", cls->TypeName.GetChars()); - } - else if (cls->IsDescendantOf(NAME_Actor)) // Creating actors here must be outright prohibited - { - ThrowAbortException(X_OTHER, "Cannot create actors with 'new'"); - } - - // [ZZ] validate readonly and between scope construction - if (c) FScopeBarrier::ValidateNew(cls, c - 1); - return cls->CreateNew(); - } - catch (...) - { - VMThrowException(std::current_exception()); - return nullptr; - } - }); + auto call = CreateCall(CreateNew); call->setRet(0, result); call->setArg(0, regA[B]); call->setArg(1, asmjit::Imm(C)); @@ -290,6 +302,43 @@ void JitCompiler::EmitNEW() cc.mov(regA[A], result); } +static void ThrowNewK(PClass *cls, int c) +{ + try + { + if (!cls->ConstructNative) + { + ThrowAbortException(X_OTHER, "Class %s requires native construction", cls->TypeName.GetChars()); + } + else if (cls->bAbstract) + { + ThrowAbortException(X_OTHER, "Cannot instantiate abstract class %s", cls->TypeName.GetChars()); + } + else // if (cls->IsDescendantOf(NAME_Actor)) // Creating actors here must be outright prohibited + { + ThrowAbortException(X_OTHER, "Cannot create actors with 'new'"); + } + } + catch (...) + { + VMThrowException(std::current_exception()); + } +} + +static DObject *CreateNewK(PClass *cls, int c) +{ + try + { + if (c) FScopeBarrier::ValidateNew(cls, c - 1); + return cls->CreateNew(); + } + catch (...) + { + VMThrowException(std::current_exception()); + return nullptr; + } +} + void JitCompiler::EmitNEW_K() { PClass *cls = (PClass*)konsta[B].v; @@ -298,44 +347,13 @@ void JitCompiler::EmitNEW_K() if (!cls->ConstructNative || cls->bAbstract || cls->IsDescendantOf(NAME_Actor)) { - auto call = CreateCall([](PClass *cls, int c) { - try - { - if (!cls->ConstructNative) - { - ThrowAbortException(X_OTHER, "Class %s requires native construction", cls->TypeName.GetChars()); - } - else if (cls->bAbstract) - { - ThrowAbortException(X_OTHER, "Cannot instantiate abstract class %s", cls->TypeName.GetChars()); - } - else // if (cls->IsDescendantOf(NAME_Actor)) // Creating actors here must be outright prohibited - { - ThrowAbortException(X_OTHER, "Cannot create actors with 'new'"); - } - } - catch (...) - { - VMThrowException(std::current_exception()); - } - }); + auto call = CreateCall(ThrowNewK); call->setArg(0, regcls); } else { auto result = newResultIntPtr(); - auto call = CreateCall([](PClass *cls, int c) -> DObject* { - try - { - if (c) FScopeBarrier::ValidateNew(cls, c - 1); - return cls->CreateNew(); - } - catch (...) - { - VMThrowException(std::current_exception()); - return nullptr; - } - }); + auto call = CreateCall(CreateNewK); call->setRet(0, result); call->setArg(0, regcls); call->setArg(1, asmjit::Imm(C)); diff --git a/src/scripting/vm/jit_load.cpp b/src/scripting/vm/jit_load.cpp index 5b35a7d44..1c6061541 100644 --- a/src/scripting/vm/jit_load.cpp +++ b/src/scripting/vm/jit_load.cpp @@ -76,6 +76,11 @@ void JitCompiler::EmitLFP() cc.lea(regA[A], asmjit::x86::ptr(vmframe, offsetExtra)); } +static uint8_t *GetClassMeta(DObject *o) +{ + return o->GetClass()->Meta; +} + void JitCompiler::EmitMETA() { auto label = EmitThrowExceptionLabel(X_READ_NIL); @@ -83,12 +88,17 @@ void JitCompiler::EmitMETA() cc.je(label); auto result = newResultIntPtr(); - auto call = CreateCall([](DObject *o) { return o->GetClass()->Meta; }); + auto call = CreateCall(GetClassMeta); call->setRet(0, result); call->setArg(0, regA[B]); cc.mov(regA[A], result); } +static PClass *GetClass(DObject *o) +{ + return o->GetClass(); +} + void JitCompiler::EmitCLSS() { auto label = EmitThrowExceptionLabel(X_READ_NIL); @@ -96,7 +106,7 @@ void JitCompiler::EmitCLSS() cc.je(label); auto result = newResultIntPtr(); - auto call = CreateCall([](DObject *o) { return o->GetClass(); }); + auto call = CreateCall(GetClass); call->setRet(0, result); call->setArg(0, regA[B]); cc.mov(regA[A], result); @@ -211,6 +221,11 @@ void JitCompiler::EmitLS_R() call->setArg(1, ptr); } +static DObject *ReadBarrier(DObject *p) +{ + return GC::ReadBarrier(p); +} + void JitCompiler::EmitLO() { EmitNullPointerThrow(B, X_READ_NIL); @@ -219,7 +234,7 @@ void JitCompiler::EmitLO() cc.mov(ptr, asmjit::x86::ptr(regA[B], konstd[C])); auto result = newResultIntPtr(); - auto call = CreateCall([](DObject *p) { return GC::ReadBarrier(p); }); + auto call = CreateCall(ReadBarrier); call->setRet(0, result); call->setArg(0, ptr); cc.mov(regA[A], result); @@ -233,7 +248,7 @@ void JitCompiler::EmitLO_R() cc.mov(ptr, asmjit::x86::ptr(regA[B], regD[C])); auto result = newResultIntPtr(); - auto call = CreateCall([](DObject *p) { return GC::ReadBarrier(p); }); + auto call = CreateCall(ReadBarrier); call->setRet(0, result); call->setArg(0, ptr); cc.mov(regA[A], result); @@ -289,12 +304,17 @@ void JitCompiler::EmitLV3_R() cc.movsd(regF[A + 2], asmjit::x86::qword_ptr(tmp, 16)); } +static void SetString(FString *to, char **from) +{ + *to = *from; +} + void JitCompiler::EmitLCS() { EmitNullPointerThrow(B, X_READ_NIL); auto ptr = newTempIntPtr(); cc.lea(ptr, asmjit::x86::ptr(regA[B], konstd[C])); - auto call = CreateCall([](FString* to, char** from) { *to = *from; }); + auto call = CreateCall(SetString); call->setArg(0, regS[A]); call->setArg(1, ptr); } @@ -304,7 +324,7 @@ void JitCompiler::EmitLCS_R() EmitNullPointerThrow(B, X_READ_NIL); auto ptr = newTempIntPtr(); cc.lea(ptr, asmjit::x86::ptr(regA[B], regD[C])); - auto call = CreateCall([](FString* to, char** from) { *to = *from; }); + auto call = CreateCall(SetString); call->setArg(0, regS[A]); call->setArg(1, ptr); } diff --git a/src/scripting/vm/jit_math.cpp b/src/scripting/vm/jit_math.cpp index 7b557cfb3..48514945d 100644 --- a/src/scripting/vm/jit_math.cpp +++ b/src/scripting/vm/jit_math.cpp @@ -4,41 +4,49 @@ ///////////////////////////////////////////////////////////////////////////// // String instructions. +static void ConcatString(FString* to, FString* first, FString* second) +{ + *to = *first + *second; +} + void JitCompiler::EmitCONCAT() { auto rc = CheckRegS(C, A); - auto call = CreateCall([](FString* to, FString* first, FString* second) { - *to = *first + *second; - }); + auto call = CreateCall(ConcatString); call->setArg(0, regS[A]); call->setArg(1, regS[B]); call->setArg(2, rc); } +static int StringLength(FString* str) +{ + return static_cast(str->Len()); +} + void JitCompiler::EmitLENS() { auto result = newResultInt32(); - auto call = CreateCall([](FString* str) -> int { - return static_cast(str->Len()); - }); + auto call = CreateCall(StringLength); call->setRet(0, result); call->setArg(0, regS[B]); cc.mov(regD[A], result); } +static int StringCompareNoCase(FString* first, FString* second) +{ + return first->CompareNoCase(*second); +} + +static int StringCompare(FString* first, FString* second) +{ + return first->Compare(*second); +} + void JitCompiler::EmitCMPS() { EmitComparisonOpcode([&](bool check, asmjit::Label& fail, asmjit::Label& success) { - auto compareNoCaseLambda = [](FString* first, FString* second) -> int { - return first->CompareNoCase(*second); - }; - auto compareLambda = [](FString* first, FString* second) -> int { - return first->Compare(*second); - }; - auto call = static_cast(A & CMP_APPROX) ? - CreateCall(compareNoCaseLambda) : - CreateCall(compareLambda); + auto call = CreateCall(static_cast(A & CMP_APPROX) ? StringCompareNoCase : StringCompare); auto result = newResultInt32(); call->setRet(0, result); @@ -738,6 +746,11 @@ void JitCompiler::EmitDIVF_KR() cc.divsd(regF[A], rc); } +static double DoubleModF(double a, double b) +{ + return a - floor(a / b) * b; +} + void JitCompiler::EmitMODF_RR() { auto label = EmitThrowExceptionLabel(X_DIVISION_BY_ZERO); @@ -745,10 +758,7 @@ void JitCompiler::EmitMODF_RR() cc.je(label); auto result = newResultXmmSd(); - auto call = CreateCall([](double a, double b) -> double - { - return a - floor(a / b) * b; - }); + auto call = CreateCall(DoubleModF); call->setRet(0, result); call->setArg(0, regF[B]); call->setArg(1, regF[C]); @@ -770,9 +780,7 @@ void JitCompiler::EmitMODF_RK() cc.movsd(tmp, asmjit::x86::qword_ptr(tmpPtr)); auto result = newResultXmmSd(); - auto call = CreateCall([](double a, double b) -> double { - return a - floor(a / b) * b; - }); + auto call = CreateCall(DoubleModF); call->setRet(0, result); call->setArg(0, regF[B]); call->setArg(1, tmp); @@ -792,9 +800,7 @@ void JitCompiler::EmitMODF_KR() cc.movsd(tmp, x86::ptr(ToMemAddress(&konstf[B]))); auto result = newResultXmmSd(); - auto call = CreateCall([](double a, double b) -> double { - return a - floor(a / b) * b; - }); + auto call = CreateCall(DoubleModF); call->setRet(0, result); call->setArg(0, tmp); call->setArg(1, regF[C]); diff --git a/src/scripting/vm/jit_move.cpp b/src/scripting/vm/jit_move.cpp index 9b82f4411..fc70bf5d4 100644 --- a/src/scripting/vm/jit_move.cpp +++ b/src/scripting/vm/jit_move.cpp @@ -38,6 +38,23 @@ void JitCompiler::EmitMOVEV3() cc.movsd(regF[A + 2], regF[B + 2]); } +static void CastI2S(FString *a, int b) { a->Format("%d", b); } +static void CastU2S(FString *a, int b) { a->Format("%u", b); } +static void CastF2S(FString *a, double b) { a->Format("%.5f", b); } +static void CastV22S(FString *a, double b, double b1) { a->Format("(%.5f, %.5f)", b, b1); } +static void CastV32S(FString *a, double b, double b1, double b2) { a->Format("(%.5f, %.5f, %.5f)", b, b1, b2); } +static void CastP2S(FString *a, void *b) { if (b == nullptr) *a = "null"; else a->Format("%p", b); } +static int CastS2I(FString *b) { return (VM_SWORD)b->ToLong(); } +static double CastS2F(FString *b) { return b->ToDouble(); } +static int CastS2N(FString *b) { return b->Len() == 0 ? FName(NAME_None) : FName(*b); } +static void CastN2S(FString *a, int b) { FName name = FName(ENamedName(b)); *a = name.IsValidName() ? name.GetChars() : ""; } +static int CastS2Co(FString *b) { return V_GetColor(nullptr, *b); } +static void CastCo2S(FString *a, int b) { PalEntry c(b); a->Format("%02x %02x %02x", c.r, c.g, c.b); } +static int CastS2So(FString *b) { return FSoundID(*b); } +static void CastSo2S(FString *a, int b) { *a = S_sfx[b].name; } +static void CastSID2S(FString *a, unsigned int b) { *a = (b >= sprites.Size()) ? "TNT1" : sprites[b].name; } +static void CastTID2S(FString *a, int b) { auto tex = TexMan[*(FTextureID*)&b]; *a = (tex == nullptr) ? "(null)" : tex->Name.GetChars(); } + void JitCompiler::EmitCAST() { asmjit::X86Gp tmp, resultD; @@ -64,95 +81,95 @@ void JitCompiler::EmitCAST() cc.mov(regD[A], tmp.r32()); break; case CAST_I2S: - call = CreateCall([](FString *a, int b) { a->Format("%d", b); }); + call = CreateCall(CastI2S); call->setArg(0, regS[A]); call->setArg(1, regD[B]); break; case CAST_U2S: - call = CreateCall([](FString *a, int b) { a->Format("%u", b); }); + call = CreateCall(CastU2S); call->setArg(0, regS[A]); call->setArg(1, regD[B]); break; case CAST_F2S: - call = CreateCall([](FString *a, double b) { a->Format("%.5f", b); }); + call = CreateCall(CastF2S); call->setArg(0, regS[A]); call->setArg(1, regF[B]); break; case CAST_V22S: - call = CreateCall([](FString *a, double b, double b1) { a->Format("(%.5f, %.5f)", b, b1); }); + call = CreateCall(CastV22S); call->setArg(0, regS[A]); call->setArg(1, regF[B]); call->setArg(2, regF[B + 1]); break; case CAST_V32S: - call = CreateCall([](FString *a, double b, double b1, double b2) { a->Format("(%.5f, %.5f, %.5f)", b, b1, b2); }); + call = CreateCall(CastV32S); call->setArg(0, regS[A]); call->setArg(1, regF[B]); call->setArg(2, regF[B + 1]); call->setArg(3, regF[B + 2]); break; case CAST_P2S: - call = CreateCall([](FString *a, void *b) { if (b == nullptr) *a = "null"; else a->Format("%p", b); }); + call = CreateCall(CastP2S); call->setArg(0, regS[A]); call->setArg(1, regA[B]); break; case CAST_S2I: resultD = newResultInt32(); - call = CreateCall([](FString *b) -> int { return (VM_SWORD)b->ToLong(); }); + call = CreateCall(CastS2I); call->setRet(0, resultD); call->setArg(0, regS[B]); cc.mov(regD[A], resultD); break; case CAST_S2F: resultF = newResultXmmSd(); - call = CreateCall([](FString *b) -> double { return b->ToDouble(); }); + call = CreateCall(CastS2F); call->setRet(0, resultF); call->setArg(0, regS[B]); cc.movsd(regF[A], resultF); break; case CAST_S2N: resultD = newResultInt32(); - call = CreateCall([](FString *b) -> int { return b->Len() == 0 ? FName(NAME_None) : FName(*b); }); + call = CreateCall(CastS2N); 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() : ""; }); + call = CreateCall(CastN2S); call->setArg(0, regS[A]); call->setArg(1, regD[B]); break; case CAST_S2Co: resultD = newResultInt32(); - call = CreateCall([](FString *b) -> int { return V_GetColor(nullptr, *b); }); + call = CreateCall(CastS2Co); 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); }); + call = CreateCall(CastCo2S); call->setArg(0, regS[A]); call->setArg(1, regD[B]); break; case CAST_S2So: resultD = newResultInt32(); - call = CreateCall([](FString *b) -> int { return FSoundID(*b); }); + call = CreateCall(CastS2So); 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; }); + call = CreateCall(CastSo2S); call->setArg(0, regS[A]); call->setArg(1, regD[B]); break; case CAST_SID2S: - call = CreateCall([](FString *a, unsigned int b) { *a = (b >= sprites.Size()) ? "TNT1" : sprites[b].name; }); + call = CreateCall(CastSID2S); call->setArg(0, regS[A]); call->setArg(1, regD[B]); break; case CAST_TID2S: - call = CreateCall([](FString *a, int b) { auto tex = TexMan[*(FTextureID*)&b]; *a = (tex == nullptr) ? "(null)" : tex->Name.GetChars(); }); + call = CreateCall(CastTID2S); call->setArg(0, regS[A]); call->setArg(1, regD[B]); break; @@ -161,6 +178,8 @@ void JitCompiler::EmitCAST() } } +static int CastB_S(FString *s) { return s->Len() > 0; } + void JitCompiler::EmitCASTB() { if (C == CASTB_I) @@ -189,19 +208,22 @@ void JitCompiler::EmitCASTB() else { auto result = newResultInt32(); - auto call = CreateCall([](FString *s) -> int { return s->Len() > 0; }); + auto call = CreateCall(CastB_S); call->setRet(0, result); call->setArg(0, regS[B]); cc.mov(regD[A], result); } } +static DObject *DynCast(DObject *obj, PClass *cls) +{ + return (obj && obj->IsKindOf(cls)) ? obj : nullptr; +} + void JitCompiler::EmitDYNCAST_R() { auto result = newResultIntPtr(); - auto call = CreateCall([](DObject *obj, PClass *cls) -> DObject* { - return (obj && obj->IsKindOf(cls)) ? obj : nullptr; - }); + auto call = CreateCall(DynCast); call->setRet(0, result); call->setArg(0, regA[B]); call->setArg(1, regA[C]); @@ -213,21 +235,22 @@ void JitCompiler::EmitDYNCAST_K() auto result = newResultIntPtr(); auto c = newTempIntPtr(); cc.mov(c, asmjit::imm_ptr(konsta[C].o)); - auto call = CreateCall([](DObject *obj, PClass *cls) -> DObject* { - return (obj && obj->IsKindOf(cls)) ? obj : nullptr; - }); + auto call = CreateCall(DynCast); call->setRet(0, result); call->setArg(0, regA[B]); call->setArg(1, c); cc.mov(regA[A], result); } +static PClass *DynCastC(PClass *cls1, PClass *cls2) +{ + return (cls1 && cls1->IsDescendantOf(cls2)) ? cls1 : nullptr; +} + void JitCompiler::EmitDYNCASTC_R() { auto result = newResultIntPtr(); - auto call = CreateCall([](PClass *cls1, PClass *cls2) -> PClass* { - return (cls1 && cls1->IsDescendantOf(cls2)) ? cls1 : nullptr; - }); + auto call = CreateCall(DynCastC); call->setRet(0, result); call->setArg(0, regA[B]); call->setArg(1, regA[C]); @@ -241,9 +264,7 @@ void JitCompiler::EmitDYNCASTC_K() auto c = newTempIntPtr(); 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; - }); + auto call = CreateCall(DynCastC); call->setRet(0, result); call->setArg(0, regA[B]); call->setArg(1, c);