diff --git a/src/scripting/vm/jit.cpp b/src/scripting/vm/jit.cpp index ceccb97fe..3ed45d302 100644 --- a/src/scripting/vm/jit.cpp +++ b/src/scripting/vm/jit.cpp @@ -303,6 +303,19 @@ void JitCompiler::EmitThrowException(EVMAbortException reason, asmjit::X86Gp arg 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); + asmjit::X86Gp vReg = newTempInt32(); + cc.mov(vReg, 0); + cc.ret(vReg); + cc.bind(noexception); +} + asmjit::X86Gp JitCompiler::CheckRegD(int r0, int r1) { if (r0 != r1) diff --git a/src/scripting/vm/jit_call.cpp b/src/scripting/vm/jit_call.cpp index ff3c2b9fa..f89fb6a22 100644 --- a/src/scripting/vm/jit_call.cpp +++ b/src/scripting/vm/jit_call.cpp @@ -180,15 +180,7 @@ void JitCompiler::EmitDoCall(asmjit::X86Gp ptr) call->setArg(5, callReturns); call->setArg(6, exceptInfo); - auto noexception = cc.newLabel(); - auto exceptResult = newTempInt32(); - cc.mov(exceptResult, x86::dword_ptr(exceptInfo, 0 * 4)); - cc.cmp(exceptResult, (int)-1); - cc.je(noexception); - X86Gp vReg = newTempInt32(); - cc.mov(vReg, 0); - cc.ret(vReg); - cc.bind(noexception); + EmitCheckForException(); LoadInOuts(B); LoadReturns(pc + 1, C); @@ -414,8 +406,8 @@ int JitCompiler::DoCall(VMFrameStack *stack, VMFunction *call, int b, int c, VMV } catch (...) { - // To do: store full exception in exceptinfo exceptinfo->reason = X_OTHER; + exceptinfo->cppException = std::current_exception(); return 0; } } diff --git a/src/scripting/vm/jit_flow.cpp b/src/scripting/vm/jit_flow.cpp index 70b8a2319..1efab419b 100644 --- a/src/scripting/vm/jit_flow.cpp +++ b/src/scripting/vm/jit_flow.cpp @@ -79,30 +79,24 @@ void JitCompiler::EmitSCOPE() auto f = newTempIntPtr(); cc.mov(f, asmjit::imm_ptr(konsta[C].v)); - auto result = newResultInt32(); typedef int(*FuncPtr)(DObject*, VMFunction*, int); - auto call = CreateCall([](DObject *o, VMFunction *f, int b) -> int { + auto call = CreateCall([](DObject *o, VMFunction *f, int b, JitExceptionInfo *exceptinfo) { try { FScopeBarrier::ValidateCall(o->GetClass(), f, b - 1); - return 1; } - catch (const CVMAbortException &) + catch (...) { - // To do: pass along the exception info - return 0; + exceptinfo->reason = X_OTHER; + exceptinfo->cppException = std::current_exception(); } }); - call->setRet(0, result); call->setArg(0, regA[A]); call->setArg(1, f); call->setArg(2, asmjit::Imm(B)); + call->setArg(3, exceptInfo); - auto notzero = cc.newLabel(); - cc.test(result, result); - cc.jnz(notzero); - EmitThrowException(X_OTHER); - cc.bind(notzero); + EmitCheckForException(); } void JitCompiler::EmitRET() @@ -259,7 +253,7 @@ void JitCompiler::EmitRETI() void JitCompiler::EmitNEW() { auto result = newResultIntPtr(); - auto call = CreateCall([](PClass *cls, int c) -> DObject* { + auto call = CreateCall([](PClass *cls, int c, JitExceptionInfo *exceptinfo) -> DObject* { try { if (!cls->ConstructNative) @@ -279,21 +273,20 @@ void JitCompiler::EmitNEW() if (c) FScopeBarrier::ValidateNew(cls, c - 1); return cls->CreateNew(); } - catch (const CVMAbortException &) + catch (...) { - // To do: pass along the exception info + exceptinfo->reason = X_OTHER; + exceptinfo->cppException = std::current_exception(); return nullptr; } }); call->setRet(0, result); call->setArg(0, regA[B]); call->setArg(1, asmjit::Imm(C)); + call->setArg(2, exceptInfo); + + EmitCheckForException(); - auto notnull = cc.newLabel(); - cc.test(result, result); - cc.jnz(notnull); - EmitThrowException(X_OTHER); - cc.bind(notnull); cc.mov(regA[A], result); } @@ -317,27 +310,26 @@ void JitCompiler::EmitNEW_K() auto result = newResultIntPtr(); auto regcls = newTempIntPtr(); cc.mov(regcls, asmjit::imm_ptr(konsta[B].v)); - auto call = CreateCall([](PClass *cls, int c) -> DObject* { + auto call = CreateCall([](PClass *cls, int c, JitExceptionInfo *exceptinfo) -> DObject* { try { if (c) FScopeBarrier::ValidateNew(cls, c - 1); return cls->CreateNew(); } - catch (const CVMAbortException &) + catch (...) { - // To do: pass along the exception info + exceptinfo->reason = X_OTHER; + exceptinfo->cppException = std::current_exception(); return nullptr; } }); call->setRet(0, result); call->setArg(0, regcls); call->setArg(1, asmjit::Imm(C)); + call->setArg(2, exceptInfo); + + EmitCheckForException(); - auto notnull = cc.newLabel(); - cc.test(result, result); - cc.jnz(notnull); - EmitThrowException(X_OTHER); - cc.bind(notnull); cc.mov(regA[A], result); } } diff --git a/src/scripting/vm/jitintern.h b/src/scripting/vm/jitintern.h index 4e1a79c73..28f9ff469 100644 --- a/src/scripting/vm/jitintern.h +++ b/src/scripting/vm/jitintern.h @@ -131,6 +131,7 @@ private: void EmitNullPointerThrow(int index, EVMAbortException reason); void EmitThrowException(EVMAbortException reason); void EmitThrowException(EVMAbortException reason, asmjit::X86Gp arg1); + void EmitCheckForException(); asmjit::X86Gp CheckRegD(int r0, int r1); asmjit::X86Xmm CheckRegF(int r0, int r1); diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index d2ad8c894..d75c898a6 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -86,7 +86,10 @@ static int Exec(VMFrameStack *stack, const VMOP *pc, VMReturn *ret, int numret) int result = sfunc->JitFunc(stack, ret, numret, &exceptInfo); if (exceptInfo.reason != -1) { - ThrowAbortException(sfunc, exceptInfo.pcOnJitAbort, (EVMAbortException)exceptInfo.reason, nullptr); + if (exceptInfo.cppException) + std::rethrow_exception(exceptInfo.cppException); + else + ThrowAbortException(sfunc, exceptInfo.pcOnJitAbort, (EVMAbortException)exceptInfo.reason, nullptr); } return result; } diff --git a/src/scripting/vm/vmintern.h b/src/scripting/vm/vmintern.h index 909d3c3b5..832372a9e 100644 --- a/src/scripting/vm/vmintern.h +++ b/src/scripting/vm/vmintern.h @@ -443,6 +443,7 @@ struct JitExceptionInfo int32_t reason; // EVMAbortException int32_t args[3]; VMOP* pcOnJitAbort; + std::exception_ptr cppException; }; typedef int(*JitFuncPtr)(VMFrameStack *stack, VMReturn *ret, int numret, JitExceptionInfo *exceptInfo);