From d7da2d838fce3f4c7c78218b9b7cb75bef2db4f8 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 4 Dec 2018 18:45:07 +0100 Subject: [PATCH] - handle JIT errors in a more user-friendly fashion than aborting. * use I_Error instead of I_FatalError to abort. I_FatalError is only for things that are not recoverable and should not be handled outside of error cleanup and rethrowing. * only catch CRecoverableError in JitCompile. Everything else should fall through to the outermost catch block. * Do not I_FatalError out after handling the exception locally. Just print an error and return null, indicating failure. --- src/scripting/vm/jit.cpp | 4 ++-- src/scripting/vm/jit_call.cpp | 34 ++++++++++++++++---------------- src/scripting/vm/jit_math.cpp | 18 ++++++++--------- src/scripting/vm/jit_move.cpp | 2 +- src/scripting/vm/jit_runtime.cpp | 6 +++--- 5 files changed, 32 insertions(+), 32 deletions(-) diff --git a/src/scripting/vm/jit.cpp b/src/scripting/vm/jit.cpp index 5da62ab5f9..6aacc4bf1e 100644 --- a/src/scripting/vm/jit.cpp +++ b/src/scripting/vm/jit.cpp @@ -30,10 +30,10 @@ JitFuncPtr JitCompile(VMScriptFunction *sfunc) return reinterpret_cast(AddJitFunction(&code, func)); } - catch (const std::exception &e) + catch (const CRecoverableError &e) { OutputJitLog(logger); - I_FatalError("Unexpected JIT error: %s\n", e.what()); + Printf("%s: Unexpected JIT error: %s\n",sfunc->PrintableName.GetChars(), e.what()); return nullptr; } } diff --git a/src/scripting/vm/jit_call.cpp b/src/scripting/vm/jit_call.cpp index a64ed9024f..f51fd1c393 100644 --- a/src/scripting/vm/jit_call.cpp +++ b/src/scripting/vm/jit_call.cpp @@ -76,7 +76,7 @@ void JitCompiler::EmitVMCall(asmjit::X86Gp vmfunc, VMFunction *target) int numparams = StoreCallParams(); if (numparams != B) - I_FatalError("OP_CALL parameter count does not match the number of preceding OP_PARAM instructions"); + I_Error("OP_CALL parameter count does not match the number of preceding OP_PARAM instructions"); if ((pc - 1)->op == OP_VTBL) EmitVtbl(pc - 1); @@ -199,7 +199,7 @@ int JitCompiler::StoreCallParams() break; default: - I_FatalError("Unknown REGT value passed to EmitPARAM\n"); + I_Error("Unknown REGT value passed to EmitPARAM\n"); break; } } @@ -224,7 +224,7 @@ void JitCompiler::LoadReturns(const VMOP *retval, int numret) for (int i = 0; i < numret; ++i) { if (retval[i].op != OP_RESULT) - I_FatalError("Expected OP_RESULT to follow OP_CALL\n"); + I_Error("Expected OP_RESULT to follow OP_CALL\n"); LoadCallResult(retval[i].b, retval[i].c, false); } @@ -264,7 +264,7 @@ void JitCompiler::LoadCallResult(int type, int regnum, bool addrof) cc.mov(regA[regnum], asmjit::x86::ptr(vmframe, offsetA + regnum * sizeof(void*))); break; default: - I_FatalError("Unknown OP_RESULT/OP_PARAM type encountered in LoadCallResult\n"); + I_Error("Unknown OP_RESULT/OP_PARAM type encountered in LoadCallResult\n"); break; } } @@ -277,7 +277,7 @@ void JitCompiler::FillReturns(const VMOP *retval, int numret) { if (retval[i].op != OP_RESULT) { - I_FatalError("Expected OP_RESULT to follow OP_CALL\n"); + I_Error("Expected OP_RESULT to follow OP_CALL\n"); } int type = retval[i].b; @@ -285,7 +285,7 @@ void JitCompiler::FillReturns(const VMOP *retval, int numret) if (type & REGT_KONST) { - I_FatalError("OP_RESULT with REGT_KONST is not allowed\n"); + I_Error("OP_RESULT with REGT_KONST is not allowed\n"); } auto regPtr = newTempIntPtr(); @@ -305,7 +305,7 @@ void JitCompiler::FillReturns(const VMOP *retval, int numret) cc.lea(regPtr, x86::ptr(vmframe, offsetA + (int)(regnum * sizeof(void*)))); break; default: - I_FatalError("Unknown OP_RESULT type encountered in FillReturns\n"); + I_Error("Unknown OP_RESULT type encountered in FillReturns\n"); break; } @@ -320,7 +320,7 @@ void JitCompiler::EmitNativeCall(VMNativeFunction *target) if ((pc - 1)->op == OP_VTBL) { - I_FatalError("Native direct member function calls not implemented\n"); + I_Error("Native direct member function calls not implemented\n"); } asmjit::CBNode *cursorBefore = cc.getCursor(); @@ -397,18 +397,18 @@ void JitCompiler::EmitNativeCall(VMNativeFunction *target) case REGT_INT | REGT_ADDROF: case REGT_POINTER | REGT_ADDROF: case REGT_FLOAT | REGT_ADDROF: - I_FatalError("REGT_ADDROF not implemented for native direct calls\n"); + I_Error("REGT_ADDROF not implemented for native direct calls\n"); break; default: - I_FatalError("Unknown REGT value passed to EmitPARAM\n"); + I_Error("Unknown REGT value passed to EmitPARAM\n"); break; } } } if (numparams != B) - I_FatalError("OP_CALL parameter count does not match the number of preceding OP_PARAM instructions\n"); + I_Error("OP_CALL parameter count does not match the number of preceding OP_PARAM instructions\n"); // Note: the usage of newResultXX is intentional. Asmjit has a register allocation bug // if the return virtual register is already allocated in an argument slot. @@ -441,7 +441,7 @@ void JitCompiler::EmitNativeCall(VMNativeFunction *target) if (type & REGT_KONST) { - I_FatalError("OP_RESULT with REGT_KONST is not allowed\n"); + I_Error("OP_RESULT with REGT_KONST is not allowed\n"); } CheckVMFrame(); @@ -470,7 +470,7 @@ void JitCompiler::EmitNativeCall(VMNativeFunction *target) cc.lea(regPtr, x86::ptr(vmframe, offsetA + (int)(regnum * sizeof(void*)))); break; default: - I_FatalError("Unknown OP_RESULT type encountered\n"); + I_Error("Unknown OP_RESULT type encountered\n"); break; } @@ -535,7 +535,7 @@ void JitCompiler::EmitNativeCall(VMNativeFunction *target) cc.mov(regA[regnum], asmjit::x86::ptr(vmframe, offsetA + regnum * sizeof(void*))); break; default: - I_FatalError("Unknown OP_RESULT type encountered\n"); + I_Error("Unknown OP_RESULT type encountered\n"); break; } } @@ -602,7 +602,7 @@ asmjit::FuncSignature JitCompiler::CreateFuncSignature() break; default: - I_FatalError("Unknown REGT value passed to EmitPARAM\n"); + I_Error("Unknown REGT value passed to EmitPARAM\n"); break; } } @@ -619,7 +619,7 @@ asmjit::FuncSignature JitCompiler::CreateFuncSignature() { if (retval[0].op != OP_RESULT) { - I_FatalError("Expected OP_RESULT to follow OP_CALL\n"); + I_Error("Expected OP_RESULT to follow OP_CALL\n"); } int type = retval[0].b; @@ -649,7 +649,7 @@ asmjit::FuncSignature JitCompiler::CreateFuncSignature() { if (retval[i].op != OP_RESULT) { - I_FatalError("Expected OP_RESULT to follow OP_CALL\n"); + I_Error("Expected OP_RESULT to follow OP_CALL\n"); } args.Push(TypeIdOf::kTypeId); diff --git a/src/scripting/vm/jit_math.cpp b/src/scripting/vm/jit_math.cpp index e929ddd846..6c814a5506 100644 --- a/src/scripting/vm/jit_math.cpp +++ b/src/scripting/vm/jit_math.cpp @@ -962,7 +962,7 @@ void JitCompiler::EmitFLOP() FuncPtr func = nullptr; switch (C) { - default: I_FatalError("Unknown OP_FLOP subfunction"); + default: I_Error("Unknown OP_FLOP subfunction"); case FLOP_ABS: func = fabs; break; case FLOP_EXP: func = g_exp; break; case FLOP_LOG: func = g_log; break; @@ -1090,7 +1090,7 @@ void JitCompiler::EmitEQF_K() void JitCompiler::EmitLTF_RR() { EmitComparisonOpcode([&](bool check, asmjit::Label& fail, asmjit::Label& success) { - if (static_cast(A & CMP_APPROX)) I_FatalError("CMP_APPROX not implemented for LTF_RR.\n"); + if (static_cast(A & CMP_APPROX)) I_Error("CMP_APPROX not implemented for LTF_RR.\n"); cc.ucomisd(regF[C], regF[B]); if (check) cc.ja(fail); @@ -1101,7 +1101,7 @@ void JitCompiler::EmitLTF_RR() void JitCompiler::EmitLTF_RK() { EmitComparisonOpcode([&](bool check, asmjit::Label& fail, asmjit::Label& success) { - if (static_cast(A & CMP_APPROX)) I_FatalError("CMP_APPROX not implemented for LTF_RK.\n"); + if (static_cast(A & CMP_APPROX)) I_Error("CMP_APPROX not implemented for LTF_RK.\n"); auto constTmp = newTempIntPtr(); auto xmmTmp = newTempXmmSd(); @@ -1117,7 +1117,7 @@ void JitCompiler::EmitLTF_RK() void JitCompiler::EmitLTF_KR() { EmitComparisonOpcode([&](bool check, asmjit::Label& fail, asmjit::Label& success) { - if (static_cast(A & CMP_APPROX)) I_FatalError("CMP_APPROX not implemented for LTF_KR.\n"); + if (static_cast(A & CMP_APPROX)) I_Error("CMP_APPROX not implemented for LTF_KR.\n"); auto tmp = newTempIntPtr(); cc.mov(tmp, asmjit::imm_ptr(&konstf[B])); @@ -1131,7 +1131,7 @@ void JitCompiler::EmitLTF_KR() void JitCompiler::EmitLEF_RR() { EmitComparisonOpcode([&](bool check, asmjit::Label& fail, asmjit::Label& success) { - if (static_cast(A & CMP_APPROX)) I_FatalError("CMP_APPROX not implemented for LEF_RR.\n"); + if (static_cast(A & CMP_APPROX)) I_Error("CMP_APPROX not implemented for LEF_RR.\n"); cc.ucomisd(regF[C], regF[B]); if (check) cc.jae(fail); @@ -1142,7 +1142,7 @@ void JitCompiler::EmitLEF_RR() void JitCompiler::EmitLEF_RK() { EmitComparisonOpcode([&](bool check, asmjit::Label& fail, asmjit::Label& success) { - if (static_cast(A & CMP_APPROX)) I_FatalError("CMP_APPROX not implemented for LEF_RK.\n"); + if (static_cast(A & CMP_APPROX)) I_Error("CMP_APPROX not implemented for LEF_RK.\n"); auto constTmp = newTempIntPtr(); auto xmmTmp = newTempXmmSd(); @@ -1158,7 +1158,7 @@ void JitCompiler::EmitLEF_RK() void JitCompiler::EmitLEF_KR() { EmitComparisonOpcode([&](bool check, asmjit::Label& fail, asmjit::Label& success) { - if (static_cast(A & CMP_APPROX)) I_FatalError("CMP_APPROX not implemented for LEF_KR.\n"); + if (static_cast(A & CMP_APPROX)) I_Error("CMP_APPROX not implemented for LEF_KR.\n"); auto tmp = newTempIntPtr(); cc.mov(tmp, asmjit::imm_ptr(&konstf[B])); @@ -1275,7 +1275,7 @@ void JitCompiler::EmitEQV2_R() void JitCompiler::EmitEQV2_K() { - I_FatalError("EQV2_K is not used."); + I_Error("EQV2_K is not used."); } ///////////////////////////////////////////////////////////////////////////// @@ -1442,7 +1442,7 @@ void JitCompiler::EmitEQV3_R() void JitCompiler::EmitEQV3_K() { - I_FatalError("EQV3_K is not used."); + I_Error("EQV3_K is not used."); } ///////////////////////////////////////////////////////////////////////////// diff --git a/src/scripting/vm/jit_move.cpp b/src/scripting/vm/jit_move.cpp index fc70bf5d4c..b8953b2aa1 100644 --- a/src/scripting/vm/jit_move.cpp +++ b/src/scripting/vm/jit_move.cpp @@ -174,7 +174,7 @@ void JitCompiler::EmitCAST() call->setArg(1, regD[B]); break; default: - I_FatalError("Unknown OP_CAST type\n"); + I_Error("Unknown OP_CAST type\n"); } } diff --git a/src/scripting/vm/jit_runtime.cpp b/src/scripting/vm/jit_runtime.cpp index 25f77c33ab..68b7988a02 100644 --- a/src/scripting/vm/jit_runtime.cpp +++ b/src/scripting/vm/jit_runtime.cpp @@ -64,7 +64,7 @@ static TArray CreateUnwindInfoWindows(asmjit::CCFunc *func) FuncFrameLayout layout; Error error = layout.init(func->getDetail(), func->getFrameInfo()); if (error != kErrorOk) - I_FatalError("FuncFrameLayout.init failed"); + I_Error("FuncFrameLayout.init failed"); // We need a dummy emitter for instruction size calculations CodeHolder code; @@ -275,7 +275,7 @@ void *AddJitFunction(asmjit::CodeHolder* code, asmjit::CCFunc *func) BOOLEAN result = RtlAddFunctionTable(table, 1, (DWORD64)baseaddr); JitFrames.Push((uint8_t*)table); if (result == 0) - I_FatalError("RtlAddFunctionTable failed"); + I_Error("RtlAddFunctionTable failed"); #endif return p; @@ -549,7 +549,7 @@ static TArray CreateUnwindInfoUnix(asmjit::CCFunc *func, unsigned int & FuncFrameLayout layout; Error error = layout.init(func->getDetail(), func->getFrameInfo()); if (error != kErrorOk) - I_FatalError("FuncFrameLayout.init failed"); + I_Error("FuncFrameLayout.init failed"); // We need a dummy emitter for instruction size calculations CodeHolder code;