From 172b3e8ab8cbe0399b0198d04df13431e8ce206e Mon Sep 17 00:00:00 2001 From: David Anderson Date: Mon, 23 Jul 2007 19:12:54 +0000 Subject: [PATCH] new jit api versioning scheme for amb398 --HG-- extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%401153 --- core/sourcemod.cpp | 82 ++++++++++++++++++++++-------- core/vm/sp_vm_engine.cpp | 5 ++ core/vm/sp_vm_engine.h | 1 + public/sourcepawn/sp_vm_api.h | 10 ++++ sourcepawn/jit/x86/dll_exports.cpp | 9 +++- 5 files changed, 84 insertions(+), 23 deletions(-) diff --git a/core/sourcemod.cpp b/core/sourcemod.cpp index 8fd8e83d..cf2998af 100644 --- a/core/sourcemod.cpp +++ b/core/sourcemod.cpp @@ -56,6 +56,7 @@ int g_StillFrames = 0; float g_StillTime = 0.0f; typedef int (*GIVEENGINEPOINTER)(ISourcePawnEngine *); +typedef int (*GIVEENGINEPOINTER2)(ISourcePawnEngine *, unsigned int api_version); typedef unsigned int (*GETEXPORTCOUNT)(); typedef IVirtualMachine *(*GETEXPORT)(unsigned int); typedef void (*NOTIFYSHUTDOWN)(); @@ -157,25 +158,43 @@ bool SourceModBase::InitializeSourceMod(char *error, size_t maxlength, bool late } int err; - GIVEENGINEPOINTER jit_init = (GIVEENGINEPOINTER)g_pJIT->GetSymbolAddress("GiveEnginePointer"); - if (!jit_init) + + GIVEENGINEPOINTER2 jit_init2 = (GIVEENGINEPOINTER2)g_pJIT->GetSymbolAddress("GiveEnginePointer2"); + if (!jit_init2) { - ShutdownJIT(); - if (error && maxlength) + GIVEENGINEPOINTER jit_init = (GIVEENGINEPOINTER)g_pJIT->GetSymbolAddress("GiveEnginePointer"); + if (!jit_init) { - snprintf(error, maxlength, "Failed to find GiveEnginePointer in JIT!"); + ShutdownJIT(); + if (error && maxlength) + { + snprintf(error, maxlength, "Failed to find GiveEnginePointer in JIT!"); + } + return false; } - return false; - } - if ((err=jit_init(g_pSourcePawn)) != 0) - { - ShutdownJIT(); - if (error && maxlength) + if ((err=jit_init(g_pSourcePawn)) != 0) { - snprintf(error, maxlength, "GiveEnginePointer returned %d in the JIT", err); + ShutdownJIT(); + if (error && maxlength) + { + snprintf(error, maxlength, "GiveEnginePointer returned %d in the JIT", err); + } + return false; + } + } else { + /* On version bumps, we should check for older versions as well, if the new version fails. + * We can then check the exports to see if any VM versions will be sufficient. + */ + if ((err=jit_init2(g_pSourcePawn, SOURCEPAWN_ENGINE_API_VERSION)) != SP_ERROR_NONE) + { + ShutdownJIT(); + if (error && maxlength) + { + snprintf(error, maxlength, "JIT incompatible with SourceMod version"); + } + return false; } - return false; } GETEXPORTCOUNT jit_getnum = (GETEXPORTCOUNT)g_pJIT->GetSymbolAddress("GetExportCount"); @@ -191,7 +210,7 @@ bool SourceModBase::InitializeSourceMod(char *error, size_t maxlength, bool late } unsigned int num = jit_getnum(); - if (!num || ((g_pVM=jit_get(0)) == NULL)) + if (!num) { ShutdownJIT(); if (error && maxlength) @@ -201,15 +220,36 @@ bool SourceModBase::InitializeSourceMod(char *error, size_t maxlength, bool late return false; } - unsigned int api = g_pVM->GetAPIVersion(); - /* :TODO: clean this up (see amb398) */ - if (api > SOURCEPAWN_VM_API_VERSION || api < 2) + unsigned int api_version; + for (unsigned int i=0; iGetAPIVersion(); + if (api_version < 3 || api_version > SOURCEPAWN_VM_API_VERSION) + { + if (error && maxlength) + { + snprintf(error, maxlength, "JIT is not a compatible version"); + } + g_pVM = NULL; + continue; + } + break; + } + + if (!g_pVM) { ShutdownJIT(); - if (error && maxlength) - { - snprintf(error, maxlength, "JIT is not a compatible version"); - } return false; } diff --git a/core/vm/sp_vm_engine.cpp b/core/vm/sp_vm_engine.cpp index 80219053..fe50287a 100644 --- a/core/vm/sp_vm_engine.cpp +++ b/core/vm/sp_vm_engine.cpp @@ -536,6 +536,11 @@ void SourcePawnEngine::PopTracer(int error, const char *msg) m_CurChain--; } +unsigned int SourcePawnEngine::GetEngineAPIVersion() +{ + return SOURCEPAWN_ENGINE_API_VERSION; +} + CContextTrace::CContextTrace(TracedCall *pStart, int error, const char *msg, uint32_t native) : m_Error(error), m_pMsg(msg), m_pStart(pStart), m_pIterator(pStart), m_Native(native) { diff --git a/core/vm/sp_vm_engine.h b/core/vm/sp_vm_engine.h index daa2ea70..0591cb1c 100644 --- a/core/vm/sp_vm_engine.h +++ b/core/vm/sp_vm_engine.h @@ -65,6 +65,7 @@ public: //ISourcePawnEngine void ExecFree(void *address); IDebugListener *SetDebugListener(IDebugListener *pListener); unsigned int GetContextCallCount(); + unsigned int GetEngineAPIVersion(); public: //Debugger Stuff /** * @brief Pushes a context onto the top of the call tracer. diff --git a/public/sourcepawn/sp_vm_api.h b/public/sourcepawn/sp_vm_api.h index 0d280dce..fbacefe9 100644 --- a/public/sourcepawn/sp_vm_api.h +++ b/public/sourcepawn/sp_vm_api.h @@ -27,6 +27,9 @@ #include #include "sp_vm_types.h" +/** SourcePawn Engine API Version */ +#define SOURCEPAWN_ENGINE_API_VERSION 1 + /** SourcePawn VM API Version */ #define SOURCEPAWN_VM_API_VERSION 3 @@ -730,6 +733,13 @@ namespace SourcePawn * @return Number of contexts in the call stack. */ virtual unsigned int GetContextCallCount() =0; + + /** + * @brief Returns the engine API version. + * + * @return Engine API version. + */ + virtual unsigned int GetEngineAPIVersion() =0; }; diff --git a/sourcepawn/jit/x86/dll_exports.cpp b/sourcepawn/jit/x86/dll_exports.cpp index 05fea4be..79fc61a9 100644 --- a/sourcepawn/jit/x86/dll_exports.cpp +++ b/sourcepawn/jit/x86/dll_exports.cpp @@ -20,11 +20,16 @@ SourcePawn::ISourcePawnEngine *engine = NULL; JITX86 g_jit; -EXPORTFUNC int GiveEnginePointer(SourcePawn::ISourcePawnEngine *engine_p) +EXPORTFUNC int GiveEnginePointer2(SourcePawn::ISourcePawnEngine *engine_p, unsigned int api_version) { engine = engine_p; - return 0; + if (api_version > SOURCEPAWN_ENGINE_API_VERSION) + { + return SP_ERROR_PARAM; + } + + return SP_ERROR_NONE; } EXPORTFUNC unsigned int GetExportCount()