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:
parent
50e5307d32
commit
438ccf39a0
@ -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
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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.
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user