diff --git a/src/scripting/vm/jit.cpp b/src/scripting/vm/jit.cpp index c2ce7398c..fe9e8319f 100644 --- a/src/scripting/vm/jit.cpp +++ b/src/scripting/vm/jit.cpp @@ -292,22 +292,6 @@ static int64_t ToMemAddress(const void *d) return (int64_t)(ptrdiff_t)d; } -void setPCOnAbort(VMScriptFunction *sfunc, VMOP* pc) { - sfunc->pcOnJitAbort = pc; -} - -void emitAbortExceptionCall(asmjit::X86Compiler& cc, VMScriptFunction* sfunc, const VMOP* pc, EVMAbortException reason, const char* moreinfo) { - using namespace asmjit; - - 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)); -} - static void CallSqrt(asmjit::X86Compiler& cc, const asmjit::X86Xmm &a, const asmjit::X86Xmm &b) { using namespace asmjit; @@ -317,6 +301,43 @@ static void CallSqrt(asmjit::X86Compiler& cc, const asmjit::X86Xmm &a, const asm call->setArg(0, b); } +static void EmitThrowException(asmjit::X86Compiler& cc, asmjit::X86Gp exceptInfo, const VMOP* pc, EVMAbortException reason) +{ + using namespace asmjit; + + // Update JitExceptionInfo struct + cc.mov(x86::dword_ptr(exceptInfo, 0 * 4), (int32_t)reason); + #ifdef ASMJIT_ARCH_X64 + cc.mov(x86::qword_ptr(exceptInfo, 4 * 4), ToMemAddress(pc)); + #else + cc.mov(x86::dword_ptr(exceptInfo, 4 * 4), ToMemAddress(pc)); + #endif + + // Return from function + X86Gp vReg = cc.newInt32(); + cc.mov(vReg, 0); + cc.ret(vReg); +} + +static void EmitThrowException(asmjit::X86Compiler& cc, asmjit::X86Gp exceptInfo, const VMOP* pc, EVMAbortException reason, asmjit::X86Gp arg1) +{ + using namespace asmjit; + + // Update JitExceptionInfo struct + cc.mov(x86::dword_ptr(exceptInfo, 0 * 4), (int32_t)reason); + cc.mov(x86::dword_ptr(exceptInfo, 1 * 4), arg1); + #ifdef ASMJIT_ARCH_X64 + cc.mov(x86::qword_ptr(exceptInfo, 4 * 4), ToMemAddress(pc)); + #else + cc.mov(x86::dword_ptr(exceptInfo, 4 * 4), ToMemAddress(pc)); + #endif + + // Return from function + X86Gp vReg = cc.newInt32(); + cc.mov(vReg, 0); + cc.ret(vReg); +} + JitFuncPtr JitCompile(VMScriptFunction *sfunc) { #if 0 // For debugging @@ -345,12 +366,14 @@ JitFuncPtr JitCompile(VMScriptFunction *sfunc) X86Gp vmregs = cc.newIntPtr("vmregs"); // void *vmregs X86Gp ret = cc.newIntPtr("ret"); // VMReturn *ret X86Gp numret = cc.newInt32("numret"); // int numret + X86Gp exceptInfo = cc.newIntPtr("exceptinfo"); // JitExceptionInfo *exceptInfo - cc.addFunc(FuncSignature4()); + cc.addFunc(FuncSignature5()); cc.setArg(0, stack); cc.setArg(1, vmregs); cc.setArg(2, ret); cc.setArg(3, numret); + cc.setArg(4, exceptInfo); const int *konstd = sfunc->KonstD; const double *konstf = sfunc->KonstF; @@ -929,7 +952,7 @@ JitFuncPtr JitCompile(VMScriptFunction *sfunc) cc.mov(regD[A], tmp0); cc.bind(label); - emitAbortExceptionCall(cc, sfunc, pc, X_DIVISION_BY_ZERO, nullptr); + EmitThrowException(cc, exceptInfo, pc, X_DIVISION_BY_ZERO); break; } case OP_DIV_RK: diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index 342b44d78..2cd86cdcf 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -45,6 +45,8 @@ #include "scripting/backend/scopebarrier.h" class DObject; +union VMOP; +class VMScriptFunction; extern FMemArena ClassDataAllocator; @@ -104,6 +106,7 @@ public: // This must be a separate function because the VC compiler would otherwise allocate memory on the stack for every separate instance of the exception object that may get thrown. void ThrowAbortException(EVMAbortException reason, const char *moreinfo, ...); +void ThrowAbortException(VMScriptFunction *sfunc, VMOP *line, EVMAbortException reason, const char *moreinfo, ...); struct VMReturn { diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index 52a9cc117..e2ec3ead3 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -80,17 +80,16 @@ static int Exec(VMFrameStack *stack, const VMOP *pc, VMReturn *ret, int numret) sfunc->JitFunc = JitCompile(sfunc); sfunc->JitCompiled = true; } - if (sfunc->JitFunc) { - try { - return sfunc->JitFunc(stack, ®, ret, numret); - } - catch (CVMAbortException &err) + if (sfunc->JitFunc) + { + JitExceptionInfo exceptInfo; + exceptInfo.reason = -1; + int result = sfunc->JitFunc(stack, ®, ret, numret, &exceptInfo); + if (exceptInfo.reason != -1) { - 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; + ThrowAbortException(sfunc, exceptInfo.pcOnJitAbort, (EVMAbortException)exceptInfo.reason, nullptr); } + return result; } } diff --git a/src/scripting/vm/vmframe.cpp b/src/scripting/vm/vmframe.cpp index a537c4637..964371331 100644 --- a/src/scripting/vm/vmframe.cpp +++ b/src/scripting/vm/vmframe.cpp @@ -577,6 +577,16 @@ void ThrowAbortException(EVMAbortException reason, const char *moreinfo, ...) va_end(ap); } +void ThrowAbortException(VMScriptFunction *sfunc, VMOP *line, EVMAbortException reason, const char *moreinfo, ...) +{ + va_list ap; + va_start(ap, moreinfo); + CVMAbortException err(reason, moreinfo, ap); + err.stacktrace.AppendFormat("Called from %s at %s, line %d\n", sfunc->PrintableName.GetChars(), sfunc->SourceFileName.GetChars(), sfunc->PCToLine(line)); + throw err; + va_end(ap); +} + DEFINE_ACTION_FUNCTION(DObject, ThrowAbortException) { PARAM_PROLOGUE; diff --git a/src/scripting/vm/vmintern.h b/src/scripting/vm/vmintern.h index 5888772e1..99cf97214 100644 --- a/src/scripting/vm/vmintern.h +++ b/src/scripting/vm/vmintern.h @@ -437,7 +437,14 @@ extern thread_local VMFrameStack GlobalVMStack; typedef std::pair FTypeAndOffset; -typedef int(*JitFuncPtr)(VMFrameStack *stack, const void *vmregs, VMReturn *ret, int numret); +struct JitExceptionInfo +{ + int32_t reason; // EVMAbortException + int32_t args[3]; + VMOP* pcOnJitAbort; +}; + +typedef int(*JitFuncPtr)(VMFrameStack *stack, const void *vmregs, VMReturn *ret, int numret, JitExceptionInfo *exceptInfo); class VMScriptFunction : public VMFunction { @@ -471,7 +478,6 @@ public: bool JitCompiled = false; JitFuncPtr JitFunc = nullptr; - VMOP* pcOnJitAbort = nullptr; void InitExtra(void *addr); void DestroyExtra(void *addr);