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);