From b2c61a341a8112c84451dc08ed5d4e1857c07f48 Mon Sep 17 00:00:00 2001
From: David Anderson <dvander@alliedmods.net>
Date: Tue, 24 Feb 2015 21:06:06 -0800
Subject: [PATCH] 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 <stdint.h>
 #include <sp_vm_api.h>
 
-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<cell_t *>(plugin->memory + ctx->sp);
-
-  cell_t &frm = *cx->addressOfFrm();
+  cell_t *stk = reinterpret_cast<cell_t *>(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<cell_t *>(plugin->memory + ctx->sp);
+        stk = reinterpret_cast<cell_t *>(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) ||