Landed sourcepawn-1.2. The big changes:
1) JIT compilation/optimization now occurs per-function, and only when functions are first used. We're now officially a whole-method JIT rather than an AOT compiler (albiet, still a simple JIT). This has two implications: Functions are now much better abstracted internally, and loading a plugin is now much less expensive. If a function contains calls to other functions, THOSE functions are only compiled when they're invoked as well. 2) I've removed debug mode. We always show full backtraces now, as there was a very cheap way to implement this which really cleaned up everything. This is great for a number of reasons -- there's less code, the JIT is better designed, we don't need to relocate debug tables, and best of all we no longer have to tell users to enable debug mode at their own expense. --HG-- extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%402459
This commit is contained in:
@@ -41,6 +41,18 @@ void DebugReport::OnSourceModAllInitialized()
|
||||
g_pSourcePawn->SetDebugListener(this);
|
||||
}
|
||||
|
||||
void DebugReport::OnDebugSpew(const char *msg, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char buffer[512];
|
||||
|
||||
va_start(ap, msg);
|
||||
UTIL_FormatArgs(buffer, sizeof(buffer), msg, ap);
|
||||
va_end(ap);
|
||||
|
||||
g_Logger.LogMessage("[SM] %s", buffer);
|
||||
}
|
||||
|
||||
void DebugReport::GenerateError(IPluginContext *ctx, cell_t func_idx, int err, const char *message, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
@@ -43,6 +43,8 @@ public: // SMGlobalClass
|
||||
void OnSourceModAllInitialized();
|
||||
public: // IDebugListener
|
||||
void OnContextExecuteError(IPluginContext *ctx, IContextTrace *error);
|
||||
void OnDebugSpew(const char *msg, ...);
|
||||
public:
|
||||
void GenerateError(IPluginContext *ctx, cell_t func_idx, int err, const char *message, ...);
|
||||
void GenerateCodeError(IPluginContext *ctx, uint32_t code_addr, int err, const char *message, ...);
|
||||
private:
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
#include "ShareSys.h"
|
||||
#include "PluginSys.h"
|
||||
|
||||
CNativeOwner::CNativeOwner() : m_nMarkSerial(0)
|
||||
{
|
||||
}
|
||||
|
||||
void CNativeOwner::SetMarkSerial(unsigned int serial)
|
||||
{
|
||||
m_nMarkSerial = serial;
|
||||
|
||||
@@ -30,6 +30,8 @@ using namespace SourceHook;
|
||||
|
||||
class CNativeOwner
|
||||
{
|
||||
public:
|
||||
CNativeOwner();
|
||||
public:
|
||||
virtual void DropEverything();
|
||||
public:
|
||||
|
||||
@@ -76,6 +76,11 @@ void ShutdownJIT()
|
||||
notify();
|
||||
}
|
||||
|
||||
if (g_pSourcePawn2 != NULL)
|
||||
{
|
||||
g_pSourcePawn2->Shutdown();
|
||||
}
|
||||
|
||||
g_pJIT->CloseLibrary();
|
||||
}
|
||||
|
||||
@@ -188,6 +193,26 @@ bool SourceModBase::InitializeSourceMod(char *error, size_t maxlength, bool late
|
||||
g_pSourcePawn = getv1();
|
||||
g_pSourcePawn2 = getv2();
|
||||
|
||||
if (g_pSourcePawn2->GetAPIVersion() < 2)
|
||||
{
|
||||
g_pSourcePawn2 = NULL;
|
||||
if (error && maxlength)
|
||||
{
|
||||
snprintf(error, maxlength, "JIT version is out of date");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!g_pSourcePawn2->Initialize())
|
||||
{
|
||||
g_pSourcePawn2 = NULL;
|
||||
if (error && maxlength)
|
||||
{
|
||||
snprintf(error, maxlength, "JIT could not be initialized");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
g_pSourcePawn2->SetDebugListener(&g_DbgReporter);
|
||||
g_pSourcePawn2->SetProfiler(&g_Profiler);
|
||||
|
||||
|
||||
+5
-146
@@ -447,7 +447,7 @@ bool CPlugin::IsDebugging()
|
||||
return false;
|
||||
}
|
||||
|
||||
return m_pRuntime->IsDebugging();
|
||||
return true;
|
||||
}
|
||||
|
||||
void CPlugin::LibraryActions(bool dropping)
|
||||
@@ -507,61 +507,6 @@ IdentityToken_t *CPlugin::GetIdentity()
|
||||
return m_ident;
|
||||
}
|
||||
|
||||
bool CPlugin::ToggleDebugMode(bool debug, char *error, size_t maxlength)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (!IsRunnable())
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
snprintf(error, maxlength, "Plugin is not runnable.");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (debug && IsDebugging())
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
snprintf(error, maxlength, "Plugin is already in debug mode.");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else if (!debug && !IsDebugging())
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
snprintf(error, maxlength, "Plugins is already in production mode.");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ICompilation *co = g_pSourcePawn2->StartCompilation();
|
||||
|
||||
if (!co->SetOption("debug", (debug) ? "1" : "0"))
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
snprintf(error, maxlength, "Failed to change plugin mode (JIT failure).");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((err = m_pRuntime->ApplyCompilationOptions(co)) != SP_ERROR_NONE)
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
snprintf(error, maxlength, "Failed to recompile plugin (JIT error %d).", err);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
UpdateInfo();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CPlugin::IsRunnable()
|
||||
{
|
||||
return (m_status <= Plugin_Paused) ? true : false;
|
||||
@@ -1057,7 +1002,7 @@ IPlugin *CPluginManager::LoadPlugin(const char *path, bool debug, PluginType typ
|
||||
LoadRes res;
|
||||
|
||||
*wasloaded = false;
|
||||
if ((res=_LoadPlugin(&pl, path, debug, type, error, maxlength)) == LoadRes_Failure)
|
||||
if ((res=_LoadPlugin(&pl, path, true, type, error, maxlength)) == LoadRes_Failure)
|
||||
{
|
||||
delete pl;
|
||||
return NULL;
|
||||
@@ -2195,14 +2140,7 @@ void CPluginManager::OnRootConsoleCommand(const char *cmdname, const CCommand &c
|
||||
{
|
||||
if (pl->GetStatus() == Plugin_Running)
|
||||
{
|
||||
if (pl->IsDebugging())
|
||||
{
|
||||
g_RootMenu.ConsolePrint(" Status: running, debugging");
|
||||
}
|
||||
else
|
||||
{
|
||||
g_RootMenu.ConsolePrint(" Status: running");
|
||||
}
|
||||
g_RootMenu.ConsolePrint(" Status: running");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2245,83 +2183,6 @@ void CPluginManager::OnRootConsoleCommand(const char *cmdname, const CCommand &c
|
||||
|
||||
return;
|
||||
}
|
||||
else if (strcmp(cmd, "debug") == 0)
|
||||
{
|
||||
if (argcount < 5)
|
||||
{
|
||||
g_RootMenu.ConsolePrint("[SM] Usage: sm plugins debug <#> [on|off]");
|
||||
return;
|
||||
}
|
||||
|
||||
CPlugin *pl;
|
||||
char *end;
|
||||
const char *arg = command.Arg(3);
|
||||
int id = strtol(arg, &end, 10);
|
||||
|
||||
if (*end == '\0')
|
||||
{
|
||||
pl = GetPluginByOrder(id);
|
||||
if (!pl)
|
||||
{
|
||||
g_RootMenu.ConsolePrint("[SM] Plugin index %d not found.", id);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
char pluginfile[256];
|
||||
const char *ext = g_LibSys.GetFileExtension(arg) ? "" : ".smx";
|
||||
UTIL_Format(pluginfile, sizeof(pluginfile), "%s%s", arg, ext);
|
||||
|
||||
if (!sm_trie_retrieve(m_LoadLookup, pluginfile, (void **)&pl))
|
||||
{
|
||||
g_RootMenu.ConsolePrint("[SM] Plugin %s is not loaded.", pluginfile);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int res;
|
||||
const char *mode = command.Arg(4);
|
||||
if ((res=strcmp("on", mode)) && strcmp("off", mode))
|
||||
{
|
||||
g_RootMenu.ConsolePrint("[SM] The only possible options are \"on\" and \"off.\"");
|
||||
return;
|
||||
}
|
||||
|
||||
bool debug;
|
||||
if (!res)
|
||||
{
|
||||
debug = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
debug = false;
|
||||
}
|
||||
|
||||
if (debug && pl->IsDebugging())
|
||||
{
|
||||
g_RootMenu.ConsolePrint("[SM] This plugin is already in debug mode.");
|
||||
return;
|
||||
}
|
||||
else if (!debug && !pl->IsDebugging())
|
||||
{
|
||||
g_RootMenu.ConsolePrint("[SM] Debug mode is already disabled in this plugin.");
|
||||
return;
|
||||
}
|
||||
|
||||
char error[256];
|
||||
if (pl->ToggleDebugMode(debug, error, sizeof(error)))
|
||||
{
|
||||
g_RootMenu.ConsolePrint("[SM] Successfully toggled debug mode on plugin %s.", pl->GetFilename());
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_RootMenu.ConsolePrint("[SM] Could not toggle debug mode on plugin %s.", pl->GetFilename());
|
||||
g_RootMenu.ConsolePrint("[SM] Plugin returned error: %s", error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (strcmp(cmd, "refresh") == 0)
|
||||
{
|
||||
g_SourceMod.DoGlobalPluginLoads();
|
||||
@@ -2382,7 +2243,6 @@ void CPluginManager::OnRootConsoleCommand(const char *cmdname, const CCommand &c
|
||||
|
||||
/* Draw the main menu */
|
||||
g_RootMenu.ConsolePrint("SourceMod Plugins Menu:");
|
||||
g_RootMenu.DrawGenericOption("debug", "Toggle debug mode on a plugin");
|
||||
g_RootMenu.DrawGenericOption("info", "Information about a plugin");
|
||||
g_RootMenu.DrawGenericOption("list", "Show loaded plugins");
|
||||
g_RootMenu.DrawGenericOption("load", "Load a plugin");
|
||||
@@ -2398,13 +2258,12 @@ bool CPluginManager::ReloadPlugin(CPlugin *pl)
|
||||
{
|
||||
List<CPlugin *>::iterator iter;
|
||||
char filename[PLATFORM_MAX_PATH];
|
||||
bool debug, wasloaded;
|
||||
bool wasloaded;
|
||||
PluginType ptype;
|
||||
IPlugin *newpl;
|
||||
int id = 1;
|
||||
|
||||
strcpy(filename, pl->m_filename);
|
||||
debug = pl->IsDebugging();
|
||||
ptype = pl->GetType();
|
||||
|
||||
for (iter=m_plugins.begin(); iter!=m_plugins.end(); iter++, id++)
|
||||
@@ -2419,7 +2278,7 @@ bool CPluginManager::ReloadPlugin(CPlugin *pl)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!(newpl=LoadPlugin(filename, debug, ptype, NULL, 0, &wasloaded)))
|
||||
if (!(newpl=LoadPlugin(filename, true, ptype, NULL, 0, &wasloaded)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -198,11 +198,6 @@ public:
|
||||
*/
|
||||
void Call_OnAllPluginsLoaded();
|
||||
|
||||
/**
|
||||
* Toggles debug mode in the plugin
|
||||
*/
|
||||
bool ToggleDebugMode(bool debug, char *error, size_t maxlength);
|
||||
|
||||
/**
|
||||
* Returns true if a plugin is usable.
|
||||
*/
|
||||
|
||||
@@ -413,9 +413,9 @@ void ShareSystem::BindNativeToPlugin(CPlugin *pPlugin,
|
||||
else
|
||||
{
|
||||
/* See if this has already been marked as a dependent.
|
||||
* If it has, it means this relationship has already occurred,
|
||||
* and there is no reason to do it again.
|
||||
*/
|
||||
* If it has, it means this relationship has already occurred,
|
||||
* and there is no reason to do it again.
|
||||
*/
|
||||
if (pEntry->owner != pPlugin
|
||||
&& pEntry->owner->GetMarkSerial() != g_mark_serial)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user