From 6424190cbf419ca14c5eccee3b02cdee16dd8d8d Mon Sep 17 00:00:00 2001 From: Jonathan Russell Date: Sat, 18 Aug 2018 18:03:18 +0100 Subject: [PATCH] - add first draft of abort exceptions --- src/scripting/vm/jit.cpp | 59 +++++++++++++++++++++++++++++++++++++ src/scripting/vm/vmexec.h | 14 +++++++-- src/scripting/vm/vmintern.h | 1 + 3 files changed, 72 insertions(+), 2 deletions(-) diff --git a/src/scripting/vm/jit.cpp b/src/scripting/vm/jit.cpp index 0e6badac8..ffba12cd4 100644 --- a/src/scripting/vm/jit.cpp +++ b/src/scripting/vm/jit.cpp @@ -292,6 +292,57 @@ static int64_t ToMemAddress(const void *d) return (int64_t)(ptrdiff_t)d; } +void setPCOnAbort(VMScriptFunction *sfunc, VMOP* pc) { + sfunc->pcOnJitAbort = pc; +} + +template +void setCallArg(T call, int num, int64_t arg) { + call->setArg(num, asmjit::imm(arg)); +} + +void setCallArg(asmjit::CCFuncCall* call, int num, uint64_t arg) { + call->setArg(num, asmjit::imm_u(arg)); +} + +void setCallArg(asmjit::CCFuncCall* call, int num, const asmjit::Reg& arg) { + call->setArg(num, arg); +} + +template +void setCallArg(asmjit::CCFuncCall* call, int num, Arg* arg) { + call->setArg(num, asmjit::imm_ptr(arg)); +} + +template +void emitCallVariadicArgs(asmjit::CCFuncCall* call, int num, Arg arg) { + setCallArg(call, num, arg); +} + +template +void emitCallVariadicArgs(asmjit::CCFuncCall* call, int num, Arg arg, Args... args) { + setCallArg(call, num, arg); + emitCallVariadicArgs(call, num + 1, args...); +} + +void emitCallVariadicArgs(asmjit::CCFuncCall*, int num) {} + +template +void emitAbortExceptionCall(asmjit::X86Compiler& cc, VMScriptFunction* sfunc, const VMOP* pc, EVMAbortException reason, const char* moreinfo, Args... args) { + using namespace asmjit; + + auto ptr = cc.newIntPtr(); + + CCFuncCall* setPCCall = cc.call(imm_ptr((void*)setPCOnAbort), FuncSignature2(CallConv::kIdHost)); + setPCCall->setArg(0, imm_ptr(sfunc)); + setPCCall->setArg(1, imm_ptr(pc)); + + CCFuncCall* throwAbortCall = cc.call(imm_ptr((void*)ThrowAbortException), FuncSignatureT(CallConv::kIdHost)); + throwAbortCall->setArg(0, imm(reason)); + throwAbortCall->setArg(1, imm_ptr(moreinfo)); + emitCallVariadicArgs(throwAbortCall, 2, args...); +} + static void CallSqrt(asmjit::X86Compiler& cc, const asmjit::X86Xmm &a, const asmjit::X86Xmm &b) { using namespace asmjit; @@ -902,10 +953,18 @@ JitFuncPtr JitCompile(VMScriptFunction *sfunc) { auto tmp0 = cc.newInt32(); auto tmp1 = cc.newInt32(); + auto label = cc.newLabel(); + + cc.test(regD[C], regD[C]); + cc.je(label); + cc.mov(tmp0, regD[B]); cc.cdq(tmp1, tmp0); cc.idiv(tmp1, tmp0, regD[C]); cc.mov(regD[A], tmp0); + + cc.bind(label); + emitAbortExceptionCall(cc, sfunc, pc, X_DIVISION_BY_ZERO, nullptr); break; } case OP_DIV_RK: diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index 8df0fb70b..52a9cc117 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -80,8 +80,18 @@ static int Exec(VMFrameStack *stack, const VMOP *pc, VMReturn *ret, int numret) sfunc->JitFunc = JitCompile(sfunc); sfunc->JitCompiled = true; } - if (sfunc->JitFunc) - return sfunc->JitFunc(stack, ®, ret, numret); + if (sfunc->JitFunc) { + try { + return sfunc->JitFunc(stack, ®, ret, numret); + } + catch (CVMAbortException &err) + { + err.MaybePrintMessage(); + err.stacktrace.AppendFormat("Called from %s at %s, line %d\n", sfunc->PrintableName.GetChars(), sfunc->SourceFileName.GetChars(), sfunc->PCToLine(sfunc->pcOnJitAbort)); + // PrintParameters(reg.param + f->NumParam - B, B); + throw; + } + } } void *ptr; diff --git a/src/scripting/vm/vmintern.h b/src/scripting/vm/vmintern.h index 379ad7c5f..5888772e1 100644 --- a/src/scripting/vm/vmintern.h +++ b/src/scripting/vm/vmintern.h @@ -471,6 +471,7 @@ public: bool JitCompiled = false; JitFuncPtr JitFunc = nullptr; + VMOP* pcOnJitAbort = nullptr; void InitExtra(void *addr); void DestroyExtra(void *addr);