From 43c70cdf9dee5adf59be6b2bf0e59b57abc50206 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= <ricolvs123@gmail.com>
Date: Wed, 6 Dec 2023 19:12:50 -0300
Subject: [PATCH] JIT-Compile all functions during startup

---
 src/common/scripting/backend/vmbuilder.cpp | 12 +++++--
 src/common/scripting/vm/vmframe.cpp        | 39 +++++++++++++++-------
 src/common/scripting/vm/vmintern.h         |  2 ++
 3 files changed, 39 insertions(+), 14 deletions(-)

diff --git a/src/common/scripting/backend/vmbuilder.cpp b/src/common/scripting/backend/vmbuilder.cpp
index 259055dc9f..71a766d9a7 100644
--- a/src/common/scripting/backend/vmbuilder.cpp
+++ b/src/common/scripting/backend/vmbuilder.cpp
@@ -41,6 +41,9 @@
 
 CVAR(Bool, strictdecorate, false, CVAR_GLOBALCONFIG | CVAR_ARCHIVE)
 
+EXTERN_CVAR(Bool, vm_jit)
+EXTERN_CVAR(Bool, vm_jit_aot)
+
 struct VMRemap
 {
 	uint8_t altOp, kReg, kType;
@@ -928,6 +931,13 @@ void FFunctionBuildList::Build()
 				disasmdump.Write(sfunc, item.PrintableName);
 
 				sfunc->Unsafe = ctx.Unsafe;
+
+				#if HAVE_VM_JIT
+					if(vm_jit && vm_jit_aot)
+					{
+						sfunc->JitCompile();
+					}
+				#endif
 			}
 			catch (CRecoverableError &err)
 			{
@@ -1094,8 +1104,6 @@ void FunctionCallEmitter::AddParameterStringConst(const FString &konst)
 	});
 }
 
-EXTERN_CVAR(Bool, vm_jit)
-
 ExpEmit FunctionCallEmitter::EmitCall(VMFunctionBuilder *build, TArray<ExpEmit> *ReturnRegs)
 {
 	unsigned paramcount = 0;
diff --git a/src/common/scripting/vm/vmframe.cpp b/src/common/scripting/vm/vmframe.cpp
index a13829ddad..635bace633 100644
--- a/src/common/scripting/vm/vmframe.cpp
+++ b/src/common/scripting/vm/vmframe.cpp
@@ -54,8 +54,14 @@ CUSTOM_CVAR(Bool, vm_jit, true, CVAR_NOINITCALL)
 	Printf("You must restart " GAMENAME " for this change to take effect.\n");
 	Printf("This cvar is currently not saved. You must specify it on the command line.");
 }
+CUSTOM_CVAR(Bool, vm_jit_aot, true, CVAR_NOINITCALL)
+{
+	Printf("You must restart " GAMENAME " for this change to take effect.\n");
+	Printf("This cvar is currently not saved. You must specify it on the command line.");
+}
 #else
 CVAR(Bool, vm_jit, false, CVAR_NOINITCALL|CVAR_NOSET)
+CVAR(Bool, vm_jit_aot, false, CVAR_NOINITCALL|CVAR_NOSET)
 FString JitCaptureStackTrace(int framesToSkip, bool includeNativeFrames, int maxFrames) { return FString(); }
 void JitRelease() {}
 #endif
@@ -282,6 +288,25 @@ static bool CanJit(VMScriptFunction *func)
 	return false;
 }
 
+void VMScriptFunction::JitCompile()
+{
+	if(!(VarFlags & VARF_Abstract))
+	{
+	#ifdef HAVE_VM_JIT
+		if (vm_jit && CanJit(this))
+		{
+			ScriptCall = ::JitCompile(this);
+			if (!ScriptCall)
+				ScriptCall = VMExec;
+		}
+		else
+	#endif // HAVE_VM_JIT
+		{
+			ScriptCall = VMExec;
+		}
+	}
+}
+
 int VMScriptFunction::FirstScriptCall(VMFunction *func, VMValue *params, int numparams, VMReturn *ret, int numret)
 {
 	// [Player701] Check that we aren't trying to call an abstract function.
@@ -291,18 +316,8 @@ int VMScriptFunction::FirstScriptCall(VMFunction *func, VMValue *params, int num
 	{
 		ThrowAbortException(X_OTHER, "attempt to call abstract function %s.", func->PrintableName);
 	}
-#ifdef HAVE_VM_JIT
-	if (vm_jit && CanJit(static_cast<VMScriptFunction*>(func)))
-	{
-		func->ScriptCall = JitCompile(static_cast<VMScriptFunction*>(func));
-		if (!func->ScriptCall)
-			func->ScriptCall = VMExec;
-	}
-	else
-#endif // HAVE_VM_JIT
-	{
-		func->ScriptCall = VMExec;
-	}
+	
+	static_cast<VMScriptFunction*>(func)->JitCompile();
 
 	return func->ScriptCall(func, params, numparams, ret, numret);
 }
diff --git a/src/common/scripting/vm/vmintern.h b/src/common/scripting/vm/vmintern.h
index 9a3e2d4010..44fb534630 100644
--- a/src/common/scripting/vm/vmintern.h
+++ b/src/common/scripting/vm/vmintern.h
@@ -481,4 +481,6 @@ public:
 
 private:
 	static int FirstScriptCall(VMFunction *func, VMValue *params, int numparams, VMReturn *ret, int numret);
+	void JitCompile();
+	friend class FFunctionBuildList;
 };