diff --git a/core/msvc8/sourcemod_mm.vcproj b/core/msvc8/sourcemod_mm.vcproj
index b40d716c..a1f60a33 100644
--- a/core/msvc8/sourcemod_mm.vcproj
+++ b/core/msvc8/sourcemod_mm.vcproj
@@ -341,10 +341,6 @@
RelativePath="..\..\public\ILibrarySys.h"
>
-
-
@@ -372,10 +368,6 @@
-
-
@@ -408,10 +400,6 @@
-
-
@@ -456,6 +444,10 @@
RelativePath="..\vm\sp_vm_engine.h"
>
+
+
+
+
diff --git a/core/systems/ForwardSys.cpp b/core/systems/ForwardSys.cpp
index 6011cdcc..9465840a 100644
--- a/core/systems/ForwardSys.cpp
+++ b/core/systems/ForwardSys.cpp
@@ -71,7 +71,7 @@ void CForwardManager::OnPluginLoaded(IPlugin *plugin)
for (iter=m_managed.begin(); iter!=m_managed.end(); iter++)
{
fwd = (*iter);
- IPluginFunction *pFunc = plugin->GetFunctionByName(fwd->GetForwardName());
+ IPluginFunction *pFunc = plugin->GetBaseContext()->GetFunctionByName(fwd->GetForwardName());
if (pFunc)
{
fwd->AddFunction(pFunc);
@@ -256,7 +256,8 @@ int CForward::Execute(cell_t *result, IForwardFilter *filter)
for (iter=m_functions.begin(); iter!=m_functions.end(); iter++)
{
func = (*iter);
- if (func->GetParentPlugin()->GetStatus() == Plugin_Paused)
+ /* Ugh... */
+ if (!func->GetParentContext()->IsRunnable())
{
continue;
}
@@ -565,15 +566,10 @@ void CForward::Cancel()
m_errstate = SP_ERROR_NONE;
}
-bool CForward::AddFunction(sp_context_t *ctx, funcid_t index)
+bool CForward::AddFunction(IPluginContext *pContext, funcid_t index)
{
- IPlugin *pPlugin = g_PluginSys.FindPluginByContext(ctx);
- if (!pPlugin)
- {
- return false;
- }
+ IPluginFunction *pFunc = pContext->GetFunctionById(index);
- IPluginFunction *pFunc = pPlugin->GetFunctionById(index);
if (!pFunc)
{
return false;
@@ -614,10 +610,11 @@ unsigned int CForward::RemoveFunctionsOfPlugin(IPlugin *plugin)
FuncIter iter;
IPluginFunction *func;
unsigned int removed = 0;
+ IPluginContext *pContext = plugin->GetBaseContext();
for (iter=m_functions.begin(); iter!=m_functions.end();)
{
func = (*iter);
- if (func->GetParentPlugin() == plugin)
+ if (func->GetParentContext() == pContext)
{
iter = m_functions.erase(iter);
removed++;
diff --git a/core/systems/ForwardSys.h b/core/systems/ForwardSys.h
index 4748e9fb..617aaf03 100644
--- a/core/systems/ForwardSys.h
+++ b/core/systems/ForwardSys.h
@@ -50,7 +50,7 @@ public: //IChangeableForward
virtual bool RemoveFunction(IPluginFunction *func);
virtual unsigned int RemoveFunctionsOfPlugin(IPlugin *plugin);
virtual bool AddFunction(IPluginFunction *func);
- virtual bool AddFunction(sp_context_t *ctx, funcid_t index);
+ virtual bool AddFunction(IPluginContext *ctx, funcid_t index);
public:
static CForward *CreateForward(const char *name,
ExecType et,
diff --git a/core/systems/PluginSys.cpp b/core/systems/PluginSys.cpp
index 6528113e..fd82b260 100644
--- a/core/systems/PluginSys.cpp
+++ b/core/systems/PluginSys.cpp
@@ -23,9 +23,6 @@ CPlugin::CPlugin(const char *file)
m_status = Plugin_Uncompiled;
m_serial = ++MySerial;
m_plugin = NULL;
- m_funcsnum = 0;
- m_priv_funcs = NULL;
- m_pub_funcs = NULL;
m_errormsg[256] = '\0';
snprintf(m_filename, sizeof(m_filename), "%s", file);
m_handle = 0;
@@ -60,26 +57,6 @@ CPlugin::~CPlugin()
m_ctx.co = NULL;
}
- if (m_pub_funcs)
- {
- for (uint32_t i=0; iinfo.publics_num; i++)
- {
- g_PluginSys.ReleaseFunctionToPool(m_pub_funcs[i]);
- }
- delete [] m_pub_funcs;
- m_pub_funcs = NULL;
- }
-
- if (m_priv_funcs)
- {
- for (unsigned int i=0; iFreeFromMemory(m_plugin);
@@ -190,30 +167,9 @@ bool CPlugin::FinishMyCompile(char *error, size_t maxlength)
}
m_ctx.base = new BaseContext(m_ctx.ctx);
+ m_ctx.base->SetRunnable(false);
m_ctx.ctx->user[SM_CONTEXTVAR_MYSELF] = (void *)this;
- m_funcsnum = m_ctx.vm->FunctionCount(m_ctx.ctx);
-
- /**
- * Note: Since the m_plugin member will never change,
- * it is safe to assume the function count will never change
- */
- if (m_funcsnum && m_priv_funcs == NULL)
- {
- m_priv_funcs = new CFunction *[m_funcsnum];
- memset(m_priv_funcs, 0, sizeof(CFunction *) * m_funcsnum);
- } else {
- m_priv_funcs = NULL;
- }
-
- if (m_plugin->info.publics_num && m_pub_funcs == NULL)
- {
- m_pub_funcs = new CFunction *[m_plugin->info.publics_num];
- memset(m_pub_funcs, 0, sizeof(CFunction *) * m_plugin->info.publics_num);
- } else {
- m_pub_funcs = NULL;
- }
-
m_status = Plugin_Created;
m_ctx.co = NULL;
@@ -230,67 +186,11 @@ void CPlugin::SetErrorState(PluginStatus status, const char *error_fmt, ...)
va_start(ap, error_fmt);
vsnprintf(m_errormsg, sizeof(m_errormsg), error_fmt, ap);
va_end(ap);
-}
-IPluginFunction *CPlugin::GetFunctionById(funcid_t func_id)
-{
- CFunction *pFunc = NULL;
- funcid_t save = func_id;
-
- if (func_id & 1)
+ if (m_ctx.base)
{
- func_id >>= 1;
- if (func_id >= m_plugin->info.publics_num)
- {
- return NULL;
- }
- pFunc = m_pub_funcs[func_id];
- if (!pFunc)
- {
- pFunc = g_PluginSys.GetFunctionFromPool(save, this);
- m_pub_funcs[func_id] = pFunc;
- }
- } else {
- func_id >>= 1;
- unsigned int index;
- if (!g_pVM->FunctionLookup(m_ctx.ctx, func_id, &index))
- {
- return NULL;
- }
- pFunc = m_priv_funcs[func_id];
- if (!pFunc)
- {
- pFunc = g_PluginSys.GetFunctionFromPool(save, this);
- m_priv_funcs[func_id] = pFunc;
- }
+ m_ctx.base->SetRunnable(false);
}
-
- return pFunc;
-}
-
-IPluginFunction *CPlugin::GetFunctionByName(const char *public_name)
-{
- uint32_t index;
- IPluginContext *base = m_ctx.base;
-
- if (base->FindPublicByName(public_name, &index) != SP_ERROR_NONE)
- {
- return NULL;
- }
-
- CFunction *pFunc = m_pub_funcs[index];
- if (!pFunc)
- {
- sp_public_t *pub = NULL;
- base->GetPublicByIndex(index, &pub);
- if (pub)
- {
- pFunc = g_PluginSys.GetFunctionFromPool(pub->funcid, this);
- m_pub_funcs[index] = pFunc;
- }
- }
-
- return pFunc;
}
void CPlugin::UpdateInfo()
@@ -338,7 +238,7 @@ void CPlugin::Call_OnPluginInit()
m_status = Plugin_Running;
cell_t result;
- IPluginFunction *pFunction = GetFunctionByName("OnPluginInit");
+ IPluginFunction *pFunction = m_ctx.base->GetFunctionByName("OnPluginInit");
if (!pFunction)
{
return;
@@ -356,7 +256,7 @@ void CPlugin::Call_OnPluginUnload()
}
cell_t result;
- IPluginFunction *pFunction = GetFunctionByName("OnPluginUnload");
+ IPluginFunction *pFunction = m_ctx.base->GetFunctionByName("OnPluginUnload");
if (!pFunction)
{
return;
@@ -373,10 +273,11 @@ bool CPlugin::Call_AskPluginLoad(char *error, size_t maxlength)
}
m_status = Plugin_Loaded;
+ m_ctx.base->SetRunnable(true);
int err;
cell_t result;
- IPluginFunction *pFunction = GetFunctionByName("AskPluginLoad");
+ IPluginFunction *pFunction = m_ctx.base->GetFunctionByName("AskPluginLoad");
if (!pFunction)
{
@@ -389,13 +290,11 @@ bool CPlugin::Call_AskPluginLoad(char *error, size_t maxlength)
pFunction->PushCell(maxlength);
if ((err=pFunction->Execute(&result)) != SP_ERROR_NONE)
{
- m_status = Plugin_Failed;
return false;
}
if (!result || m_status != Plugin_Loaded)
{
- m_status = Plugin_Failed;
return false;
}
@@ -463,7 +362,7 @@ bool CPlugin::SetPauseState(bool paused)
m_status = (paused) ? Plugin_Paused : Plugin_Running;
- IPluginFunction *pFunction = GetFunctionByName("OnPluginPauseChange");
+ IPluginFunction *pFunction = m_ctx.base->GetFunctionByName("OnPluginPauseChange");
if (pFunction)
{
cell_t result;
@@ -756,7 +655,6 @@ bool CPluginManager::_LoadPlugin(CPlugin **_plugin, const char *path, bool debug
snprintf(error, err_max, "Unable to set JIT option (key \"%s\") (value \"%s\")", key, val);
}
pPlugin->CancelMyCompile();
- pPlugin->m_status = Plugin_Failed;
co = NULL;
break;
}
@@ -932,7 +830,6 @@ bool CPluginManager::LoadOrRequireExtensions(CPlugin *pPlugin, unsigned int pass
{
snprintf(error, maxlength, "Required extension \"%s\" file(\"%s\") not running", name, file);
}
- pPlugin->m_status = Plugin_Failed;
return false;
} else {
g_Extensions.BindChildPlugin(pExt, pPlugin);
@@ -1091,29 +988,6 @@ void CPluginManager::ReleaseIterator(CPluginIterator *iter)
m_iters.push(iter);
}
-void CPluginManager::ReleaseFunctionToPool(CFunction *func)
-{
- if (!func)
- {
- return;
- }
- func->Cancel();
- m_funcpool.push(func);
-}
-
-CFunction *CPluginManager::GetFunctionFromPool(funcid_t f, CPlugin *plugin)
-{
- if (m_funcpool.empty())
- {
- return new CFunction(f, plugin);
- } else {
- CFunction *func = m_funcpool.front();
- m_funcpool.pop();
- func->Set(f, plugin);
- return func;
- }
-}
-
bool CPluginManager::TestAliasMatch(const char *alias, const char *localpath)
{
/* As an optimization, we do not call strlen, but compute the length in the first pass */
diff --git a/core/systems/PluginSys.h b/core/systems/PluginSys.h
index 5e804503..fa4930eb 100644
--- a/core/systems/PluginSys.h
+++ b/core/systems/PluginSys.h
@@ -8,7 +8,6 @@
#include
#include "sm_globals.h"
#include "vm/sp_vm_basecontext.h"
-#include "CFunction.h"
#include "PluginInfoDatabase.h"
#include "sm_trie.h"
#include "sourcemod.h"
@@ -93,8 +92,6 @@ public:
virtual bool SetPauseState(bool paused);
virtual unsigned int GetSerial() const;
virtual const sp_plugin_t *GetPluginStructure() const;
- virtual IPluginFunction *GetFunctionByName(const char *public_name);
- virtual IPluginFunction *GetFunctionById(funcid_t func_id);
virtual IdentityToken_t *GetIdentity() const;
public:
/**
@@ -174,9 +171,6 @@ private:
unsigned int m_serial;
sm_plugininfo_t m_info;
sp_plugin_t *m_plugin;
- unsigned int m_funcsnum;
- CFunction **m_priv_funcs;
- CFunction **m_pub_funcs;
char m_errormsg[256];
time_t m_LastAccess;
IdentityToken_t *m_ident;
@@ -312,8 +306,6 @@ protected:
* Caching internal objects
*/
void ReleaseIterator(CPluginIterator *iter);
- CFunction *GetFunctionFromPool(funcid_t f, CPlugin *plugin);
- void ReleaseFunctionToPool(CFunction *func);
inline IdentityToken_t *GetIdentity()
{
return m_MyIdent;
@@ -323,7 +315,6 @@ private:
List m_plugins;
List m_natives;
CStack m_iters;
- CStack m_funcpool;
CPluginInfoDatabase m_PluginInfo;
Trie *m_LoadLookup;
bool m_AllPluginsLoaded;
diff --git a/core/vm/sp_vm_basecontext.cpp b/core/vm/sp_vm_basecontext.cpp
index fecfe427..96b6a7fe 100644
--- a/core/vm/sp_vm_basecontext.cpp
+++ b/core/vm/sp_vm_basecontext.cpp
@@ -27,6 +27,60 @@ BaseContext::BaseContext(sp_context_t *_ctx)
ctx->dbreak = GlobalDebugBreak;
m_InExec = false;
m_CustomMsg = false;
+ m_Runnable = true;
+ m_funcsnum = ctx->vmbase->FunctionCount(ctx);
+ m_priv_funcs = NULL;
+ m_pub_funcs = NULL;
+
+ /**
+ * Note: Since the m_plugin member will never change,
+ * it is safe to assume the function count will never change
+ */
+ if (m_funcsnum && m_priv_funcs == NULL)
+ {
+ m_priv_funcs = new CFunction *[m_funcsnum];
+ memset(m_priv_funcs, 0, sizeof(CFunction *) * m_funcsnum);
+ } else {
+ m_priv_funcs = NULL;
+ }
+
+ if (ctx->plugin->info.publics_num && m_pub_funcs == NULL)
+ {
+ m_pub_funcs = new CFunction *[ctx->plugin->info.publics_num];
+ memset(m_pub_funcs, 0, sizeof(CFunction *) * ctx->plugin->info.publics_num);
+ } else {
+ m_pub_funcs = NULL;
+ }
+}
+
+void BaseContext::FlushFunctionCache()
+{
+ if (m_pub_funcs)
+ {
+ for (uint32_t i=0; iplugin->info.publics_num; i++)
+ {
+ delete m_pub_funcs[i];
+ m_pub_funcs[i] = NULL;
+ }
+ }
+
+ if (m_priv_funcs)
+ {
+ for (unsigned int i=0; icontext = this;
+ ctx->dbreak = GlobalDebugBreak;
+ FlushFunctionCache();
}
IVirtualMachine *BaseContext::GetVirtualMachine()
@@ -73,6 +130,11 @@ IPluginDebugInfo *BaseContext::GetDebugInfo()
int BaseContext::Execute(funcid_t funcid, cell_t *result)
{
+ if (!m_Runnable)
+ {
+ return SP_ERROR_NOT_RUNNABLE;
+ }
+
IVirtualMachine *vm = (IVirtualMachine *)ctx->vmbase;
uint32_t pushcount = ctx->pushcount;
@@ -794,6 +856,63 @@ int BaseContext::LookupLine(ucell_t addr, uint32_t *line)
return SP_ERROR_NONE;
}
+IPluginFunction *BaseContext::GetFunctionById(funcid_t func_id)
+{
+ CFunction *pFunc = NULL;
+ funcid_t save = func_id;
+
+ if (func_id & 1)
+ {
+ func_id >>= 1;
+ if (func_id >= ctx->plugin->info.publics_num)
+ {
+ return NULL;
+ }
+ pFunc = m_pub_funcs[func_id];
+ if (!pFunc)
+ {
+ m_pub_funcs[func_id] = new CFunction(save, this);
+ }
+ } else {
+ func_id >>= 1;
+ unsigned int index;
+ if (!g_pVM->FunctionLookup(ctx, func_id, &index))
+ {
+ return NULL;
+ }
+ pFunc = m_priv_funcs[func_id];
+ if (!pFunc)
+ {
+ m_priv_funcs[func_id] = new CFunction(save, this);
+ }
+ }
+
+ return pFunc;
+}
+
+IPluginFunction *BaseContext::GetFunctionByName(const char *public_name)
+{
+ uint32_t index;
+
+ if (FindPublicByName(public_name, &index) != SP_ERROR_NONE)
+ {
+ return NULL;
+ }
+
+ CFunction *pFunc = m_pub_funcs[index];
+ if (!pFunc)
+ {
+ sp_public_t *pub = NULL;
+ GetPublicByIndex(index, &pub);
+ if (pub)
+ {
+ m_pub_funcs[index] = new CFunction(pub->funcid, this);
+ }
+ }
+
+ return pFunc;
+}
+
#if defined SOURCEMOD_BUILD
SourceMod::IdentityToken_t *BaseContext::GetIdentity()
{
@@ -804,4 +923,14 @@ void BaseContext::SetIdentity(SourceMod::IdentityToken_t *token)
{
m_pToken = token;
}
+
+bool BaseContext::IsRunnable()
+{
+ return m_Runnable;
+}
+
+void BaseContext::SetRunnable(bool runnable)
+{
+ m_Runnable = runnable;
+}
#endif
diff --git a/core/vm/sp_vm_basecontext.h b/core/vm/sp_vm_basecontext.h
index f755335e..d2625686 100644
--- a/core/vm/sp_vm_basecontext.h
+++ b/core/vm/sp_vm_basecontext.h
@@ -2,6 +2,11 @@
#define _INCLUDE_SOURCEPAWN_BASECONTEXT_H_
#include "sp_vm_api.h"
+#include "sp_vm_function.h"
+
+/**
+ * :TODO: Make functions allocate as a lump instead of individual allocations!
+ */
namespace SourcePawn
{
@@ -11,6 +16,7 @@ namespace SourcePawn
{
public:
BaseContext(sp_context_t *ctx);
+ ~BaseContext();
public: //IPluginContext
IVirtualMachine *GetVirtualMachine();
sp_context_t *GetContext();
@@ -44,9 +50,13 @@ namespace SourcePawn
virtual int Execute(funcid_t funcid, cell_t *result);
virtual void ThrowNativeErrorEx(int error, const char *msg, ...);
virtual cell_t ThrowNativeError(const char *msg, ...);
+ virtual IPluginFunction *GetFunctionByName(const char *public_name);
+ virtual IPluginFunction *GetFunctionById(funcid_t func_id);
#if defined SOURCEMOD_BUILD
virtual SourceMod::IdentityToken_t *GetIdentity();
void SetIdentity(SourceMod::IdentityToken_t *token);
+ bool IsRunnable();
+ void SetRunnable(bool runnable);
#endif
public: //IPluginDebugInfo
virtual int LookupFile(ucell_t addr, const char **filename);
@@ -56,6 +66,7 @@ namespace SourcePawn
void SetContext(sp_context_t *_ctx);
private:
void SetErrorMessage(const char *msg, va_list ap);
+ void FlushFunctionCache();
private:
sp_context_t *ctx;
#if defined SOURCEMOD_BUILD
@@ -64,6 +75,10 @@ namespace SourcePawn
char m_MsgCache[1024];
bool m_CustomMsg;
bool m_InExec;
+ bool m_Runnable;
+ unsigned int m_funcsnum;
+ CFunction **m_priv_funcs;
+ CFunction **m_pub_funcs;
};
};
diff --git a/core/vm/sp_vm_engine.cpp b/core/vm/sp_vm_engine.cpp
index cb6cf700..e39e0e52 100644
--- a/core/vm/sp_vm_engine.cpp
+++ b/core/vm/sp_vm_engine.cpp
@@ -53,6 +53,9 @@ SourcePawnEngine::SourcePawnEngine()
m_CallStack = NULL;
m_FreedCalls = NULL;
m_CurChain = 0;
+#if 0
+ m_pFreeFuncs = NULL;
+#endif
}
SourcePawnEngine::~SourcePawnEngine()
@@ -66,6 +69,16 @@ SourcePawnEngine::~SourcePawnEngine()
delete m_FreedCalls;
m_FreedCalls = pTemp;
}
+
+#if 0
+ CFunction *pNext;
+ while (m_pFreeFuncs)
+ {
+ pNext = m_pFreeFuncs->m_pNext;
+ delete m_pFreeFuncs;
+ m_pFreeFuncs = pNext;
+ }
+#endif
}
void *SourcePawnEngine::ExecAlloc(size_t size)
@@ -356,6 +369,32 @@ int SourcePawnEngine::FreeFromMemory(sp_plugin_t *plugin)
return SP_ERROR_NONE;
}
+#if 0
+void SourcePawnEngine::ReleaseFunctionToPool(CFunction *func)
+{
+ if (!func)
+ {
+ return;
+ }
+ func->Cancel();
+ func->m_pNext = m_pFreeFuncs;
+ m_pFreeFuncs = func;
+}
+
+CFunction *SourcePawnEngine::GetFunctionFromPool(funcid_t f, IPluginContext *plugin)
+{
+ if (!m_pFreeFuncs)
+ {
+ return new CFunction(f, plugin);
+ } else {
+ CFunction *pFunc = m_pFreeFuncs;
+ m_pFreeFuncs = m_pFreeFuncs->m_pNext;
+ pFunc->Set(f, plugin);
+ return pFunc;
+ }
+}
+#endif
+
IDebugListener *SourcePawnEngine::SetDebugListener(IDebugListener *pListener)
{
IDebugListener *old = m_pDebugHook;
diff --git a/core/vm/sp_vm_engine.h b/core/vm/sp_vm_engine.h
index ca0ac7f3..4ad0f715 100644
--- a/core/vm/sp_vm_engine.h
+++ b/core/vm/sp_vm_engine.h
@@ -2,83 +2,85 @@
#define _INCLUDE_SOURCEPAWN_VM_ENGINE_H_
#include "sp_vm_api.h"
+#include "sp_vm_function.h"
-namespace SourcePawn
+struct TracedCall
{
- struct TracedCall
- {
- uint32_t cip;
- uint32_t frm;
- sp_context_t *ctx;
- TracedCall *next;
- unsigned int chain;
- };
+ uint32_t cip;
+ uint32_t frm;
+ sp_context_t *ctx;
+ TracedCall *next;
+ unsigned int chain;
+};
- class CContextTrace : public IContextTrace
- {
- public:
- CContextTrace(TracedCall *pStart, int error, const char *msg, uint32_t native);
- public:
- virtual int GetErrorCode();
- virtual const char *GetErrorString();
- virtual bool DebugInfoAvailable();
- virtual const char *GetCustomErrorString();
- virtual bool GetTraceInfo(CallStackInfo *trace);
- virtual void ResetTrace();
- virtual const char *GetLastNative(uint32_t *index);
- private:
- TracedCall *m_pStart;
- TracedCall *m_pIterator;
- const char *m_pMsg;
- int m_Error;
- uint32_t m_Native;
- };
+class CContextTrace : public IContextTrace
+{
+public:
+ CContextTrace(TracedCall *pStart, int error, const char *msg, uint32_t native);
+public:
+ virtual int GetErrorCode();
+ virtual const char *GetErrorString();
+ virtual bool DebugInfoAvailable();
+ virtual const char *GetCustomErrorString();
+ virtual bool GetTraceInfo(CallStackInfo *trace);
+ virtual void ResetTrace();
+ virtual const char *GetLastNative(uint32_t *index);
+private:
+ TracedCall *m_pStart;
+ TracedCall *m_pIterator;
+ const char *m_pMsg;
+ int m_Error;
+ uint32_t m_Native;
+};
- class SourcePawnEngine : public ISourcePawnEngine
- {
- public:
- SourcePawnEngine();
- ~SourcePawnEngine();
- public: //ISourcePawnEngine
- sp_plugin_t *LoadFromFilePointer(FILE *fp, int *err);
- sp_plugin_t *LoadFromMemory(void *base, sp_plugin_t *plugin, int *err);
- int FreeFromMemory(sp_plugin_t *plugin);
- IPluginContext *CreateBaseContext(sp_context_t *ctx);
- void FreeBaseContext(IPluginContext *ctx);
- void *BaseAlloc(size_t size);
- void BaseFree(void *memory);
- void *ExecAlloc(size_t size);
- void ExecFree(void *address);
- IDebugListener *SetDebugListener(IDebugListener *pListener);
- unsigned int GetContextCallCount();
- public: //Debugger Stuff
- /**
- * @brief Pushes a context onto the top of the call tracer.
- *
- * @param ctx Plugin context.
- */
- void PushTracer(sp_context_t *ctx);
+class SourcePawnEngine : public ISourcePawnEngine
+{
+public:
+ SourcePawnEngine();
+ ~SourcePawnEngine();
+public: //ISourcePawnEngine
+ sp_plugin_t *LoadFromFilePointer(FILE *fp, int *err);
+ sp_plugin_t *LoadFromMemory(void *base, sp_plugin_t *plugin, int *err);
+ int FreeFromMemory(sp_plugin_t *plugin);
+ IPluginContext *CreateBaseContext(sp_context_t *ctx);
+ void FreeBaseContext(IPluginContext *ctx);
+ void *BaseAlloc(size_t size);
+ void BaseFree(void *memory);
+ void *ExecAlloc(size_t size);
+ void ExecFree(void *address);
+ IDebugListener *SetDebugListener(IDebugListener *pListener);
+ unsigned int GetContextCallCount();
+public: //Debugger Stuff
+ /**
+ * @brief Pushes a context onto the top of the call tracer.
+ *
+ * @param ctx Plugin context.
+ */
+ void PushTracer(sp_context_t *ctx);
- /**
- * @brief Pops a plugin off the call tracer.
- */
- void PopTracer(int error, const char *msg);
+ /**
+ * @brief Pops a plugin off the call tracer.
+ */
+ void PopTracer(int error, const char *msg);
- /**
- * @brief Runs tracer from a debug break.
- */
- void RunTracer(sp_context_t *ctx, uint32_t frame, uint32_t codeip);
- private:
- TracedCall *MakeTracedCall(bool new_chain);
- void FreeTracedCall(TracedCall *pCall);
- private:
- IDebugListener *m_pDebugHook;
- TracedCall *m_FreedCalls;
- TracedCall *m_CallStack;
- unsigned int m_CurChain;
- };
+ /**
+ * @brief Runs tracer from a debug break.
+ */
+ void RunTracer(sp_context_t *ctx, uint32_t frame, uint32_t codeip);
+public: //Plugin function stuff
+ CFunction *GetFunctionFromPool(funcid_t f, IPluginContext *plugin);
+ void ReleaseFunctionToPool(CFunction *func);
+private:
+ TracedCall *MakeTracedCall(bool new_chain);
+ void FreeTracedCall(TracedCall *pCall);
+private:
+ IDebugListener *m_pDebugHook;
+ TracedCall *m_FreedCalls;
+ TracedCall *m_CallStack;
+ unsigned int m_CurChain;
+ //CFunction *m_pFreeFuncs;
};
#endif //_INCLUDE_SOURCEPAWN_VM_ENGINE_H_
diff --git a/core/systems/CFunction.cpp b/core/vm/sp_vm_function.cpp
similarity index 76%
rename from core/systems/CFunction.cpp
rename to core/vm/sp_vm_function.cpp
index 6f123518..523a85a3 100644
--- a/core/systems/CFunction.cpp
+++ b/core/vm/sp_vm_function.cpp
@@ -5,33 +5,31 @@
* FUNCTION CALLING *
********************/
-void CFunction::Set(funcid_t funcid, CPlugin *plugin)
+void CFunction::Set(funcid_t funcid, IPluginContext *plugin)
{
m_funcid = funcid;
- m_pPlugin = plugin;
+ m_pContext = plugin;
m_curparam = 0;
m_errorstate = SP_ERROR_NONE;
}
int CFunction::CallFunction(const cell_t *params, unsigned int num_params, cell_t *result)
{
- IPluginContext *ctx = m_pPlugin->m_ctx.base;
-
while (num_params--)
{
- ctx->PushCell(params[num_params]);
+ m_pContext->PushCell(params[num_params]);
}
- return ctx->Execute(m_funcid, result);
+ return m_pContext->Execute(m_funcid, result);
}
-IPlugin *CFunction::GetParentPlugin()
+IPluginContext *CFunction::GetParentContext()
{
- return m_pPlugin;
+ return m_pContext;
}
-CFunction::CFunction(funcid_t funcid, CPlugin *plugin) :
- m_funcid(funcid), m_pPlugin(plugin), m_curparam(0),
+CFunction::CFunction(funcid_t funcid, IPluginContext *plugin) :
+ m_funcid(funcid), m_pContext(plugin), m_curparam(0),
m_errorstate(SP_ERROR_NONE)
{
}
@@ -79,11 +77,10 @@ int CFunction::PushArray(cell_t *inarray, unsigned int cells, cell_t **phys_addr
return SetError(SP_ERROR_PARAMS_MAX);
}
- IPluginContext *ctx = m_pPlugin->m_ctx.base;
ParamInfo *info = &m_info[m_curparam];
int err;
- if ((err=ctx->HeapAlloc(cells, &info->local_addr, &info->phys_addr)) != SP_ERROR_NONE)
+ if ((err=m_pContext->HeapAlloc(cells, &info->local_addr, &info->phys_addr)) != SP_ERROR_NONE)
{
return SetError(err);
}
@@ -127,12 +124,11 @@ int CFunction::_PushString(const char *string, int sz_flags, int cp_flags, size_
return SetError(SP_ERROR_PARAMS_MAX);
}
- IPluginContext *base = m_pPlugin->m_ctx.base;
ParamInfo *info = &m_info[m_curparam];
size_t cells = (len + sizeof(cell_t) - 1) / sizeof(cell_t);
int err;
- if ((err=base->HeapAlloc(cells, &info->local_addr, &info->phys_addr)) != SP_ERROR_NONE)
+ if ((err=m_pContext->HeapAlloc(cells, &info->local_addr, &info->phys_addr)) != SP_ERROR_NONE)
{
return SetError(err);
}
@@ -148,12 +144,12 @@ int CFunction::_PushString(const char *string, int sz_flags, int cp_flags, size_
if (sz_flags & SM_PARAM_STRING_UTF8)
{
- if ((err=base->StringToLocalUTF8(info->local_addr, len, string, NULL)) != SP_ERROR_NONE)
+ if ((err=m_pContext->StringToLocalUTF8(info->local_addr, len, string, NULL)) != SP_ERROR_NONE)
{
return SetError(err);
}
} else {
- if ((err=base->StringToLocal(info->local_addr, len, string)) != SP_ERROR_NONE)
+ if ((err=m_pContext->StringToLocal(info->local_addr, len, string)) != SP_ERROR_NONE)
{
return SetError(err);
}
@@ -174,13 +170,11 @@ void CFunction::Cancel()
return;
}
- IPluginContext *base = m_pPlugin->m_ctx.base;
-
while (m_curparam--)
{
if (m_info[m_curparam].marked)
{
- base->HeapRelease(m_info[m_curparam].local_addr);
+ m_pContext->HeapRelease(m_info[m_curparam].local_addr);
m_info[m_curparam].marked = false;
}
}
@@ -217,8 +211,6 @@ int CFunction::Execute(cell_t *result)
docopies = false;
}
- IPluginContext *base = m_pPlugin->m_ctx.base;
-
while (numparams--)
{
if (!temp_info[numparams].marked)
@@ -239,7 +231,7 @@ int CFunction::Execute(cell_t *result)
}
}
}
- base->HeapPop(temp_info[numparams].local_addr);
+ m_pContext->HeapPop(temp_info[numparams].local_addr);
temp_info[numparams].marked = false;
}
diff --git a/core/vm/sp_vm_function.h b/core/vm/sp_vm_function.h
new file mode 100644
index 00000000..ad688c1c
--- /dev/null
+++ b/core/vm/sp_vm_function.h
@@ -0,0 +1,55 @@
+#ifndef _INCLUDE_SOURCEMOD_BASEFUNCTION_H_
+#define _INCLUDE_SOURCEMOD_BASEFUNCTION_H_
+
+#include "sm_globals.h"
+
+struct ParamInfo
+{
+ int flags; /* Copy-back flags */
+ bool marked; /* Whether this is marked as being used */
+ cell_t local_addr; /* Local address to free */
+ cell_t *phys_addr; /* Physical address of our copy */
+ cell_t *orig_addr; /* Original address to copy back to */
+ ucell_t size; /* Size of array in bytes */
+};
+
+class CPlugin;
+
+class CFunction : public IPluginFunction
+{
+ friend class SourcePawnEngine;
+public:
+ CFunction(funcid_t funcid, IPluginContext *pContext);
+public:
+ virtual int PushCell(cell_t cell);
+ virtual int PushCellByRef(cell_t *cell, int flags);
+ virtual int PushFloat(float number);
+ virtual int PushFloatByRef(float *number, int flags);
+ virtual int PushArray(cell_t *inarray, unsigned int cells, cell_t **phys_addr, int copyback);
+ virtual int PushString(const char *string);
+ virtual int PushStringEx(char *buffer, size_t length, int sz_flags, int cp_flags);
+ virtual cell_t *GetAddressOfPushedParam(unsigned int param);
+ virtual int Execute(cell_t *result);
+ virtual void Cancel();
+ virtual int CallFunction(const cell_t *params, unsigned int num_params, cell_t *result);
+ virtual IPluginContext *GetParentContext();
+public:
+ void Set(funcid_t funcid, IPluginContext *plugin);
+private:
+ int _PushString(const char *string, int sz_flags, int cp_flags, size_t len);
+ inline int SetError(int err)
+ {
+ m_errorstate = err;
+ return err;
+ }
+private:
+ funcid_t m_funcid;
+ IPluginContext *m_pContext;
+ cell_t m_params[SP_MAX_EXEC_PARAMS];
+ ParamInfo m_info[SP_MAX_EXEC_PARAMS];
+ unsigned int m_curparam;
+ int m_errorstate;
+ CFunction *m_pNext;
+};
+
+#endif //_INCLUDE_SOURCEMOD_BASEFUNCTION_H_
diff --git a/public/IForwardSys.h b/public/IForwardSys.h
index d4732899..bd023adc 100644
--- a/public/IForwardSys.h
+++ b/public/IForwardSys.h
@@ -3,7 +3,9 @@
#include
#include
-#include
+#include
+
+using namespace SourcePawn;
#define SMINTERFACE_FORWARDMANAGER_NAME "IForwardManager"
#define SMINTERFACE_FORWARDMANAGER_VERSION 1
@@ -190,7 +192,7 @@ namespace SourceMod
* @param funcid Function id to add.
* @return True on success, otherwise false.
*/
- virtual bool AddFunction(sp_context_t *ctx, funcid_t index) =0;
+ virtual bool AddFunction(IPluginContext *ctx, funcid_t index) =0;
};
#define SP_PARAMTYPE_ANY 0
diff --git a/public/IPluginFunction.h b/public/IPluginFunction.h
deleted file mode 100644
index 7174baf6..00000000
--- a/public/IPluginFunction.h
+++ /dev/null
@@ -1,153 +0,0 @@
-#ifndef _INCLUDE_SOURCEMOD_PLUGINFUNCTION_INTERFACE_H_
-#define _INCLUDE_SOURCEMOD_PLUGINFUNCTION_INTERFACE_H_
-
-#include
-
-namespace SourceMod
-{
- #define SM_PARAM_COPYBACK (1<<0) /* Copy an array/reference back after call */
-
- #define SM_PARAM_STRING_UTF8 (1<<0) /* String should be UTF-8 handled */
- #define SM_PARAM_STRING_COPY (1<<1) /* String should be copied into the plugin */
-
- /**
- * @brief Represents what a function needs to implement in order to be callable.
- */
- class ICallable
- {
- public:
- /**
- * @brief Pushes a cell onto the current call.
- *
- * @param cell Parameter value to push.
- * @return Error code, if any.
- */
- virtual int PushCell(cell_t cell) =0;
-
- /**
- * @brief Pushes a cell by reference onto the current call.
- * NOTE: On Execute, the pointer passed will be modified if copyback is enabled.
- * NOTE: By reference parameters are cached and thus are not read until execution.
- * This means you cannot push a pointer, change it, and push it again and expect
- * two different values to come out.
- *
- * @param cell Address containing parameter value to push.
- * @param flags Copy-back flags.
- * @return Error code, if any.
- */
- virtual int PushCellByRef(cell_t *cell, int flags) =0;
-
- /**
- * @brief Pushes a float onto the current call.
- *
- * @param float Parameter value to push.
- * @return Error code, if any.
- */
- virtual int PushFloat(float number) =0;
-
- /**
- * @brief Pushes a float onto the current call by reference.
- * NOTE: On Execute, the pointer passed will be modified if copyback is enabled.
- * NOTE: By reference parameters are cached and thus are not read until execution.
- * This means you cannot push a pointer, change it, and push it again and expect
- * two different values to come out.
- *
- * @param float Parameter value to push.
- & @param flags Copy-back flags.
- * @return Error code, if any.
- */
- virtual int PushFloatByRef(float *number, int flags) =0;
-
- /**
- * @brief Pushes an array of cells onto the current call.
- * NOTE: On Execute, the pointer passed will be modified if non-NULL and copy-back
- * is enabled.
- * NOTE: By reference parameters are cached and thus are not read until execution.
- * This means you cannot push a pointer, change it, and push it again and expect
- * two different values to come out.
- *
- * @param inarray Array to copy, NULL if no initial array should be copied.
- * @param cells Number of cells to allocate and optionally read from the input array.
- * @param phys_addr Optional return address for physical array, if one was made.
- * @param flags Whether or not changes should be copied back to the input array.
- * @return Error code, if any.
- */
- virtual int PushArray(cell_t *inarray,
- unsigned int cells,
- cell_t **phys_addr,
- int flags=0) =0;
-
- /**
- * @brief Pushes a string onto the current call.
- *
- * @param string String to push.
- * @return Error code, if any.
- */
- virtual int PushString(const char *string) =0;
-
- /**
- * @brief Pushes a string or string buffer.
- * NOTE: On Execute, the pointer passed will be modified if copy-back is enabled.
- *
- * @param buffer Pointer to string buffer.
- * @param length Length of buffer.
- * @param sz_flags String flags.
- * @param cp_flags Copy-back flags.
- * @return Error code, if any.
- */
- virtual int PushStringEx(char *buffer, size_t length, int sz_flags, int cp_flags) =0;
-
- /**
- * @brief Cancels a function call that is being pushed but not yet executed.
- * This can be used be reset for CallFunction() use.
- */
- virtual void Cancel() =0;
- };
-
- /**
- * @brief Encapsulates a function call in a plugin.
- * NOTE: Function calls must be atomic to one execution context.
- * NOTE: This object should not be deleted. It lives for the lifetime of the plugin.
- */
- class IPluginFunction : public ICallable
- {
- public:
- /**
- * @brief Executes the forward, resets the pushed parameter list, and performs any copybacks.
- *
- * @param result Pointer to store return value in.
- * @return Error code, if any.
- */
- virtual int Execute(cell_t *result) =0;
-
- /**
- * @brief Executes the function with the given parameter array.
- * Parameters are read in forward order (i.e. index 0 is parameter #1)
- * NOTE: You will get an error if you attempt to use CallFunction() with
- * previously pushed parameters.
- *
- * @param param Array of cell parameters.
- * @param num_params Number of parameters to push.
- * @param result Pointer to store result of function on return.
- * @return SourcePawn error code (if any).
- */
- virtual int CallFunction(const cell_t *params, unsigned int num_params, cell_t *result) =0;
-
- /**
- * @brief Returns which plugin this function belongs to.
- *
- * @return IPlugin pointer to parent plugin.
- */
- virtual IPlugin *GetParentPlugin() =0;
-
- /**
- * @brief Returns the physical address of a by-reference parameter.
- *
- * @param Parameter index to read (beginning at 0).
- * @return Address, or NULL if invalid parameter specified.
- */
- virtual cell_t *GetAddressOfPushedParam(unsigned int param) =0;
- };
-};
-
-#endif //_INCLUDE_SOURCEMOD_PLUGINFUNCTION_INTERFACE_H_
diff --git a/public/IPluginSys.h b/public/IPluginSys.h
index 45f27065..589b788f 100644
--- a/public/IPluginSys.h
+++ b/public/IPluginSys.h
@@ -57,8 +57,6 @@ namespace SourceMod
PluginType_Global, /* Plugin will never be unloaded or updated */
};
- class IPluginFunction;
-
/**
* @brief Encapsulates a run-time plugin as maintained by SourceMod.
*/
@@ -129,22 +127,6 @@ namespace SourceMod
*/
virtual unsigned int GetSerial() const =0;
- /**
- * @brief Returns a function by name.
- *
- * @param public_name Name of the function.
- * @return A new IPluginFunction pointer, NULL if not found.
- */
- virtual IPluginFunction *GetFunctionByName(const char *public_name) =0;
-
- /**
- * @brief Returns a function by its id.
- *
- * @param func_id Function ID.
- * @return A new IPluginFunction pointer, NULL if not found.
- */
- virtual IPluginFunction *GetFunctionById(funcid_t func_id) =0;
-
/**
* @brief Returns a plugin's identity token.
*/
diff --git a/public/sourcepawn/sp_vm_api.h b/public/sourcepawn/sp_vm_api.h
index cb904105..21ff120d 100644
--- a/public/sourcepawn/sp_vm_api.h
+++ b/public/sourcepawn/sp_vm_api.h
@@ -17,6 +17,152 @@ namespace SourcePawn
{
class IVirtualMachine;
+ #define SM_PARAM_COPYBACK (1<<0) /* Copy an array/reference back after call */
+
+ #define SM_PARAM_STRING_UTF8 (1<<0) /* String should be UTF-8 handled */
+ #define SM_PARAM_STRING_COPY (1<<1) /* String should be copied into the plugin */
+
+ /**
+ * @brief Represents what a function needs to implement in order to be callable.
+ */
+ class ICallable
+ {
+ public:
+ /**
+ * @brief Pushes a cell onto the current call.
+ *
+ * @param cell Parameter value to push.
+ * @return Error code, if any.
+ */
+ virtual int PushCell(cell_t cell) =0;
+
+ /**
+ * @brief Pushes a cell by reference onto the current call.
+ * NOTE: On Execute, the pointer passed will be modified if copyback is enabled.
+ * NOTE: By reference parameters are cached and thus are not read until execution.
+ * This means you cannot push a pointer, change it, and push it again and expect
+ * two different values to come out.
+ *
+ * @param cell Address containing parameter value to push.
+ * @param flags Copy-back flags.
+ * @return Error code, if any.
+ */
+ virtual int PushCellByRef(cell_t *cell, int flags) =0;
+
+ /**
+ * @brief Pushes a float onto the current call.
+ *
+ * @param float Parameter value to push.
+ * @return Error code, if any.
+ */
+ virtual int PushFloat(float number) =0;
+
+ /**
+ * @brief Pushes a float onto the current call by reference.
+ * NOTE: On Execute, the pointer passed will be modified if copyback is enabled.
+ * NOTE: By reference parameters are cached and thus are not read until execution.
+ * This means you cannot push a pointer, change it, and push it again and expect
+ * two different values to come out.
+ *
+ * @param float Parameter value to push.
+ & @param flags Copy-back flags.
+ * @return Error code, if any.
+ */
+ virtual int PushFloatByRef(float *number, int flags) =0;
+
+ /**
+ * @brief Pushes an array of cells onto the current call.
+ * NOTE: On Execute, the pointer passed will be modified if non-NULL and copy-back
+ * is enabled.
+ * NOTE: By reference parameters are cached and thus are not read until execution.
+ * This means you cannot push a pointer, change it, and push it again and expect
+ * two different values to come out.
+ *
+ * @param inarray Array to copy, NULL if no initial array should be copied.
+ * @param cells Number of cells to allocate and optionally read from the input array.
+ * @param phys_addr Optional return address for physical array, if one was made.
+ * @param flags Whether or not changes should be copied back to the input array.
+ * @return Error code, if any.
+ */
+ virtual int PushArray(cell_t *inarray,
+ unsigned int cells,
+ cell_t **phys_addr,
+ int flags=0) =0;
+
+ /**
+ * @brief Pushes a string onto the current call.
+ *
+ * @param string String to push.
+ * @return Error code, if any.
+ */
+ virtual int PushString(const char *string) =0;
+
+ /**
+ * @brief Pushes a string or string buffer.
+ * NOTE: On Execute, the pointer passed will be modified if copy-back is enabled.
+ *
+ * @param buffer Pointer to string buffer.
+ * @param length Length of buffer.
+ * @param sz_flags String flags.
+ * @param cp_flags Copy-back flags.
+ * @return Error code, if any.
+ */
+ virtual int PushStringEx(char *buffer, size_t length, int sz_flags, int cp_flags) =0;
+
+ /**
+ * @brief Cancels a function call that is being pushed but not yet executed.
+ * This can be used be reset for CallFunction() use.
+ */
+ virtual void Cancel() =0;
+ };
+
+
+ /**
+ * @brief Encapsulates a function call in a plugin.
+ * NOTE: Function calls must be atomic to one execution context.
+ * NOTE: This object should not be deleted. It lives for the lifetime of the plugin.
+ */
+ class IPluginFunction : public ICallable
+ {
+ public:
+ /**
+ * @brief Executes the forward, resets the pushed parameter list, and performs any copybacks.
+ *
+ * @param result Pointer to store return value in.
+ * @return Error code, if any.
+ */
+ virtual int Execute(cell_t *result) =0;
+
+ /**
+ * @brief Executes the function with the given parameter array.
+ * Parameters are read in forward order (i.e. index 0 is parameter #1)
+ * NOTE: You will get an error if you attempt to use CallFunction() with
+ * previously pushed parameters.
+ *
+ * @param param Array of cell parameters.
+ * @param num_params Number of parameters to push.
+ * @param result Pointer to store result of function on return.
+ * @return SourcePawn error code (if any).
+ */
+ virtual int CallFunction(const cell_t *params, unsigned int num_params, cell_t *result) =0;
+
+ /**
+ * @brief Returns which plugin this function belongs to.
+ *
+ * @return IPluginContext pointer to parent plugin.
+ */
+ virtual IPluginContext *GetParentContext() =0;
+
+ /**
+ * @brief Returns the physical address of a by-reference parameter.
+ *
+ * @param Parameter index to read (beginning at 0).
+ * @return Address, or NULL if invalid parameter specified.
+ */
+ virtual cell_t *GetAddressOfPushedParam(unsigned int param) =0;
+ };
+
+
/**
* @brief Interface to managing a debug context at runtime.
*/
@@ -340,6 +486,22 @@ namespace SourcePawn
*/
virtual cell_t ThrowNativeError(const char *msg, ...) =0;
+ /**
+ * @brief Returns a function by name.
+ *
+ * @param public_name Name of the function.
+ * @return A new IPluginFunction pointer, NULL if not found.
+ */
+ virtual IPluginFunction *GetFunctionByName(const char *public_name) =0;
+
+ /**
+ * @brief Returns a function by its id.
+ *
+ * @param func_id Function ID.
+ * @return A new IPluginFunction pointer, NULL if not found.
+ */
+ virtual IPluginFunction *GetFunctionById(funcid_t func_id) =0;
+
#if defined SOURCEMOD_BUILD
/**
* @brief Returns the identity token for this context.
@@ -348,6 +510,13 @@ namespace SourcePawn
* @return Identity token.
*/
virtual SourceMod::IdentityToken_t *GetIdentity() =0;
+
+ /**
+ * @brief Returns whether the identity is runnable.
+ *
+ * @return True if runnable, false otherwise.
+ */
+ virtual bool IsRunnable() =0;
#endif
};
diff --git a/public/sourcepawn/sp_vm_types.h b/public/sourcepawn/sp_vm_types.h
index 2436144d..74e47434 100644
--- a/public/sourcepawn/sp_vm_types.h
+++ b/public/sourcepawn/sp_vm_types.h
@@ -39,6 +39,7 @@ typedef uint32_t funcid_t;
#define SP_ERROR_INVALID_NATIVE 21 /* Native was pending or invalid */
#define SP_ERROR_PARAMS_MAX 22 /* Maximum number of parameters reached */
#define SP_ERROR_NATIVE 23 /* Error originates from a native */
+#define SP_ERROR_NOT_RUNNABLE 24 /* Function or plugin is not runnable */
/**********************************************
*** The following structures are reference structures.