Landed sourcepawn-1.2. The big changes:

1) JIT compilation/optimization now occurs per-function, and only when functions are first used.  We're now officially a whole-method JIT rather than an AOT compiler (albiet, still a simple JIT).  This has two implications: Functions are now much better abstracted internally, and loading a plugin is now much less expensive.  If a function contains calls to other functions, THOSE functions are only compiled when they're invoked as well.

2) I've removed debug mode.  We always show full backtraces now, as there was a very cheap way to implement this which really cleaned up everything.  This is great for a number of reasons -- there's less code, the JIT is better designed, we don't need to relocate debug tables, and best of all we no longer have to tell users to enable debug mode at their own expense.

--HG--
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%402459
This commit is contained in:
David Anderson
2008-08-15 05:22:26 +00:00
parent 95aca7b61b
commit 7875fe1acd
49 changed files with 3475 additions and 1724 deletions
+260 -94
View File
@@ -1,6 +1,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "BaseRuntime.h"
#include "sp_vm_engine.h"
#include "x86/jit_x86.h"
@@ -9,61 +10,225 @@
using namespace SourcePawn;
int GlobalDebugBreak(BaseContext *ctx, uint32_t frm, uint32_t cip)
BaseRuntime::BaseRuntime() : m_Debug(&m_plugin), m_pPlugin(&m_plugin), m_pCtx(NULL),
m_PubFuncs(NULL), m_PubJitFuncs(NULL), m_pCo(NULL), m_CompSerial(0)
{
g_engine1.RunTracer(ctx, frm, cip);
memset(&m_plugin, 0, sizeof(m_plugin));
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;
}
m_pPlugin->dbreak = GlobalDebugBreak;
m_pPlugin->profiler = g_engine2.GetProfiler();
m_FuncCache = NULL;
m_MaxFuncs = 0;
m_NumFuncs = 0;
}
BaseRuntime::~BaseRuntime()
{
for (uint32_t i = 0; i < m_pPlugin->info.publics_num; i++)
for (uint32_t i = 0; i < m_pPlugin->num_publics; i++)
{
delete m_PubFuncs[i];
m_PubFuncs[i] = NULL;
}
delete [] m_PubFuncs;
delete [] m_PubJitFuncs;
ClearCompile();
for (unsigned int i = 0; i < m_NumFuncs; i++)
{
delete m_FuncCache[i];
}
free(m_FuncCache);
delete m_pCtx;
delete m_pCo;
free(m_pPlugin->base);
delete [] m_pPlugin->memory;
delete [] m_pPlugin->publics;
delete [] m_pPlugin->pubvars;
delete [] m_pPlugin->natives;
delete m_pPlugin;
free(m_pPlugin->name);
}
void BaseRuntime::ClearCompile()
static cell_t InvalidNative(IPluginContext *pCtx, const cell_t *params)
{
g_Jit1.FreeContextVars(m_pCtx->GetCtx());
g_Jit1.FreePluginVars(m_pPlugin);
return pCtx->ThrowNativeErrorEx(SP_ERROR_INVALID_NATIVE, "Invalid native");
}
int BaseRuntime::CreateFromMemory(sp_file_hdr_t *hdr, uint8_t *base)
{
int set_err;
char *nameptr;
uint8_t sectnum = 0;
sp_plugin_t *plugin = m_pPlugin;
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;
plugin->base_size = hdr->imagesize;
set_err = SP_ERROR_NONE;
/* We have to read the name section first */
for (sectnum = 0; sectnum < hdr->sections; sectnum++)
{
nameptr = (char *)(base + hdr->stringtab + secptr[sectnum].nameoffs);
if (strcmp(nameptr, ".names") == 0)
{
plugin->stringbase = (const char *)(base + secptr[sectnum].dataoffs);
break;
}
}
sectnum = 0;
/* Now read the rest of the sections */
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);
if (cod->codeversion < SP_CODEVERS_JIT1)
{
return SP_ERROR_CODE_TOO_OLD;
}
else if (cod->codeversion > SP_CODEVERS_JIT2)
{
return SP_ERROR_CODE_TOO_NEW;
}
plugin->pcode = base + secptr->dataoffs + cod->code;
plugin->pcode_size = cod->codesize;
plugin->flags = cod->flags;
plugin->pcode_version = cod->codeversion;
}
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->publics == NULL) && !strcmp(nameptr, ".publics"))
{
sp_file_publics_t *publics;
publics = (sp_file_publics_t *)(base + secptr->dataoffs);
plugin->num_publics = secptr->size / sizeof(sp_file_publics_t);
if (plugin->num_publics > 0)
{
plugin->publics = new sp_public_t[plugin->num_publics];
for (uint32_t i = 0; i < plugin->num_publics; i++)
{
plugin->publics[i].code_offs = publics[i].address;
plugin->publics[i].funcid = (i << 1) | 1;
plugin->publics[i].name = plugin->stringbase + publics[i].name;
}
}
}
else if ((plugin->pubvars == NULL) && !strcmp(nameptr, ".pubvars"))
{
sp_file_pubvars_t *pubvars;
pubvars = (sp_file_pubvars_t *)(base + secptr->dataoffs);
plugin->num_pubvars = secptr->size / sizeof(sp_file_pubvars_t);
if (plugin->num_pubvars > 0)
{
plugin->pubvars = new sp_pubvar_t[plugin->num_pubvars];
for (uint32_t i = 0; i < plugin->num_pubvars; i++)
{
plugin->pubvars[i].name = plugin->stringbase + pubvars[i].name;
plugin->pubvars[i].offs = (cell_t *)(plugin->memory + pubvars[i].address);
}
}
}
else if ((plugin->natives == NULL) && !strcmp(nameptr, ".natives"))
{
sp_file_natives_t *natives;
natives = (sp_file_natives_t *)(base + secptr->dataoffs);
plugin->num_natives = secptr->size / sizeof(sp_file_natives_t);
if (plugin->num_natives > 0)
{
plugin->natives = new sp_native_t[plugin->num_natives];
for (uint32_t i = 0; i < plugin->num_natives; i++)
{
plugin->natives[i].flags = 0;
plugin->natives[i].pfn = InvalidNative;
plugin->natives[i].status = SP_NATIVE_UNBOUND;
plugin->natives[i].user = NULL;
plugin->natives[i].name = plugin->stringbase + natives[i].name;
}
}
}
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 == NULL || plugin->data == NULL)
{
return SP_ERROR_FILE_FORMAT;
}
if ((plugin->flags & SP_FLAG_DEBUG) && (!(plugin->debug.files) || !(plugin->debug.lines) || !(plugin->debug.symbols)))
{
return SP_ERROR_FILE_FORMAT;
}
if (m_pPlugin->num_publics > 0)
{
m_PubFuncs = new CFunction *[m_pPlugin->num_publics];
memset(m_PubFuncs, 0, sizeof(CFunction *) * m_pPlugin->num_publics);
m_PubJitFuncs = new JitFunction *[m_pPlugin->num_publics];
memset(m_PubJitFuncs, 0, sizeof(JitFunction *) * m_pPlugin->num_publics);
}
m_pPlugin->profiler = g_engine2.GetProfiler();
m_pCtx = new BaseContext(this);
m_pCo = g_Jit.StartCompilation(this);
return SP_ERROR_NONE;
}
int BaseRuntime::FindNativeByName(const char *name, uint32_t *index)
{
int high;
high = m_pPlugin->info.natives_num - 1;
high = m_pPlugin->num_natives - 1;
for (uint32_t i=0; i<m_pPlugin->info.natives_num; i++)
for (uint32_t i=0; i<m_pPlugin->num_natives; i++)
{
if (strcmp(m_pPlugin->natives[i].name, name) == 0)
{
@@ -80,7 +245,7 @@ int BaseRuntime::FindNativeByName(const char *name, uint32_t *index)
int BaseRuntime::GetNativeByIndex(uint32_t index, sp_native_t **native)
{
if (index >= m_pPlugin->info.natives_num)
if (index >= m_pPlugin->num_natives)
{
return SP_ERROR_INDEX;
}
@@ -96,7 +261,7 @@ int BaseRuntime::GetNativeByIndex(uint32_t index, sp_native_t **native)
uint32_t BaseRuntime::GetNativesNum()
{
return m_pPlugin->info.natives_num;
return m_pPlugin->num_natives;
}
int BaseRuntime::FindPublicByName(const char *name, uint32_t *index)
@@ -104,7 +269,7 @@ int BaseRuntime::FindPublicByName(const char *name, uint32_t *index)
int diff, high, low;
uint32_t mid;
high = m_pPlugin->info.publics_num - 1;
high = m_pPlugin->num_publics - 1;
low = 0;
while (low <= high)
@@ -130,7 +295,7 @@ int BaseRuntime::FindPublicByName(const char *name, uint32_t *index)
int BaseRuntime::GetPublicByIndex(uint32_t index, sp_public_t **pblic)
{
if (index >= m_pPlugin->info.publics_num)
if (index >= m_pPlugin->num_publics)
{
return SP_ERROR_INDEX;
}
@@ -145,12 +310,12 @@ int BaseRuntime::GetPublicByIndex(uint32_t index, sp_public_t **pblic)
uint32_t BaseRuntime::GetPublicsNum()
{
return m_pPlugin->info.publics_num;
return m_pPlugin->num_publics;
}
int BaseRuntime::GetPubvarByIndex(uint32_t index, sp_pubvar_t **pubvar)
{
if (index >= m_pPlugin->info.pubvars_num)
if (index >= m_pPlugin->num_pubvars)
{
return SP_ERROR_INDEX;
}
@@ -168,7 +333,7 @@ int BaseRuntime::FindPubvarByName(const char *name, uint32_t *index)
int diff, high, low;
uint32_t mid;
high = m_pPlugin->info.pubvars_num - 1;
high = m_pPlugin->num_pubvars - 1;
low = 0;
while (low <= high)
@@ -182,9 +347,13 @@ int BaseRuntime::FindPubvarByName(const char *name, uint32_t *index)
*index = mid;
}
return SP_ERROR_NONE;
} else if (diff < 0) {
}
else if (diff < 0)
{
low = mid + 1;
} else {
}
else
{
high = mid - 1;
}
}
@@ -194,12 +363,12 @@ int BaseRuntime::FindPubvarByName(const char *name, uint32_t *index)
int BaseRuntime::GetPubvarAddrs(uint32_t index, cell_t *local_addr, cell_t **phys_addr)
{
if (index >= m_pPlugin->info.pubvars_num)
if (index >= m_pPlugin->num_pubvars)
{
return SP_ERROR_INDEX;
}
*local_addr = m_pPlugin->info.pubvars[index].address;
*local_addr = (uint8_t *)m_pPlugin->pubvars[index].offs - m_pPlugin->memory;
*phys_addr = m_pPlugin->pubvars[index].offs;
return SP_ERROR_NONE;
@@ -207,7 +376,7 @@ int BaseRuntime::GetPubvarAddrs(uint32_t index, cell_t *local_addr, cell_t **phy
uint32_t BaseRuntime::GetPubVarsNum()
{
return m_pPlugin->info.pubvars_num;
return m_pPlugin->num_pubvars;
}
IPluginContext *BaseRuntime::GetDefaultContext()
@@ -217,35 +386,9 @@ IPluginContext *BaseRuntime::GetDefaultContext()
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, (i << 1) | 1, i);
}
}
}
IPluginFunction *BaseRuntime::GetFunctionById(funcid_t func_id)
{
CFunction *pFunc = NULL;
@@ -253,26 +396,18 @@ IPluginFunction *BaseRuntime::GetFunctionById(funcid_t func_id)
if (func_id & 1)
{
func_id >>= 1;
if (func_id >= m_pPlugin->info.publics_num)
if (func_id >= m_pPlugin->num_publics)
{
return NULL;
}
pFunc = m_PubFuncs[func_id];
if (!pFunc)
{
m_PubFuncs[func_id] = new CFunction(m_pPlugin->publics[func_id].code_offs,
this,
m_PubFuncs[func_id] = new CFunction(this,
(func_id << 1) | 1,
func_id);
pFunc = m_PubFuncs[func_id];
}
else if (pFunc->IsInvalidated())
{
pFunc->Set(m_pPlugin->publics[func_id].code_offs,
this,
(func_id << 1) | 1,
func_id);
}
}
return pFunc;
@@ -294,30 +429,17 @@ IPluginFunction *BaseRuntime::GetFunctionByName(const char *public_name)
GetPublicByIndex(index, &pub);
if (pub)
{
m_PubFuncs[index] = new CFunction(pub->code_offs, this, (index << 1) | 1, index);
m_PubFuncs[index] = new CFunction(this, (index << 1) | 1, 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, (index << 1) | 1, index);
}
else
{
pFunc = NULL;
}
}
return pFunc;
}
bool BaseRuntime::IsDebugging()
{
return ((m_pPlugin->run_flags & SPFLAG_PLUGIN_DEBUG) == SPFLAG_PLUGIN_DEBUG);
return true;
}
void BaseRuntime::SetPauseState(bool paused)
@@ -345,8 +467,6 @@ size_t BaseRuntime::GetMemUsage()
mem += sizeof(sp_plugin_t);
mem += sizeof(BaseContext);
mem += m_pPlugin->base_size;
mem += m_pPlugin->jit_codesize;
mem += m_pPlugin->jit_memsize;
return mem;
}
@@ -356,3 +476,49 @@ BaseContext *BaseRuntime::GetBaseContext()
return m_pCtx;
}
int BaseRuntime::ApplyCompilationOptions(ICompilation *co)
{
if (co == NULL)
{
return SP_ERROR_NONE;
}
m_pCo = g_Jit.ApplyOptions(m_pCo, co);
return SP_ERROR_NONE;
}
JitFunction *BaseRuntime::GetJittedFunction(uint32_t idx)
{
assert(idx <= m_NumFuncs);
if (idx == 0 || idx > m_NumFuncs)
{
return NULL;
}
return m_FuncCache[idx - 1];
}
uint32_t BaseRuntime::AddJittedFunction(JitFunction *fn)
{
if (m_NumFuncs + 1 > m_MaxFuncs)
{
if (m_MaxFuncs == 0)
{
m_MaxFuncs = 8;
}
else
{
m_MaxFuncs *= 2;
}
m_FuncCache = (JitFunction **)realloc(
m_FuncCache,
sizeof(JitFunction *) * m_MaxFuncs);
}
m_FuncCache[m_NumFuncs++] = fn;
return m_NumFuncs;
}
+12 -3
View File
@@ -6,6 +6,7 @@
#include "sp_vm_function.h"
class BaseContext;
class JitFunction;
class DebugInfo : public IPluginDebugInfo
{
@@ -23,9 +24,10 @@ private:
class BaseRuntime : public SourcePawn::IPluginRuntime
{
public:
BaseRuntime(sp_plugin_t *pl);
BaseRuntime();
~BaseRuntime();
public:
virtual int CreateFromMemory(sp_file_hdr_t *hdr, uint8_t *base);
virtual bool IsDebugging();
virtual IPluginDebugInfo *GetDebugInfo();
virtual int FindNativeByName(const char *name, uint32_t *index);
@@ -45,16 +47,23 @@ public:
virtual void SetPauseState(bool paused);
virtual bool IsPaused();
virtual size_t GetMemUsage();
JitFunction *GetJittedFunction(uint32_t idx);
uint32_t AddJittedFunction(JitFunction *fn);
public:
BaseContext *GetBaseContext();
private:
void ClearCompile();
void RefreshFunctionCache();
sp_plugin_t m_plugin;
unsigned int m_NumFuncs;
unsigned int m_MaxFuncs;
JitFunction **m_FuncCache;
public:
DebugInfo m_Debug;
sp_plugin_t *m_pPlugin;
BaseContext *m_pCtx;
CFunction **m_PubFuncs;
JitFunction **m_PubJitFuncs;
ICompilation *m_pCo;
unsigned int m_CompSerial;
};
#endif //_INCLUDE_SOURCEPAWN_JIT_RUNTIME_H_
+110 -98
View File
@@ -1,98 +1,110 @@
# (C)2004-2008 SourceMod Development Team
# Makefile written by David "BAILOPAN" Anderson
SMSDK = ../..
SOURCEHOOK = ../../../sourcemm-1.6/sourcehook
#####################################
### EDIT BELOW FOR OTHER PROJECTS ###
#####################################
PROJECT = sourcepawn.jit.x86
OBJECTS = dll_exports.cpp \
x86/jit_x86.cpp \
x86/opcode_helpers.cpp \
sp_vm_basecontext.cpp \
sp_vm_engine.cpp \
sp_vm_function.cpp \
engine2.cpp \
BaseRuntime.cpp \
zlib/adler32.c \
zlib/compress.c \
zlib/crc32.c \
zlib/deflate.c \
zlib/gzio.c \
zlib/infback.c \
zlib/inffast.c \
zlib/inflate.c \
zlib/inftrees.c \
zlib/trees.c \
zlib/uncompr.c \
zlib/zutil.c
##############################################
### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ###
##############################################
C_OPT_FLAGS = -DNDEBUG -O3 -funroll-loops -pipe -fno-strict-aliasing
C_DEBUG_FLAGS = -D_DEBUG -DDEBUG -g -ggdb3
C_GCC4_FLAGS = -fvisibility=hidden
CPP_GCC4_FLAGS = -fvisibility-inlines-hidden
CPP = gcc-4.1
LINK = -static-libgcc
INCLUDE = -I. -I.. -I$(SMSDK)/public -I$(SMSDK)/public/jit -I$(SMSDK)/public/jit/x86 \
-I$(SMSDK)/public/sourcepawn -I$(SOURCEHOOK)
CFLAGS += -D_LINUX -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp -Dstrnicmp=strncasecmp \
-D_snprintf=snprintf -D_vsnprintf=vsnprintf -D_alloca=alloca -Dstrcmpi=strcasecmp -Wall -DHAVE_STDINT_H \
-m32
CPPFLAGS += -Wno-non-virtual-dtor -fno-exceptions -fno-rtti
################################################
### DO NOT EDIT BELOW HERE FOR MOST PROJECTS ###
################################################
ifeq "$(DEBUG)" "true"
BIN_DIR = Debug
CFLAGS += $(C_DEBUG_FLAGS)
else
BIN_DIR = Release
CFLAGS += $(C_OPT_FLAGS)
endif
GCC_VERSION := $(shell $(CPP) -dumpversion >&1 | cut -b1)
ifeq "$(GCC_VERSION)" "4"
CFLAGS += $(C_GCC4_FLAGS)
CPPFLAGS += $(CPP_GCC4_FLAGS)
endif
BINARY = $(PROJECT).so
OBJ_LINUX := $(OBJECTS:%.cpp=$(BIN_DIR)/%.o)
OBJ_LINUX := $(OBJ_LINUX:%.c=$(BIN_DIR)/%.o)
$(BIN_DIR)/%.o: %.c
$(CPP) $(INCLUDE) $(CFLAGS) -o $@ -c $<
$(BIN_DIR)/%.o: %.cpp
$(CPP) $(INCLUDE) $(CFLAGS) $(CPPFLAGS) -o $@ -c $<
all:
mkdir -p $(BIN_DIR)/x86
mkdir -p $(BIN_DIR)/zlib
$(MAKE) -f Makefile jit
jit: $(OBJ_LINUX)
$(CPP) $(INCLUDE) $(OBJ_LINUX) $(LINK) -m32 -shared -ldl -lm -o$(BIN_DIR)/$(BINARY)
debug:
$(MAKE) -f Makefile all DEBUG=true
default: all
clean:
rm -rf $(BIN_DIR)/*.o
rm -rf $(BIN_DIR)/$(BINARY)
# (C)2004-2008 SourceMod Development Team
# Makefile written by David "BAILOPAN" Anderson
SMSDK = ../..
SOURCEHOOK = ../../../sourcemm-1.6/sourcehook
#####################################
### EDIT BELOW FOR OTHER PROJECTS ###
#####################################
PROJECT = sourcepawn.jit.x86
OBJECTS = dll_exports.cpp \
x86/jit_x86.cpp \
x86/opcode_helpers.cpp \
sp_vm_basecontext.cpp \
sp_vm_engine.cpp \
sp_vm_function.cpp \
engine2.cpp \
BaseRuntime.cpp \
jit_function.cpp \
zlib/adler32.c \
zlib/compress.c \
zlib/crc32.c \
zlib/deflate.c \
zlib/gzio.c \
zlib/infback.c \
zlib/inffast.c \
zlib/inflate.c \
zlib/inftrees.c \
zlib/trees.c \
zlib/uncompr.c \
zlib/zutil.c \
OBJECTS += ../../knight/shared/KeCodeAllocator.cpp
##############################################
### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ###
##############################################
C_OPT_FLAGS = -DNDEBUG -O3 -funroll-loops -pipe -fno-strict-aliasing
C_DEBUG_FLAGS = -D_DEBUG -DDEBUG -g -ggdb3
C_GCC4_FLAGS = -fvisibility=hidden
CPP_GCC4_FLAGS = -fvisibility-inlines-hidden
CPP = gcc-4.1
LINK = -static-libgcc
INCLUDE = -I. -I.. -I$(SMSDK)/public -I$(SMSDK)/public/jit -I$(SMSDK)/public/jit/x86 \
-I$(SMSDK)/public/sourcepawn -I$(SOURCEHOOK) -I$(SMSDK)/knight/shared -Ix86
CFLAGS += -D_LINUX -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp -Dstrnicmp=strncasecmp \
-D_snprintf=snprintf -D_vsnprintf=vsnprintf -D_alloca=alloca -Dstrcmpi=strcasecmp -Wall -DHAVE_STDINT_H \
-m32 -Wno-uninitialized -Werror
CPPFLAGS += -Wno-non-virtual-dtor -fno-exceptions -fno-rtti
################################################
### DO NOT EDIT BELOW HERE FOR MOST PROJECTS ###
################################################
ifeq "$(DEBUG)" "true"
BIN_DIR = Debug
CFLAGS += $(C_DEBUG_FLAGS)
else
BIN_DIR = Release
CFLAGS += $(C_OPT_FLAGS)
endif
GCC_VERSION := $(shell $(CPP) -dumpversion >&1 | cut -b1)
ifeq "$(GCC_VERSION)" "4"
CFLAGS += $(C_GCC4_FLAGS)
CPPFLAGS += $(CPP_GCC4_FLAGS)
endif
BINARY = $(PROJECT).so
OBJ_LINUX := $(OBJECTS:../../knight/shared/%.cpp=$(BIN_DIR)/knight/%.o)
OBJ_LINUX := $(OBJ_LINUX:%.cpp=$(BIN_DIR)/%.o)
OBJ_LINUX := $(OBJ_LINUX:%.c=$(BIN_DIR)/%.o)
default: all
$(BIN_DIR)/%.o: %.c
$(CPP) $(INCLUDE) $(CFLAGS) -o $@ -c $<
$(BIN_DIR)/%.o: %.cpp
$(CPP) $(INCLUDE) $(CFLAGS) $(CPPFLAGS) -o $@ -c $<
$(BIN_DIR)/knight/%.o: ../../knight/shared/%.cpp
$(CPP) $(INCLUDE) $(CFLAGS) $(CPPFLAGS) -o $@ -c $<
all:
mkdir -p $(BIN_DIR)/x86
mkdir -p $(BIN_DIR)/zlib
mkdir -p $(BIN_DIR)/knight
$(MAKE) -f Makefile jit
jit: $(OBJ_LINUX)
$(CPP) $(INCLUDE) $(OBJ_LINUX) $(LINK) -m32 -shared -ldl -lm -o$(BIN_DIR)/$(BINARY)
debug:
$(MAKE) -f Makefile all DEBUG=true
clean:
rm -rf $(BIN_DIR)/x86/*.o
rm -rf $(BIN_DIR)/zlib/*.o
rm -rf $(BIN_DIR)/knight/*.o
rm -rf $(BIN_DIR)/*.o
rm -rf $(BIN_DIR)/$(BINARY)
+39 -134
View File
@@ -15,113 +15,9 @@ 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;
@@ -141,7 +37,6 @@ IPluginRuntime *SourcePawnEngine2::LoadPlugin(ICompilation *co, const char *file
if (hdr.magic != SPFILE_MAGIC)
{
error = SP_ERROR_FILE_FORMAT;
fclose(fp);
goto return_error;
}
@@ -168,7 +63,6 @@ IPluginRuntime *SourcePawnEngine2::LoadPlugin(ICompilation *co, const char *file
free(sectheader);
free(uncompdata);
error = SP_ERROR_DECOMPRESSOR;
fclose(fp);
goto return_error;
}
@@ -190,40 +84,41 @@ IPluginRuntime *SourcePawnEngine2::LoadPlugin(ICompilation *co, const char *file
default:
{
error = SP_ERROR_DECOMPRESSOR;
fclose(fp);
goto return_error;
}
}
fclose(fp);
plugin = new sp_plugin_t;
memset(plugin, 0, sizeof(sp_plugin_t));
plugin->base_size = hdr.imagesize;
if (!_ReadPlugin(&hdr, base, plugin, err))
{
delete plugin;
free(base);
return NULL;
}
pRuntime = new BaseRuntime(plugin);
if (co == NULL)
{
co = g_Jit1.StartCompilation(pRuntime);
}
*err = pRuntime->ApplyCompilationOptions(co);
if (*err != SP_ERROR_NONE)
pRuntime = new BaseRuntime();
if ((error = pRuntime->CreateFromMemory(&hdr, base)) != SP_ERROR_NONE)
{
delete pRuntime;
return NULL;
goto return_error;
}
size_t len;
len = strlen(file);
for (size_t i = len - 1; i >= 0 && i < len; i--)
{
if (file[i] == '/'
#if defined WIN32
|| file[i] == '\\'
#endif
)
{
pRuntime->m_pPlugin->name = strdup(&file[i+1]);
break;
}
}
if (pRuntime->m_pPlugin->name == NULL)
{
pRuntime->m_pPlugin->name = strdup(file);
}
pRuntime->ApplyCompilationOptions(co);
return pRuntime;
return_error:
@@ -234,12 +129,12 @@ return_error:
SPVM_NATIVE_FUNC SourcePawnEngine2::CreateFakeNative(SPVM_FAKENATIVE_FUNC callback, void *pData)
{
return g_Jit1.CreateFakeNative(callback, pData);
return g_Jit.CreateFakeNative(callback, pData);
}
void SourcePawnEngine2::DestroyFakeNative(SPVM_NATIVE_FUNC func)
{
g_Jit1.DestroyFakeNative(func);
g_Jit.DestroyFakeNative(func);
}
const char *SourcePawnEngine2::GetEngineName()
@@ -274,10 +169,20 @@ unsigned int SourcePawnEngine2::GetAPIVersion()
ICompilation *SourcePawnEngine2::StartCompilation()
{
return g_Jit1.StartCompilation();
return g_Jit.StartCompilation();
}
const char *SourcePawnEngine2::GetErrorString(int err)
{
return g_engine1.GetErrorString(err);
}
bool SourcePawnEngine2::Initialize()
{
return g_Jit.InitializeJIT();
}
void SourcePawnEngine2::Shutdown()
{
g_Jit.ShutdownJIT();
}
+2
View File
@@ -23,6 +23,8 @@ namespace SourcePawn
void SetProfiler(IProfiler *profiler);
ICompilation *StartCompilation();
const char *GetErrorString(int err);
bool Initialize();
void Shutdown();
public:
IProfiler *GetProfiler();
private:
+23
View File
@@ -0,0 +1,23 @@
#include "jit_function.h"
#include "sp_vm_engine.h"
#include "jit_x86.h"
JitFunction::JitFunction(void *entry_addr, cell_t pcode_offs)
: m_pEntryAddr(entry_addr), m_PcodeOffs(pcode_offs)
{
}
JitFunction::~JitFunction()
{
g_Jit.FreeCode(m_pEntryAddr);
}
void *JitFunction::GetEntryAddress()
{
return m_pEntryAddr;
}
cell_t JitFunction::GetPCodeAddress()
{
return m_PcodeOffs;
}
+19
View File
@@ -0,0 +1,19 @@
#ifndef _INCLUDE_SOURCEPAWN_JIT2_FUNCTION_H_
#define _INCLUDE_SOURCEPAWN_JIT2_FUNCTION_H_
#include <sp_vm_types.h>
class JitFunction
{
public:
JitFunction(void *entry_addr, cell_t pcode_offs);
~JitFunction();
public:
void *GetEntryAddress();
cell_t GetPCodeAddress();
private:
void *m_pEntryAddr;
cell_t m_PcodeOffs;
};
#endif //_INCLUDE_SOURCEPAWN_JIT2_FUNCTION_H_
+27 -36
View File
@@ -5,23 +5,11 @@
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;
#define SP_MAX_RETURN_STACK 1024
/**
* @brief Information about the plugin's debug tables. These are all present if one is present.
*/
* @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 */
@@ -36,12 +24,12 @@ typedef struct sp_plugin_debug_s
class BaseContext;
/**
* Breaks into a debugger
* Params:
* [0] - plugin context
* [1] - frm
* [2] - cip
*/
* Breaks into a debugger
* Params:
* [0] - plugin context
* [1] - frm
* [2] - cip
*/
typedef int (*SPVM_DEBUGBREAK)(BaseContext *, uint32_t, uint32_t);
/**
@@ -59,37 +47,40 @@ namespace SourcePawn
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 */
size_t base_size; /**< Size of the entire plugin base */
void *codebase; /**< Base of generated code and memory */
SPVM_DEBUGBREAK dbreak; /**< Debug break function */
uint8_t *memory; /**< Data chunk */
const char *stringbase; /**< base of string table */
sp_public_t *publics; /**< Public functions table */
uint32_t num_publics; /**< Number of publics. */
sp_pubvar_t *pubvars; /**< Public variables table */
uint32_t num_pubvars; /**< Number of public variables */
sp_native_t *natives; /**< Natives table */
sp_debug_file_t *files; /**< Files */
sp_debug_line_t *lines; /**< Lines */
sp_debug_symbol_t *symbols; /**< Symbols */
uint32_t num_natives; /**< Number of natives */
IProfiler *profiler; /**< Pointer to IProfiler */
uint32_t prof_flags; /**< Profiling flags */
uint32_t run_flags; /**< Runtime flags */
size_t jit_codesize; /**< JIT compiled codesize */
size_t jit_memsize; /**< JIT additional memory */
uint32_t pcode_version; /**< P-Code version number */
char *name; /**< Plugin/script name */
} 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 */
cell_t hp; /**< Heap pointer */
cell_t sp; /**< Stack pointer */
cell_t frm; /**< Frame pointer */
int32_t err_cip; /**< Code pointer last error occurred in */
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 */
cell_t rp; /**< Return stack pointer */
cell_t rstk_cips[SP_MAX_RETURN_STACK];
} sp_context_t;
#define SPFLAG_PLUGIN_DEBUG (1<<0)
//#define SPFLAG_PLUGIN_DEBUG (1<<0)
#define SPFLAG_PLUGIN_PAUSED (1<<1)
#define INVALID_CIP 0xFFFFFFFF
#endif //_INCLUDE_SOURCEPAWN_JIT_SHARED_H_
+2 -2
View File
@@ -32,7 +32,7 @@
#ifndef _INCLUDE_JIT_VERSION_H_
#define _INCLUDE_JIT_VERSION_H_
#define SVN_FULL_VERSION "1.1.0-svn"
#define SVN_FILE_VERSION 1,1,0,2218
#define SVN_FULL_VERSION "1.2.0-svn"
#define SVN_FILE_VERSION 1,2,0,2218
#endif //_INCLUDE_JIT_VERSION_H_
+108 -78
View File
@@ -51,12 +51,43 @@ BaseContext::BaseContext(BaseRuntime *pRuntime)
m_InExec = false;
m_CustomMsg = false;
m_pNullVec = NULL;
m_pNullString = NULL;
/* Initialize the null references */
uint32_t index;
if (FindPubvarByName("NULL_VECTOR", &index) == SP_ERROR_NONE)
{
sp_pubvar_t *pubvar;
GetPubvarByIndex(index, &pubvar);
m_pNullVec = pubvar->offs;
}
else
{
m_pNullVec = NULL;
}
if (FindPubvarByName("NULL_STRING", &index) == SP_ERROR_NONE)
{
sp_pubvar_t *pubvar;
GetPubvarByIndex(index, &pubvar);
m_pNullString = pubvar->offs;
}
else
{
m_pNullString = NULL;
}
m_ctx.hp = m_pPlugin->data_size;
m_ctx.sp = m_pPlugin->mem_size - sizeof(cell_t);
m_ctx.frm = m_ctx.sp;
m_ctx.n_err = SP_ERROR_NONE;
m_ctx.n_idx = SP_ERROR_NONE;
m_ctx.rp = 0;
g_Jit.SetupContextVars(m_pRuntime, this, &m_ctx);
}
BaseContext::~BaseContext()
{
g_Jit.FreeContextVars(&m_ctx);
}
IVirtualMachine *BaseContext::GetVirtualMachine()
@@ -76,7 +107,7 @@ sp_context_t *BaseContext::GetCtx()
bool BaseContext::IsDebugging()
{
return m_pRuntime->IsDebugging();
return true;
}
int BaseContext::SetDebugBreak(void *newpfn, void *oldpfn)
@@ -517,15 +548,15 @@ int BaseContext::Execute2(IPluginFunction *function, const cell_t *params, unsig
int serial;
cell_t *sp;
funcid_t fnid;
JitFunction *fn;
sp_public_t *pubfunc;
cell_t _ignore_result;
unsigned int public_id;
fnid = function->GetFunctionID();
if (fnid & 1)
{
unsigned int public_id;
{
public_id = fnid >> 1;
if (m_pRuntime->GetPublicByIndex(public_id, &pubfunc) != SP_ERROR_NONE)
@@ -560,16 +591,40 @@ int BaseContext::Execute2(IPluginFunction *function, const cell_t *params, unsig
serial = m_pPlugin->profiler->OnCallbackBegin(this, pubfunc);
}
/* See if we have to compile the callee. */
if ((fn = m_pRuntime->m_PubJitFuncs[public_id]) == NULL)
{
uint32_t func_idx;
/* We might not have to - check pcode offset. */
if ((func_idx = FuncLookup((CompData *)m_pRuntime->m_pCo, pubfunc->code_offs)) != 0)
{
fn = m_pRuntime->GetJittedFunction(func_idx);
assert(fn != NULL);
m_pRuntime->m_PubJitFuncs[public_id] = fn;
}
else
{
if ((fn = g_Jit.CompileFunction(m_pRuntime, pubfunc->code_offs, &ir)) == NULL)
{
return ir;
}
m_pRuntime->m_PubJitFuncs[public_id] = fn;
}
}
/* Save our previous state. */
bool save_exec;
uint32_t save_n_idx;
cell_t save_sp, save_hp;
cell_t save_sp, save_hp, save_rp, save_cip;
save_sp = m_ctx.sp;
save_hp = m_ctx.hp;
save_exec = m_InExec;
save_n_idx = m_ctx.n_idx;
save_rp = m_ctx.rp;
save_cip = m_ctx.err_cip;
/* Push parameters */
@@ -589,15 +644,11 @@ int BaseContext::Execute2(IPluginFunction *function, const cell_t *params, unsig
m_CustomMsg = false;
m_InExec = true;
/* Start the tracer */
/* Start the frame tracer */
g_engine1.PushTracer(this);
ir = g_Jit.InvokeFunction(m_pRuntime, fn, result);
/* Execute the function */
ir = g_Jit1.ContextExecute(m_pPlugin, &m_ctx, pubfunc->code_offs, result);
/* Restore some states, stop tracing */
/* Restore some states, stop the frame tracer */
m_InExec = save_exec;
@@ -618,18 +669,30 @@ int BaseContext::Execute2(IPluginFunction *function, const cell_t *params, unsig
m_ctx.hp,
save_hp);
}
if (m_ctx.rp != save_rp)
{
ir = SP_ERROR_STACKLEAK;
_SetErrorMessage("Return stack leak detected: rp:%d should be %d!",
m_ctx.rp,
save_rp);
}
}
if (ir != SP_ERROR_NONE)
{
g_engine1.ReportError(m_pRuntime, ir, m_MsgCache, save_rp);
}
m_ctx.sp = save_sp;
m_ctx.hp = save_hp;
g_engine1.PopTracer(ir, m_CustomMsg ? m_MsgCache : NULL);
m_ctx.rp = save_rp;
if ((m_pPlugin->prof_flags & SP_PROF_CALLBACKS) == SP_PROF_CALLBACKS)
{
m_pPlugin->profiler->OnCallbackEnd(serial);
}
m_ctx.err_cip = save_cip;
m_ctx.n_idx = save_n_idx;
m_ctx.n_err = SP_ERROR_NONE;
m_MsgCache[0] = '\0';
@@ -643,23 +706,6 @@ 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();
m_pCtx->Refresh();
return SP_ERROR_NONE;
}
DebugInfo::DebugInfo(sp_plugin_t *plugin) : m_pPlugin(plugin)
{
}
@@ -676,7 +722,7 @@ int DebugInfo::LookupFile(ucell_t addr, const char **filename)
while (high - low > 1)
{
mid = USHR(low + high);
if (m_pPlugin->files[mid].addr <= addr)
if (m_pPlugin->debug.files[mid].addr <= addr)
{
low = mid;
} else {
@@ -689,33 +735,44 @@ int DebugInfo::LookupFile(ucell_t addr, const char **filename)
return SP_ERROR_NOT_FOUND;
}
*filename = m_pPlugin->files[low].name;
*filename = m_pPlugin->debug.stringbase + m_pPlugin->debug.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;
uint32_t max, iter;
sp_fdbg_symbol_t *sym;
sp_fdbg_arraydim_t *arr;
uint8_t *cursor = (uint8_t *)(m_pPlugin->debug.symbols);
for (iter=0; iter<max; iter++)
max = m_pPlugin->debug.syms_num;
for (iter = 0; iter < max; iter++)
{
if ((m_pPlugin->symbols[iter].sym->ident == SP_SYM_FUNCTION)
&& (m_pPlugin->symbols[iter].codestart <= addr)
&& (m_pPlugin->symbols[iter].codeend > addr))
sym = (sp_fdbg_symbol_t *)cursor;
if (sym->ident == SP_SYM_FUNCTION
&& sym->codestart <= addr
&& sym->codeend > addr)
{
break;
*name = m_pPlugin->debug.stringbase + sym->name;
return SP_ERROR_NONE;
}
if (sym->dimcount > 0)
{
cursor += sizeof(sp_fdbg_symbol_t);
arr = (sp_fdbg_arraydim_t *)cursor;
cursor += sizeof(sp_fdbg_arraydim_t) * sym->dimcount;
continue;
}
cursor += sizeof(sp_fdbg_symbol_t);
}
if (iter >= max)
{
return SP_ERROR_NOT_FOUND;
}
return SP_ERROR_NOT_FOUND;
*name = m_pPlugin->symbols[iter].name;
return SP_ERROR_NONE;
}
int DebugInfo::LookupLine(ucell_t addr, uint32_t *line)
@@ -728,7 +785,7 @@ int DebugInfo::LookupLine(ucell_t addr, uint32_t *line)
while (high - low > 1)
{
mid = USHR(low + high);
if (m_pPlugin->lines[mid].addr <= addr)
if (m_pPlugin->debug.lines[mid].addr <= addr)
{
low = mid;
} else {
@@ -742,7 +799,7 @@ int DebugInfo::LookupLine(ucell_t addr, uint32_t *line)
}
/* Since the CIP occurs BEFORE the line, we have to add one */
*line = m_pPlugin->lines[low].line + 1;
*line = m_pPlugin->debug.lines[low].line + 1;
return SP_ERROR_NONE;
}
@@ -781,30 +838,3 @@ bool BaseContext::GetKey(int k, void **value)
return true;
}
void BaseContext::Refresh()
{
/* Initialize the null references */
uint32_t index;
if (FindPubvarByName("NULL_VECTOR", &index) == SP_ERROR_NONE)
{
sp_pubvar_t *pubvar;
GetPubvarByIndex(index, &pubvar);
m_pNullVec = pubvar->offs;
}
else
{
m_pNullVec = NULL;
}
if (FindPubvarByName("NULL_STRING", &index) == SP_ERROR_NONE)
{
sp_pubvar_t *pubvar;
GetPubvarByIndex(index, &pubvar);
m_pNullString = pubvar->offs;
}
else
{
m_pNullString = NULL;
}
}
+82 -194
View File
@@ -30,23 +30,18 @@
*/
#include "sp_vm_types.h"
#include <sh_memory.h>
/* HACK to avoid including sourcehook.h for just the SH_ASSERT definition */
#if !defined SH_ASSERT
#define SH_ASSERT(x, info)
#include <sh_pagealloc.h>
#undef SH_ASSERT
#else
#include <sh_pagealloc.h>
#endif
#include <malloc.h>
#include <string.h>
#include <assert.h>
#include <KeCodeAllocator.h>
#include "sp_file_headers.h"
#include "sp_vm_engine.h"
#include "zlib/zlib.h"
#include "sp_vm_basecontext.h"
#include "jit_x86.h"
#if defined __GNUC__
#include <unistd.h>
#endif
SourcePawnEngine g_engine1;
@@ -57,12 +52,8 @@ SourcePawnEngine g_engine1;
#include <sys/mman.h>
#endif
#define INVALID_CIP 0xFFFFFFFF
using namespace SourcePawn;
SourceHook::CPageAlloc g_ExeMemory(16);
#define ERROR_MESSAGE_MAX 25
static const char *g_ErrorMsgTable[] =
{
@@ -92,6 +83,8 @@ static const char *g_ErrorMsgTable[] =
"Native detected error",
"Plugin not runnable",
"Call was aborted",
"Plugin format is too old",
"Plugin format is too new",
};
const char *SourcePawnEngine::GetErrorString(int error)
@@ -107,33 +100,10 @@ const char *SourcePawnEngine::GetErrorString(int error)
SourcePawnEngine::SourcePawnEngine()
{
m_pDebugHook = NULL;
m_CallStack = NULL;
m_FreedCalls = NULL;
m_CurChain = 0;
#if 0
m_pFreeFuncs = NULL;
#endif
}
SourcePawnEngine::~SourcePawnEngine()
{
TracedCall *pTemp;
while (m_FreedCalls)
{
pTemp = m_FreedCalls->next;
delete m_FreedCalls;
m_FreedCalls = pTemp;
}
#if 0
CFunction *pNext;
while (m_pFreeFuncs)
{
pNext = m_pFreeFuncs->m_pNext;
delete m_pFreeFuncs;
m_pFreeFuncs = pNext;
}
#endif
}
void *SourcePawnEngine::ExecAlloc(size_t size)
@@ -153,22 +123,22 @@ void *SourcePawnEngine::ExecAlloc(size_t size)
void *SourcePawnEngine::AllocatePageMemory(size_t size)
{
return g_ExeMemory.Alloc(size);
return g_Jit.AllocCode(size);
}
void SourcePawnEngine::SetReadExecute(void *ptr)
{
g_ExeMemory.SetRE(ptr);
/* already re */
}
void SourcePawnEngine::SetReadWrite(void *ptr)
{
g_ExeMemory.SetRW(ptr);
/* already rw */
}
void SourcePawnEngine::FreePageMemory(void *ptr)
{
g_ExeMemory.Free(ptr);
g_Jit.FreeCode(ptr);
}
void SourcePawnEngine::ExecFree(void *address)
@@ -180,6 +150,12 @@ void SourcePawnEngine::ExecFree(void *address)
#endif
}
void SourcePawnEngine::SetReadWriteExecute(void *ptr)
{
//:TODO: g_ExeMemory.SetRWE(ptr);
SetReadExecute(ptr);
}
void *SourcePawnEngine::BaseAlloc(size_t size)
{
return malloc(size);
@@ -224,142 +200,38 @@ IDebugListener *SourcePawnEngine::SetDebugListener(IDebugListener *pListener)
return old;
}
unsigned int SourcePawnEngine::GetContextCallCount()
{
if (!m_CallStack)
{
return 0;
}
return m_CallStack->chain;
}
TracedCall *SourcePawnEngine::MakeTracedCall(bool new_chain)
{
TracedCall *pCall;
if (!m_FreedCalls)
{
pCall = new TracedCall;
} else {
/* Unlink the head node from the free list */
pCall = m_FreedCalls;
m_FreedCalls = m_FreedCalls->next;
}
/* Link as the head node into the call stack */
pCall->next = m_CallStack;
if (new_chain)
{
pCall->chain = ++m_CurChain;
} else {
pCall->chain = m_CurChain;
}
m_CallStack = pCall;
return pCall;
}
void SourcePawnEngine::FreeTracedCall(TracedCall *pCall)
{
/* Check if this is the top of the call stack */
if (pCall == m_CallStack)
{
m_CallStack = m_CallStack->next;
}
/* Add this to our linked list of freed calls */
if (!m_FreedCalls)
{
m_FreedCalls = pCall;
m_FreedCalls->next = NULL;
} else {
pCall->next = m_FreedCalls;
m_FreedCalls = pCall;
}
}
void SourcePawnEngine::PushTracer(BaseContext *ctx)
{
TracedCall *pCall = MakeTracedCall(true);
pCall->cip = INVALID_CIP;
pCall->ctx = ctx;
pCall->frm = INVALID_CIP;
}
void SourcePawnEngine::RunTracer(BaseContext *ctx, uint32_t frame, uint32_t codeip)
{
assert(m_CallStack != NULL);
assert(m_CallStack->ctx == ctx);
assert(m_CallStack->chain == m_CurChain);
if (m_CallStack->cip == INVALID_CIP)
{
/* We aren't logging anything yet, so begin the trace */
m_CallStack->cip = codeip;
m_CallStack->frm = frame;
} else {
if (m_CallStack->frm > frame)
{
/* The last frame has moved down the stack,
* so we have to push a new call onto our list.
*/
TracedCall *pCall = MakeTracedCall(false);
pCall->ctx = ctx;
pCall->frm = frame;
} else if (m_CallStack->frm < frame) {
/* The last frame has moved up the stack,
* so we have to pop the call from our list.
*/
FreeTracedCall(m_CallStack);
}
/* no matter where we are, update the cip */
m_CallStack->cip = codeip;
}
}
void SourcePawnEngine::PopTracer(int error, const char *msg)
{
assert(m_CallStack != NULL);
if (error != SP_ERROR_NONE && m_pDebugHook)
{
uint32_t native = INVALID_CIP;
if (m_CallStack->ctx->GetCtx()->n_err)
{
native = m_CallStack->ctx->GetCtx()->n_idx;
}
CContextTrace trace(m_CallStack, error, msg, native);
m_pDebugHook->OnContextExecuteError(m_CallStack->ctx, &trace);
}
/* Now pop the error chain */
while (m_CallStack && m_CallStack->chain == m_CurChain)
{
FreeTracedCall(m_CallStack);
}
m_CurChain--;
}
unsigned int SourcePawnEngine::GetEngineAPIVersion()
{
return SOURCEPAWN_ENGINE_API_VERSION;
}
CContextTrace::CContextTrace(TracedCall *pStart, int error, const char *msg, uint32_t native) :
m_Error(error), m_pMsg(msg), m_pStart(pStart), m_pIterator(pStart), m_Native(native)
unsigned int SourcePawnEngine::GetContextCallCount()
{
return 0;
}
void SourcePawnEngine::ReportError(BaseRuntime *runtime, int err, const char *errstr, cell_t rp_start)
{
if (m_pDebugHook == NULL)
{
return;
}
CContextTrace trace(runtime, err, errstr, rp_start);
m_pDebugHook->OnContextExecuteError(runtime->GetDefaultContext(), &trace);
}
CContextTrace::CContextTrace(BaseRuntime *pRuntime, int err, const char *errstr, cell_t start_rp)
: m_pRuntime(pRuntime), m_Error(err), m_pMsg(errstr), m_StartRp(start_rp), m_Level(0)
{
m_ctx = pRuntime->m_pCtx->GetCtx();
m_pDebug = m_pRuntime->GetDebugInfo();
}
bool CContextTrace::DebugInfoAvailable()
{
return m_pStart->ctx->IsDebugging();
return (m_pDebug != NULL);
}
const char *CContextTrace::GetCustomErrorString()
@@ -374,83 +246,99 @@ int CContextTrace::GetErrorCode()
const char *CContextTrace::GetErrorString()
{
if (m_Error > ERROR_MESSAGE_MAX ||
m_Error < 1)
if (m_Error > ERROR_MESSAGE_MAX || m_Error < 1)
{
return "Invalid error code";
} else {
}
else
{
return g_ErrorMsgTable[m_Error];
}
}
void CContextTrace::ResetTrace()
{
m_pIterator = m_pStart;
m_Level = 0;
}
bool CContextTrace::GetTraceInfo(CallStackInfo *trace)
{
if (!m_pIterator || (m_pIterator->chain != m_pStart->chain))
cell_t cip;
if (m_Level == 0)
{
cip = m_ctx->err_cip;
}
else if (m_ctx->rp > 0)
{
/* Entries go from ctx.rp - 1 to m_StartRp */
cell_t offs, start, end;
offs = m_Level - 1;
start = m_ctx->rp - 1;
end = m_StartRp;
if (start - offs < end)
{
return false;
}
cip = m_ctx->rstk_cips[start - offs];
}
else
{
return false;
}
if (m_pIterator->cip == INVALID_CIP)
if (trace == NULL)
{
return false;
}
IPluginContext *pContext = m_pIterator->ctx;
IPluginDebugInfo *pInfo = pContext->GetRuntime()->GetDebugInfo();
if (!pInfo)
{
return false;
}
if (!trace)
{
m_pIterator = m_pIterator->next;
m_Level++;
return true;
}
if (pInfo->LookupFile(m_pIterator->cip, &(trace->filename)) != SP_ERROR_NONE)
if (m_pDebug->LookupFile(cip, &(trace->filename)) != SP_ERROR_NONE)
{
trace->filename = NULL;
}
if (pInfo->LookupFunction(m_pIterator->cip, &(trace->function)) != SP_ERROR_NONE)
if (m_pDebug->LookupFunction(cip, &(trace->function)) != SP_ERROR_NONE)
{
trace->function = NULL;
}
if (pInfo->LookupLine(m_pIterator->cip, &(trace->line)) != SP_ERROR_NONE)
if (m_pDebug->LookupLine(cip, &(trace->line)) != SP_ERROR_NONE)
{
trace->line = 0;
}
m_pIterator = m_pIterator->next;
m_Level++;
return true;
}
const char *CContextTrace::GetLastNative(uint32_t *index)
{
if (m_Native == INVALID_CIP)
if (m_ctx->n_err == SP_ERROR_NONE)
{
return NULL;
}
sp_native_t *native;
if (m_pIterator->ctx->GetNativeByIndex(m_Native, &native) != SP_ERROR_NONE)
if (m_pRuntime->GetNativeByIndex(m_ctx->n_idx, &native) != SP_ERROR_NONE)
{
return NULL;
}
if (index)
{
*index = m_Native;
*index = m_ctx->n_idx;
}
return native->name;
}
IDebugListener *SourcePawnEngine::GetDebugHook()
{
return m_pDebugHook;
}
+9 -37
View File
@@ -37,19 +37,10 @@
class BaseContext;
struct TracedCall
{
uint32_t cip;
uint32_t frm;
BaseContext *ctx;
TracedCall *next;
unsigned int chain;
};
class CContextTrace : public IContextTrace
{
public:
CContextTrace(TracedCall *pStart, int error, const char *msg, uint32_t native);
CContextTrace(BaseRuntime *pRuntime, int err, const char *errstr, cell_t start_rp);
public:
int GetErrorCode();
const char *GetErrorString();
@@ -59,11 +50,13 @@ public:
void ResetTrace();
const char *GetLastNative(uint32_t *index);
private:
BaseRuntime *m_pRuntime;
sp_context_t *m_ctx;
int m_Error;
const char *m_pMsg;
TracedCall *m_pStart;
TracedCall *m_pIterator;
uint32_t m_Native;
cell_t m_StartRp;
cell_t m_Level;
IPluginDebugInfo *m_pDebug;
};
class SourcePawnEngine : public ISourcePawnEngine
@@ -85,37 +78,16 @@ public: //ISourcePawnEngine
void *AllocatePageMemory(size_t size);
void SetReadWrite(void *ptr);
void SetReadExecute(void *ptr);
void SetReadWriteExecute(void *ptr);
void FreePageMemory(void *ptr);
const char *GetErrorString(int err);
public: //Debugger Stuff
/**
* @brief Pushes a context onto the top of the call tracer.
*
* @param ctx Plugin context.
*/
void PushTracer(BaseContext *ctx);
/**
* @brief Pops a plugin off the call tracer.
*/
void PopTracer(int error, const char *msg);
/**
* @brief Runs tracer from a debug break.
*/
void RunTracer(BaseContext *ctx, uint32_t frame, uint32_t codeip);
void ReportError(BaseRuntime *runtime, int err, const char *errstr, cell_t rp_start);
public: //Plugin function stuff
CFunction *GetFunctionFromPool(funcid_t f, IPluginContext *plugin);
void ReleaseFunctionToPool(CFunction *func);
private:
TracedCall *MakeTracedCall(bool new_chain);
void FreeTracedCall(TracedCall *pCall);
IDebugListener *GetDebugHook();
private:
IDebugListener *m_pDebugHook;
TracedCall *m_FreedCalls;
TracedCall *m_CallStack;
unsigned int m_CurChain;
//CFunction *m_pFreeFuncs;
};
extern SourcePawnEngine g_engine1;
+3 -12
View File
@@ -38,13 +38,11 @@
* FUNCTION CALLING *
********************/
void CFunction::Set(uint32_t code_addr, BaseRuntime *runtime, funcid_t fnid, uint32_t pub_id)
void CFunction::Set(BaseRuntime *runtime, funcid_t fnid, uint32_t pub_id)
{
m_codeaddr = code_addr;
m_pRuntime = runtime;
m_curparam = 0;
m_errorstate = SP_ERROR_NONE;
m_Invalid = false;
m_FnId = fnid;
}
@@ -68,10 +66,9 @@ IPluginContext *CFunction::GetParentContext()
return m_pRuntime->GetDefaultContext();
}
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)
CFunction::CFunction(BaseRuntime *runtime, funcid_t id, uint32_t pub_id) :
m_curparam(0), m_errorstate(SP_ERROR_NONE), m_FnId(id)
{
m_Invalid = false;
m_pRuntime = runtime;
}
@@ -347,9 +344,3 @@ int CFunction::SetError(int err)
return err;
}
bool CFunction::IsInvalidated()
{
return m_Invalid;
}
+3 -8
View File
@@ -54,13 +54,13 @@ struct ParamInfo
};
class CPlugin;
class JitFunction;
class CFunction : public IPluginFunction
{
friend class SourcePawnEngine;
public:
CFunction(uint32_t code_addr,
BaseRuntime *pRuntime,
CFunction(BaseRuntime *pRuntime,
funcid_t fnid,
uint32_t pub_id);
public:
@@ -75,8 +75,6 @@ public:
virtual void Cancel();
virtual int CallFunction(const cell_t *params, unsigned int num_params, cell_t *result);
virtual IPluginContext *GetParentContext();
bool IsInvalidated();
void Invalidate();
bool IsRunnable();
funcid_t GetFunctionID();
int Execute2(IPluginContext *ctx, cell_t *result);
@@ -85,19 +83,16 @@ public:
unsigned int num_params,
cell_t *result);
public:
void Set(uint32_t code_addr, BaseRuntime *runtime, funcid_t fnid, uint32_t pub_id);
void Set(BaseRuntime *runtime, funcid_t fnid, uint32_t pub_id);
private:
int _PushString(const char *string, int sz_flags, int cp_flags, size_t len);
int SetError(int err);
private:
uint32_t m_codeaddr;
BaseRuntime *m_pRuntime;
cell_t m_params[SP_MAX_EXEC_PARAMS];
ParamInfo m_info[SP_MAX_EXEC_PARAMS];
unsigned int m_curparam;
int m_errorstate;
CFunction *m_pNext;
bool m_Invalid;
funcid_t m_FnId;
};
File diff suppressed because it is too large Load Diff
+60 -24
View File
@@ -34,9 +34,11 @@
#include <sp_vm_types.h>
#include <sp_vm_api.h>
#include <jit_helpers.h>
#include "../jit_shared.h"
#include "../BaseRuntime.h"
#include <KeCodeAllocator.h>
#include "jit_helpers.h"
#include "jit_shared.h"
#include "BaseRuntime.h"
#include "jit_function.h"
using namespace SourcePawn;
@@ -84,12 +86,27 @@ struct floattbl_t
unsigned int index;
};
struct call_thunk_t
{
jitoffs_t patch_addr;
cell_t pcode_offs;
jitoffs_t thunk_addr;
};
class CompData : public ICompilation
{
public:
CompData() : plugin(NULL),
debug(false), profile(0), inline_level(0), rebase(NULL),
error_set(SP_ERROR_NONE), func_idx(0)
CompData()
: runtime(NULL),
plugin(NULL),
rebase(NULL),
jit_float_table(NULL),
profile(0),
inline_level(0),
error_set(SP_ERROR_NONE),
num_thunks(0),
max_thunks(0),
thunks(NULL)
{
};
bool SetOption(const char *key, const char *val);
@@ -98,18 +115,15 @@ public:
public:
BaseRuntime *runtime; /* runtime handle */
sp_plugin_t *plugin; /* plugin handle */
bool debug; /* whether to compile debug mode */
uint8_t *rebase; /* relocation map */
floattbl_t *jit_float_table;
cell_t cur_func; /* current func pcode offset */
/* Options */
int profile; /* profiling flags */
int inline_level; /* inline optimization level */
jitcode_t rebase; /* relocation map */
/* Per-compilation properties */
int error_set; /* error code to halt process */
unsigned int func_idx; /* current function index */
jitoffs_t jit_return; /* point in main call to return to */
jitoffs_t jit_verify_addr_eax;
jitoffs_t jit_verify_addr_edx;
jitoffs_t jit_break; /* call to op.break */
jitoffs_t jit_sysreq_n; /* call version of op.sysreq.n */
jitoffs_t jit_genarray; /* call to genarray intrinsic */
jitoffs_t jit_error_bounds;
jitoffs_t jit_error_divzero;
jitoffs_t jit_error_stacklow;
@@ -117,32 +131,47 @@ public:
jitoffs_t jit_error_memaccess;
jitoffs_t jit_error_heaplow;
jitoffs_t jit_error_heapmin;
jitoffs_t jit_error_array_too_big;
jitoffs_t jit_extern_error; /* returning generic error */
jitoffs_t jit_sysreq_c; /* old version! */
jitoffs_t jit_rounding_table;
floattbl_t *jit_float_table;
uint32_t codesize; /* total codesize */
uint32_t num_thunks; /* number of thunks needed */
uint32_t max_thunks; /* maximum number of thunks */
call_thunk_t *thunks; /* thunk array */
};
class JITX86
{
public:
JITX86();
public:
bool InitializeJIT();
void ShutdownJIT();
ICompilation *StartCompilation(BaseRuntime *runtime);
ICompilation *StartCompilation();
bool Compile(ICompilation *co, BaseRuntime *runtime, int *err);
void FreePluginVars(sp_plugin_t *pl);
void SetupContextVars(BaseRuntime *runtime, BaseContext *pCtx, sp_context_t *ctx);
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);
JitFunction *CompileFunction(BaseRuntime *runtime, cell_t pcode_offs, int *err);
ICompilation *ApplyOptions(ICompilation *_IN, ICompilation *_OUT);
int InvokeFunction(BaseRuntime *runtime, JitFunction *fn, cell_t *result);
public:
void *GetGenArrayIntrinsic();
void *GetReturnPoint();
void *GetRoundingTable();
void *AllocCode(size_t size);
void FreeCode(void *code);
private:
void *m_pJitEntry; /* Entry function */
void *m_pJitReturn; /* Return point for errors */
int m_RoundTable[3]; /* [-1, 0, 1] rounding table */
void *m_pJitGenArray; /* Generates an array */
};
cell_t NativeCallback(sp_context_t *ctx, ucell_t native_idx, cell_t *params);
cell_t NativeCallback_Debug(sp_context_t *ctx, ucell_t native_idx, cell_t *params);
cell_t NativeCallback_Debug_Profile(sp_context_t *ctx, ucell_t native_idx, cell_t *params);
cell_t NativeCallback_Profile(sp_context_t *ctx, ucell_t native_idx, cell_t *params);
uint32_t FuncLookup(CompData *data, cell_t pcode_offs);
jitoffs_t RelocLookup(JitWriter *jit, cell_t pcode_offs, bool relative=false);
void *CompileThunk(BaseRuntime *runtime, cell_t pcode_ffs, void *jmploc_addr);
#define AMX_REG_PRI REG_EAX
#define AMX_REG_ALT REG_EDX
@@ -152,13 +181,20 @@ jitoffs_t RelocLookup(JitWriter *jit, cell_t pcode_offs, bool relative=false);
#define AMX_REG_INFO REG_ESI
#define AMX_REG_FRM REG_EBX
#define AMX_NUM_INFO_VARS 9
#define AMX_INFO_FRM AMX_REG_INFO //not relocated
#define AMX_INFO_FRAME 0 //(same thing as above)
#define AMX_INFO_HEAP 4 //not relocated
#define AMX_INFO_RETVAL 8 //physical
#define AMX_INFO_CONTEXT 12 //physical
#define AMX_INFO_STACKTOP 16 //relocated
#define AMX_INFO_CIP 20 //pcode CIP
#define AMX_INFO_DATASIZE 24 //plugin->data_size
#define AMX_INFO_MEMORY 28 //plugin->memory
#define AMX_INFO_NSTACK 32 //native stack
extern JITX86 g_Jit1;
extern Knight::KeCodeCache *g_pCodeCache;
extern JITX86 g_Jit;
#endif //_INCLUDE_SOURCEPAWN_JIT_X86_H_
+51 -257
View File
@@ -36,14 +36,11 @@
#include "opcode_helpers.h"
#include "x86_macros.h"
#define NUM_INFO_PARAMS 5
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
* void *vars[], void *entry_func
*/
/**
@@ -65,97 +62,58 @@ jitoffs_t Write_Execute_Function(JitWriter *jit)
IA32_Push_Reg(jit, REG_EDI);
IA32_Push_Reg(jit, REG_EBX);
//sub esp, 4*n - reserve info array
//mov esi, esp - save info pointer
IA32_Sub_Rm_Imm8(jit, REG_ESP, 4*NUM_INFO_PARAMS, MOD_REG);
IA32_Mov_Reg_Rm(jit, AMX_REG_INFO, REG_ESP, MOD_REG);
/* Prep us for doing the real work */
//mov esi, [ebp+param0] ;get vars
//mov ecx, [ebp+param1] ;get entry addr
//mov eax, [esi+MEMORY] ;get memory base
//mov edx, [esi+CONTEXT] ;get context
IA32_Mov_Reg_Rm_Disp8(jit, REG_ESI, REG_EBP, 8 + 4*0);
IA32_Mov_Reg_Rm_Disp8(jit, REG_ECX, REG_EBP, 8 + 4*1);
IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, REG_ESI, AMX_INFO_MEMORY);
IA32_Mov_Reg_Rm_Disp8(jit, REG_EDX, REG_ESI, AMX_INFO_CONTEXT);
/* Initial memory setup */
//mov eax, [ebp+16] - get result pointer
//mov [esi+8], eax - store into info pointer
//mov eax, [ebp+8] - get context
//mov [esi+12], eax - store context into info pointer
//mov ecx, [eax+<offs>] - get heap pointer
//mov [esi+4], ecx - store heap into info pointer
//mov ebp, <addr> - get data pointer
IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, REG_EBP, 16);
IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_INFO, REG_EAX, AMX_INFO_RETVAL);
IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, REG_EBP, 8);
IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_INFO, REG_EAX, AMX_INFO_CONTEXT);
IA32_Mov_Reg_Rm_Disp8(jit, REG_ECX, REG_EAX, offsetof(sp_context_t, hp));
IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_INFO, REG_ECX, AMX_INFO_HEAP);
IA32_Mov_Reg_Imm32(jit, AMX_REG_DAT, jit_int32_t(co->plugin->memory));
/* Frame setup */
//mov edi, [eax+<offs>] - get stack pointer
//add edi, ebp - relocate to data section
//mov ebx, edi - copy sp to frm
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_STK, REG_EAX, offsetof(sp_context_t, sp));
IA32_Add_Rm_Reg(jit, AMX_REG_STK, AMX_REG_DAT, MOD_REG);
IA32_Mov_Reg_Rm(jit, AMX_REG_FRM, AMX_REG_STK, MOD_REG);
/* Info memory setup */
//mov ecx, [eax+<offs>] - copy memsize to temp var
//add ecx, ebp - relocate
//mov [esi+x], ecx - store relocated
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)
//push eax
//mov eax, <addr of addr of code>
//mov eax, [eax]
//add ecx, eax
//pop eax
IA32_Mov_Reg_Esp_Disp8(jit, REG_ECX, 12+(4*(NUM_INFO_PARAMS+3)));
IA32_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);
/* Set up run-time registers */
//mov edi, [edx+SP] ;non-reloc SP
//add edi, eax ;reloc SP
//mov ebp, eax ;DAT
//mov ebx, edi ;reloc FRM
//mov [esi+NSTACK], esp ;save ESP
IA32_Mov_Reg_Rm_Disp8(jit, REG_EDI, REG_EDX, offsetof(sp_context_t, sp));
IA32_Add_Rm_Reg(jit, REG_EDI, REG_EAX, MOD_REG);
IA32_Mov_Reg_Rm(jit, REG_EBP, REG_EAX, MOD_REG);
IA32_Mov_Reg_Rm(jit, REG_EBX, REG_EDI, MOD_REG);
IA32_Mov_Rm_Reg_Disp8(jit, REG_ESI, REG_ESP, AMX_INFO_NSTACK);
/* by now, everything is set up, so we can call into the plugin */
//call ecx
IA32_Call_Reg(jit, REG_ECX);
/* if the code flow gets to here, there was a normal return */
//mov ecx, [esi+8] - get retval pointer
//mov [ecx], eax - store retval from PRI
//mov eax, SP_ERROR_NONE - set no error
//mov ecx, [esi+RETVAL] ;get retval pointer
//mov [ecx], eax ;store retval from PRI
//mov eax, SP_ERROR_NONE ;set no error
IA32_Mov_Reg_Rm_Disp8(jit, REG_ECX, AMX_REG_INFO, AMX_INFO_RETVAL);
IA32_Mov_Rm_Reg(jit, REG_ECX, AMX_REG_PRI, MOD_MEM_REG);
IA32_Mov_Reg_Imm32(jit, REG_EAX, SP_ERROR_NONE);
/* save where error checking/halting functions should go to */
jitoffs_t offs_return = jit->get_outputpos();
//mov esp, esi - restore stack pointer
IA32_Mov_Reg_Rm(jit, REG_ESP, REG_ESI, MOD_REG);
//mov esp, [esi+NSTACK] ;restore stack pointer
IA32_Mov_Reg_Rm_Disp8(jit, REG_ESP, REG_ESI, AMX_INFO_NSTACK);
/* _FOR NOW_ ...
* We are going to restore SP, HP, and FRM for now. This is for
* debugging only, to check for alignment errors. As such:
* :TODO: probably remove this.
*/
//mov ecx, [esi+context]
/* Restore SP */
//mov ecx, [esi+CONTEXT]
//sub edi, ebp
//mov edx, [esi+heap]
//mov [ecx+sp], edi
//mov [ecx+hp], edx
//mov [ecx+SP], edi
IA32_Mov_Reg_Rm_Disp8(jit, REG_ECX, REG_ESI, AMX_INFO_CONTEXT);
IA32_Sub_Reg_Rm(jit, REG_EDI, REG_EBP, MOD_REG);
IA32_Mov_Reg_Rm_Disp8(jit, REG_EDX, REG_ESI, AMX_INFO_HEAP);
IA32_Mov_Rm_Reg_Disp8(jit, REG_ECX, REG_EDI, offsetof(sp_context_t, sp));
IA32_Mov_Rm_Reg_Disp8(jit, REG_ECX, REG_EDX, offsetof(sp_context_t, hp));
//add esp, 4*NUM_INFO_PARAMS
//pop ebx
//pop edi
//pop esi
//pop ebp
//ret
IA32_Add_Rm_Imm8(jit, REG_ESP, 4*NUM_INFO_PARAMS, MOD_REG);
IA32_Pop_Reg(jit, REG_EBX);
IA32_Pop_Reg(jit, REG_EDI);
IA32_Pop_Reg(jit, REG_ESI);
@@ -165,58 +123,22 @@ jitoffs_t Write_Execute_Function(JitWriter *jit)
return offs_return;
}
void Write_BreakDebug(JitWriter *jit)
{
//push edi
//mov edi, ecx
//mov ecx, [esi+ctx]
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);
//: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+basectx]
//mov ecx, <dbreak>
//call ecx
//add esp, 8
//popad
IA32_Pushad(jit);
IA32_Push_Rm_Disp8(jit, AMX_REG_INFO, AMX_INFO_FRAME); //:TODO: move to regs and push? and dont disp for 0
IA32_Push_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);
//pop edi
//ret
IA32_Pop_Reg(jit, REG_EDI);
IA32_Return(jit);
}
void Write_GetError(JitWriter *jit)
{
CompData *data = (CompData *)jit->data;
//mov eax, [esi+info.context]
//mov eax, [eax+ctx.error]
//jmp [jit_return]
IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, AMX_REG_INFO, AMX_INFO_CONTEXT);
IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, REG_EAX, offsetof(sp_context_t, n_err));
IA32_Jump_Imm32_Abs(jit, data->jit_return);
IA32_Jump_Imm32_Abs(jit, g_Jit.GetReturnPoint());
}
void Write_SetError(JitWriter *jit, int error)
{
CompData *data = (CompData *)jit->data;
//mov eax, <error>
//jmp [jit_return]
IA32_Mov_Reg_Imm32(jit, REG_EAX, error);
IA32_Jump_Imm32_Abs(jit, data->jit_return);
IA32_Jump_Imm32_Abs(jit, g_Jit.GetReturnPoint());
}
void Write_Check_DivZero(JitWriter *jit, jit_uint8_t reg)
@@ -224,7 +146,7 @@ void Write_Check_DivZero(JitWriter *jit, jit_uint8_t reg)
//test reg, reg
//jz :error
IA32_Test_Rm_Reg(jit, reg, reg, MOD_REG);
IA32_Jump_Cond_Imm32_Abs(jit, CC_Z, ((CompData *)jit->data)->jit_error_divzero);
IA32_Jump_Cond_Imm32_Rel(jit, CC_Z, ((CompData *)jit->data)->jit_error_divzero);
}
void Write_CheckHeap_Min(JitWriter *jit)
@@ -238,7 +160,7 @@ void Write_CheckHeap_Min(JitWriter *jit)
//cmp [esi+info.heap], <heaplow>
//jb :error
IA32_Cmp_Rm_Imm32_Disp8(jit, AMX_REG_INFO, AMX_INFO_HEAP, data->plugin->data_size);
IA32_Jump_Cond_Imm32_Abs(jit, CC_B, data->jit_error_heapmin);
IA32_Jump_Cond_Imm32_Rel(jit, CC_B, data->jit_error_heapmin);
}
void Write_CheckHeap_Low(JitWriter *jit)
@@ -252,7 +174,7 @@ void Write_CheckHeap_Low(JitWriter *jit)
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_HEAP);
IA32_Lea_Reg_DispRegMultImm8(jit, AMX_REG_TMP, AMX_REG_DAT, AMX_REG_TMP, NOSCALE, STACK_MARGIN);
IA32_Cmp_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_STK, MOD_REG);
IA32_Jump_Cond_Imm32_Abs(jit, CC_A, ((CompData *)jit->data)->jit_error_heaplow);
IA32_Jump_Cond_Imm32_Rel(jit, CC_A, ((CompData *)jit->data)->jit_error_heaplow);
}
void Write_CheckStack_Min(JitWriter *jit)
@@ -263,7 +185,7 @@ void Write_CheckStack_Min(JitWriter *jit)
//cmp edi, [esi+info.stacktop]
//jae :error
IA32_Cmp_Reg_Rm_Disp8(jit, AMX_REG_STK, AMX_REG_INFO, AMX_INFO_STACKTOP);
IA32_Jump_Cond_Imm32_Abs(jit, CC_AE, ((CompData *)jit->data)->jit_error_stackmin);
IA32_Jump_Cond_Imm32_Rel(jit, CC_AE, ((CompData *)jit->data)->jit_error_stackmin);
}
void Write_CheckStack_Low(JitWriter *jit)
@@ -279,36 +201,15 @@ void Write_CheckStack_Low(JitWriter *jit)
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_HEAP);
IA32_Lea_Reg_DispRegMultImm8(jit, AMX_REG_TMP, AMX_REG_DAT, AMX_REG_TMP, NOSCALE, STACK_MARGIN);
IA32_Cmp_Reg_Rm(jit, AMX_REG_STK, AMX_REG_TMP, MOD_REG);
IA32_Jump_Cond_Imm32_Abs(jit, CC_B, ((CompData *)jit->data)->jit_error_stacklow);
IA32_Jump_Cond_Imm32_Rel(jit, CC_B, ((CompData *)jit->data)->jit_error_stacklow);
}
void Write_Check_VerifyAddr(JitWriter *jit, jit_uint8_t reg)
{
CompData *data = (CompData *)jit->data;
/* :TODO: Should this be checking for below heaplow?
* The old JIT did not.
*/
bool call = false;
if (!(data->inline_level & JIT_INLINE_ERRORCHECKS))
{
/* If we're not in the initial generation phase,
* Write a call to the actual routine instead.
*/
if ((reg == REG_EAX) && data->jit_verify_addr_eax)
{
jitoffs_t call = IA32_Call_Imm32(jit, 0);
IA32_Write_Jump32(jit, call, data->jit_verify_addr_eax);
return;
} else if ((reg == REG_EDX) && data->jit_verify_addr_edx) {
jitoffs_t call = IA32_Call_Imm32(jit, 0);
IA32_Write_Jump32(jit, call, data->jit_verify_addr_edx);
return;
}
call = true;
}
/**
* :TODO: If we can't find a nicer way of doing this,
* then scrap it on high optimizations. The second portion is not needed at all!
@@ -318,7 +219,7 @@ void Write_Check_VerifyAddr(JitWriter *jit, jit_uint8_t reg)
//cmp <reg>, <stpu>
//jae :error
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);
IA32_Jump_Cond_Imm32_Rel(jit, CC_AE, ((CompData *)jit->data)->jit_error_memaccess);
/* Part 2: Check if we're in the invalid region between HP and SP */
jitoffs_t jmp;
@@ -332,13 +233,8 @@ void Write_Check_VerifyAddr(JitWriter *jit, jit_uint8_t reg)
jmp = IA32_Jump_Cond_Imm8(jit, CC_B, 0);
IA32_Lea_Reg_DispRegMultImm8(jit, AMX_REG_TMP, AMX_REG_DAT, reg, NOSCALE, 0);
IA32_Cmp_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_STK, MOD_REG);
IA32_Jump_Cond_Imm32_Abs(jit, CC_B, ((CompData *)jit->data)->jit_error_memaccess);
IA32_Jump_Cond_Imm32_Rel(jit, CC_B, ((CompData *)jit->data)->jit_error_memaccess);
IA32_Send_Jump8_Here(jit, jmp);
if (call)
{
IA32_Return(jit);
}
}
void Macro_PushN_Addr(JitWriter *jit, int i)
@@ -472,12 +368,7 @@ void WriteOp_Sysreq_C_Function(JitWriter *jit)
//call NativeCallback
IA32_Push_Reg(jit, REG_EAX);
jitoffs_t call = IA32_Call_Imm32(jit, 0);
if (!data->debug)
{
IA32_Write_Jump32_Abs(jit, call, (void *)NativeCallback);
} else {
IA32_Write_Jump32_Abs(jit, call, (void *)NativeCallback_Debug);
}
IA32_Write_Jump32_Abs(jit, call, (void *)NativeCallback);
/* Test for error */
//mov ecx, [esi+context]
@@ -485,7 +376,7 @@ void WriteOp_Sysreq_C_Function(JitWriter *jit)
//jnz :error
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, n_err), 0);
IA32_Jump_Cond_Imm32_Abs(jit, CC_NZ, data->jit_extern_error);
IA32_Jump_Cond_Imm32_Rel(jit, CC_NZ, data->jit_extern_error);
/* restore what we damaged */
//mov esp, ebx
@@ -594,6 +485,8 @@ void GenerateArrayIndirectionVectors(cell_t *arraybase, cell_t dims[], cell_t _d
*/
void WriteIntrinsic_GenArray(JitWriter *jit)
{
jitoffs_t err1, err2;
/**
* save important values
*/
@@ -635,18 +528,18 @@ void WriteIntrinsic_GenArray(JitWriter *jit)
/* Test if we have heap space for this */
//mov eax, [esi+info.heap] ;get heap pointer
//lea eax, [eax+edx*4] ;new heap pointer
//cmp eax, <hlw> ;compare to heap low
//cmp eax, [esi+info.datasz] ;compare to heap low
//jbe :error ;die if we hit this (it should always be >)
//add eax, ebp ;relocate to stack
//cmp eax, edi ;die if above the stack pointer
//jae :error
IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, AMX_REG_INFO, AMX_INFO_HEAP);
IA32_Lea_Reg_DispRegMult(jit, REG_EAX, REG_EAX, REG_EDX, SCALE4);
IA32_Cmp_Rm_Imm32(jit, MOD_REG, REG_EAX, ((CompData *)jit->data)->plugin->data_size);
IA32_Jump_Cond_Imm32_Abs(jit, CC_BE, ((CompData *)jit->data)->jit_error_array_too_big);
IA32_Cmp_Reg_Rm_Disp8(jit, REG_EAX, AMX_REG_INFO, AMX_INFO_DATASIZE);
err1 = IA32_Jump_Cond_Imm32(jit, CC_BE, 0);
IA32_Add_Reg_Rm(jit, REG_EAX, AMX_REG_DAT, MOD_REG);
IA32_Cmp_Reg_Rm(jit, REG_EAX, AMX_REG_STK, MOD_REG);
IA32_Jump_Cond_Imm32_Abs(jit, CC_AE, ((CompData *)jit->data)->jit_error_array_too_big);
err2 = IA32_Jump_Cond_Imm32(jit, CC_AE, 0);
/* Prepare for indirection iteration */
//mov eax, [esi+info.heap] ;get heap pointer
@@ -697,107 +590,15 @@ void WriteIntrinsic_GenArray(JitWriter *jit)
IA32_Pop_Reg(jit, REG_EAX);
IA32_Pop_Reg(jit, REG_EBX);
IA32_Return(jit);
}
void WriteOp_Sysreq_N_Function(JitWriter *jit)
{
/* The big daddy of opcodes.
* eax - num_params
* ecx - native index
*/
CompData *data = (CompData *)jit->data;
/* store the number of parameters on the stack */
//mov [edi-4], eax
//sub edi, 4
IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_STK, REG_EAX, -4);
IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
/* save registers we will need */
//push eax ; num_params for stack popping
//push edx
IA32_Push_Reg(jit, REG_EAX);
IA32_Push_Reg(jit, AMX_REG_ALT);
/* Align the stack to 16 bytes */
//push ebx
//mov ebx, esp
//and esp, 0xFFFFFF0
//sub esp, 4
IA32_Push_Reg(jit, REG_EBX);
IA32_Mov_Reg_Rm(jit, REG_EBX, REG_ESP, MOD_REG);
IA32_And_Rm_Imm8(jit, REG_ESP, MOD_REG, -16);
IA32_Sub_Rm_Imm8(jit, REG_ESP, 4, MOD_REG);
/* push some callback stuff */
//push edi ; stack
//push ecx ; native index
IA32_Push_Reg(jit, AMX_REG_STK);
IA32_Push_Reg(jit, REG_ECX);
/* Relocate stack, heap, frm information, then store back */
//mov eax, [esi+context]
//mov ecx, [esi+hea]
//sub edi, ebp
//mov [eax+hp], ecx
//mov ecx, [esi]
//mov [eax+sp], edi
//mov [eax+frm], ecx
IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, AMX_REG_INFO, AMX_INFO_CONTEXT);
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_HEAP);
IA32_Sub_Reg_Rm(jit, AMX_REG_STK, AMX_REG_DAT, MOD_REG);
IA32_Mov_Rm_Reg_Disp8(jit, REG_EAX, AMX_REG_TMP, offsetof(sp_context_t, hp));
IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_INFO_FRM, MOD_MEM_REG);
IA32_Mov_Rm_Reg_Disp8(jit, REG_EAX, AMX_REG_STK, offsetof(sp_context_t, sp));
IA32_Mov_Rm_Reg_Disp8(jit, REG_EAX, AMX_REG_TMP, offsetof(sp_context_t, frm));
/* finally, push the last parameter and make the call */
//push eax ; context
//call NativeCallback
IA32_Push_Reg(jit, REG_EAX);
jitoffs_t call = IA32_Call_Imm32(jit, 0);
if (!data->debug)
{
IA32_Write_Jump32_Abs(jit, call, (void *)NativeCallback);
} else {
IA32_Write_Jump32_Abs(jit, call, (void *)NativeCallback_Debug);
}
/* Test for error */
//mov ecx, [esi+context]
//cmp [ecx+err], 0
//jnz :error
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, n_err), 0);
IA32_Jump_Cond_Imm32_Abs(jit, CC_NZ, data->jit_extern_error);
/* restore what we damaged */
//mov esp, ebx
//pop ebx
//add edi, ebp
//pop edx
//pop ecx ; num_params
IA32_Mov_Reg_Rm(jit, REG_ESP, REG_EBX, MOD_REG);
IA32_Pop_Reg(jit, REG_EBX);
IA32_Add_Reg_Rm(jit, AMX_REG_STK, AMX_REG_DAT, MOD_REG);
IA32_Pop_Reg(jit, AMX_REG_ALT);
IA32_Pop_Reg(jit, REG_ECX);
/* pop the AMX stack. do not check the margins.
* Note that this is not a true macro - we don't bother to
* set ALT here because nothing will be using it.
*/
//lea edi, [edi+ecx*4+4]
IA32_Lea_Reg_DispRegMultImm8(jit, AMX_REG_STK, AMX_REG_STK, REG_ECX, SCALE4, 4);
//ret
IA32_Return(jit);
//:error
IA32_Send_Jump32_Here(jit, err1);
IA32_Send_Jump32_Here(jit, err2);
Write_SetError(jit, SP_ERROR_ARRAY_TOO_BIG);
}
void WriteOp_Tracker_Push_Reg(JitWriter *jit, uint8_t reg)
{
CompData *data = (CompData *)jit->data;
/* Save registers that may be damaged by the call */
//push eax
//push ecx
@@ -824,7 +625,7 @@ void WriteOp_Tracker_Push_Reg(JitWriter *jit, uint8_t reg)
//cmp eax, 0
//jnz :error
IA32_Cmp_Rm_Imm8(jit, MOD_REG, REG_EAX, 0);
IA32_Jump_Cond_Imm32_Abs(jit, CC_NZ, data->jit_return);
IA32_Jump_Cond_Imm32_Abs(jit, CC_NZ, g_Jit.GetReturnPoint());
/* Restore */
//pop eax
@@ -890,13 +691,6 @@ int JIT_VerifyLowBoundTracker(sp_context_t *ctx)
return SP_ERROR_NONE;
}
void Write_RoundingTable(JitWriter *jit)
{
jit->write_int32(-1);
jit->write_int32(0);
jit->write_int32(1);
}
void AlignMe(JitWriter *jit)
{
jitoffs_t cur_offs = jit->get_outputpos();
+3 -7
View File
@@ -44,7 +44,6 @@ jitoffs_t Write_Execute_Function(JitWriter *jit);
/**
* Writes the Sysreq.* opcodes as a function call.
*/
void WriteOp_Sysreq_N_Function(JitWriter *jit);
void WriteOp_Sysreq_C_Function(JitWriter *jit);
/**
@@ -52,6 +51,8 @@ void WriteOp_Sysreq_C_Function(JitWriter *jit);
*/
void WriteIntrinsic_GenArray(JitWriter *jit);
void Write_Check_VerifyAddr(JitWriter *jit, jit_uint8_t reg);
/**
* Generates code to set an error state in the VM and return.
* This is used for generating the error set points in the VM.
@@ -73,12 +74,6 @@ void Write_CheckStack_Low(JitWriter *jit);
void Write_CheckHeap_Min(JitWriter *jit);
void Write_CheckHeap_Low(JitWriter *jit);
/**
* Verifies an address by register. The address must reside
* between DAT and HP and SP and STP.
*/
void Write_Check_VerifyAddr(JitWriter *jit, jit_uint8_t reg);
/**
* Checks for division by zero.
*/
@@ -303,6 +298,7 @@ typedef enum
OP_GENARRAY_Z, //-VERIFIED (not tested for 1D arrays)
OP_STRADJUST_PRI, //VERIFIED
OP_STACKADJUST, //:TODO: VERIFY
OP_ENDPROC, //VERIFIED
OP_FABS, //VERIFIED
OP_FLOAT, //VERIFIED
OP_FLOATADD, //VERIFIED
+6 -6
View File
@@ -676,12 +676,7 @@
}
case OP_SYSREQ_N:
{
if (data->inline_level & JIT_INLINE_NATIVES)
{
WriteOp_Sysreq_N(jit);
} else {
WriteOp_Sysreq_N_NoInline(jit);
}
WriteOp_Sysreq_N(jit);
break;
}
case OP_TRACKER_PUSH_C:
@@ -769,6 +764,11 @@
WriteOp_StackAdjust(jit);
break;
}
case OP_ENDPROC:
{
WriteOp_EndProc(jit);
break;
}
#if defined USE_UNGEN_OPCODES
#include "ungen_opcode_switch.inc"
#endif