diff --git a/core/vm/sp_vm_basecontext.cpp b/core/vm/sp_vm_basecontext.cpp index f9961a17..9e82f672 100644 --- a/core/vm/sp_vm_basecontext.cpp +++ b/core/vm/sp_vm_basecontext.cpp @@ -48,17 +48,24 @@ IPluginDebugInfo *BaseContext::GetDebugInfo() return this; } -int BaseContext::Execute(uint32_t public_func, cell_t *result) +int BaseContext::Execute(funcid_t funcid, cell_t *result) { IVirtualMachine *vm = (IVirtualMachine *)ctx->vmbase; uint32_t pushcount = ctx->pushcount; - + uint32_t code_addr; int err; - sp_public_t *pubfunc; - if ((err=GetPublicByIndex(public_func, &pubfunc)) != SP_ERROR_NONE) + + if (funcid & 1) { - return err; + sp_public_t *pubfunc; + if ((err=GetPublicByIndex((funcid>>1), &pubfunc)) != SP_ERROR_NONE) + { + return err; + } + code_addr = pubfunc->code_offs; + } else { + code_addr = funcid >> 1; } PushCell(pushcount++); @@ -67,7 +74,7 @@ int BaseContext::Execute(uint32_t public_func, cell_t *result) cell_t save_sp = ctx->sp; cell_t save_hp = ctx->hp; - err = vm->ContextExecute(ctx, pubfunc->offs, result); + err = vm->ContextExecute(ctx, code_addr, result); /** * :TODO: turn this into an error check @@ -338,7 +345,7 @@ int BaseContext::BindNatives(sp_nativeinfo_t *natives, unsigned int num, int ove for (i=0; inatives[i].status == SP_NATIVE_OKAY) && !overwrite) + if ((ctx->natives[i].status == SP_NATIVE_BOUND) && !overwrite) { continue; } @@ -348,7 +355,7 @@ int BaseContext::BindNatives(sp_nativeinfo_t *natives, unsigned int num, int ove if (!strcmp(ctx->natives[i].name, natives[j].name)) { ctx->natives[i].pfn = natives[j].func; - ctx->natives[i].status = SP_NATIVE_OKAY; + ctx->natives[i].status = SP_NATIVE_BOUND; } } } @@ -356,7 +363,7 @@ int BaseContext::BindNatives(sp_nativeinfo_t *natives, unsigned int num, int ove return SP_ERROR_NONE; } -int BaseContext::BindNative(sp_nativeinfo_t *native, uint32_t status) +int BaseContext::BindNative(sp_nativeinfo_t *native) { uint32_t index; int err; @@ -367,7 +374,6 @@ int BaseContext::BindNative(sp_nativeinfo_t *native, uint32_t status) } ctx->natives[index].pfn = native->func; - ctx->natives[index].status = status; return SP_ERROR_NONE; } @@ -380,10 +386,9 @@ int BaseContext::BindNativeToAny(SPVM_NATIVE_FUNC native) for (i=0; inatives[i].status != SP_NATIVE_OKAY) + if (ctx->natives[i].status == SP_NATIVE_UNBOUND) { ctx->natives[i].pfn = native; - ctx->natives[i].status = SP_NATIVE_PENDING; } } diff --git a/core/vm/sp_vm_basecontext.h b/core/vm/sp_vm_basecontext.h index 1faf1b81..9fbe2dd6 100644 --- a/core/vm/sp_vm_basecontext.h +++ b/core/vm/sp_vm_basecontext.h @@ -38,9 +38,9 @@ namespace SourcePawn virtual int PushString(cell_t *local_addr, cell_t **phys_addr, const char *string); virtual int PushCellsFromArray(cell_t array[], unsigned int numcells); virtual int BindNatives(sp_nativeinfo_t *natives, unsigned int num, int overwrite); - virtual int BindNative(sp_nativeinfo_t *native, uint32_t status); + virtual int BindNative(sp_nativeinfo_t *native); virtual int BindNativeToAny(SPVM_NATIVE_FUNC native); - virtual int Execute(uint32_t public_func, cell_t *result); + virtual int Execute(funcid_t funcid, cell_t *result); public: //IPluginDebugInfo virtual int LookupFile(ucell_t addr, const char **filename); virtual int LookupFunction(ucell_t addr, const char **name); diff --git a/sourcepawn/compiler/sc3.c b/sourcepawn/compiler/sc3.c index 5e7a2840..e31e195c 100644 --- a/sourcepawn/compiler/sc3.c +++ b/sourcepawn/compiler/sc3.c @@ -1965,10 +1965,10 @@ restart: lval1->ident=iCONSTEXPR; /* Generate a quick pseudo-tag! */ if (usage == uPUBLIC) { - lval1->constval=(n>>1)|(1<<1); + lval1->constval=(n<<1)|1; snprintf(faketag, sizeof(faketag)-1, "$Func@%d", n); } else { - lval1->constval=(code_addr>>1)|(1<<0); + lval1->constval=(code_addr<<1)|0; snprintf(faketag, sizeof(faketag)-1, "$Func!%d", code_addr); } lval1->tag=pc_addfunctag(faketag); diff --git a/sourcepawn/include/sp_vm_api.h b/sourcepawn/include/sp_vm_api.h index 56e354de..9a1ba692 100644 --- a/sourcepawn/include/sp_vm_api.h +++ b/sourcepawn/include/sp_vm_api.h @@ -8,6 +8,9 @@ namespace SourcePawn { class IVirtualMachine; + /** + * @brief Interface to managing a debug context at runtime. + */ class IPluginDebugInfo { public: @@ -36,6 +39,9 @@ namespace SourcePawn virtual int LookupLine(ucell_t addr, uint32_t *line) =0; }; + /** + * @brief Interface to managing a context at runtime. + */ class IPluginContext { public: @@ -260,7 +266,6 @@ namespace SourcePawn /** * Binds a list of native names and their function pointers to a context. * If num is 0, the list is read until an entry with a NULL name is reached. - * All natives are assigned a status of SP_NATIVE_OKAY by default. * If overwrite is non-zero, already registered natives will be overwritten. * * @param natives Array of natives. @@ -272,29 +277,31 @@ namespace SourcePawn /** * Binds a single native. Overwrites any existing bind. * If the context does not contain the native that will be binded the function will return - * with a SP_ERROR_OT_FOUND error. + * with a SP_ERROR_NOT_FOUND error. * * @param native Pointer to native. - * @param status Status value to set (should be SP_NATIVE_OKAY). */ - virtual int BindNative(sp_nativeinfo_t *native, uint32_t status) =0; + virtual int BindNative(sp_nativeinfo_t *native) =0; /** - * Binds a single native to any non-registered or pending native. - * Status is automatically set to pending. + * Binds a single native to any non-registered native. * * @param native Native to bind. */ virtual int BindNativeToAny(SPVM_NATIVE_FUNC native) =0; /** - * Executes a public function. + * Executes a function ID located in this context. + * + * @param funcid Function id to execute. + * @param result Pointer to store the return value (required). + * @return Error code (if any) from the VM. */ - virtual int Execute(uint32_t public_func, cell_t *result) =0; + virtual int Execute(uint32_t funcid, cell_t *result) =0; }; /** - * Contains helper functions used by VMs and the host app + * @brief Contains helper functions used by VMs and the host app */ class ISourcePawnEngine { @@ -379,6 +386,9 @@ namespace SourcePawn virtual ~ICompilation() { }; }; + /** + * @brief Outlines the interface a Virtual Machine (JIT) must expose + */ class IVirtualMachine { public: diff --git a/sourcepawn/include/sp_vm_types.h b/sourcepawn/include/sp_vm_types.h index 49cbb984..2c7bea84 100644 --- a/sourcepawn/include/sp_vm_types.h +++ b/sourcepawn/include/sp_vm_types.h @@ -5,6 +5,7 @@ typedef uint32_t ucell_t; typedef int32_t cell_t; +typedef uint32_t funcid_t; /** * Error codes @@ -17,20 +18,20 @@ typedef int32_t cell_t; #define SP_ERROR_INVALID_ADDRESS 5 /* A memory address was not valid */ #define SP_ERROR_NOT_FOUND 6 /* The object in question was not found */ #define SP_ERROR_INDEX 7 /* Invalid index parameter */ -#define SP_ERROR_NATIVE_PENDING 8 /* A script tried to exec an unbound native */ -#define SP_ERROR_STACKLOW 9 /* Nnot enough space left on the stack */ -#define SP_ERROR_NOTDEBUGGING 10 /* Debug mode was not on or debug section not found */ -#define SP_ERROR_INVALID_INSTRUCTION 11 /* Invalid instruction was encountered */ -#define SP_ERROR_MEMACCESS 12 /* Invalid memory access */ -#define SP_ERROR_STACKMIN 13 /* Stack went beyond its minimum value */ -#define SP_ERROR_HEAPMIN 14 /* Heap went beyond its minimum value */ -#define SP_ERROR_DIVIDE_BY_ZERO 15 /* Division by zero */ -#define SP_ERROR_ARRAY_BOUNDS 16 /* Array index is out of bounds */ -#define SP_ERROR_INSTRUCTION_PARAM 17 /* Instruction had an invalid parameter */ -#define SP_ERROR_STACKLEAK 18 /* A native leaked an item on the stack */ -#define SP_ERROR_HEAPLEAK 19 /* A native leaked an item on the heap */ -#define SP_ERROR_ARRAY_TOO_BIG 20 /* A dynamic array is too big */ -#define SP_ERROR_TRACKER_BOUNDS 21 /* Tracker stack is out of bounds */ +#define SP_ERROR_STACKLOW 8 /* Nnot enough space left on the stack */ +#define SP_ERROR_NOTDEBUGGING 9 /* Debug mode was not on or debug section not found */ +#define SP_ERROR_INVALID_INSTRUCTION 10 /* Invalid instruction was encountered */ +#define SP_ERROR_MEMACCESS 11 /* Invalid memory access */ +#define SP_ERROR_STACKMIN 12 /* Stack went beyond its minimum value */ +#define SP_ERROR_HEAPMIN 13 /* Heap went beyond its minimum value */ +#define SP_ERROR_DIVIDE_BY_ZERO 14 /* Division by zero */ +#define SP_ERROR_ARRAY_BOUNDS 15 /* Array index is out of bounds */ +#define SP_ERROR_INSTRUCTION_PARAM 16 /* Instruction had an invalid parameter */ +#define SP_ERROR_STACKLEAK 17 /* A native leaked an item on the stack */ +#define SP_ERROR_HEAPLEAK 18 /* A native leaked an item on the heap */ +#define SP_ERROR_ARRAY_TOO_BIG 19 /* A dynamic array is too big */ +#define SP_ERROR_TRACKER_BOUNDS 20 /* Tracker stack is out of bounds */ +#define SP_ERROR_INVALID_NATIVE 21 /* Native was pending or invalid */ /********************************************** *** The following structures are reference structures. @@ -117,7 +118,8 @@ typedef cell_t (*SPVM_NATIVE_FUNC)(struct sp_context_s *, cell_t *); */ typedef struct sp_public_s { - uint32_t offs; /* code offset */ + funcid_t funcid; /* encoded function id */ + uint32_t code_offs; /* code offset */ const char *name; /* name */ } sp_public_t; @@ -132,9 +134,8 @@ typedef struct sp_pubvar_s const char *name; /* name */ } sp_pubvar_t; -#define SP_NATIVE_NONE (0) /* Native is not yet found */ -#define SP_NATIVE_OKAY (1) /* Native has been added */ -#define SP_NATIVE_PENDING (2) /* Native is marked as usable but replaceable */ +#define SP_NATIVE_UNBOUND (0) /* Native is undefined */ +#define SP_NATIVE_BOUND (1) /* Native is bound */ /** * Native lookup table, by default names diff --git a/sourcepawn/jit/x86/jit_x86.cpp b/sourcepawn/jit/x86/jit_x86.cpp index 07787592..1dfe2d97 100644 --- a/sourcepawn/jit/x86/jit_x86.cpp +++ b/sourcepawn/jit/x86/jit_x86.cpp @@ -1747,15 +1747,22 @@ cell_t NativeCallback(sp_context_t *ctx, ucell_t native_idx, cell_t *params) sp_native_t *native = &ctx->natives[native_idx]; /* Technically both aren't needed, I guess */ - if (native->status == SP_NATIVE_NONE) + if (native->status == SP_NATIVE_UNBOUND) { - ctx->err = SP_ERROR_NATIVE_PENDING; + ctx->err = SP_ERROR_INVALID_NATIVE; return 0; } return native->pfn(ctx, params); } +cell_t InvalidNative(sp_context_t *ctx, cell_t *params) +{ + ctx->err = SP_ERROR_INVALID_NATIVE; + + return 0; +} + cell_t NativeCallback_Debug(sp_context_t *ctx, ucell_t native_idx, cell_t *params) { cell_t save_sp = ctx->sp; @@ -2002,7 +2009,9 @@ jit_rewind: for (iter=0; iterpublics[iter].name = strbase + plugin->info.publics[iter].name; - ctx->publics[iter].offs = RelocLookup(jit, plugin->info.publics[iter].address, false); + ctx->publics[iter].code_offs = RelocLookup(jit, plugin->info.publics[iter].address, false); + /* Encode the ID as a straight code offset */ + ctx->publics[iter].funcid = (ctx->publics[iter].code_offs << 1); } } @@ -2025,8 +2034,8 @@ jit_rewind: for (iter=0; iternatives[iter].name = strbase + plugin->info.natives[iter].name; - ctx->natives[iter].pfn = NULL; - ctx->natives[iter].status = SP_NATIVE_NONE; + ctx->natives[iter].pfn = &InvalidNative; + ctx->natives[iter].status = SP_NATIVE_UNBOUND; } } diff --git a/sourcepawn/jit/x86/msvc8/jit-x86.vcproj b/sourcepawn/jit/x86/msvc8/jit-x86.vcproj index 7298d68d..537fd87b 100644 --- a/sourcepawn/jit/x86/msvc8/jit-x86.vcproj +++ b/sourcepawn/jit/x86/msvc8/jit-x86.vcproj @@ -247,23 +247,19 @@ > - -