Add an interpreter because. (bug 5902, r=ds).
1.1 --- a/configs/core.cfg Sat Aug 31 19:50:36 2013 -0700
1.2 +++ b/configs/core.cfg Sun Sep 01 00:23:44 2013 -0700
1.3 @@ -132,5 +132,13 @@
1.4 * passed. You can disable this feature by setting the value to "0".
1.5 */
1.6 "SlowScriptTimeout" "8"
1.7 +
1.8 + /**
1.9 + * Disable the SourcePawn just-in-time compiler. This is intended for C++ developers using
1.10 + * debugging tools and finding it difficult to inspect JIT stack frames. The interpreter
1.11 + * is not as well-tested as the JIT and will make script execution roughly 10X slower, so
1.12 + * it is not intended for general purpose use.
1.13 + */
1.14 + "DisableJIT" "no"
1.15 }
1.16
2.1 --- a/core/sm_srvcmds.cpp Sat Aug 31 19:50:36 2013 -0700
2.2 +++ b/core/sm_srvcmds.cpp Sun Sep 01 00:23:44 2013 -0700
2.3 @@ -334,7 +334,10 @@
2.4 {
2.5 ConsolePrint(" SourceMod Version Information:");
2.6 ConsolePrint(" SourceMod Version: %s", SM_VERSION_STRING);
2.7 - ConsolePrint(" SourcePawn Engine: %s (build %s)", g_pSourcePawn2->GetEngineName(), g_pSourcePawn2->GetVersionString());
2.8 + if (g_pSourcePawn2->IsJitEnabled())
2.9 + ConsolePrint(" SourcePawn Engine: %s (build %s)", g_pSourcePawn2->GetEngineName(), g_pSourcePawn2->GetVersionString());
2.10 + else
2.11 + ConsolePrint(" SourcePawn Engine: %s (build %s NO JIT)", g_pSourcePawn2->GetEngineName(), g_pSourcePawn2->GetVersionString());
2.12 ConsolePrint(" SourcePawn API: v1 = %d, v2 = %d", g_pSourcePawn->GetEngineAPIVersion(), g_pSourcePawn2->GetAPIVersion());
2.13 ConsolePrint(" Compiled on: %s %s", __DATE__, __TIME__);
2.14 ConsolePrint(" Build ID: %s", SM_BUILD_UNIQUEID);
3.1 --- a/core/sourcemod.cpp Sat Aug 31 19:50:36 2013 -0700
3.2 +++ b/core/sourcemod.cpp Sun Sep 01 00:23:44 2013 -0700
3.3 @@ -61,6 +61,7 @@
3.4 IGameConfig *g_pGameConf = NULL;
3.5 bool g_Loaded = false;
3.6 bool sm_show_debug_spew = false;
3.7 +bool sm_disable_jit = false;
3.8
3.9 typedef ISourcePawnEngine *(*GET_SP_V1)();
3.10 typedef ISourcePawnEngine2 *(*GET_SP_V2)();
3.11 @@ -125,6 +126,14 @@
3.12
3.13 return ConfigResult_Accept;
3.14 }
3.15 + else if (strcasecmp(key, "DisableJIT") == 0)
3.16 + {
3.17 + sm_disable_jit = (strcasecmp(value, "yes") == 0) ? true : false;
3.18 + if (g_pSourcePawn2)
3.19 + g_pSourcePawn2->SetJitEnabled(!sm_disable_jit);
3.20 +
3.21 + return ConfigResult_Accept;
3.22 + }
3.23
3.24 return ConfigResult_Ignore;
3.25 }
3.26 @@ -242,6 +251,9 @@
3.27
3.28 g_pSourcePawn2->SetDebugListener(logicore.debugger);
3.29
3.30 + if (sm_disable_jit)
3.31 + g_pSourcePawn2->SetJitEnabled(!sm_disable_jit);
3.32 +
3.33 sSourceModInitialized = true;
3.34
3.35 /* Hook this now so we can detect startup without calling StartSourceMod() */
4.1 --- a/public/sourcepawn/sp_vm_api.h Sat Aug 31 19:50:36 2013 -0700
4.2 +++ b/public/sourcepawn/sp_vm_api.h Sun Sep 01 00:23:44 2013 -0700
4.3 @@ -40,7 +40,7 @@
4.4
4.5 /** SourcePawn Engine API Version */
4.6 #define SOURCEPAWN_ENGINE_API_VERSION 4
4.7 -#define SOURCEPAWN_ENGINE2_API_VERSION 5
4.8 +#define SOURCEPAWN_ENGINE2_API_VERSION 6
4.9
4.10 #if !defined SOURCEMOD_BUILD
4.11 #define SOURCEMOD_BUILD
4.12 @@ -1295,6 +1295,21 @@
4.13 * @return True on success, false on failure.
4.14 */
4.15 virtual bool InstallWatchdogTimer(size_t timeout_ms) =0;
4.16 +
4.17 + /**
4.18 + * @brief Sets whether the JIT is enabled or disabled.
4.19 + *
4.20 + * @param enabled True or false to enable or disable.
4.21 + * @return True if successful, false otherwise.
4.22 + */
4.23 + virtual bool SetJitEnabled(bool enabled) =0;
4.24 +
4.25 + /**
4.26 + * @brief Returns whether the JIT is enabled.
4.27 + *
4.28 + * @return True if the JIT is enabled, false otherwise.
4.29 + */
4.30 + virtual bool IsJitEnabled() =0;
4.31 };
4.32 };
4.33
5.1 --- a/sourcepawn/jit/AMBuilder Sat Aug 31 19:50:36 2013 -0700
5.2 +++ b/sourcepawn/jit/AMBuilder Sun Sep 01 00:23:44 2013 -0700
5.3 @@ -31,6 +31,7 @@
5.4 'sp_vm_engine.cpp',
5.5 'sp_vm_function.cpp',
5.6 'opcodes.cpp',
5.7 + 'interpreter.cpp',
5.8 'watchdog_timer.cpp',
5.9 'x86/jit_x86.cpp',
5.10 'zlib/adler32.c',
6.1 --- a/sourcepawn/jit/Makefile.shell Sat Aug 31 19:50:36 2013 -0700
6.2 +++ b/sourcepawn/jit/Makefile.shell Sun Sep 01 00:23:44 2013 -0700
6.3 @@ -20,6 +20,7 @@
6.4 jit_function.cpp \
6.5 opcodes.cpp \
6.6 watchdog_timer.cpp \
6.7 + interpreter.cpp \
6.8 md5/md5.cpp \
6.9 zlib/adler32.c \
6.10 zlib/compress.c \
6.11 @@ -51,7 +52,8 @@
6.12 LINK = -m32 -lm -lpthread -lrt
6.13
6.14 INCLUDE = -I. -I.. -I$(SMSDK)/public -I$(SMSDK)/public/jit -I$(SMSDK)/public/jit/x86 \
6.15 - -I$(SMSDK)/public/sourcepawn -I$(MMSOURCE17)/core/sourcehook -I$(SMSDK)/knight/shared -Ix86
6.16 + -I$(SMSDK)/public/sourcepawn -I$(MMSOURCE17)/core/sourcehook -I$(SMSDK)/knight/shared -Ix86 \
6.17 + -I$(SMSDK)/public/amtl
6.18
6.19 CFLAGS += -D_LINUX -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp -Dstrnicmp=strncasecmp \
6.20 -D_snprintf=snprintf -D_vsnprintf=vsnprintf -D_alloca=alloca -Dstrcmpi=strcasecmp -Wall -DHAVE_STDINT_H \
7.1 --- a/sourcepawn/jit/dll_exports.cpp Sat Aug 31 19:50:36 2013 -0700
7.2 +++ b/sourcepawn/jit/dll_exports.cpp Sun Sep 01 00:23:44 2013 -0700
7.3 @@ -219,6 +219,9 @@
7.4 return 1;
7.5 }
7.6
7.7 + if (getenv("DISABLE_JIT"))
7.8 + g_engine2.SetJitEnabled(false);
7.9 +
7.10 ShellDebugListener debug;
7.11 g_engine1.SetDebugListener(&debug);
7.12 g_engine2.InstallWatchdogTimer(5000);
8.1 --- a/sourcepawn/jit/engine2.cpp Sat Aug 31 19:50:36 2013 -0700
8.2 +++ b/sourcepawn/jit/engine2.cpp Sun Sep 01 00:23:44 2013 -0700
8.3 @@ -15,6 +15,7 @@
8.4 SourcePawnEngine2::SourcePawnEngine2()
8.5 {
8.6 m_Profiler = NULL;
8.7 + jit_enabled_ = true;
8.8 }
8.9
8.10 IPluginRuntime *SourcePawnEngine2::LoadPlugin(ICompilation *co, const char *file, int *err)
8.11 @@ -146,7 +147,7 @@
8.12
8.13 const char *SourcePawnEngine2::GetEngineName()
8.14 {
8.15 - return "SourcePawn 1.1, jit-x86";
8.16 + return "SourcePawn 1.2, jit-x86";
8.17 }
8.18
8.19 const char *SourcePawnEngine2::GetVersionString()
9.1 --- a/sourcepawn/jit/engine2.h Sat Aug 31 19:50:36 2013 -0700
9.2 +++ b/sourcepawn/jit/engine2.h Sun Sep 01 00:23:44 2013 -0700
9.3 @@ -1,3 +1,4 @@
9.4 +// vim: set ts=4 sw=4 tw=99 noet:
9.5 #ifndef _INCLUDE_SOURCEPAWN_ENGINE_2_H_
9.6 #define _INCLUDE_SOURCEPAWN_ENGINE_2_H_
9.7
9.8 @@ -27,10 +28,20 @@
9.9 void Shutdown();
9.10 IPluginRuntime *CreateEmptyRuntime(const char *name, uint32_t memory);
9.11 bool InstallWatchdogTimer(size_t timeout_ms);
9.12 +
9.13 + bool SetJitEnabled(bool enabled) {
9.14 + jit_enabled_ = enabled;
9.15 + return true;
9.16 + }
9.17 +
9.18 + bool IsJitEnabled() {
9.19 + return jit_enabled_;
9.20 + }
9.21 public:
9.22 IProfiler *GetProfiler();
9.23 private:
9.24 IProfiler *m_Profiler;
9.25 + bool jit_enabled_;
9.26 };
9.27 }
9.28
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
10.2 +++ b/sourcepawn/jit/interpreter.cpp Sun Sep 01 00:23:44 2013 -0700
10.3 @@ -0,0 +1,965 @@
10.4 +// vim: set ts=8 sts=2 sw=2 tw=99 et:
10.5 +//
10.6 +// This file is part of SourcePawn.
10.7 +//
10.8 +// SourcePawn is free software: you can redistribute it and/or modify
10.9 +// it under the terms of the GNU General Public License as published by
10.10 +// the Free Software Foundation, either version 3 of the License, or
10.11 +// (at your option) any later version.
10.12 +//
10.13 +// SourcePawn is distributed in the hope that it will be useful,
10.14 +// but WITHOUT ANY WARRANTY; without even the implied warranty of
10.15 +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10.16 +// GNU General Public License for more details.
10.17 +//
10.18 +// You should have received a copy of the GNU General Public License
10.19 +// along with SourcePawn. If not, see <http://www.gnu.org/licenses/>.
10.20 +#include <limits.h>
10.21 +#include <string.h>
10.22 +#include "interpreter.h"
10.23 +#include "opcodes.h"
10.24 +#include "watchdog_timer.h"
10.25 +
10.26 +#define STACK_MARGIN 64
10.27 +
10.28 +using namespace SourcePawn;
10.29 +
10.30 +static inline bool
10.31 +IsValidOffset(uint32_t cip)
10.32 +{
10.33 + return cip % 4 == 0;
10.34 +}
10.35 +
10.36 +static inline cell_t
10.37 +Read(const sp_plugin_t *plugin, cell_t offset)
10.38 +{
10.39 + return *reinterpret_cast<cell_t *>(plugin->memory + offset);
10.40 +}
10.41 +
10.42 +static inline void
10.43 +Write(const sp_plugin_t *plugin, cell_t offset, cell_t value)
10.44 +{
10.45 + *reinterpret_cast<cell_t *>(plugin->memory + offset) = value;
10.46 +}
10.47 +
10.48 +static inline cell_t *
10.49 +Jump(const sp_plugin_t *plugin, sp_context_t *ctx, cell_t target)
10.50 +{
10.51 + if (!IsValidOffset(target) || uint32_t(target) >= plugin->pcode_size) {
10.52 + ctx->err = SP_ERROR_INVALID_INSTRUCTION;
10.53 + return NULL;
10.54 + }
10.55 +
10.56 + return reinterpret_cast<cell_t *>(plugin->pcode + target);
10.57 +}
10.58 +
10.59 +static inline cell_t *
10.60 +JumpTarget(const sp_plugin_t *plugin, sp_context_t *ctx, cell_t *cip, bool cond)
10.61 +{
10.62 + if (!cond)
10.63 + return cip + 1;
10.64 +
10.65 + cell_t target = *cip;
10.66 + if (!IsValidOffset(target) || uint32_t(target) >= plugin->pcode_size) {
10.67 + ctx->err = SP_ERROR_INVALID_INSTRUCTION;
10.68 + return NULL;
10.69 + }
10.70 +
10.71 + cell_t *next = reinterpret_cast<cell_t *>(plugin->pcode + target);
10.72 + if (next < cip && !g_WatchdogTimer.HandleInterrupt()) {
10.73 + ctx->err = SP_ERROR_TIMEOUT;
10.74 + return NULL;
10.75 + }
10.76 +
10.77 + return next;
10.78 +}
10.79 +
10.80 +static inline bool
10.81 +CheckAddress(const sp_plugin_t *plugin, sp_context_t *ctx, cell_t *stk, cell_t addr)
10.82 +{
10.83 + if (uint32_t(addr) >= plugin->mem_size) {
10.84 + ctx->err = SP_ERROR_MEMACCESS;
10.85 + return false;
10.86 + }
10.87 +
10.88 + if (addr < ctx->hp)
10.89 + return true;
10.90 +
10.91 + if (reinterpret_cast<cell_t *>(plugin->memory + addr) < stk) {
10.92 + ctx->err = SP_ERROR_MEMACCESS;
10.93 + return false;
10.94 + }
10.95 +
10.96 + return true;
10.97 +}
10.98 +
10.99 +int
10.100 +PopTrackerAndSetHeap(BaseRuntime *rt)
10.101 +{
10.102 + sp_context_t *ctx = rt->GetBaseContext()->GetCtx();
10.103 + tracker_t *trk = ctx->tracker;
10.104 + assert(trk->pCur > trk->pBase);
10.105 +
10.106 + trk->pCur--;
10.107 + if (trk->pCur < trk->pBase)
10.108 + return SP_ERROR_TRACKER_BOUNDS;
10.109 +
10.110 + ucell_t amt = *trk->pCur;
10.111 + if (amt > (ctx->hp - rt->plugin()->data_size))
10.112 + return SP_ERROR_HEAPMIN;
10.113 +
10.114 + ctx->hp -= amt;
10.115 + return SP_ERROR_NONE;
10.116 +}
10.117 +
10.118 +int
10.119 +PushTracker(sp_context_t *ctx, size_t amount)
10.120 +{
10.121 + tracker_t *trk = ctx->tracker;
10.122 +
10.123 + if ((size_t)(trk->pCur - trk->pBase) >= trk->size)
10.124 + return SP_ERROR_TRACKER_BOUNDS;
10.125 +
10.126 + if (trk->pCur + 1 - (trk->pBase + trk->size) == 0) {
10.127 + size_t disp = trk->size - 1;
10.128 + trk->size *= 2;
10.129 + trk->pBase = (ucell_t *)realloc(trk->pBase, trk->size * sizeof(cell_t));
10.130 +
10.131 + if (!trk->pBase)
10.132 + return SP_ERROR_TRACKER_BOUNDS;
10.133 +
10.134 + trk->pCur = trk->pBase + disp;
10.135 + }
10.136 +
10.137 + *trk->pCur++ = amount;
10.138 + return SP_ERROR_NONE;
10.139 +}
10.140 +
10.141 +cell_t
10.142 +NativeCallback(sp_context_t *ctx, ucell_t native_idx, cell_t *params)
10.143 +{
10.144 + cell_t save_sp = ctx->sp;
10.145 + cell_t save_hp = ctx->hp;
10.146 +
10.147 + ctx->n_idx = native_idx;
10.148 +
10.149 + sp_native_t *native = &ctx->plugin->natives[native_idx];
10.150 +
10.151 + if (native->status == SP_NATIVE_UNBOUND) {
10.152 + ctx->n_err = SP_ERROR_INVALID_NATIVE;
10.153 + return 0;
10.154 + }
10.155 +
10.156 + cell_t result = native->pfn(ctx->basecx, params);
10.157 +
10.158 + if (ctx->n_err != SP_ERROR_NONE)
10.159 + return result;
10.160 +
10.161 + if (save_sp != ctx->sp) {
10.162 + ctx->n_err = SP_ERROR_STACKLEAK;
10.163 + return result;
10.164 + }
10.165 + if (save_hp != ctx->hp) {
10.166 + ctx->n_err = SP_ERROR_HEAPLEAK;
10.167 + return result;
10.168 + }
10.169 +
10.170 + return result;
10.171 +}
10.172 +
10.173 +static inline bool
10.174 +GenerateArray(BaseRuntime *rt, sp_context_t *ctx, cell_t dims, cell_t *stk, bool autozero)
10.175 +{
10.176 + if (dims == 1) {
10.177 + uint32_t size = *stk;
10.178 + if (size == 0 || !ke::IsUint32MultiplySafe(size, 4)) {
10.179 + ctx->err = SP_ERROR_ARRAY_TOO_BIG;
10.180 + return false;
10.181 + }
10.182 + *stk = ctx->hp;
10.183 +
10.184 + uint32_t bytes = size * 4;
10.185 +
10.186 + ctx->hp += bytes;
10.187 + if (uintptr_t(ctx->plugin->memory + ctx->hp) >= uintptr_t(stk)) {
10.188 + ctx->err = SP_ERROR_HEAPLOW;
10.189 + return false;
10.190 + }
10.191 +
10.192 + if ((ctx->err = PushTracker(ctx, bytes)) != SP_ERROR_NONE)
10.193 + return false;
10.194 +
10.195 + if (autozero)
10.196 + memset(ctx->plugin->memory + ctx->hp, 0, bytes);
10.197 +
10.198 + return true;
10.199 + }
10.200 +
10.201 + if ((ctx->err = GenerateFullArray(rt, dims, stk, autozero)) != SP_ERROR_NONE)
10.202 + return false;
10.203 +
10.204 + return true;
10.205 +}
10.206 +
10.207 +int
10.208 +Interpret(BaseRuntime *rt, uint32_t aCodeStart, cell_t *rval)
10.209 +{
10.210 + const sp_plugin_t *plugin = rt->plugin();
10.211 + cell_t *code = reinterpret_cast<cell_t *>(plugin->pcode);
10.212 + cell_t *codeend = reinterpret_cast<cell_t *>(plugin->pcode + plugin->pcode_size);
10.213 +
10.214 + if (!IsValidOffset(aCodeStart) || aCodeStart > plugin->pcode_size)
10.215 + return SP_ERROR_INVALID_INSTRUCTION;
10.216 +
10.217 + sp_context_t *ctx = rt->GetBaseContext()->GetCtx();
10.218 + ctx->err = SP_ERROR_NONE;
10.219 +
10.220 + // Save the original frm. BaseContext won't, and if we error, we won't hit
10.221 + // the stack unwinding code.
10.222 + cell_t orig_frm = ctx->frm;
10.223 +
10.224 + cell_t pri = 0;
10.225 + cell_t alt = 0;
10.226 + cell_t *cip = code + (aCodeStart / 4);
10.227 + cell_t *stk = reinterpret_cast<cell_t *>(plugin->memory + ctx->sp);
10.228 +
10.229 + for (;;) {
10.230 + if (cip >= codeend) {
10.231 + ctx->err = SP_ERROR_INVALID_INSTRUCTION;
10.232 + goto error;
10.233 + }
10.234 +
10.235 +#if 0
10.236 + SpewOpcode(plugin, reinterpret_cast<cell_t *>(plugin->pcode + aCodeStart), cip);
10.237 +#endif
10.238 +
10.239 + OPCODE op = (OPCODE)*cip++;
10.240 +
10.241 + switch (op) {
10.242 + case OP_MOVE_PRI:
10.243 + pri = alt;
10.244 + break;
10.245 + case OP_MOVE_ALT:
10.246 + alt = pri;
10.247 + break;
10.248 +
10.249 + case OP_XCHG:
10.250 + {
10.251 + cell_t tmp = pri;
10.252 + pri = alt;
10.253 + alt = tmp;
10.254 + break;
10.255 + }
10.256 +
10.257 + case OP_ZERO:
10.258 + Write(plugin, *cip++, 0);
10.259 + break;
10.260 +
10.261 + case OP_ZERO_S:
10.262 + Write(plugin, *cip++, 0);
10.263 + break;
10.264 +
10.265 + case OP_PUSH_PRI:
10.266 + *--stk = pri;
10.267 + break;
10.268 + case OP_PUSH_ALT:
10.269 + *--stk = alt;
10.270 + break;
10.271 +
10.272 + case OP_PUSH_C:
10.273 + case OP_PUSH2_C:
10.274 + case OP_PUSH3_C:
10.275 + case OP_PUSH4_C:
10.276 + case OP_PUSH5_C:
10.277 + {
10.278 + int n = 1;
10.279 + if (op >= OP_PUSH2_C)
10.280 + n = ((op - OP_PUSH2_C) / 4) + 2;
10.281 +
10.282 + int i = 1;
10.283 + do {
10.284 + *--stk = *cip++;
10.285 + } while (i++ < n);
10.286 + break;
10.287 + }
10.288 +
10.289 + case OP_PUSH_ADR:
10.290 + case OP_PUSH2_ADR:
10.291 + case OP_PUSH3_ADR:
10.292 + case OP_PUSH4_ADR:
10.293 + case OP_PUSH5_ADR:
10.294 + {
10.295 + int n = 1;
10.296 + if (op >= OP_PUSH2_ADR)
10.297 + n = ((op - OP_PUSH2_ADR) / 4) + 2;
10.298 +
10.299 + int i = 1;
10.300 +
10.301 + do {
10.302 + cell_t addr = ctx->frm + *cip++;
10.303 + *--stk = addr;
10.304 + } while (i++ < n);
10.305 + break;
10.306 + }
10.307 +
10.308 + case OP_PUSH_S:
10.309 + case OP_PUSH2_S:
10.310 + case OP_PUSH3_S:
10.311 + case OP_PUSH4_S:
10.312 + case OP_PUSH5_S:
10.313 + {
10.314 + int n = 1;
10.315 + if (op >= OP_PUSH2_S)
10.316 + n = ((op - OP_PUSH2_S) / 4) + 2;
10.317 +
10.318 + int i = 1;
10.319 + do {
10.320 + cell_t value = Read(plugin, ctx->frm + *cip++);
10.321 + *--stk = value;
10.322 + } while (i++ < n);
10.323 + break;
10.324 + }
10.325 +
10.326 + case OP_PUSH:
10.327 + case OP_PUSH2:
10.328 + case OP_PUSH3:
10.329 + case OP_PUSH4:
10.330 + case OP_PUSH5:
10.331 + {
10.332 + int n = 1;
10.333 + if (op >= OP_PUSH2)
10.334 + n = ((op - OP_PUSH2) / 4) + 2;
10.335 +
10.336 + int i = 1;
10.337 + do {
10.338 + cell_t value = Read(plugin, *cip++);
10.339 + *--stk = value;
10.340 + } while (i++ < n);
10.341 + break;
10.342 + }
10.343 +
10.344 + case OP_ZERO_PRI:
10.345 + pri = 0;
10.346 + break;
10.347 + case OP_ZERO_ALT:
10.348 + alt = 0;
10.349 + break;
10.350 +
10.351 + case OP_ADD:
10.352 + pri += alt;
10.353 + break;
10.354 +
10.355 + case OP_SUB:
10.356 + pri -= alt;
10.357 + break;
10.358 +
10.359 + case OP_SUB_ALT:
10.360 + pri = alt - pri;
10.361 + break;
10.362 +
10.363 + case OP_PROC:
10.364 + {
10.365 + *--stk = ctx->frm;
10.366 + *--stk = 0;
10.367 + ctx->frm = uintptr_t(stk) - uintptr_t(plugin->memory);
10.368 + break;
10.369 + }
10.370 +
10.371 + case OP_IDXADDR_B:
10.372 + pri <<= *cip++;
10.373 + pri += alt;
10.374 + break;
10.375 +
10.376 + case OP_SHL:
10.377 + pri <<= alt;
10.378 + break;
10.379 +
10.380 + case OP_SHR:
10.381 + pri = unsigned(pri) >> unsigned(alt);
10.382 + break;
10.383 +
10.384 + case OP_SSHR:
10.385 + pri >>= alt;
10.386 + break;
10.387 +
10.388 + case OP_SHL_C_PRI:
10.389 + pri <<= *cip++;
10.390 + break;
10.391 + case OP_SHL_C_ALT:
10.392 + alt <<= *cip++;
10.393 + break;
10.394 +
10.395 + case OP_SHR_C_PRI:
10.396 + pri >>= *cip++;
10.397 + break;
10.398 + case OP_SHR_C_ALT:
10.399 + alt >>= *cip++;
10.400 + break;
10.401 +
10.402 + case OP_SMUL:
10.403 + pri *= alt;
10.404 + break;
10.405 +
10.406 + case OP_NOT:
10.407 + pri = pri ? 0 : 1;
10.408 + break;
10.409 +
10.410 + case OP_NEG:
10.411 + pri = -pri;
10.412 + break;
10.413 +
10.414 + case OP_XOR:
10.415 + pri ^= alt;
10.416 + break;
10.417 +
10.418 + case OP_OR:
10.419 + pri |= alt;
10.420 + break;
10.421 +
10.422 + case OP_AND:
10.423 + pri &= alt;
10.424 + break;
10.425 +
10.426 + case OP_INVERT:
10.427 + pri = ~pri;
10.428 + break;
10.429 +
10.430 + case OP_ADD_C:
10.431 + pri += *cip++;
10.432 + break;
10.433 +
10.434 + case OP_SMUL_C:
10.435 + pri *= *cip++;
10.436 + break;
10.437 +
10.438 + case OP_EQ:
10.439 + pri = pri == alt;
10.440 + break;
10.441 +
10.442 + case OP_NEQ:
10.443 + pri = pri != alt;
10.444 + break;
10.445 +
10.446 + case OP_SLESS:
10.447 + pri = pri < alt;
10.448 + break;
10.449 +
10.450 + case OP_SLEQ:
10.451 + pri = pri <= alt;
10.452 + break;
10.453 +
10.454 + case OP_SGRTR:
10.455 + pri = pri > alt;
10.456 + break;
10.457 +
10.458 + case OP_SGEQ:
10.459 + pri = pri >= alt;
10.460 + break;
10.461 +
10.462 + case OP_EQ_C_PRI:
10.463 + pri = pri == *cip++;
10.464 + break;
10.465 + case OP_EQ_C_ALT:
10.466 + pri = alt == *cip++;
10.467 + break;
10.468 +
10.469 + case OP_INC_PRI:
10.470 + pri++;
10.471 + break;
10.472 + case OP_INC_ALT:
10.473 + alt++;
10.474 + break;
10.475 +
10.476 + case OP_INC:
10.477 + {
10.478 + cell_t offset = *cip++;
10.479 + Write(plugin, offset, Read(plugin, offset) + 1);
10.480 + break;
10.481 + }
10.482 +
10.483 + case OP_INC_S:
10.484 + {
10.485 + cell_t offset = *cip++;
10.486 + cell_t value = Read(plugin, ctx->frm + offset);
10.487 + Write(plugin, ctx->frm + offset, value + 1);
10.488 + break;
10.489 + }
10.490 +
10.491 + case OP_INC_I:
10.492 + if (!CheckAddress(plugin, ctx, stk, pri))
10.493 + goto error;
10.494 + Write(plugin, pri, Read(plugin, pri) + 1);
10.495 + break;
10.496 +
10.497 + case OP_DEC_PRI:
10.498 + pri--;
10.499 + break;
10.500 + case OP_DEC_ALT:
10.501 + alt--;
10.502 + break;
10.503 +
10.504 + case OP_DEC:
10.505 + {
10.506 + cell_t offset = *cip++;
10.507 + Write(plugin, offset, Read(plugin, offset) - 1);
10.508 + break;
10.509 + }
10.510 +
10.511 + case OP_DEC_S:
10.512 + {
10.513 + cell_t offset = *cip++;
10.514 + cell_t value = Read(plugin, ctx->frm + offset);
10.515 + Write(plugin, ctx->frm + offset, value - 1);
10.516 + break;
10.517 + }
10.518 +
10.519 + case OP_DEC_I:
10.520 + if (!CheckAddress(plugin, ctx, stk, pri))
10.521 + goto error;
10.522 + Write(plugin, pri, Read(plugin, pri) - 1);
10.523 + break;
10.524 +
10.525 + case OP_LOAD_PRI:
10.526 + pri = Read(plugin, *cip++);
10.527 + break;
10.528 + case OP_LOAD_ALT:
10.529 + alt = Read(plugin, *cip++);
10.530 + break;
10.531 +
10.532 + case OP_LOAD_S_PRI:
10.533 + pri = Read(plugin, ctx->frm + *cip++);
10.534 + break;
10.535 + case OP_LOAD_S_ALT:
10.536 + alt = Read(plugin, ctx->frm + *cip++);
10.537 + break;
10.538 +
10.539 + case OP_LOAD_S_BOTH:
10.540 + pri = Read(plugin, ctx->frm + *cip++);
10.541 + alt = Read(plugin, ctx->frm + *cip++);
10.542 + break;
10.543 +
10.544 + case OP_LREF_S_PRI:
10.545 + {
10.546 + pri = Read(plugin, ctx->frm + *cip++);
10.547 + pri = Read(plugin, pri);
10.548 + break;
10.549 + }
10.550 +
10.551 + case OP_LREF_S_ALT:
10.552 + {
10.553 + alt = Read(plugin, ctx->frm + *cip++);
10.554 + alt = Read(plugin, alt);
10.555 + break;
10.556 + }
10.557 +
10.558 + case OP_CONST_PRI:
10.559 + pri = *cip++;
10.560 + break;
10.561 + case OP_CONST_ALT:
10.562 + alt = *cip++;
10.563 + break;
10.564 +
10.565 + case OP_ADDR_PRI:
10.566 + pri = ctx->frm + *cip++;
10.567 + break;
10.568 + case OP_ADDR_ALT:
10.569 + alt = ctx->frm + *cip++;
10.570 + break;
10.571 +
10.572 + case OP_STOR_PRI:
10.573 + Write(plugin, *cip++, pri);
10.574 + break;
10.575 + case OP_STOR_ALT:
10.576 + Write(plugin, *cip++, alt);
10.577 + break;
10.578 +
10.579 + case OP_STOR_S_PRI:
10.580 + Write(plugin, ctx->frm + *cip++, pri);
10.581 + break;
10.582 + case OP_STOR_S_ALT:
10.583 + Write(plugin, ctx->frm +*cip++, alt);
10.584 + break;
10.585 +
10.586 + case OP_IDXADDR:
10.587 + pri = alt + pri * 4;
10.588 + break;
10.589 +
10.590 + case OP_SREF_S_PRI:
10.591 + {
10.592 + cell_t offset = *cip++;
10.593 + cell_t addr = Read(plugin, ctx->frm + offset);
10.594 + Write(plugin, addr, pri);
10.595 + break;
10.596 + }
10.597 +
10.598 + case OP_SREF_S_ALT:
10.599 + {
10.600 + cell_t offset = *cip++;
10.601 + cell_t addr = Read(plugin, ctx->frm + offset);
10.602 + Write(plugin, addr, alt);
10.603 + break;
10.604 + }
10.605 +
10.606 + case OP_POP_PRI:
10.607 + pri = *stk++;
10.608 + break;
10.609 + case OP_POP_ALT:
10.610 + alt = *stk++;
10.611 + break;
10.612 +
10.613 + case OP_SWAP_PRI:
10.614 + case OP_SWAP_ALT:
10.615 + {
10.616 + cell_t reg = (op == OP_SREF_S_PRI) ? pri : alt;
10.617 + cell_t temp = *stk;
10.618 + *stk = reg;
10.619 + reg = temp;
10.620 + break;
10.621 + }
10.622 +
10.623 + case OP_LIDX:
10.624 + pri = alt + pri * 4;
10.625 + if (!CheckAddress(plugin, ctx, stk, pri))
10.626 + goto error;
10.627 + pri = Read(plugin, pri);
10.628 + break;
10.629 +
10.630 + case OP_LIDX_B:
10.631 + {
10.632 + cell_t val = *cip++;
10.633 + pri = alt + (pri << val);
10.634 + if (!CheckAddress(plugin, ctx, stk, pri))
10.635 + goto error;
10.636 + pri = Read(plugin, pri);
10.637 + break;
10.638 + }
10.639 +
10.640 + case OP_CONST:
10.641 + {
10.642 + cell_t offset = *cip++;
10.643 + cell_t value = *cip++;
10.644 + Write(plugin, offset, value);
10.645 + break;
10.646 + }
10.647 +
10.648 + case OP_CONST_S:
10.649 + {
10.650 + cell_t offset = *cip++;
10.651 + cell_t value = *cip++;
10.652 + Write(plugin, ctx->frm + offset, value);
10.653 + break;
10.654 + }
10.655 +
10.656 + case OP_LOAD_I:
10.657 + if (!CheckAddress(plugin, ctx, stk, pri))
10.658 + goto error;
10.659 + pri = Read(plugin, pri);
10.660 + break;
10.661 +
10.662 + case OP_STOR_I:
10.663 + if (!CheckAddress(plugin, ctx, stk, alt))
10.664 + goto error;
10.665 + Write(plugin, alt, pri);
10.666 + break;
10.667 +
10.668 + case OP_SDIV:
10.669 + case OP_SDIV_ALT:
10.670 + {
10.671 + cell_t dividend = (op == OP_SDIV) ? pri : alt;
10.672 + cell_t divisor = (op == OP_SDIV) ? alt : pri;
10.673 + if (divisor == 0) {
10.674 + ctx->err = SP_ERROR_DIVIDE_BY_ZERO;
10.675 + goto error;
10.676 + }
10.677 + if (dividend == INT_MIN && divisor == -1) {
10.678 + ctx->err = SP_ERROR_INTEGER_OVERFLOW;
10.679 + goto error;
10.680 + }
10.681 + pri = dividend / divisor;
10.682 + alt = dividend % divisor;
10.683 + break;
10.684 + }
10.685 +
10.686 + case OP_LODB_I:
10.687 + {
10.688 + cell_t val = *cip++;
10.689 + if (!CheckAddress(plugin, ctx, stk, pri))
10.690 + goto error;
10.691 + pri = Read(plugin, pri);
10.692 + if (val == 1)
10.693 + pri &= 0xff;
10.694 + else if (val == 2)
10.695 + pri &= 0xffff;
10.696 + break;
10.697 + }
10.698 +
10.699 + case OP_STRB_I:
10.700 + {
10.701 + cell_t val = *cip++;
10.702 + if (!CheckAddress(plugin, ctx, stk, alt))
10.703 + goto error;
10.704 + if (val == 1)
10.705 + *reinterpret_cast<int8_t *>(plugin->memory + alt) = pri;
10.706 + else if (val == 2)
10.707 + *reinterpret_cast<int16_t *>(plugin->memory + alt) = pri;
10.708 + else if (val == 4)
10.709 + *reinterpret_cast<int32_t *>(plugin->memory + alt) = pri;
10.710 + break;
10.711 + }
10.712 +
10.713 + case OP_RETN:
10.714 + {
10.715 + stk++;
10.716 + ctx->frm = *stk++;
10.717 + stk += *stk + 1;
10.718 + *rval = pri;
10.719 + ctx->err = SP_ERROR_NONE;
10.720 + goto done;
10.721 + }
10.722 +
10.723 + case OP_MOVS:
10.724 + {
10.725 + uint8_t *src = plugin->memory + pri;
10.726 + uint8_t *dest = plugin->memory + alt;
10.727 + memcpy(dest, src, *cip++);
10.728 + break;
10.729 + }
10.730 +
10.731 + case OP_FILL:
10.732 + {
10.733 + uint8_t *dest = plugin->memory + alt;
10.734 + memset(dest, pri, *cip++);
10.735 + break;
10.736 + }
10.737 +
10.738 + case OP_STRADJUST_PRI:
10.739 + pri += 4;
10.740 + pri >>= 2;
10.741 + break;
10.742 +
10.743 + case OP_STACK:
10.744 + {
10.745 + cell_t amount = *cip++;
10.746 + if (!IsValidOffset(amount)) {
10.747 + ctx->err = SP_ERROR_INVALID_INSTRUCTION;
10.748 + goto error;
10.749 + }
10.750 +
10.751 + stk += amount / 4;
10.752 + if (amount > 0) {
10.753 + if (uintptr_t(stk) >= uintptr_t(plugin->memory + plugin->mem_size)) {
10.754 + ctx->err = SP_ERROR_STACKMIN;
10.755 + goto error;
10.756 + }
10.757 + } else {
10.758 + if (uintptr_t(stk) < uintptr_t(plugin->memory + ctx->hp + STACK_MARGIN)) {
10.759 + ctx->err = SP_ERROR_STACKLOW;
10.760 + goto error;
10.761 + }
10.762 + }
10.763 + break;
10.764 + }
10.765 +
10.766 + case OP_HEAP:
10.767 + {
10.768 + cell_t amount = *cip++;
10.769 +
10.770 + alt = ctx->hp;
10.771 + ctx->hp += amount;
10.772 +
10.773 + if (amount > 0) {
10.774 + if (uintptr_t(plugin->memory + ctx->hp) > uintptr_t(stk)) {
10.775 + ctx->err = SP_ERROR_HEAPLOW;
10.776 + goto error;
10.777 + }
10.778 + } else {
10.779 + if (uint32_t(ctx->hp) < plugin->data_size) {
10.780 + ctx->err = SP_ERROR_HEAPMIN;
10.781 + goto error;
10.782 + }
10.783 + }
10.784 + break;
10.785 + }
10.786 +
10.787 + case OP_JUMP:
10.788 + if ((cip = JumpTarget(plugin, ctx, cip, true)) == NULL)
10.789 + goto error;
10.790 + break;
10.791 +
10.792 + case OP_JZER:
10.793 + if ((cip = JumpTarget(plugin, ctx, cip, pri == 0)) == NULL)
10.794 + goto error;
10.795 + break;
10.796 + case OP_JNZ:
10.797 + if ((cip = JumpTarget(plugin, ctx, cip, pri != 0)) == NULL)
10.798 + goto error;
10.799 + break;
10.800 +
10.801 + case OP_JEQ:
10.802 + if ((cip = JumpTarget(plugin, ctx, cip, pri == alt)) == NULL)
10.803 + goto error;
10.804 + break;
10.805 + case OP_JNEQ:
10.806 + if ((cip = JumpTarget(plugin, ctx, cip, pri != alt)) == NULL)
10.807 + goto error;
10.808 + break;
10.809 + case OP_JSLESS:
10.810 + if ((cip = JumpTarget(plugin, ctx, cip, pri < alt)) == NULL)
10.811 + goto error;
10.812 + break;
10.813 + case OP_JSLEQ:
10.814 + if ((cip = JumpTarget(plugin, ctx, cip, pri <= alt)) == NULL)
10.815 + goto error;
10.816 + break;
10.817 + case OP_JSGRTR:
10.818 + if ((cip = JumpTarget(plugin, ctx, cip, pri > alt)) == NULL)
10.819 + goto error;
10.820 + break;
10.821 + case OP_JSGEQ:
10.822 + if ((cip = JumpTarget(plugin, ctx, cip, pri >= alt)) == NULL)
10.823 + goto error;
10.824 + break;
10.825 +
10.826 + case OP_TRACKER_PUSH_C:
10.827 + {
10.828 + cell_t amount = *cip++;
10.829 + int error = PushTracker(ctx, amount * 4);
10.830 + if (error != SP_ERROR_NONE) {
10.831 + ctx->err = error;
10.832 + goto error;
10.833 + }
10.834 + break;
10.835 + }
10.836 +
10.837 + case OP_TRACKER_POP_SETHEAP:
10.838 + {
10.839 + int error = PopTrackerAndSetHeap(rt);
10.840 + if (error != SP_ERROR_NONE) {
10.841 + ctx->err = error;
10.842 + goto error;
10.843 + }
10.844 + break;
10.845 + }
10.846 +
10.847 + case OP_BREAK:
10.848 + ctx->cip = uintptr_t(cip - 1) - uintptr_t(plugin->pcode);
10.849 + break;
10.850 +
10.851 + case OP_BOUNDS:
10.852 + {
10.853 + cell_t value = *cip++;
10.854 + if (uint32_t(pri) > uint32_t(value)) {
10.855 + ctx->err = SP_ERROR_ARRAY_BOUNDS;
10.856 + goto error;
10.857 + }
10.858 + break;
10.859 + }
10.860 +
10.861 + case OP_CALL:
10.862 + {
10.863 + cell_t offset = *cip++;
10.864 +
10.865 + if (!IsValidOffset(offset) || uint32_t(offset) >= plugin->pcode_size) {
10.866 + ctx->err = SP_ERROR_INSTRUCTION_PARAM;
10.867 + goto error;
10.868 + }
10.869 +
10.870 + if (ctx->rp >= SP_MAX_RETURN_STACK) {
10.871 + ctx->err = SP_ERROR_STACKLOW;
10.872 + goto error;
10.873 + }
10.874 +
10.875 + // For debugging.
10.876 + uintptr_t rcip = uintptr_t(cip - 2) - uintptr_t(plugin->pcode);
10.877 + ctx->rstk_cips[ctx->rp++] = rcip;
10.878 + ctx->cip = offset;
10.879 + ctx->sp = uintptr_t(stk) - uintptr_t(plugin->memory);
10.880 +
10.881 + int err = Interpret(rt, offset, &pri);
10.882 +
10.883 + stk = reinterpret_cast<cell_t *>(plugin->memory + ctx->sp);
10.884 + ctx->cip = rcip;
10.885 + ctx->rp--;
10.886 +
10.887 + if (err != SP_ERROR_NONE)
10.888 + goto error;
10.889 + break;
10.890 + }
10.891 +
10.892 + case OP_GENARRAY:
10.893 + case OP_GENARRAY_Z:
10.894 + {
10.895 + cell_t val = *cip++;
10.896 + if (!GenerateArray(rt, ctx, val, stk, op == OP_GENARRAY_Z))
10.897 + goto error;
10.898 +
10.899 + stk += (val - 1) * 4;
10.900 + break;
10.901 + }
10.902 +
10.903 + case OP_SYSREQ_C:
10.904 + case OP_SYSREQ_N:
10.905 + {
10.906 + uint32_t native_index = *cip++;
10.907 +
10.908 + if (native_index >= plugin->num_natives) {
10.909 + ctx->err = SP_ERROR_INSTRUCTION_PARAM;
10.910 + goto error;
10.911 + }
10.912 +
10.913 + uint32_t num_params;
10.914 + if (op == OP_SYSREQ_N) {
10.915 + num_params = *cip++;
10.916 + *--stk = num_params;
10.917 + }
10.918 +
10.919 + ctx->sp = uintptr_t(stk) - uintptr_t(plugin->memory);
10.920 + pri = NativeCallback(ctx, native_index, stk);
10.921 + if (ctx->n_err != SP_ERROR_NONE) {
10.922 + ctx->err = ctx->n_err;
10.923 + goto error;
10.924 + }
10.925 +
10.926 + if (op == OP_SYSREQ_N)
10.927 + stk += num_params + 1;
10.928 + break;
10.929 + }
10.930 +
10.931 + case OP_SWITCH:
10.932 + {
10.933 + cell_t offset = *cip++;
10.934 + cell_t *table = reinterpret_cast<cell_t *>(plugin->pcode + offset + sizeof(cell_t));
10.935 +
10.936 + size_t ncases = *table++;
10.937 + cell_t target = *table++; // default case
10.938 +
10.939 + for (size_t i = 0; i < ncases; i++) {
10.940 + if (table[i * 2] == pri) {
10.941 + target = table[i * 2 + 1];
10.942 + break;
10.943 + }
10.944 + }
10.945 +
10.946 + if ((cip = Jump(plugin, ctx, target)) == NULL)
10.947 + goto error;
10.948 + break;
10.949 + }
10.950 +
10.951 + default:
10.952 + {
10.953 + ctx->err = SP_ERROR_INVALID_INSTRUCTION;
10.954 + goto error;
10.955 + }
10.956 + } // switch
10.957 + }
10.958 +
10.959 + done:
10.960 + assert(orig_frm == ctx->frm);
10.961 + ctx->sp = uintptr_t(stk) - uintptr_t(plugin->memory);
10.962 + return ctx->err;
10.963 +
10.964 + error:
10.965 + ctx->frm = orig_frm;
10.966 + goto done;
10.967 +}
10.968 +
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
11.2 +++ b/sourcepawn/jit/interpreter.h Sun Sep 01 00:23:44 2013 -0700
11.3 @@ -0,0 +1,39 @@
11.4 +// vim: set ts=8 sts=2 sw=2 tw=99 et:
11.5 +//
11.6 +// This file is part of SourcePawn.
11.7 +//
11.8 +// SourcePawn is free software: you can redistribute it and/or modify
11.9 +// it under the terms of the GNU General Public License as published by
11.10 +// the Free Software Foundation, either version 3 of the License, or
11.11 +// (at your option) any later version.
11.12 +//
11.13 +// SourcePawn is distributed in the hope that it will be useful,
11.14 +// but WITHOUT ANY WARRANTY; without even the implied warranty of
11.15 +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11.16 +// GNU General Public License for more details.
11.17 +//
11.18 +// You should have received a copy of the GNU General Public License
11.19 +// along with SourcePawn. If not, see <http://www.gnu.org/licenses/>.
11.20 +#ifndef _include_sourcepawn_interpreter_h_
11.21 +#define _include_sourcepawn_interpreter_h_
11.22 +
11.23 +#include <sp_vm_types.h>
11.24 +#include <sp_vm_api.h>
11.25 +#include "BaseRuntime.h"
11.26 +#include "sp_vm_basecontext.h"
11.27 +
11.28 +struct tracker_t
11.29 +{
11.30 + size_t size;
11.31 + ucell_t *pBase;
11.32 + ucell_t *pCur;
11.33 +};
11.34 +
11.35 +int Interpret(BaseRuntime *rt, uint32_t aCodeStart, cell_t *rval);
11.36 +
11.37 +int GenerateFullArray(BaseRuntime *rt, uint32_t argc, cell_t *argv, int autozero);
11.38 +cell_t NativeCallback(sp_context_t *ctx, ucell_t native_idx, cell_t *params);
11.39 +int PopTrackerAndSetHeap(BaseRuntime *rt);
11.40 +int PushTracker(sp_context_t *ctx, size_t amount);
11.41 +
11.42 +#endif // _include_sourcepawn_interpreter_h_
12.1 --- a/sourcepawn/jit/jit_shared.h Sat Aug 31 19:50:36 2013 -0700
12.2 +++ b/sourcepawn/jit/jit_shared.h Sun Sep 01 00:23:44 2013 -0700
12.3 @@ -67,6 +67,9 @@
12.4 } sp_plugin_t;
12.5 }
12.6
12.7 +struct tracker_t;
12.8 +class BaseContext;
12.9 +
12.10 typedef struct sp_context_s
12.11 {
12.12 cell_t hp; /**< Heap pointer */
12.13 @@ -74,8 +77,12 @@
12.14 cell_t frm; /**< Frame pointer */
12.15 cell_t rval; /**< Return value from InvokeFunction() */
12.16 int32_t cip; /**< Code pointer last error occurred in */
12.17 + int32_t err; /**< Error last set by interpreter */
12.18 int32_t n_err; /**< Error code set by a native */
12.19 uint32_t n_idx; /**< Current native index being executed */
12.20 + tracker_t *tracker;
12.21 + sp_plugin_t *plugin;
12.22 + BaseContext *basecx;
12.23 void * vm[8]; /**< VM-specific pointers */
12.24 cell_t rp; /**< Return stack pointer */
12.25 cell_t rstk_cips[SP_MAX_RETURN_STACK];
13.1 --- a/sourcepawn/jit/sp_vm_basecontext.cpp Sat Aug 31 19:50:36 2013 -0700
13.2 +++ b/sourcepawn/jit/sp_vm_basecontext.cpp Sun Sep 01 00:23:44 2013 -0700
13.3 @@ -38,6 +38,8 @@
13.4 #include "sp_vm_engine.h"
13.5 #include "watchdog_timer.h"
13.6 #include "x86/jit_x86.h"
13.7 +#include "engine2.h"
13.8 +#include "interpreter.h"
13.9
13.10 using namespace SourcePawn;
13.11
13.12 @@ -595,7 +597,7 @@
13.13 }
13.14
13.15 /* See if we have to compile the callee. */
13.16 - if ((fn = m_pRuntime->m_PubJitFuncs[public_id]) == NULL)
13.17 + if (g_engine2.IsJitEnabled() && (fn = m_pRuntime->m_PubJitFuncs[public_id]) == NULL)
13.18 {
13.19 /* We might not have to - check pcode offset. */
13.20 fn = m_pRuntime->GetJittedFunctionByOffset(pubfunc->code_offs);
13.21 @@ -646,7 +648,10 @@
13.22
13.23 /* Start the frame tracer */
13.24
13.25 - ir = g_Jit.InvokeFunction(m_pRuntime, fn, result);
13.26 + if (g_engine2.IsJitEnabled())
13.27 + ir = g_Jit.InvokeFunction(m_pRuntime, fn, result);
13.28 + else
13.29 + ir = Interpret(m_pRuntime, pubfunc->code_offs, result);
13.30
13.31 /* Restore some states, stop the frame tracer */
13.32
14.1 --- a/sourcepawn/jit/x86/jit_x86.cpp Sat Aug 31 19:50:36 2013 -0700
14.2 +++ b/sourcepawn/jit/x86/jit_x86.cpp Sun Sep 01 00:23:44 2013 -0700
14.3 @@ -38,6 +38,7 @@
14.4 #include "../BaseRuntime.h"
14.5 #include "../sp_vm_basecontext.h"
14.6 #include "watchdog_timer.h"
14.7 +#include "interpreter.h"
14.8
14.9 using namespace Knight;
14.10
14.11 @@ -166,50 +167,8 @@
14.12 return data_offs;
14.13 }
14.14
14.15 -static int
14.16 -PopTrackerAndSetHeap(BaseRuntime *rt)
14.17 -{
14.18 - sp_context_t *ctx = rt->GetBaseContext()->GetCtx();
14.19 - tracker_t *trk = (tracker_t *)(ctx->vm[JITVARS_TRACKER]);
14.20 - assert(trk->pCur > trk->pBase);
14.21 -
14.22 - trk->pCur--;
14.23 - if (trk->pCur < trk->pBase)
14.24 - return SP_ERROR_TRACKER_BOUNDS;
14.25 -
14.26 - ucell_t amt = *trk->pCur;
14.27 - if (amt > (ctx->hp - rt->plugin()->data_size))
14.28 - return SP_ERROR_HEAPMIN;
14.29 -
14.30 - ctx->hp -= amt;
14.31 - return SP_ERROR_NONE;
14.32 -}
14.33 -
14.34 -static int
14.35 -PushTracker(sp_context_t *ctx, size_t amount)
14.36 -{
14.37 - tracker_t *trk = (tracker_t *)(ctx->vm[JITVARS_TRACKER]);
14.38 -
14.39 - if ((size_t)(trk->pCur - trk->pBase) >= trk->size)
14.40 - return SP_ERROR_TRACKER_BOUNDS;
14.41 -
14.42 - if (trk->pCur + 1 - (trk->pBase + trk->size) == 0) {
14.43 - size_t disp = trk->size - 1;
14.44 - trk->size *= 2;
14.45 - trk->pBase = (ucell_t *)realloc(trk->pBase, trk->size * sizeof(cell_t));
14.46 -
14.47 - if (!trk->pBase)
14.48 - return SP_ERROR_TRACKER_BOUNDS;
14.49 -
14.50 - trk->pCur = trk->pBase + disp;
14.51 - }
14.52 -
14.53 - *trk->pCur++ = amount;
14.54 - return SP_ERROR_NONE;
14.55 -}
14.56 -
14.57 -static int
14.58 -GenerateArray(BaseRuntime *rt, uint32_t argc, cell_t *argv, int autozero)
14.59 +int
14.60 +GenerateFullArray(BaseRuntime *rt, uint32_t argc, cell_t *argv, int autozero)
14.61 {
14.62 sp_context_t *ctx = rt->GetBaseContext()->GetCtx();
14.63
14.64 @@ -342,55 +301,6 @@
14.65 return SP_ERROR_NONE;
14.66 }
14.67
14.68 -static cell_t
14.69 -NativeCallback(sp_context_t *ctx, ucell_t native_idx, cell_t *params)
14.70 -{
14.71 - sp_native_t *native;
14.72 - cell_t save_sp = ctx->sp;
14.73 - cell_t save_hp = ctx->hp;
14.74 - sp_plugin_t *pl = (sp_plugin_t *)(ctx->vm[JITVARS_PLUGIN]);
14.75 -
14.76 - ctx->n_idx = native_idx;
14.77 -
14.78 - if (ctx->hp < (cell_t)pl->data_size) {
14.79 - ctx->n_err = SP_ERROR_HEAPMIN;
14.80 - return 0;
14.81 - }
14.82 -
14.83 - if (ctx->hp + STACK_MARGIN > ctx->sp) {
14.84 - ctx->n_err = SP_ERROR_STACKLOW;
14.85 - return 0;
14.86 - }
14.87 -
14.88 - if ((uint32_t)ctx->sp >= pl->mem_size) {
14.89 - ctx->n_err = SP_ERROR_STACKMIN;
14.90 - return 0;
14.91 - }
14.92 -
14.93 - native = &pl->natives[native_idx];
14.94 -
14.95 - if (native->status == SP_NATIVE_UNBOUND) {
14.96 - ctx->n_err = SP_ERROR_INVALID_NATIVE;
14.97 - return 0;
14.98 - }
14.99 -
14.100 - cell_t result = native->pfn(GET_CONTEXT(ctx), params);
14.101 -
14.102 - if (ctx->n_err != SP_ERROR_NONE)
14.103 - return result;
14.104 -
14.105 - if (save_sp != ctx->sp) {
14.106 - ctx->n_err = SP_ERROR_STACKLEAK;
14.107 - return result;
14.108 - }
14.109 - if (save_hp != ctx->hp) {
14.110 - ctx->n_err = SP_ERROR_HEAPLEAK;
14.111 - return result;
14.112 - }
14.113 -
14.114 - return result;
14.115 -}
14.116 -
14.117 Compiler::Compiler(BaseRuntime *rt, cell_t pcode_offs)
14.118 : rt_(rt),
14.119 plugin_(rt->plugin()),
14.120 @@ -1226,7 +1136,7 @@
14.121 __ movl(alt, Operand(hpAddr()));
14.122 __ addl(Operand(hpAddr()), amount);
14.123
14.124 - if (amount > 0) {
14.125 + if (amount < 0) {
14.126 __ cmpl(Operand(hpAddr()), plugin_->data_size);
14.127 __ j(below, &error_heap_min_);
14.128 } else {
14.129 @@ -1473,7 +1383,7 @@
14.130 __ push(stk);
14.131 __ push(val);
14.132 __ push(intptr_t(rt_));
14.133 - __ call(ExternalAddress((void *)GenerateArray));
14.134 + __ call(ExternalAddress((void *)GenerateFullArray));
14.135 __ addl(esp, 4 * sizeof(void *));
14.136
14.137 // restore pri to tmp
14.138 @@ -1921,16 +1831,13 @@
14.139 void
14.140 JITX86::SetupContextVars(BaseRuntime *runtime, BaseContext *pCtx, sp_context_t *ctx)
14.141 {
14.142 - tracker_t *trk = new tracker_t;
14.143 -
14.144 - ctx->vm[JITVARS_TRACKER] = trk;
14.145 - ctx->vm[JITVARS_BASECTX] = pCtx; /* GetDefaultContext() is not constructed yet */
14.146 + ctx->tracker = new tracker_t;
14.147 + ctx->tracker->pBase = (ucell_t *)malloc(1024);
14.148 + ctx->tracker->pCur = ctx->tracker->pBase;
14.149 + ctx->tracker->size = 1024 / sizeof(cell_t);
14.150 + ctx->basecx = pCtx;
14.151 ctx->vm[JITVARS_PROFILER] = g_engine2.GetProfiler();
14.152 - ctx->vm[JITVARS_PLUGIN] = const_cast<sp_plugin_t *>(runtime->plugin());
14.153 -
14.154 - trk->pBase = (ucell_t *)malloc(1024);
14.155 - trk->pCur = trk->pBase;
14.156 - trk->size = 1024 / sizeof(cell_t);
14.157 + ctx->plugin = const_cast<sp_plugin_t *>(runtime->plugin());
14.158 }
14.159
14.160 SPVM_NATIVE_FUNC
14.161 @@ -1987,8 +1894,8 @@
14.162 void
14.163 JITX86::FreeContextVars(sp_context_t *ctx)
14.164 {
14.165 - free(((tracker_t *)(ctx->vm[JITVARS_TRACKER]))->pBase);
14.166 - delete (tracker_t *)ctx->vm[JITVARS_TRACKER];
14.167 + free(ctx->tracker->pBase);
14.168 + delete ctx->tracker;
14.169 }
14.170
14.171 bool
15.1 --- a/sourcepawn/jit/x86/jit_x86.h Sat Aug 31 19:50:36 2013 -0700
15.2 +++ b/sourcepawn/jit/x86/jit_x86.h Sun Sep 01 00:23:44 2013 -0700
15.3 @@ -36,22 +36,10 @@
15.4 #define STACK_MARGIN 64 //8 parameters of safety, I guess
15.5 #define JIT_FUNCMAGIC 0x214D4148 //magic function offset
15.6
15.7 -#define JITVARS_TRACKER 0 //important: don't change this to avoid trouble
15.8 -#define JITVARS_BASECTX 1 //important: don't change this aWOAWOGJQG I LIKE HAM
15.9 #define JITVARS_PROFILER 2 //profiler
15.10 -#define JITVARS_PLUGIN 3 //sp_plugin_t
15.11
15.12 #define sDIMEN_MAX 5 //this must mirror what the compiler has.
15.13
15.14 -#define GET_CONTEXT(c) ((IPluginContext *)c->vm[JITVARS_BASECTX])
15.15 -
15.16 -typedef struct tracker_s
15.17 -{
15.18 - size_t size;
15.19 - ucell_t *pBase;
15.20 - ucell_t *pCur;
15.21 -} tracker_t;
15.22 -
15.23 typedef struct funcinfo_s
15.24 {
15.25 unsigned int magic;