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_sourcefiletable();
|
||||
delete_dbgstringtable();
|
||||
funcenums_free();
|
||||
pstructs_free();
|
||||
#if !defined NO_DEFINE
|
||||
delete_substtable();
|
||||
#endif
|
||||
|
@ -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;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user