finished massive reorganization - IPluginFunction is now part of the VM, NOT the plugin system! This is how it should have been in the first place...

--HG--
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%40332
This commit is contained in:
David Anderson
2007-01-19 08:22:44 +00:00
parent a25f2f7be6
commit cd735aec71
16 changed files with 526 additions and 435 deletions
+13 -17
View File
@@ -341,10 +341,6 @@
RelativePath="..\..\public\ILibrarySys.h"
>
</File>
<File
RelativePath="..\..\public\IPluginFunction.h"
>
</File>
<File
RelativePath="..\..\public\IPluginSys.h"
>
@@ -372,10 +368,6 @@
<Filter
Name="Header Files"
>
<File
RelativePath="..\systems\CFunction.h"
>
</File>
<File
RelativePath="..\systems\ExtensionSys.h"
>
@@ -408,10 +400,6 @@
<Filter
Name="Source Files"
>
<File
RelativePath="..\systems\CFunction.cpp"
>
</File>
<File
RelativePath="..\systems\ExtensionSys.cpp"
>
@@ -456,6 +444,10 @@
RelativePath="..\vm\sp_vm_engine.h"
>
</File>
<File
RelativePath="..\vm\sp_vm_function.h"
>
</File>
</Filter>
<Filter
Name="Source Files"
@@ -468,28 +460,32 @@
RelativePath="..\vm\sp_vm_engine.cpp"
>
</File>
<File
RelativePath="..\vm\sp_vm_function.cpp"
>
</File>
</Filter>
<Filter
Name="SDK"
>
<File
RelativePath="..\..\sourcepawn\include\sp_file_headers.h"
RelativePath="..\..\public\sourcepawn\sp_file_headers.h"
>
</File>
<File
RelativePath="..\..\sourcepawn\include\sp_typeutil.h"
RelativePath="..\..\public\sourcepawn\sp_typeutil.h"
>
</File>
<File
RelativePath="..\..\sourcepawn\include\sp_vm_api.h"
RelativePath="..\..\public\sourcepawn\sp_vm_api.h"
>
</File>
<File
RelativePath="..\..\sourcepawn\include\sp_vm_base.h"
RelativePath="..\..\public\sourcepawn\sp_vm_base.h"
>
</File>
<File
RelativePath="..\..\sourcepawn\include\sp_vm_types.h"
RelativePath="..\..\public\sourcepawn\sp_vm_types.h"
>
</File>
</Filter>
+7 -10
View File
@@ -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++;
+1 -1
View File
@@ -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,
+8 -134
View File
@@ -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; i<m_plugin->info.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; i<m_funcsnum; i++)
{
g_PluginSys.ReleaseFunctionToPool(m_priv_funcs[i]);
}
delete [] m_priv_funcs;
m_priv_funcs = NULL;
}
if (m_plugin)
{
g_pSourcePawn->FreeFromMemory(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 */
-9
View File
@@ -8,7 +8,6 @@
#include <sh_stack.h>
#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<CPlugin *> m_plugins;
List<sp_nativeinfo_t *> m_natives;
CStack<CPluginManager::CPluginIterator *> m_iters;
CStack<CFunction *> m_funcpool;
CPluginInfoDatabase m_PluginInfo;
Trie *m_LoadLookup;
bool m_AllPluginsLoaded;
+129
View File
@@ -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; i<ctx->plugin->info.publics_num; i++)
{
delete m_pub_funcs[i];
m_pub_funcs[i] = NULL;
}
}
if (m_priv_funcs)
{
for (unsigned int i=0; i<m_funcsnum; i++)
{
delete m_priv_funcs[i];
m_priv_funcs[i] = NULL;
}
}
}
BaseContext::~BaseContext()
{
FlushFunctionCache();
delete [] m_pub_funcs;
m_pub_funcs = NULL;
delete [] m_priv_funcs;
m_priv_funcs = NULL;
}
void BaseContext::SetContext(sp_context_t *_ctx)
@@ -36,6 +90,9 @@ void BaseContext::SetContext(sp_context_t *_ctx)
return;
}
ctx = _ctx;
ctx->context = 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
+15
View File
@@ -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;
};
};
+39
View File
@@ -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;
+71 -69
View File
@@ -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_
@@ -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;
}
+55
View File
@@ -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_