From b7c0cd5d05c9fb8b912053236fb27a532607561d Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Tue, 9 Oct 2018 03:37:11 +0200 Subject: [PATCH] - move VM creation into the jitted function. this will allow the jit compiler to skip vm frame creation when possible --- src/scripting/vm/jit.cpp | 59 +++++++++++++++++++++++++++++++---- src/scripting/vm/jit_call.cpp | 1 + src/scripting/vm/jit_flow.cpp | 9 ++++++ src/scripting/vm/jitintern.h | 5 ++- src/scripting/vm/vmframe.cpp | 31 ++++++------------ src/scripting/vm/vmintern.h | 2 +- 6 files changed, 77 insertions(+), 30 deletions(-) diff --git a/src/scripting/vm/jit.cpp b/src/scripting/vm/jit.cpp index 17f6c11edc..a5c0990232 100644 --- a/src/scripting/vm/jit.cpp +++ b/src/scripting/vm/jit.cpp @@ -142,20 +142,24 @@ void JitCompiler::Setup() { using namespace asmjit; + ResetTemp(); + FString funcname; funcname.Format("Function: %s", sfunc->PrintableName.GetChars()); cc.comment(funcname.GetChars(), funcname.Len()); - stack = cc.newIntPtr("stack"); // VMFrameStack *stack + args = cc.newIntPtr("args"); // VMValue *params + numargs = cc.newInt32("numargs"); // int numargs ret = cc.newIntPtr("ret"); // VMReturn *ret numret = cc.newInt32("numret"); // int numret exceptInfo = cc.newIntPtr("exceptinfo"); // JitExceptionInfo *exceptInfo - cc.addFunc(FuncSignature4()); - cc.setArg(0, stack); - cc.setArg(1, ret); - cc.setArg(2, numret); - cc.setArg(3, exceptInfo); + cc.addFunc(FuncSignature5()); + cc.setArg(0, args); + cc.setArg(1, numargs); + cc.setArg(2, ret); + cc.setArg(3, numret); + cc.setArg(4, exceptInfo); auto stackalloc = cc.newStack(sizeof(VMReturn) * MAX_RETURNS, alignof(VMReturn)); callReturns = cc.newIntPtr("callReturns"); @@ -185,6 +189,29 @@ void JitCompiler::Setup() int offsetD = offsetA + (int)(sfunc->NumRegA * sizeof(void*)); offsetExtra = (offsetD + (int)(sfunc->NumRegD * sizeof(int32_t)) + 15) & ~15; + stack = cc.newIntPtr("stack"); + auto allocFrame = CreateCall([](VMScriptFunction *func, VMValue *args, int numargs, JitExceptionInfo *exceptinfo) -> VMFrameStack* { + try + { + VMFrameStack *stack = &GlobalVMStack; + VMFrame *newf = stack->AllocFrame(func); + VMFillParams(args, newf, numargs); + return stack; + } + catch (...) + { + exceptinfo->reason = X_OTHER; + exceptinfo->cppException = std::current_exception(); + return nullptr; + } + }); + allocFrame->setRet(0, stack); + allocFrame->setArg(0, imm_ptr(sfunc)); + allocFrame->setArg(1, args); + allocFrame->setArg(2, numargs); + allocFrame->setArg(3, exceptInfo); + EmitCheckForException(); + vmframe = cc.newIntPtr(); cc.mov(vmframe, x86::ptr(stack)); // stack->Blocks cc.mov(vmframe, x86::ptr(vmframe, VMFrameStack::OffsetLastFrame())); // Blocks->LastFrame @@ -232,6 +259,23 @@ void JitCompiler::Setup() for (int i = 0; i < size; i++) labels[i] = cc.newLabel(); } +void JitCompiler::EmitPopFrame() +{ + auto popFrame = CreateCall([](VMFrameStack *stack, JitExceptionInfo *exceptinfo) { + try + { + stack->PopFrame(); + } + catch (...) + { + exceptinfo->reason = X_OTHER; + exceptinfo->cppException = std::current_exception(); + } + }); + popFrame->setArg(0, stack); + popFrame->setArg(1, exceptInfo); +} + void JitCompiler::EmitNullPointerThrow(int index, EVMAbortException reason) { auto label = cc.newLabel(); @@ -253,6 +297,7 @@ void JitCompiler::EmitThrowException(EVMAbortException reason) cc.mov(x86::dword_ptr(exceptInfo, 4 * 4), imm_ptr(pc)); // Return from function + EmitPopFrame(); X86Gp vReg = newTempInt32(); cc.mov(vReg, 0); cc.ret(vReg); @@ -271,6 +316,7 @@ void JitCompiler::EmitThrowException(EVMAbortException reason, asmjit::X86Gp arg cc.mov(x86::dword_ptr(exceptInfo, 4 * 4), imm_ptr(pc)); // Return from function + EmitPopFrame(); X86Gp vReg = newTempInt32(); cc.mov(vReg, 0); cc.ret(vReg); @@ -283,6 +329,7 @@ void JitCompiler::EmitCheckForException() cc.mov(exceptResult, asmjit::x86::dword_ptr(exceptInfo, 0 * 4)); cc.cmp(exceptResult, (int)-1); cc.je(noexception); + EmitPopFrame(); asmjit::X86Gp vReg = newTempInt32(); cc.mov(vReg, 0); cc.ret(vReg); diff --git a/src/scripting/vm/jit_call.cpp b/src/scripting/vm/jit_call.cpp index 82c6d5ea3e..2f92d0a424 100644 --- a/src/scripting/vm/jit_call.cpp +++ b/src/scripting/vm/jit_call.cpp @@ -225,6 +225,7 @@ void JitCompiler::EmitDoTail(asmjit::X86Gp ptr) call->setArg(5, ret); call->setArg(6, exceptInfo); + EmitPopFrame(); cc.ret(result); NumParam -= B; diff --git a/src/scripting/vm/jit_flow.cpp b/src/scripting/vm/jit_flow.cpp index 3fec98ec51..da11b1222a 100644 --- a/src/scripting/vm/jit_flow.cpp +++ b/src/scripting/vm/jit_flow.cpp @@ -104,6 +104,7 @@ void JitCompiler::EmitRET() using namespace asmjit; if (B == REGT_NIL) { + EmitPopFrame(); X86Gp vReg = newTempInt32(); cc.mov(vReg, 0); cc.ret(vReg); @@ -215,12 +216,16 @@ void JitCompiler::EmitRET() if (a & RET_FINAL) { cc.add(reg_retnum, 1); + EmitPopFrame(); cc.ret(reg_retnum); } cc.bind(L_endif); if (a & RET_FINAL) + { + EmitPopFrame(); cc.ret(numret); + } } } @@ -245,12 +250,16 @@ void JitCompiler::EmitRETI() if (a & RET_FINAL) { cc.add(reg_retnum, 1); + EmitPopFrame(); cc.ret(reg_retnum); } cc.bind(L_endif); if (a & RET_FINAL) + { + EmitPopFrame(); cc.ret(numret); + } } void JitCompiler::EmitNEW() diff --git a/src/scripting/vm/jitintern.h b/src/scripting/vm/jitintern.h index f49b05f01c..44e03a2a1b 100644 --- a/src/scripting/vm/jitintern.h +++ b/src/scripting/vm/jitintern.h @@ -39,6 +39,7 @@ private: void Setup(); void EmitOpcode(); + void EmitPopFrame(); void EmitDoCall(asmjit::X86Gp ptr); void EmitDoTail(asmjit::X86Gp ptr); @@ -141,10 +142,12 @@ private: asmjit::X86Compiler cc; VMScriptFunction *sfunc; - asmjit::X86Gp stack; + asmjit::X86Gp args; + asmjit::X86Gp numargs; asmjit::X86Gp ret; asmjit::X86Gp numret; asmjit::X86Gp exceptInfo; + asmjit::X86Gp stack; int offsetExtra; asmjit::X86Gp vmframe; diff --git a/src/scripting/vm/vmframe.cpp b/src/scripting/vm/vmframe.cpp index 5157bf3773..805b6a2911 100644 --- a/src/scripting/vm/vmframe.cpp +++ b/src/scripting/vm/vmframe.cpp @@ -226,30 +226,17 @@ int VMScriptFunction::FirstScriptCall(VMScriptFunction *func, VMValue *params, i int VMScriptFunction::JitCall(VMScriptFunction *func, VMValue *params, int numparams, VMReturn *ret, int numret) { - VMFrameStack *stack = &GlobalVMStack; - VMFrame *newf = stack->AllocFrame(func); - VMFillParams(params, newf, numparams); - try + JitExceptionInfo exceptInfo; + exceptInfo.reason = -1; + int result = func->JitFunc(params, numparams, ret, numret, &exceptInfo); + if (exceptInfo.reason != -1) { - JitExceptionInfo exceptInfo; - exceptInfo.reason = -1; - int result = func->JitFunc(stack, ret, numret, &exceptInfo); - if (exceptInfo.reason != -1) - { - if (exceptInfo.cppException) - std::rethrow_exception(exceptInfo.cppException); - else - ThrowAbortException(func, exceptInfo.pcOnJitAbort, (EVMAbortException)exceptInfo.reason, nullptr); - } - return result; + if (exceptInfo.cppException) + std::rethrow_exception(exceptInfo.cppException); + else + ThrowAbortException(func, exceptInfo.pcOnJitAbort, (EVMAbortException)exceptInfo.reason, nullptr); } - catch (...) - { - stack->PopFrame(); - throw; - } - stack->PopFrame(); - return numret; + return result; } //=========================================================================== diff --git a/src/scripting/vm/vmintern.h b/src/scripting/vm/vmintern.h index 935695d7d5..a8a6105785 100644 --- a/src/scripting/vm/vmintern.h +++ b/src/scripting/vm/vmintern.h @@ -446,7 +446,7 @@ struct JitExceptionInfo std::exception_ptr cppException; }; -typedef int(*JitFuncPtr)(VMFrameStack *stack, VMReturn *ret, int numret, JitExceptionInfo *exceptInfo); +typedef int(*JitFuncPtr)(VMValue *params, int numparams, VMReturn *ret, int numret, JitExceptionInfo *exceptInfo); class VMScriptFunction : public VMFunction {