Skip to content

Commit

Permalink
- implement throwing by storing exception information in a struct, th…
Browse files Browse the repository at this point in the history
…en return from the jitted function and throw from c++
  • Loading branch information
dpjudas committed Aug 18, 2018
1 parent b6f52c3 commit 3453f05
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 28 deletions.
57 changes: 40 additions & 17 deletions src/scripting/vm/jit.cpp
Expand Up @@ -292,29 +292,50 @@ static int64_t ToMemAddress(const void *d)
return (int64_t)(ptrdiff_t)d;
}

void setPCOnAbort(VMScriptFunction *sfunc, VMOP* pc) {
sfunc->pcOnJitAbort = pc;
static void CallSqrt(asmjit::X86Compiler& cc, const asmjit::X86Xmm &a, const asmjit::X86Xmm &b)
{
using namespace asmjit;
typedef double(*FuncPtr)(double);
auto call = cc.call(ToMemAddress(static_cast<FuncPtr>(g_sqrt)), FuncSignature1<void, double>());
call->setRet(0, a);
call->setArg(0, b);
}

void emitAbortExceptionCall(asmjit::X86Compiler& cc, VMScriptFunction* sfunc, const VMOP* pc, EVMAbortException reason, const char* moreinfo) {
static void EmitThrowException(asmjit::X86Compiler& cc, asmjit::X86Gp exceptInfo, const VMOP* pc, EVMAbortException reason)
{
using namespace asmjit;

CCFuncCall* setPCCall = cc.call(imm_ptr((void*)setPCOnAbort), FuncSignature2<void, VMScriptFunction*, VMOP*>(CallConv::kIdHost));
setPCCall->setArg(0, imm_ptr(sfunc));
setPCCall->setArg(1, imm_ptr(pc));

CCFuncCall* throwAbortCall = cc.call(imm_ptr((void*)ThrowAbortException), FuncSignatureT<void, int, const char*>(CallConv::kIdHost));
throwAbortCall->setArg(0, imm(reason));
throwAbortCall->setArg(1, imm_ptr(moreinfo));
// 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 CallSqrt(asmjit::X86Compiler& cc, const asmjit::X86Xmm &a, const asmjit::X86Xmm &b)
static void EmitThrowException(asmjit::X86Compiler& cc, asmjit::X86Gp exceptInfo, const VMOP* pc, EVMAbortException reason, asmjit::X86Gp arg1)
{
using namespace asmjit;
typedef double(*FuncPtr)(double);
auto call = cc.call(ToMemAddress(static_cast<FuncPtr>(g_sqrt)), FuncSignature1<void, double>());
call->setRet(0, a);
call->setArg(0, b);

// 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)
Expand Down Expand Up @@ -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<int, void *, void *, void *, int>());
cc.addFunc(FuncSignature5<int, void *, void *, void *, int, void *>());
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;
Expand Down Expand Up @@ -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:
Expand Down
3 changes: 3 additions & 0 deletions src/scripting/vm/vm.h
Expand Up @@ -45,6 +45,8 @@
#include "scripting/backend/scopebarrier.h"

class DObject;
union VMOP;
class VMScriptFunction;

extern FMemArena ClassDataAllocator;

Expand Down Expand Up @@ -104,6 +106,7 @@ class CVMAbortException : public CDoomError

// 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
{
Expand Down
17 changes: 8 additions & 9 deletions src/scripting/vm/vmexec.h
Expand Up @@ -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, &reg, ret, numret);
}
catch (CVMAbortException &err)
if (sfunc->JitFunc)
{
JitExceptionInfo exceptInfo;
exceptInfo.reason = -1;
int result = sfunc->JitFunc(stack, &reg, 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;
}
}

Expand Down
10 changes: 10 additions & 0 deletions src/scripting/vm/vmframe.cpp
Expand Up @@ -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;
Expand Down
10 changes: 8 additions & 2 deletions src/scripting/vm/vmintern.h
Expand Up @@ -437,7 +437,14 @@ extern thread_local VMFrameStack GlobalVMStack;

typedef std::pair<const class PType *, unsigned> 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
{
Expand Down Expand Up @@ -471,7 +478,6 @@ class VMScriptFunction : public VMFunction

bool JitCompiled = false;
JitFuncPtr JitFunc = nullptr;
VMOP* pcOnJitAbort = nullptr;

void InitExtra(void *addr);
void DestroyExtra(void *addr);
Expand Down

0 comments on commit 3453f05

Please sign in to comment.