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_sourcefiletable();
delete_dbgstringtable();
funcenums_free();
pstructs_free();
#if !defined NO_DEFINE
delete_substtable();
#endif

View File

@ -4,6 +4,8 @@
#include <stdio.h>
#include "sp_vm_types.h"
#define SOURCEPAWN_VM_API_VERSION 1
namespace SourcePawn
{
class IVirtualMachine;
@ -393,12 +395,17 @@ namespace SourcePawn
{
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;
/**
* Begins a new compilation
* @brief Begins a new compilation
*
* @param plugin Pointer to a plugin structure.
* @return New compilation pointer.
@ -406,7 +413,7 @@ namespace SourcePawn
virtual ICompilation *StartCompilation(sp_plugin_t *plugin) =0;
/**
* Sets a compilation option.
* @brief Sets a compilation option.
*
* @param co Pointer to a compilation.
* @param key Option key name.
@ -416,7 +423,7 @@ namespace SourcePawn
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.
*
* @param co Compilation pointer.
@ -426,28 +433,46 @@ namespace SourcePawn
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.
*/
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.
*/
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 code_idx Index into the code section.
* @param result Pointer to store result in.
* @param code_addr Index into the code section.
* @param result Pointer to store result into.
* @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;
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.

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.
*/
jitoffs_t cur_offs = jit->get_outputpos();
CompData *co = (CompData *)jit->data;
if (cur_offs % 4)
{
cur_offs = 4 - (cur_offs % 4);
@ -240,11 +241,25 @@ inline void WriteOp_Proc(JitWriter *jit)
{
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);
jitcode_t rebase = ((CompData *)jit->data)->rebase;
*(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:
//mov ecx, [esi+frm]
//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);
}
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;
@ -1877,6 +1892,7 @@ sp_context_t *JITX86::CompileToContext(ICompilation *co, int *err)
JitWriter writer;
JitWriter *jit = &writer;
cell_t *endptr = (cell_t *)(end_cip);
uint32_t codemem = 0;
/* Initial code is written "blank,"
* so we can check the exact memory usage.
@ -1957,8 +1973,8 @@ jit_rewind:
WriteErrorRoutines(data, jit);
/* the total codesize is now known! */
uint32_t mem = writer.get_outputpos();
writer.outbase = (jitcode_t)engine->ExecAlloc(mem);
codemem = writer.get_outputpos();
writer.outbase = (jitcode_t)engine->ExecAlloc(codemem);
writer.outptr = writer.outbase;
/* go back for third pass */
goto jit_rewind;
@ -2100,6 +2116,11 @@ jit_rewind:
trk->pCur = trk->pBase;
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 */
AbortCompilation(co);
@ -2172,3 +2193,38 @@ bool JITX86::SetCompilationOption(ICompilation *co, const char *key, const char
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_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_FUNCINFO 1 //important: don't change this aWOAWOGJQG I LIKE HAM
typedef struct tracker_s
{
@ -20,12 +22,24 @@ typedef struct tracker_s
ucell_t *pCur;
} 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
{
public:
CompData() : plugin(NULL),
debug(false), inline_level(0), rebase(NULL),
error_set(SP_ERROR_NONE)
error_set(SP_ERROR_NONE), func_idx(0)
{
};
public:
@ -49,6 +63,7 @@ public:
jitoffs_t jit_extern_error; /* returning generic error */
jitoffs_t jit_sysreq_c; /* old version! */
uint32_t codesize; /* total codesize */
unsigned int func_idx; /* current function index */
int inline_level; /* inline optimization level */
int error_set; /* error code to halt process */
bool debug; /* whether to compile debug mode */
@ -64,6 +79,9 @@ public:
void AbortCompilation(ICompilation *co);
void FreeContext(sp_context_t *ctx);
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);