refac-jit is almost done i think, next comes getting core compatible.

--HG--
branch : refac-jit
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/refac-jit%402373
This commit is contained in:
David Anderson 2008-07-07 04:56:29 +00:00
parent 307adb34ab
commit 3f38171d8c
17 changed files with 1574 additions and 1397 deletions

View File

@ -0,0 +1,333 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "BaseRuntime.h"
#include "sp_vm_engine.h"
#include "x86/jit_x86.h"
#include "sp_vm_basecontext.h"
using namespace SourcePawn;
int GlobalDebugBreak(BaseContext *ctx, uint32_t frm, uint32_t cip)
{
g_engine1.RunTracer(ctx, frm, cip);
return SP_ERROR_NONE;
}
BaseRuntime::BaseRuntime(sp_plugin_t *pl) : m_Debug(pl), m_pPlugin(pl)
{
m_pCtx = new BaseContext(this);
if (m_pPlugin->info.publics_num > 0)
{
m_PubFuncs = new CFunction *[m_pPlugin->info.publics_num];
memset(m_PubFuncs, 0, sizeof(CFunction *) * m_pPlugin->info.publics_num);
}
else
{
m_PubFuncs = NULL;
}
}
BaseRuntime::~BaseRuntime()
{
for (uint32_t i = 0; i < m_pPlugin->info.publics_num; i++)
{
delete m_PubFuncs[i];
m_PubFuncs[i] = NULL;
}
delete [] m_PubFuncs;
ClearCompile();
free(m_pPlugin->base);
delete [] m_pPlugin->memory;
delete m_pPlugin;
}
void BaseRuntime::ClearCompile()
{
g_Jit1.FreeContextVars(m_pCtx->GetContext());
g_Jit1.FreePluginVars(m_pPlugin);
}
int BaseRuntime::FindNativeByName(const char *name, uint32_t *index)
{
int high;
high = m_pPlugin->info.natives_num - 1;
for (uint32_t i=0; i<m_pPlugin->info.natives_num; i++)
{
if (strcmp(m_pPlugin->natives[i].name, name) == 0)
{
if (index)
{
*index = i;
}
return SP_ERROR_NONE;
}
}
return SP_ERROR_NOT_FOUND;
}
int BaseRuntime::GetNativeByIndex(uint32_t index, sp_native_t **native)
{
if (index >= m_pPlugin->info.natives_num)
{
return SP_ERROR_INDEX;
}
if (native)
{
*native = &(m_pPlugin->natives[index]);
}
return SP_ERROR_NONE;
}
uint32_t BaseRuntime::GetNativesNum()
{
return m_pPlugin->info.natives_num;
}
int BaseRuntime::FindPublicByName(const char *name, uint32_t *index)
{
int diff, high, low;
uint32_t mid;
high = m_pPlugin->info.publics_num - 1;
low = 0;
while (low <= high)
{
mid = (low + high) / 2;
diff = strcmp(m_pPlugin->publics[mid].name, name);
if (diff == 0)
{
if (index)
{
*index = mid;
}
return SP_ERROR_NONE;
} else if (diff < 0) {
low = mid + 1;
} else {
high = mid - 1;
}
}
return SP_ERROR_NOT_FOUND;
}
int BaseRuntime::GetPublicByIndex(uint32_t index, sp_public_t **pblic)
{
if (index >= m_pPlugin->info.publics_num)
{
return SP_ERROR_INDEX;
}
if (pblic)
{
*pblic = &(m_pPlugin->publics[index]);
}
return SP_ERROR_NONE;
}
uint32_t BaseRuntime::GetPublicsNum()
{
return m_pPlugin->info.publics_num;
}
int BaseRuntime::GetPubvarByIndex(uint32_t index, sp_pubvar_t **pubvar)
{
if (index >= m_pPlugin->info.pubvars_num)
{
return SP_ERROR_INDEX;
}
if (pubvar)
{
*pubvar = &(m_pPlugin->pubvars[index]);
}
return SP_ERROR_NONE;
}
int BaseRuntime::FindPubvarByName(const char *name, uint32_t *index)
{
int diff, high, low;
uint32_t mid;
high = m_pPlugin->info.pubvars_num - 1;
low = 0;
while (low <= high)
{
mid = (low + high) / 2;
diff = strcmp(m_pPlugin->pubvars[mid].name, name);
if (diff == 0)
{
if (index)
{
*index = mid;
}
return SP_ERROR_NONE;
} else if (diff < 0) {
low = mid + 1;
} else {
high = mid - 1;
}
}
return SP_ERROR_NOT_FOUND;
}
int BaseRuntime::GetPubvarAddrs(uint32_t index, cell_t *local_addr, cell_t **phys_addr)
{
if (index >= m_pPlugin->info.pubvars_num)
{
return SP_ERROR_INDEX;
}
*local_addr = m_pPlugin->info.pubvars[index].address;
*phys_addr = m_pPlugin->pubvars[index].offs;
return SP_ERROR_NONE;
}
uint32_t BaseRuntime::GetPubVarsNum()
{
return m_pPlugin->info.pubvars_num;
}
IPluginContext *BaseRuntime::GetDefaultContext()
{
return m_pCtx;
}
IPluginDebugInfo *BaseRuntime::GetDebugInfo()
{
if (!IsDebugging())
{
return NULL;
}
return &m_Debug;
}
void BaseRuntime::RefreshFunctionCache()
{
if (m_PubFuncs != NULL)
{
sp_public_t *pub;
for (uint32_t i = 0; i < m_pPlugin->info.publics_num; i++)
{
if (m_PubFuncs[i] == NULL)
{
continue;
}
if (GetPublicByIndex(i, &pub) != SP_ERROR_NONE)
{
continue;
}
m_PubFuncs[i]->Set(pub->code_offs, this, pub->funcid, i);
}
}
}
IPluginFunction *BaseRuntime::GetFunctionById(funcid_t func_id)
{
CFunction *pFunc = NULL;
if (func_id & 1)
{
func_id >>= 1;
if (func_id >= m_pPlugin->info.publics_num)
{
return NULL;
}
pFunc = m_PubFuncs[func_id];
if (!pFunc)
{
m_PubFuncs[func_id] = new CFunction(m_pPlugin->publics[func_id].code_offs,
this,
m_pPlugin->publics[func_id].funcid,
func_id);
pFunc = m_PubFuncs[func_id];
}
else if (pFunc->IsInvalidated())
{
pFunc->Set(m_pPlugin->publics[func_id].code_offs,
this,
m_pPlugin->publics[func_id].funcid,
func_id);
}
}
return pFunc;
}
IPluginFunction *BaseRuntime::GetFunctionByName(const char *public_name)
{
uint32_t index;
if (FindPublicByName(public_name, &index) != SP_ERROR_NONE)
{
return NULL;
}
CFunction *pFunc = m_PubFuncs[index];
if (!pFunc)
{
sp_public_t *pub = NULL;
GetPublicByIndex(index, &pub);
if (pub)
{
m_PubFuncs[index] = new CFunction(pub->code_offs, this, pub->funcid, index);
}
pFunc = m_PubFuncs[index];
}
else if (pFunc->IsInvalidated())
{
sp_public_t *pub = NULL;
GetPublicByIndex(index, &pub);
if (pub)
{
pFunc->Set(pub->code_offs, this, pub->funcid, index);
}
else
{
pFunc = NULL;
}
}
return pFunc;
}
bool BaseRuntime::IsDebugging()
{
return ((m_pPlugin->run_flags & SPFLAG_PLUGIN_DEBUG) == SPFLAG_PLUGIN_DEBUG);
}
void BaseRuntime::SetPauseState(bool paused)
{
if (paused)
{
m_pPlugin->run_flags |= SPFLAG_PLUGIN_PAUSED;
}
else
{
m_pPlugin->run_flags &= ~SPFLAG_PLUGIN_PAUSED;
}
}
bool BaseRuntime::IsPaused()
{
return ((m_pPlugin->run_flags & SPFLAG_PLUGIN_PAUSED) == SPFLAG_PLUGIN_PAUSED);
}

View File

@ -0,0 +1,57 @@
#ifndef _INCLUDE_SOURCEPAWN_JIT_RUNTIME_H_
#define _INCLUDE_SOURCEPAWN_JIT_RUNTIME_H_
#include <sp_vm_api.h>
#include "jit_shared.h"
#include "sp_vm_function.h"
class BaseContext;
class DebugInfo : public IPluginDebugInfo
{
public:
DebugInfo(sp_plugin_t *plugin);
public:
int LookupFile(ucell_t addr, const char **filename);
int LookupFunction(ucell_t addr, const char **name);
int LookupLine(ucell_t addr, uint32_t *line);
private:
sp_plugin_t *m_pPlugin;
};
/* Jit wants fast access to this so we expose things as public */
class BaseRuntime : public SourcePawn::IPluginRuntime
{
public:
BaseRuntime(sp_plugin_t *pl);
~BaseRuntime();
public:
virtual bool IsDebugging();
virtual IPluginDebugInfo *GetDebugInfo();
virtual int FindNativeByName(const char *name, uint32_t *index);
virtual int GetNativeByIndex(uint32_t index, sp_native_t **native);
virtual uint32_t GetNativesNum();
virtual int FindPublicByName(const char *name, uint32_t *index);
virtual int GetPublicByIndex(uint32_t index, sp_public_t **publicptr);
virtual uint32_t GetPublicsNum();
virtual int GetPubvarByIndex(uint32_t index, sp_pubvar_t **pubvar);
virtual int FindPubvarByName(const char *name, uint32_t *index);
virtual int GetPubvarAddrs(uint32_t index, cell_t *local_addr, cell_t **phys_addr);
virtual uint32_t GetPubVarsNum();
virtual IPluginFunction *GetFunctionByName(const char *public_name);
virtual IPluginFunction *GetFunctionById(funcid_t func_id);
virtual IPluginContext *GetDefaultContext();
virtual int ApplyCompilationOptions(ICompilation *co);
virtual void SetPauseState(bool paused);
virtual bool IsPaused();
private:
void ClearCompile();
void RefreshFunctionCache();
public:
DebugInfo m_Debug;
sp_plugin_t *m_pPlugin;
BaseContext *m_pCtx;
CFunction **m_PubFuncs;
};
#endif //_INCLUDE_SOURCEPAWN_JIT_RUNTIME_H_

View File

@ -31,44 +31,21 @@
#include <sp_vm_api.h>
#include <malloc.h>
#include "jit_x86.h"
#include "x86/jit_x86.h"
#include "dll_exports.h"
#include "sp_vm_engine.h"
#include "engine2.h"
SourcePawn::ISourcePawnEngine *engine = NULL;
JITX86 g_jit;
SourcePawnEngine2 g_engine2;
EXPORTFUNC int GiveEnginePointer2(SourcePawn::ISourcePawnEngine *engine_p, unsigned int api_version)
EXPORTFUNC ISourcePawnEngine *GetSourcePawnEngine1()
{
engine = engine_p;
if (api_version > SOURCEPAWN_ENGINE_API_VERSION || api_version < 2)
{
return SP_ERROR_PARAM;
}
return SP_ERROR_NONE;
return &g_engine1;
}
EXPORTFUNC unsigned int GetExportCount()
EXPORTFUNC ISourcePawnEngine2 *GetSourcePawnEngine2()
{
return 1;
}
EXPORTFUNC SourcePawn::IVirtualMachine *GetExport(unsigned int exportnum)
{
/* Don't return anything if we're not initialized yet */
if (!engine)
{
return NULL;
}
/* We only have one export - 0 */
if (exportnum)
{
return NULL;
}
return &g_jit;
return &g_engine2;
}
#if defined __linux__

271
sourcepawn/jit/engine2.cpp Normal file
View File

@ -0,0 +1,271 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "engine2.h"
#include "x86/jit_x86.h"
#include "jit_version.h"
#include "zlib/zlib.h"
#include "BaseRuntime.h"
#include "sp_vm_engine.h"
using namespace SourcePawn;
SourcePawnEngine2::SourcePawnEngine2()
{
m_Profiler = NULL;
}
sp_plugin_t *_ReadPlugin(sp_file_hdr_t *hdr, uint8_t *base, sp_plugin_t *plugin, int *err)
{
char *nameptr;
uint8_t sectnum = 0;
sp_file_section_t *secptr = (sp_file_section_t *)(base + sizeof(sp_file_hdr_t));
memset(plugin, 0, sizeof(sp_plugin_t));
plugin->base = base;
while (sectnum < hdr->sections)
{
nameptr = (char *)(base + hdr->stringtab + secptr->nameoffs);
if (!(plugin->pcode) && !strcmp(nameptr, ".code"))
{
sp_file_code_t *cod = (sp_file_code_t *)(base + secptr->dataoffs);
plugin->pcode = base + secptr->dataoffs + cod->code;
plugin->pcode_size = cod->codesize;
plugin->flags = cod->flags;
}
else if (!(plugin->data) && !strcmp(nameptr, ".data"))
{
sp_file_data_t *dat = (sp_file_data_t *)(base + secptr->dataoffs);
plugin->data = base + secptr->dataoffs + dat->data;
plugin->data_size = dat->datasize;
plugin->mem_size = dat->memsize;
plugin->memory = new uint8_t[plugin->mem_size];
memcpy(plugin->memory, plugin->data, plugin->data_size);
}
else if (!(plugin->info.publics) && !strcmp(nameptr, ".publics"))
{
plugin->info.publics_num = secptr->size / sizeof(sp_file_publics_t);
plugin->info.publics = (sp_file_publics_t *)(base + secptr->dataoffs);
}
else if (!(plugin->info.pubvars) && !strcmp(nameptr, ".pubvars"))
{
plugin->info.pubvars_num = secptr->size / sizeof(sp_file_pubvars_t);
plugin->info.pubvars = (sp_file_pubvars_t *)(base + secptr->dataoffs);
}
else if (!(plugin->info.natives) && !strcmp(nameptr, ".natives"))
{
plugin->info.natives_num = secptr->size / sizeof(sp_file_natives_t);
plugin->info.natives = (sp_file_natives_t *)(base + secptr->dataoffs);
}
else if (!(plugin->info.stringbase) && !strcmp(nameptr, ".names"))
{
plugin->info.stringbase = (const char *)(base + secptr->dataoffs);
}
else if (!(plugin->debug.files) && !strcmp(nameptr, ".dbg.files"))
{
plugin->debug.files = (sp_fdbg_file_t *)(base + secptr->dataoffs);
}
else if (!(plugin->debug.lines) && !strcmp(nameptr, ".dbg.lines"))
{
plugin->debug.lines = (sp_fdbg_line_t *)(base + secptr->dataoffs);
}
else if (!(plugin->debug.symbols) && !strcmp(nameptr, ".dbg.symbols"))
{
plugin->debug.symbols = (sp_fdbg_symbol_t *)(base + secptr->dataoffs);
}
else if (!(plugin->debug.lines_num) && !strcmp(nameptr, ".dbg.info"))
{
sp_fdbg_info_t *inf = (sp_fdbg_info_t *)(base + secptr->dataoffs);
plugin->debug.files_num = inf->num_files;
plugin->debug.lines_num = inf->num_lines;
plugin->debug.syms_num = inf->num_syms;
}
else if (!(plugin->debug.stringbase) && !strcmp(nameptr, ".dbg.strings"))
{
plugin->debug.stringbase = (const char *)(base + secptr->dataoffs);
}
secptr++;
sectnum++;
}
if (!(plugin->pcode) || !(plugin->data) || !(plugin->info.stringbase))
{
goto return_error;
}
if ((plugin->flags & SP_FLAG_DEBUG) && (!(plugin->debug.files) || !(plugin->debug.lines) || !(plugin->debug.symbols)))
{
goto return_error;
}
if (err)
{
*err = SP_ERROR_NONE;
}
return plugin;
return_error:
if (err)
{
*err = SP_ERROR_FILE_FORMAT;
}
return NULL;
}
IPluginRuntime *SourcePawnEngine2::LoadPlugin(ICompilation *co, const char *file, int *err)
{
sp_file_hdr_t hdr;
sp_plugin_t *plugin;
uint8_t *base;
int z_result;
int error;
FILE *fp = fopen(file, "rb");
if (!fp)
{
error = SP_ERROR_NOT_FOUND;
goto return_error;
}
/* Rewind for safety */
fread(&hdr, sizeof(sp_file_hdr_t), 1, fp);
if (hdr.magic != SPFILE_MAGIC)
{
error = SP_ERROR_FILE_FORMAT;
goto return_error;
}
switch (hdr.compression)
{
case SPFILE_COMPRESSION_GZ:
{
uint32_t uncompsize = hdr.imagesize - hdr.dataoffs;
uint32_t compsize = hdr.disksize - hdr.dataoffs;
uint32_t sectsize = hdr.dataoffs - sizeof(sp_file_hdr_t);
uLongf destlen = uncompsize;
char *tempbuf = (char *)malloc(compsize);
void *uncompdata = malloc(uncompsize);
void *sectheader = malloc(sectsize);
fread(sectheader, sectsize, 1, fp);
fread(tempbuf, compsize, 1, fp);
z_result = uncompress((Bytef *)uncompdata, &destlen, (Bytef *)tempbuf, compsize);
free(tempbuf);
if (z_result != Z_OK)
{
free(sectheader);
free(uncompdata);
error = SP_ERROR_DECOMPRESSOR;
goto return_error;
}
base = (uint8_t *)malloc(hdr.imagesize);
memcpy(base, &hdr, sizeof(sp_file_hdr_t));
memcpy(base + sizeof(sp_file_hdr_t), sectheader, sectsize);
free(sectheader);
memcpy(base + hdr.dataoffs, uncompdata, uncompsize);
free(uncompdata);
break;
}
case SPFILE_COMPRESSION_NONE:
{
base = (uint8_t *)malloc(hdr.imagesize);
rewind(fp);
fread(base, hdr.imagesize, 1, fp);
break;
}
default:
{
error = SP_ERROR_DECOMPRESSOR;
goto return_error;
}
}
plugin = new sp_plugin_t;
memset(plugin, 0, sizeof(sp_plugin_t));
if (!_ReadPlugin(&hdr, base, plugin, err))
{
delete plugin;
free(base);
return NULL;
}
BaseRuntime *pRuntime = new BaseRuntime(plugin);
if (co == NULL)
{
co = g_Jit1.StartCompilation(pRuntime);
}
*err = pRuntime->ApplyCompilationOptions(co);
if (*err != SP_ERROR_NONE)
{
delete pRuntime;
return NULL;
}
return pRuntime;
return_error:
*err = error;
return NULL;
}
SPVM_NATIVE_FUNC SourcePawnEngine2::CreateFakeNative(SPVM_FAKENATIVE_FUNC callback, void *pData)
{
return g_Jit1.CreateFakeNative(callback, pData);
}
void SourcePawnEngine2::DestroyFakeNative(SPVM_NATIVE_FUNC func)
{
g_Jit1.DestroyFakeNative(func);
}
const char *SourcePawnEngine2::GetEngineName()
{
return "SourcePawn 1.1, jit-x86";
}
const char *SourcePawnEngine2::GetVersionString()
{
return SVN_FULL_VERSION;
}
IProfiler *SourcePawnEngine2::GetProfiler()
{
return m_Profiler;
}
void SourcePawnEngine2::SetProfiler(IProfiler *profiler)
{
m_Profiler = profiler;
}
IDebugListener *SourcePawnEngine2::SetDebugListener(IDebugListener *listener)
{
return g_engine1.SetDebugListener(listener);
}
unsigned int SourcePawnEngine2::GetAPIVersion()
{
return SOURCEPAWN_ENGINE2_API_VERSION;
}
ICompilation *SourcePawnEngine2::StartCompilation()
{
return g_Jit1.StartCompilation();
}

34
sourcepawn/jit/engine2.h Normal file
View File

@ -0,0 +1,34 @@
#ifndef _INCLUDE_SOURCEPAWN_ENGINE_2_H_
#define _INCLUDE_SOURCEPAWN_ENGINE_2_H_
#include <sp_vm_api.h>
namespace SourcePawn
{
/**
* @brief Outlines the interface a Virtual Machine (JIT) must expose
*/
class SourcePawnEngine2 : public ISourcePawnEngine2
{
public:
SourcePawnEngine2();
public:
unsigned int GetAPIVersion();
const char *GetEngineName();
const char *GetVersionString();
IPluginRuntime *LoadPlugin(ICompilation *co, const char *file, int *err);
SPVM_NATIVE_FUNC CreateFakeNative(SPVM_FAKENATIVE_FUNC callback, void *pData);
void DestroyFakeNative(SPVM_NATIVE_FUNC func);
IDebugListener *SetDebugListener(IDebugListener *listener);
void SetProfiler(IProfiler *profiler);
ICompilation *StartCompilation();
public:
IProfiler *GetProfiler();
private:
IProfiler *m_Profiler;
};
}
extern SourcePawn::SourcePawnEngine2 g_engine2;
#endif //_INCLUDE_SOURCEPAWN_ENGINE_2_H_

View File

@ -0,0 +1,92 @@
#ifndef _INCLUDE_SOURCEPAWN_JIT_SHARED_H_
#define _INCLUDE_SOURCEPAWN_JIT_SHARED_H_
#include <sp_vm_api.h>
using namespace SourcePawn;
/**
* @brief Information about the core plugin tables. These may or may not be present!
*/
typedef struct sp_plugin_infotab_s
{
const char *stringbase; /**< base of string table */
uint32_t publics_num; /**< number of publics */
sp_file_publics_t *publics; /**< public table */
uint32_t natives_num; /**< number of natives */
sp_file_natives_t *natives; /**< native table */
uint32_t pubvars_num; /**< number of pubvars */
sp_file_pubvars_t *pubvars; /**< pubvars table */
} sp_plugin_infotab_t;
/**
* @brief Information about the plugin's debug tables. These are all present if one is present.
*/
typedef struct sp_plugin_debug_s
{
const char *stringbase; /**< base of string table */
uint32_t files_num; /**< number of files */
sp_fdbg_file_t *files; /**< files table */
uint32_t lines_num; /**< number of lines */
sp_fdbg_line_t *lines; /**< lines table */
uint32_t syms_num; /**< number of symbols */
sp_fdbg_symbol_t *symbols; /**< symbol table */
} sp_plugin_debug_t;
class BaseContext;
/**
* Breaks into a debugger
* Params:
* [0] - plugin context
* [1] - frm
* [2] - cip
*/
typedef int (*SPVM_DEBUGBREAK)(BaseContext *, uint32_t, uint32_t);
/**
* @brief The rebased memory format of a plugin. This differs from the on-disk structure
* to ensure that the format is properly read.
*/
namespace SourcePawn
{
typedef struct sp_plugin_s
{
uint8_t *base; /**< Base of memory for this plugin. */
uint8_t *pcode; /**< P-Code of plugin */
uint32_t pcode_size; /**< Size of p-code */
uint8_t *data; /**< Data/memory layout */
uint32_t data_size; /**< Size of data */
uint32_t mem_size; /**< Required memory space */
uint16_t flags; /**< Code flags */
sp_plugin_infotab_t info; /**< Base info table */
sp_plugin_debug_t debug; /**< Debug info table */
void *codebase; /**< Base of generated code and memory */
SPVM_DEBUGBREAK dbreak; /**< Debug break function */
uint8_t *memory; /**< Data chunk */
sp_public_t *publics; /**< Public functions table */
sp_pubvar_t *pubvars; /**< Public variables table */
sp_native_t *natives; /**< Natives table */
sp_debug_file_t *files; /**< Files */
sp_debug_line_t *lines; /**< Lines */
sp_debug_symbol_t *symbols; /**< Symbols */
IProfiler *profiler; /**< Pointer to IProfiler */
uint32_t prof_flags; /**< Profiling flags */
uint32_t run_flags; /**< Runtime flags */
} sp_plugin_t;
}
typedef struct sp_context_s
{
cell_t hp; /**< Heap pointer */
cell_t sp; /**< Stack pointer */
cell_t frm; /**< Frame pointer */
int32_t n_err; /**< Error code set by a native */
uint32_t n_idx; /**< Current native index being executed */
void * vm[8]; /**< VM-specific pointers */
} sp_context_t;
#define SPFLAG_PLUGIN_DEBUG (1<<0)
#define SPFLAG_PLUGIN_PAUSED (1<<1)
#endif //_INCLUDE_SOURCEPAWN_JIT_SHARED_H_

View File

@ -40,7 +40,7 @@
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\..\..\public\jit;..\..\..\..\public\jit\x86;..\..\..\..\public\sourcepawn"
AdditionalIncludeDirectories="..\..\..\public\jit;..\..\..\public\jit\x86;..\..\..\public\sourcepawn"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;JITX86_EXPORTS;_CRT_SECURE_NO_DEPRECATE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
@ -185,24 +185,44 @@
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath="..\BaseRuntime.cpp"
>
</File>
<File
RelativePath="..\dll_exports.cpp"
>
</File>
<File
RelativePath="..\engine2.cpp"
>
</File>
<File
RelativePath="..\x86\jit_x86.cpp"
>
</File>
<File
RelativePath="..\x86\opcode_helpers.cpp"
>
</File>
<File
RelativePath="..\sp_vm_basecontext.cpp"
>
</File>
<File
RelativePath="..\sp_vm_engine.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
AdditionalIncludeDirectories="&quot;$(SOURCEMM16)\sourcehook&quot;"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\jit_x86.cpp"
>
</File>
<File
RelativePath="..\opcode_helpers.cpp"
RelativePath="..\sp_vm_function.cpp"
>
</File>
</Filter>
@ -211,12 +231,20 @@
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath="..\BaseRuntime.h"
>
</File>
<File
RelativePath="..\dll_exports.h"
>
</File>
<File
RelativePath="..\..\..\..\public\jit\jit_helpers.h"
RelativePath="..\engine2.h"
>
</File>
<File
RelativePath="..\jit_shared.h"
>
</File>
<File
@ -224,19 +252,23 @@
>
</File>
<File
RelativePath="..\jit_x86.h"
RelativePath="..\x86\jit_x86.h"
>
</File>
<File
RelativePath="..\opcode_helpers.h"
RelativePath="..\x86\opcode_helpers.h"
>
</File>
<File
RelativePath="..\ungen_opcodes.h"
RelativePath="..\sp_vm_basecontext.h"
>
</File>
<File
RelativePath="..\..\..\..\public\jit\x86\x86_macros.h"
RelativePath="..\sp_vm_engine.h"
>
</File>
<File
RelativePath="..\sp_vm_function.h"
>
</File>
</Filter>
@ -245,18 +277,6 @@
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
<File
RelativePath="..\jit_version.tpl"
>
</File>
<File
RelativePath="..\opcode_switch.inc"
>
</File>
<File
RelativePath="..\ungen_opcode_switch.inc"
>
</File>
<File
RelativePath="..\version.rc"
>
@ -266,27 +286,75 @@
Name="SDK"
>
<File
RelativePath="..\..\jit_helpers.h"
RelativePath="..\..\..\public\sourcepawn\sp_file_headers.h"
>
</File>
<File
RelativePath="..\..\..\..\public\sourcepawn\sp_file_headers.h"
RelativePath="..\..\..\public\sourcepawn\sp_typeutil.h"
>
</File>
<File
RelativePath="..\..\..\..\public\sourcepawn\sp_typeutil.h"
RelativePath="..\..\..\public\sourcepawn\sp_vm_api.h"
>
</File>
<File
RelativePath="..\..\..\..\public\sourcepawn\sp_vm_api.h"
RelativePath="..\..\..\public\sourcepawn\sp_vm_base.h"
>
</File>
<File
RelativePath="..\..\..\..\public\sourcepawn\sp_vm_base.h"
RelativePath="..\..\..\public\sourcepawn\sp_vm_types.h"
>
</File>
</Filter>
<Filter
Name="zlib"
>
<File
RelativePath="..\zlib\adler32.c"
>
</File>
<File
RelativePath="..\..\..\..\public\sourcepawn\sp_vm_types.h"
RelativePath="..\zlib\compress.c"
>
</File>
<File
RelativePath="..\zlib\crc32.c"
>
</File>
<File
RelativePath="..\zlib\deflate.c"
>
</File>
<File
RelativePath="..\zlib\gzio.c"
>
</File>
<File
RelativePath="..\zlib\infback.c"
>
</File>
<File
RelativePath="..\zlib\inffast.c"
>
</File>
<File
RelativePath="..\zlib\inflate.c"
>
</File>
<File
RelativePath="..\zlib\inftrees.c"
>
</File>
<File
RelativePath="..\zlib\trees.c"
>
</File>
<File
RelativePath="..\zlib\uncompr.c"
>
</File>
<File
RelativePath="..\zlib\zutil.c"
>
</File>
</Filter>

File diff suppressed because it is too large Load Diff

View File

@ -34,91 +34,75 @@
#include "sp_vm_api.h"
#include "sp_vm_function.h"
#include "BaseRuntime.h"
#include "jit_shared.h"
/**
* :TODO: Make functions allocate as a lump instead of individual allocations!
*/
extern IProfiler *sm_profiler;
namespace SourcePawn
class BaseContext : public IPluginContext
{
class BaseContext :
public IPluginContext,
public IPluginDebugInfo
{
public:
BaseContext(sp_context_t *ctx);
~BaseContext();
public: //IPluginContext
IVirtualMachine *GetVirtualMachine();
sp_context_t *GetContext();
bool IsDebugging();
int SetDebugBreak(SPVM_DEBUGBREAK newpfn, SPVM_DEBUGBREAK *oldpfn);
IPluginDebugInfo *GetDebugInfo();
int HeapAlloc(unsigned int cells, cell_t *local_addr, cell_t **phys_addr);
int HeapPop(cell_t local_addr);
int HeapRelease(cell_t local_addr);
int FindNativeByName(const char *name, uint32_t *index);
int GetNativeByIndex(uint32_t index, sp_native_t **native);
uint32_t GetNativesNum();
int FindPublicByName(const char *name, uint32_t *index);
int GetPublicByIndex(uint32_t index, sp_public_t **publicptr);
uint32_t GetPublicsNum();
int GetPubvarByIndex(uint32_t index, sp_pubvar_t **pubvar);
int FindPubvarByName(const char *name, uint32_t *index);
int GetPubvarAddrs(uint32_t index, cell_t *local_addr, cell_t **phys_addr);
uint32_t GetPubVarsNum();
int LocalToPhysAddr(cell_t local_addr, cell_t **phys_addr);
int LocalToString(cell_t local_addr, char **addr);
int StringToLocal(cell_t local_addr, size_t chars, const char *source);
int StringToLocalUTF8(cell_t local_addr, size_t maxbytes, const char *source, size_t *wrtnbytes);
int PushCell(cell_t value);
int PushCellArray(cell_t *local_addr, cell_t **phys_addr, cell_t array[], unsigned int numcells);
int PushString(cell_t *local_addr, char **phys_addr, const char *string);
int PushCellsFromArray(cell_t array[], unsigned int numcells);
int BindNatives(const sp_nativeinfo_t *natives, unsigned int num, int overwrite);
int BindNative(const sp_nativeinfo_t *native);
int BindNativeToAny(SPVM_NATIVE_FUNC native);
int Execute(uint32_t code_addr, cell_t *result);
cell_t ThrowNativeErrorEx(int error, const char *msg, ...);
cell_t ThrowNativeError(const char *msg, ...);
IPluginFunction *GetFunctionByName(const char *public_name);
IPluginFunction *GetFunctionById(funcid_t func_id);
#if defined SOURCEMOD_BUILD
SourceMod::IdentityToken_t *GetIdentity();
void SetIdentity(SourceMod::IdentityToken_t *token);
cell_t *GetNullRef(SP_NULL_TYPE type);
int LocalToStringNULL(cell_t local_addr, char **addr);
#endif
int BindNativeToIndex(uint32_t index, SPVM_NATIVE_FUNC native);
public: //IPluginDebugInfo
int LookupFile(ucell_t addr, const char **filename);
int LookupFunction(ucell_t addr, const char **name);
int LookupLine(ucell_t addr, uint32_t *line);
public:
void SetContext(sp_context_t *_ctx);
bool IsInExec();
private:
void SetErrorMessage(const char *msg, va_list ap);
void FlushFunctionCache();
void RefreshFunctionCache();
private:
sp_context_t *ctx;
#if defined SOURCEMOD_BUILD
SourceMod::IdentityToken_t *m_pToken;
cell_t *m_pNullVec;
cell_t *m_pNullString;
#endif
char m_MsgCache[1024];
bool m_CustomMsg;
bool m_InExec;
unsigned int m_funcsnum;
#if 0
CFunction **m_priv_funcs;
#endif
CFunction **m_pub_funcs;
};
public:
BaseContext(BaseRuntime *pRuntime);
~BaseContext();
public: //IPluginContext
IVirtualMachine *GetVirtualMachine();
sp_context_t *GetContext();
bool IsDebugging();
int SetDebugBreak(void *newpfn, void *oldpfn);
IPluginDebugInfo *GetDebugInfo();
int HeapAlloc(unsigned int cells, cell_t *local_addr, cell_t **phys_addr);
int HeapPop(cell_t local_addr);
int HeapRelease(cell_t local_addr);
int FindNativeByName(const char *name, uint32_t *index);
int GetNativeByIndex(uint32_t index, sp_native_t **native);
uint32_t GetNativesNum();
int FindPublicByName(const char *name, uint32_t *index);
int GetPublicByIndex(uint32_t index, sp_public_t **publicptr);
uint32_t GetPublicsNum();
int GetPubvarByIndex(uint32_t index, sp_pubvar_t **pubvar);
int FindPubvarByName(const char *name, uint32_t *index);
int GetPubvarAddrs(uint32_t index, cell_t *local_addr, cell_t **phys_addr);
uint32_t GetPubVarsNum();
int LocalToPhysAddr(cell_t local_addr, cell_t **phys_addr);
int LocalToString(cell_t local_addr, char **addr);
int StringToLocal(cell_t local_addr, size_t chars, const char *source);
int StringToLocalUTF8(cell_t local_addr, size_t maxbytes, const char *source, size_t *wrtnbytes);
int PushCell(cell_t value);
int PushCellArray(cell_t *local_addr, cell_t **phys_addr, cell_t array[], unsigned int numcells);
int PushString(cell_t *local_addr, char **phys_addr, const char *string);
int PushCellsFromArray(cell_t array[], unsigned int numcells);
int BindNatives(const sp_nativeinfo_t *natives, unsigned int num, int overwrite);
int BindNative(const sp_nativeinfo_t *native);
int BindNativeToAny(SPVM_NATIVE_FUNC native);
int Execute(uint32_t code_addr, cell_t *result);
cell_t ThrowNativeErrorEx(int error, const char *msg, ...);
cell_t ThrowNativeError(const char *msg, ...);
IPluginFunction *GetFunctionByName(const char *public_name);
IPluginFunction *GetFunctionById(funcid_t func_id);
SourceMod::IdentityToken_t *GetIdentity();
void SetIdentity(SourceMod::IdentityToken_t *token);
cell_t *GetNullRef(SP_NULL_TYPE type);
int LocalToStringNULL(cell_t local_addr, char **addr);
int BindNativeToIndex(uint32_t index, SPVM_NATIVE_FUNC native);
int Execute(IPluginFunction *function, const cell_t *params, unsigned int num_params, cell_t *result);
IPluginRuntime *GetRuntime();
public:
bool IsInExec();
private:
void SetErrorMessage(const char *msg, va_list ap);
void _SetErrorMessage(const char *msg, ...);
private:
sp_plugin_t *m_pPlugin;
SourceMod::IdentityToken_t *m_pToken;
cell_t *m_pNullVec;
cell_t *m_pNullString;
char m_MsgCache[1024];
bool m_CustomMsg;
bool m_InExec;
BaseRuntime *m_pRuntime;
sp_context_t m_ctx;
};
#endif //_INCLUDE_SOURCEPAWN_BASECONTEXT_H_

View File

@ -48,6 +48,8 @@
#include "zlib/zlib.h"
#include "sp_vm_basecontext.h"
SourcePawnEngine g_engine1;
#if defined WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
@ -188,281 +190,31 @@ void SourcePawnEngine::BaseFree(void *memory)
free(memory);
}
IPluginContext *SourcePawnEngine::CreateBaseContext(sp_context_t *ctx)
{
return new BaseContext(ctx);
}
void SourcePawnEngine::FreeBaseContext(IPluginContext *ctx)
{
delete ctx;
}
sp_plugin_t *_ReadPlugin(sp_file_hdr_t *hdr, uint8_t *base, sp_plugin_t *plugin, int *err)
{
char *nameptr;
uint8_t sectnum = 0;
sp_file_section_t *secptr = (sp_file_section_t *)(base + sizeof(sp_file_hdr_t));
memset(plugin, 0, sizeof(sp_plugin_t));
plugin->base = base;
while (sectnum < hdr->sections)
{
nameptr = (char *)(base + hdr->stringtab + secptr->nameoffs);
if (!(plugin->pcode) && !strcmp(nameptr, ".code"))
{
sp_file_code_t *cod = (sp_file_code_t *)(base + secptr->dataoffs);
plugin->pcode = base + secptr->dataoffs + cod->code;
plugin->pcode_size = cod->codesize;
plugin->flags = cod->flags;
}
else if (!(plugin->data) && !strcmp(nameptr, ".data"))
{
sp_file_data_t *dat = (sp_file_data_t *)(base + secptr->dataoffs);
plugin->data = base + secptr->dataoffs + dat->data;
plugin->data_size = dat->datasize;
plugin->memory = dat->memsize;
}
else if (!(plugin->info.publics) && !strcmp(nameptr, ".publics"))
{
plugin->info.publics_num = secptr->size / sizeof(sp_file_publics_t);
plugin->info.publics = (sp_file_publics_t *)(base + secptr->dataoffs);
}
else if (!(plugin->info.pubvars) && !strcmp(nameptr, ".pubvars"))
{
plugin->info.pubvars_num = secptr->size / sizeof(sp_file_pubvars_t);
plugin->info.pubvars = (sp_file_pubvars_t *)(base + secptr->dataoffs);
}
else if (!(plugin->info.natives) && !strcmp(nameptr, ".natives"))
{
plugin->info.natives_num = secptr->size / sizeof(sp_file_natives_t);
plugin->info.natives = (sp_file_natives_t *)(base + secptr->dataoffs);
}
else if (!(plugin->info.stringbase) && !strcmp(nameptr, ".names"))
{
plugin->info.stringbase = (const char *)(base + secptr->dataoffs);
}
else if (!(plugin->debug.files) && !strcmp(nameptr, ".dbg.files"))
{
plugin->debug.files = (sp_fdbg_file_t *)(base + secptr->dataoffs);
}
else if (!(plugin->debug.lines) && !strcmp(nameptr, ".dbg.lines"))
{
plugin->debug.lines = (sp_fdbg_line_t *)(base + secptr->dataoffs);
}
else if (!(plugin->debug.symbols) && !strcmp(nameptr, ".dbg.symbols"))
{
plugin->debug.symbols = (sp_fdbg_symbol_t *)(base + secptr->dataoffs);
}
else if (!(plugin->debug.lines_num) && !strcmp(nameptr, ".dbg.info"))
{
sp_fdbg_info_t *inf = (sp_fdbg_info_t *)(base + secptr->dataoffs);
plugin->debug.files_num = inf->num_files;
plugin->debug.lines_num = inf->num_lines;
plugin->debug.syms_num = inf->num_syms;
}
else if (!(plugin->debug.stringbase) && !strcmp(nameptr, ".dbg.strings"))
{
plugin->debug.stringbase = (const char *)(base + secptr->dataoffs);
}
secptr++;
sectnum++;
}
if (!(plugin->pcode) || !(plugin->data) || !(plugin->info.stringbase))
{
goto return_error;
}
if ((plugin->flags & SP_FLAG_DEBUG) && (!(plugin->debug.files) || !(plugin->debug.lines) || !(plugin->debug.symbols)))
{
goto return_error;
}
if (err)
{
*err = SP_ERROR_NONE;
}
return plugin;
return_error:
if (err)
{
*err = SP_ERROR_FILE_FORMAT;
}
return NULL;
}
sp_plugin_t *SourcePawnEngine::LoadFromFilePointer(FILE *fp, int *err)
{
sp_file_hdr_t hdr;
sp_plugin_t *plugin;
uint8_t *base;
int z_result;
int error;
if (!fp)
if (err != NULL)
{
error = SP_ERROR_NOT_FOUND;
goto return_error;
*err = SP_ERROR_ABORTED;
}
/* Rewind for safety */
rewind(fp);
fread(&hdr, sizeof(sp_file_hdr_t), 1, fp);
if (hdr.magic != SPFILE_MAGIC)
{
error = SP_ERROR_FILE_FORMAT;
goto return_error;
}
switch (hdr.compression)
{
case SPFILE_COMPRESSION_GZ:
{
uint32_t uncompsize = hdr.imagesize - hdr.dataoffs;
uint32_t compsize = hdr.disksize - hdr.dataoffs;
uint32_t sectsize = hdr.dataoffs - sizeof(sp_file_hdr_t);
uLongf destlen = uncompsize;
char *tempbuf = (char *)malloc(compsize);
void *uncompdata = malloc(uncompsize);
void *sectheader = malloc(sectsize);
fread(sectheader, sectsize, 1, fp);
fread(tempbuf, compsize, 1, fp);
z_result = uncompress((Bytef *)uncompdata, &destlen, (Bytef *)tempbuf, compsize);
free(tempbuf);
if (z_result != Z_OK)
{
free(sectheader);
free(uncompdata);
error = SP_ERROR_DECOMPRESSOR;
goto return_error;
}
base = (uint8_t *)malloc(hdr.imagesize);
memcpy(base, &hdr, sizeof(sp_file_hdr_t));
memcpy(base + sizeof(sp_file_hdr_t), sectheader, sectsize);
free(sectheader);
memcpy(base + hdr.dataoffs, uncompdata, uncompsize);
free(uncompdata);
break;
}
case SPFILE_COMPRESSION_NONE:
{
base = (uint8_t *)malloc(hdr.imagesize);
rewind(fp);
fread(base, hdr.imagesize, 1, fp);
break;
}
default:
{
error = SP_ERROR_DECOMPRESSOR;
goto return_error;
}
}
plugin = (sp_plugin_t *)malloc(sizeof(sp_plugin_t));
if (!_ReadPlugin(&hdr, base, plugin, err))
{
free(plugin);
free(base);
return NULL;
}
plugin->allocflags = 0;
return plugin;
return_error:
if (err)
{
*err = error;
}
return NULL;
}
sp_plugin_t *SourcePawnEngine::LoadFromMemory(void *base, sp_plugin_t *plugin, int *err)
{
sp_file_hdr_t hdr;
uint8_t noptr = 0;
memcpy(&hdr, base, sizeof(sp_file_hdr_t));
if (!plugin)
if (err != NULL)
{
plugin = (sp_plugin_t *)malloc(sizeof(sp_plugin_t));
noptr = 1;
*err = SP_ERROR_ABORTED;
}
if (!_ReadPlugin(&hdr, (uint8_t *)base, plugin, err))
{
if (noptr)
{
free(plugin);
}
return NULL;
}
if (!noptr)
{
plugin->allocflags |= SP_FA_SELF_EXTERNAL;
}
plugin->allocflags |= SP_FA_BASE_EXTERNAL;
return plugin;
return NULL;
}
int SourcePawnEngine::FreeFromMemory(sp_plugin_t *plugin)
{
if (!(plugin->allocflags & SP_FA_BASE_EXTERNAL))
{
free(plugin->base);
plugin->base = NULL;
}
if (!(plugin->allocflags & SP_FA_SELF_EXTERNAL))
{
free(plugin);
}
return SP_ERROR_NONE;
return SP_ERROR_ABORTED;
}
#if 0
void SourcePawnEngine::ReleaseFunctionToPool(CFunction *func)
{
if (!func)
{
return;
}
func->Cancel();
func->m_pNext = m_pFreeFuncs;
m_pFreeFuncs = func;
}
CFunction *SourcePawnEngine::GetFunctionFromPool(funcid_t f, IPluginContext *plugin)
{
if (!m_pFreeFuncs)
{
return new CFunction(f, plugin);
} else {
CFunction *pFunc = m_pFreeFuncs;
m_pFreeFuncs = m_pFreeFuncs->m_pNext;
pFunc->Set(f, plugin);
return pFunc;
}
}
#endif
IDebugListener *SourcePawnEngine::SetDebugListener(IDebugListener *pListener)
{
IDebugListener *old = m_pDebugHook;
@ -529,7 +281,7 @@ void SourcePawnEngine::FreeTracedCall(TracedCall *pCall)
}
}
void SourcePawnEngine::PushTracer(sp_context_t *ctx)
void SourcePawnEngine::PushTracer(BaseContext *ctx)
{
TracedCall *pCall = MakeTracedCall(true);
@ -538,7 +290,7 @@ void SourcePawnEngine::PushTracer(sp_context_t *ctx)
pCall->frm = INVALID_CIP;
}
void SourcePawnEngine::RunTracer(sp_context_t *ctx, uint32_t frame, uint32_t codeip)
void SourcePawnEngine::RunTracer(BaseContext *ctx, uint32_t frame, uint32_t codeip)
{
assert(m_CallStack != NULL);
assert(m_CallStack->ctx == ctx);
@ -577,13 +329,13 @@ void SourcePawnEngine::PopTracer(int error, const char *msg)
{
uint32_t native = INVALID_CIP;
if (m_CallStack->ctx->n_err)
if (m_CallStack->ctx->GetContext()->n_err)
{
native = m_CallStack->ctx->n_idx;
native = m_CallStack->ctx->GetContext()->n_idx;
}
CContextTrace trace(m_CallStack, error, msg, native);
m_pDebugHook->OnContextExecuteError(m_CallStack->ctx->context, &trace);
m_pDebugHook->OnContextExecuteError(m_CallStack->ctx, &trace);
}
/* Now pop the error chain */
@ -607,7 +359,7 @@ CContextTrace::CContextTrace(TracedCall *pStart, int error, const char *msg, uin
bool CContextTrace::DebugInfoAvailable()
{
return ((m_pStart->ctx->flags & SP_FLAG_DEBUG) == SP_FLAG_DEBUG);
return m_pStart->ctx->IsDebugging();
}
const char *CContextTrace::GetCustomErrorString()
@ -648,7 +400,7 @@ bool CContextTrace::GetTraceInfo(CallStackInfo *trace)
return false;
}
IPluginContext *pContext = m_pIterator->ctx->context;
IPluginContext *pContext = m_pIterator->ctx;
IPluginDebugInfo *pInfo = pContext->GetDebugInfo();
if (!pInfo)
@ -690,7 +442,7 @@ const char *CContextTrace::GetLastNative(uint32_t *index)
}
sp_native_t *native;
if (m_pIterator->ctx->context->GetNativeByIndex(m_Native, &native) != SP_ERROR_NONE)
if (m_pIterator->ctx->GetNativeByIndex(m_Native, &native) != SP_ERROR_NONE)
{
return NULL;
}

View File

@ -35,11 +35,13 @@
#include "sp_vm_api.h"
#include "sp_vm_function.h"
class BaseContext;
struct TracedCall
{
uint32_t cip;
uint32_t frm;
sp_context_t *ctx;
BaseContext *ctx;
TracedCall *next;
unsigned int chain;
};
@ -73,8 +75,6 @@ public: //ISourcePawnEngine
sp_plugin_t *LoadFromFilePointer(FILE *fp, int *err);
sp_plugin_t *LoadFromMemory(void *base, sp_plugin_t *plugin, int *err);
int FreeFromMemory(sp_plugin_t *plugin);
IPluginContext *CreateBaseContext(sp_context_t *ctx);
void FreeBaseContext(IPluginContext *ctx);
void *BaseAlloc(size_t size);
void BaseFree(void *memory);
void *ExecAlloc(size_t size);
@ -92,7 +92,7 @@ public: //Debugger Stuff
*
* @param ctx Plugin context.
*/
void PushTracer(sp_context_t *ctx);
void PushTracer(BaseContext *ctx);
/**
* @brief Pops a plugin off the call tracer.
@ -102,7 +102,7 @@ public: //Debugger Stuff
/**
* @brief Runs tracer from a debug break.
*/
void RunTracer(sp_context_t *ctx, uint32_t frame, uint32_t codeip);
void RunTracer(BaseContext *ctx, uint32_t frame, uint32_t codeip);
public: //Plugin function stuff
CFunction *GetFunctionFromPool(funcid_t f, IPluginContext *plugin);
void ReleaseFunctionToPool(CFunction *func);
@ -117,4 +117,6 @@ private:
//CFunction *m_pFreeFuncs;
};
extern SourcePawnEngine g_engine1;
#endif //_INCLUDE_SOURCEPAWN_VM_ENGINE_H_

View File

@ -32,76 +32,47 @@
#include <stdio.h>
#include <string.h>
#include "sp_vm_function.h"
#include "sm_stringutil.h"
#include "BaseRuntime.h"
/********************
* FUNCTION CALLING *
********************/
void CFunction::Set(uint32_t code_addr, IPluginContext *plugin, funcid_t id, uint32_t pub_id)
void CFunction::Set(uint32_t code_addr, BaseRuntime *runtime, funcid_t fnid, uint32_t pub_id)
{
m_codeaddr = code_addr;
m_pContext = plugin;
m_pRuntime = runtime;
m_curparam = 0;
m_errorstate = SP_ERROR_NONE;
m_Invalid = false;
m_pCtx = plugin ? plugin->GetContext() : NULL;
m_FnId = id;
m_pContext->GetPublicByIndex(pub_id, &m_pPublic);
m_FnId = fnid;
}
bool CFunction::IsRunnable()
{
return ((m_pCtx->flags & SPFLAG_PLUGIN_PAUSED) != SPFLAG_PLUGIN_PAUSED);
return m_pRuntime->IsPaused();
}
int CFunction::CallFunction(const cell_t *params, unsigned int num_params, cell_t *result)
{
int ir, serial;
return CallFunction(m_pRuntime->GetDefaultContext(), params, num_params, result);
}
if (!IsRunnable())
{
return SP_ERROR_NOT_RUNNABLE;
}
if ((m_pCtx->prof_flags & SP_PROF_CALLBACKS) == SP_PROF_CALLBACKS
&& m_pPublic != NULL)
{
serial = m_pCtx->profiler->OnCallbackBegin(m_pContext, m_pPublic);
}
while (num_params--)
{
m_pContext->PushCell(params[num_params]);
}
ir = m_pContext->Execute(m_codeaddr, result);
if ((m_pCtx->prof_flags & SP_PROF_CALLBACKS) == SP_PROF_CALLBACKS
&& m_pPublic != NULL)
{
m_pCtx->profiler->OnCallbackEnd(serial);
}
return ir;
int CFunction::CallFunction(IPluginContext *pContext, const cell_t *params, unsigned int num_params, cell_t *result)
{
return pContext->Execute(this, params, num_params, result);
}
IPluginContext *CFunction::GetParentContext()
{
return m_pContext;
return m_pRuntime->GetDefaultContext();
}
CFunction::CFunction(uint32_t code_addr, IPluginContext *plugin, funcid_t id, uint32_t pub_id) :
m_codeaddr(code_addr), m_pContext(plugin), m_curparam(0),
m_errorstate(SP_ERROR_NONE), m_FnId(id)
CFunction::CFunction(uint32_t code_addr, BaseRuntime *runtime, funcid_t id, uint32_t pub_id) :
m_codeaddr(code_addr), m_curparam(0), m_errorstate(SP_ERROR_NONE), m_FnId(id)
{
m_Invalid = false;
if (plugin)
{
m_pCtx = plugin->GetContext();
}
m_pContext->GetPublicByIndex(pub_id, &m_pPublic);
m_pRuntime = runtime;
}
int CFunction::PushCell(cell_t cell)
@ -198,6 +169,11 @@ void CFunction::Cancel()
}
int CFunction::Execute(cell_t *result)
{
return Execute(m_pRuntime->GetDefaultContext(), result);
}
int CFunction::Execute(IPluginContext *ctx, cell_t *result)
{
int err = SP_ERROR_NONE;
@ -236,9 +212,9 @@ int CFunction::Execute(cell_t *result)
if (!temp_info[i].str.is_sz)
{
/* Allocate a normal/generic array */
if ((err=m_pContext->HeapAlloc(temp_info[i].size,
&(temp_info[i].local_addr),
&(temp_info[i].phys_addr)))
if ((err=ctx->HeapAlloc(temp_info[i].size,
&(temp_info[i].local_addr),
&(temp_info[i].phys_addr)))
!= SP_ERROR_NONE)
{
break;
@ -254,9 +230,9 @@ int CFunction::Execute(cell_t *result)
size_t cells = (temp_info[i].size + sizeof(cell_t) - 1) / sizeof(cell_t);
/* Allocate the buffer */
if ((err=m_pContext->HeapAlloc(cells,
&(temp_info[i].local_addr),
&(temp_info[i].phys_addr)))
if ((err=ctx->HeapAlloc(cells,
&(temp_info[i].local_addr),
&(temp_info[i].phys_addr)))
!= SP_ERROR_NONE)
{
break;
@ -267,10 +243,10 @@ int CFunction::Execute(cell_t *result)
/* Cut off UTF-8 properly */
if (temp_info[i].str.sz_flags & SM_PARAM_STRING_UTF8)
{
if ((err=m_pContext->StringToLocalUTF8(temp_info[i].local_addr,
temp_info[i].size,
(const char *)temp_info[i].orig_addr,
NULL))
if ((err=ctx->StringToLocalUTF8(temp_info[i].local_addr,
temp_info[i].size,
(const char *)temp_info[i].orig_addr,
NULL))
!= SP_ERROR_NONE)
{
break;
@ -284,9 +260,9 @@ int CFunction::Execute(cell_t *result)
/* Copy ASCII characters */
else
{
if ((err=m_pContext->StringToLocal(temp_info[i].local_addr,
temp_info[i].size,
(const char *)temp_info[i].orig_addr))
if ((err=ctx->StringToLocal(temp_info[i].local_addr,
temp_info[i].size,
(const char *)temp_info[i].orig_addr))
!= SP_ERROR_NONE)
{
break;
@ -307,7 +283,7 @@ int CFunction::Execute(cell_t *result)
/* Make the call if we can */
if (err == SP_ERROR_NONE)
{
if ((err = CallFunction(temp_params, numparams, result)) != SP_ERROR_NONE)
if ((err = CallFunction(ctx, temp_params, numparams, result)) != SP_ERROR_NONE)
{
docopies = false;
}
@ -350,7 +326,7 @@ int CFunction::Execute(cell_t *result)
}
}
if ((err=m_pContext->HeapPop(temp_info[i].local_addr)) != SP_ERROR_NONE)
if ((err=ctx->HeapPop(temp_info[i].local_addr)) != SP_ERROR_NONE)
{
return err;
}
@ -364,3 +340,16 @@ funcid_t CFunction::GetFunctionID()
return m_FnId;
}
int CFunction::SetError(int err)
{
m_errorstate = err;
return err;
}
bool CFunction::IsInvalidated()
{
return m_Invalid;
}

View File

@ -32,7 +32,11 @@
#ifndef _INCLUDE_SOURCEMOD_BASEFUNCTION_H_
#define _INCLUDE_SOURCEMOD_BASEFUNCTION_H_
#include "sm_globals.h"
#include <sp_vm_api.h>
class BaseRuntime;
using namespace SourcePawn;
struct ParamInfo
{
@ -56,7 +60,7 @@ class CFunction : public IPluginFunction
friend class SourcePawnEngine;
public:
CFunction(uint32_t code_addr,
IPluginContext *pContext,
BaseRuntime *pRuntime,
funcid_t fnid,
uint32_t pub_id);
public:
@ -71,29 +75,23 @@ public:
virtual void Cancel();
virtual int CallFunction(const cell_t *params, unsigned int num_params, cell_t *result);
virtual IPluginContext *GetParentContext();
inline bool IsInvalidated()
{
return m_Invalid;
}
inline void Invalidate()
{
m_Invalid = true;
}
bool IsInvalidated();
void Invalidate();
bool IsRunnable();
funcid_t GetFunctionID();
int Execute(IPluginContext *ctx, cell_t *result);
int CallFunction(IPluginContext *ctx,
const cell_t *params,
unsigned int num_params,
cell_t *result);
public:
void Set(uint32_t code_addr, IPluginContext *plugin, funcid_t fnid, uint32_t pub_id);
void Set(uint32_t code_addr, BaseRuntime *runtime, funcid_t fnid, uint32_t pub_id);
private:
int _PushString(const char *string, int sz_flags, int cp_flags, size_t len);
inline int SetError(int err)
{
m_errorstate = err;
return err;
}
int SetError(int err);
private:
uint32_t m_codeaddr;
IPluginContext *m_pContext;
sp_context_t *m_pCtx;
BaseRuntime *m_pRuntime;
cell_t m_params[SP_MAX_EXEC_PARAMS];
ParamInfo m_info[SP_MAX_EXEC_PARAMS];
unsigned int m_curparam;
@ -101,7 +99,6 @@ private:
CFunction *m_pNext;
bool m_Invalid;
funcid_t m_FnId;
sp_public_t *m_pPublic;
};
#endif //_INCLUDE_SOURCEMOD_BASEFUNCTION_H_

View File

@ -35,12 +35,22 @@
#include "jit_x86.h"
#include "opcode_helpers.h"
#include <x86_macros.h>
#include "jit_version.h"
#include "../jit_version.h"
#include "../sp_vm_engine.h"
#include "../engine2.h"
#if defined USE_UNGEN_OPCODES
#include "ungen_opcodes.h"
#endif
JITX86 g_Jit1;
ISourcePawnEngine *engine = &g_engine1;
inline sp_plugin_t *GETPLUGIN(sp_context_t *ctx)
{
return (sp_plugin_t *)(ctx->vm[JITVARS_PLUGIN]);
}
inline void WriteOp_Move_Pri(JitWriter *jit)
{
//mov eax, edx
@ -1318,12 +1328,12 @@ inline void WriteOp_Retn(JitWriter *jit)
void ProfCallGate_Begin(sp_context_t *ctx, const char *name)
{
ctx->profiler->OnFunctionBegin(ctx->context, name);
((IProfiler *)ctx->vm[JITVARS_PROFILER])->OnFunctionBegin((IPluginContext *)ctx->vm[JITVARS_BASECTX], name);
}
void ProfCallGate_End(sp_context_t *ctx)
{
ctx->profiler->OnFunctionEnd();
((IProfiler *)ctx->vm[JITVARS_PROFILER])->OnFunctionEnd();
}
const char *find_func_name(sp_plugin_t *plugin, uint32_t offs)
@ -2264,8 +2274,11 @@ inline void WriteOp_FloatCompare(JitWriter *jit)
cell_t NativeCallback(sp_context_t *ctx, ucell_t native_idx, cell_t *params)
{
sp_native_t *native;
sp_plugin_t *plugin;
plugin = (sp_plugin_t *)ctx->vm[JITVARS_PLUGIN];
native = &ctx->natives[native_idx];
native = &plugin->natives[native_idx];
ctx->n_idx = native_idx;
@ -2276,15 +2289,18 @@ cell_t NativeCallback(sp_context_t *ctx, ucell_t native_idx, cell_t *params)
return 0;
}
return native->pfn(ctx->context, params);
return native->pfn(GET_CONTEXT(ctx), params);
}
cell_t NativeCallback_Profile(sp_context_t *ctx, ucell_t native_idx, cell_t *params)
{
cell_t val;
sp_native_t *native;
sp_plugin_t *plugin;
native = &ctx->natives[native_idx];
plugin = (sp_plugin_t *)ctx->vm[JITVARS_PLUGIN];
native = &plugin->natives[native_idx];
ctx->n_idx = native_idx;
@ -2295,9 +2311,9 @@ cell_t NativeCallback_Profile(sp_context_t *ctx, ucell_t native_idx, cell_t *par
return 0;
}
ctx->profiler->OnNativeBegin(ctx->context, native);
val = native->pfn(ctx->context, params);
ctx->profiler->OnNativeEnd();
plugin->profiler->OnNativeBegin(GET_CONTEXT(ctx), native);
val = native->pfn(GET_CONTEXT(ctx), params);
plugin->profiler->OnNativeEnd();
return val;
}
@ -2307,9 +2323,11 @@ cell_t NativeCallback_Debug(sp_context_t *ctx, ucell_t native_idx, cell_t *param
cell_t save_sp = ctx->sp;
cell_t save_hp = ctx->hp;
sp_plugin_t *pl = GETPLUGIN(ctx);
ctx->n_idx = native_idx;
if (ctx->hp < ctx->heap_base)
if (ctx->hp < (cell_t)pl->data_size)
{
ctx->n_err = SP_ERROR_HEAPMIN;
return 0;
@ -2321,7 +2339,7 @@ cell_t NativeCallback_Debug(sp_context_t *ctx, ucell_t native_idx, cell_t *param
return 0;
}
if ((uint32_t)ctx->sp >= ctx->mem_size)
if ((uint32_t)ctx->sp >= pl->mem_size)
{
ctx->n_err = SP_ERROR_STACKMIN;
return 0;
@ -2353,9 +2371,11 @@ cell_t NativeCallback_Debug_Profile(sp_context_t *ctx, ucell_t native_idx, cell_
cell_t save_sp = ctx->sp;
cell_t save_hp = ctx->hp;
sp_plugin_t *pl = GETPLUGIN(ctx);
ctx->n_idx = native_idx;
if (ctx->hp < ctx->heap_base)
if (ctx->hp < (cell_t)pl->data_size)
{
ctx->n_err = SP_ERROR_HEAPMIN;
return 0;
@ -2367,7 +2387,7 @@ cell_t NativeCallback_Debug_Profile(sp_context_t *ctx, ucell_t native_idx, cell_
return 0;
}
if ((uint32_t)ctx->sp >= ctx->mem_size)
if ((uint32_t)ctx->sp >= pl->mem_size)
{
ctx->n_err = SP_ERROR_STACKMIN;
return 0;
@ -2457,11 +2477,26 @@ void WriteErrorRoutines(CompData *data, JitWriter *jit)
Write_GetError(jit);
}
sp_context_t *JITX86::CompileToContext(ICompilation *co, int *err)
bool JITX86::Compile(ICompilation *co, BaseRuntime *prt, int *err)
{
CompData *data = (CompData *)co;
sp_plugin_t *plugin = data->plugin;
if (data->plugin == NULL)
{
if (data->debug && !(prt->m_pPlugin->flags & SP_FLAG_DEBUG))
{
if (err != NULL)
{
*err = SP_ERROR_NOTDEBUGGING;
}
co->Abort();
return false;
}
data->SetRuntime(prt);
}
/* The first phase is to browse */
uint8_t *code = plugin->pcode;
uint8_t *end_cip = plugin->pcode + plugin->pcode_size;
@ -2584,8 +2619,8 @@ jit_rewind:
if (data->error_set != SP_ERROR_NONE)
{
*err = data->error_set;
AbortCompilation(co);
return NULL;
co->Abort();
return false;
}
}
/* Write these last because error jumps should be unpredicted, and thus forward */
@ -2627,23 +2662,27 @@ jit_rewind:
* FOURTH PASS - Context Setup
*************/
sp_context_t *ctx = new sp_context_t;
memset(ctx, 0, sizeof(sp_context_t));
/* setup basics */
ctx->codebase = writer.outbase;
ctx->plugin = plugin;
ctx->vmbase = this;
ctx->flags = (data->debug ? SPFLAG_PLUGIN_DEBUG : 0);
sp_context_t *ctx = data->runtime->GetDefaultContext()->GetContext();
/* Clear out any old cruft */
if (plugin->codebase != NULL)
{
FreePluginVars(data->runtime->m_pPlugin);
FreeContextVars(ctx);
}
plugin->codebase = writer.outbase;
/* setup memory */
ctx->memory = new uint8_t[plugin->memory];
memcpy(ctx->memory, plugin->data, plugin->data_size);
ctx->mem_size = plugin->memory;
ctx->heap_base = plugin->data_size;
ctx->hp = ctx->heap_base;
ctx->sp = ctx->mem_size - sizeof(cell_t);
ctx->prof_flags = data->profile;
ctx->hp = plugin->data_size;
ctx->sp = plugin->mem_size - sizeof(cell_t);
ctx->frm = ctx->sp;
ctx->n_err = SP_ERROR_NONE;
ctx->n_idx = SP_ERROR_NONE;
plugin->prof_flags = data->profile;
plugin->flags = data->debug ? SPFLAG_PLUGIN_DEBUG : 0;
const char *strbase = plugin->info.stringbase;
uint32_t max, iter;
@ -2651,39 +2690,39 @@ jit_rewind:
/* relocate public info */
if ((max = plugin->info.publics_num))
{
ctx->publics = new sp_public_t[max];
plugin->publics = new sp_public_t[max];
for (iter=0; iter<max; iter++)
{
ctx->publics[iter].name = strbase + plugin->info.publics[iter].name;
ctx->publics[iter].code_offs = RelocLookup(jit, plugin->info.publics[iter].address, false);
plugin->publics[iter].name = strbase + plugin->info.publics[iter].name;
plugin->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);
plugin->publics[iter].funcid = (plugin->publics[iter].code_offs << 1);
}
}
/* relocate pubvar info */
if ((max = plugin->info.pubvars_num))
{
uint8_t *dat = ctx->memory;
ctx->pubvars = new sp_pubvar_t[max];
uint8_t *dat = plugin->memory;
plugin->pubvars = new sp_pubvar_t[max];
for (iter=0; iter<max; iter++)
{
ctx->pubvars[iter].name = strbase + plugin->info.pubvars[iter].name;
ctx->pubvars[iter].offs = (cell_t *)(dat + plugin->info.pubvars[iter].address);
plugin->pubvars[iter].name = strbase + plugin->info.pubvars[iter].name;
plugin->pubvars[iter].offs = (cell_t *)(dat + plugin->info.pubvars[iter].address);
}
}
/* relocate native info */
if ((max = plugin->info.natives_num))
{
ctx->natives = new sp_native_t[max];
plugin->natives = new sp_native_t[max];
for (iter=0; iter<max; iter++)
{
ctx->natives[iter].name = strbase + plugin->info.natives[iter].name;
ctx->natives[iter].pfn = &InvalidNative;
ctx->natives[iter].status = SP_NATIVE_UNBOUND;
ctx->natives[iter].flags = 0;
ctx->natives[iter].user = NULL;
plugin->natives[iter].name = strbase + plugin->info.natives[iter].name;
plugin->natives[iter].pfn = &InvalidNative;
plugin->natives[iter].status = SP_NATIVE_UNBOUND;
plugin->natives[iter].flags = 0;
plugin->natives[iter].user = NULL;
}
}
@ -2696,20 +2735,20 @@ jit_rewind:
/* relocate files */
max = plugin->debug.files_num;
ctx->files = new sp_debug_file_t[max];
plugin->files = new sp_debug_file_t[max];
for (iter=0; iter<max; iter++)
{
ctx->files[iter].addr = RelocLookup(jit, plugin->debug.files[iter].addr, false);
ctx->files[iter].name = strbase + plugin->debug.files[iter].name;
plugin->files[iter].addr = RelocLookup(jit, plugin->debug.files[iter].addr, false);
plugin->files[iter].name = strbase + plugin->debug.files[iter].name;
}
/* relocate lines */
max = plugin->debug.lines_num;
ctx->lines = new sp_debug_line_t[max];
plugin->lines = new sp_debug_line_t[max];
for (iter=0; iter<max; iter++)
{
ctx->lines[iter].addr = RelocLookup(jit, plugin->debug.lines[iter].addr, false);
ctx->lines[iter].line = plugin->debug.lines[iter].line;
plugin->lines[iter].addr = RelocLookup(jit, plugin->debug.lines[iter].addr, false);
plugin->lines[iter].line = plugin->debug.lines[iter].line;
}
/* relocate arrays */
@ -2718,7 +2757,7 @@ jit_rewind:
uint8_t *cursor = (uint8_t *)(plugin->debug.symbols);
max = plugin->debug.syms_num;
ctx->symbols = new sp_debug_symbol_t[max];
plugin->symbols = new sp_debug_symbol_t[max];
for (iter=0; iter<max; iter++)
{
sym = (sp_fdbg_symbol_t *)cursor;
@ -2730,52 +2769,48 @@ jit_rewind:
*/
if (sym->codestart > data->codesize)
{
ctx->symbols[iter].codestart = 0;
plugin->symbols[iter].codestart = 0;
} else {
ctx->symbols[iter].codestart = RelocLookup(jit, sym->codestart, false);
plugin->symbols[iter].codestart = RelocLookup(jit, sym->codestart, false);
}
if (sym->codeend > data->codesize)
{
ctx->symbols[iter].codeend = data->codesize;
plugin->symbols[iter].codeend = data->codesize;
} else {
ctx->symbols[iter].codeend = RelocLookup(jit, sym->codeend, false);
plugin->symbols[iter].codeend = RelocLookup(jit, sym->codeend, false);
}
ctx->symbols[iter].name = strbase + sym->name;
ctx->symbols[iter].sym = sym;
plugin->symbols[iter].name = strbase + sym->name;
plugin->symbols[iter].sym = sym;
if (sym->dimcount > 0)
{
cursor += sizeof(sp_fdbg_symbol_t);
arr = (sp_fdbg_arraydim_t *)cursor;
ctx->symbols[iter].dims = arr;
plugin->symbols[iter].dims = arr;
cursor += sizeof(sp_fdbg_arraydim_t) * sym->dimcount;
continue;
}
ctx->symbols[iter].dims = NULL;
plugin->symbols[iter].dims = NULL;
cursor += sizeof(sp_fdbg_symbol_t);
}
}
tracker_t *trk = new tracker_t;
ctx->vm[JITVARS_TRACKER] = trk;
ctx->vm[JITVARS_BASECTX] = data->runtime->GetDefaultContext();
ctx->vm[JITVARS_PROFILER] = g_engine2.GetProfiler();
ctx->vm[JITVARS_PLUGIN] = data->runtime->m_pPlugin;
trk->pBase = (ucell_t *)malloc(1024);
trk->pCur = trk->pBase;
trk->size = 1024 / sizeof(cell_t);
functracker_t *fnc = new functracker_t;
ctx->vm[JITVARS_FUNCINFO] = fnc;
ctx->vm[JITVARS_REBASE] = data->rebase;
fnc->code_size = codemem;
fnc->num_functions = data->func_idx;
/* clean up relocation+compilation memory */
data->rebase = NULL;
AbortCompilation(co);
co->Abort();
*err = SP_ERROR_NONE;
return ctx;
return true;
}
SPVM_NATIVE_FUNC JITX86::CreateFakeNative(SPVM_FAKENATIVE_FUNC callback, void *pData)
@ -2851,126 +2886,146 @@ void JITX86::DestroyFakeNative(SPVM_NATIVE_FUNC func)
engine->FreePageMemory((void *)func);
}
const char *JITX86::GetVMName()
{
return "JIT (x86)";
}
int JITX86::ContextExecute(sp_context_t *ctx, uint32_t code_idx, cell_t *result)
int JITX86::ContextExecute(sp_plugin_t *pl, sp_context_t *ctx, uint32_t code_idx, cell_t *result)
{
typedef int (*CONTEXT_EXECUTE)(sp_context_t *, uint32_t, cell_t *);
CONTEXT_EXECUTE fn = (CONTEXT_EXECUTE)ctx->codebase;
CONTEXT_EXECUTE fn = (CONTEXT_EXECUTE)pl->codebase;
return fn(ctx, code_idx, result);
}
void JITX86::FreeContext(sp_context_t *ctx)
{
engine->FreePageMemory(ctx->codebase);
delete [] ctx->memory;
delete [] ctx->files;
delete [] ctx->lines;
delete [] ctx->natives;
delete [] ctx->publics;
delete [] ctx->pubvars;
delete [] ctx->symbols;
engine->BaseFree(ctx->vm[JITVARS_REBASE]);
free(((tracker_t *)(ctx->vm[JITVARS_TRACKER]))->pBase);
delete (tracker_t *)ctx->vm[JITVARS_TRACKER];
delete (functracker_t *)ctx->vm[JITVARS_FUNCINFO];
delete ctx;
}
ICompilation *JITX86::StartCompilation(sp_plugin_t *plugin)
ICompilation *JITX86::StartCompilation()
{
CompData *data = new CompData;
data->jit_float_table = NULL;
return data;
}
void CompData::SetRuntime(BaseRuntime *runtime)
{
uint32_t max_natives = plugin->info.natives_num;
const char *strbase = plugin->info.stringbase;
data->plugin = plugin;
data->inline_level = JIT_INLINE_ERRORCHECKS|JIT_INLINE_NATIVES;
data->error_set = SP_ERROR_NONE;
plugin = runtime->m_pPlugin;
inline_level = JIT_INLINE_ERRORCHECKS|JIT_INLINE_NATIVES;
error_set = SP_ERROR_NONE;
data->jit_float_table = new floattbl_t[max_natives];
jit_float_table = new floattbl_t[max_natives];
for (uint32_t i=0; i<max_natives; i++)
{
const char *name = strbase + plugin->info.natives[i].name;
if (!strcmp(name, "FloatAbs"))
{
data->jit_float_table[i].found = true;
data->jit_float_table[i].index = OP_FABS;
jit_float_table[i].found = true;
jit_float_table[i].index = OP_FABS;
} else if (!strcmp(name, "FloatAdd")) {
data->jit_float_table[i].found = true;
data->jit_float_table[i].index = OP_FLOATADD;
jit_float_table[i].found = true;
jit_float_table[i].index = OP_FLOATADD;
} else if (!strcmp(name, "FloatSub")) {
data->jit_float_table[i].found = true;
data->jit_float_table[i].index = OP_FLOATSUB;
jit_float_table[i].found = true;
jit_float_table[i].index = OP_FLOATSUB;
} else if (!strcmp(name, "FloatMul")) {
data->jit_float_table[i].found = true;
data->jit_float_table[i].index = OP_FLOATMUL;
jit_float_table[i].found = true;
jit_float_table[i].index = OP_FLOATMUL;
} else if (!strcmp(name, "FloatDiv")) {
data->jit_float_table[i].found = true;
data->jit_float_table[i].index = OP_FLOATDIV;
jit_float_table[i].found = true;
jit_float_table[i].index = OP_FLOATDIV;
} else if (!strcmp(name, "float")) {
data->jit_float_table[i].found = true;
data->jit_float_table[i].index = OP_FLOAT;
jit_float_table[i].found = true;
jit_float_table[i].index = OP_FLOAT;
} else if (!strcmp(name, "FloatCompare")) {
data->jit_float_table[i].found = true;
data->jit_float_table[i].index = OP_FLOATCMP;
jit_float_table[i].found = true;
jit_float_table[i].index = OP_FLOATCMP;
} else if (!strcmp(name, "RoundToZero")) {
data->jit_float_table[i].found = true;
data->jit_float_table[i].index = OP_RND_TO_ZERO;
jit_float_table[i].found = true;
jit_float_table[i].index = OP_RND_TO_ZERO;
} else if (!strcmp(name, "RoundToCeil")) {
data->jit_float_table[i].found = true;
data->jit_float_table[i].index = OP_RND_TO_CEIL;
jit_float_table[i].found = true;
jit_float_table[i].index = OP_RND_TO_CEIL;
} else if (!strcmp(name, "RoundToFloor")) {
data->jit_float_table[i].found = true;
data->jit_float_table[i].index = OP_RND_TO_FLOOR;
jit_float_table[i].found = true;
jit_float_table[i].index = OP_RND_TO_FLOOR;
} else if (!strcmp(name, "RoundToNearest")) {
data->jit_float_table[i].found = true;
data->jit_float_table[i].index = OP_RND_TO_NEAREST;
jit_float_table[i].found = true;
jit_float_table[i].index = OP_RND_TO_NEAREST;
}
}
}
ICompilation *JITX86::StartCompilation(BaseRuntime *runtime)
{
CompData *data = new CompData;
data->SetRuntime(runtime);
return data;
}
void JITX86::AbortCompilation(ICompilation *co)
void CompData::Abort()
{
if (((CompData *)co)->rebase)
if (rebase)
{
engine->BaseFree(((CompData *)co)->rebase);
engine->BaseFree(rebase);
}
delete [] ((CompData *)co)->jit_float_table;
delete (CompData *)co;
delete [] jit_float_table;
delete this;
}
bool JITX86::SetCompilationOption(ICompilation *co, const char *key, const char *val)
void JITX86::FreeContextVars(sp_context_t *ctx)
{
CompData *data = (CompData *)co;
free(((tracker_t *)(ctx->vm[JITVARS_TRACKER]))->pBase);
delete (tracker_t *)ctx->vm[JITVARS_TRACKER];
}
void JITX86::FreePluginVars(sp_plugin_t *pl)
{
delete [] pl->files;
delete [] pl->lines;
delete [] pl->natives;
delete [] pl->publics;
delete [] pl->pubvars;
delete [] pl->symbols;
if (pl->codebase != NULL)
{
g_engine1.FreePageMemory(pl->codebase);
pl->codebase = NULL;
}
pl->files = NULL;
pl->lines = NULL;
pl->natives = NULL;
pl->publics = NULL;
pl->pubvars = NULL;
pl->symbols = NULL;
}
bool CompData::SetOption(const char *key, const char *val)
{
if (strcmp(key, SP_JITCONF_DEBUG) == 0)
{
if ((atoi(val) == 1) || !strcmp(val, "yes"))
{
data->debug = true;
debug = true;
} else {
data->debug = false;
debug = false;
}
if (data->debug && !(data->plugin->flags & SP_FLAG_DEBUG))
if (debug && plugin && !(plugin->flags & SP_FLAG_DEBUG))
{
data->debug = false;
debug = false;
return false;
}
return true;
}
else if (strcmp(key, SP_JITCONF_PROFILE) == 0)
{
data->profile = atoi(val);
profile = atoi(val);
/** Callbacks must be profiled to profile functions! */
if ((data->profile & SP_PROF_FUNCTIONS) == SP_PROF_FUNCTIONS)
if ((profile & SP_PROF_FUNCTIONS) == SP_PROF_FUNCTIONS)
{
data->profile |= SP_PROF_CALLBACKS;
profile |= SP_PROF_CALLBACKS;
}
return true;
@ -2979,83 +3034,3 @@ bool JITX86::SetCompilationOption(ICompilation *co, const char *key, const char
return false;
}
unsigned int JITX86::GetAPIVersion()
{
return SOURCEPAWN_VM_API_VERSION;
}
bool JITX86::FunctionPLookup(const sp_context_t *ctx, uint32_t code_addr, unsigned int *result)
{
uint8_t *rebase = (uint8_t *)ctx->vm[JITVARS_REBASE];
/* Is this within the pcode bounds? */
if (code_addr >= ctx->plugin->pcode_size - sizeof(uint32_t))
{
return false;
}
/* Relocate this */
code_addr = *(jitoffs_t *)(rebase + code_addr);
/* Check if this is in the relocation bounds */
functracker_t *fnc = (functracker_t *)ctx->vm[JITVARS_FUNCINFO];
if (code_addr >= fnc->code_size)
{
return false;
}
/* Get the function info and sanity check */
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;
}
bool JITX86::FunctionLookup(const sp_context_t *ctx, uint32_t code_addr, unsigned int *result)
{
/* Check if this is in the relocation bounds */
functracker_t *fnc = (functracker_t *)ctx->vm[JITVARS_FUNCINFO];
if (code_addr >= fnc->code_size)
{
return false;
}
/* Get the function info and sanity check */
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;
}
const char *JITX86::GetVersionString()
{
return SVN_FULL_VERSION;
}
const char *JITX86::GetCPUOptimizations()
{
return "Generic i686";
}

View File

@ -35,6 +35,8 @@
#include <sp_vm_types.h>
#include <sp_vm_api.h>
#include <jit_helpers.h>
#include "../jit_shared.h"
#include "../BaseRuntime.h"
using namespace SourcePawn;
@ -44,11 +46,14 @@ using namespace SourcePawn;
#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
#define JITVARS_REBASE 2 //important: hi, i'm bail
#define JITVARS_BASECTX 1 //important: don't change this aWOAWOGJQG I LIKE HAM
#define JITVARS_PROFILER 2 //profiler
#define JITVARS_PLUGIN 3 //sp_plugin_t
#define sDIMEN_MAX 5 //this must mirror what the compiler has.
#define GET_CONTEXT(c) ((IPluginContext *)c->vm[JITVARS_BASECTX])
typedef struct tracker_s
{
size_t size;
@ -87,7 +92,11 @@ public:
error_set(SP_ERROR_NONE), func_idx(0)
{
};
bool SetOption(const char *key, const char *val);
void SetRuntime(BaseRuntime *runtime);
void Abort();
public:
BaseRuntime *runtime; /* runtime handle */
sp_plugin_t *plugin; /* plugin handle */
bool debug; /* whether to compile debug mode */
int profile; /* profiling flags */
@ -116,22 +125,15 @@ public:
uint32_t codesize; /* total codesize */
};
class JITX86 : public IVirtualMachine
class JITX86
{
public:
const char *GetVMName();
ICompilation *StartCompilation(sp_plugin_t *plugin);
bool SetCompilationOption(ICompilation *co, const char *key, const char *val);
sp_context_t *CompileToContext(ICompilation *co, int *err);
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);
bool FunctionPLookup(const sp_context_t *ctx, uint32_t code_addr, unsigned int *result);
unsigned int FunctionCount(const sp_context_t *ctx);
const char *GetVersionString();
const char *GetCPUOptimizations();
ICompilation *StartCompilation(BaseRuntime *runtime);
ICompilation *StartCompilation();
bool Compile(ICompilation *co, BaseRuntime *runtime, int *err);
void FreePluginVars(sp_plugin_t *pl);
void FreeContextVars(sp_context_t *ctx);
int ContextExecute(sp_plugin_t *pl, sp_context_t *ctx, uint32_t code_idx, cell_t *result);
SPVM_NATIVE_FUNC CreateFakeNative(SPVM_FAKENATIVE_FUNC callback, void *pData);
void DestroyFakeNative(SPVM_NATIVE_FUNC func);
};
@ -157,6 +159,6 @@ jitoffs_t RelocLookup(JitWriter *jit, cell_t pcode_offs, bool relative=false);
#define AMX_INFO_CONTEXT 12 //physical
#define AMX_INFO_STACKTOP 16 //relocated
extern ISourcePawnEngine *engine;
extern JITX86 g_Jit1;
#endif //_INCLUDE_SOURCEPAWN_JIT_X86_H_

View File

@ -40,6 +40,7 @@
jitoffs_t Write_Execute_Function(JitWriter *jit)
{
CompData *co = (CompData *)jit->data;
/**
* The variables we're passed in:
* sp_context_t *ctx, uint32_t code_idx, cell_t *result
@ -76,14 +77,14 @@ jitoffs_t Write_Execute_Function(JitWriter *jit)
//mov [esi+12], eax - store context into info pointer
//mov ecx, [eax+<offs>] - get heap pointer
//mov [esi+4], ecx - store heap into info pointer
//mov ebp, [eax+<offs>] - get data pointer
//mov ebp, <addr> - get data pointer
IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, REG_EBP, 16);
IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_INFO, REG_EAX, AMX_INFO_RETVAL);
IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, REG_EBP, 8);
IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_INFO, REG_EAX, AMX_INFO_CONTEXT);
IA32_Mov_Reg_Rm_Disp8(jit, REG_ECX, REG_EAX, offsetof(sp_context_t, hp));
IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_INFO, REG_ECX, AMX_INFO_HEAP);
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_DAT, REG_EAX, offsetof(sp_context_t, memory));
IA32_Mov_Reg_Imm32(jit, AMX_REG_DAT, jit_int32_t(co->plugin->memory));
/* Frame setup */
//mov edi, [eax+<offs>] - get stack pointer
@ -97,15 +98,23 @@ jitoffs_t Write_Execute_Function(JitWriter *jit)
//mov ecx, [eax+<offs>] - copy memsize to temp var
//add ecx, ebp - relocate
//mov [esi+x], ecx - store relocated
IA32_Mov_Reg_Rm_Disp8(jit, REG_ECX, REG_EAX, offsetof(sp_context_t, mem_size));
IA32_Mov_Reg_Imm32(jit, REG_ECX, co->plugin->mem_size);
IA32_Add_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_DAT, MOD_REG);
IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_INFO, REG_ECX, AMX_INFO_STACKTOP);
/* Remaining needed vars */
//mov ecx, [esp+(4*(NUM_INFO_PARAMS+3))+12] - get code index (normally esp+12, but we have another array on the stack)
//add ecx, [eax+<offs>] - add code base to index
//push eax
//mov eax, <addr of addr of code>
//mov eax, [eax]
//add ecx, eax
//pop eax
IA32_Mov_Reg_Esp_Disp8(jit, REG_ECX, 12+(4*(NUM_INFO_PARAMS+3)));
IA32_Add_Reg_Rm_Disp8(jit, REG_ECX, REG_EAX, offsetof(sp_context_t, codebase));
IA32_Push_Reg(jit, REG_EAX);
IA32_Mov_Reg_Imm32(jit, REG_EAX, jit_int32_t(&co->plugin->codebase));
IA32_Mov_Reg_Rm(jit, REG_EAX, REG_EAX, MOD_MEM_REG);
IA32_Add_Reg_Rm(jit, REG_ECX, REG_EAX, MOD_REG);
IA32_Pop_Reg(jit, REG_EAX);
/* by now, everything is set up, so we can call into the plugin */
//call ecx
@ -161,36 +170,30 @@ void Write_BreakDebug(JitWriter *jit)
//push edi
//mov edi, ecx
//mov ecx, [esi+ctx]
//cmp [ecx+dbreak], 0
//jnz :nocall
IA32_Push_Reg(jit, REG_EDI);
IA32_Mov_Reg_Rm(jit, REG_EDI, REG_ECX, MOD_REG);
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_CONTEXT);
IA32_Cmp_Rm_Disp8_Imm8(jit, AMX_REG_TMP, offsetof(sp_context_t, dbreak), 0);
jitoffs_t jmp = IA32_Jump_Cond_Imm8(jit, CC_Z, 0);
//:TODO: align the stack to 16bytes like in sysreq.x
/* NOTE, Hack! PUSHAD pushes EDI last which still has the CIP */
//pushad
//push [esi+frm]
//push ctx
//mov ecx, [ecx+dbreak]
//push [ctx+basectx]
//mov ecx, <dbreak>
//call ecx
//add esp, 8
//popad
IA32_Pushad(jit);
IA32_Push_Rm_Disp8(jit, AMX_REG_INFO, AMX_INFO_FRAME); //:TODO: move to regs and push? and dont disp for 0
IA32_Push_Reg(jit, AMX_REG_TMP);
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_TMP, offsetof(sp_context_t, dbreak));
IA32_Push_Rm_Disp8(jit, AMX_REG_TMP, offsetof(sp_context_t, vm[JITVARS_BASECTX]));
IA32_Mov_Reg_Imm32(jit, AMX_REG_TMP, jit_int32_t(((CompData *)jit->data)->plugin->dbreak));
IA32_Call_Reg(jit, AMX_REG_TMP);
IA32_Add_Rm_Imm8(jit, REG_ESP, 4*2, MOD_REG);
IA32_Popad(jit);
//:nocall
//pop edi
//ret
IA32_Pop_Reg(jit, REG_EDI);
IA32_Send_Jump8_Here(jit, jmp);
IA32_Return(jit);
}
@ -314,7 +317,7 @@ void Write_Check_VerifyAddr(JitWriter *jit, jit_uint8_t reg)
/* Part 1: Check if we're in the memory bounds */
//cmp <reg>, <stpu>
//jae :error
IA32_Cmp_Rm_Imm32(jit, MOD_REG, reg, ((CompData *)jit->data)->plugin->memory);
IA32_Cmp_Rm_Imm32(jit, MOD_REG, reg, ((CompData *)jit->data)->plugin->mem_size);
IA32_Jump_Cond_Imm32_Abs(jit, CC_AE, ((CompData *)jit->data)->jit_error_memaccess);
/* Part 2: Check if we're in the invalid region between HP and SP */