From 37af05c4564b24e0e6c956cbb71cc8bcacee798b Mon Sep 17 00:00:00 2001 From: "dvander@alliedmods.net" Date: Tue, 24 Feb 2015 15:20:00 -0800 Subject: [PATCH 01/14] Move the debug return stack into PluginContext. --- sourcepawn/jit/AMBuilder | 5 ++++- sourcepawn/jit/debug-trace.cpp | 9 ++++----- sourcepawn/jit/debug-trace.h | 2 ++ sourcepawn/jit/interpreter.cpp | 13 ++++++------- sourcepawn/jit/jit_shared.h | 2 -- sourcepawn/jit/plugin-context.cpp | 10 +++++----- sourcepawn/jit/plugin-context.h | 29 +++++++++++++++++++++++++++++ sourcepawn/jit/x86/jit_x86.cpp | 12 ++++++------ 8 files changed, 56 insertions(+), 26 deletions(-) diff --git a/sourcepawn/jit/AMBuilder b/sourcepawn/jit/AMBuilder index 88ba7434..ec77f382 100644 --- a/sourcepawn/jit/AMBuilder +++ b/sourcepawn/jit/AMBuilder @@ -18,7 +18,10 @@ def setup(binary): compiler = binary.compiler compiler.includes += Includes if compiler.vendor == 'gcc' or compiler.vendor == 'clang': - compiler.cxxflags += ['-fno-rtti'] + compiler.cxxflags += [ + '-fno-rtti', + '-Wno-invalid-offsetof', + ] elif binary.compiler.vendor == 'msvc': compiler.cxxflags += ['/GR-'] diff --git a/sourcepawn/jit/debug-trace.cpp b/sourcepawn/jit/debug-trace.cpp index c3a3e60d..569d3291 100644 --- a/sourcepawn/jit/debug-trace.cpp +++ b/sourcepawn/jit/debug-trace.cpp @@ -20,6 +20,7 @@ using namespace SourcePawn; CContextTrace::CContextTrace(PluginRuntime *pRuntime, int err, const char *errstr, cell_t start_rp) : m_pRuntime(pRuntime), + context_(pRuntime->GetBaseContext()), m_Error(err), m_pMsg(errstr), m_StartRp(start_rp), @@ -66,20 +67,18 @@ CContextTrace::GetTraceInfo(CallStackInfo *trace) if (m_Level == 0) { cip = m_ctx->cip; - } else if (m_ctx->rp > 0) { + } else if (context_->rp() > 0) { /* Entries go from ctx.rp - 1 to m_StartRp */ cell_t offs, start, end; offs = m_Level - 1; - start = m_ctx->rp - 1; + start = context_->rp() - 1; end = m_StartRp; if (start - offs < end) - { return false; - } - cip = m_ctx->rstk_cips[start - offs]; + cip = context_->getReturnStackCip(start - offs); } else { return false; } diff --git a/sourcepawn/jit/debug-trace.h b/sourcepawn/jit/debug-trace.h index e6d3f3f2..acecae2c 100644 --- a/sourcepawn/jit/debug-trace.h +++ b/sourcepawn/jit/debug-trace.h @@ -16,6 +16,7 @@ #include class PluginRuntime; +class PluginContext; namespace sp { @@ -37,6 +38,7 @@ class CContextTrace : public IContextTrace private: PluginRuntime *m_pRuntime; + PluginContext *context_; sp_context_t *m_ctx; int m_Error; const char *m_pMsg; diff --git a/sourcepawn/jit/interpreter.cpp b/sourcepawn/jit/interpreter.cpp index 1cc394cd..adcfb47f 100644 --- a/sourcepawn/jit/interpreter.cpp +++ b/sourcepawn/jit/interpreter.cpp @@ -236,7 +236,8 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) if (!IsValidOffset(aCodeStart) || aCodeStart > plugin->pcode_size) return SP_ERROR_INVALID_INSTRUCTION; - sp_context_t *ctx = rt->GetBaseContext()->GetCtx(); + PluginContext *cx = rt->GetBaseContext(); + sp_context_t *ctx = cx->GetCtx(); ctx->err = SP_ERROR_NONE; // Save the original frm. BaseContext won't, and if we error, we won't hit @@ -889,14 +890,12 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) goto error; } - if (ctx->rp >= SP_MAX_RETURN_STACK) { + // For debugging. + uintptr_t rcip = uintptr_t(cip - 2) - uintptr_t(plugin->pcode); + if (!cx->pushReturnCip(rcip)) { ctx->err = SP_ERROR_STACKLOW; goto error; } - - // For debugging. - uintptr_t rcip = uintptr_t(cip - 2) - uintptr_t(plugin->pcode); - ctx->rstk_cips[ctx->rp++] = rcip; ctx->cip = offset; ctx->sp = uintptr_t(stk) - uintptr_t(plugin->memory); @@ -904,7 +903,7 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) stk = reinterpret_cast(plugin->memory + ctx->sp); ctx->cip = rcip; - ctx->rp--; + cx->popReturnCip(); if (err != SP_ERROR_NONE) goto error; diff --git a/sourcepawn/jit/jit_shared.h b/sourcepawn/jit/jit_shared.h index 8c615bf4..7cdb176a 100644 --- a/sourcepawn/jit/jit_shared.h +++ b/sourcepawn/jit/jit_shared.h @@ -85,8 +85,6 @@ typedef struct sp_context_s sp_plugin_t *plugin; PluginContext *basecx; void * vm[8]; /**< VM-specific pointers */ - cell_t rp; /**< Return stack pointer */ - cell_t rstk_cips[SP_MAX_RETURN_STACK]; } sp_context_t; //#define SPFLAG_PLUGIN_DEBUG (1<<0) diff --git a/sourcepawn/jit/plugin-context.cpp b/sourcepawn/jit/plugin-context.cpp index 79d0e451..f444826c 100644 --- a/sourcepawn/jit/plugin-context.cpp +++ b/sourcepawn/jit/plugin-context.cpp @@ -56,7 +56,7 @@ PluginContext::PluginContext(PluginRuntime *pRuntime) m_ctx.frm = m_ctx.sp; m_ctx.n_err = SP_ERROR_NONE; m_ctx.n_idx = SP_ERROR_NONE; - m_ctx.rp = 0; + rp_ = 0; m_ctx.tracker = new tracker_t; m_ctx.tracker->pBase = (ucell_t *)malloc(1024); @@ -584,7 +584,7 @@ PluginContext::Execute2(IPluginFunction *function, const cell_t *params, unsigne save_hp = m_ctx.hp; save_exec = m_InExec; save_n_idx = m_ctx.n_idx; - save_rp = m_ctx.rp; + save_rp = rp_; save_cip = m_ctx.cip; /* Push parameters */ @@ -628,10 +628,10 @@ PluginContext::Execute2(IPluginFunction *function, const cell_t *params, unsigne m_ctx.hp, save_hp); } - if (m_ctx.rp != save_rp) { + if (rp_ != save_rp) { ir = SP_ERROR_STACKLEAK; _SetErrorMessage("Return stack leak detected: rp:%d should be %d!", - m_ctx.rp, + rp_, save_rp); } } @@ -644,7 +644,7 @@ PluginContext::Execute2(IPluginFunction *function, const cell_t *params, unsigne m_ctx.sp = save_sp; m_ctx.hp = save_hp; - m_ctx.rp = save_rp; + rp_ = save_rp; m_ctx.cip = save_cip; m_ctx.n_idx = save_n_idx; diff --git a/sourcepawn/jit/plugin-context.h b/sourcepawn/jit/plugin-context.h index a96da4a2..b853a247 100644 --- a/sourcepawn/jit/plugin-context.h +++ b/sourcepawn/jit/plugin-context.h @@ -76,6 +76,31 @@ class PluginContext : public IPluginContext public: bool IsInExec(); + static inline size_t offsetOfRp() { + return offsetof(PluginContext, rp_); + } + static inline size_t offsetOfRstkCips() { + return offsetof(PluginContext, rstk_cips_); + } + + bool pushReturnCip(cell_t cip) { + if (rp_ >= SP_MAX_RETURN_STACK) + return false; + rstk_cips_[rp_++] = cip; + return true; + } + void popReturnCip() { + assert(rp_ > 0); + rp_--; + } + cell_t rp() const { + return rp_; + } + cell_t getReturnStackCip(int index) { + assert(index >= 0 && index < SP_MAX_RETURN_STACK); + return rstk_cips_[index]; + } + private: void SetErrorMessage(const char *msg, va_list ap); void _SetErrorMessage(const char *msg, ...); @@ -90,6 +115,10 @@ class PluginContext : public IPluginContext sp_context_t m_ctx; void *m_keys[4]; bool m_keys_set[4]; + + // Return stack. + cell_t rp_; + cell_t rstk_cips_[SP_MAX_RETURN_STACK]; }; #endif //_INCLUDE_SOURCEPAWN_BASECONTEXT_H_ diff --git a/sourcepawn/jit/x86/jit_x86.cpp b/sourcepawn/jit/x86/jit_x86.cpp index 5c00bcac..1422b88a 100644 --- a/sourcepawn/jit/x86/jit_x86.cpp +++ b/sourcepawn/jit/x86/jit_x86.cpp @@ -1462,8 +1462,8 @@ Compiler::emitCall() // eax = context // ecx = rp - __ movl(eax, intptr_t(rt_->GetBaseContext()->GetCtx())); - __ movl(ecx, Operand(eax, offsetof(sp_context_t, rp))); + __ movl(eax, intptr_t(rt_->GetBaseContext())); + __ movl(ecx, Operand(eax, PluginContext::offsetOfRp())); // Check if the return stack is used up. __ cmpl(ecx, SP_MAX_RETURN_STACK); @@ -1471,10 +1471,10 @@ Compiler::emitCall() // Add to the return stack. uintptr_t cip = uintptr_t(cip_ - 2) - uintptr_t(plugin_->pcode); - __ movl(Operand(eax, ecx, ScaleFour, offsetof(sp_context_t, rstk_cips)), cip); + __ movl(Operand(eax, ecx, ScaleFour, PluginContext::offsetOfRstkCips()), cip); // Increment the return stack pointer. - __ addl(Operand(eax, offsetof(sp_context_t, rp)), 1); + __ addl(Operand(eax, PluginContext::offsetOfRp()), 1); // Store the CIP of the function we're about to call. __ movl(Operand(cipAddr()), offset); @@ -1495,8 +1495,8 @@ Compiler::emitCall() __ movl(Operand(cipAddr()), cip); // Mark us as leaving the last frame. - __ movl(tmp, intptr_t(rt_->GetBaseContext()->GetCtx())); - __ subl(Operand(tmp, offsetof(sp_context_t, rp)), 1); + __ movl(tmp, intptr_t(rt_->GetBaseContext())); + __ subl(Operand(tmp, PluginContext::offsetOfRp()), 1); return true; } From deedc1aaa6f96b670cde805443e9168bb90cee2d Mon Sep 17 00:00:00 2001 From: "dvander@alliedmods.net" Date: Tue, 24 Feb 2015 15:21:52 -0800 Subject: [PATCH 02/14] Remove unused fields from sp_context_t. --- sourcepawn/jit/jit_shared.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sourcepawn/jit/jit_shared.h b/sourcepawn/jit/jit_shared.h index 7cdb176a..f96661bf 100644 --- a/sourcepawn/jit/jit_shared.h +++ b/sourcepawn/jit/jit_shared.h @@ -82,9 +82,8 @@ typedef struct sp_context_s int32_t n_err; /**< Error code set by a native */ uint32_t n_idx; /**< Current native index being executed */ tracker_t *tracker; - sp_plugin_t *plugin; - PluginContext *basecx; - void * vm[8]; /**< VM-specific pointers */ + sp_plugin_t *plugin; + PluginContext *basecx; } sp_context_t; //#define SPFLAG_PLUGIN_DEBUG (1<<0) From 5502fbbdc10512f094d299c1ae2351373f6e002b Mon Sep 17 00:00:00 2001 From: "dvander@alliedmods.net" Date: Tue, 24 Feb 2015 15:43:41 -0800 Subject: [PATCH 03/14] Move the tracker from sp_context_t to PluginContext. --- sourcepawn/jit/interpreter.cpp | 48 ++----------------------------- sourcepawn/jit/interpreter.h | 9 ------ sourcepawn/jit/jit_shared.h | 2 -- sourcepawn/jit/plugin-context.cpp | 48 +++++++++++++++++++++++++++---- sourcepawn/jit/plugin-context.h | 21 ++++++++++++++ sourcepawn/jit/x86/jit_x86.cpp | 27 ++++++++++++----- 6 files changed, 86 insertions(+), 69 deletions(-) diff --git a/sourcepawn/jit/interpreter.cpp b/sourcepawn/jit/interpreter.cpp index adcfb47f..0fa41014 100644 --- a/sourcepawn/jit/interpreter.cpp +++ b/sourcepawn/jit/interpreter.cpp @@ -95,48 +95,6 @@ CheckAddress(const sp_plugin_t *plugin, sp_context_t *ctx, cell_t *stk, cell_t a return true; } -int -PopTrackerAndSetHeap(PluginRuntime *rt) -{ - sp_context_t *ctx = rt->GetBaseContext()->GetCtx(); - tracker_t *trk = ctx->tracker; - assert(trk->pCur > trk->pBase); - - trk->pCur--; - if (trk->pCur < trk->pBase) - return SP_ERROR_TRACKER_BOUNDS; - - ucell_t amt = *trk->pCur; - if (amt > (ctx->hp - rt->plugin()->data_size)) - return SP_ERROR_HEAPMIN; - - ctx->hp -= amt; - return SP_ERROR_NONE; -} - -int -PushTracker(sp_context_t *ctx, size_t amount) -{ - tracker_t *trk = ctx->tracker; - - if ((size_t)(trk->pCur - trk->pBase) >= trk->size) - return SP_ERROR_TRACKER_BOUNDS; - - if (trk->pCur + 1 - (trk->pBase + trk->size) == 0) { - size_t disp = trk->size - 1; - trk->size *= 2; - trk->pBase = (ucell_t *)realloc(trk->pBase, trk->size * sizeof(cell_t)); - - if (!trk->pBase) - return SP_ERROR_TRACKER_BOUNDS; - - trk->pCur = trk->pBase + disp; - } - - *trk->pCur++ = amount; - return SP_ERROR_NONE; -} - cell_t NativeCallback(sp_context_t *ctx, ucell_t native_idx, cell_t *params) { @@ -211,7 +169,7 @@ GenerateArray(PluginRuntime *rt, sp_context_t *ctx, cell_t dims, cell_t *stk, bo return false; } - if ((ctx->err = PushTracker(ctx, bytes)) != SP_ERROR_NONE) + if ((ctx->err = rt->GetBaseContext()->pushTracker(bytes)) != SP_ERROR_NONE) return false; if (autozero) @@ -849,7 +807,7 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) case OP_TRACKER_PUSH_C: { cell_t amount = *cip++; - int error = PushTracker(ctx, amount * 4); + int error = cx->pushTracker(amount * 4); if (error != SP_ERROR_NONE) { ctx->err = error; goto error; @@ -859,7 +817,7 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) case OP_TRACKER_POP_SETHEAP: { - int error = PopTrackerAndSetHeap(rt); + int error = cx->popTrackerAndSetHeap(); if (error != SP_ERROR_NONE) { ctx->err = error; goto error; diff --git a/sourcepawn/jit/interpreter.h b/sourcepawn/jit/interpreter.h index b4603c96..ed73a55f 100644 --- a/sourcepawn/jit/interpreter.h +++ b/sourcepawn/jit/interpreter.h @@ -22,19 +22,10 @@ #include "plugin-runtime.h" #include "plugin-context.h" -struct tracker_t -{ - size_t size; - ucell_t *pBase; - ucell_t *pCur; -}; - int Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval); int GenerateFullArray(PluginRuntime *rt, uint32_t argc, cell_t *argv, int autozero); cell_t NativeCallback(sp_context_t *ctx, ucell_t native_idx, cell_t *params); cell_t BoundNativeCallback(sp_context_t *ctx, SPVM_NATIVE_FUNC pfn, cell_t *params); -int PopTrackerAndSetHeap(PluginRuntime *rt); -int PushTracker(sp_context_t *ctx, size_t amount); #endif // _include_sourcepawn_interpreter_h_ diff --git a/sourcepawn/jit/jit_shared.h b/sourcepawn/jit/jit_shared.h index f96661bf..593d1db4 100644 --- a/sourcepawn/jit/jit_shared.h +++ b/sourcepawn/jit/jit_shared.h @@ -68,7 +68,6 @@ namespace SourcePawn } sp_plugin_t; } -struct tracker_t; class PluginContext; typedef struct sp_context_s @@ -81,7 +80,6 @@ typedef struct sp_context_s int32_t err; /**< Error last set by interpreter */ int32_t n_err; /**< Error code set by a native */ uint32_t n_idx; /**< Current native index being executed */ - tracker_t *tracker; sp_plugin_t *plugin; PluginContext *basecx; } sp_context_t; diff --git a/sourcepawn/jit/plugin-context.cpp b/sourcepawn/jit/plugin-context.cpp index f444826c..9b6cc381 100644 --- a/sourcepawn/jit/plugin-context.cpp +++ b/sourcepawn/jit/plugin-context.cpp @@ -58,18 +58,16 @@ PluginContext::PluginContext(PluginRuntime *pRuntime) m_ctx.n_idx = SP_ERROR_NONE; rp_ = 0; - m_ctx.tracker = new tracker_t; - m_ctx.tracker->pBase = (ucell_t *)malloc(1024); - m_ctx.tracker->pCur = m_ctx.tracker->pBase; - m_ctx.tracker->size = 1024 / sizeof(cell_t); + tracker_.pBase = (ucell_t *)malloc(1024); + tracker_.pCur = tracker_.pBase; + tracker_.size = 1024 / sizeof(cell_t); m_ctx.basecx = this; m_ctx.plugin = const_cast(pRuntime->plugin()); } PluginContext::~PluginContext() { - free(m_ctx.tracker->pBase); - delete m_ctx.tracker; + free(tracker_.pBase); } IVirtualMachine * @@ -814,3 +812,41 @@ PluginContext::ClearLastNativeError() { m_ctx.n_err = SP_ERROR_NONE; } + +int +PluginContext::popTrackerAndSetHeap() +{ + assert(tracker_.pCur > tracker_.pBase); + + tracker_.pCur--; + if (tracker_.pCur < tracker_.pBase) + return SP_ERROR_TRACKER_BOUNDS; + + ucell_t amt = *tracker_.pCur; + if (amt > (m_ctx.hp - m_pRuntime->plugin()->data_size)) + return SP_ERROR_HEAPMIN; + + m_ctx.hp -= amt; + return SP_ERROR_NONE; +} + +int +PluginContext::pushTracker(uint32_t amount) +{ + if ((size_t)(tracker_.pCur - tracker_.pBase) >= tracker_.size) + return SP_ERROR_TRACKER_BOUNDS; + + if (tracker_.pCur + 1 - (tracker_.pBase + tracker_.size) == 0) { + size_t disp = tracker_.size - 1; + tracker_.size *= 2; + tracker_.pBase = (ucell_t *)realloc(tracker_.pBase, tracker_.size * sizeof(cell_t)); + + if (!tracker_.pBase) + return SP_ERROR_TRACKER_BOUNDS; + + tracker_.pCur = tracker_.pBase + disp; + } + + *tracker_.pCur++ = amount; + return SP_ERROR_NONE; +} diff --git a/sourcepawn/jit/plugin-context.h b/sourcepawn/jit/plugin-context.h index b853a247..b1f730d4 100644 --- a/sourcepawn/jit/plugin-context.h +++ b/sourcepawn/jit/plugin-context.h @@ -18,6 +18,18 @@ #include "plugin-runtime.h" #include "jit_shared.h" +struct HeapTracker +{ + HeapTracker() + : size(0), + pBase(nullptr), + pCur(nullptr) + {} + size_t size; + ucell_t *pBase; + ucell_t *pCur; +}; + class PluginContext : public IPluginContext { public: @@ -82,6 +94,9 @@ class PluginContext : public IPluginContext static inline size_t offsetOfRstkCips() { return offsetof(PluginContext, rstk_cips_); } + static inline size_t offsetOfTracker() { + return offsetof(PluginContext, tracker_); + } bool pushReturnCip(cell_t cip) { if (rp_ >= SP_MAX_RETURN_STACK) @@ -101,6 +116,9 @@ class PluginContext : public IPluginContext return rstk_cips_[index]; } + int popTrackerAndSetHeap(); + int pushTracker(uint32_t amount); + private: void SetErrorMessage(const char *msg, va_list ap); void _SetErrorMessage(const char *msg, ...); @@ -116,6 +134,9 @@ class PluginContext : public IPluginContext void *m_keys[4]; bool m_keys_set[4]; + // Tracker for local HEA growth. + HeapTracker tracker_; + // Return stack. cell_t rp_; cell_t rstk_cips_[SP_MAX_RETURN_STACK]; diff --git a/sourcepawn/jit/x86/jit_x86.cpp b/sourcepawn/jit/x86/jit_x86.cpp index 1422b88a..bcdad96a 100644 --- a/sourcepawn/jit/x86/jit_x86.cpp +++ b/sourcepawn/jit/x86/jit_x86.cpp @@ -187,7 +187,7 @@ GenerateFullArray(PluginRuntime *rt, uint32_t argc, cell_t *argv, int autozero) if (dat_hp >= argv - STACK_MARGIN) return SP_ERROR_HEAPLOW; - if (int err = PushTracker(rt->GetBaseContext()->GetCtx(), bytes)) + if (int err = rt->GetBaseContext()->pushTracker(bytes)) return err; cell_t *base = reinterpret_cast(rt->plugin()->memory + ctx->hp); @@ -384,6 +384,19 @@ Compiler::emit(int *errp) return new CompiledFunction(code, pcode_start_, edges.take()); } +// Helpers for invoking context members. +static int +InvokePushTracker(PluginContext *cx, uint32_t amount) +{ + return cx->pushTracker(amount); +} + +static int +InvokePopTrackerAndSetHeap(PluginContext *cx) +{ + return cx->popTrackerAndSetHeap(); +} + bool Compiler::emitOp(OPCODE op) { @@ -1258,8 +1271,8 @@ Compiler::emitOp(OPCODE op) __ push(alt); __ push(amount * 4); - __ push(intptr_t(rt_->GetBaseContext()->GetCtx())); - __ call(ExternalAddress((void *)PushTracker)); + __ push(intptr_t(rt_->GetBaseContext())); + __ call(ExternalAddress((void *)InvokePushTracker)); __ addl(esp, 8); __ testl(eax, eax); __ j(not_zero, &extern_error_); @@ -1276,8 +1289,8 @@ Compiler::emitOp(OPCODE op) __ push(alt); // Get the context pointer and call the sanity checker. - __ push(intptr_t(rt_)); - __ call(ExternalAddress((void *)PopTrackerAndSetHeap)); + __ push(intptr_t(rt_->GetBaseContext())); + __ call(ExternalAddress((void *)InvokePopTrackerAndSetHeap)); __ addl(esp, 4); __ testl(eax, eax); __ j(not_zero, &extern_error_); @@ -1405,8 +1418,8 @@ Compiler::emitGenArray(bool autozero) __ shll(tmp, 2); __ push(tmp); - __ push(intptr_t(rt_->GetBaseContext()->GetCtx())); - __ call(ExternalAddress((void *)PushTracker)); + __ push(intptr_t(rt_->GetBaseContext())); + __ call(ExternalAddress((void *)InvokePushTracker)); __ addl(esp, 4); __ pop(tmp); __ shrl(tmp, 2); From 9c104ef310dd84c42d07e895b397eb73cfbf1166 Mon Sep 17 00:00:00 2001 From: "dvander@alliedmods.net" Date: Tue, 24 Feb 2015 19:59:45 -0800 Subject: [PATCH 04/14] Move nidx from sp_context_t to PluginContext. --- sourcepawn/jit/debug-trace.cpp | 8 +++- sourcepawn/jit/interpreter.cpp | 57 +-------------------------- sourcepawn/jit/interpreter.h | 1 - sourcepawn/jit/jit_shared.h | 1 - sourcepawn/jit/plugin-context.cpp | 64 +++++++++++++++++++++++++++++-- sourcepawn/jit/plugin-context.h | 13 +++++++ sourcepawn/jit/x86/jit_x86.cpp | 25 +++++++++--- 7 files changed, 99 insertions(+), 70 deletions(-) diff --git a/sourcepawn/jit/debug-trace.cpp b/sourcepawn/jit/debug-trace.cpp index 569d3291..5aaef6ee 100644 --- a/sourcepawn/jit/debug-trace.cpp +++ b/sourcepawn/jit/debug-trace.cpp @@ -108,12 +108,16 @@ CContextTrace::GetLastNative(uint32_t *index) if (m_ctx->n_err == SP_ERROR_NONE) return NULL; + int lastNative = context_->lastNative(); + if (lastNative < 0) + return NULL; + sp_native_t *native; - if (m_pRuntime->GetNativeByIndex(m_ctx->n_idx, &native) != SP_ERROR_NONE) + if (m_pRuntime->GetNativeByIndex(lastNative, &native) != SP_ERROR_NONE) return NULL; if (index) - *index = m_ctx->n_idx; + *index = lastNative; return native->name; } diff --git a/sourcepawn/jit/interpreter.cpp b/sourcepawn/jit/interpreter.cpp index 0fa41014..a5eac421 100644 --- a/sourcepawn/jit/interpreter.cpp +++ b/sourcepawn/jit/interpreter.cpp @@ -95,61 +95,6 @@ CheckAddress(const sp_plugin_t *plugin, sp_context_t *ctx, cell_t *stk, cell_t a return true; } -cell_t -NativeCallback(sp_context_t *ctx, ucell_t native_idx, cell_t *params) -{ - cell_t save_sp = ctx->sp; - cell_t save_hp = ctx->hp; - - ctx->n_idx = native_idx; - - sp_native_t *native = &ctx->plugin->natives[native_idx]; - - if (native->status == SP_NATIVE_UNBOUND) { - ctx->n_err = SP_ERROR_INVALID_NATIVE; - return 0; - } - - cell_t result = native->pfn(ctx->basecx, params); - - if (ctx->n_err != SP_ERROR_NONE) - return result; - - if (save_sp != ctx->sp) { - ctx->n_err = SP_ERROR_STACKLEAK; - return result; - } - if (save_hp != ctx->hp) { - ctx->n_err = SP_ERROR_HEAPLEAK; - return result; - } - - return result; -} - -cell_t -BoundNativeCallback(sp_context_t *ctx, SPVM_NATIVE_FUNC pfn, cell_t *params) -{ - cell_t save_sp = ctx->sp; - cell_t save_hp = ctx->hp; - - cell_t result = pfn(ctx->basecx, params); - - if (ctx->n_err != SP_ERROR_NONE) - return result; - - if (save_sp != ctx->sp) { - ctx->n_err = SP_ERROR_STACKLEAK; - return result; - } - if (save_hp != ctx->hp) { - ctx->n_err = SP_ERROR_HEAPLEAK; - return result; - } - - return result; -} - static inline bool GenerateArray(PluginRuntime *rt, sp_context_t *ctx, cell_t dims, cell_t *stk, bool autozero) { @@ -896,7 +841,7 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) } ctx->sp = uintptr_t(stk) - uintptr_t(plugin->memory); - pri = NativeCallback(ctx, native_index, stk); + pri = cx->invokeNative(native_index, stk); if (ctx->n_err != SP_ERROR_NONE) { ctx->err = ctx->n_err; goto error; diff --git a/sourcepawn/jit/interpreter.h b/sourcepawn/jit/interpreter.h index ed73a55f..0274707a 100644 --- a/sourcepawn/jit/interpreter.h +++ b/sourcepawn/jit/interpreter.h @@ -25,7 +25,6 @@ int Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval); int GenerateFullArray(PluginRuntime *rt, uint32_t argc, cell_t *argv, int autozero); -cell_t NativeCallback(sp_context_t *ctx, ucell_t native_idx, cell_t *params); cell_t BoundNativeCallback(sp_context_t *ctx, SPVM_NATIVE_FUNC pfn, cell_t *params); #endif // _include_sourcepawn_interpreter_h_ diff --git a/sourcepawn/jit/jit_shared.h b/sourcepawn/jit/jit_shared.h index 593d1db4..eea556e5 100644 --- a/sourcepawn/jit/jit_shared.h +++ b/sourcepawn/jit/jit_shared.h @@ -79,7 +79,6 @@ typedef struct sp_context_s int32_t cip; /**< Code pointer last error occurred in */ int32_t err; /**< Error last set by interpreter */ int32_t n_err; /**< Error code set by a native */ - uint32_t n_idx; /**< Current native index being executed */ sp_plugin_t *plugin; PluginContext *basecx; } sp_context_t; diff --git a/sourcepawn/jit/plugin-context.cpp b/sourcepawn/jit/plugin-context.cpp index 9b6cc381..f65f22eb 100644 --- a/sourcepawn/jit/plugin-context.cpp +++ b/sourcepawn/jit/plugin-context.cpp @@ -55,8 +55,8 @@ PluginContext::PluginContext(PluginRuntime *pRuntime) m_ctx.sp = m_pRuntime->plugin()->mem_size - sizeof(cell_t); m_ctx.frm = m_ctx.sp; m_ctx.n_err = SP_ERROR_NONE; - m_ctx.n_idx = SP_ERROR_NONE; rp_ = 0; + last_native_ = -1; tracker_.pBase = (ucell_t *)malloc(1024); tracker_.pCur = tracker_.pBase; @@ -581,7 +581,7 @@ PluginContext::Execute2(IPluginFunction *function, const cell_t *params, unsigne save_sp = m_ctx.sp; save_hp = m_ctx.hp; save_exec = m_InExec; - save_n_idx = m_ctx.n_idx; + save_n_idx = last_native_; save_rp = rp_; save_cip = m_ctx.cip; @@ -596,7 +596,7 @@ PluginContext::Execute2(IPluginFunction *function, const cell_t *params, unsigne /* Clear internal state */ m_ctx.n_err = SP_ERROR_NONE; - m_ctx.n_idx = 0; + last_native_ = -1; m_MsgCache[0] = '\0'; m_CustomMsg = false; m_InExec = true; @@ -645,7 +645,7 @@ PluginContext::Execute2(IPluginFunction *function, const cell_t *params, unsigne rp_ = save_rp; m_ctx.cip = save_cip; - m_ctx.n_idx = save_n_idx; + last_native_ = save_n_idx; m_ctx.n_err = SP_ERROR_NONE; m_MsgCache[0] = '\0'; m_CustomMsg = false; @@ -850,3 +850,59 @@ PluginContext::pushTracker(uint32_t amount) *tracker_.pCur++ = amount; return SP_ERROR_NONE; } + +cell_t +PluginContext::invokeNative(ucell_t native_idx, cell_t *params) +{ + cell_t save_sp = m_ctx.sp; + cell_t save_hp = m_ctx.hp; + + // Note: Invoke() saves the last native, so we don't need to here. + last_native_ = native_idx; + + sp_native_t *native = &m_pRuntime->plugin()->natives[native_idx]; + + if (native->status == SP_NATIVE_UNBOUND) { + m_ctx.n_err = SP_ERROR_INVALID_NATIVE; + return 0; + } + + cell_t result = native->pfn(m_ctx.basecx, params); + + if (m_ctx.n_err != SP_ERROR_NONE) + return result; + + if (save_sp != m_ctx.sp) { + m_ctx.n_err = SP_ERROR_STACKLEAK; + return result; + } + if (save_hp != m_ctx.hp) { + m_ctx.n_err = SP_ERROR_HEAPLEAK; + return result; + } + + return result; +} + +cell_t +PluginContext::invokeBoundNative(SPVM_NATIVE_FUNC pfn, cell_t *params) +{ + cell_t save_sp = m_ctx.sp; + cell_t save_hp = m_ctx.hp; + + cell_t result = pfn(this, params); + + if (m_ctx.n_err != SP_ERROR_NONE) + return result; + + if (save_sp != m_ctx.sp) { + m_ctx.n_err = SP_ERROR_STACKLEAK; + return result; + } + if (save_hp != m_ctx.hp) { + m_ctx.n_err = SP_ERROR_HEAPLEAK; + return result; + } + + return result; +} diff --git a/sourcepawn/jit/plugin-context.h b/sourcepawn/jit/plugin-context.h index b1f730d4..d00b7c04 100644 --- a/sourcepawn/jit/plugin-context.h +++ b/sourcepawn/jit/plugin-context.h @@ -97,7 +97,11 @@ class PluginContext : public IPluginContext static inline size_t offsetOfTracker() { return offsetof(PluginContext, tracker_); } + static inline size_t offsetOfLastNative() { + return offsetof(PluginContext, last_native_); + } + // Return stack logic. bool pushReturnCip(cell_t cip) { if (rp_ >= SP_MAX_RETURN_STACK) return false; @@ -119,6 +123,12 @@ class PluginContext : public IPluginContext int popTrackerAndSetHeap(); int pushTracker(uint32_t amount); + cell_t invokeNative(ucell_t native_idx, cell_t *params); + cell_t invokeBoundNative(SPVM_NATIVE_FUNC pfn, cell_t *params); + int lastNative() const { + return last_native_; + } + private: void SetErrorMessage(const char *msg, va_list ap); void _SetErrorMessage(const char *msg, ...); @@ -140,6 +150,9 @@ class PluginContext : public IPluginContext // Return stack. cell_t rp_; cell_t rstk_cips_[SP_MAX_RETURN_STACK]; + + // Track the currently executing native index. + uint32_t last_native_; }; #endif //_INCLUDE_SOURCEPAWN_BASECONTEXT_H_ diff --git a/sourcepawn/jit/x86/jit_x86.cpp b/sourcepawn/jit/x86/jit_x86.cpp index bcdad96a..93c2769d 100644 --- a/sourcepawn/jit/x86/jit_x86.cpp +++ b/sourcepawn/jit/x86/jit_x86.cpp @@ -397,6 +397,18 @@ InvokePopTrackerAndSetHeap(PluginContext *cx) return cx->popTrackerAndSetHeap(); } +static cell_t +InvokeNativeHelper(PluginContext *cx, ucell_t native_idx, cell_t *params) +{ + return cx->invokeNative(native_idx, params); +} + +static cell_t +InvokeBoundNativeHelper(PluginContext *cx, SPVM_NATIVE_FUNC fn, cell_t *params) +{ + return cx->invokeBoundNative(fn, params); +} + bool Compiler::emitOp(OPCODE op) { @@ -1594,14 +1606,15 @@ Compiler::emitNativeCall(OPCODE op) // Push the last parameter for the C++ function. __ push(stk); + __ movl(eax, intptr_t(rt_->GetBaseContext())); + __ movl(Operand(eax, PluginContext::offsetOfLastNative()), native_index); + // Relocate our absolute stk to be dat-relative, and update the context's // view. __ movl(eax, intptr_t(rt_->GetBaseContext()->GetCtx())); __ subl(stk, dat); __ movl(Operand(eax, offsetof(sp_context_t, sp)), stk); - __ movl(Operand(eax, offsetof(sp_context_t, n_idx)), native_index); - sp_native_t *native = rt_->GetNativeByIndex(native_index); if ((native->status != SP_NATIVE_BOUND) || (native->flags & (SP_NTVFLAG_OPTIONAL | SP_NTVFLAG_EPHEMERAL))) @@ -1609,13 +1622,13 @@ Compiler::emitNativeCall(OPCODE op) // The native is either unbound, or it could become unbound in the // future. Invoke the slower native callback. __ push(native_index); - __ push(eax); - __ call(ExternalAddress((void *)NativeCallback)); + __ push(intptr_t(rt_->GetBaseContext())); + __ call(ExternalAddress((void *)InvokeNativeHelper)); } else { // The native is bound so we have a few more guarantees. __ push(intptr_t(native->pfn)); - __ push(eax); - __ call(ExternalAddress((void *)BoundNativeCallback)); + __ push(intptr_t(rt_->GetBaseContext())); + __ call(ExternalAddress((void *)InvokeBoundNativeHelper)); } // Check for errors. From 97dbc7ff071daf79c0b6e1664bf9c88a06ea2896 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Tue, 24 Feb 2015 20:16:13 -0800 Subject: [PATCH 05/14] Move n_err from sp_context_t to PluginContext. --- sourcepawn/jit/debug-trace.cpp | 2 +- sourcepawn/jit/interpreter.cpp | 4 ++-- sourcepawn/jit/jit_shared.h | 1 - sourcepawn/jit/plugin-context.cpp | 30 +++++++++++++++--------------- sourcepawn/jit/plugin-context.h | 8 ++++++-- sourcepawn/jit/x86/jit_x86.cpp | 8 ++++---- 6 files changed, 28 insertions(+), 25 deletions(-) diff --git a/sourcepawn/jit/debug-trace.cpp b/sourcepawn/jit/debug-trace.cpp index 5aaef6ee..960148dd 100644 --- a/sourcepawn/jit/debug-trace.cpp +++ b/sourcepawn/jit/debug-trace.cpp @@ -105,7 +105,7 @@ CContextTrace::GetTraceInfo(CallStackInfo *trace) const char * CContextTrace::GetLastNative(uint32_t *index) { - if (m_ctx->n_err == SP_ERROR_NONE) + if (context_->GetLastNativeError() == SP_ERROR_NONE) return NULL; int lastNative = context_->lastNative(); diff --git a/sourcepawn/jit/interpreter.cpp b/sourcepawn/jit/interpreter.cpp index a5eac421..7e4e5399 100644 --- a/sourcepawn/jit/interpreter.cpp +++ b/sourcepawn/jit/interpreter.cpp @@ -842,8 +842,8 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) ctx->sp = uintptr_t(stk) - uintptr_t(plugin->memory); pri = cx->invokeNative(native_index, stk); - if (ctx->n_err != SP_ERROR_NONE) { - ctx->err = ctx->n_err; + if (cx->GetLastNativeError() != SP_ERROR_NONE) { + ctx->err = cx->GetLastNativeError(); goto error; } diff --git a/sourcepawn/jit/jit_shared.h b/sourcepawn/jit/jit_shared.h index eea556e5..73c68a39 100644 --- a/sourcepawn/jit/jit_shared.h +++ b/sourcepawn/jit/jit_shared.h @@ -78,7 +78,6 @@ typedef struct sp_context_s cell_t rval; /**< Return value from InvokeFunction() */ int32_t cip; /**< Code pointer last error occurred in */ int32_t err; /**< Error last set by interpreter */ - int32_t n_err; /**< Error code set by a native */ sp_plugin_t *plugin; PluginContext *basecx; } sp_context_t; diff --git a/sourcepawn/jit/plugin-context.cpp b/sourcepawn/jit/plugin-context.cpp index f65f22eb..61d887ea 100644 --- a/sourcepawn/jit/plugin-context.cpp +++ b/sourcepawn/jit/plugin-context.cpp @@ -54,9 +54,9 @@ PluginContext::PluginContext(PluginRuntime *pRuntime) m_ctx.hp = m_pRuntime->plugin()->data_size; m_ctx.sp = m_pRuntime->plugin()->mem_size - sizeof(cell_t); m_ctx.frm = m_ctx.sp; - m_ctx.n_err = SP_ERROR_NONE; rp_ = 0; last_native_ = -1; + native_error_ = SP_ERROR_NONE; tracker_.pBase = (ucell_t *)malloc(1024); tracker_.pCur = tracker_.pBase; @@ -135,7 +135,7 @@ PluginContext::ThrowNativeErrorEx(int error, const char *msg, ...) if (!m_InExec) return 0; - m_ctx.n_err = error; + native_error_ = error; if (msg) { va_list ap; @@ -153,7 +153,7 @@ PluginContext::ThrowNativeError(const char *msg, ...) if (!m_InExec) return 0; - m_ctx.n_err = SP_ERROR_NATIVE; + native_error_ = SP_ERROR_NATIVE; if (msg) { va_list ap; @@ -595,7 +595,7 @@ PluginContext::Execute2(IPluginFunction *function, const cell_t *params, unsigne sp[i + 1] = params[i]; /* Clear internal state */ - m_ctx.n_err = SP_ERROR_NONE; + native_error_ = SP_ERROR_NONE; last_native_ = -1; m_MsgCache[0] = '\0'; m_CustomMsg = false; @@ -613,7 +613,7 @@ PluginContext::Execute2(IPluginFunction *function, const cell_t *params, unsigne m_InExec = save_exec; if (ir == SP_ERROR_NONE) { - m_ctx.n_err = SP_ERROR_NONE; + native_error_ = SP_ERROR_NONE; if (m_ctx.sp != save_sp) { ir = SP_ERROR_STACKLEAK; _SetErrorMessage("Stack leak detected: sp:%d should be %d!", @@ -646,7 +646,7 @@ PluginContext::Execute2(IPluginFunction *function, const cell_t *params, unsigne m_ctx.cip = save_cip; last_native_ = save_n_idx; - m_ctx.n_err = SP_ERROR_NONE; + native_error_ = SP_ERROR_NONE; m_MsgCache[0] = '\0'; m_CustomMsg = false; @@ -778,7 +778,7 @@ DebugInfo::LookupLine(ucell_t addr, uint32_t *line) int PluginContext::GetLastNativeError() { - return m_ctx.n_err; + return native_error_; } cell_t * @@ -810,7 +810,7 @@ PluginContext::GetKey(int k, void **value) void PluginContext::ClearLastNativeError() { - m_ctx.n_err = SP_ERROR_NONE; + native_error_ = SP_ERROR_NONE; } int @@ -863,21 +863,21 @@ PluginContext::invokeNative(ucell_t native_idx, cell_t *params) sp_native_t *native = &m_pRuntime->plugin()->natives[native_idx]; if (native->status == SP_NATIVE_UNBOUND) { - m_ctx.n_err = SP_ERROR_INVALID_NATIVE; + native_error_ = SP_ERROR_INVALID_NATIVE; return 0; } cell_t result = native->pfn(m_ctx.basecx, params); - if (m_ctx.n_err != SP_ERROR_NONE) + if (native_error_ != SP_ERROR_NONE) return result; if (save_sp != m_ctx.sp) { - m_ctx.n_err = SP_ERROR_STACKLEAK; + native_error_ = SP_ERROR_STACKLEAK; return result; } if (save_hp != m_ctx.hp) { - m_ctx.n_err = SP_ERROR_HEAPLEAK; + native_error_ = SP_ERROR_HEAPLEAK; return result; } @@ -892,15 +892,15 @@ PluginContext::invokeBoundNative(SPVM_NATIVE_FUNC pfn, cell_t *params) cell_t result = pfn(this, params); - if (m_ctx.n_err != SP_ERROR_NONE) + if (native_error_ != SP_ERROR_NONE) return result; if (save_sp != m_ctx.sp) { - m_ctx.n_err = SP_ERROR_STACKLEAK; + native_error_ = SP_ERROR_STACKLEAK; return result; } if (save_hp != m_ctx.hp) { - m_ctx.n_err = SP_ERROR_HEAPLEAK; + native_error_ = SP_ERROR_HEAPLEAK; return result; } diff --git a/sourcepawn/jit/plugin-context.h b/sourcepawn/jit/plugin-context.h index d00b7c04..90b2c9d3 100644 --- a/sourcepawn/jit/plugin-context.h +++ b/sourcepawn/jit/plugin-context.h @@ -100,6 +100,9 @@ class PluginContext : public IPluginContext static inline size_t offsetOfLastNative() { return offsetof(PluginContext, last_native_); } + static inline size_t offsetOfNativeError() { + return offsetof(PluginContext, native_error_); + } // Return stack logic. bool pushReturnCip(cell_t cip) { @@ -151,8 +154,9 @@ class PluginContext : public IPluginContext cell_t rp_; cell_t rstk_cips_[SP_MAX_RETURN_STACK]; - // Track the currently executing native index. - uint32_t last_native_; + // Track the currently executing native index, and any error it throws. + int32_t last_native_; + int native_error_; }; #endif //_INCLUDE_SOURCEPAWN_BASECONTEXT_H_ diff --git a/sourcepawn/jit/x86/jit_x86.cpp b/sourcepawn/jit/x86/jit_x86.cpp index 93c2769d..dca060d1 100644 --- a/sourcepawn/jit/x86/jit_x86.cpp +++ b/sourcepawn/jit/x86/jit_x86.cpp @@ -1632,8 +1632,8 @@ Compiler::emitNativeCall(OPCODE op) } // Check for errors. - __ movl(ecx, intptr_t(rt_->GetBaseContext()->GetCtx())); - __ movl(ecx, Operand(ecx, offsetof(sp_context_t, n_err))); + __ movl(ecx, intptr_t(rt_->GetBaseContext())); + __ movl(ecx, Operand(ecx, PluginContext::offsetOfNativeError())); __ testl(ecx, ecx); __ j(not_zero, &extern_error_); @@ -1824,8 +1824,8 @@ Compiler::emitErrorPaths() if (extern_error_.used()) { __ bind(&extern_error_); - __ movl(eax, intptr_t(rt_->GetBaseContext()->GetCtx())); - __ movl(eax, Operand(eax, offsetof(sp_context_t, n_err))); + __ movl(eax, intptr_t(rt_->GetBaseContext())); + __ movl(eax, Operand(eax, PluginContext::offsetOfNativeError())); __ jmp(ExternalAddress(env_->stubs()->ReturnStub())); } } From 8817de8a559186d87c3874ad2f9714623478b0f8 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Tue, 24 Feb 2015 20:41:13 -0800 Subject: [PATCH 06/14] Remove err from sp_context_t. --- sourcepawn/jit/interpreter.cpp | 140 +++++++++++++++++---------------- sourcepawn/jit/jit_shared.h | 1 - 2 files changed, 74 insertions(+), 67 deletions(-) diff --git a/sourcepawn/jit/interpreter.cpp b/sourcepawn/jit/interpreter.cpp index 7e4e5399..50d87b87 100644 --- a/sourcepawn/jit/interpreter.cpp +++ b/sourcepawn/jit/interpreter.cpp @@ -47,29 +47,26 @@ Write(const sp_plugin_t *plugin, cell_t offset, cell_t value) static inline cell_t * Jump(const sp_plugin_t *plugin, sp_context_t *ctx, cell_t target) { - if (!IsValidOffset(target) || uint32_t(target) >= plugin->pcode_size) { - ctx->err = SP_ERROR_INVALID_INSTRUCTION; + if (!IsValidOffset(target) || uint32_t(target) >= plugin->pcode_size) return NULL; - } - return reinterpret_cast(plugin->pcode + target); } static inline cell_t * -JumpTarget(const sp_plugin_t *plugin, sp_context_t *ctx, cell_t *cip, bool cond) +JumpTarget(const sp_plugin_t *plugin, sp_context_t *ctx, cell_t *cip, bool cond, int *errp) { if (!cond) return cip + 1; cell_t target = *cip; if (!IsValidOffset(target) || uint32_t(target) >= plugin->pcode_size) { - ctx->err = SP_ERROR_INVALID_INSTRUCTION; + *errp = SP_ERROR_INVALID_INSTRUCTION; return NULL; } cell_t *next = reinterpret_cast(plugin->pcode + target); if (next < cip && !Environment::get()->watchdog()->HandleInterrupt()) { - ctx->err = SP_ERROR_TIMEOUT; + *errp = SP_ERROR_TIMEOUT; return NULL; } @@ -79,54 +76,46 @@ JumpTarget(const sp_plugin_t *plugin, sp_context_t *ctx, cell_t *cip, bool cond) static inline bool CheckAddress(const sp_plugin_t *plugin, sp_context_t *ctx, cell_t *stk, cell_t addr) { - if (uint32_t(addr) >= plugin->mem_size) { - ctx->err = SP_ERROR_MEMACCESS; + if (uint32_t(addr) >= plugin->mem_size) return false; - } if (addr < ctx->hp) return true; - if (reinterpret_cast(plugin->memory + addr) < stk) { - ctx->err = SP_ERROR_MEMACCESS; + if (reinterpret_cast(plugin->memory + addr) < stk) return false; - } return true; } -static inline bool +static inline int GenerateArray(PluginRuntime *rt, sp_context_t *ctx, cell_t dims, cell_t *stk, bool autozero) { if (dims == 1) { uint32_t size = *stk; - if (size == 0 || !ke::IsUint32MultiplySafe(size, 4)) { - ctx->err = SP_ERROR_ARRAY_TOO_BIG; - return false; - } + if (size == 0 || !ke::IsUint32MultiplySafe(size, 4)) + return SP_ERROR_ARRAY_TOO_BIG; *stk = ctx->hp; uint32_t bytes = size * 4; ctx->hp += bytes; - if (uintptr_t(ctx->plugin->memory + ctx->hp) >= uintptr_t(stk)) { - ctx->err = SP_ERROR_HEAPLOW; - return false; - } + if (uintptr_t(ctx->plugin->memory + ctx->hp) >= uintptr_t(stk)) + return SP_ERROR_HEAPLOW; - if ((ctx->err = rt->GetBaseContext()->pushTracker(bytes)) != SP_ERROR_NONE) - return false; + if (int err = rt->GetBaseContext()->pushTracker(bytes)) + return err; if (autozero) memset(ctx->plugin->memory + ctx->hp, 0, bytes); - return true; + return SP_ERROR_NONE; } - if ((ctx->err = GenerateFullArray(rt, dims, stk, autozero)) != SP_ERROR_NONE) - return false; + if (int err = GenerateFullArray(rt, dims, stk, autozero)) + return err; - return true; + return SP_ERROR_NONE; } int @@ -141,7 +130,8 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) PluginContext *cx = rt->GetBaseContext(); sp_context_t *ctx = cx->GetCtx(); - ctx->err = SP_ERROR_NONE; + + int err = SP_ERROR_NONE; // Save the original frm. BaseContext won't, and if we error, we won't hit // the stack unwinding code. @@ -154,7 +144,7 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) for (;;) { if (cip >= codeend) { - ctx->err = SP_ERROR_INVALID_INSTRUCTION; + err = SP_ERROR_INVALID_INSTRUCTION; goto error; } @@ -415,8 +405,10 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) } case OP_INC_I: - if (!CheckAddress(plugin, ctx, stk, pri)) + if (!CheckAddress(plugin, ctx, stk, pri)) { + err = SP_ERROR_MEMACCESS; goto error; + } Write(plugin, pri, Read(plugin, pri) + 1); break; @@ -443,8 +435,10 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) } case OP_DEC_I: - if (!CheckAddress(plugin, ctx, stk, pri)) + if (!CheckAddress(plugin, ctx, stk, pri)) { + err = SP_ERROR_MEMACCESS; goto error; + } Write(plugin, pri, Read(plugin, pri) - 1); break; @@ -548,8 +542,10 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) case OP_LIDX: pri = alt + pri * 4; - if (!CheckAddress(plugin, ctx, stk, pri)) + if (!CheckAddress(plugin, ctx, stk, pri)) { + err = SP_ERROR_MEMACCESS; goto error; + } pri = Read(plugin, pri); break; @@ -557,8 +553,10 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) { cell_t val = *cip++; pri = alt + (pri << val); - if (!CheckAddress(plugin, ctx, stk, pri)) + if (!CheckAddress(plugin, ctx, stk, pri)) { + err = SP_ERROR_MEMACCESS; goto error; + } pri = Read(plugin, pri); break; } @@ -580,14 +578,18 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) } case OP_LOAD_I: - if (!CheckAddress(plugin, ctx, stk, pri)) + if (!CheckAddress(plugin, ctx, stk, pri)) { + err = SP_ERROR_MEMACCESS; goto error; + } pri = Read(plugin, pri); break; case OP_STOR_I: - if (!CheckAddress(plugin, ctx, stk, alt)) + if (!CheckAddress(plugin, ctx, stk, alt)) { + err = SP_ERROR_MEMACCESS; goto error; + } Write(plugin, alt, pri); break; @@ -597,11 +599,11 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) cell_t dividend = (op == OP_SDIV) ? pri : alt; cell_t divisor = (op == OP_SDIV) ? alt : pri; if (divisor == 0) { - ctx->err = SP_ERROR_DIVIDE_BY_ZERO; + err = SP_ERROR_DIVIDE_BY_ZERO; goto error; } if (dividend == INT_MIN && divisor == -1) { - ctx->err = SP_ERROR_INTEGER_OVERFLOW; + err = SP_ERROR_INTEGER_OVERFLOW; goto error; } pri = dividend / divisor; @@ -612,8 +614,10 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) case OP_LODB_I: { cell_t val = *cip++; - if (!CheckAddress(plugin, ctx, stk, pri)) + if (!CheckAddress(plugin, ctx, stk, pri)) { + err = SP_ERROR_MEMACCESS; goto error; + } pri = Read(plugin, pri); if (val == 1) pri &= 0xff; @@ -625,8 +629,10 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) case OP_STRB_I: { cell_t val = *cip++; - if (!CheckAddress(plugin, ctx, stk, alt)) + if (!CheckAddress(plugin, ctx, stk, alt)) { + err = SP_ERROR_MEMACCESS; goto error; + } if (val == 1) *reinterpret_cast(plugin->memory + alt) = pri; else if (val == 2) @@ -642,7 +648,7 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) ctx->frm = *stk++; stk += *stk + 1; *rval = pri; - ctx->err = SP_ERROR_NONE; + err = SP_ERROR_NONE; goto done; } @@ -670,19 +676,19 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) { cell_t amount = *cip++; if (!IsValidOffset(amount)) { - ctx->err = SP_ERROR_INVALID_INSTRUCTION; + err = SP_ERROR_INVALID_INSTRUCTION; goto error; } stk += amount / 4; if (amount > 0) { if (uintptr_t(stk) >= uintptr_t(plugin->memory + plugin->mem_size)) { - ctx->err = SP_ERROR_STACKMIN; + err = SP_ERROR_STACKMIN; goto error; } } else { if (uintptr_t(stk) < uintptr_t(plugin->memory + ctx->hp + STACK_MARGIN)) { - ctx->err = SP_ERROR_STACKLOW; + err = SP_ERROR_STACKLOW; goto error; } } @@ -698,12 +704,12 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) if (amount > 0) { if (uintptr_t(plugin->memory + ctx->hp) > uintptr_t(stk)) { - ctx->err = SP_ERROR_HEAPLOW; + err = SP_ERROR_HEAPLOW; goto error; } } else { if (uint32_t(ctx->hp) < plugin->data_size) { - ctx->err = SP_ERROR_HEAPMIN; + err = SP_ERROR_HEAPMIN; goto error; } } @@ -711,41 +717,41 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) } case OP_JUMP: - if ((cip = JumpTarget(plugin, ctx, cip, true)) == NULL) + if ((cip = JumpTarget(plugin, ctx, cip, true, &err)) == NULL) goto error; break; case OP_JZER: - if ((cip = JumpTarget(plugin, ctx, cip, pri == 0)) == NULL) + if ((cip = JumpTarget(plugin, ctx, cip, pri == 0, &err)) == NULL) goto error; break; case OP_JNZ: - if ((cip = JumpTarget(plugin, ctx, cip, pri != 0)) == NULL) + if ((cip = JumpTarget(plugin, ctx, cip, pri != 0, &err)) == NULL) goto error; break; case OP_JEQ: - if ((cip = JumpTarget(plugin, ctx, cip, pri == alt)) == NULL) + if ((cip = JumpTarget(plugin, ctx, cip, pri == alt, &err)) == NULL) goto error; break; case OP_JNEQ: - if ((cip = JumpTarget(plugin, ctx, cip, pri != alt)) == NULL) + if ((cip = JumpTarget(plugin, ctx, cip, pri != alt, &err)) == NULL) goto error; break; case OP_JSLESS: - if ((cip = JumpTarget(plugin, ctx, cip, pri < alt)) == NULL) + if ((cip = JumpTarget(plugin, ctx, cip, pri < alt, &err)) == NULL) goto error; break; case OP_JSLEQ: - if ((cip = JumpTarget(plugin, ctx, cip, pri <= alt)) == NULL) + if ((cip = JumpTarget(plugin, ctx, cip, pri <= alt, &err)) == NULL) goto error; break; case OP_JSGRTR: - if ((cip = JumpTarget(plugin, ctx, cip, pri > alt)) == NULL) + if ((cip = JumpTarget(plugin, ctx, cip, pri > alt, &err)) == NULL) goto error; break; case OP_JSGEQ: - if ((cip = JumpTarget(plugin, ctx, cip, pri >= alt)) == NULL) + if ((cip = JumpTarget(plugin, ctx, cip, pri >= alt, &err)) == NULL) goto error; break; @@ -754,7 +760,7 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) cell_t amount = *cip++; int error = cx->pushTracker(amount * 4); if (error != SP_ERROR_NONE) { - ctx->err = error; + err = error; goto error; } break; @@ -764,7 +770,7 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) { int error = cx->popTrackerAndSetHeap(); if (error != SP_ERROR_NONE) { - ctx->err = error; + err = error; goto error; } break; @@ -778,7 +784,7 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) { cell_t value = *cip++; if (uint32_t(pri) > uint32_t(value)) { - ctx->err = SP_ERROR_ARRAY_BOUNDS; + err = SP_ERROR_ARRAY_BOUNDS; goto error; } break; @@ -789,14 +795,14 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) cell_t offset = *cip++; if (!IsValidOffset(offset) || uint32_t(offset) >= plugin->pcode_size) { - ctx->err = SP_ERROR_INSTRUCTION_PARAM; + err = SP_ERROR_INSTRUCTION_PARAM; goto error; } // For debugging. uintptr_t rcip = uintptr_t(cip - 2) - uintptr_t(plugin->pcode); if (!cx->pushReturnCip(rcip)) { - ctx->err = SP_ERROR_STACKLOW; + err = SP_ERROR_STACKLOW; goto error; } ctx->cip = offset; @@ -817,7 +823,7 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) case OP_GENARRAY_Z: { cell_t val = *cip++; - if (!GenerateArray(rt, ctx, val, stk, op == OP_GENARRAY_Z)) + if ((err = GenerateArray(rt, ctx, val, stk, op == OP_GENARRAY_Z)) != SP_ERROR_NONE) goto error; stk += (val - 1) * 4; @@ -830,7 +836,7 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) uint32_t native_index = *cip++; if (native_index >= plugin->num_natives) { - ctx->err = SP_ERROR_INSTRUCTION_PARAM; + err = SP_ERROR_INSTRUCTION_PARAM; goto error; } @@ -843,7 +849,7 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) ctx->sp = uintptr_t(stk) - uintptr_t(plugin->memory); pri = cx->invokeNative(native_index, stk); if (cx->GetLastNativeError() != SP_ERROR_NONE) { - ctx->err = cx->GetLastNativeError(); + err = cx->GetLastNativeError(); goto error; } @@ -867,14 +873,16 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) } } - if ((cip = Jump(plugin, ctx, target)) == NULL) + if ((cip = Jump(plugin, ctx, target)) == NULL) { + err = SP_ERROR_INVALID_INSTRUCTION; goto error; + } break; } default: { - ctx->err = SP_ERROR_INVALID_INSTRUCTION; + err = SP_ERROR_INVALID_INSTRUCTION; goto error; } } // switch @@ -883,7 +891,7 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) done: assert(orig_frm == ctx->frm); ctx->sp = uintptr_t(stk) - uintptr_t(plugin->memory); - return ctx->err; + return err; error: ctx->frm = orig_frm; diff --git a/sourcepawn/jit/jit_shared.h b/sourcepawn/jit/jit_shared.h index 73c68a39..e2c4ad15 100644 --- a/sourcepawn/jit/jit_shared.h +++ b/sourcepawn/jit/jit_shared.h @@ -77,7 +77,6 @@ typedef struct sp_context_s cell_t frm; /**< Frame pointer */ cell_t rval; /**< Return value from InvokeFunction() */ int32_t cip; /**< Code pointer last error occurred in */ - int32_t err; /**< Error last set by interpreter */ sp_plugin_t *plugin; PluginContext *basecx; } sp_context_t; From d2005bd42a1d3afeb6b56383103cc288c1d9e360 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Tue, 24 Feb 2015 20:53:44 -0800 Subject: [PATCH 07/14] Move cip from sp_context_t to PluginContext. --- sourcepawn/jit/debug-trace.cpp | 2 +- sourcepawn/jit/environment.cpp | 5 +++-- sourcepawn/jit/interpreter.cpp | 6 +++--- sourcepawn/jit/jit_shared.h | 1 - sourcepawn/jit/plugin-context.cpp | 4 ++-- sourcepawn/jit/plugin-context.h | 10 ++++++++++ sourcepawn/jit/x86/jit_x86.cpp | 1 + sourcepawn/jit/x86/jit_x86.h | 4 ++-- 8 files changed, 22 insertions(+), 11 deletions(-) diff --git a/sourcepawn/jit/debug-trace.cpp b/sourcepawn/jit/debug-trace.cpp index 960148dd..df857d8f 100644 --- a/sourcepawn/jit/debug-trace.cpp +++ b/sourcepawn/jit/debug-trace.cpp @@ -66,7 +66,7 @@ CContextTrace::GetTraceInfo(CallStackInfo *trace) cell_t cip; if (m_Level == 0) { - cip = m_ctx->cip; + cip = context_->cip(); } else if (context_->rp() > 0) { /* Entries go from ctx.rp - 1 to m_StartRp */ cell_t offs, start, end; diff --git a/sourcepawn/jit/environment.cpp b/sourcepawn/jit/environment.cpp index 6c2feb67..25e127e1 100644 --- a/sourcepawn/jit/environment.cpp +++ b/sourcepawn/jit/environment.cpp @@ -238,10 +238,11 @@ Environment::UnpatchAllJumpsFromTimeout() int Environment::Invoke(PluginRuntime *runtime, CompiledFunction *fn, cell_t *result) { - sp_context_t *ctx = runtime->GetBaseContext()->GetCtx(); + PluginContext *cx = runtime->GetBaseContext(); + sp_context_t *ctx = cx->GetCtx(); // Note that cip, hp, sp are saved and restored by Execute2(). - ctx->cip = fn->GetCodeOffset(); + *cx->addressOfCip() = fn->GetCodeOffset(); InvokeStubFn invoke = code_stubs_->InvokeStub(); diff --git a/sourcepawn/jit/interpreter.cpp b/sourcepawn/jit/interpreter.cpp index 50d87b87..3e8a8a7b 100644 --- a/sourcepawn/jit/interpreter.cpp +++ b/sourcepawn/jit/interpreter.cpp @@ -777,7 +777,7 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) } case OP_BREAK: - ctx->cip = uintptr_t(cip - 1) - uintptr_t(plugin->pcode); + *cx->addressOfCip() = uintptr_t(cip - 1) - uintptr_t(plugin->pcode); break; case OP_BOUNDS: @@ -805,13 +805,13 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) err = SP_ERROR_STACKLOW; goto error; } - ctx->cip = offset; + *cx->addressOfCip() = offset; ctx->sp = uintptr_t(stk) - uintptr_t(plugin->memory); int err = Interpret(rt, offset, &pri); stk = reinterpret_cast(plugin->memory + ctx->sp); - ctx->cip = rcip; + *cx->addressOfCip() = rcip; cx->popReturnCip(); if (err != SP_ERROR_NONE) diff --git a/sourcepawn/jit/jit_shared.h b/sourcepawn/jit/jit_shared.h index e2c4ad15..7b971028 100644 --- a/sourcepawn/jit/jit_shared.h +++ b/sourcepawn/jit/jit_shared.h @@ -76,7 +76,6 @@ typedef struct sp_context_s cell_t sp; /**< Stack pointer */ cell_t frm; /**< Frame pointer */ cell_t rval; /**< Return value from InvokeFunction() */ - int32_t cip; /**< Code pointer last error occurred in */ sp_plugin_t *plugin; PluginContext *basecx; } sp_context_t; diff --git a/sourcepawn/jit/plugin-context.cpp b/sourcepawn/jit/plugin-context.cpp index 61d887ea..afdae4e7 100644 --- a/sourcepawn/jit/plugin-context.cpp +++ b/sourcepawn/jit/plugin-context.cpp @@ -583,7 +583,7 @@ PluginContext::Execute2(IPluginFunction *function, const cell_t *params, unsigne save_exec = m_InExec; save_n_idx = last_native_; save_rp = rp_; - save_cip = m_ctx.cip; + save_cip = cip_; /* Push parameters */ @@ -644,7 +644,7 @@ PluginContext::Execute2(IPluginFunction *function, const cell_t *params, unsigne m_ctx.hp = save_hp; rp_ = save_rp; - m_ctx.cip = save_cip; + cip_ = save_cip; last_native_ = save_n_idx; native_error_ = SP_ERROR_NONE; m_MsgCache[0] = '\0'; diff --git a/sourcepawn/jit/plugin-context.h b/sourcepawn/jit/plugin-context.h index 90b2c9d3..cde2bd68 100644 --- a/sourcepawn/jit/plugin-context.h +++ b/sourcepawn/jit/plugin-context.h @@ -104,6 +104,13 @@ class PluginContext : public IPluginContext return offsetof(PluginContext, native_error_); } + int32_t *addressOfCip() { + return &cip_; + } + int32_t cip() const { + return cip_; + } + // Return stack logic. bool pushReturnCip(cell_t cip) { if (rp_ >= SP_MAX_RETURN_STACK) @@ -157,6 +164,9 @@ class PluginContext : public IPluginContext // Track the currently executing native index, and any error it throws. int32_t last_native_; int native_error_; + + // Most recent CIP. + int32_t cip_; }; #endif //_INCLUDE_SOURCEPAWN_BASECONTEXT_H_ diff --git a/sourcepawn/jit/x86/jit_x86.cpp b/sourcepawn/jit/x86/jit_x86.cpp index dca060d1..f0b0fbbf 100644 --- a/sourcepawn/jit/x86/jit_x86.cpp +++ b/sourcepawn/jit/x86/jit_x86.cpp @@ -303,6 +303,7 @@ CompileFromThunk(PluginRuntime *runtime, cell_t pcode_offs, void **addrp, char * Compiler::Compiler(PluginRuntime *rt, cell_t pcode_offs) : env_(Environment::get()), rt_(rt), + context_(rt->GetBaseContext()), plugin_(rt->plugin()), error_(SP_ERROR_NONE), pcode_start_(pcode_offs), diff --git a/sourcepawn/jit/x86/jit_x86.h b/sourcepawn/jit/x86/jit_x86.h index 3af246b2..7d32957b 100644 --- a/sourcepawn/jit/x86/jit_x86.h +++ b/sourcepawn/jit/x86/jit_x86.h @@ -91,8 +91,7 @@ class Compiler void emitFloatCmp(ConditionCode cc); ExternalAddress cipAddr() { - sp_context_t *ctx = rt_->GetBaseContext()->GetCtx(); - return ExternalAddress(&ctx->cip); + return ExternalAddress(context_->addressOfCip()); } ExternalAddress hpAddr() { sp_context_t *ctx = rt_->GetBaseContext()->GetCtx(); @@ -107,6 +106,7 @@ class Compiler AssemblerX86 masm; sp::Environment *env_; PluginRuntime *rt_; + PluginContext *context_; const sp_plugin_t *plugin_; int error_; uint32_t pcode_start_; From 4c9321f02a97791d3e72309e3161939c741f3847 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Tue, 24 Feb 2015 21:01:05 -0800 Subject: [PATCH 08/14] Move frm from sp_context_t to PluginContext. --- sourcepawn/jit/interpreter.cpp | 54 ++++++++++++++++--------------- sourcepawn/jit/jit_shared.h | 1 - sourcepawn/jit/plugin-context.cpp | 4 +-- sourcepawn/jit/plugin-context.h | 10 ++++++ sourcepawn/jit/x86/jit_x86.h | 3 +- 5 files changed, 41 insertions(+), 31 deletions(-) diff --git a/sourcepawn/jit/interpreter.cpp b/sourcepawn/jit/interpreter.cpp index 3e8a8a7b..07badecc 100644 --- a/sourcepawn/jit/interpreter.cpp +++ b/sourcepawn/jit/interpreter.cpp @@ -135,13 +135,15 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) // Save the original frm. BaseContext won't, and if we error, we won't hit // the stack unwinding code. - cell_t orig_frm = ctx->frm; + cell_t orig_frm = cx->frm(); cell_t pri = 0; cell_t alt = 0; cell_t *cip = code + (aCodeStart / 4); cell_t *stk = reinterpret_cast(plugin->memory + ctx->sp); + cell_t &frm = *cx->addressOfFrm(); + for (;;) { if (cip >= codeend) { err = SP_ERROR_INVALID_INSTRUCTION; @@ -175,7 +177,7 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) break; case OP_ZERO_S: - Write(plugin, ctx->frm + *cip++, 0); + Write(plugin, frm + *cip++, 0); break; case OP_PUSH_PRI: @@ -215,7 +217,7 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) int i = 1; do { - cell_t addr = ctx->frm + *cip++; + cell_t addr = frm + *cip++; *--stk = addr; } while (i++ < n); break; @@ -233,7 +235,7 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) int i = 1; do { - cell_t value = Read(plugin, ctx->frm + *cip++); + cell_t value = Read(plugin, frm + *cip++); *--stk = value; } while (i++ < n); break; @@ -278,9 +280,9 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) case OP_PROC: { - *--stk = ctx->frm; + *--stk = frm; *--stk = 0; - ctx->frm = uintptr_t(stk) - uintptr_t(plugin->memory); + frm = uintptr_t(stk) - uintptr_t(plugin->memory); break; } @@ -399,8 +401,8 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) case OP_INC_S: { cell_t offset = *cip++; - cell_t value = Read(plugin, ctx->frm + offset); - Write(plugin, ctx->frm + offset, value + 1); + cell_t value = Read(plugin, frm + offset); + Write(plugin, frm + offset, value + 1); break; } @@ -429,8 +431,8 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) case OP_DEC_S: { cell_t offset = *cip++; - cell_t value = Read(plugin, ctx->frm + offset); - Write(plugin, ctx->frm + offset, value - 1); + cell_t value = Read(plugin, frm + offset); + Write(plugin, frm + offset, value - 1); break; } @@ -450,27 +452,27 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) break; case OP_LOAD_S_PRI: - pri = Read(plugin, ctx->frm + *cip++); + pri = Read(plugin, frm + *cip++); break; case OP_LOAD_S_ALT: - alt = Read(plugin, ctx->frm + *cip++); + alt = Read(plugin, frm + *cip++); break; case OP_LOAD_S_BOTH: - pri = Read(plugin, ctx->frm + *cip++); - alt = Read(plugin, ctx->frm + *cip++); + pri = Read(plugin, frm + *cip++); + alt = Read(plugin, frm + *cip++); break; case OP_LREF_S_PRI: { - pri = Read(plugin, ctx->frm + *cip++); + pri = Read(plugin, frm + *cip++); pri = Read(plugin, pri); break; } case OP_LREF_S_ALT: { - alt = Read(plugin, ctx->frm + *cip++); + alt = Read(plugin, frm + *cip++); alt = Read(plugin, alt); break; } @@ -483,10 +485,10 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) break; case OP_ADDR_PRI: - pri = ctx->frm + *cip++; + pri = frm + *cip++; break; case OP_ADDR_ALT: - alt = ctx->frm + *cip++; + alt = frm + *cip++; break; case OP_STOR_PRI: @@ -497,10 +499,10 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) break; case OP_STOR_S_PRI: - Write(plugin, ctx->frm + *cip++, pri); + Write(plugin, frm + *cip++, pri); break; case OP_STOR_S_ALT: - Write(plugin, ctx->frm +*cip++, alt); + Write(plugin, frm +*cip++, alt); break; case OP_IDXADDR: @@ -510,7 +512,7 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) case OP_SREF_S_PRI: { cell_t offset = *cip++; - cell_t addr = Read(plugin, ctx->frm + offset); + cell_t addr = Read(plugin, frm + offset); Write(plugin, addr, pri); break; } @@ -518,7 +520,7 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) case OP_SREF_S_ALT: { cell_t offset = *cip++; - cell_t addr = Read(plugin, ctx->frm + offset); + cell_t addr = Read(plugin, frm + offset); Write(plugin, addr, alt); break; } @@ -573,7 +575,7 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) { cell_t offset = *cip++; cell_t value = *cip++; - Write(plugin, ctx->frm + offset, value); + Write(plugin, frm + offset, value); break; } @@ -645,7 +647,7 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) case OP_RETN: { stk++; - ctx->frm = *stk++; + frm = *stk++; stk += *stk + 1; *rval = pri; err = SP_ERROR_NONE; @@ -889,12 +891,12 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) } done: - assert(orig_frm == ctx->frm); + assert(orig_frm == frm); ctx->sp = uintptr_t(stk) - uintptr_t(plugin->memory); return err; error: - ctx->frm = orig_frm; + frm = orig_frm; goto done; } diff --git a/sourcepawn/jit/jit_shared.h b/sourcepawn/jit/jit_shared.h index 7b971028..2c220d93 100644 --- a/sourcepawn/jit/jit_shared.h +++ b/sourcepawn/jit/jit_shared.h @@ -74,7 +74,6 @@ typedef struct sp_context_s { cell_t hp; /**< Heap pointer */ cell_t sp; /**< Stack pointer */ - cell_t frm; /**< Frame pointer */ cell_t rval; /**< Return value from InvokeFunction() */ sp_plugin_t *plugin; PluginContext *basecx; diff --git a/sourcepawn/jit/plugin-context.cpp b/sourcepawn/jit/plugin-context.cpp index afdae4e7..58f7b4f8 100644 --- a/sourcepawn/jit/plugin-context.cpp +++ b/sourcepawn/jit/plugin-context.cpp @@ -53,7 +53,7 @@ PluginContext::PluginContext(PluginRuntime *pRuntime) m_ctx.hp = m_pRuntime->plugin()->data_size; m_ctx.sp = m_pRuntime->plugin()->mem_size - sizeof(cell_t); - m_ctx.frm = m_ctx.sp; + frm_ = m_ctx.sp; rp_ = 0; last_native_ = -1; native_error_ = SP_ERROR_NONE; @@ -784,7 +784,7 @@ PluginContext::GetLastNativeError() cell_t * PluginContext::GetLocalParams() { - return (cell_t *)(m_pRuntime->plugin()->memory + m_ctx.frm + (2 * sizeof(cell_t))); + return (cell_t *)(m_pRuntime->plugin()->memory + frm_ + (2 * sizeof(cell_t))); } void diff --git a/sourcepawn/jit/plugin-context.h b/sourcepawn/jit/plugin-context.h index cde2bd68..e71301fa 100644 --- a/sourcepawn/jit/plugin-context.h +++ b/sourcepawn/jit/plugin-context.h @@ -107,9 +107,16 @@ class PluginContext : public IPluginContext int32_t *addressOfCip() { return &cip_; } + cell_t *addressOfFrm() { + return &frm_; + } + int32_t cip() const { return cip_; } + cell_t frm() const { + return frm_; + } // Return stack logic. bool pushReturnCip(cell_t cip) { @@ -167,6 +174,9 @@ class PluginContext : public IPluginContext // Most recent CIP. int32_t cip_; + + // Frame pointer. + cell_t frm_; }; #endif //_INCLUDE_SOURCEPAWN_BASECONTEXT_H_ diff --git a/sourcepawn/jit/x86/jit_x86.h b/sourcepawn/jit/x86/jit_x86.h index 7d32957b..1b3ac4ee 100644 --- a/sourcepawn/jit/x86/jit_x86.h +++ b/sourcepawn/jit/x86/jit_x86.h @@ -98,8 +98,7 @@ class Compiler return ExternalAddress(&ctx->hp); } ExternalAddress frmAddr() { - sp_context_t *ctx = rt_->GetBaseContext()->GetCtx(); - return ExternalAddress(&ctx->frm); + return ExternalAddress(context_->addressOfFrm()); } private: From b2c61a341a8112c84451dc08ed5d4e1857c07f48 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Tue, 24 Feb 2015 21:06:06 -0800 Subject: [PATCH 09/14] Move sp from sp_context_t to PluginContext. --- sourcepawn/jit/code-stubs.h | 4 +-- sourcepawn/jit/environment.cpp | 4 +-- sourcepawn/jit/interpreter.cpp | 15 ++++++----- sourcepawn/jit/jit_shared.h | 1 - sourcepawn/jit/plugin-context.cpp | 38 +++++++++++++-------------- sourcepawn/jit/plugin-context.h | 12 ++++++++- sourcepawn/jit/plugin-runtime.h | 4 +++ sourcepawn/jit/x86/code-stubs-x86.cpp | 20 +++++++++----- sourcepawn/jit/x86/jit_x86.cpp | 3 +-- 9 files changed, 60 insertions(+), 41 deletions(-) diff --git a/sourcepawn/jit/code-stubs.h b/sourcepawn/jit/code-stubs.h index 093ec7aa..045280de 100644 --- a/sourcepawn/jit/code-stubs.h +++ b/sourcepawn/jit/code-stubs.h @@ -16,13 +16,13 @@ #include #include -typedef struct sp_context_s sp_context_t; +class PluginContext; namespace sp { class Environment; -typedef int (*InvokeStubFn)(sp_context_t *ctx, uint8_t *memory, void *code); +typedef int (*InvokeStubFn)(PluginContext *cx, void *code, cell_t *rval); class CodeStubs { diff --git a/sourcepawn/jit/environment.cpp b/sourcepawn/jit/environment.cpp index 25e127e1..7c808817 100644 --- a/sourcepawn/jit/environment.cpp +++ b/sourcepawn/jit/environment.cpp @@ -239,7 +239,6 @@ int Environment::Invoke(PluginRuntime *runtime, CompiledFunction *fn, cell_t *result) { PluginContext *cx = runtime->GetBaseContext(); - sp_context_t *ctx = cx->GetCtx(); // Note that cip, hp, sp are saved and restored by Execute2(). *cx->addressOfCip() = fn->GetCodeOffset(); @@ -247,9 +246,8 @@ Environment::Invoke(PluginRuntime *runtime, CompiledFunction *fn, cell_t *result InvokeStubFn invoke = code_stubs_->InvokeStub(); EnterInvoke(); - int err = invoke(ctx, runtime->plugin()->memory, fn->GetEntryAddress()); + int err = invoke(cx, fn->GetEntryAddress(), result); LeaveInvoke(); - *result = ctx->rval; return err; } diff --git a/sourcepawn/jit/interpreter.cpp b/sourcepawn/jit/interpreter.cpp index 07badecc..f100a6d6 100644 --- a/sourcepawn/jit/interpreter.cpp +++ b/sourcepawn/jit/interpreter.cpp @@ -137,12 +137,13 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) // the stack unwinding code. cell_t orig_frm = cx->frm(); + cell_t &frm = *cx->addressOfFrm(); + cell_t &sp = *cx->addressOfSp(); + cell_t pri = 0; cell_t alt = 0; cell_t *cip = code + (aCodeStart / 4); - cell_t *stk = reinterpret_cast(plugin->memory + ctx->sp); - - cell_t &frm = *cx->addressOfFrm(); + cell_t *stk = reinterpret_cast(plugin->memory + sp); for (;;) { if (cip >= codeend) { @@ -808,11 +809,11 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) goto error; } *cx->addressOfCip() = offset; - ctx->sp = uintptr_t(stk) - uintptr_t(plugin->memory); + sp = uintptr_t(stk) - uintptr_t(plugin->memory); int err = Interpret(rt, offset, &pri); - stk = reinterpret_cast(plugin->memory + ctx->sp); + stk = reinterpret_cast(plugin->memory + sp); *cx->addressOfCip() = rcip; cx->popReturnCip(); @@ -848,7 +849,7 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) *--stk = num_params; } - ctx->sp = uintptr_t(stk) - uintptr_t(plugin->memory); + sp = uintptr_t(stk) - uintptr_t(plugin->memory); pri = cx->invokeNative(native_index, stk); if (cx->GetLastNativeError() != SP_ERROR_NONE) { err = cx->GetLastNativeError(); @@ -892,7 +893,7 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) done: assert(orig_frm == frm); - ctx->sp = uintptr_t(stk) - uintptr_t(plugin->memory); + sp = uintptr_t(stk) - uintptr_t(plugin->memory); return err; error: diff --git a/sourcepawn/jit/jit_shared.h b/sourcepawn/jit/jit_shared.h index 2c220d93..35486862 100644 --- a/sourcepawn/jit/jit_shared.h +++ b/sourcepawn/jit/jit_shared.h @@ -73,7 +73,6 @@ class PluginContext; typedef struct sp_context_s { cell_t hp; /**< Heap pointer */ - cell_t sp; /**< Stack pointer */ cell_t rval; /**< Return value from InvokeFunction() */ sp_plugin_t *plugin; PluginContext *basecx; diff --git a/sourcepawn/jit/plugin-context.cpp b/sourcepawn/jit/plugin-context.cpp index 58f7b4f8..6ea64b0b 100644 --- a/sourcepawn/jit/plugin-context.cpp +++ b/sourcepawn/jit/plugin-context.cpp @@ -52,8 +52,8 @@ PluginContext::PluginContext(PluginRuntime *pRuntime) } m_ctx.hp = m_pRuntime->plugin()->data_size; - m_ctx.sp = m_pRuntime->plugin()->mem_size - sizeof(cell_t); - frm_ = m_ctx.sp; + sp_ = m_pRuntime->plugin()->mem_size - sizeof(cell_t); + frm_ = sp_; rp_ = 0; last_native_ = -1; native_error_ = SP_ERROR_NONE; @@ -185,7 +185,7 @@ PluginContext::HeapAlloc(unsigned int cells, cell_t *local_addr, cell_t **phys_a /** * Check if the space between the heap and stack is sufficient. */ - if ((cell_t)(m_ctx.sp - m_ctx.hp - realmem) < STACKMARGIN) + if ((cell_t)(sp_ - m_ctx.hp - realmem) < STACKMARGIN) return SP_ERROR_HEAPLOW; addr = (cell_t *)(m_pRuntime->plugin()->memory + m_ctx.hp); @@ -212,7 +212,7 @@ PluginContext::HeapPop(cell_t local_addr) /* check the bounds of this address */ local_addr -= sizeof(cell_t); - if (local_addr < (cell_t)m_pRuntime->plugin()->data_size || local_addr >= m_ctx.sp) + if (local_addr < (cell_t)m_pRuntime->plugin()->data_size || local_addr >= sp_) return SP_ERROR_INVALID_ADDRESS; addr = (cell_t *)(m_pRuntime->plugin()->memory + local_addr); @@ -325,7 +325,7 @@ PluginContext::BindNativeToAny(SPVM_NATIVE_FUNC native) int PluginContext::LocalToPhysAddr(cell_t local_addr, cell_t **phys_addr) { - if (((local_addr >= m_ctx.hp) && (local_addr < m_ctx.sp)) || + if (((local_addr >= m_ctx.hp) && (local_addr < sp_)) || (local_addr < 0) || ((ucell_t)local_addr >= m_pRuntime->plugin()->mem_size)) { return SP_ERROR_INVALID_ADDRESS; @@ -358,7 +358,7 @@ PluginContext::PushCellArray(cell_t *local_addr, cell_t **phys_addr, cell_t arra int PluginContext::LocalToString(cell_t local_addr, char **addr) { - if (((local_addr >= m_ctx.hp) && (local_addr < m_ctx.sp)) || + if (((local_addr >= m_ctx.hp) && (local_addr < sp_)) || (local_addr < 0) || ((ucell_t)local_addr >= m_pRuntime->plugin()->mem_size)) { return SP_ERROR_INVALID_ADDRESS; @@ -380,7 +380,7 @@ PluginContext::StringToLocal(cell_t local_addr, size_t bytes, const char *source char *dest; size_t len; - if (((local_addr >= m_ctx.hp) && (local_addr < m_ctx.sp)) || + if (((local_addr >= m_ctx.hp) && (local_addr < sp_)) || (local_addr < 0) || ((ucell_t)local_addr >= m_pRuntime->plugin()->mem_size)) { return SP_ERROR_INVALID_ADDRESS; @@ -443,7 +443,7 @@ PluginContext::StringToLocalUTF8(cell_t local_addr, size_t maxbytes, const char size_t len; bool needtocheck = false; - if (((local_addr >= m_ctx.hp) && (local_addr < m_ctx.sp)) || + if (((local_addr >= m_ctx.hp) && (local_addr < sp_)) || (local_addr < 0) || ((ucell_t)local_addr >= m_pRuntime->plugin()->mem_size)) { @@ -548,7 +548,7 @@ PluginContext::Execute2(IPluginFunction *function, const cell_t *params, unsigne if (m_pRuntime->IsPaused()) return SP_ERROR_NOT_RUNNABLE; - if ((cell_t)(m_ctx.hp + 16*sizeof(cell_t)) > (cell_t)(m_ctx.sp - (sizeof(cell_t) * (num_params + 1)))) + if ((cell_t)(m_ctx.hp + 16*sizeof(cell_t)) > (cell_t)(sp_ - (sizeof(cell_t) * (num_params + 1)))) return SP_ERROR_STACKLOW; if (result == NULL) @@ -578,7 +578,7 @@ PluginContext::Execute2(IPluginFunction *function, const cell_t *params, unsigne uint32_t save_n_idx; cell_t save_sp, save_hp, save_rp, save_cip; - save_sp = m_ctx.sp; + save_sp = sp_; save_hp = m_ctx.hp; save_exec = m_InExec; save_n_idx = last_native_; @@ -587,8 +587,8 @@ PluginContext::Execute2(IPluginFunction *function, const cell_t *params, unsigne /* Push parameters */ - m_ctx.sp -= sizeof(cell_t) * (num_params + 1); - sp = (cell_t *)(m_pRuntime->plugin()->memory + m_ctx.sp); + sp_ -= sizeof(cell_t) * (num_params + 1); + sp = (cell_t *)(m_pRuntime->plugin()->memory + sp_); sp[0] = num_params; for (unsigned int i = 0; i < num_params; i++) @@ -614,10 +614,10 @@ PluginContext::Execute2(IPluginFunction *function, const cell_t *params, unsigne if (ir == SP_ERROR_NONE) { native_error_ = SP_ERROR_NONE; - if (m_ctx.sp != save_sp) { + if (sp_ != save_sp) { ir = SP_ERROR_STACKLEAK; _SetErrorMessage("Stack leak detected: sp:%d should be %d!", - m_ctx.sp, + sp_, save_sp); } if (m_ctx.hp != save_hp) { @@ -640,7 +640,7 @@ PluginContext::Execute2(IPluginFunction *function, const cell_t *params, unsigne if (ir != SP_ERROR_NONE) Environment::get()->ReportError(m_pRuntime, ir, m_MsgCache, save_rp); - m_ctx.sp = save_sp; + sp_ = save_sp; m_ctx.hp = save_hp; rp_ = save_rp; @@ -854,7 +854,7 @@ PluginContext::pushTracker(uint32_t amount) cell_t PluginContext::invokeNative(ucell_t native_idx, cell_t *params) { - cell_t save_sp = m_ctx.sp; + cell_t save_sp = sp_; cell_t save_hp = m_ctx.hp; // Note: Invoke() saves the last native, so we don't need to here. @@ -872,7 +872,7 @@ PluginContext::invokeNative(ucell_t native_idx, cell_t *params) if (native_error_ != SP_ERROR_NONE) return result; - if (save_sp != m_ctx.sp) { + if (save_sp != sp_) { native_error_ = SP_ERROR_STACKLEAK; return result; } @@ -887,7 +887,7 @@ PluginContext::invokeNative(ucell_t native_idx, cell_t *params) cell_t PluginContext::invokeBoundNative(SPVM_NATIVE_FUNC pfn, cell_t *params) { - cell_t save_sp = m_ctx.sp; + cell_t save_sp = sp_; cell_t save_hp = m_ctx.hp; cell_t result = pfn(this, params); @@ -895,7 +895,7 @@ PluginContext::invokeBoundNative(SPVM_NATIVE_FUNC pfn, cell_t *params) if (native_error_ != SP_ERROR_NONE) return result; - if (save_sp != m_ctx.sp) { + if (save_sp != sp_) { native_error_ = SP_ERROR_STACKLEAK; return result; } diff --git a/sourcepawn/jit/plugin-context.h b/sourcepawn/jit/plugin-context.h index e71301fa..4a78eac5 100644 --- a/sourcepawn/jit/plugin-context.h +++ b/sourcepawn/jit/plugin-context.h @@ -103,10 +103,19 @@ class PluginContext : public IPluginContext static inline size_t offsetOfNativeError() { return offsetof(PluginContext, native_error_); } + static inline size_t offsetOfSp() { + return offsetof(PluginContext, sp_); + } + static inline size_t offsetOfRuntime() { + return offsetof(PluginContext, m_pRuntime); + } int32_t *addressOfCip() { return &cip_; } + int32_t *addressOfSp() { + return &sp_; + } cell_t *addressOfFrm() { return &frm_; } @@ -175,7 +184,8 @@ class PluginContext : public IPluginContext // Most recent CIP. int32_t cip_; - // Frame pointer. + // Stack and frame pointer. + cell_t sp_; cell_t frm_; }; diff --git a/sourcepawn/jit/plugin-runtime.h b/sourcepawn/jit/plugin-runtime.h index 9f0706a0..1ced62dc 100644 --- a/sourcepawn/jit/plugin-runtime.h +++ b/sourcepawn/jit/plugin-runtime.h @@ -96,6 +96,10 @@ class PluginRuntime return m_JitFunctions[i]; } + static inline size_t offsetToPlugin() { + return offsetof(PluginRuntime, m_plugin); + } + private: void SetupFloatNativeRemapping(); diff --git a/sourcepawn/jit/x86/code-stubs-x86.cpp b/sourcepawn/jit/x86/code-stubs-x86.cpp index 2b7a4b94..9b85bb1a 100644 --- a/sourcepawn/jit/x86/code-stubs-x86.cpp +++ b/sourcepawn/jit/x86/code-stubs-x86.cpp @@ -47,12 +47,19 @@ CodeStubs::CompileInvokeStub() __ push(ebx); // ebp - 12 __ push(esp); // ebp - 16 + // ebx = cx __ movl(ebx, Operand(ebp, 8 + 4 * 0)); - __ movl(eax, Operand(ebp, 8 + 4 * 1)); - __ movl(ecx, Operand(ebp, 8 + 4 * 2)); + + // ecx = code + __ movl(ecx, Operand(ebp, 8 + 4 * 1)); + + // eax = cx->m_pRuntime->m_plugin.memory + __ movl(eax, Operand(ebx, PluginContext::offsetOfRuntime())); + __ addl(eax, PluginRuntime::offsetToPlugin()); + __ movl(eax, Operand(eax, offsetof(sp_plugin_t, memory))); // Set up run-time registers. - __ movl(edi, Operand(ebx, offsetof(sp_context_t, sp))); + __ movl(edi, Operand(ebx, PluginContext::offsetOfSp())); __ addl(edi, eax); __ movl(esi, eax); __ movl(ebx, edi); @@ -64,8 +71,8 @@ CodeStubs::CompileInvokeStub() __ call(ecx); // Get input context, store rval. - __ movl(ecx, Operand(ebp, 8 + 4 * 0)); - __ movl(Operand(ecx, offsetof(sp_context_t, rval)), pri); + __ movl(ecx, Operand(ebp, 8 + 4 * 2)); + __ movl(Operand(ecx, 0), pri); // Set no error. __ movl(eax, SP_ERROR_NONE); @@ -75,7 +82,8 @@ CodeStubs::CompileInvokeStub() Label ret; __ bind(&ret); __ subl(stk, dat); - __ movl(Operand(ecx, offsetof(sp_context_t, sp)), stk); + __ movl(ecx, Operand(ebp, 8 + 4 * 0)); + __ movl(Operand(ecx, PluginContext::offsetOfSp()), stk); // Restore stack. __ movl(esp, Operand(ebp, -16)); diff --git a/sourcepawn/jit/x86/jit_x86.cpp b/sourcepawn/jit/x86/jit_x86.cpp index f0b0fbbf..576c6d1e 100644 --- a/sourcepawn/jit/x86/jit_x86.cpp +++ b/sourcepawn/jit/x86/jit_x86.cpp @@ -1612,9 +1612,8 @@ Compiler::emitNativeCall(OPCODE op) // Relocate our absolute stk to be dat-relative, and update the context's // view. - __ movl(eax, intptr_t(rt_->GetBaseContext()->GetCtx())); __ subl(stk, dat); - __ movl(Operand(eax, offsetof(sp_context_t, sp)), stk); + __ movl(Operand(eax, PluginContext::offsetOfSp()), stk); sp_native_t *native = rt_->GetNativeByIndex(native_index); if ((native->status != SP_NATIVE_BOUND) || From 31ab1ced06e14c94acb4c238d7745e2f115e2c88 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Tue, 24 Feb 2015 21:18:34 -0800 Subject: [PATCH 10/14] Move hp from sp_context_t to PluginContext. --- sourcepawn/jit/interpreter.cpp | 73 +++-------- sourcepawn/jit/interpreter.h | 3 - sourcepawn/jit/jit_shared.h | 1 - sourcepawn/jit/plugin-context.cpp | 199 ++++++++++++++++++++++++++---- sourcepawn/jit/plugin-context.h | 24 +++- sourcepawn/jit/x86/jit_x86.cpp | 132 ++------------------ sourcepawn/jit/x86/jit_x86.h | 3 +- 7 files changed, 221 insertions(+), 214 deletions(-) diff --git a/sourcepawn/jit/interpreter.cpp b/sourcepawn/jit/interpreter.cpp index f100a6d6..096049c6 100644 --- a/sourcepawn/jit/interpreter.cpp +++ b/sourcepawn/jit/interpreter.cpp @@ -73,51 +73,6 @@ JumpTarget(const sp_plugin_t *plugin, sp_context_t *ctx, cell_t *cip, bool cond, return next; } -static inline bool -CheckAddress(const sp_plugin_t *plugin, sp_context_t *ctx, cell_t *stk, cell_t addr) -{ - if (uint32_t(addr) >= plugin->mem_size) - return false; - - if (addr < ctx->hp) - return true; - - if (reinterpret_cast(plugin->memory + addr) < stk) - return false; - - return true; -} - -static inline int -GenerateArray(PluginRuntime *rt, sp_context_t *ctx, cell_t dims, cell_t *stk, bool autozero) -{ - if (dims == 1) { - uint32_t size = *stk; - if (size == 0 || !ke::IsUint32MultiplySafe(size, 4)) - return SP_ERROR_ARRAY_TOO_BIG; - *stk = ctx->hp; - - uint32_t bytes = size * 4; - - ctx->hp += bytes; - if (uintptr_t(ctx->plugin->memory + ctx->hp) >= uintptr_t(stk)) - return SP_ERROR_HEAPLOW; - - if (int err = rt->GetBaseContext()->pushTracker(bytes)) - return err; - - if (autozero) - memset(ctx->plugin->memory + ctx->hp, 0, bytes); - - return SP_ERROR_NONE; - } - - if (int err = GenerateFullArray(rt, dims, stk, autozero)) - return err; - - return SP_ERROR_NONE; -} - int Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) { @@ -408,7 +363,7 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) } case OP_INC_I: - if (!CheckAddress(plugin, ctx, stk, pri)) { + if (!cx->checkAddress(stk, pri)) { err = SP_ERROR_MEMACCESS; goto error; } @@ -438,7 +393,7 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) } case OP_DEC_I: - if (!CheckAddress(plugin, ctx, stk, pri)) { + if (!cx->checkAddress(stk, pri)) { err = SP_ERROR_MEMACCESS; goto error; } @@ -545,7 +500,7 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) case OP_LIDX: pri = alt + pri * 4; - if (!CheckAddress(plugin, ctx, stk, pri)) { + if (!cx->checkAddress(stk, pri)) { err = SP_ERROR_MEMACCESS; goto error; } @@ -556,7 +511,7 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) { cell_t val = *cip++; pri = alt + (pri << val); - if (!CheckAddress(plugin, ctx, stk, pri)) { + if (!cx->checkAddress(stk, pri)) { err = SP_ERROR_MEMACCESS; goto error; } @@ -581,7 +536,7 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) } case OP_LOAD_I: - if (!CheckAddress(plugin, ctx, stk, pri)) { + if (!cx->checkAddress(stk, pri)) { err = SP_ERROR_MEMACCESS; goto error; } @@ -589,7 +544,7 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) break; case OP_STOR_I: - if (!CheckAddress(plugin, ctx, stk, alt)) { + if (!cx->checkAddress(stk, alt)) { err = SP_ERROR_MEMACCESS; goto error; } @@ -617,7 +572,7 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) case OP_LODB_I: { cell_t val = *cip++; - if (!CheckAddress(plugin, ctx, stk, pri)) { + if (!cx->checkAddress(stk, pri)) { err = SP_ERROR_MEMACCESS; goto error; } @@ -632,7 +587,7 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) case OP_STRB_I: { cell_t val = *cip++; - if (!CheckAddress(plugin, ctx, stk, alt)) { + if (!cx->checkAddress(stk, alt)) { err = SP_ERROR_MEMACCESS; goto error; } @@ -690,7 +645,7 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) goto error; } } else { - if (uintptr_t(stk) < uintptr_t(plugin->memory + ctx->hp + STACK_MARGIN)) { + if (uintptr_t(stk) < uintptr_t(plugin->memory + cx->hp() + STACK_MARGIN)) { err = SP_ERROR_STACKLOW; goto error; } @@ -702,16 +657,16 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) { cell_t amount = *cip++; - alt = ctx->hp; - ctx->hp += amount; + alt = cx->hp(); + *cx->addressOfHp() += amount; if (amount > 0) { - if (uintptr_t(plugin->memory + ctx->hp) > uintptr_t(stk)) { + if (uintptr_t(plugin->memory + cx->hp()) > uintptr_t(stk)) { err = SP_ERROR_HEAPLOW; goto error; } } else { - if (uint32_t(ctx->hp) < plugin->data_size) { + if (uint32_t(cx->hp()) < plugin->data_size) { err = SP_ERROR_HEAPMIN; goto error; } @@ -826,7 +781,7 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) case OP_GENARRAY_Z: { cell_t val = *cip++; - if ((err = GenerateArray(rt, ctx, val, stk, op == OP_GENARRAY_Z)) != SP_ERROR_NONE) + if ((err = cx->generateArray(val, stk, op == OP_GENARRAY_Z)) != SP_ERROR_NONE) goto error; stk += (val - 1) * 4; diff --git a/sourcepawn/jit/interpreter.h b/sourcepawn/jit/interpreter.h index 0274707a..c367874d 100644 --- a/sourcepawn/jit/interpreter.h +++ b/sourcepawn/jit/interpreter.h @@ -24,7 +24,4 @@ int Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval); -int GenerateFullArray(PluginRuntime *rt, uint32_t argc, cell_t *argv, int autozero); -cell_t BoundNativeCallback(sp_context_t *ctx, SPVM_NATIVE_FUNC pfn, cell_t *params); - #endif // _include_sourcepawn_interpreter_h_ diff --git a/sourcepawn/jit/jit_shared.h b/sourcepawn/jit/jit_shared.h index 35486862..2aec77b0 100644 --- a/sourcepawn/jit/jit_shared.h +++ b/sourcepawn/jit/jit_shared.h @@ -72,7 +72,6 @@ class PluginContext; typedef struct sp_context_s { - cell_t hp; /**< Heap pointer */ cell_t rval; /**< Return value from InvokeFunction() */ sp_plugin_t *plugin; PluginContext *basecx; diff --git a/sourcepawn/jit/plugin-context.cpp b/sourcepawn/jit/plugin-context.cpp index 6ea64b0b..1c173e15 100644 --- a/sourcepawn/jit/plugin-context.cpp +++ b/sourcepawn/jit/plugin-context.cpp @@ -51,7 +51,7 @@ PluginContext::PluginContext(PluginRuntime *pRuntime) m_pNullString = NULL; } - m_ctx.hp = m_pRuntime->plugin()->data_size; + hp_ = m_pRuntime->plugin()->data_size; sp_ = m_pRuntime->plugin()->mem_size - sizeof(cell_t); frm_ = sp_; rp_ = 0; @@ -185,21 +185,21 @@ PluginContext::HeapAlloc(unsigned int cells, cell_t *local_addr, cell_t **phys_a /** * Check if the space between the heap and stack is sufficient. */ - if ((cell_t)(sp_ - m_ctx.hp - realmem) < STACKMARGIN) + if ((cell_t)(sp_ - hp_ - realmem) < STACKMARGIN) return SP_ERROR_HEAPLOW; - addr = (cell_t *)(m_pRuntime->plugin()->memory + m_ctx.hp); + addr = (cell_t *)(m_pRuntime->plugin()->memory + hp_); /* store size of allocation in cells */ *addr = (cell_t)cells; addr++; - m_ctx.hp += sizeof(cell_t); + hp_ += sizeof(cell_t); - *local_addr = m_ctx.hp; + *local_addr = hp_; if (phys_addr) *phys_addr = addr; - m_ctx.hp += realmem; + hp_ += realmem; return SP_ERROR_NONE; } @@ -218,10 +218,10 @@ PluginContext::HeapPop(cell_t local_addr) addr = (cell_t *)(m_pRuntime->plugin()->memory + local_addr); cellcount = (*addr) * sizeof(cell_t); /* check if this memory count looks valid */ - if ((signed)(m_ctx.hp - cellcount - sizeof(cell_t)) != local_addr) + if ((signed)(hp_ - cellcount - sizeof(cell_t)) != local_addr) return SP_ERROR_INVALID_ADDRESS; - m_ctx.hp = local_addr; + hp_ = local_addr; return SP_ERROR_NONE; } @@ -233,7 +233,7 @@ PluginContext::HeapRelease(cell_t local_addr) if (local_addr < (cell_t)m_pRuntime->plugin()->data_size) return SP_ERROR_INVALID_ADDRESS; - m_ctx.hp = local_addr - sizeof(cell_t); + hp_ = local_addr - sizeof(cell_t); return SP_ERROR_NONE; } @@ -325,7 +325,7 @@ PluginContext::BindNativeToAny(SPVM_NATIVE_FUNC native) int PluginContext::LocalToPhysAddr(cell_t local_addr, cell_t **phys_addr) { - if (((local_addr >= m_ctx.hp) && (local_addr < sp_)) || + if (((local_addr >= hp_) && (local_addr < sp_)) || (local_addr < 0) || ((ucell_t)local_addr >= m_pRuntime->plugin()->mem_size)) { return SP_ERROR_INVALID_ADDRESS; @@ -358,7 +358,7 @@ PluginContext::PushCellArray(cell_t *local_addr, cell_t **phys_addr, cell_t arra int PluginContext::LocalToString(cell_t local_addr, char **addr) { - if (((local_addr >= m_ctx.hp) && (local_addr < sp_)) || + if (((local_addr >= hp_) && (local_addr < sp_)) || (local_addr < 0) || ((ucell_t)local_addr >= m_pRuntime->plugin()->mem_size)) { return SP_ERROR_INVALID_ADDRESS; @@ -380,7 +380,7 @@ PluginContext::StringToLocal(cell_t local_addr, size_t bytes, const char *source char *dest; size_t len; - if (((local_addr >= m_ctx.hp) && (local_addr < sp_)) || + if (((local_addr >= hp_) && (local_addr < sp_)) || (local_addr < 0) || ((ucell_t)local_addr >= m_pRuntime->plugin()->mem_size)) { return SP_ERROR_INVALID_ADDRESS; @@ -443,7 +443,7 @@ PluginContext::StringToLocalUTF8(cell_t local_addr, size_t maxbytes, const char size_t len; bool needtocheck = false; - if (((local_addr >= m_ctx.hp) && (local_addr < sp_)) || + if (((local_addr >= hp_) && (local_addr < sp_)) || (local_addr < 0) || ((ucell_t)local_addr >= m_pRuntime->plugin()->mem_size)) { @@ -548,7 +548,7 @@ PluginContext::Execute2(IPluginFunction *function, const cell_t *params, unsigne if (m_pRuntime->IsPaused()) return SP_ERROR_NOT_RUNNABLE; - if ((cell_t)(m_ctx.hp + 16*sizeof(cell_t)) > (cell_t)(sp_ - (sizeof(cell_t) * (num_params + 1)))) + if ((cell_t)(hp_ + 16*sizeof(cell_t)) > (cell_t)(sp_ - (sizeof(cell_t) * (num_params + 1)))) return SP_ERROR_STACKLOW; if (result == NULL) @@ -579,7 +579,7 @@ PluginContext::Execute2(IPluginFunction *function, const cell_t *params, unsigne cell_t save_sp, save_hp, save_rp, save_cip; save_sp = sp_; - save_hp = m_ctx.hp; + save_hp = hp_; save_exec = m_InExec; save_n_idx = last_native_; save_rp = rp_; @@ -620,10 +620,10 @@ PluginContext::Execute2(IPluginFunction *function, const cell_t *params, unsigne sp_, save_sp); } - if (m_ctx.hp != save_hp) { + if (hp_ != save_hp) { ir = SP_ERROR_HEAPLEAK; _SetErrorMessage("Heap leak detected: hp:%d should be %d!", - m_ctx.hp, + hp_, save_hp); } if (rp_ != save_rp) { @@ -641,7 +641,7 @@ PluginContext::Execute2(IPluginFunction *function, const cell_t *params, unsigne Environment::get()->ReportError(m_pRuntime, ir, m_MsgCache, save_rp); sp_ = save_sp; - m_ctx.hp = save_hp; + hp_ = save_hp; rp_ = save_rp; cip_ = save_cip; @@ -823,10 +823,10 @@ PluginContext::popTrackerAndSetHeap() return SP_ERROR_TRACKER_BOUNDS; ucell_t amt = *tracker_.pCur; - if (amt > (m_ctx.hp - m_pRuntime->plugin()->data_size)) + if (amt > (hp_ - m_pRuntime->plugin()->data_size)) return SP_ERROR_HEAPMIN; - m_ctx.hp -= amt; + hp_ -= amt; return SP_ERROR_NONE; } @@ -855,7 +855,7 @@ cell_t PluginContext::invokeNative(ucell_t native_idx, cell_t *params) { cell_t save_sp = sp_; - cell_t save_hp = m_ctx.hp; + cell_t save_hp = hp_; // Note: Invoke() saves the last native, so we don't need to here. last_native_ = native_idx; @@ -876,7 +876,7 @@ PluginContext::invokeNative(ucell_t native_idx, cell_t *params) native_error_ = SP_ERROR_STACKLEAK; return result; } - if (save_hp != m_ctx.hp) { + if (save_hp != hp_) { native_error_ = SP_ERROR_HEAPLEAK; return result; } @@ -888,7 +888,7 @@ cell_t PluginContext::invokeBoundNative(SPVM_NATIVE_FUNC pfn, cell_t *params) { cell_t save_sp = sp_; - cell_t save_hp = m_ctx.hp; + cell_t save_hp = hp_; cell_t result = pfn(this, params); @@ -899,10 +899,161 @@ PluginContext::invokeBoundNative(SPVM_NATIVE_FUNC pfn, cell_t *params) native_error_ = SP_ERROR_STACKLEAK; return result; } - if (save_hp != m_ctx.hp) { + if (save_hp != hp_) { native_error_ = SP_ERROR_HEAPLEAK; return result; } return result; } + +struct array_creation_t +{ + const cell_t *dim_list; /* Dimension sizes */ + cell_t dim_count; /* Number of dimensions */ + cell_t *data_offs; /* Current offset AFTER the indirection vectors (data) */ + cell_t *base; /* array base */ +}; + +static cell_t +GenerateInnerArrayIndirectionVectors(array_creation_t *ar, int dim, cell_t cur_offs) +{ + cell_t write_offs = cur_offs; + cell_t *data_offs = ar->data_offs; + + cur_offs += ar->dim_list[dim]; + + // Dimension n-x where x > 2 will have sub-vectors. + // Otherwise, we just need to reference the data section. + if (ar->dim_count > 2 && dim < ar->dim_count - 2) { + // For each index at this dimension, write offstes to our sub-vectors. + // After we write one sub-vector, we generate its sub-vectors recursively. + // At the end, we're given the next offset we can use. + for (int i = 0; i < ar->dim_list[dim]; i++) { + ar->base[write_offs] = (cur_offs - write_offs) * sizeof(cell_t); + write_offs++; + cur_offs = GenerateInnerArrayIndirectionVectors(ar, dim + 1, cur_offs); + } + } else { + // In this section, there are no sub-vectors, we need to write offsets + // to the data. This is separate so the data stays in one big chunk. + // The data offset will increment by the size of the last dimension, + // because that is where the data is finally computed as. + for (int i = 0; i < ar->dim_list[dim]; i++) { + ar->base[write_offs] = (*data_offs - write_offs) * sizeof(cell_t); + write_offs++; + *data_offs = *data_offs + ar->dim_list[dim + 1]; + } + } + + return cur_offs; +} + +static cell_t +calc_indirection(const array_creation_t *ar, cell_t dim) +{ + cell_t size = ar->dim_list[dim]; + if (dim < ar->dim_count - 2) + size += ar->dim_list[dim] * calc_indirection(ar, dim + 1); + return size; +} + +static cell_t +GenerateArrayIndirectionVectors(cell_t *arraybase, cell_t dims[], cell_t _dimcount, bool autozero) +{ + array_creation_t ar; + cell_t data_offs; + + /* Reverse the dimensions */ + cell_t dim_list[sDIMEN_MAX]; + int cur_dim = 0; + for (int i = _dimcount - 1; i >= 0; i--) + dim_list[cur_dim++] = dims[i]; + + ar.base = arraybase; + ar.dim_list = dim_list; + ar.dim_count = _dimcount; + ar.data_offs = &data_offs; + + data_offs = calc_indirection(&ar, 0); + GenerateInnerArrayIndirectionVectors(&ar, 0, 0); + return data_offs; +} + +int +PluginContext::generateFullArray(uint32_t argc, cell_t *argv, int autozero) +{ + // Calculate how many cells are needed. + if (argv[0] <= 0) + return SP_ERROR_ARRAY_TOO_BIG; + + uint32_t cells = argv[0]; + + for (uint32_t dim = 1; dim < argc; dim++) { + cell_t dimsize = argv[dim]; + if (dimsize <= 0) + return SP_ERROR_ARRAY_TOO_BIG; + if (!ke::IsUint32MultiplySafe(cells, dimsize)) + return SP_ERROR_ARRAY_TOO_BIG; + cells *= uint32_t(dimsize); + if (!ke::IsUint32AddSafe(cells, dimsize)) + return SP_ERROR_ARRAY_TOO_BIG; + cells += uint32_t(dimsize); + } + + if (!ke::IsUint32MultiplySafe(cells, 4)) + return SP_ERROR_ARRAY_TOO_BIG; + + uint32_t bytes = cells * 4; + if (!ke::IsUint32AddSafe(hp_, bytes)) + return SP_ERROR_ARRAY_TOO_BIG; + + uint32_t new_hp = hp_ + bytes; + cell_t *dat_hp = reinterpret_cast(m_pRuntime->plugin()->memory + new_hp); + + // argv, coincidentally, is STK. + if (dat_hp >= argv - STACK_MARGIN) + return SP_ERROR_HEAPLOW; + + if (int err = pushTracker(bytes)) + return err; + + cell_t *base = reinterpret_cast(m_pRuntime->plugin()->memory + hp_); + cell_t offs = GenerateArrayIndirectionVectors(base, argv, argc, !!autozero); + assert(size_t(offs) == cells); + + argv[argc - 1] = hp_; + hp_ = new_hp; + return SP_ERROR_NONE; +} + +int +PluginContext::generateArray(cell_t dims, cell_t *stk, bool autozero) +{ + if (dims == 1) { + uint32_t size = *stk; + if (size == 0 || !ke::IsUint32MultiplySafe(size, 4)) + return SP_ERROR_ARRAY_TOO_BIG; + *stk = hp_; + + uint32_t bytes = size * 4; + + hp_ += bytes; + if (uintptr_t(m_pRuntime->plugin()->memory + hp_) >= uintptr_t(stk)) + return SP_ERROR_HEAPLOW; + + if (int err = pushTracker(bytes)) + return err; + + if (autozero) + memset(m_pRuntime->plugin()->memory + hp_, 0, bytes); + + return SP_ERROR_NONE; + } + + if (int err = generateFullArray(dims, stk, autozero)) + return err; + + return SP_ERROR_NONE; +} + diff --git a/sourcepawn/jit/plugin-context.h b/sourcepawn/jit/plugin-context.h index 4a78eac5..65a0a243 100644 --- a/sourcepawn/jit/plugin-context.h +++ b/sourcepawn/jit/plugin-context.h @@ -119,6 +119,9 @@ class PluginContext : public IPluginContext cell_t *addressOfFrm() { return &frm_; } + cell_t *addressOfHp() { + return &hp_; + } int32_t cip() const { return cip_; @@ -126,6 +129,9 @@ class PluginContext : public IPluginContext cell_t frm() const { return frm_; } + cell_t hp() const { + return hp_; + } // Return stack logic. bool pushReturnCip(cell_t cip) { @@ -149,12 +155,27 @@ class PluginContext : public IPluginContext int popTrackerAndSetHeap(); int pushTracker(uint32_t amount); + int generateArray(cell_t dims, cell_t *stk, bool autozero); + int generateFullArray(uint32_t argc, cell_t *argv, int autozero); cell_t invokeNative(ucell_t native_idx, cell_t *params); cell_t invokeBoundNative(SPVM_NATIVE_FUNC pfn, cell_t *params); int lastNative() const { return last_native_; } + inline bool checkAddress(cell_t *stk, cell_t addr) { + if (uint32_t(addr) >= m_pRuntime->plugin()->mem_size) + return false; + + if (addr < hp_) + return true; + + if (reinterpret_cast(m_pRuntime->plugin()->memory + addr) < stk) + return false; + + return true; + } + private: void SetErrorMessage(const char *msg, va_list ap); void _SetErrorMessage(const char *msg, ...); @@ -184,8 +205,9 @@ class PluginContext : public IPluginContext // Most recent CIP. int32_t cip_; - // Stack and frame pointer. + // Stack, heap, and frame pointer. cell_t sp_; + cell_t hp_; cell_t frm_; }; diff --git a/sourcepawn/jit/x86/jit_x86.cpp b/sourcepawn/jit/x86/jit_x86.cpp index 576c6d1e..b06a8548 100644 --- a/sourcepawn/jit/x86/jit_x86.cpp +++ b/sourcepawn/jit/x86/jit_x86.cpp @@ -77,128 +77,6 @@ OpToCondition(OPCODE op) } } -struct array_creation_t -{ - const cell_t *dim_list; /* Dimension sizes */ - cell_t dim_count; /* Number of dimensions */ - cell_t *data_offs; /* Current offset AFTER the indirection vectors (data) */ - cell_t *base; /* array base */ -}; - -static cell_t -GenerateInnerArrayIndirectionVectors(array_creation_t *ar, int dim, cell_t cur_offs) -{ - cell_t write_offs = cur_offs; - cell_t *data_offs = ar->data_offs; - - cur_offs += ar->dim_list[dim]; - - // Dimension n-x where x > 2 will have sub-vectors. - // Otherwise, we just need to reference the data section. - if (ar->dim_count > 2 && dim < ar->dim_count - 2) { - // For each index at this dimension, write offstes to our sub-vectors. - // After we write one sub-vector, we generate its sub-vectors recursively. - // At the end, we're given the next offset we can use. - for (int i = 0; i < ar->dim_list[dim]; i++) { - ar->base[write_offs] = (cur_offs - write_offs) * sizeof(cell_t); - write_offs++; - cur_offs = GenerateInnerArrayIndirectionVectors(ar, dim + 1, cur_offs); - } - } else { - // In this section, there are no sub-vectors, we need to write offsets - // to the data. This is separate so the data stays in one big chunk. - // The data offset will increment by the size of the last dimension, - // because that is where the data is finally computed as. - for (int i = 0; i < ar->dim_list[dim]; i++) { - ar->base[write_offs] = (*data_offs - write_offs) * sizeof(cell_t); - write_offs++; - *data_offs = *data_offs + ar->dim_list[dim + 1]; - } - } - - return cur_offs; -} - -static cell_t -calc_indirection(const array_creation_t *ar, cell_t dim) -{ - cell_t size = ar->dim_list[dim]; - if (dim < ar->dim_count - 2) - size += ar->dim_list[dim] * calc_indirection(ar, dim + 1); - return size; -} - -static cell_t -GenerateArrayIndirectionVectors(cell_t *arraybase, cell_t dims[], cell_t _dimcount, bool autozero) -{ - array_creation_t ar; - cell_t data_offs; - - /* Reverse the dimensions */ - cell_t dim_list[sDIMEN_MAX]; - int cur_dim = 0; - for (int i = _dimcount - 1; i >= 0; i--) - dim_list[cur_dim++] = dims[i]; - - ar.base = arraybase; - ar.dim_list = dim_list; - ar.dim_count = _dimcount; - ar.data_offs = &data_offs; - - data_offs = calc_indirection(&ar, 0); - GenerateInnerArrayIndirectionVectors(&ar, 0, 0); - return data_offs; -} - -int -GenerateFullArray(PluginRuntime *rt, uint32_t argc, cell_t *argv, int autozero) -{ - sp_context_t *ctx = rt->GetBaseContext()->GetCtx(); - - // Calculate how many cells are needed. - if (argv[0] <= 0) - return SP_ERROR_ARRAY_TOO_BIG; - - uint32_t cells = argv[0]; - - for (uint32_t dim = 1; dim < argc; dim++) { - cell_t dimsize = argv[dim]; - if (dimsize <= 0) - return SP_ERROR_ARRAY_TOO_BIG; - if (!ke::IsUint32MultiplySafe(cells, dimsize)) - return SP_ERROR_ARRAY_TOO_BIG; - cells *= uint32_t(dimsize); - if (!ke::IsUint32AddSafe(cells, dimsize)) - return SP_ERROR_ARRAY_TOO_BIG; - cells += uint32_t(dimsize); - } - - if (!ke::IsUint32MultiplySafe(cells, 4)) - return SP_ERROR_ARRAY_TOO_BIG; - - uint32_t bytes = cells * 4; - if (!ke::IsUint32AddSafe(ctx->hp, bytes)) - return SP_ERROR_ARRAY_TOO_BIG; - - uint32_t new_hp = ctx->hp + bytes; - cell_t *dat_hp = reinterpret_cast(rt->plugin()->memory + new_hp); - - // argv, coincidentally, is STK. - if (dat_hp >= argv - STACK_MARGIN) - return SP_ERROR_HEAPLOW; - - if (int err = rt->GetBaseContext()->pushTracker(bytes)) - return err; - - cell_t *base = reinterpret_cast(rt->plugin()->memory + ctx->hp); - cell_t offs = GenerateArrayIndirectionVectors(base, argv, argc, !!autozero); - assert(size_t(offs) == cells); - - argv[argc - 1] = ctx->hp; - ctx->hp = new_hp; - return SP_ERROR_NONE; -} - #if !defined NDEBUG static const char * GetFunctionName(const sp_plugin_t *plugin, uint32_t offs) @@ -410,6 +288,12 @@ InvokeBoundNativeHelper(PluginContext *cx, SPVM_NATIVE_FUNC fn, cell_t *params) return cx->invokeBoundNative(fn, params); } +static int +InvokeGenerateFullArray(PluginContext *cx, uint32_t argc, cell_t *argv, int autozero) +{ + return cx->generateFullArray(argc, argv, autozero); +} + bool Compiler::emitOp(OPCODE op) { @@ -1458,8 +1342,8 @@ Compiler::emitGenArray(bool autozero) __ push(autozero ? 1 : 0); __ push(stk); __ push(val); - __ push(intptr_t(rt_)); - __ call(ExternalAddress((void *)GenerateFullArray)); + __ push(intptr_t(context_)); + __ call(ExternalAddress((void *)InvokeGenerateFullArray)); __ addl(esp, 4 * sizeof(void *)); // restore pri to tmp diff --git a/sourcepawn/jit/x86/jit_x86.h b/sourcepawn/jit/x86/jit_x86.h index 1b3ac4ee..ddea57ed 100644 --- a/sourcepawn/jit/x86/jit_x86.h +++ b/sourcepawn/jit/x86/jit_x86.h @@ -94,8 +94,7 @@ class Compiler return ExternalAddress(context_->addressOfCip()); } ExternalAddress hpAddr() { - sp_context_t *ctx = rt_->GetBaseContext()->GetCtx(); - return ExternalAddress(&ctx->hp); + return ExternalAddress(context_->addressOfHp()); } ExternalAddress frmAddr() { return ExternalAddress(context_->addressOfFrm()); From 3a0310e8320fc95b95ace5e54485f9ac455bbd85 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Tue, 24 Feb 2015 21:19:29 -0800 Subject: [PATCH 11/14] Remove sp_context_t::basecx. --- sourcepawn/jit/jit_shared.h | 1 - sourcepawn/jit/plugin-context.cpp | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/sourcepawn/jit/jit_shared.h b/sourcepawn/jit/jit_shared.h index 2aec77b0..945fc77d 100644 --- a/sourcepawn/jit/jit_shared.h +++ b/sourcepawn/jit/jit_shared.h @@ -74,7 +74,6 @@ typedef struct sp_context_s { cell_t rval; /**< Return value from InvokeFunction() */ sp_plugin_t *plugin; - PluginContext *basecx; } sp_context_t; //#define SPFLAG_PLUGIN_DEBUG (1<<0) diff --git a/sourcepawn/jit/plugin-context.cpp b/sourcepawn/jit/plugin-context.cpp index 1c173e15..704a1e43 100644 --- a/sourcepawn/jit/plugin-context.cpp +++ b/sourcepawn/jit/plugin-context.cpp @@ -61,7 +61,6 @@ PluginContext::PluginContext(PluginRuntime *pRuntime) tracker_.pBase = (ucell_t *)malloc(1024); tracker_.pCur = tracker_.pBase; tracker_.size = 1024 / sizeof(cell_t); - m_ctx.basecx = this; m_ctx.plugin = const_cast(pRuntime->plugin()); } @@ -867,7 +866,7 @@ PluginContext::invokeNative(ucell_t native_idx, cell_t *params) return 0; } - cell_t result = native->pfn(m_ctx.basecx, params); + cell_t result = native->pfn(this, params); if (native_error_ != SP_ERROR_NONE) return result; From 11ea385169bb631e967f5a1aeb365d7d49ad6c8c Mon Sep 17 00:00:00 2001 From: David Anderson Date: Tue, 24 Feb 2015 21:34:30 -0800 Subject: [PATCH 12/14] Remove sp_context_t::rval. --- sourcepawn/jit/jit_shared.h | 1 - sourcepawn/jit/x86/jit_x86.cpp | 2 -- 2 files changed, 3 deletions(-) diff --git a/sourcepawn/jit/jit_shared.h b/sourcepawn/jit/jit_shared.h index 945fc77d..e197d9a6 100644 --- a/sourcepawn/jit/jit_shared.h +++ b/sourcepawn/jit/jit_shared.h @@ -72,7 +72,6 @@ class PluginContext; typedef struct sp_context_s { - cell_t rval; /**< Return value from InvokeFunction() */ sp_plugin_t *plugin; } sp_context_t; diff --git a/sourcepawn/jit/x86/jit_x86.cpp b/sourcepawn/jit/x86/jit_x86.cpp index b06a8548..b66643f3 100644 --- a/sourcepawn/jit/x86/jit_x86.cpp +++ b/sourcepawn/jit/x86/jit_x86.cpp @@ -1206,8 +1206,6 @@ Compiler::emitOp(OPCODE op) case OP_HALT: __ align(16); - __ movl(tmp, intptr_t(rt_->GetBaseContext()->GetCtx())); - __ movl(Operand(tmp, offsetof(sp_context_t, rval)), pri); __ movl(pri, readCell()); __ jmp(&extern_error_); break; From c09c65e4c70ea1a8a20adbc7d0b11e04087cbd95 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Tue, 24 Feb 2015 21:35:22 -0800 Subject: [PATCH 13/14] Remove sp_context_t::plugin. --- sourcepawn/jit/jit_shared.h | 1 - sourcepawn/jit/plugin-context.cpp | 1 - 2 files changed, 2 deletions(-) diff --git a/sourcepawn/jit/jit_shared.h b/sourcepawn/jit/jit_shared.h index e197d9a6..6e918f39 100644 --- a/sourcepawn/jit/jit_shared.h +++ b/sourcepawn/jit/jit_shared.h @@ -72,7 +72,6 @@ class PluginContext; typedef struct sp_context_s { - sp_plugin_t *plugin; } sp_context_t; //#define SPFLAG_PLUGIN_DEBUG (1<<0) diff --git a/sourcepawn/jit/plugin-context.cpp b/sourcepawn/jit/plugin-context.cpp index 704a1e43..0754f40c 100644 --- a/sourcepawn/jit/plugin-context.cpp +++ b/sourcepawn/jit/plugin-context.cpp @@ -61,7 +61,6 @@ PluginContext::PluginContext(PluginRuntime *pRuntime) tracker_.pBase = (ucell_t *)malloc(1024); tracker_.pCur = tracker_.pBase; tracker_.size = 1024 / sizeof(cell_t); - m_ctx.plugin = const_cast(pRuntime->plugin()); } PluginContext::~PluginContext() From 33588b65ce5fd11ede8dd88af45e825c74f1a23e Mon Sep 17 00:00:00 2001 From: David Anderson Date: Tue, 24 Feb 2015 21:41:35 -0800 Subject: [PATCH 14/14] Remove sp_context_t. --- sourcepawn/jit/debug-trace.cpp | 1 - sourcepawn/jit/debug-trace.h | 1 - sourcepawn/jit/interpreter.cpp | 25 ++++++++++++------------- sourcepawn/jit/jit_shared.h | 4 ---- sourcepawn/jit/plugin-context.cpp | 6 ------ sourcepawn/jit/plugin-context.h | 2 -- 6 files changed, 12 insertions(+), 27 deletions(-) diff --git a/sourcepawn/jit/debug-trace.cpp b/sourcepawn/jit/debug-trace.cpp index df857d8f..32e3fc81 100644 --- a/sourcepawn/jit/debug-trace.cpp +++ b/sourcepawn/jit/debug-trace.cpp @@ -26,7 +26,6 @@ CContextTrace::CContextTrace(PluginRuntime *pRuntime, int err, const char *errst m_StartRp(start_rp), m_Level(0) { - m_ctx = pRuntime->m_pCtx->GetCtx(); m_pDebug = m_pRuntime->GetDebugInfo(); } diff --git a/sourcepawn/jit/debug-trace.h b/sourcepawn/jit/debug-trace.h index acecae2c..a59fa11e 100644 --- a/sourcepawn/jit/debug-trace.h +++ b/sourcepawn/jit/debug-trace.h @@ -39,7 +39,6 @@ class CContextTrace : public IContextTrace private: PluginRuntime *m_pRuntime; PluginContext *context_; - sp_context_t *m_ctx; int m_Error; const char *m_pMsg; cell_t m_StartRp; diff --git a/sourcepawn/jit/interpreter.cpp b/sourcepawn/jit/interpreter.cpp index 096049c6..90404866 100644 --- a/sourcepawn/jit/interpreter.cpp +++ b/sourcepawn/jit/interpreter.cpp @@ -45,7 +45,7 @@ Write(const sp_plugin_t *plugin, cell_t offset, cell_t value) } static inline cell_t * -Jump(const sp_plugin_t *plugin, sp_context_t *ctx, cell_t target) +Jump(const sp_plugin_t *plugin, cell_t target) { if (!IsValidOffset(target) || uint32_t(target) >= plugin->pcode_size) return NULL; @@ -53,7 +53,7 @@ Jump(const sp_plugin_t *plugin, sp_context_t *ctx, cell_t target) } static inline cell_t * -JumpTarget(const sp_plugin_t *plugin, sp_context_t *ctx, cell_t *cip, bool cond, int *errp) +JumpTarget(const sp_plugin_t *plugin, cell_t *cip, bool cond, int *errp) { if (!cond) return cip + 1; @@ -84,7 +84,6 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) return SP_ERROR_INVALID_INSTRUCTION; PluginContext *cx = rt->GetBaseContext(); - sp_context_t *ctx = cx->GetCtx(); int err = SP_ERROR_NONE; @@ -675,41 +674,41 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) } case OP_JUMP: - if ((cip = JumpTarget(plugin, ctx, cip, true, &err)) == NULL) + if ((cip = JumpTarget(plugin, cip, true, &err)) == NULL) goto error; break; case OP_JZER: - if ((cip = JumpTarget(plugin, ctx, cip, pri == 0, &err)) == NULL) + if ((cip = JumpTarget(plugin, cip, pri == 0, &err)) == NULL) goto error; break; case OP_JNZ: - if ((cip = JumpTarget(plugin, ctx, cip, pri != 0, &err)) == NULL) + if ((cip = JumpTarget(plugin, cip, pri != 0, &err)) == NULL) goto error; break; case OP_JEQ: - if ((cip = JumpTarget(plugin, ctx, cip, pri == alt, &err)) == NULL) + if ((cip = JumpTarget(plugin, cip, pri == alt, &err)) == NULL) goto error; break; case OP_JNEQ: - if ((cip = JumpTarget(plugin, ctx, cip, pri != alt, &err)) == NULL) + if ((cip = JumpTarget(plugin, cip, pri != alt, &err)) == NULL) goto error; break; case OP_JSLESS: - if ((cip = JumpTarget(plugin, ctx, cip, pri < alt, &err)) == NULL) + if ((cip = JumpTarget(plugin, cip, pri < alt, &err)) == NULL) goto error; break; case OP_JSLEQ: - if ((cip = JumpTarget(plugin, ctx, cip, pri <= alt, &err)) == NULL) + if ((cip = JumpTarget(plugin, cip, pri <= alt, &err)) == NULL) goto error; break; case OP_JSGRTR: - if ((cip = JumpTarget(plugin, ctx, cip, pri > alt, &err)) == NULL) + if ((cip = JumpTarget(plugin, cip, pri > alt, &err)) == NULL) goto error; break; case OP_JSGEQ: - if ((cip = JumpTarget(plugin, ctx, cip, pri >= alt, &err)) == NULL) + if ((cip = JumpTarget(plugin, cip, pri >= alt, &err)) == NULL) goto error; break; @@ -831,7 +830,7 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) } } - if ((cip = Jump(plugin, ctx, target)) == NULL) { + if ((cip = Jump(plugin, target)) == NULL) { err = SP_ERROR_INVALID_INSTRUCTION; goto error; } diff --git a/sourcepawn/jit/jit_shared.h b/sourcepawn/jit/jit_shared.h index 6e918f39..ef1c7ec1 100644 --- a/sourcepawn/jit/jit_shared.h +++ b/sourcepawn/jit/jit_shared.h @@ -70,10 +70,6 @@ namespace SourcePawn class PluginContext; -typedef struct sp_context_s -{ -} sp_context_t; - //#define SPFLAG_PLUGIN_DEBUG (1<<0) #define SPFLAG_PLUGIN_PAUSED (1<<1) diff --git a/sourcepawn/jit/plugin-context.cpp b/sourcepawn/jit/plugin-context.cpp index 0754f40c..22dd7ef1 100644 --- a/sourcepawn/jit/plugin-context.cpp +++ b/sourcepawn/jit/plugin-context.cpp @@ -80,12 +80,6 @@ PluginContext::GetContext() return reinterpret_cast((IPluginContext * )this); } -sp_context_t * -PluginContext::GetCtx() -{ - return &m_ctx; -} - bool PluginContext::IsDebugging() { diff --git a/sourcepawn/jit/plugin-context.h b/sourcepawn/jit/plugin-context.h index 65a0a243..278a776a 100644 --- a/sourcepawn/jit/plugin-context.h +++ b/sourcepawn/jit/plugin-context.h @@ -39,7 +39,6 @@ class PluginContext : public IPluginContext public: //IPluginContext IVirtualMachine *GetVirtualMachine(); sp_context_t *GetContext(); - sp_context_t *GetCtx(); bool IsDebugging(); int SetDebugBreak(void *newpfn, void *oldpfn); IPluginDebugInfo *GetDebugInfo(); @@ -187,7 +186,6 @@ class PluginContext : public IPluginContext bool m_CustomMsg; bool m_InExec; PluginRuntime *m_pRuntime; - sp_context_t m_ctx; void *m_keys[4]; bool m_keys_set[4];