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.
3 * =============================================================================
5 * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
6 * =============================================================================
8 * This program is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU General Public License, version 3.0, as published by the
10 * Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
17 * You should have received a copy of the GNU General Public License along with
18 * this program. If not, see <http://www.gnu.org/licenses/>.
20 * As a special exception, AlliedModders LLC gives you permission to link the
21 * code of this program (as well as its derivative works) to "Half-Life 2," the
22 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
23 * by the Valve Corporation. You must obey the GNU General Public License in
24 * all respects for all other code used. Additionally, AlliedModders LLC grants
25 * this exception to all derivative works. AlliedModders LLC defines further
26 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
27 * or <http://www.sourcemod.net/license.php>.
32 #include "DebugReporter.h"
34 #include "PluginSys.h"
35 #include "sm_stringutil.h"
37 DebugReport g_DbgReporter;
39 void DebugReport::OnSourceModAllInitialized()
41 g_pSourcePawn->SetDebugListener(this);
44 void DebugReport::OnDebugSpew(const char *msg, ...)
50 UTIL_FormatArgs(buffer, sizeof(buffer), msg, ap);
53 g_Logger.LogMessage("[SM] %s", buffer);
56 void DebugReport::GenerateError(IPluginContext *ctx, cell_t func_idx, int err, const char *message, ...)
61 va_start(ap, message);
62 UTIL_FormatArgs(buffer, sizeof(buffer), message, ap);
65 const char *plname = g_PluginSys.FindPluginByContext(ctx->GetContext())->GetFilename();
66 const char *error = g_pSourcePawn2->GetErrorString(err);
70 g_Logger.LogError("[SM] Plugin \"%s\" encountered error %d: %s", plname, err, error);
72 g_Logger.LogError("[SM] Plugin \"%s\" encountered unknown error %d", plname, err);
75 g_Logger.LogError("[SM] %s", buffer);
82 sp_public_t *function;
83 if (ctx->GetRuntime()->GetPublicByIndex(func_idx, &function) == SP_ERROR_NONE)
85 g_Logger.LogError("[SM] Unable to call function \"%s\" due to above error(s).", function->name);
91 void DebugReport::GenerateCodeError(IPluginContext *pContext, uint32_t code_addr, int err, const char *message, ...)
96 va_start(ap, message);
97 UTIL_FormatArgs(buffer, sizeof(buffer), message, ap);
100 const char *plname = g_PluginSys.FindPluginByContext(pContext->GetContext())->GetFilename();
101 const char *error = g_pSourcePawn2->GetErrorString(err);
105 g_Logger.LogError("[SM] Plugin \"%s\" encountered error %d: %s", plname, err, error);
107 g_Logger.LogError("[SM] Plugin \"%s\" encountered unknown error %d", plname, err);
110 g_Logger.LogError("[SM] %s", buffer);
112 IPluginDebugInfo *pDebug;
113 if ((pDebug = pContext->GetRuntime()->GetDebugInfo()) == NULL)
115 g_Logger.LogError("[SM] Debug mode is not enabled for \"%s\"", plname);
116 g_Logger.LogError("[SM] To enable debug mode, edit plugin_settings.cfg, or type: sm plugins debug %d on",
117 _GetPluginIndex(pContext));
122 if (pDebug->LookupFunction(code_addr, &name) == SP_ERROR_NONE)
124 g_Logger.LogError("[SM] Unable to call function \"%s\" due to above error(s).", name);
126 g_Logger.LogError("[SM] Unable to call function (name unknown, address \"%x\").", code_addr);
130 void DebugReport::OnContextExecuteError(IPluginContext *ctx, IContextTrace *error)
132 const char *lastname;
133 const char *plname = g_PluginSys.FindPluginByContext(ctx->GetContext())->GetFilename();
134 int n_err = error->GetErrorCode();
136 if (n_err != SP_ERROR_NATIVE)
138 g_Logger.LogError("[SM] Plugin encountered error %d: %s",
140 error->GetErrorString());
143 if ((lastname=error->GetLastNative(NULL)) != NULL)
146 if ((custerr=error->GetCustomErrorString()) != NULL)
148 g_Logger.LogError("[SM] Native \"%s\" reported: %s", lastname, custerr);
150 g_Logger.LogError("[SM] Native \"%s\" encountered a generic error.", lastname);
154 if (!error->DebugInfoAvailable())
156 g_Logger.LogError("[SM] Debug mode is not enabled for \"%s\"", plname);
157 g_Logger.LogError("[SM] To enable debug mode, edit plugin_settings.cfg, or type: sm plugins debug %d on",
158 _GetPluginIndex(ctx));
162 CallStackInfo stk_info;
164 g_Logger.LogError("[SM] Displaying call stack trace for plugin \"%s\":", plname);
165 while (error->GetTraceInfo(&stk_info))
167 g_Logger.LogError("[SM] [%d] Line %d, %s::%s()",
175 int DebugReport::_GetPluginIndex(IPluginContext *ctx)
178 IPluginIterator *iter = g_PluginSys.GetPluginIterator();
180 for (; iter->MorePlugins(); iter->NextPlugin(), id++)
182 IPlugin *pl = iter->GetPlugin();
183 if (pl->GetBaseContext() == ctx)
192 /* If we don't know which plugin this is, it's one being loaded. Fake its index for now. */
194 return g_PluginSys.GetPluginCount() + 1;