From e2dcca611cc95aaea47a697df5abc5c51cbb2e98 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sun, 7 Oct 2018 20:38:08 +0200 Subject: [PATCH] - catch and rethrow c++ exceptions --- src/scripting/vm/jit.cpp | 13 ++++++++++ src/scripting/vm/jit_call.cpp | 12 ++------- src/scripting/vm/jit_flow.cpp | 48 +++++++++++++++-------------------- src/scripting/vm/jitintern.h | 1 + src/scripting/vm/vmexec.h | 5 +++- src/scripting/vm/vmintern.h | 1 + 6 files changed, 41 insertions(+), 39 deletions(-) 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 abf630b41..7937c8bfd 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 0158e195f..c4711ce98 100644 --- a/src/scripting/vm/vmintern.h +++ b/src/scripting/vm/vmintern.h @@ -447,6 +447,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);