mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-11 07:11:54 +00:00
- switch to using setjmp/longjmp for exception handling
This commit is contained in:
parent
2b05e75656
commit
884e185db0
6 changed files with 102 additions and 125 deletions
|
@ -152,18 +152,18 @@ void JitCompiler::Setup()
|
||||||
funcname.Format("Function: %s", sfunc->PrintableName.GetChars());
|
funcname.Format("Function: %s", sfunc->PrintableName.GetChars());
|
||||||
cc.comment(funcname.GetChars(), funcname.Len());
|
cc.comment(funcname.GetChars(), funcname.Len());
|
||||||
|
|
||||||
|
auto unusedFunc = cc.newIntPtr("func"); // VMFunction*
|
||||||
args = cc.newIntPtr("args"); // VMValue *params
|
args = cc.newIntPtr("args"); // VMValue *params
|
||||||
numargs = cc.newInt32("numargs"); // int numargs
|
numargs = cc.newInt32("numargs"); // int numargs
|
||||||
ret = cc.newIntPtr("ret"); // VMReturn *ret
|
ret = cc.newIntPtr("ret"); // VMReturn *ret
|
||||||
numret = cc.newInt32("numret"); // int numret
|
numret = cc.newInt32("numret"); // int numret
|
||||||
exceptInfo = cc.newIntPtr("exceptinfo"); // JitExceptionInfo *exceptInfo
|
|
||||||
|
|
||||||
cc.addFunc(FuncSignature5<int, void *, int, void *, int, void *>());
|
cc.addFunc(FuncSignature5<int, VMFunction *, void *, int, void *, int>());
|
||||||
cc.setArg(0, args);
|
cc.setArg(0, unusedFunc);
|
||||||
cc.setArg(1, numargs);
|
cc.setArg(1, args);
|
||||||
cc.setArg(2, ret);
|
cc.setArg(2, numargs);
|
||||||
cc.setArg(3, numret);
|
cc.setArg(3, ret);
|
||||||
cc.setArg(4, exceptInfo);
|
cc.setArg(4, numret);
|
||||||
|
|
||||||
auto stackalloc = cc.newStack(sizeof(VMReturn) * MAX_RETURNS, alignof(VMReturn));
|
auto stackalloc = cc.newStack(sizeof(VMReturn) * MAX_RETURNS, alignof(VMReturn));
|
||||||
callReturns = cc.newIntPtr("callReturns");
|
callReturns = cc.newIntPtr("callReturns");
|
||||||
|
@ -297,22 +297,19 @@ void JitCompiler::Setup()
|
||||||
cc.mov(x86::word_ptr(vmframe, offsetof(VMFrame, MaxParam)), sfunc->MaxParam);
|
cc.mov(x86::word_ptr(vmframe, offsetof(VMFrame, MaxParam)), sfunc->MaxParam);
|
||||||
cc.mov(x86::word_ptr(vmframe, offsetof(VMFrame, NumParam)), 0);
|
cc.mov(x86::word_ptr(vmframe, offsetof(VMFrame, NumParam)), 0);
|
||||||
|
|
||||||
auto fillParams = CreateCall<void, VMFrame *, VMValue *, int, JitExceptionInfo *>([](VMFrame *newf, VMValue *args, int numargs, JitExceptionInfo *exceptinfo) {
|
auto fillParams = CreateCall<void, VMFrame *, VMValue *, int>([](VMFrame *newf, VMValue *args, int numargs) {
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
VMFillParams(args, newf, numargs);
|
VMFillParams(args, newf, numargs);
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
exceptinfo->reason = X_OTHER;
|
VMThrowException(std::current_exception());
|
||||||
exceptinfo->cppException = std::current_exception();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
fillParams->setArg(0, vmframe);
|
fillParams->setArg(0, vmframe);
|
||||||
fillParams->setArg(1, args);
|
fillParams->setArg(1, args);
|
||||||
fillParams->setArg(2, numargs);
|
fillParams->setArg(2, numargs);
|
||||||
fillParams->setArg(3, exceptInfo);
|
|
||||||
EmitCheckForException();
|
|
||||||
|
|
||||||
for (int i = 0; i < sfunc->NumRegD; i++)
|
for (int i = 0; i < sfunc->NumRegD; i++)
|
||||||
cc.mov(regD[i], x86::dword_ptr(frameD, i * sizeof(int32_t)));
|
cc.mov(regD[i], x86::dword_ptr(frameD, i * sizeof(int32_t)));
|
||||||
|
@ -331,18 +328,18 @@ void JitCompiler::Setup()
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
stack = cc.newIntPtr("stack");
|
stack = cc.newIntPtr("stack");
|
||||||
auto allocFrame = CreateCall<VMFrameStack *, VMScriptFunction *, VMValue *, int, JitExceptionInfo *>([](VMScriptFunction *func, VMValue *args, int numargs, JitExceptionInfo *exceptinfo) -> VMFrameStack* {
|
auto allocFrame = CreateCall<VMFrameStack *, VMScriptFunction *, VMValue *, int>([](VMScriptFunction *func, VMValue *args, int numargs) -> VMFrameStack* {
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
VMFrameStack *stack = &GlobalVMStack;
|
VMFrameStack *stack = &GlobalVMStack;
|
||||||
VMFrame *newf = stack->AllocFrame(func);
|
VMFrame *newf = stack->AllocFrame(func);
|
||||||
|
CurrentJitExceptInfo->vmframes++;
|
||||||
VMFillParams(args, newf, numargs);
|
VMFillParams(args, newf, numargs);
|
||||||
return stack;
|
return stack;
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
exceptinfo->reason = X_OTHER;
|
VMThrowException(std::current_exception());
|
||||||
exceptinfo->cppException = std::current_exception();
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -350,8 +347,6 @@ void JitCompiler::Setup()
|
||||||
allocFrame->setArg(0, imm_ptr(sfunc));
|
allocFrame->setArg(0, imm_ptr(sfunc));
|
||||||
allocFrame->setArg(1, args);
|
allocFrame->setArg(1, args);
|
||||||
allocFrame->setArg(2, numargs);
|
allocFrame->setArg(2, numargs);
|
||||||
allocFrame->setArg(3, exceptInfo);
|
|
||||||
EmitCheckForException();
|
|
||||||
|
|
||||||
cc.mov(vmframe, x86::ptr(stack)); // stack->Blocks
|
cc.mov(vmframe, x86::ptr(stack)); // stack->Blocks
|
||||||
cc.mov(vmframe, x86::ptr(vmframe, VMFrameStack::OffsetLastFrame())); // Blocks->LastFrame
|
cc.mov(vmframe, x86::ptr(vmframe, VMFrameStack::OffsetLastFrame())); // Blocks->LastFrame
|
||||||
|
@ -384,19 +379,18 @@ void JitCompiler::EmitPopFrame()
|
||||||
{
|
{
|
||||||
if (sfunc->SpecialInits.Size() != 0 || sfunc->NumRegS != 0)
|
if (sfunc->SpecialInits.Size() != 0 || sfunc->NumRegS != 0)
|
||||||
{
|
{
|
||||||
auto popFrame = CreateCall<void, VMFrameStack *, JitExceptionInfo *>([](VMFrameStack *stack, JitExceptionInfo *exceptinfo) {
|
auto popFrame = CreateCall<void, VMFrameStack *>([](VMFrameStack *stack) {
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
stack->PopFrame();
|
stack->PopFrame();
|
||||||
|
CurrentJitExceptInfo->vmframes--;
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
exceptinfo->reason = X_OTHER;
|
VMThrowException(std::current_exception());
|
||||||
exceptinfo->cppException = std::current_exception();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
popFrame->setArg(0, stack);
|
popFrame->setArg(0, stack);
|
||||||
popFrame->setArg(1, exceptInfo);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -411,53 +405,25 @@ void JitCompiler::EmitNullPointerThrow(int index, EVMAbortException reason)
|
||||||
|
|
||||||
void JitCompiler::EmitThrowException(EVMAbortException reason)
|
void JitCompiler::EmitThrowException(EVMAbortException reason)
|
||||||
{
|
{
|
||||||
using namespace asmjit;
|
auto call = CreateCall<void, VMScriptFunction *, VMOP *, int>([](VMScriptFunction *func, VMOP *line, int r) {
|
||||||
|
try
|
||||||
// Update JitExceptionInfo struct
|
{
|
||||||
cc.mov(x86::dword_ptr(exceptInfo, 0 * 4), (int32_t)reason);
|
ThrowAbortException(func, line, (EVMAbortException)r, nullptr);
|
||||||
if (cc.is64Bit())
|
}
|
||||||
cc.mov(x86::qword_ptr(exceptInfo, 4 * 4), imm_ptr(pc));
|
catch (...)
|
||||||
else
|
{
|
||||||
cc.mov(x86::dword_ptr(exceptInfo, 4 * 4), imm_ptr(pc));
|
VMThrowException(std::current_exception());
|
||||||
|
}
|
||||||
// Return from function
|
});
|
||||||
EmitPopFrame();
|
call->setArg(0, asmjit::imm_ptr(sfunc));
|
||||||
X86Gp vReg = newTempInt32();
|
call->setArg(1, asmjit::imm_ptr(pc));
|
||||||
cc.mov(vReg, 0);
|
call->setArg(2, asmjit::imm(reason));
|
||||||
cc.ret(vReg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitCompiler::EmitThrowException(EVMAbortException reason, asmjit::X86Gp arg1)
|
void JitCompiler::EmitThrowException(EVMAbortException reason, asmjit::X86Gp arg1)
|
||||||
{
|
{
|
||||||
using namespace asmjit;
|
// To do: fix throw message and use arg1
|
||||||
|
EmitThrowException(reason);
|
||||||
// Update JitExceptionInfo struct
|
|
||||||
cc.mov(x86::dword_ptr(exceptInfo, 0 * 4), (int32_t)reason);
|
|
||||||
cc.mov(x86::dword_ptr(exceptInfo, 1 * 4), arg1);
|
|
||||||
if (cc.is64Bit())
|
|
||||||
cc.mov(x86::qword_ptr(exceptInfo, 4 * 4), imm_ptr(pc));
|
|
||||||
else
|
|
||||||
cc.mov(x86::dword_ptr(exceptInfo, 4 * 4), imm_ptr(pc));
|
|
||||||
|
|
||||||
// Return from function
|
|
||||||
EmitPopFrame();
|
|
||||||
X86Gp vReg = newTempInt32();
|
|
||||||
cc.mov(vReg, 0);
|
|
||||||
cc.ret(vReg);
|
|
||||||
}
|
|
||||||
|
|
||||||
void JitCompiler::EmitCheckForException()
|
|
||||||
{
|
|
||||||
auto noexception = cc.newLabel();
|
|
||||||
auto exceptResult = newTempInt32();
|
|
||||||
cc.mov(exceptResult, asmjit::x86::dword_ptr(exceptInfo, 0 * 4));
|
|
||||||
cc.cmp(exceptResult, (int)-1);
|
|
||||||
cc.je(noexception);
|
|
||||||
EmitPopFrame();
|
|
||||||
asmjit::X86Gp vReg = newTempInt32();
|
|
||||||
cc.mov(vReg, 0);
|
|
||||||
cc.ret(vReg);
|
|
||||||
cc.bind(noexception);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
asmjit::X86Gp JitCompiler::CheckRegD(int r0, int r1)
|
asmjit::X86Gp JitCompiler::CheckRegD(int r0, int r1)
|
||||||
|
|
|
@ -170,16 +170,13 @@ void JitCompiler::EmitDoCall(asmjit::X86Gp ptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
auto result = newResultInt32();
|
auto result = newResultInt32();
|
||||||
auto call = CreateCall<int, VMFunction*, int, int, VMValue*, VMReturn*, JitExceptionInfo*>(&JitCompiler::DoCall);
|
auto call = CreateCall<int, VMFunction*, int, int, VMValue*, VMReturn*>(&JitCompiler::DoCall);
|
||||||
call->setRet(0, result);
|
call->setRet(0, result);
|
||||||
call->setArg(0, ptr);
|
call->setArg(0, ptr);
|
||||||
call->setArg(1, Imm(B));
|
call->setArg(1, Imm(B));
|
||||||
call->setArg(2, Imm(C));
|
call->setArg(2, Imm(C));
|
||||||
call->setArg(3, paramsptr);
|
call->setArg(3, paramsptr);
|
||||||
call->setArg(4, callReturns);
|
call->setArg(4, callReturns);
|
||||||
call->setArg(5, exceptInfo);
|
|
||||||
|
|
||||||
EmitCheckForException();
|
|
||||||
|
|
||||||
LoadInOuts(B);
|
LoadInOuts(B);
|
||||||
LoadReturns(pc + 1, C);
|
LoadReturns(pc + 1, C);
|
||||||
|
@ -214,14 +211,13 @@ void JitCompiler::EmitDoTail(asmjit::X86Gp ptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
auto result = newResultInt32();
|
auto result = newResultInt32();
|
||||||
auto call = CreateCall<int, VMFunction*, int, int, VMValue*, VMReturn*, JitExceptionInfo*>(&JitCompiler::DoCall);
|
auto call = CreateCall<int, VMFunction*, int, int, VMValue*, VMReturn*>(&JitCompiler::DoCall);
|
||||||
call->setRet(0, result);
|
call->setRet(0, result);
|
||||||
call->setArg(0, ptr);
|
call->setArg(0, ptr);
|
||||||
call->setArg(1, Imm(B));
|
call->setArg(1, Imm(B));
|
||||||
call->setArg(2, numret);
|
call->setArg(2, numret);
|
||||||
call->setArg(3, paramsptr);
|
call->setArg(3, paramsptr);
|
||||||
call->setArg(4, ret);
|
call->setArg(4, ret);
|
||||||
call->setArg(5, exceptInfo);
|
|
||||||
|
|
||||||
EmitPopFrame();
|
EmitPopFrame();
|
||||||
cc.ret(result);
|
cc.ret(result);
|
||||||
|
@ -393,7 +389,7 @@ void JitCompiler::FillReturns(const VMOP *retval, int numret)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int JitCompiler::DoCall(VMFunction *call, int b, int c, VMValue *param, VMReturn *returns, JitExceptionInfo *exceptinfo)
|
int JitCompiler::DoCall(VMFunction *call, int b, int c, VMValue *param, VMReturn *returns)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -424,8 +420,7 @@ int JitCompiler::DoCall(VMFunction *call, int b, int c, VMValue *param, VMReturn
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
exceptinfo->reason = X_OTHER;
|
VMThrowException(std::current_exception());
|
||||||
exceptinfo->cppException = std::current_exception();
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,23 +80,19 @@ void JitCompiler::EmitSCOPE()
|
||||||
cc.mov(f, asmjit::imm_ptr(konsta[C].v));
|
cc.mov(f, asmjit::imm_ptr(konsta[C].v));
|
||||||
|
|
||||||
typedef int(*FuncPtr)(DObject*, VMFunction*, int);
|
typedef int(*FuncPtr)(DObject*, VMFunction*, int);
|
||||||
auto call = CreateCall<void, DObject*, VMFunction*, int, JitExceptionInfo *>([](DObject *o, VMFunction *f, int b, JitExceptionInfo *exceptinfo) {
|
auto call = CreateCall<void, DObject*, VMFunction*, int>([](DObject *o, VMFunction *f, int b) {
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
FScopeBarrier::ValidateCall(o->GetClass(), f, b - 1);
|
FScopeBarrier::ValidateCall(o->GetClass(), f, b - 1);
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
exceptinfo->reason = X_OTHER;
|
VMThrowException(std::current_exception());
|
||||||
exceptinfo->cppException = std::current_exception();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
call->setArg(0, regA[A]);
|
call->setArg(0, regA[A]);
|
||||||
call->setArg(1, f);
|
call->setArg(1, f);
|
||||||
call->setArg(2, asmjit::Imm(B));
|
call->setArg(2, asmjit::Imm(B));
|
||||||
call->setArg(3, exceptInfo);
|
|
||||||
|
|
||||||
EmitCheckForException();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitCompiler::EmitRET()
|
void JitCompiler::EmitRET()
|
||||||
|
@ -265,7 +261,7 @@ void JitCompiler::EmitRETI()
|
||||||
void JitCompiler::EmitNEW()
|
void JitCompiler::EmitNEW()
|
||||||
{
|
{
|
||||||
auto result = newResultIntPtr();
|
auto result = newResultIntPtr();
|
||||||
auto call = CreateCall<DObject*, PClass*, int, JitExceptionInfo *>([](PClass *cls, int c, JitExceptionInfo *exceptinfo) -> DObject* {
|
auto call = CreateCall<DObject*, PClass*, int>([](PClass *cls, int c) -> DObject* {
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (!cls->ConstructNative)
|
if (!cls->ConstructNative)
|
||||||
|
@ -287,17 +283,13 @@ void JitCompiler::EmitNEW()
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
exceptinfo->reason = X_OTHER;
|
VMThrowException(std::current_exception());
|
||||||
exceptinfo->cppException = std::current_exception();
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
call->setRet(0, result);
|
call->setRet(0, result);
|
||||||
call->setArg(0, regA[B]);
|
call->setArg(0, regA[B]);
|
||||||
call->setArg(1, asmjit::Imm(C));
|
call->setArg(1, asmjit::Imm(C));
|
||||||
call->setArg(2, exceptInfo);
|
|
||||||
|
|
||||||
EmitCheckForException();
|
|
||||||
|
|
||||||
cc.mov(regA[A], result);
|
cc.mov(regA[A], result);
|
||||||
}
|
}
|
||||||
|
@ -322,7 +314,7 @@ void JitCompiler::EmitNEW_K()
|
||||||
auto result = newResultIntPtr();
|
auto result = newResultIntPtr();
|
||||||
auto regcls = newTempIntPtr();
|
auto regcls = newTempIntPtr();
|
||||||
cc.mov(regcls, asmjit::imm_ptr(konsta[B].v));
|
cc.mov(regcls, asmjit::imm_ptr(konsta[B].v));
|
||||||
auto call = CreateCall<DObject*, PClass*, int, JitExceptionInfo *>([](PClass *cls, int c, JitExceptionInfo *exceptinfo) -> DObject* {
|
auto call = CreateCall<DObject*, PClass*, int>([](PClass *cls, int c) -> DObject* {
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (c) FScopeBarrier::ValidateNew(cls, c - 1);
|
if (c) FScopeBarrier::ValidateNew(cls, c - 1);
|
||||||
|
@ -330,17 +322,13 @@ void JitCompiler::EmitNEW_K()
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
exceptinfo->reason = X_OTHER;
|
VMThrowException(std::current_exception());
|
||||||
exceptinfo->cppException = std::current_exception();
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
call->setRet(0, result);
|
call->setRet(0, result);
|
||||||
call->setArg(0, regcls);
|
call->setArg(0, regcls);
|
||||||
call->setArg(1, asmjit::Imm(C));
|
call->setArg(1, asmjit::Imm(C));
|
||||||
call->setArg(2, exceptInfo);
|
|
||||||
|
|
||||||
EmitCheckForException();
|
|
||||||
|
|
||||||
cc.mov(regA[A], result);
|
cc.mov(regA[A], result);
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,7 @@ private:
|
||||||
void LoadReturns(const VMOP *retval, int numret);
|
void LoadReturns(const VMOP *retval, int numret);
|
||||||
void FillReturns(const VMOP *retval, int numret);
|
void FillReturns(const VMOP *retval, int numret);
|
||||||
void LoadCallResult(const VMOP &opdata, bool addrof);
|
void LoadCallResult(const VMOP &opdata, bool addrof);
|
||||||
static int DoCall(VMFunction *call, int b, int c, VMValue *param, VMReturn *returns, JitExceptionInfo *exceptinfo);
|
static int DoCall(VMFunction *call, int b, int c, VMValue *param, VMReturn *returns);
|
||||||
|
|
||||||
template <typename Func>
|
template <typename Func>
|
||||||
void EmitComparisonOpcode(Func jmpFunc)
|
void EmitComparisonOpcode(Func jmpFunc)
|
||||||
|
@ -131,7 +131,6 @@ private:
|
||||||
void EmitNullPointerThrow(int index, EVMAbortException reason);
|
void EmitNullPointerThrow(int index, EVMAbortException reason);
|
||||||
void EmitThrowException(EVMAbortException reason);
|
void EmitThrowException(EVMAbortException reason);
|
||||||
void EmitThrowException(EVMAbortException reason, asmjit::X86Gp arg1);
|
void EmitThrowException(EVMAbortException reason, asmjit::X86Gp arg1);
|
||||||
void EmitCheckForException();
|
|
||||||
|
|
||||||
asmjit::X86Gp CheckRegD(int r0, int r1);
|
asmjit::X86Gp CheckRegD(int r0, int r1);
|
||||||
asmjit::X86Xmm CheckRegF(int r0, int r1);
|
asmjit::X86Xmm CheckRegF(int r0, int r1);
|
||||||
|
@ -147,7 +146,6 @@ private:
|
||||||
asmjit::X86Gp numargs;
|
asmjit::X86Gp numargs;
|
||||||
asmjit::X86Gp ret;
|
asmjit::X86Gp ret;
|
||||||
asmjit::X86Gp numret;
|
asmjit::X86Gp numret;
|
||||||
asmjit::X86Gp exceptInfo;
|
|
||||||
asmjit::X86Gp stack;
|
asmjit::X86Gp stack;
|
||||||
|
|
||||||
int offsetExtra;
|
int offsetExtra;
|
||||||
|
|
|
@ -78,10 +78,10 @@ VMScriptFunction::VMScriptFunction(FName name)
|
||||||
|
|
||||||
VMScriptFunction::~VMScriptFunction()
|
VMScriptFunction::~VMScriptFunction()
|
||||||
{
|
{
|
||||||
if (JitFunc)
|
if (FunctionJitted)
|
||||||
{
|
{
|
||||||
JitCleanUp(this);
|
JitCleanUp(this);
|
||||||
JitFunc = nullptr;
|
FunctionJitted = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Code != NULL)
|
if (Code != NULL)
|
||||||
|
@ -215,30 +215,15 @@ int VMScriptFunction::PCToLine(const VMOP *pc)
|
||||||
|
|
||||||
int VMScriptFunction::FirstScriptCall(VMScriptFunction *func, VMValue *params, int numparams, VMReturn *ret, int numret)
|
int VMScriptFunction::FirstScriptCall(VMScriptFunction *func, VMValue *params, int numparams, VMReturn *ret, int numret)
|
||||||
{
|
{
|
||||||
func->JitFunc = JitCompile(func);
|
func->ScriptCall = JitCompile(func);
|
||||||
if (func->JitFunc)
|
if (!func->ScriptCall)
|
||||||
func->ScriptCall = &VMScriptFunction::JitCall;
|
|
||||||
else
|
|
||||||
func->ScriptCall = VMExec;
|
func->ScriptCall = VMExec;
|
||||||
|
else
|
||||||
|
func->FunctionJitted = true;
|
||||||
|
|
||||||
return func->ScriptCall(func, params, numparams, ret, numret);
|
return func->ScriptCall(func, params, numparams, ret, numret);
|
||||||
}
|
}
|
||||||
|
|
||||||
int VMScriptFunction::JitCall(VMScriptFunction *func, VMValue *params, int numparams, VMReturn *ret, int numret)
|
|
||||||
{
|
|
||||||
JitExceptionInfo exceptInfo;
|
|
||||||
exceptInfo.reason = -1;
|
|
||||||
int result = func->JitFunc(params, numparams, ret, numret, &exceptInfo);
|
|
||||||
if (exceptInfo.reason != -1)
|
|
||||||
{
|
|
||||||
if (exceptInfo.cppException)
|
|
||||||
std::rethrow_exception(exceptInfo.cppException);
|
|
||||||
else
|
|
||||||
ThrowAbortException(func, exceptInfo.pcOnJitAbort, (EVMAbortException)exceptInfo.reason, nullptr);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
// VMFrame :: InitRegS
|
// VMFrame :: InitRegS
|
||||||
|
@ -449,6 +434,32 @@ VMFrame *VMFrameStack::PopFrame()
|
||||||
return parent;
|
return parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// The jitted code does not implement C++ exception handling.
|
||||||
|
// Catch them, longjmp out of the jitted functions, perform vmframe cleanup
|
||||||
|
// then rethrow the C++ exception
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
thread_local JitExceptionInfo *CurrentJitExceptInfo;
|
||||||
|
|
||||||
|
void VMThrowException(std::exception_ptr cppException)
|
||||||
|
{
|
||||||
|
CurrentJitExceptInfo->cppException = cppException;
|
||||||
|
longjmp(CurrentJitExceptInfo->sjljbuf, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void VMRethrowException(JitExceptionInfo *exceptInfo)
|
||||||
|
{
|
||||||
|
int c = exceptInfo->vmframes;
|
||||||
|
VMFrameStack *stack = &GlobalVMStack;
|
||||||
|
for (int i = 0; i < c; i++)
|
||||||
|
stack->PopFrame();
|
||||||
|
|
||||||
|
std::rethrow_exception(exceptInfo->cppException);
|
||||||
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
// VMFrameStack :: Call
|
// VMFrameStack :: Call
|
||||||
|
@ -490,10 +501,25 @@ int VMCall(VMFunction *func, VMValue *params, int numparams, VMReturn *results,
|
||||||
{
|
{
|
||||||
VMCycles[0].Clock();
|
VMCycles[0].Clock();
|
||||||
VMCalls[0]++;
|
VMCalls[0]++;
|
||||||
auto sfunc = static_cast<VMScriptFunction *>(func);
|
|
||||||
int numret = sfunc->ScriptCall(sfunc, params, numparams, results, numresults);
|
JitExceptionInfo *prevExceptInfo = CurrentJitExceptInfo;
|
||||||
VMCycles[0].Unclock();
|
JitExceptionInfo newExceptInfo;
|
||||||
return numret;
|
CurrentJitExceptInfo = &newExceptInfo;
|
||||||
|
if (setjmp(CurrentJitExceptInfo->sjljbuf) == 0)
|
||||||
|
{
|
||||||
|
auto sfunc = static_cast<VMScriptFunction *>(func);
|
||||||
|
int numret = sfunc->ScriptCall(sfunc, params, numparams, results, numresults);
|
||||||
|
CurrentJitExceptInfo = prevExceptInfo;
|
||||||
|
VMCycles[0].Unclock();
|
||||||
|
return numret;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
VMCycles[0].Unclock();
|
||||||
|
auto exceptInfo = CurrentJitExceptInfo;
|
||||||
|
CurrentJitExceptInfo = prevExceptInfo;
|
||||||
|
VMRethrowException(exceptInfo);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "vm.h"
|
#include "vm.h"
|
||||||
|
#include <csetjmp>
|
||||||
|
|
||||||
class VMScriptFunction;
|
class VMScriptFunction;
|
||||||
|
|
||||||
|
@ -440,13 +441,16 @@ typedef std::pair<const class PType *, unsigned> FTypeAndOffset;
|
||||||
|
|
||||||
struct JitExceptionInfo
|
struct JitExceptionInfo
|
||||||
{
|
{
|
||||||
int32_t reason; // EVMAbortException
|
|
||||||
int32_t args[3];
|
|
||||||
VMOP* pcOnJitAbort;
|
|
||||||
std::exception_ptr cppException;
|
std::exception_ptr cppException;
|
||||||
|
std::jmp_buf sjljbuf;
|
||||||
|
int vmframes = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef int(*JitFuncPtr)(VMValue *params, int numparams, VMReturn *ret, int numret, JitExceptionInfo *exceptInfo);
|
extern thread_local JitExceptionInfo *CurrentJitExceptInfo;
|
||||||
|
|
||||||
|
void VMThrowException(std::exception_ptr cppException);
|
||||||
|
|
||||||
|
typedef int(*JitFuncPtr)(VMScriptFunction *func, VMValue *params, int numparams, VMReturn *ret, int numret);
|
||||||
|
|
||||||
class VMScriptFunction : public VMFunction
|
class VMScriptFunction : public VMFunction
|
||||||
{
|
{
|
||||||
|
@ -487,6 +491,6 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static int FirstScriptCall(VMScriptFunction *func, VMValue *params, int numparams, VMReturn *ret, int numret);
|
static int FirstScriptCall(VMScriptFunction *func, VMValue *params, int numparams, VMReturn *ret, int numret);
|
||||||
static int JitCall(VMScriptFunction *func, VMValue *params, int numparams, VMReturn *ret, int numret);
|
|
||||||
JitFuncPtr JitFunc = nullptr;
|
bool FunctionJitted = false;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue