Merge pull request #280 from alliedmodders/rm-ctx

Remove sp_context_t.
This commit is contained in:
David Anderson 2015-02-26 15:46:32 -08:00
commit 9a37b94f4d
14 changed files with 631 additions and 521 deletions

View File

@ -18,7 +18,10 @@ def setup(binary):
compiler = binary.compiler compiler = binary.compiler
compiler.includes += Includes compiler.includes += Includes
if compiler.vendor == 'gcc' or compiler.vendor == 'clang': if compiler.vendor == 'gcc' or compiler.vendor == 'clang':
compiler.cxxflags += ['-fno-rtti'] compiler.cxxflags += [
'-fno-rtti',
'-Wno-invalid-offsetof',
]
elif binary.compiler.vendor == 'msvc': elif binary.compiler.vendor == 'msvc':
compiler.cxxflags += ['/GR-'] compiler.cxxflags += ['/GR-']

View File

@ -16,13 +16,13 @@
#include <stdint.h> #include <stdint.h>
#include <sp_vm_api.h> #include <sp_vm_api.h>
typedef struct sp_context_s sp_context_t; class PluginContext;
namespace sp { namespace sp {
class Environment; 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 class CodeStubs
{ {

View File

@ -20,12 +20,12 @@ using namespace SourcePawn;
CContextTrace::CContextTrace(PluginRuntime *pRuntime, int err, const char *errstr, cell_t start_rp) CContextTrace::CContextTrace(PluginRuntime *pRuntime, int err, const char *errstr, cell_t start_rp)
: m_pRuntime(pRuntime), : m_pRuntime(pRuntime),
context_(pRuntime->GetBaseContext()),
m_Error(err), m_Error(err),
m_pMsg(errstr), m_pMsg(errstr),
m_StartRp(start_rp), m_StartRp(start_rp),
m_Level(0) m_Level(0)
{ {
m_ctx = pRuntime->m_pCtx->GetCtx();
m_pDebug = m_pRuntime->GetDebugInfo(); m_pDebug = m_pRuntime->GetDebugInfo();
} }
@ -65,21 +65,19 @@ CContextTrace::GetTraceInfo(CallStackInfo *trace)
cell_t cip; cell_t cip;
if (m_Level == 0) { if (m_Level == 0) {
cip = m_ctx->cip; cip = context_->cip();
} else if (m_ctx->rp > 0) { } else if (context_->rp() > 0) {
/* Entries go from ctx.rp - 1 to m_StartRp */ /* Entries go from ctx.rp - 1 to m_StartRp */
cell_t offs, start, end; cell_t offs, start, end;
offs = m_Level - 1; offs = m_Level - 1;
start = m_ctx->rp - 1; start = context_->rp() - 1;
end = m_StartRp; end = m_StartRp;
if (start - offs < end) if (start - offs < end)
{
return false; return false;
}
cip = m_ctx->rstk_cips[start - offs]; cip = context_->getReturnStackCip(start - offs);
} else { } else {
return false; return false;
} }
@ -106,15 +104,19 @@ CContextTrace::GetTraceInfo(CallStackInfo *trace)
const char * const char *
CContextTrace::GetLastNative(uint32_t *index) 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();
if (lastNative < 0)
return NULL; return NULL;
sp_native_t *native; 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; return NULL;
if (index) if (index)
*index = m_ctx->n_idx; *index = lastNative;
return native->name; return native->name;
} }

View File

@ -16,6 +16,7 @@
#include <sp_vm_api.h> #include <sp_vm_api.h>
class PluginRuntime; class PluginRuntime;
class PluginContext;
namespace sp { namespace sp {
@ -37,7 +38,7 @@ class CContextTrace : public IContextTrace
private: private:
PluginRuntime *m_pRuntime; PluginRuntime *m_pRuntime;
sp_context_t *m_ctx; PluginContext *context_;
int m_Error; int m_Error;
const char *m_pMsg; const char *m_pMsg;
cell_t m_StartRp; cell_t m_StartRp;

View File

@ -238,17 +238,16 @@ Environment::UnpatchAllJumpsFromTimeout()
int int
Environment::Invoke(PluginRuntime *runtime, CompiledFunction *fn, cell_t *result) Environment::Invoke(PluginRuntime *runtime, CompiledFunction *fn, cell_t *result)
{ {
sp_context_t *ctx = runtime->GetBaseContext()->GetCtx(); PluginContext *cx = runtime->GetBaseContext();
// Note that cip, hp, sp are saved and restored by Execute2(). // Note that cip, hp, sp are saved and restored by Execute2().
ctx->cip = fn->GetCodeOffset(); *cx->addressOfCip() = fn->GetCodeOffset();
InvokeStubFn invoke = code_stubs_->InvokeStub(); InvokeStubFn invoke = code_stubs_->InvokeStub();
EnterInvoke(); EnterInvoke();
int err = invoke(ctx, runtime->plugin()->memory, fn->GetEntryAddress()); int err = invoke(cx, fn->GetEntryAddress(), result);
LeaveInvoke(); LeaveInvoke();
*result = ctx->rval;
return err; return err;
} }

View File

@ -45,187 +45,34 @@ Write(const sp_plugin_t *plugin, cell_t offset, cell_t value)
} }
static inline cell_t * 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) { if (!IsValidOffset(target) || uint32_t(target) >= plugin->pcode_size)
ctx->err = SP_ERROR_INVALID_INSTRUCTION;
return NULL; return NULL;
}
return reinterpret_cast<cell_t *>(plugin->pcode + target); return reinterpret_cast<cell_t *>(plugin->pcode + target);
} }
static inline cell_t * 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, cell_t *cip, bool cond, int *errp)
{ {
if (!cond) if (!cond)
return cip + 1; return cip + 1;
cell_t target = *cip; cell_t target = *cip;
if (!IsValidOffset(target) || uint32_t(target) >= plugin->pcode_size) { if (!IsValidOffset(target) || uint32_t(target) >= plugin->pcode_size) {
ctx->err = SP_ERROR_INVALID_INSTRUCTION; *errp = SP_ERROR_INVALID_INSTRUCTION;
return NULL; return NULL;
} }
cell_t *next = reinterpret_cast<cell_t *>(plugin->pcode + target); cell_t *next = reinterpret_cast<cell_t *>(plugin->pcode + target);
if (next < cip && !Environment::get()->watchdog()->HandleInterrupt()) { if (next < cip && !Environment::get()->watchdog()->HandleInterrupt()) {
ctx->err = SP_ERROR_TIMEOUT; *errp = SP_ERROR_TIMEOUT;
return NULL; return NULL;
} }
return next; 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) {
ctx->err = SP_ERROR_MEMACCESS;
return false;
}
if (addr < ctx->hp)
return true;
if (reinterpret_cast<cell_t *>(plugin->memory + addr) < stk) {
ctx->err = SP_ERROR_MEMACCESS;
return false;
}
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)
{
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)
{
if (dims == 1) {
uint32_t size = *stk;
if (size == 0 || !ke::IsUint32MultiplySafe(size, 4)) {
ctx->err = SP_ERROR_ARRAY_TOO_BIG;
return false;
}
*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 ((ctx->err = PushTracker(ctx, bytes)) != SP_ERROR_NONE)
return false;
if (autozero)
memset(ctx->plugin->memory + ctx->hp, 0, bytes);
return true;
}
if ((ctx->err = GenerateFullArray(rt, dims, stk, autozero)) != SP_ERROR_NONE)
return false;
return true;
}
int int
Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval) Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval)
{ {
@ -236,21 +83,25 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval)
if (!IsValidOffset(aCodeStart) || aCodeStart > plugin->pcode_size) if (!IsValidOffset(aCodeStart) || aCodeStart > plugin->pcode_size)
return SP_ERROR_INVALID_INSTRUCTION; return SP_ERROR_INVALID_INSTRUCTION;
sp_context_t *ctx = rt->GetBaseContext()->GetCtx(); PluginContext *cx = rt->GetBaseContext();
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 // Save the original frm. BaseContext won't, and if we error, we won't hit
// the stack unwinding code. // the stack unwinding code.
cell_t orig_frm = ctx->frm; cell_t orig_frm = cx->frm();
cell_t &frm = *cx->addressOfFrm();
cell_t &sp = *cx->addressOfSp();
cell_t pri = 0; cell_t pri = 0;
cell_t alt = 0; cell_t alt = 0;
cell_t *cip = code + (aCodeStart / 4); cell_t *cip = code + (aCodeStart / 4);
cell_t *stk = reinterpret_cast<cell_t *>(plugin->memory + ctx->sp); cell_t *stk = reinterpret_cast<cell_t *>(plugin->memory + sp);
for (;;) { for (;;) {
if (cip >= codeend) { if (cip >= codeend) {
ctx->err = SP_ERROR_INVALID_INSTRUCTION; err = SP_ERROR_INVALID_INSTRUCTION;
goto error; goto error;
} }
@ -281,7 +132,7 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval)
break; break;
case OP_ZERO_S: case OP_ZERO_S:
Write(plugin, ctx->frm + *cip++, 0); Write(plugin, frm + *cip++, 0);
break; break;
case OP_PUSH_PRI: case OP_PUSH_PRI:
@ -321,7 +172,7 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval)
int i = 1; int i = 1;
do { do {
cell_t addr = ctx->frm + *cip++; cell_t addr = frm + *cip++;
*--stk = addr; *--stk = addr;
} while (i++ < n); } while (i++ < n);
break; break;
@ -339,7 +190,7 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval)
int i = 1; int i = 1;
do { do {
cell_t value = Read(plugin, ctx->frm + *cip++); cell_t value = Read(plugin, frm + *cip++);
*--stk = value; *--stk = value;
} while (i++ < n); } while (i++ < n);
break; break;
@ -384,9 +235,9 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval)
case OP_PROC: case OP_PROC:
{ {
*--stk = ctx->frm; *--stk = frm;
*--stk = 0; *--stk = 0;
ctx->frm = uintptr_t(stk) - uintptr_t(plugin->memory); frm = uintptr_t(stk) - uintptr_t(plugin->memory);
break; break;
} }
@ -505,14 +356,16 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval)
case OP_INC_S: case OP_INC_S:
{ {
cell_t offset = *cip++; cell_t offset = *cip++;
cell_t value = Read(plugin, ctx->frm + offset); cell_t value = Read(plugin, frm + offset);
Write(plugin, ctx->frm + offset, value + 1); Write(plugin, frm + offset, value + 1);
break; break;
} }
case OP_INC_I: case OP_INC_I:
if (!CheckAddress(plugin, ctx, stk, pri)) if (!cx->checkAddress(stk, pri)) {
err = SP_ERROR_MEMACCESS;
goto error; goto error;
}
Write(plugin, pri, Read(plugin, pri) + 1); Write(plugin, pri, Read(plugin, pri) + 1);
break; break;
@ -533,14 +386,16 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval)
case OP_DEC_S: case OP_DEC_S:
{ {
cell_t offset = *cip++; cell_t offset = *cip++;
cell_t value = Read(plugin, ctx->frm + offset); cell_t value = Read(plugin, frm + offset);
Write(plugin, ctx->frm + offset, value - 1); Write(plugin, frm + offset, value - 1);
break; break;
} }
case OP_DEC_I: case OP_DEC_I:
if (!CheckAddress(plugin, ctx, stk, pri)) if (!cx->checkAddress(stk, pri)) {
err = SP_ERROR_MEMACCESS;
goto error; goto error;
}
Write(plugin, pri, Read(plugin, pri) - 1); Write(plugin, pri, Read(plugin, pri) - 1);
break; break;
@ -552,27 +407,27 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval)
break; break;
case OP_LOAD_S_PRI: case OP_LOAD_S_PRI:
pri = Read(plugin, ctx->frm + *cip++); pri = Read(plugin, frm + *cip++);
break; break;
case OP_LOAD_S_ALT: case OP_LOAD_S_ALT:
alt = Read(plugin, ctx->frm + *cip++); alt = Read(plugin, frm + *cip++);
break; break;
case OP_LOAD_S_BOTH: case OP_LOAD_S_BOTH:
pri = Read(plugin, ctx->frm + *cip++); pri = Read(plugin, frm + *cip++);
alt = Read(plugin, ctx->frm + *cip++); alt = Read(plugin, frm + *cip++);
break; break;
case OP_LREF_S_PRI: case OP_LREF_S_PRI:
{ {
pri = Read(plugin, ctx->frm + *cip++); pri = Read(plugin, frm + *cip++);
pri = Read(plugin, pri); pri = Read(plugin, pri);
break; break;
} }
case OP_LREF_S_ALT: case OP_LREF_S_ALT:
{ {
alt = Read(plugin, ctx->frm + *cip++); alt = Read(plugin, frm + *cip++);
alt = Read(plugin, alt); alt = Read(plugin, alt);
break; break;
} }
@ -585,10 +440,10 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval)
break; break;
case OP_ADDR_PRI: case OP_ADDR_PRI:
pri = ctx->frm + *cip++; pri = frm + *cip++;
break; break;
case OP_ADDR_ALT: case OP_ADDR_ALT:
alt = ctx->frm + *cip++; alt = frm + *cip++;
break; break;
case OP_STOR_PRI: case OP_STOR_PRI:
@ -599,10 +454,10 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval)
break; break;
case OP_STOR_S_PRI: case OP_STOR_S_PRI:
Write(plugin, ctx->frm + *cip++, pri); Write(plugin, frm + *cip++, pri);
break; break;
case OP_STOR_S_ALT: case OP_STOR_S_ALT:
Write(plugin, ctx->frm +*cip++, alt); Write(plugin, frm +*cip++, alt);
break; break;
case OP_IDXADDR: case OP_IDXADDR:
@ -612,7 +467,7 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval)
case OP_SREF_S_PRI: case OP_SREF_S_PRI:
{ {
cell_t offset = *cip++; cell_t offset = *cip++;
cell_t addr = Read(plugin, ctx->frm + offset); cell_t addr = Read(plugin, frm + offset);
Write(plugin, addr, pri); Write(plugin, addr, pri);
break; break;
} }
@ -620,7 +475,7 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval)
case OP_SREF_S_ALT: case OP_SREF_S_ALT:
{ {
cell_t offset = *cip++; cell_t offset = *cip++;
cell_t addr = Read(plugin, ctx->frm + offset); cell_t addr = Read(plugin, frm + offset);
Write(plugin, addr, alt); Write(plugin, addr, alt);
break; break;
} }
@ -644,8 +499,10 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval)
case OP_LIDX: case OP_LIDX:
pri = alt + pri * 4; pri = alt + pri * 4;
if (!CheckAddress(plugin, ctx, stk, pri)) if (!cx->checkAddress(stk, pri)) {
err = SP_ERROR_MEMACCESS;
goto error; goto error;
}
pri = Read(plugin, pri); pri = Read(plugin, pri);
break; break;
@ -653,8 +510,10 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval)
{ {
cell_t val = *cip++; cell_t val = *cip++;
pri = alt + (pri << val); pri = alt + (pri << val);
if (!CheckAddress(plugin, ctx, stk, pri)) if (!cx->checkAddress(stk, pri)) {
err = SP_ERROR_MEMACCESS;
goto error; goto error;
}
pri = Read(plugin, pri); pri = Read(plugin, pri);
break; break;
} }
@ -671,19 +530,23 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval)
{ {
cell_t offset = *cip++; cell_t offset = *cip++;
cell_t value = *cip++; cell_t value = *cip++;
Write(plugin, ctx->frm + offset, value); Write(plugin, frm + offset, value);
break; break;
} }
case OP_LOAD_I: case OP_LOAD_I:
if (!CheckAddress(plugin, ctx, stk, pri)) if (!cx->checkAddress(stk, pri)) {
err = SP_ERROR_MEMACCESS;
goto error; goto error;
}
pri = Read(plugin, pri); pri = Read(plugin, pri);
break; break;
case OP_STOR_I: case OP_STOR_I:
if (!CheckAddress(plugin, ctx, stk, alt)) if (!cx->checkAddress(stk, alt)) {
err = SP_ERROR_MEMACCESS;
goto error; goto error;
}
Write(plugin, alt, pri); Write(plugin, alt, pri);
break; break;
@ -693,11 +556,11 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval)
cell_t dividend = (op == OP_SDIV) ? pri : alt; cell_t dividend = (op == OP_SDIV) ? pri : alt;
cell_t divisor = (op == OP_SDIV) ? alt : pri; cell_t divisor = (op == OP_SDIV) ? alt : pri;
if (divisor == 0) { if (divisor == 0) {
ctx->err = SP_ERROR_DIVIDE_BY_ZERO; err = SP_ERROR_DIVIDE_BY_ZERO;
goto error; goto error;
} }
if (dividend == INT_MIN && divisor == -1) { if (dividend == INT_MIN && divisor == -1) {
ctx->err = SP_ERROR_INTEGER_OVERFLOW; err = SP_ERROR_INTEGER_OVERFLOW;
goto error; goto error;
} }
pri = dividend / divisor; pri = dividend / divisor;
@ -708,8 +571,10 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval)
case OP_LODB_I: case OP_LODB_I:
{ {
cell_t val = *cip++; cell_t val = *cip++;
if (!CheckAddress(plugin, ctx, stk, pri)) if (!cx->checkAddress(stk, pri)) {
err = SP_ERROR_MEMACCESS;
goto error; goto error;
}
pri = Read(plugin, pri); pri = Read(plugin, pri);
if (val == 1) if (val == 1)
pri &= 0xff; pri &= 0xff;
@ -721,8 +586,10 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval)
case OP_STRB_I: case OP_STRB_I:
{ {
cell_t val = *cip++; cell_t val = *cip++;
if (!CheckAddress(plugin, ctx, stk, alt)) if (!cx->checkAddress(stk, alt)) {
err = SP_ERROR_MEMACCESS;
goto error; goto error;
}
if (val == 1) if (val == 1)
*reinterpret_cast<int8_t *>(plugin->memory + alt) = pri; *reinterpret_cast<int8_t *>(plugin->memory + alt) = pri;
else if (val == 2) else if (val == 2)
@ -735,10 +602,10 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval)
case OP_RETN: case OP_RETN:
{ {
stk++; stk++;
ctx->frm = *stk++; frm = *stk++;
stk += *stk + 1; stk += *stk + 1;
*rval = pri; *rval = pri;
ctx->err = SP_ERROR_NONE; err = SP_ERROR_NONE;
goto done; goto done;
} }
@ -766,19 +633,19 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval)
{ {
cell_t amount = *cip++; cell_t amount = *cip++;
if (!IsValidOffset(amount)) { if (!IsValidOffset(amount)) {
ctx->err = SP_ERROR_INVALID_INSTRUCTION; err = SP_ERROR_INVALID_INSTRUCTION;
goto error; goto error;
} }
stk += amount / 4; stk += amount / 4;
if (amount > 0) { if (amount > 0) {
if (uintptr_t(stk) >= uintptr_t(plugin->memory + plugin->mem_size)) { if (uintptr_t(stk) >= uintptr_t(plugin->memory + plugin->mem_size)) {
ctx->err = SP_ERROR_STACKMIN; err = SP_ERROR_STACKMIN;
goto error; goto error;
} }
} else { } 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)) {
ctx->err = SP_ERROR_STACKLOW; err = SP_ERROR_STACKLOW;
goto error; goto error;
} }
} }
@ -789,17 +656,17 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval)
{ {
cell_t amount = *cip++; cell_t amount = *cip++;
alt = ctx->hp; alt = cx->hp();
ctx->hp += amount; *cx->addressOfHp() += amount;
if (amount > 0) { if (amount > 0) {
if (uintptr_t(plugin->memory + ctx->hp) > uintptr_t(stk)) { if (uintptr_t(plugin->memory + cx->hp()) > uintptr_t(stk)) {
ctx->err = SP_ERROR_HEAPLOW; err = SP_ERROR_HEAPLOW;
goto error; goto error;
} }
} else { } else {
if (uint32_t(ctx->hp) < plugin->data_size) { if (uint32_t(cx->hp()) < plugin->data_size) {
ctx->err = SP_ERROR_HEAPMIN; err = SP_ERROR_HEAPMIN;
goto error; goto error;
} }
} }
@ -807,50 +674,50 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval)
} }
case OP_JUMP: case OP_JUMP:
if ((cip = JumpTarget(plugin, ctx, cip, true)) == NULL) if ((cip = JumpTarget(plugin, cip, true, &err)) == NULL)
goto error; goto error;
break; break;
case OP_JZER: case OP_JZER:
if ((cip = JumpTarget(plugin, ctx, cip, pri == 0)) == NULL) if ((cip = JumpTarget(plugin, cip, pri == 0, &err)) == NULL)
goto error; goto error;
break; break;
case OP_JNZ: case OP_JNZ:
if ((cip = JumpTarget(plugin, ctx, cip, pri != 0)) == NULL) if ((cip = JumpTarget(plugin, cip, pri != 0, &err)) == NULL)
goto error; goto error;
break; break;
case OP_JEQ: case OP_JEQ:
if ((cip = JumpTarget(plugin, ctx, cip, pri == alt)) == NULL) if ((cip = JumpTarget(plugin, cip, pri == alt, &err)) == NULL)
goto error; goto error;
break; break;
case OP_JNEQ: case OP_JNEQ:
if ((cip = JumpTarget(plugin, ctx, cip, pri != alt)) == NULL) if ((cip = JumpTarget(plugin, cip, pri != alt, &err)) == NULL)
goto error; goto error;
break; break;
case OP_JSLESS: case OP_JSLESS:
if ((cip = JumpTarget(plugin, ctx, cip, pri < alt)) == NULL) if ((cip = JumpTarget(plugin, cip, pri < alt, &err)) == NULL)
goto error; goto error;
break; break;
case OP_JSLEQ: case OP_JSLEQ:
if ((cip = JumpTarget(plugin, ctx, cip, pri <= alt)) == NULL) if ((cip = JumpTarget(plugin, cip, pri <= alt, &err)) == NULL)
goto error; goto error;
break; break;
case OP_JSGRTR: case OP_JSGRTR:
if ((cip = JumpTarget(plugin, ctx, cip, pri > alt)) == NULL) if ((cip = JumpTarget(plugin, cip, pri > alt, &err)) == NULL)
goto error; goto error;
break; break;
case OP_JSGEQ: case OP_JSGEQ:
if ((cip = JumpTarget(plugin, ctx, cip, pri >= alt)) == NULL) if ((cip = JumpTarget(plugin, cip, pri >= alt, &err)) == NULL)
goto error; goto error;
break; break;
case OP_TRACKER_PUSH_C: case OP_TRACKER_PUSH_C:
{ {
cell_t amount = *cip++; cell_t amount = *cip++;
int error = PushTracker(ctx, amount * 4); int error = cx->pushTracker(amount * 4);
if (error != SP_ERROR_NONE) { if (error != SP_ERROR_NONE) {
ctx->err = error; err = error;
goto error; goto error;
} }
break; break;
@ -858,23 +725,23 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval)
case OP_TRACKER_POP_SETHEAP: case OP_TRACKER_POP_SETHEAP:
{ {
int error = PopTrackerAndSetHeap(rt); int error = cx->popTrackerAndSetHeap();
if (error != SP_ERROR_NONE) { if (error != SP_ERROR_NONE) {
ctx->err = error; err = error;
goto error; goto error;
} }
break; break;
} }
case OP_BREAK: case OP_BREAK:
ctx->cip = uintptr_t(cip - 1) - uintptr_t(plugin->pcode); *cx->addressOfCip() = uintptr_t(cip - 1) - uintptr_t(plugin->pcode);
break; break;
case OP_BOUNDS: case OP_BOUNDS:
{ {
cell_t value = *cip++; cell_t value = *cip++;
if (uint32_t(pri) > uint32_t(value)) { if (uint32_t(pri) > uint32_t(value)) {
ctx->err = SP_ERROR_ARRAY_BOUNDS; err = SP_ERROR_ARRAY_BOUNDS;
goto error; goto error;
} }
break; break;
@ -885,26 +752,24 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval)
cell_t offset = *cip++; cell_t offset = *cip++;
if (!IsValidOffset(offset) || uint32_t(offset) >= plugin->pcode_size) { if (!IsValidOffset(offset) || uint32_t(offset) >= plugin->pcode_size) {
ctx->err = SP_ERROR_INSTRUCTION_PARAM; err = SP_ERROR_INSTRUCTION_PARAM;
goto error;
}
if (ctx->rp >= SP_MAX_RETURN_STACK) {
ctx->err = SP_ERROR_STACKLOW;
goto error; goto error;
} }
// For debugging. // For debugging.
uintptr_t rcip = uintptr_t(cip - 2) - uintptr_t(plugin->pcode); uintptr_t rcip = uintptr_t(cip - 2) - uintptr_t(plugin->pcode);
ctx->rstk_cips[ctx->rp++] = rcip; if (!cx->pushReturnCip(rcip)) {
ctx->cip = offset; err = SP_ERROR_STACKLOW;
ctx->sp = uintptr_t(stk) - uintptr_t(plugin->memory); goto error;
}
*cx->addressOfCip() = offset;
sp = uintptr_t(stk) - uintptr_t(plugin->memory);
int err = Interpret(rt, offset, &pri); int err = Interpret(rt, offset, &pri);
stk = reinterpret_cast<cell_t *>(plugin->memory + ctx->sp); stk = reinterpret_cast<cell_t *>(plugin->memory + sp);
ctx->cip = rcip; *cx->addressOfCip() = rcip;
ctx->rp--; cx->popReturnCip();
if (err != SP_ERROR_NONE) if (err != SP_ERROR_NONE)
goto error; goto error;
@ -915,7 +780,7 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval)
case OP_GENARRAY_Z: case OP_GENARRAY_Z:
{ {
cell_t val = *cip++; cell_t val = *cip++;
if (!GenerateArray(rt, ctx, val, stk, op == OP_GENARRAY_Z)) if ((err = cx->generateArray(val, stk, op == OP_GENARRAY_Z)) != SP_ERROR_NONE)
goto error; goto error;
stk += (val - 1) * 4; stk += (val - 1) * 4;
@ -928,7 +793,7 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval)
uint32_t native_index = *cip++; uint32_t native_index = *cip++;
if (native_index >= plugin->num_natives) { if (native_index >= plugin->num_natives) {
ctx->err = SP_ERROR_INSTRUCTION_PARAM; err = SP_ERROR_INSTRUCTION_PARAM;
goto error; goto error;
} }
@ -938,10 +803,10 @@ Interpret(PluginRuntime *rt, uint32_t aCodeStart, cell_t *rval)
*--stk = num_params; *--stk = num_params;
} }
ctx->sp = uintptr_t(stk) - uintptr_t(plugin->memory); 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) { if (cx->GetLastNativeError() != SP_ERROR_NONE) {
ctx->err = ctx->n_err; err = cx->GetLastNativeError();
goto error; goto error;
} }
@ -965,26 +830,28 @@ 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; goto error;
}
break; break;
} }
default: default:
{ {
ctx->err = SP_ERROR_INVALID_INSTRUCTION; err = SP_ERROR_INVALID_INSTRUCTION;
goto error; goto error;
} }
} // switch } // switch
} }
done: done:
assert(orig_frm == ctx->frm); assert(orig_frm == frm);
ctx->sp = uintptr_t(stk) - uintptr_t(plugin->memory); sp = uintptr_t(stk) - uintptr_t(plugin->memory);
return ctx->err; return err;
error: error:
ctx->frm = orig_frm; frm = orig_frm;
goto done; goto done;
} }

View File

@ -22,19 +22,6 @@
#include "plugin-runtime.h" #include "plugin-runtime.h"
#include "plugin-context.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 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_ #endif // _include_sourcepawn_interpreter_h_

View File

@ -68,27 +68,8 @@ namespace SourcePawn
} sp_plugin_t; } sp_plugin_t;
} }
struct tracker_t;
class PluginContext; class PluginContext;
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() */
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 */
tracker_t *tracker;
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) //#define SPFLAG_PLUGIN_DEBUG (1<<0)
#define SPFLAG_PLUGIN_PAUSED (1<<1) #define SPFLAG_PLUGIN_PAUSED (1<<1)

View File

@ -51,25 +51,21 @@ PluginContext::PluginContext(PluginRuntime *pRuntime)
m_pNullString = NULL; m_pNullString = NULL;
} }
m_ctx.hp = m_pRuntime->plugin()->data_size; hp_ = m_pRuntime->plugin()->data_size;
m_ctx.sp = m_pRuntime->plugin()->mem_size - sizeof(cell_t); sp_ = m_pRuntime->plugin()->mem_size - sizeof(cell_t);
m_ctx.frm = m_ctx.sp; frm_ = sp_;
m_ctx.n_err = SP_ERROR_NONE; rp_ = 0;
m_ctx.n_idx = SP_ERROR_NONE; last_native_ = -1;
m_ctx.rp = 0; native_error_ = SP_ERROR_NONE;
m_ctx.tracker = new tracker_t; tracker_.pBase = (ucell_t *)malloc(1024);
m_ctx.tracker->pBase = (ucell_t *)malloc(1024); tracker_.pCur = tracker_.pBase;
m_ctx.tracker->pCur = m_ctx.tracker->pBase; tracker_.size = 1024 / sizeof(cell_t);
m_ctx.tracker->size = 1024 / sizeof(cell_t);
m_ctx.basecx = this;
m_ctx.plugin = const_cast<sp_plugin_t *>(pRuntime->plugin());
} }
PluginContext::~PluginContext() PluginContext::~PluginContext()
{ {
free(m_ctx.tracker->pBase); free(tracker_.pBase);
delete m_ctx.tracker;
} }
IVirtualMachine * IVirtualMachine *
@ -84,12 +80,6 @@ PluginContext::GetContext()
return reinterpret_cast<sp_context_t *>((IPluginContext * )this); return reinterpret_cast<sp_context_t *>((IPluginContext * )this);
} }
sp_context_t *
PluginContext::GetCtx()
{
return &m_ctx;
}
bool bool
PluginContext::IsDebugging() PluginContext::IsDebugging()
{ {
@ -137,7 +127,7 @@ PluginContext::ThrowNativeErrorEx(int error, const char *msg, ...)
if (!m_InExec) if (!m_InExec)
return 0; return 0;
m_ctx.n_err = error; native_error_ = error;
if (msg) { if (msg) {
va_list ap; va_list ap;
@ -155,7 +145,7 @@ PluginContext::ThrowNativeError(const char *msg, ...)
if (!m_InExec) if (!m_InExec)
return 0; return 0;
m_ctx.n_err = SP_ERROR_NATIVE; native_error_ = SP_ERROR_NATIVE;
if (msg) { if (msg) {
va_list ap; va_list ap;
@ -187,21 +177,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. * 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_ - hp_ - realmem) < STACKMARGIN)
return SP_ERROR_HEAPLOW; 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 */ /* store size of allocation in cells */
*addr = (cell_t)cells; *addr = (cell_t)cells;
addr++; addr++;
m_ctx.hp += sizeof(cell_t); hp_ += sizeof(cell_t);
*local_addr = m_ctx.hp; *local_addr = hp_;
if (phys_addr) if (phys_addr)
*phys_addr = addr; *phys_addr = addr;
m_ctx.hp += realmem; hp_ += realmem;
return SP_ERROR_NONE; return SP_ERROR_NONE;
} }
@ -214,16 +204,16 @@ PluginContext::HeapPop(cell_t local_addr)
/* check the bounds of this address */ /* check the bounds of this address */
local_addr -= sizeof(cell_t); 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; return SP_ERROR_INVALID_ADDRESS;
addr = (cell_t *)(m_pRuntime->plugin()->memory + local_addr); addr = (cell_t *)(m_pRuntime->plugin()->memory + local_addr);
cellcount = (*addr) * sizeof(cell_t); cellcount = (*addr) * sizeof(cell_t);
/* check if this memory count looks valid */ /* 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; return SP_ERROR_INVALID_ADDRESS;
m_ctx.hp = local_addr; hp_ = local_addr;
return SP_ERROR_NONE; return SP_ERROR_NONE;
} }
@ -235,7 +225,7 @@ PluginContext::HeapRelease(cell_t local_addr)
if (local_addr < (cell_t)m_pRuntime->plugin()->data_size) if (local_addr < (cell_t)m_pRuntime->plugin()->data_size)
return SP_ERROR_INVALID_ADDRESS; return SP_ERROR_INVALID_ADDRESS;
m_ctx.hp = local_addr - sizeof(cell_t); hp_ = local_addr - sizeof(cell_t);
return SP_ERROR_NONE; return SP_ERROR_NONE;
} }
@ -327,7 +317,7 @@ PluginContext::BindNativeToAny(SPVM_NATIVE_FUNC native)
int int
PluginContext::LocalToPhysAddr(cell_t local_addr, cell_t **phys_addr) PluginContext::LocalToPhysAddr(cell_t local_addr, cell_t **phys_addr)
{ {
if (((local_addr >= m_ctx.hp) && (local_addr < m_ctx.sp)) || if (((local_addr >= hp_) && (local_addr < sp_)) ||
(local_addr < 0) || ((ucell_t)local_addr >= m_pRuntime->plugin()->mem_size)) (local_addr < 0) || ((ucell_t)local_addr >= m_pRuntime->plugin()->mem_size))
{ {
return SP_ERROR_INVALID_ADDRESS; return SP_ERROR_INVALID_ADDRESS;
@ -360,7 +350,7 @@ PluginContext::PushCellArray(cell_t *local_addr, cell_t **phys_addr, cell_t arra
int int
PluginContext::LocalToString(cell_t local_addr, char **addr) PluginContext::LocalToString(cell_t local_addr, char **addr)
{ {
if (((local_addr >= m_ctx.hp) && (local_addr < m_ctx.sp)) || if (((local_addr >= hp_) && (local_addr < sp_)) ||
(local_addr < 0) || ((ucell_t)local_addr >= m_pRuntime->plugin()->mem_size)) (local_addr < 0) || ((ucell_t)local_addr >= m_pRuntime->plugin()->mem_size))
{ {
return SP_ERROR_INVALID_ADDRESS; return SP_ERROR_INVALID_ADDRESS;
@ -382,7 +372,7 @@ PluginContext::StringToLocal(cell_t local_addr, size_t bytes, const char *source
char *dest; char *dest;
size_t len; size_t len;
if (((local_addr >= m_ctx.hp) && (local_addr < m_ctx.sp)) || if (((local_addr >= hp_) && (local_addr < sp_)) ||
(local_addr < 0) || ((ucell_t)local_addr >= m_pRuntime->plugin()->mem_size)) (local_addr < 0) || ((ucell_t)local_addr >= m_pRuntime->plugin()->mem_size))
{ {
return SP_ERROR_INVALID_ADDRESS; return SP_ERROR_INVALID_ADDRESS;
@ -445,7 +435,7 @@ PluginContext::StringToLocalUTF8(cell_t local_addr, size_t maxbytes, const char
size_t len; size_t len;
bool needtocheck = false; bool needtocheck = false;
if (((local_addr >= m_ctx.hp) && (local_addr < m_ctx.sp)) || if (((local_addr >= hp_) && (local_addr < sp_)) ||
(local_addr < 0) || (local_addr < 0) ||
((ucell_t)local_addr >= m_pRuntime->plugin()->mem_size)) ((ucell_t)local_addr >= m_pRuntime->plugin()->mem_size))
{ {
@ -550,7 +540,7 @@ PluginContext::Execute2(IPluginFunction *function, const cell_t *params, unsigne
if (m_pRuntime->IsPaused()) if (m_pRuntime->IsPaused())
return SP_ERROR_NOT_RUNNABLE; 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)(hp_ + 16*sizeof(cell_t)) > (cell_t)(sp_ - (sizeof(cell_t) * (num_params + 1))))
return SP_ERROR_STACKLOW; return SP_ERROR_STACKLOW;
if (result == NULL) if (result == NULL)
@ -580,25 +570,25 @@ PluginContext::Execute2(IPluginFunction *function, const cell_t *params, unsigne
uint32_t save_n_idx; uint32_t save_n_idx;
cell_t save_sp, save_hp, save_rp, save_cip; cell_t save_sp, save_hp, save_rp, save_cip;
save_sp = m_ctx.sp; save_sp = sp_;
save_hp = m_ctx.hp; save_hp = hp_;
save_exec = m_InExec; save_exec = m_InExec;
save_n_idx = m_ctx.n_idx; save_n_idx = last_native_;
save_rp = m_ctx.rp; save_rp = rp_;
save_cip = m_ctx.cip; save_cip = cip_;
/* Push parameters */ /* Push parameters */
m_ctx.sp -= sizeof(cell_t) * (num_params + 1); sp_ -= sizeof(cell_t) * (num_params + 1);
sp = (cell_t *)(m_pRuntime->plugin()->memory + m_ctx.sp); sp = (cell_t *)(m_pRuntime->plugin()->memory + sp_);
sp[0] = num_params; sp[0] = num_params;
for (unsigned int i = 0; i < num_params; i++) for (unsigned int i = 0; i < num_params; i++)
sp[i + 1] = params[i]; sp[i + 1] = params[i];
/* Clear internal state */ /* Clear internal state */
m_ctx.n_err = SP_ERROR_NONE; native_error_ = SP_ERROR_NONE;
m_ctx.n_idx = 0; last_native_ = -1;
m_MsgCache[0] = '\0'; m_MsgCache[0] = '\0';
m_CustomMsg = false; m_CustomMsg = false;
m_InExec = true; m_InExec = true;
@ -615,23 +605,23 @@ PluginContext::Execute2(IPluginFunction *function, const cell_t *params, unsigne
m_InExec = save_exec; m_InExec = save_exec;
if (ir == SP_ERROR_NONE) { if (ir == SP_ERROR_NONE) {
m_ctx.n_err = SP_ERROR_NONE; native_error_ = SP_ERROR_NONE;
if (m_ctx.sp != save_sp) { if (sp_ != save_sp) {
ir = SP_ERROR_STACKLEAK; ir = SP_ERROR_STACKLEAK;
_SetErrorMessage("Stack leak detected: sp:%d should be %d!", _SetErrorMessage("Stack leak detected: sp:%d should be %d!",
m_ctx.sp, sp_,
save_sp); save_sp);
} }
if (m_ctx.hp != save_hp) { if (hp_ != save_hp) {
ir = SP_ERROR_HEAPLEAK; ir = SP_ERROR_HEAPLEAK;
_SetErrorMessage("Heap leak detected: hp:%d should be %d!", _SetErrorMessage("Heap leak detected: hp:%d should be %d!",
m_ctx.hp, hp_,
save_hp); save_hp);
} }
if (m_ctx.rp != save_rp) { if (rp_ != save_rp) {
ir = SP_ERROR_STACKLEAK; ir = SP_ERROR_STACKLEAK;
_SetErrorMessage("Return stack leak detected: rp:%d should be %d!", _SetErrorMessage("Return stack leak detected: rp:%d should be %d!",
m_ctx.rp, rp_,
save_rp); save_rp);
} }
} }
@ -642,13 +632,13 @@ PluginContext::Execute2(IPluginFunction *function, const cell_t *params, unsigne
if (ir != SP_ERROR_NONE) if (ir != SP_ERROR_NONE)
Environment::get()->ReportError(m_pRuntime, ir, m_MsgCache, save_rp); Environment::get()->ReportError(m_pRuntime, ir, m_MsgCache, save_rp);
m_ctx.sp = save_sp; sp_ = save_sp;
m_ctx.hp = save_hp; hp_ = save_hp;
m_ctx.rp = save_rp; rp_ = save_rp;
m_ctx.cip = save_cip; cip_ = save_cip;
m_ctx.n_idx = save_n_idx; last_native_ = save_n_idx;
m_ctx.n_err = SP_ERROR_NONE; native_error_ = SP_ERROR_NONE;
m_MsgCache[0] = '\0'; m_MsgCache[0] = '\0';
m_CustomMsg = false; m_CustomMsg = false;
@ -780,13 +770,13 @@ DebugInfo::LookupLine(ucell_t addr, uint32_t *line)
int int
PluginContext::GetLastNativeError() PluginContext::GetLastNativeError()
{ {
return m_ctx.n_err; return native_error_;
} }
cell_t * cell_t *
PluginContext::GetLocalParams() 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 void
@ -812,5 +802,250 @@ PluginContext::GetKey(int k, void **value)
void void
PluginContext::ClearLastNativeError() PluginContext::ClearLastNativeError()
{ {
m_ctx.n_err = SP_ERROR_NONE; native_error_ = 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 > (hp_ - m_pRuntime->plugin()->data_size))
return SP_ERROR_HEAPMIN;
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;
}
cell_t
PluginContext::invokeNative(ucell_t native_idx, cell_t *params)
{
cell_t save_sp = sp_;
cell_t save_hp = 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) {
native_error_ = SP_ERROR_INVALID_NATIVE;
return 0;
}
cell_t result = native->pfn(this, params);
if (native_error_ != SP_ERROR_NONE)
return result;
if (save_sp != sp_) {
native_error_ = SP_ERROR_STACKLEAK;
return result;
}
if (save_hp != hp_) {
native_error_ = SP_ERROR_HEAPLEAK;
return result;
}
return result;
}
cell_t
PluginContext::invokeBoundNative(SPVM_NATIVE_FUNC pfn, cell_t *params)
{
cell_t save_sp = sp_;
cell_t save_hp = hp_;
cell_t result = pfn(this, params);
if (native_error_ != SP_ERROR_NONE)
return result;
if (save_sp != sp_) {
native_error_ = SP_ERROR_STACKLEAK;
return result;
}
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<cell_t *>(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<cell_t *>(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;
}

View File

@ -18,6 +18,18 @@
#include "plugin-runtime.h" #include "plugin-runtime.h"
#include "jit_shared.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 class PluginContext : public IPluginContext
{ {
public: public:
@ -27,7 +39,6 @@ class PluginContext : public IPluginContext
public: //IPluginContext public: //IPluginContext
IVirtualMachine *GetVirtualMachine(); IVirtualMachine *GetVirtualMachine();
sp_context_t *GetContext(); sp_context_t *GetContext();
sp_context_t *GetCtx();
bool IsDebugging(); bool IsDebugging();
int SetDebugBreak(void *newpfn, void *oldpfn); int SetDebugBreak(void *newpfn, void *oldpfn);
IPluginDebugInfo *GetDebugInfo(); IPluginDebugInfo *GetDebugInfo();
@ -76,6 +87,94 @@ class PluginContext : public IPluginContext
public: public:
bool IsInExec(); bool IsInExec();
static inline size_t offsetOfRp() {
return offsetof(PluginContext, rp_);
}
static inline size_t offsetOfRstkCips() {
return offsetof(PluginContext, rstk_cips_);
}
static inline size_t offsetOfTracker() {
return offsetof(PluginContext, tracker_);
}
static inline size_t offsetOfLastNative() {
return offsetof(PluginContext, last_native_);
}
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_;
}
cell_t *addressOfHp() {
return &hp_;
}
int32_t cip() const {
return cip_;
}
cell_t frm() const {
return frm_;
}
cell_t hp() const {
return hp_;
}
// Return stack logic.
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];
}
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<cell_t *>(m_pRuntime->plugin()->memory + addr) < stk)
return false;
return true;
}
private: private:
void SetErrorMessage(const char *msg, va_list ap); void SetErrorMessage(const char *msg, va_list ap);
void _SetErrorMessage(const char *msg, ...); void _SetErrorMessage(const char *msg, ...);
@ -87,9 +186,27 @@ class PluginContext : public IPluginContext
bool m_CustomMsg; bool m_CustomMsg;
bool m_InExec; bool m_InExec;
PluginRuntime *m_pRuntime; PluginRuntime *m_pRuntime;
sp_context_t m_ctx;
void *m_keys[4]; void *m_keys[4];
bool m_keys_set[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];
// Track the currently executing native index, and any error it throws.
int32_t last_native_;
int native_error_;
// Most recent CIP.
int32_t cip_;
// Stack, heap, and frame pointer.
cell_t sp_;
cell_t hp_;
cell_t frm_;
}; };
#endif //_INCLUDE_SOURCEPAWN_BASECONTEXT_H_ #endif //_INCLUDE_SOURCEPAWN_BASECONTEXT_H_

View File

@ -96,6 +96,10 @@ class PluginRuntime
return m_JitFunctions[i]; return m_JitFunctions[i];
} }
static inline size_t offsetToPlugin() {
return offsetof(PluginRuntime, m_plugin);
}
private: private:
void SetupFloatNativeRemapping(); void SetupFloatNativeRemapping();

View File

@ -47,12 +47,19 @@ CodeStubs::CompileInvokeStub()
__ push(ebx); // ebp - 12 __ push(ebx); // ebp - 12
__ push(esp); // ebp - 16 __ push(esp); // ebp - 16
// ebx = cx
__ movl(ebx, Operand(ebp, 8 + 4 * 0)); __ 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. // Set up run-time registers.
__ movl(edi, Operand(ebx, offsetof(sp_context_t, sp))); __ movl(edi, Operand(ebx, PluginContext::offsetOfSp()));
__ addl(edi, eax); __ addl(edi, eax);
__ movl(esi, eax); __ movl(esi, eax);
__ movl(ebx, edi); __ movl(ebx, edi);
@ -64,8 +71,8 @@ CodeStubs::CompileInvokeStub()
__ call(ecx); __ call(ecx);
// Get input context, store rval. // Get input context, store rval.
__ movl(ecx, Operand(ebp, 8 + 4 * 0)); __ movl(ecx, Operand(ebp, 8 + 4 * 2));
__ movl(Operand(ecx, offsetof(sp_context_t, rval)), pri); __ movl(Operand(ecx, 0), pri);
// Set no error. // Set no error.
__ movl(eax, SP_ERROR_NONE); __ movl(eax, SP_ERROR_NONE);
@ -75,7 +82,8 @@ CodeStubs::CompileInvokeStub()
Label ret; Label ret;
__ bind(&ret); __ bind(&ret);
__ subl(stk, dat); __ 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. // Restore stack.
__ movl(esp, Operand(ebp, -16)); __ movl(esp, Operand(ebp, -16));

View File

@ -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<cell_t *>(rt->plugin()->memory + new_hp);
// argv, coincidentally, is STK.
if (dat_hp >= argv - STACK_MARGIN)
return SP_ERROR_HEAPLOW;
if (int err = PushTracker(rt->GetBaseContext()->GetCtx(), bytes))
return err;
cell_t *base = reinterpret_cast<cell_t *>(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 #if !defined NDEBUG
static const char * static const char *
GetFunctionName(const sp_plugin_t *plugin, uint32_t offs) GetFunctionName(const sp_plugin_t *plugin, uint32_t offs)
@ -303,6 +181,7 @@ CompileFromThunk(PluginRuntime *runtime, cell_t pcode_offs, void **addrp, char *
Compiler::Compiler(PluginRuntime *rt, cell_t pcode_offs) Compiler::Compiler(PluginRuntime *rt, cell_t pcode_offs)
: env_(Environment::get()), : env_(Environment::get()),
rt_(rt), rt_(rt),
context_(rt->GetBaseContext()),
plugin_(rt->plugin()), plugin_(rt->plugin()),
error_(SP_ERROR_NONE), error_(SP_ERROR_NONE),
pcode_start_(pcode_offs), pcode_start_(pcode_offs),
@ -384,6 +263,37 @@ Compiler::emit(int *errp)
return new CompiledFunction(code, pcode_start_, edges.take()); 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();
}
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);
}
static int
InvokeGenerateFullArray(PluginContext *cx, uint32_t argc, cell_t *argv, int autozero)
{
return cx->generateFullArray(argc, argv, autozero);
}
bool bool
Compiler::emitOp(OPCODE op) Compiler::emitOp(OPCODE op)
{ {
@ -1258,8 +1168,8 @@ Compiler::emitOp(OPCODE op)
__ push(alt); __ push(alt);
__ push(amount * 4); __ push(amount * 4);
__ push(intptr_t(rt_->GetBaseContext()->GetCtx())); __ push(intptr_t(rt_->GetBaseContext()));
__ call(ExternalAddress((void *)PushTracker)); __ call(ExternalAddress((void *)InvokePushTracker));
__ addl(esp, 8); __ addl(esp, 8);
__ testl(eax, eax); __ testl(eax, eax);
__ j(not_zero, &extern_error_); __ j(not_zero, &extern_error_);
@ -1276,8 +1186,8 @@ Compiler::emitOp(OPCODE op)
__ push(alt); __ push(alt);
// Get the context pointer and call the sanity checker. // Get the context pointer and call the sanity checker.
__ push(intptr_t(rt_)); __ push(intptr_t(rt_->GetBaseContext()));
__ call(ExternalAddress((void *)PopTrackerAndSetHeap)); __ call(ExternalAddress((void *)InvokePopTrackerAndSetHeap));
__ addl(esp, 4); __ addl(esp, 4);
__ testl(eax, eax); __ testl(eax, eax);
__ j(not_zero, &extern_error_); __ j(not_zero, &extern_error_);
@ -1296,8 +1206,6 @@ Compiler::emitOp(OPCODE op)
case OP_HALT: case OP_HALT:
__ align(16); __ align(16);
__ movl(tmp, intptr_t(rt_->GetBaseContext()->GetCtx()));
__ movl(Operand(tmp, offsetof(sp_context_t, rval)), pri);
__ movl(pri, readCell()); __ movl(pri, readCell());
__ jmp(&extern_error_); __ jmp(&extern_error_);
break; break;
@ -1405,8 +1313,8 @@ Compiler::emitGenArray(bool autozero)
__ shll(tmp, 2); __ shll(tmp, 2);
__ push(tmp); __ push(tmp);
__ push(intptr_t(rt_->GetBaseContext()->GetCtx())); __ push(intptr_t(rt_->GetBaseContext()));
__ call(ExternalAddress((void *)PushTracker)); __ call(ExternalAddress((void *)InvokePushTracker));
__ addl(esp, 4); __ addl(esp, 4);
__ pop(tmp); __ pop(tmp);
__ shrl(tmp, 2); __ shrl(tmp, 2);
@ -1432,8 +1340,8 @@ Compiler::emitGenArray(bool autozero)
__ push(autozero ? 1 : 0); __ push(autozero ? 1 : 0);
__ push(stk); __ push(stk);
__ push(val); __ push(val);
__ push(intptr_t(rt_)); __ push(intptr_t(context_));
__ call(ExternalAddress((void *)GenerateFullArray)); __ call(ExternalAddress((void *)InvokeGenerateFullArray));
__ addl(esp, 4 * sizeof(void *)); __ addl(esp, 4 * sizeof(void *));
// restore pri to tmp // restore pri to tmp
@ -1462,8 +1370,8 @@ Compiler::emitCall()
// eax = context // eax = context
// ecx = rp // ecx = rp
__ movl(eax, intptr_t(rt_->GetBaseContext()->GetCtx())); __ movl(eax, intptr_t(rt_->GetBaseContext()));
__ movl(ecx, Operand(eax, offsetof(sp_context_t, rp))); __ movl(ecx, Operand(eax, PluginContext::offsetOfRp()));
// Check if the return stack is used up. // Check if the return stack is used up.
__ cmpl(ecx, SP_MAX_RETURN_STACK); __ cmpl(ecx, SP_MAX_RETURN_STACK);
@ -1471,10 +1379,10 @@ Compiler::emitCall()
// Add to the return stack. // Add to the return stack.
uintptr_t cip = uintptr_t(cip_ - 2) - uintptr_t(plugin_->pcode); 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. // 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. // Store the CIP of the function we're about to call.
__ movl(Operand(cipAddr()), offset); __ movl(Operand(cipAddr()), offset);
@ -1495,8 +1403,8 @@ Compiler::emitCall()
__ movl(Operand(cipAddr()), cip); __ movl(Operand(cipAddr()), cip);
// Mark us as leaving the last frame. // Mark us as leaving the last frame.
__ movl(tmp, intptr_t(rt_->GetBaseContext()->GetCtx())); __ movl(tmp, intptr_t(rt_->GetBaseContext()));
__ subl(Operand(tmp, offsetof(sp_context_t, rp)), 1); __ subl(Operand(tmp, PluginContext::offsetOfRp()), 1);
return true; return true;
} }
@ -1581,13 +1489,13 @@ Compiler::emitNativeCall(OPCODE op)
// Push the last parameter for the C++ function. // Push the last parameter for the C++ function.
__ push(stk); __ 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 // Relocate our absolute stk to be dat-relative, and update the context's
// view. // view.
__ movl(eax, intptr_t(rt_->GetBaseContext()->GetCtx()));
__ subl(stk, dat); __ subl(stk, dat);
__ movl(Operand(eax, offsetof(sp_context_t, sp)), stk); __ movl(Operand(eax, PluginContext::offsetOfSp()), stk);
__ movl(Operand(eax, offsetof(sp_context_t, n_idx)), native_index);
sp_native_t *native = rt_->GetNativeByIndex(native_index); sp_native_t *native = rt_->GetNativeByIndex(native_index);
if ((native->status != SP_NATIVE_BOUND) || if ((native->status != SP_NATIVE_BOUND) ||
@ -1596,18 +1504,18 @@ Compiler::emitNativeCall(OPCODE op)
// The native is either unbound, or it could become unbound in the // The native is either unbound, or it could become unbound in the
// future. Invoke the slower native callback. // future. Invoke the slower native callback.
__ push(native_index); __ push(native_index);
__ push(eax); __ push(intptr_t(rt_->GetBaseContext()));
__ call(ExternalAddress((void *)NativeCallback)); __ call(ExternalAddress((void *)InvokeNativeHelper));
} else { } else {
// The native is bound so we have a few more guarantees. // The native is bound so we have a few more guarantees.
__ push(intptr_t(native->pfn)); __ push(intptr_t(native->pfn));
__ push(eax); __ push(intptr_t(rt_->GetBaseContext()));
__ call(ExternalAddress((void *)BoundNativeCallback)); __ call(ExternalAddress((void *)InvokeBoundNativeHelper));
} }
// Check for errors. // Check for errors.
__ movl(ecx, intptr_t(rt_->GetBaseContext()->GetCtx())); __ movl(ecx, intptr_t(rt_->GetBaseContext()));
__ movl(ecx, Operand(ecx, offsetof(sp_context_t, n_err))); __ movl(ecx, Operand(ecx, PluginContext::offsetOfNativeError()));
__ testl(ecx, ecx); __ testl(ecx, ecx);
__ j(not_zero, &extern_error_); __ j(not_zero, &extern_error_);
@ -1798,8 +1706,8 @@ Compiler::emitErrorPaths()
if (extern_error_.used()) { if (extern_error_.used()) {
__ bind(&extern_error_); __ bind(&extern_error_);
__ movl(eax, intptr_t(rt_->GetBaseContext()->GetCtx())); __ movl(eax, intptr_t(rt_->GetBaseContext()));
__ movl(eax, Operand(eax, offsetof(sp_context_t, n_err))); __ movl(eax, Operand(eax, PluginContext::offsetOfNativeError()));
__ jmp(ExternalAddress(env_->stubs()->ReturnStub())); __ jmp(ExternalAddress(env_->stubs()->ReturnStub()));
} }
} }

View File

@ -91,22 +91,20 @@ class Compiler
void emitFloatCmp(ConditionCode cc); void emitFloatCmp(ConditionCode cc);
ExternalAddress cipAddr() { ExternalAddress cipAddr() {
sp_context_t *ctx = rt_->GetBaseContext()->GetCtx(); return ExternalAddress(context_->addressOfCip());
return ExternalAddress(&ctx->cip);
} }
ExternalAddress hpAddr() { ExternalAddress hpAddr() {
sp_context_t *ctx = rt_->GetBaseContext()->GetCtx(); return ExternalAddress(context_->addressOfHp());
return ExternalAddress(&ctx->hp);
} }
ExternalAddress frmAddr() { ExternalAddress frmAddr() {
sp_context_t *ctx = rt_->GetBaseContext()->GetCtx(); return ExternalAddress(context_->addressOfFrm());
return ExternalAddress(&ctx->frm);
} }
private: private:
AssemblerX86 masm; AssemblerX86 masm;
sp::Environment *env_; sp::Environment *env_;
PluginRuntime *rt_; PluginRuntime *rt_;
PluginContext *context_;
const sp_plugin_t *plugin_; const sp_plugin_t *plugin_;
int error_; int error_;
uint32_t pcode_start_; uint32_t pcode_start_;