added new API for function address lookups. this gives us O(1) code_addr -> sequential index

--HG--
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%40180
This commit is contained in:
David Anderson 2006-11-11 05:47:00 +00:00
parent 50e5307d32
commit 438ccf39a0
5 changed files with 118 additions and 17 deletions

View File

@ -505,6 +505,8 @@ cleanup:
delete_pathtable(); delete_pathtable();
delete_sourcefiletable(); delete_sourcefiletable();
delete_dbgstringtable(); delete_dbgstringtable();
funcenums_free();
pstructs_free();
#if !defined NO_DEFINE #if !defined NO_DEFINE
delete_substtable(); delete_substtable();
#endif #endif

View File

@ -4,6 +4,8 @@
#include <stdio.h> #include <stdio.h>
#include "sp_vm_types.h" #include "sp_vm_types.h"
#define SOURCEPAWN_VM_API_VERSION 1
namespace SourcePawn namespace SourcePawn
{ {
class IVirtualMachine; class IVirtualMachine;
@ -393,12 +395,17 @@ namespace SourcePawn
{ {
public: public:
/** /**
* Returns the string name of a VM implementation. * @brief Returns the current API version.
*/
virtual unsigned int GetAPIVersion() =0;
/**
* @brief Returns the string name of a VM implementation.
*/ */
virtual const char *GetVMName() =0; virtual const char *GetVMName() =0;
/** /**
* Begins a new compilation * @brief Begins a new compilation
* *
* @param plugin Pointer to a plugin structure. * @param plugin Pointer to a plugin structure.
* @return New compilation pointer. * @return New compilation pointer.
@ -406,7 +413,7 @@ namespace SourcePawn
virtual ICompilation *StartCompilation(sp_plugin_t *plugin) =0; virtual ICompilation *StartCompilation(sp_plugin_t *plugin) =0;
/** /**
* Sets a compilation option. * @brief Sets a compilation option.
* *
* @param co Pointer to a compilation. * @param co Pointer to a compilation.
* @param key Option key name. * @param key Option key name.
@ -416,7 +423,7 @@ namespace SourcePawn
virtual bool SetCompilationOption(ICompilation *co, const char *key, const char *val) =0; virtual bool SetCompilationOption(ICompilation *co, const char *key, const char *val) =0;
/** /**
* Finalizes a compilation into a new sp_context_t. * @brief Finalizes a compilation into a new sp_context_t.
* Note: This will free the ICompilation pointer. * Note: This will free the ICompilation pointer.
* *
* @param co Compilation pointer. * @param co Compilation pointer.
@ -426,28 +433,46 @@ namespace SourcePawn
virtual sp_context_t *CompileToContext(ICompilation *co, int *err) =0; virtual sp_context_t *CompileToContext(ICompilation *co, int *err) =0;
/** /**
* Aborts a compilation and frees the ICompilation pointer. * @brief Aborts a compilation and frees the ICompilation pointer.
* *
* @param co Compilation pointer. * @param co Compilation pointer.
*/ */
virtual void AbortCompilation(ICompilation *co) =0; virtual void AbortCompilation(ICompilation *co) =0;
/** /**
* Frees any internal variable usage on a context. * @brief Frees any internal variable usage on a context.
* *
* @param ctx Context structure pointer. * @param ctx Context structure pointer.
*/ */
virtual void FreeContext(sp_context_t *ctx) =0; virtual void FreeContext(sp_context_t *ctx) =0;
/** /**
* Calls the "execute" function on a context. * @brief Calls the "execute" function on a context.
* *
* @param ctx Executes a function in a context. * @param ctx Executes a function in a context.
* @param code_idx Index into the code section. * @param code_addr Index into the code section.
* @param result Pointer to store result in. * @param result Pointer to store result into.
* @return Error code (if any). * @return Error code (if any).
*/ */
virtual int ContextExecute(sp_context_t *ctx, uint32_t code_idx, cell_t *result) =0; virtual int ContextExecute(sp_context_t *ctx, uint32_t code_addr, cell_t *result) =0;
/**
* @brief Given a context and a code address, returns the index of the function.
*
* @param ctx Context to search.
* @param code_addr Index into the code section.
* @param result Pointer to store result into.
* @return True if code index is valid, false otherwise.
*/
virtual bool FunctionLookup(const sp_context_t *ctx, uint32_t code_addr, unsigned int *result) =0;
/**
* @brief Returns the number of functions defined in the context.
*
* @param ctx Context to search.
* @return Number of functions.
*/
virtual unsigned int FunctionCount(const sp_context_t *ctx) =0;
}; };
}; };

View File

@ -104,7 +104,7 @@ namespace SourcePawn
struct sp_context_s; struct sp_context_s;
typedef cell_t (*SPVM_NATIVE_FUNC)(struct sp_context_s *, cell_t *); typedef cell_t (*SPVM_NATIVE_FUNC)(struct sp_context_s *, const cell_t *);
/********************************************** /**********************************************
*** The following structures are bound to the VM/JIT. *** The following structures are bound to the VM/JIT.

View File

@ -233,6 +233,7 @@ inline void WriteOp_Proc(JitWriter *jit)
* Just in case, we guard this memory with INT3 to break into the debugger. * Just in case, we guard this memory with INT3 to break into the debugger.
*/ */
jitoffs_t cur_offs = jit->get_outputpos(); jitoffs_t cur_offs = jit->get_outputpos();
CompData *co = (CompData *)jit->data;
if (cur_offs % 4) if (cur_offs % 4)
{ {
cur_offs = 4 - (cur_offs % 4); cur_offs = 4 - (cur_offs % 4);
@ -240,11 +241,25 @@ inline void WriteOp_Proc(JitWriter *jit)
{ {
jit->write_ubyte(IA32_INT3); jit->write_ubyte(IA32_INT3);
} }
/* add this amt to the offset we relocated */ }
/* Write the info struct about this function */
jit->write_uint32(JIT_FUNCMAGIC);
jit->write_uint32(co->func_idx);
/* Now we have to backpatch our reloction offset! */
{
jitoffs_t offs = jit->get_inputpos() - sizeof(cell_t); jitoffs_t offs = jit->get_inputpos() - sizeof(cell_t);
jitcode_t rebase = ((CompData *)jit->data)->rebase; jitcode_t rebase = ((CompData *)jit->data)->rebase;
*(jitoffs_t *)((unsigned char *)rebase + offs) = jit->get_outputpos(); *(jitoffs_t *)((unsigned char *)rebase + offs) = jit->get_outputpos();
} }
/* Lastly, if we're writing, keep track of the function count */
if (jit->outbase)
{
co->func_idx++;
}
//push old frame on stack: //push old frame on stack:
//mov ecx, [esi+frm] //mov ecx, [esi+frm]
//mov [edi-4], ecx //mov [edi-4], ecx
@ -1756,7 +1771,7 @@ cell_t NativeCallback(sp_context_t *ctx, ucell_t native_idx, cell_t *params)
return native->pfn(ctx, params); return native->pfn(ctx, params);
} }
cell_t InvalidNative(sp_context_t *ctx, cell_t *params) cell_t InvalidNative(sp_context_t *ctx, const cell_t *params)
{ {
ctx->err = SP_ERROR_INVALID_NATIVE; ctx->err = SP_ERROR_INVALID_NATIVE;
@ -1877,6 +1892,7 @@ sp_context_t *JITX86::CompileToContext(ICompilation *co, int *err)
JitWriter writer; JitWriter writer;
JitWriter *jit = &writer; JitWriter *jit = &writer;
cell_t *endptr = (cell_t *)(end_cip); cell_t *endptr = (cell_t *)(end_cip);
uint32_t codemem = 0;
/* Initial code is written "blank," /* Initial code is written "blank,"
* so we can check the exact memory usage. * so we can check the exact memory usage.
@ -1957,8 +1973,8 @@ jit_rewind:
WriteErrorRoutines(data, jit); WriteErrorRoutines(data, jit);
/* the total codesize is now known! */ /* the total codesize is now known! */
uint32_t mem = writer.get_outputpos(); codemem = writer.get_outputpos();
writer.outbase = (jitcode_t)engine->ExecAlloc(mem); writer.outbase = (jitcode_t)engine->ExecAlloc(codemem);
writer.outptr = writer.outbase; writer.outptr = writer.outbase;
/* go back for third pass */ /* go back for third pass */
goto jit_rewind; goto jit_rewind;
@ -2100,6 +2116,11 @@ jit_rewind:
trk->pCur = trk->pBase; trk->pCur = trk->pBase;
trk->size = 1024 / sizeof(cell_t); trk->size = 1024 / sizeof(cell_t);
functracker_t *fnc = new functracker_t;
ctx->vm[JITVARS_FUNCINFO] = fnc;
fnc->code_size = codemem;
fnc->num_functions = data->func_idx;
/* clean up relocation+compilation memory */ /* clean up relocation+compilation memory */
AbortCompilation(co); AbortCompilation(co);
@ -2172,3 +2193,38 @@ bool JITX86::SetCompilationOption(ICompilation *co, const char *key, const char
return false; return false;
} }
unsigned int JITX86::GetAPIVersion()
{
return SOURCEPAWN_VM_API_VERSION;
}
bool JITX86::FunctionLookup(const sp_context_t *ctx, uint32_t code_addr, unsigned int *result)
{
functracker_t *fnc = (functracker_t *)ctx->vm[JITVARS_FUNCINFO];
if (code_addr >= fnc->code_size)
{
return false;
}
funcinfo_t *f = (funcinfo_t *)((char *)ctx->codebase + code_addr - sizeof(funcinfo_t));
if (f->magic != JIT_FUNCMAGIC || f->index >= fnc->num_functions)
{
return false;
}
if (result)
{
*result = f->index;
}
return true;
}
unsigned int JITX86::FunctionCount(const sp_context_t *ctx)
{
functracker_t *fnc = (functracker_t *)ctx->vm[JITVARS_FUNCINFO];
return fnc->num_functions;
}

View File

@ -9,9 +9,11 @@ using namespace SourcePawn;
#define JIT_INLINE_ERRORCHECKS (1<<0) #define JIT_INLINE_ERRORCHECKS (1<<0)
#define JIT_INLINE_NATIVES (1<<1) #define JIT_INLINE_NATIVES (1<<1)
#define STACK_MARGIN 64 //8 parameters of safety, I guess #define STACK_MARGIN 64 //8 parameters of safety, I guess
#define JIT_FUNCMAGIC 0x214D4148 //magic function offset
#define JITVARS_TRACKER 0 //important: don't change this to avoid trouble #define JITVARS_TRACKER 0 //important: don't change this to avoid trouble
#define JITVARS_FUNCINFO 1 //important: don't change this aWOAWOGJQG I LIKE HAM
typedef struct tracker_s typedef struct tracker_s
{ {
@ -20,12 +22,24 @@ typedef struct tracker_s
ucell_t *pCur; ucell_t *pCur;
} tracker_t; } tracker_t;
typedef struct funcinfo_s
{
unsigned int magic;
unsigned int index;
} funcinfo_t;
typedef struct functracker_s
{
unsigned int num_functions;
unsigned int code_size;
} functracker_t;
class CompData : public ICompilation class CompData : public ICompilation
{ {
public: public:
CompData() : plugin(NULL), CompData() : plugin(NULL),
debug(false), inline_level(0), rebase(NULL), debug(false), inline_level(0), rebase(NULL),
error_set(SP_ERROR_NONE) error_set(SP_ERROR_NONE), func_idx(0)
{ {
}; };
public: public:
@ -49,6 +63,7 @@ public:
jitoffs_t jit_extern_error; /* returning generic error */ jitoffs_t jit_extern_error; /* returning generic error */
jitoffs_t jit_sysreq_c; /* old version! */ jitoffs_t jit_sysreq_c; /* old version! */
uint32_t codesize; /* total codesize */ uint32_t codesize; /* total codesize */
unsigned int func_idx; /* current function index */
int inline_level; /* inline optimization level */ int inline_level; /* inline optimization level */
int error_set; /* error code to halt process */ int error_set; /* error code to halt process */
bool debug; /* whether to compile debug mode */ bool debug; /* whether to compile debug mode */
@ -64,6 +79,9 @@ public:
void AbortCompilation(ICompilation *co); void AbortCompilation(ICompilation *co);
void FreeContext(sp_context_t *ctx); void FreeContext(sp_context_t *ctx);
int ContextExecute(sp_context_t *ctx, uint32_t code_idx, cell_t *result); int ContextExecute(sp_context_t *ctx, uint32_t code_idx, cell_t *result);
unsigned int GetAPIVersion();
bool FunctionLookup(const sp_context_t *ctx, uint32_t code_addr, unsigned int *result);
unsigned int FunctionCount(const sp_context_t *ctx);
}; };
cell_t NativeCallback(sp_context_t *ctx, ucell_t native_idx, cell_t *params); cell_t NativeCallback(sp_context_t *ctx, ucell_t native_idx, cell_t *params);