Optimize native call if statically bound (bug 5842, r=ds,fyren f=dvander).
authorKyle Sanderson <kyle.leet@gmail.com>
Sun May 11 14:36:32 2014 -0700 (2014-05-11)
changeset 435852aa5fab9866
parent 4357 82898b97ddc4
child 4359 444f983b8356
Optimize native call if statically bound (bug 5842, r=ds,fyren f=dvander).
Original patch written by David Anderson (original r from Fyren).
- Updated to function with the current JIT compiler.
- Took in clean-ups from later-dated patches.
core/logic/ShareSys.cpp
public/sourcepawn/sp_vm_types.h
sourcepawn/jit/BaseRuntime.cpp
sourcepawn/jit/BaseRuntime.h
sourcepawn/jit/interpreter.cpp
sourcepawn/jit/interpreter.h
sourcepawn/jit/x86/jit_x86.cpp
     1.1 --- a/core/logic/ShareSys.cpp	Sat May 10 22:21:42 2014 -0400
     1.2 +++ b/core/logic/ShareSys.cpp	Sun May 11 14:36:32 2014 -0700
     1.3 @@ -331,6 +331,13 @@
     1.4  	native->status = SP_NATIVE_BOUND;
     1.5  	native->pfn = pEntry->func();
     1.6  
     1.7 +	if (pEntry->fake)
     1.8 +	{
     1.9 +		/* This native is not necessarily optional, but we don't guarantee
    1.10 +		 * that its address is long-lived. */
    1.11 +		native->flags |= SP_NTVFLAG_EPHEMERAL;
    1.12 +	}
    1.13 +
    1.14  	/* We don't bother with dependency crap if the owner is Core. */
    1.15  	if (pEntry->owner != &g_CoreNatives)
    1.16  	{
     2.1 --- a/public/sourcepawn/sp_vm_types.h	Sat May 10 22:21:42 2014 -0400
     2.2 +++ b/public/sourcepawn/sp_vm_types.h	Sun May 11 14:36:32 2014 -0700
     2.3 @@ -148,6 +148,7 @@
     2.4  #define SP_NATIVE_BOUND			(1)		/**< Native is bound */
     2.5  
     2.6  #define SP_NTVFLAG_OPTIONAL		(1<<0)	/**< Native is optional */
     2.7 +#define SP_NTVFLAG_EPHEMERAL		(1<<1)	/**< Native can be unbound */
     2.8  
     2.9  /** 
    2.10   * @brief Native lookup table, by default names point back to the sp_plugin_infotab_t structure.
     3.1 --- a/sourcepawn/jit/BaseRuntime.cpp	Sat May 10 22:21:42 2014 -0400
     3.2 +++ b/sourcepawn/jit/BaseRuntime.cpp	Sun May 11 14:36:32 2014 -0700
     3.3 @@ -355,6 +355,12 @@
     3.4    return SP_ERROR_NONE;
     3.5  }
     3.6  
     3.7 +sp_native_t *
     3.8 +BaseRuntime::GetNativeByIndex(uint32_t index)
     3.9 +{
    3.10 +  assert(index < m_plugin.num_natives);
    3.11 +  return &m_plugin.natives[index];
    3.12 +}
    3.13  
    3.14  uint32_t
    3.15  BaseRuntime::GetNativesNum()
     4.1 --- a/sourcepawn/jit/BaseRuntime.h	Sat May 10 22:21:42 2014 -0400
     4.2 +++ b/sourcepawn/jit/BaseRuntime.h	Sun May 11 14:36:32 2014 -0700
     4.3 @@ -49,6 +49,7 @@
     4.4    virtual IPluginDebugInfo *GetDebugInfo();
     4.5    virtual int FindNativeByName(const char *name, uint32_t *index);
     4.6    virtual int GetNativeByIndex(uint32_t index, sp_native_t **native);
     4.7 +  virtual sp_native_t *GetNativeByIndex(uint32_t index);
     4.8    virtual uint32_t GetNativesNum();
     4.9    virtual int FindPublicByName(const char *name, uint32_t *index);
    4.10    virtual int GetPublicByIndex(uint32_t index, sp_public_t **publicptr);
     5.1 --- a/sourcepawn/jit/interpreter.cpp	Sat May 10 22:21:42 2014 -0400
     5.2 +++ b/sourcepawn/jit/interpreter.cpp	Sun May 11 14:36:32 2014 -0700
     5.3 @@ -167,6 +167,29 @@
     5.4    return result;
     5.5  }
     5.6  
     5.7 +cell_t
     5.8 +BoundNativeCallback(sp_context_t *ctx, SPVM_NATIVE_FUNC pfn, cell_t *params)
     5.9 +{
    5.10 +  cell_t save_sp = ctx->sp;
    5.11 +  cell_t save_hp = ctx->hp;
    5.12 +
    5.13 +  cell_t result = pfn(ctx->basecx, params);
    5.14 +
    5.15 +  if (ctx->n_err != SP_ERROR_NONE)
    5.16 +    return result;
    5.17 +
    5.18 +  if (save_sp != ctx->sp) {
    5.19 +    ctx->n_err = SP_ERROR_STACKLEAK;
    5.20 +    return result;
    5.21 +  }
    5.22 +  if (save_hp != ctx->hp) {
    5.23 +    ctx->n_err = SP_ERROR_HEAPLEAK;
    5.24 +    return result;
    5.25 +  }
    5.26 +
    5.27 +  return result;
    5.28 +}
    5.29 +
    5.30  static inline bool
    5.31  GenerateArray(BaseRuntime *rt, sp_context_t *ctx, cell_t dims, cell_t *stk, bool autozero)
    5.32  {
     6.1 --- a/sourcepawn/jit/interpreter.h	Sat May 10 22:21:42 2014 -0400
     6.2 +++ b/sourcepawn/jit/interpreter.h	Sun May 11 14:36:32 2014 -0700
     6.3 @@ -33,6 +33,7 @@
     6.4  
     6.5  int GenerateFullArray(BaseRuntime *rt, uint32_t argc, cell_t *argv, int autozero);
     6.6  cell_t NativeCallback(sp_context_t *ctx, ucell_t native_idx, cell_t *params);
     6.7 +cell_t BoundNativeCallback(sp_context_t *ctx, SPVM_NATIVE_FUNC pfn, cell_t *params);
     6.8  int PopTrackerAndSetHeap(BaseRuntime *rt);
     6.9  int PushTracker(sp_context_t *ctx, size_t amount);
    6.10  
     7.1 --- a/sourcepawn/jit/x86/jit_x86.cpp	Sat May 10 22:21:42 2014 -0400
     7.2 +++ b/sourcepawn/jit/x86/jit_x86.cpp	Sun May 11 14:36:32 2014 -0700
     7.3 @@ -1579,9 +1579,8 @@
     7.4    // Save registers.
     7.5    __ push(edx);
     7.6  
     7.7 -  // Push the parameters for the C++ function.
     7.8 +  // Push the last parameter for the C++ function.
     7.9    __ push(stk);
    7.10 -  __ push(native_index);
    7.11  
    7.12    // Relocate our absolute stk to be dat-relative, and update the context's
    7.13    // view.
    7.14 @@ -1589,9 +1588,23 @@
    7.15    __ subl(stk, dat);
    7.16    __ movl(Operand(eax, offsetof(sp_context_t, sp)), stk);
    7.17  
    7.18 -  // Push context and make the call.
    7.19 -  __ push(eax);
    7.20 -  __ call(ExternalAddress((void *)NativeCallback));
    7.21 +  __ movl(Operand(eax, offsetof(sp_context_t, n_idx)), native_index);
    7.22 +
    7.23 +  sp_native_t *native = rt_->GetNativeByIndex(native_index);
    7.24 +  if ((native->status != SP_NATIVE_BOUND) ||
    7.25 +      (native->flags & (SP_NTVFLAG_OPTIONAL | SP_NTVFLAG_EPHEMERAL)))
    7.26 +  {
    7.27 +    // The native is either unbound, or it could become unbound in the
    7.28 +    // future. Invoke the slower native callback.
    7.29 +    __ push(native_index);
    7.30 +    __ push(eax);
    7.31 +    __ call(ExternalAddress((void *)NativeCallback));
    7.32 +  } else {
    7.33 +    // The native is bound so we have a few more guarantees.
    7.34 +    __ push(intptr_t(native->pfn));
    7.35 +    __ push(eax);
    7.36 +    __ call(ExternalAddress((void *)BoundNativeCallback));
    7.37 +  }
    7.38  
    7.39    // Check for errors.
    7.40    __ movl(ecx, intptr_t(rt_->GetBaseContext()->GetCtx()));