585 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			585 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
#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"
 | 
						|
#include "sp_vm_basecontext.h"
 | 
						|
#include "engine2.h"
 | 
						|
 | 
						|
#include "md5/md5.h"
 | 
						|
 | 
						|
using namespace SourcePawn;
 | 
						|
 | 
						|
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)
 | 
						|
{
 | 
						|
	memset(&m_plugin, 0, sizeof(m_plugin));
 | 
						|
 | 
						|
	m_FuncCache = NULL;
 | 
						|
	m_MaxFuncs = 0;
 | 
						|
	m_NumFuncs = 0;
 | 
						|
	
 | 
						|
	memset(m_CodeHash, 0, sizeof(m_CodeHash));
 | 
						|
	memset(m_DataHash, 0, sizeof(m_DataHash));
 | 
						|
}
 | 
						|
 | 
						|
BaseRuntime::~BaseRuntime()
 | 
						|
{
 | 
						|
	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;
 | 
						|
 | 
						|
	for (unsigned int i = 0; i < m_NumFuncs; i++)
 | 
						|
	{
 | 
						|
		delete m_FuncCache[i];
 | 
						|
	}
 | 
						|
	free(m_FuncCache);
 | 
						|
 | 
						|
	delete m_pCtx;
 | 
						|
	if (m_pCo != NULL)
 | 
						|
	{
 | 
						|
		m_pCo->Abort();
 | 
						|
	}
 | 
						|
 | 
						|
	free(m_pPlugin->base);
 | 
						|
	delete [] m_pPlugin->memory;
 | 
						|
	delete [] m_pPlugin->publics;
 | 
						|
	delete [] m_pPlugin->pubvars;
 | 
						|
	delete [] m_pPlugin->natives;
 | 
						|
	free(m_pPlugin->name);
 | 
						|
}
 | 
						|
 | 
						|
static cell_t InvalidNative(IPluginContext *pCtx, const cell_t *params)
 | 
						|
{
 | 
						|
	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;
 | 
						|
 | 
						|
	if (hdr->version == 0x0101)
 | 
						|
	{
 | 
						|
		plugin->debug.unpacked = true;
 | 
						|
	}
 | 
						|
 | 
						|
	/* 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);
 | 
						|
		}
 | 
						|
		else if (strcmp(nameptr, ".dbg.natives") == 0)
 | 
						|
		{
 | 
						|
			plugin->debug.unpacked = false;
 | 
						|
		}
 | 
						|
 | 
						|
		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) || 
 | 
						|
		!(plugin->debug.stringbase) ))
 | 
						|
	{
 | 
						|
		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);
 | 
						|
	}
 | 
						|
 | 
						|
	MD5 md5_pcode;
 | 
						|
	md5_pcode.update(plugin->pcode, plugin->pcode_size);
 | 
						|
	md5_pcode.finalize();
 | 
						|
	md5_pcode.raw_digest(m_CodeHash);
 | 
						|
	
 | 
						|
	MD5 md5_data;
 | 
						|
	md5_data.update(plugin->data, plugin->data_size);
 | 
						|
	md5_data.finalize();
 | 
						|
	md5_data.raw_digest(m_DataHash);
 | 
						|
 | 
						|
	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->num_natives - 1;
 | 
						|
 | 
						|
	for (uint32_t i=0; i<m_pPlugin->num_natives; 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->num_natives)
 | 
						|
	{
 | 
						|
		return SP_ERROR_INDEX;
 | 
						|
	}
 | 
						|
 | 
						|
	if (native)
 | 
						|
	{
 | 
						|
		*native = &(m_pPlugin->natives[index]);
 | 
						|
	}
 | 
						|
 | 
						|
	return SP_ERROR_NONE;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
uint32_t BaseRuntime::GetNativesNum()
 | 
						|
{
 | 
						|
	return m_pPlugin->num_natives;
 | 
						|
}
 | 
						|
 | 
						|
int BaseRuntime::FindPublicByName(const char *name, uint32_t *index)
 | 
						|
{
 | 
						|
	int diff, high, low;
 | 
						|
	uint32_t mid;
 | 
						|
 | 
						|
	high = m_pPlugin->num_publics - 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->num_publics)
 | 
						|
	{
 | 
						|
		return SP_ERROR_INDEX;
 | 
						|
	}
 | 
						|
 | 
						|
	if (pblic)
 | 
						|
	{
 | 
						|
		*pblic = &(m_pPlugin->publics[index]);
 | 
						|
	}
 | 
						|
 | 
						|
	return SP_ERROR_NONE;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t BaseRuntime::GetPublicsNum()
 | 
						|
{
 | 
						|
	return m_pPlugin->num_publics;
 | 
						|
}
 | 
						|
 | 
						|
int BaseRuntime::GetPubvarByIndex(uint32_t index, sp_pubvar_t **pubvar)
 | 
						|
{
 | 
						|
	if (index >= m_pPlugin->num_pubvars)
 | 
						|
	{
 | 
						|
		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->num_pubvars - 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->num_pubvars)
 | 
						|
	{
 | 
						|
		return SP_ERROR_INDEX;
 | 
						|
	}
 | 
						|
 | 
						|
	*local_addr = (uint8_t *)m_pPlugin->pubvars[index].offs - m_pPlugin->memory;
 | 
						|
	*phys_addr = m_pPlugin->pubvars[index].offs;
 | 
						|
 | 
						|
	return SP_ERROR_NONE;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t BaseRuntime::GetPubVarsNum()
 | 
						|
{
 | 
						|
	return m_pPlugin->num_pubvars;
 | 
						|
}
 | 
						|
 | 
						|
IPluginContext *BaseRuntime::GetDefaultContext()
 | 
						|
{
 | 
						|
	return m_pCtx;
 | 
						|
}
 | 
						|
 | 
						|
IPluginDebugInfo *BaseRuntime::GetDebugInfo()
 | 
						|
{
 | 
						|
	return &m_Debug;
 | 
						|
}
 | 
						|
 | 
						|
IPluginFunction *BaseRuntime::GetFunctionById(funcid_t func_id)
 | 
						|
{
 | 
						|
	CFunction *pFunc = NULL;
 | 
						|
 | 
						|
	if (func_id & 1)
 | 
						|
	{
 | 
						|
		func_id >>= 1;
 | 
						|
		if (func_id >= m_pPlugin->num_publics)
 | 
						|
		{
 | 
						|
			return NULL;
 | 
						|
		}
 | 
						|
		pFunc = m_PubFuncs[func_id];
 | 
						|
		if (!pFunc)
 | 
						|
		{
 | 
						|
			m_PubFuncs[func_id] = new CFunction(this, 
 | 
						|
				(func_id << 1) | 1,
 | 
						|
				func_id);
 | 
						|
			pFunc = m_PubFuncs[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(this, (index << 1) | 1, index);
 | 
						|
		}
 | 
						|
		pFunc = m_PubFuncs[index];
 | 
						|
	}
 | 
						|
 | 
						|
	return pFunc;
 | 
						|
}
 | 
						|
 | 
						|
bool BaseRuntime::IsDebugging()
 | 
						|
{
 | 
						|
	return true;
 | 
						|
}
 | 
						|
 | 
						|
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);
 | 
						|
}
 | 
						|
 | 
						|
size_t BaseRuntime::GetMemUsage()
 | 
						|
{
 | 
						|
	size_t mem = 0;
 | 
						|
 | 
						|
	mem += sizeof(this);
 | 
						|
	mem += sizeof(sp_plugin_t);
 | 
						|
	mem += sizeof(BaseContext);
 | 
						|
	mem += m_pPlugin->base_size;
 | 
						|
 | 
						|
	return mem;
 | 
						|
}
 | 
						|
 | 
						|
unsigned char *BaseRuntime::GetCodeHash()
 | 
						|
{
 | 
						|
	return m_CodeHash;
 | 
						|
}
 | 
						|
 | 
						|
unsigned char *BaseRuntime::GetDataHash()
 | 
						|
{
 | 
						|
	return m_DataHash;
 | 
						|
}
 | 
						|
 | 
						|
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);
 | 
						|
	m_pPlugin->prof_flags = ((CompData *)m_pCo)->profile;
 | 
						|
 | 
						|
	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;
 | 
						|
}
 | 
						|
 | 
						|
int BaseRuntime::CreateBlank(uint32_t heastk)
 | 
						|
{
 | 
						|
	memset(m_pPlugin, 0, sizeof(sp_plugin_t));
 | 
						|
 | 
						|
	/* Align to cell_t bytes */
 | 
						|
	heastk += sizeof(cell_t);
 | 
						|
	heastk -= heastk % sizeof(cell_t);
 | 
						|
 | 
						|
	m_pPlugin->mem_size = heastk;
 | 
						|
	m_pPlugin->memory = new uint8_t[heastk];
 | 
						|
 | 
						|
	m_pPlugin->profiler = g_engine2.GetProfiler();
 | 
						|
	m_pCtx = new BaseContext(this);
 | 
						|
	m_pCo = g_Jit.StartCompilation(this);
 | 
						|
 | 
						|
	return SP_ERROR_NONE;
 | 
						|
}
 |