From 3f38171d8ced8ac17464efe377a0f056c6138844 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Mon, 7 Jul 2008 04:56:29 +0000 Subject: [PATCH] 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 --- sourcepawn/jit/BaseRuntime.cpp | 333 +++++++++ sourcepawn/jit/BaseRuntime.h | 57 ++ sourcepawn/jit/dll_exports.cpp | 39 +- sourcepawn/jit/engine2.cpp | 271 +++++++ sourcepawn/jit/engine2.h | 34 + sourcepawn/jit/jit_shared.h | 92 +++ sourcepawn/jit/msvc8/jit-x86.vcproj | 128 +++- sourcepawn/jit/sp_vm_basecontext.cpp | 971 ++++++++------------------ sourcepawn/jit/sp_vm_basecontext.h | 142 ++-- sourcepawn/jit/sp_vm_engine.cpp | 280 +------- sourcepawn/jit/sp_vm_engine.h | 12 +- sourcepawn/jit/sp_vm_function.cpp | 105 ++- sourcepawn/jit/sp_vm_function.h | 35 +- sourcepawn/jit/{x86 => }/version.rc | 0 sourcepawn/jit/x86/jit_x86.cpp | 401 +++++------ sourcepawn/jit/x86/jit_x86.h | 36 +- sourcepawn/jit/x86/opcode_helpers.cpp | 35 +- 17 files changed, 1574 insertions(+), 1397 deletions(-) create mode 100644 sourcepawn/jit/BaseRuntime.cpp create mode 100644 sourcepawn/jit/BaseRuntime.h create mode 100644 sourcepawn/jit/engine2.cpp create mode 100644 sourcepawn/jit/engine2.h create mode 100644 sourcepawn/jit/jit_shared.h rename sourcepawn/jit/{x86 => }/version.rc (100%) diff --git a/sourcepawn/jit/BaseRuntime.cpp b/sourcepawn/jit/BaseRuntime.cpp new file mode 100644 index 00000000..86a8fd36 --- /dev/null +++ b/sourcepawn/jit/BaseRuntime.cpp @@ -0,0 +1,333 @@ +#include +#include +#include +#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; iinfo.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); +} diff --git a/sourcepawn/jit/BaseRuntime.h b/sourcepawn/jit/BaseRuntime.h new file mode 100644 index 00000000..38527987 --- /dev/null +++ b/sourcepawn/jit/BaseRuntime.h @@ -0,0 +1,57 @@ +#ifndef _INCLUDE_SOURCEPAWN_JIT_RUNTIME_H_ +#define _INCLUDE_SOURCEPAWN_JIT_RUNTIME_H_ + +#include +#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_ diff --git a/sourcepawn/jit/dll_exports.cpp b/sourcepawn/jit/dll_exports.cpp index 522eabe3..91a80743 100644 --- a/sourcepawn/jit/dll_exports.cpp +++ b/sourcepawn/jit/dll_exports.cpp @@ -31,44 +31,21 @@ #include #include -#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__ diff --git a/sourcepawn/jit/engine2.cpp b/sourcepawn/jit/engine2.cpp new file mode 100644 index 00000000..8626fece --- /dev/null +++ b/sourcepawn/jit/engine2.cpp @@ -0,0 +1,271 @@ +#include +#include +#include +#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(); +} diff --git a/sourcepawn/jit/engine2.h b/sourcepawn/jit/engine2.h new file mode 100644 index 00000000..7a92e0aa --- /dev/null +++ b/sourcepawn/jit/engine2.h @@ -0,0 +1,34 @@ +#ifndef _INCLUDE_SOURCEPAWN_ENGINE_2_H_ +#define _INCLUDE_SOURCEPAWN_ENGINE_2_H_ + +#include + +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_ diff --git a/sourcepawn/jit/jit_shared.h b/sourcepawn/jit/jit_shared.h new file mode 100644 index 00000000..e4b92e39 --- /dev/null +++ b/sourcepawn/jit/jit_shared.h @@ -0,0 +1,92 @@ +#ifndef _INCLUDE_SOURCEPAWN_JIT_SHARED_H_ +#define _INCLUDE_SOURCEPAWN_JIT_SHARED_H_ + +#include + +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_ diff --git a/sourcepawn/jit/msvc8/jit-x86.vcproj b/sourcepawn/jit/msvc8/jit-x86.vcproj index 3e75a734..a1d74a10 100644 --- a/sourcepawn/jit/msvc8/jit-x86.vcproj +++ b/sourcepawn/jit/msvc8/jit-x86.vcproj @@ -40,7 +40,7 @@ + + + + + + + + + + + + - - @@ -211,12 +231,20 @@ Filter="h;hpp;hxx;hm;inl;inc;xsd" UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" > + + + + + + @@ -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}" > - - - - - - @@ -266,27 +286,75 @@ Name="SDK" > + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sourcepawn/jit/sp_vm_basecontext.cpp b/sourcepawn/jit/sp_vm_basecontext.cpp index b963d523..36315f12 100644 --- a/sourcepawn/jit/sp_vm_basecontext.cpp +++ b/sourcepawn/jit/sp_vm_basecontext.cpp @@ -36,66 +36,19 @@ #include "sp_vm_api.h" #include "sp_vm_basecontext.h" #include "sp_vm_engine.h" - -#ifdef SOURCEMOD_BUILD -#include "Logger.h" -#include "DebugReporter.h" -#endif +#include "x86/jit_x86.h" using namespace SourcePawn; -extern SourcePawnEngine g_SourcePawn; - #define CELLBOUNDMAX (INT_MAX/sizeof(cell_t)) #define STACKMARGIN ((cell_t)(16*sizeof(cell_t))) -int GlobalDebugBreak(sp_context_t *ctx, uint32_t frm, uint32_t cip) +BaseContext::BaseContext(BaseRuntime *pRuntime) { - g_SourcePawn.RunTracer(ctx, frm, cip); - - return SP_ERROR_NONE; -} - -BaseContext::BaseContext(sp_context_t *_ctx) -{ - ctx = _ctx; - ctx->context = this; - ctx->dbreak = GlobalDebugBreak; - - if (ctx->prof_flags != 0) - { - ctx->profiler = sm_profiler; - } + m_pRuntime = pRuntime; m_InExec = false; m_CustomMsg = false; - m_funcsnum = ctx->vmbase->FunctionCount(ctx); -#if 0 - m_priv_funcs = NULL; -#endif - m_pub_funcs = NULL; - -#if 0 - /** - * Note: Since the m_plugin member will never change, - * it is safe to assume the function count will never change - */ - if (m_funcsnum && m_priv_funcs == NULL) - { - m_priv_funcs = new CFunction *[m_funcsnum]; - memset(m_priv_funcs, 0, sizeof(CFunction *) * m_funcsnum); - } else { - m_priv_funcs = NULL; - } -#endif - - if (ctx->plugin->info.publics_num && m_pub_funcs == NULL) - { - m_pub_funcs = new CFunction *[ctx->plugin->info.publics_num]; - memset(m_pub_funcs, 0, sizeof(CFunction *) * ctx->plugin->info.publics_num); - } else { - m_pub_funcs = NULL; - } /* Initialize the null references */ uint32_t index; @@ -104,7 +57,9 @@ BaseContext::BaseContext(sp_context_t *_ctx) sp_pubvar_t *pubvar; GetPubvarByIndex(index, &pubvar); m_pNullVec = pubvar->offs; - } else { + } + else + { m_pNullVec = NULL; } @@ -113,224 +68,45 @@ BaseContext::BaseContext(sp_context_t *_ctx) sp_pubvar_t *pubvar; GetPubvarByIndex(index, &pubvar); m_pNullString = pubvar->offs; - } else { + } + else + { m_pNullString = NULL; } } -void BaseContext::FlushFunctionCache() -{ - if (m_pub_funcs) - { - for (uint32_t i=0; iplugin->info.publics_num; i++) - { - delete m_pub_funcs[i]; - m_pub_funcs[i] = NULL; - } - } - -#if 0 - if (m_priv_funcs) - { - for (unsigned int i=0; iplugin->info.publics_num; i++) - { - if (!m_pub_funcs[i]) - { - continue; - } - if (GetPublicByIndex(i, &pub) != SP_ERROR_NONE) - { - continue; - } - m_pub_funcs[i]->Set(pub->code_offs, this, pub->funcid, i); - } - } - -#if 0 - if (m_priv_funcs) - { - for (unsigned int i=0; i - } - } -#endif -} - BaseContext::~BaseContext() { - FlushFunctionCache(); - delete [] m_pub_funcs; - m_pub_funcs = NULL; -#if 0 - delete [] m_priv_funcs; - m_priv_funcs = NULL; -#endif -} - -void BaseContext::SetContext(sp_context_t *_ctx) -{ - if (!_ctx) - { - return; - } - - ctx = _ctx; - ctx->context = this; - ctx->dbreak = GlobalDebugBreak; - - if (ctx->prof_flags != 0) - { - ctx->profiler = sm_profiler; - } - - RefreshFunctionCache(); } IVirtualMachine *BaseContext::GetVirtualMachine() { - return (IVirtualMachine *)ctx->vmbase; + return NULL; } sp_context_t *BaseContext::GetContext() { - return ctx; + return &m_ctx; } bool BaseContext::IsDebugging() { - return (ctx->flags & SPFLAG_PLUGIN_DEBUG); + return m_pRuntime->IsDebugging(); } -int BaseContext::SetDebugBreak(SPVM_DEBUGBREAK newpfn, SPVM_DEBUGBREAK *oldpfn) +int BaseContext::SetDebugBreak(void *newpfn, void *oldpfn) { - if (!IsDebugging()) - { - return SP_ERROR_NOTDEBUGGING; - } - - *oldpfn = ctx->dbreak; - ctx->dbreak = newpfn; - - return SP_ERROR_NONE; + return SP_ERROR_ABORTED; } IPluginDebugInfo *BaseContext::GetDebugInfo() { - if (!IsDebugging()) - { - return NULL; - } - return this; + return NULL; } int BaseContext::Execute(uint32_t code_addr, cell_t *result) { - if ((ctx->flags & SPFLAG_PLUGIN_PAUSED) == SPFLAG_PLUGIN_PAUSED) - { - return SP_ERROR_NOT_RUNNABLE; - } - - /* tada, prevent a crash */ - cell_t _ignore_result; - if (!result) - { - result = &_ignore_result; - } - - IVirtualMachine *vm = (IVirtualMachine *)ctx->vmbase; - - uint32_t pushcount = ctx->pushcount; - int err; - - if ((err = PushCell(pushcount++)) != SP_ERROR_NONE) - { -#if defined SOURCEMOD_BUILD - g_DbgReporter.GenerateCodeError(this, code_addr, err, "Stack error; cannot complete execution!"); -#endif - return SP_ERROR_NOT_RUNNABLE; - } - ctx->pushcount = 0; - - cell_t save_sp = ctx->sp + (pushcount * sizeof(cell_t)); - cell_t save_hp = ctx->hp; - uint32_t n_idx = ctx->n_idx; - - bool wasExec = m_InExec; - - /* Clear the error state, if any */ - ctx->n_err = SP_ERROR_NONE; - ctx->n_idx = 0; - m_InExec = true; - m_MsgCache[0] = '\0'; - m_CustomMsg = false; - - g_SourcePawn.PushTracer(ctx); - - err = vm->ContextExecute(ctx, code_addr, result); - - m_InExec = wasExec; - - /** - * :TODO: Calling from a plugin in here will erase the cached message... - * Should that be documented? - */ - g_SourcePawn.PopTracer(err, m_CustomMsg ? m_MsgCache : NULL); - -#if defined SOURCEMOD_BUILD - if (err == SP_ERROR_NONE) - { - if (ctx->sp != save_sp) - { - g_DbgReporter.GenerateCodeError(this, - code_addr, - SP_ERROR_STACKLEAK, - "Stack leak detected: sp:%d should be %d!", - ctx->sp, - save_sp); - } - if (ctx->hp != save_hp) - { - g_DbgReporter.GenerateCodeError(this, - code_addr, - SP_ERROR_HEAPLEAK, - "Heap leak detected: sp:%d should be %d!", - ctx->hp, - save_hp); - } - } -#endif - - if (err != SP_ERROR_NONE) - { - ctx->sp = save_sp; - ctx->hp = save_hp; - } - - ctx->n_idx = n_idx; - ctx->n_err = SP_ERROR_NONE; - m_MsgCache[0] = '\0'; - m_CustomMsg = false; - - return err; + return SP_ERROR_ABORTED; } void BaseContext::SetErrorMessage(const char *msg, va_list ap) @@ -340,6 +116,14 @@ void BaseContext::SetErrorMessage(const char *msg, va_list ap) vsnprintf(m_MsgCache, sizeof(m_MsgCache), msg, ap); } +void BaseContext::_SetErrorMessage(const char *msg, ...) +{ + va_list ap; + va_start(ap, msg); + SetErrorMessage(msg, ap); + va_end(ap); +} + cell_t BaseContext::ThrowNativeErrorEx(int error, const char *msg, ...) { if (!m_InExec) @@ -347,7 +131,7 @@ cell_t BaseContext::ThrowNativeErrorEx(int error, const char *msg, ...) return 0; } - ctx->n_err = error; + m_ctx.n_err = error; if (msg) { @@ -367,7 +151,7 @@ cell_t BaseContext::ThrowNativeError(const char *msg, ...) return 0; } - ctx->n_err = SP_ERROR_NATIVE; + m_ctx.n_err = SP_ERROR_NATIVE; if (msg) { @@ -399,25 +183,25 @@ int BaseContext::HeapAlloc(unsigned int cells, cell_t *local_addr, cell_t **phys /** * Check if the space between the heap and stack is sufficient. */ - if ((cell_t)(ctx->sp - ctx->hp - realmem) < STACKMARGIN) + if ((cell_t)(m_ctx.sp - m_ctx.hp - realmem) < STACKMARGIN) { return SP_ERROR_HEAPLOW; } - addr = (cell_t *)(ctx->memory + ctx->hp); + addr = (cell_t *)(m_pPlugin->memory + m_ctx.hp); /* store size of allocation in cells */ *addr = (cell_t)cells; addr++; - ctx->hp += sizeof(cell_t); + m_ctx.hp += sizeof(cell_t); - *local_addr = ctx->hp; + *local_addr = m_ctx.hp; if (phys_addr) { *phys_addr = addr; } - ctx->hp += realmem; + m_ctx.hp += realmem; return SP_ERROR_NONE; } @@ -429,20 +213,20 @@ int BaseContext::HeapPop(cell_t local_addr) /* check the bounds of this address */ local_addr -= sizeof(cell_t); - if (local_addr < ctx->heap_base || local_addr >= ctx->sp) + if (local_addr < (cell_t)m_pPlugin->data_size || local_addr >= m_ctx.sp) { return SP_ERROR_INVALID_ADDRESS; } - addr = (cell_t *)(ctx->memory + local_addr); + addr = (cell_t *)(m_pPlugin->memory + local_addr); cellcount = (*addr) * sizeof(cell_t); /* check if this memory count looks valid */ - if ((signed)(ctx->hp - cellcount - sizeof(cell_t)) != local_addr) + if ((signed)(m_ctx.hp - cellcount - sizeof(cell_t)) != local_addr) { return SP_ERROR_INVALID_ADDRESS; } - ctx->hp = local_addr; + m_ctx.hp = local_addr; return SP_ERROR_NONE; } @@ -450,255 +234,98 @@ int BaseContext::HeapPop(cell_t local_addr) int BaseContext::HeapRelease(cell_t local_addr) { - if (local_addr < ctx->heap_base) + if (local_addr < (cell_t)m_pPlugin->data_size) { return SP_ERROR_INVALID_ADDRESS; } - ctx->hp = local_addr - sizeof(cell_t); + m_ctx.hp = local_addr - sizeof(cell_t); return SP_ERROR_NONE; } int BaseContext::FindNativeByName(const char *name, uint32_t *index) { - int high; - - high = ctx->plugin->info.natives_num - 1; - - for (uint32_t i=0; iplugin->info.natives_num; i++) - { - if (strcmp(ctx->natives[i].name, name) == 0) - { - if (index) - { - *index = i; - } - return SP_ERROR_NONE; - } - } - - return SP_ERROR_NOT_FOUND; + return m_pRuntime->FindNativeByName(name, index); } int BaseContext::GetNativeByIndex(uint32_t index, sp_native_t **native) { - if (index >= ctx->plugin->info.natives_num) - { - return SP_ERROR_INDEX; - } - - if (native) - { - *native = &(ctx->natives[index]); - } - - return SP_ERROR_NONE; + return m_pRuntime->GetNativeByIndex(index, native); } uint32_t BaseContext::GetNativesNum() { - return ctx->plugin->info.natives_num; + return m_pRuntime->GetNativesNum(); } int BaseContext::FindPublicByName(const char *name, uint32_t *index) { - int diff, high, low; - uint32_t mid; - - high = ctx->plugin->info.publics_num - 1; - low = 0; - - while (low <= high) - { - mid = (low + high) / 2; - diff = strcmp(ctx->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; + return m_pRuntime->FindPublicByName(name, index); } int BaseContext::GetPublicByIndex(uint32_t index, sp_public_t **pblic) { - if (index >= ctx->plugin->info.publics_num) - { - return SP_ERROR_INDEX; - } - - if (pblic) - { - *pblic = &(ctx->publics[index]); - } - - return SP_ERROR_NONE; + return m_pRuntime->GetPublicByIndex(index, pblic); } uint32_t BaseContext::GetPublicsNum() { - return ctx->plugin->info.publics_num; + return m_pRuntime->GetPublicsNum(); } int BaseContext::GetPubvarByIndex(uint32_t index, sp_pubvar_t **pubvar) { - if (index >= ctx->plugin->info.pubvars_num) - { - return SP_ERROR_INDEX; - } - - if (pubvar) - { - *pubvar = &(ctx->pubvars[index]); - } - - return SP_ERROR_NONE; + return m_pRuntime->GetPubvarByIndex(index, pubvar); } int BaseContext::FindPubvarByName(const char *name, uint32_t *index) { - int diff, high, low; - uint32_t mid; - - high = ctx->plugin->info.pubvars_num - 1; - low = 0; - - while (low <= high) - { - mid = (low + high) / 2; - diff = strcmp(ctx->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; + return m_pRuntime->FindPublicByName(name, index); } int BaseContext::GetPubvarAddrs(uint32_t index, cell_t *local_addr, cell_t **phys_addr) { - if (index >= ctx->plugin->info.pubvars_num) - { - return SP_ERROR_INDEX; - } - - *local_addr = ctx->plugin->info.pubvars[index].address; - *phys_addr = ctx->pubvars[index].offs; - - return SP_ERROR_NONE; + return m_pRuntime->GetPubvarAddrs(index, local_addr, phys_addr); } uint32_t BaseContext::GetPubVarsNum() { - return ctx->plugin->info.pubvars_num; + return m_pRuntime->GetPubVarsNum(); } int BaseContext::BindNatives(const sp_nativeinfo_t *natives, unsigned int num, int overwrite) { - uint32_t i, j, max; - - max = ctx->plugin->info.natives_num; - - for (i=0; inatives[i].status == SP_NATIVE_BOUND) && !overwrite) - { - continue; - } - - for (j=0; (natives[j].name) && (!num || jnatives[i].name, natives[j].name)) - { - ctx->natives[i].pfn = natives[j].func; - ctx->natives[i].status = SP_NATIVE_BOUND; - } - } - } - - return SP_ERROR_NONE; + return SP_ERROR_ABORTED; } int BaseContext::BindNative(const sp_nativeinfo_t *native) { - uint32_t index; - int err; - - if ((err = FindNativeByName(native->name, &index)) != SP_ERROR_NONE) - { - return err; - } - - ctx->natives[index].pfn = native->func; - ctx->natives[index].status = SP_NATIVE_BOUND; - - return SP_ERROR_NONE; + return SP_ERROR_ABORTED; } int BaseContext::BindNativeToIndex(uint32_t index, SPVM_NATIVE_FUNC func) { - int err; - sp_native_t *native; - - if ((err = GetNativeByIndex(index, &native)) != SP_ERROR_NONE) - { - return err; - } - - ctx->natives[index].pfn = func; - ctx->natives[index].status = SP_NATIVE_BOUND; - - return SP_ERROR_NONE; + return SP_ERROR_ABORTED; } int BaseContext::BindNativeToAny(SPVM_NATIVE_FUNC native) { - uint32_t nativesnum, i; - - nativesnum = ctx->plugin->info.natives_num; - - for (i=0; inatives[i].status == SP_NATIVE_UNBOUND) - { - ctx->natives[i].pfn = native; - ctx->natives[i].status = SP_NATIVE_BOUND; - } - } - - return SP_ERROR_NONE; + return SP_ERROR_ABORTED; } int BaseContext::LocalToPhysAddr(cell_t local_addr, cell_t **phys_addr) { - if (((local_addr >= ctx->hp) && (local_addr < ctx->sp)) || (local_addr < 0) || ((ucell_t)local_addr >= ctx->mem_size)) + if (((local_addr >= m_ctx.hp) && (local_addr < m_ctx.sp)) + || (local_addr < 0) || ((ucell_t)local_addr >= m_pPlugin->mem_size)) { return SP_ERROR_INVALID_ADDRESS; } if (phys_addr) { - *phys_addr = (cell_t *)(ctx->memory + local_addr); + *phys_addr = (cell_t *)(m_pPlugin->memory + local_addr); } return SP_ERROR_NONE; @@ -706,99 +333,34 @@ int BaseContext::LocalToPhysAddr(cell_t local_addr, cell_t **phys_addr) int BaseContext::PushCell(cell_t value) { - if ((ctx->hp + STACKMARGIN) > (cell_t)(ctx->sp - sizeof(cell_t))) - { - return SP_ERROR_STACKLOW; - } - - ctx->sp -= sizeof(cell_t); - *(cell_t *)(ctx->memory + ctx->sp) = value; - ctx->pushcount++; - - return SP_ERROR_NONE; + return SP_ERROR_ABORTED; } int BaseContext::PushCellsFromArray(cell_t array[], unsigned int numcells) { - unsigned int i; - int err; - - for (i=0; isp += (cell_t)(i * sizeof(cell_t)); - ctx->pushcount -= i; - return err; - } - } - - return SP_ERROR_NONE; + return SP_ERROR_ABORTED; } int BaseContext::PushCellArray(cell_t *local_addr, cell_t **phys_addr, cell_t array[], unsigned int numcells) { - cell_t *ph_addr; - int err; - - if ((err = HeapAlloc(numcells, local_addr, &ph_addr)) != SP_ERROR_NONE) - { - return err; - } - - memcpy(ph_addr, array, numcells * sizeof(cell_t)); - - if ((err = PushCell(*local_addr)) != SP_ERROR_NONE) - { - HeapRelease(*local_addr); - return err; - } - - if (phys_addr) - { - *phys_addr = ph_addr; - } - - return SP_ERROR_NONE; + return SP_ERROR_ABORTED; } int BaseContext::LocalToString(cell_t local_addr, char **addr) { - if (((local_addr >= ctx->hp) && (local_addr < ctx->sp)) || (local_addr < 0) || ((ucell_t)local_addr >= ctx->mem_size)) + if (((local_addr >= m_ctx.hp) && (local_addr < m_ctx.sp)) + || (local_addr < 0) || ((ucell_t)local_addr >= m_pPlugin->mem_size)) { return SP_ERROR_INVALID_ADDRESS; } - *addr = (char *)(ctx->memory + local_addr); + *addr = (char *)(m_pPlugin->memory + local_addr); return SP_ERROR_NONE; } int BaseContext::PushString(cell_t *local_addr, char **phys_addr, const char *string) { - char *ph_addr; - int err; - unsigned int len, numcells = ((len=strlen(string)) + sizeof(cell_t)) / sizeof(cell_t); - - if ((err = HeapAlloc(numcells, local_addr, (cell_t **)&ph_addr)) != SP_ERROR_NONE) - { - return err; - } - - memcpy(ph_addr, string, len); - ph_addr[len] = '\0'; - - if ((err = PushCell(*local_addr)) != SP_ERROR_NONE) - { - HeapRelease(*local_addr); - return err; - } - - if (phys_addr) - { - *phys_addr = ph_addr; - } - - return SP_ERROR_NONE; + return SP_ERROR_ABORTED; } int BaseContext::StringToLocal(cell_t local_addr, size_t bytes, const char *source) @@ -806,7 +368,8 @@ int BaseContext::StringToLocal(cell_t local_addr, size_t bytes, const char *sour char *dest; size_t len; - if (((local_addr >= ctx->hp) && (local_addr < ctx->sp)) || (local_addr < 0) || ((ucell_t)local_addr >= ctx->mem_size)) + if (((local_addr >= m_ctx.hp) && (local_addr < m_ctx.sp)) + || (local_addr < 0) || ((ucell_t)local_addr >= m_pPlugin->mem_size)) { return SP_ERROR_INVALID_ADDRESS; } @@ -817,7 +380,7 @@ int BaseContext::StringToLocal(cell_t local_addr, size_t bytes, const char *sour } len = strlen(source); - dest = (char *)(ctx->memory + local_addr); + dest = (char *)(m_pPlugin->memory + local_addr); if (len >= bytes) { @@ -874,7 +437,9 @@ int BaseContext::StringToLocalUTF8(cell_t local_addr, size_t maxbytes, const cha size_t len; bool needtocheck = false; - if (((local_addr >= ctx->hp) && (local_addr < ctx->sp)) || (local_addr < 0) || ((ucell_t)local_addr >= ctx->mem_size)) + if (((local_addr >= m_ctx.hp) && (local_addr < m_ctx.sp)) + || (local_addr < 0) + || ((ucell_t)local_addr >= m_pPlugin->mem_size)) { return SP_ERROR_INVALID_ADDRESS; } @@ -885,7 +450,7 @@ int BaseContext::StringToLocalUTF8(cell_t local_addr, size_t maxbytes, const cha } len = strlen(source); - dest = (char *)(ctx->memory + local_addr); + dest = (char *)(m_pPlugin->memory + local_addr); if ((size_t)len >= maxbytes) { @@ -908,172 +473,14 @@ int BaseContext::StringToLocalUTF8(cell_t local_addr, size_t maxbytes, const cha return SP_ERROR_NONE; } -#define USHR(x) ((unsigned int)(x)>>1) - -int BaseContext::LookupFile(ucell_t addr, const char **filename) -{ - int high, low, mid; - - high = ctx->plugin->debug.files_num; - low = -1; - - while (high - low > 1) - { - mid = USHR(low + high); - if (ctx->files[mid].addr <= addr) - { - low = mid; - } else { - high = mid; - } - } - - if (low == -1) - { - return SP_ERROR_NOT_FOUND; - } - - *filename = ctx->files[low].name; - - return SP_ERROR_NONE; -} - -int BaseContext::LookupFunction(ucell_t addr, const char **name) -{ - uint32_t iter, max = ctx->plugin->debug.syms_num; - - for (iter=0; itersymbols[iter].sym->ident == SP_SYM_FUNCTION) - && (ctx->symbols[iter].codestart <= addr) - && (ctx->symbols[iter].codeend > addr)) - { - break; - } - } - - if (iter >= max) - { - return SP_ERROR_NOT_FOUND; - } - - *name = ctx->symbols[iter].name; - - return SP_ERROR_NONE; -} - -int BaseContext::LookupLine(ucell_t addr, uint32_t *line) -{ - int high, low, mid; - - high = ctx->plugin->debug.lines_num; - low = -1; - - while (high - low > 1) - { - mid = USHR(low + high); - if (ctx->lines[mid].addr <= addr) - { - low = mid; - } else { - high = mid; - } - } - - if (low == -1) - { - return SP_ERROR_NOT_FOUND; - } - - /* Since the CIP occurs BEFORE the line, we have to add one */ - *line = ctx->lines[low].line + 1; - - return SP_ERROR_NONE; -} - IPluginFunction *BaseContext::GetFunctionById(funcid_t func_id) { - CFunction *pFunc = NULL; - - if (func_id & 1) - { - func_id >>= 1; - if (func_id >= ctx->plugin->info.publics_num) - { - return NULL; - } - pFunc = m_pub_funcs[func_id]; - if (!pFunc) - { - m_pub_funcs[func_id] = new CFunction(ctx->publics[func_id].code_offs, - this, - ctx->publics[func_id].funcid, - func_id); - pFunc = m_pub_funcs[func_id]; - } - else if (pFunc->IsInvalidated()) - { - pFunc->Set(ctx->publics[func_id].code_offs, - this, - ctx->publics[func_id].funcid, - func_id); - } - } else { - /* :TODO: currently not used */ -#if 0 - func_id >>= 1; - unsigned int index; - if (!g_pVM->FunctionLookup(ctx, func_id, &index)) - { - return NULL; - } - pFunc = m_priv_funcs[func_id]; - if (!pFunc) - { - m_priv_funcs[func_id] = new CFunction(save, this); - pFunc = m_priv_funcs[func_id]; - } -#endif - } - - return pFunc; + return m_pRuntime->GetFunctionById(func_id); } IPluginFunction *BaseContext::GetFunctionByName(const char *public_name) { - uint32_t index; - - if (FindPublicByName(public_name, &index) != SP_ERROR_NONE) - { - return NULL; - } - - CFunction *pFunc = m_pub_funcs[index]; - if (!pFunc) - { - sp_public_t *pub = NULL; - GetPublicByIndex(index, &pub); - if (pub) - { - m_pub_funcs[index] = new CFunction(pub->code_offs, this, pub->funcid, index); - } - pFunc = m_pub_funcs[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; + return m_pRuntime->GetFunctionByName(public_name); } int BaseContext::LocalToStringNULL(cell_t local_addr, char **addr) @@ -1092,7 +499,6 @@ int BaseContext::LocalToStringNULL(cell_t local_addr, char **addr) return SP_ERROR_NONE; } -#if defined SOURCEMOD_BUILD SourceMod::IdentityToken_t *BaseContext::GetIdentity() { return m_pToken; @@ -1112,9 +518,244 @@ cell_t *BaseContext::GetNullRef(SP_NULL_TYPE type) return NULL; } -#endif bool BaseContext::IsInExec() { return m_InExec; } + +int BaseContext::Execute(IPluginFunction *function, const cell_t *params, unsigned int num_params, cell_t *result) +{ + int ir; + int serial; + cell_t *sp; + funcid_t fnid; + sp_public_t *pubfunc; + cell_t _ignore_result; + + fnid = function->GetFunctionID(); + + if (fnid & 1) + { + unsigned int public_id; + + public_id = fnid >> 1; + + if (m_pRuntime->GetPublicByIndex(public_id, &pubfunc) != SP_ERROR_NONE) + { + return SP_ERROR_NOT_FOUND; + } + } + else + { + return SP_ERROR_INVALID_ADDRESS; + } + + if (m_pRuntime->IsPaused()) + { + return SP_ERROR_NOT_RUNNABLE; + } + + if (m_ctx.hp + 16*sizeof(cell_t) > (cell_t)(m_ctx.sp - (sizeof(cell_t) * (num_params + 1)))) + { + return SP_ERROR_STACKLOW; + } + + if (result == NULL) + { + result = &_ignore_result; + } + + /* We got this far. It's time to start profiling. */ + + if ((m_pPlugin->prof_flags & SP_PROF_CALLBACKS) == SP_PROF_CALLBACKS) + { + serial = m_pPlugin->profiler->OnCallbackBegin(this, pubfunc); + } + + /* Save our previous state. */ + + bool save_exec; + uint32_t save_n_idx; + cell_t save_sp, save_hp; + + save_sp = m_ctx.sp; + save_hp = m_ctx.hp; + save_exec = m_InExec; + save_n_idx = m_ctx.n_idx; + + /* Push parameters */ + + m_ctx.sp -= sizeof(cell_t) * (num_params + 1); + sp = (cell_t *)(m_pPlugin->memory + m_ctx.sp); + + sp[0] = num_params; + for (unsigned int i = 0; i < num_params; i++) + { + sp[i + 1] = params[i]; + } + + /* Clear internal state */ + m_ctx.n_err = SP_ERROR_NONE; + m_ctx.n_idx = 0; + m_MsgCache[0] = '\0'; + m_CustomMsg = false; + m_InExec = false; + + /* Start the tracer */ + + g_engine1.PushTracer(this); + + /* Execute the function */ + + ir = g_Jit1.ContextExecute(m_pPlugin, &m_ctx, pubfunc->code_offs, result); + + /* Restore some states, stop tracing */ + + m_InExec = save_exec; + + if (ir == SP_ERROR_NONE) + { + m_ctx.n_err = SP_ERROR_NONE; + if (m_ctx.sp != save_sp) + { + ir = SP_ERROR_STACKLEAK; + _SetErrorMessage("Stack leak detected: sp:%d should be %d!", + m_ctx.sp, + save_sp); + } + if (m_ctx.hp != save_hp) + { + ir = SP_ERROR_HEAPLEAK; + _SetErrorMessage("Heap leak detected: hp:%d should be %d!", + m_ctx.hp, + save_hp); + } + } + + m_ctx.sp = save_sp; + m_ctx.hp = save_hp; + + g_engine1.PopTracer(ir, m_CustomMsg ? m_MsgCache : NULL); + + if ((m_pPlugin->prof_flags & SP_PROF_CALLBACKS) == SP_PROF_CALLBACKS) + { + m_pPlugin->profiler->OnCallbackEnd(serial); + } + + m_ctx.n_idx = save_n_idx; + m_ctx.n_err = SP_ERROR_NONE; + m_MsgCache[0] = '\0'; + m_CustomMsg = false; + + return ir; +} + +IPluginRuntime *BaseContext::GetRuntime() +{ + return m_pRuntime; +} + +int BaseRuntime::ApplyCompilationOptions(ICompilation *co) +{ + int err; + + /* The JIT does not destroy anything until it is guaranteed to succeed. */ + if (!g_Jit1.Compile(co, this, &err)) + { + return err; + } + + RefreshFunctionCache(); + + return SP_ERROR_NONE; +} + +DebugInfo::DebugInfo(sp_plugin_t *plugin) : m_pPlugin(plugin) +{ +} + +#define USHR(x) ((unsigned int)(x)>>1) + +int DebugInfo::LookupFile(ucell_t addr, const char **filename) +{ + int high, low, mid; + + high = m_pPlugin->debug.files_num; + low = -1; + + while (high - low > 1) + { + mid = USHR(low + high); + if (m_pPlugin->files[mid].addr <= addr) + { + low = mid; + } else { + high = mid; + } + } + + if (low == -1) + { + return SP_ERROR_NOT_FOUND; + } + + *filename = m_pPlugin->files[low].name; + + return SP_ERROR_NONE; +} + +int DebugInfo::LookupFunction(ucell_t addr, const char **name) +{ + uint32_t iter, max = m_pPlugin->debug.syms_num; + + for (iter=0; itersymbols[iter].sym->ident == SP_SYM_FUNCTION) + && (m_pPlugin->symbols[iter].codestart <= addr) + && (m_pPlugin->symbols[iter].codeend > addr)) + { + break; + } + } + + if (iter >= max) + { + return SP_ERROR_NOT_FOUND; + } + + *name = m_pPlugin->symbols[iter].name; + + return SP_ERROR_NONE; +} + +int DebugInfo::LookupLine(ucell_t addr, uint32_t *line) +{ + int high, low, mid; + + high = m_pPlugin->debug.lines_num; + low = -1; + + while (high - low > 1) + { + mid = USHR(low + high); + if (m_pPlugin->lines[mid].addr <= addr) + { + low = mid; + } else { + high = mid; + } + } + + if (low == -1) + { + return SP_ERROR_NOT_FOUND; + } + + /* Since the CIP occurs BEFORE the line, we have to add one */ + *line = m_pPlugin->lines[low].line + 1; + + return SP_ERROR_NONE; +} + +#undef USHR diff --git a/sourcepawn/jit/sp_vm_basecontext.h b/sourcepawn/jit/sp_vm_basecontext.h index 4b58937e..d56f3ed4 100644 --- a/sourcepawn/jit/sp_vm_basecontext.h +++ b/sourcepawn/jit/sp_vm_basecontext.h @@ -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_ diff --git a/sourcepawn/jit/sp_vm_engine.cpp b/sourcepawn/jit/sp_vm_engine.cpp index 6a28014b..226b6099 100644 --- a/sourcepawn/jit/sp_vm_engine.cpp +++ b/sourcepawn/jit/sp_vm_engine.cpp @@ -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 @@ -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; } diff --git a/sourcepawn/jit/sp_vm_engine.h b/sourcepawn/jit/sp_vm_engine.h index c50f8267..137f1c1e 100644 --- a/sourcepawn/jit/sp_vm_engine.h +++ b/sourcepawn/jit/sp_vm_engine.h @@ -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_ diff --git a/sourcepawn/jit/sp_vm_function.cpp b/sourcepawn/jit/sp_vm_function.cpp index cfc080ab..c94528a0 100644 --- a/sourcepawn/jit/sp_vm_function.cpp +++ b/sourcepawn/jit/sp_vm_function.cpp @@ -32,76 +32,47 @@ #include #include #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; +} + + diff --git a/sourcepawn/jit/sp_vm_function.h b/sourcepawn/jit/sp_vm_function.h index 275143c9..d9fe8f6c 100644 --- a/sourcepawn/jit/sp_vm_function.h +++ b/sourcepawn/jit/sp_vm_function.h @@ -32,7 +32,11 @@ #ifndef _INCLUDE_SOURCEMOD_BASEFUNCTION_H_ #define _INCLUDE_SOURCEMOD_BASEFUNCTION_H_ -#include "sm_globals.h" +#include + +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_ diff --git a/sourcepawn/jit/x86/version.rc b/sourcepawn/jit/version.rc similarity index 100% rename from sourcepawn/jit/x86/version.rc rename to sourcepawn/jit/version.rc diff --git a/sourcepawn/jit/x86/jit_x86.cpp b/sourcepawn/jit/x86/jit_x86.cpp index 8d68c91d..bb35c2dd 100644 --- a/sourcepawn/jit/x86/jit_x86.cpp +++ b/sourcepawn/jit/x86/jit_x86.cpp @@ -35,12 +35,22 @@ #include "jit_x86.h" #include "opcode_helpers.h" #include -#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; iterpublics[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; iterpubvars[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; iternatives[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; iterfiles[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; iterlines[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; itercodestart > 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; iinfo.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"; -} diff --git a/sourcepawn/jit/x86/jit_x86.h b/sourcepawn/jit/x86/jit_x86.h index 9e093831..7b8bdf31 100644 --- a/sourcepawn/jit/x86/jit_x86.h +++ b/sourcepawn/jit/x86/jit_x86.h @@ -35,6 +35,8 @@ #include #include #include +#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_ diff --git a/sourcepawn/jit/x86/opcode_helpers.cpp b/sourcepawn/jit/x86/opcode_helpers.cpp index 8ec41cb6..2b12036c 100644 --- a/sourcepawn/jit/x86/opcode_helpers.cpp +++ b/sourcepawn/jit/x86/opcode_helpers.cpp @@ -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+] - get heap pointer //mov [esi+4], ecx - store heap into info pointer - //mov ebp, [eax+] - get data pointer + //mov ebp, - 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+] - get stack pointer @@ -97,15 +98,23 @@ jitoffs_t Write_Execute_Function(JitWriter *jit) //mov ecx, [eax+] - 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+] - add code base to index + //push eax + //mov eax, + //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, //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 , //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 */