- remove the need to do any VARF_Native runtime checks by making native functions use the same calling convention as the script version
This commit is contained in:
parent
b6bc06e568
commit
0120ea190c
8 changed files with 68 additions and 157 deletions
|
|
@ -106,7 +106,6 @@ void JitCompiler::EmitPARAM()
|
|||
I_FatalError("Unknown REGT value passed to EmitPARAM\n");
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void JitCompiler::EmitPARAMI()
|
||||
|
|
@ -126,33 +125,29 @@ void JitCompiler::EmitRESULT()
|
|||
|
||||
void JitCompiler::EmitCALL()
|
||||
{
|
||||
EmitDoCall(regA[A], CallType::Unknown);
|
||||
EmitDoCall(regA[A]);
|
||||
}
|
||||
|
||||
void JitCompiler::EmitCALL_K()
|
||||
{
|
||||
VMFunction *func = (VMFunction*)konsta[A].o;
|
||||
|
||||
auto ptr = newTempIntPtr();
|
||||
cc.mov(ptr, asmjit::imm_ptr(func));
|
||||
EmitDoCall(ptr, (func->VarFlags & VARF_Native) ? CallType::Native : CallType::Script);
|
||||
cc.mov(ptr, asmjit::imm_ptr(konsta[A].o));
|
||||
EmitDoCall(ptr);
|
||||
}
|
||||
|
||||
void JitCompiler::EmitTAIL()
|
||||
{
|
||||
EmitDoTail(regA[A], CallType::Unknown);
|
||||
EmitDoTail(regA[A]);
|
||||
}
|
||||
|
||||
void JitCompiler::EmitTAIL_K()
|
||||
{
|
||||
VMFunction *func = (VMFunction*)konsta[A].o;
|
||||
|
||||
auto ptr = newTempIntPtr();
|
||||
cc.mov(ptr, asmjit::imm_ptr(func));
|
||||
EmitDoTail(ptr, (func->VarFlags & VARF_Native) ? CallType::Native : CallType::Script);
|
||||
cc.mov(ptr, asmjit::imm_ptr(konsta[A].o));
|
||||
EmitDoTail(ptr);
|
||||
}
|
||||
|
||||
void JitCompiler::EmitDoCall(asmjit::X86Gp vmfunc, CallType calltype)
|
||||
void JitCompiler::EmitDoCall(asmjit::X86Gp vmfunc)
|
||||
{
|
||||
using namespace asmjit;
|
||||
|
||||
|
|
@ -173,28 +168,7 @@ void JitCompiler::EmitDoCall(asmjit::X86Gp vmfunc, CallType calltype)
|
|||
paramsptr = params;
|
||||
}
|
||||
|
||||
if (calltype == CallType::Script)
|
||||
{
|
||||
EmitScriptCall(vmfunc, paramsptr);
|
||||
}
|
||||
else if (calltype == CallType::Native)
|
||||
{
|
||||
EmitNativeCall(vmfunc, paramsptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto nativecall = cc.newLabel();
|
||||
auto endcall = cc.newLabel();
|
||||
auto varflags = newTempInt32();
|
||||
cc.mov(varflags, x86::dword_ptr(vmfunc, offsetof(VMFunction, VarFlags)));
|
||||
cc.test(varflags, (int)VARF_Native);
|
||||
cc.jnz(nativecall);
|
||||
EmitScriptCall(vmfunc, paramsptr);
|
||||
cc.jmp(endcall);
|
||||
cc.bind(nativecall);
|
||||
EmitNativeCall(vmfunc, paramsptr);
|
||||
cc.bind(endcall);
|
||||
}
|
||||
EmitScriptCall(vmfunc, paramsptr);
|
||||
|
||||
LoadInOuts(B);
|
||||
LoadReturns(pc + 1, C);
|
||||
|
|
@ -207,14 +181,6 @@ void JitCompiler::EmitScriptCall(asmjit::X86Gp vmfunc, asmjit::X86Gp paramsptr)
|
|||
{
|
||||
using namespace asmjit;
|
||||
|
||||
// VMCalls[0]++
|
||||
auto vmcallsptr = newTempIntPtr();
|
||||
auto vmcalls = newTempInt32();
|
||||
cc.mov(vmcallsptr, imm_ptr(VMCalls));
|
||||
cc.mov(vmcalls, x86::dword_ptr(vmcallsptr));
|
||||
cc.add(vmcalls, (int)1);
|
||||
cc.mov(x86::dword_ptr(vmcallsptr), vmcalls);
|
||||
|
||||
auto scriptcall = newTempIntPtr();
|
||||
cc.mov(scriptcall, x86::ptr(vmfunc, offsetof(VMScriptFunction, ScriptCall)));
|
||||
|
||||
|
|
@ -228,20 +194,7 @@ void JitCompiler::EmitScriptCall(asmjit::X86Gp vmfunc, asmjit::X86Gp paramsptr)
|
|||
call->setArg(4, Imm(C));
|
||||
}
|
||||
|
||||
void JitCompiler::EmitNativeCall(asmjit::X86Gp vmfunc, asmjit::X86Gp paramsptr)
|
||||
{
|
||||
using namespace asmjit;
|
||||
auto result = newResultInt32();
|
||||
auto call = CreateCall<int, VMFunction*, int, int, VMValue*, VMReturn*>(&JitCompiler::DoNativeCall);
|
||||
call->setRet(0, result);
|
||||
call->setArg(0, vmfunc);
|
||||
call->setArg(1, Imm(B));
|
||||
call->setArg(2, Imm(C));
|
||||
call->setArg(3, paramsptr);
|
||||
call->setArg(4, callReturns);
|
||||
}
|
||||
|
||||
void JitCompiler::EmitDoTail(asmjit::X86Gp vmfunc, CallType calltype)
|
||||
void JitCompiler::EmitDoTail(asmjit::X86Gp vmfunc)
|
||||
{
|
||||
// Whereas the CALL instruction uses its third operand to specify how many return values
|
||||
// it expects, TAIL ignores its third operand and uses whatever was passed to this Exec call.
|
||||
|
|
@ -268,28 +221,7 @@ void JitCompiler::EmitDoTail(asmjit::X86Gp vmfunc, CallType calltype)
|
|||
|
||||
auto result = newResultInt32();
|
||||
|
||||
if (calltype == CallType::Script)
|
||||
{
|
||||
EmitScriptTailCall(vmfunc, result, paramsptr);
|
||||
}
|
||||
else if (calltype == CallType::Native)
|
||||
{
|
||||
EmitNativeTailCall(vmfunc, result, paramsptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto nativecall = cc.newLabel();
|
||||
auto endcall = cc.newLabel();
|
||||
auto varflags = newTempInt32();
|
||||
cc.mov(varflags, x86::dword_ptr(vmfunc, offsetof(VMFunction, VarFlags)));
|
||||
cc.test(varflags, (int)VARF_Native);
|
||||
cc.jnz(nativecall);
|
||||
EmitScriptTailCall(vmfunc, result, paramsptr);
|
||||
cc.jmp(endcall);
|
||||
cc.bind(nativecall);
|
||||
EmitNativeTailCall(vmfunc, result, paramsptr);
|
||||
cc.bind(endcall);
|
||||
}
|
||||
EmitScriptTailCall(vmfunc, result, paramsptr);
|
||||
|
||||
EmitPopFrame();
|
||||
cc.ret(result);
|
||||
|
|
@ -302,14 +234,6 @@ void JitCompiler::EmitScriptTailCall(asmjit::X86Gp vmfunc, asmjit::X86Gp result,
|
|||
{
|
||||
using namespace asmjit;
|
||||
|
||||
// VMCalls[0]++
|
||||
auto vmcallsptr = newTempIntPtr();
|
||||
auto vmcalls = newTempInt32();
|
||||
cc.mov(vmcallsptr, imm_ptr(VMCalls));
|
||||
cc.mov(vmcalls, x86::dword_ptr(vmcallsptr));
|
||||
cc.add(vmcalls, (int)1);
|
||||
cc.mov(x86::dword_ptr(vmcallsptr), vmcalls);
|
||||
|
||||
auto scriptcall = newTempIntPtr();
|
||||
cc.mov(scriptcall, x86::ptr(vmfunc, offsetof(VMScriptFunction, ScriptCall)));
|
||||
|
||||
|
|
@ -322,19 +246,6 @@ void JitCompiler::EmitScriptTailCall(asmjit::X86Gp vmfunc, asmjit::X86Gp result,
|
|||
call->setArg(4, numret);
|
||||
}
|
||||
|
||||
void JitCompiler::EmitNativeTailCall(asmjit::X86Gp vmfunc, asmjit::X86Gp result, asmjit::X86Gp paramsptr)
|
||||
{
|
||||
using namespace asmjit;
|
||||
|
||||
auto call = CreateCall<int, VMFunction*, int, int, VMValue*, VMReturn*>(&JitCompiler::DoNativeCall);
|
||||
call->setRet(0, result);
|
||||
call->setArg(0, vmfunc);
|
||||
call->setArg(1, Imm(B));
|
||||
call->setArg(2, numret);
|
||||
call->setArg(3, paramsptr);
|
||||
call->setArg(4, ret);
|
||||
}
|
||||
|
||||
void JitCompiler::StoreInOuts(int b)
|
||||
{
|
||||
using namespace asmjit;
|
||||
|
|
@ -497,29 +408,3 @@ void JitCompiler::FillReturns(const VMOP *retval, int numret)
|
|||
cc.mov(x86::byte_ptr(callReturns, i * sizeof(VMReturn) + offsetof(VMReturn, RegType)), type);
|
||||
}
|
||||
}
|
||||
|
||||
int JitCompiler::DoNativeCall(VMFunction *call, int b, int c, VMValue *param, VMReturn *returns)
|
||||
{
|
||||
try
|
||||
{
|
||||
assert((call->VarFlags & VARF_Native) && "DoNativeCall must only be called for native functions");
|
||||
|
||||
VMCycles[0].Unclock();
|
||||
int numret = static_cast<VMNativeFunction *>(call)->NativeCall(param, call->DefaultArgs, b, returns, c);
|
||||
VMCycles[0].Clock();
|
||||
|
||||
return numret;
|
||||
}
|
||||
catch (CVMAbortException &err)
|
||||
{
|
||||
err.MaybePrintMessage();
|
||||
err.stacktrace.AppendFormat("Called from %s\n", call->PrintableName.GetChars());
|
||||
VMThrowException(std::current_exception());
|
||||
return 0;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
VMThrowException(std::current_exception());
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue