Optimize native call if statically bound (bug 5842, r=ds,fyren f=dvander).
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.
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()));