sourcepawn/jit/engine2.cpp
author David Anderson <dvander@alliedmods.net>
Fri Jul 11 08:18:43 2008 +0000 (2008-07-11)
changeset 2193 db7c6362f3f2
child 2219 5ddd93671335
permissions -rw-r--r--
landed massive refactoring of the JIT. contexts are actually contexts now, and a higher level structure wraps sp_plugin_t info. on that note, both sp_plugin_t and sp_context_t are entirely opaque, and not even core has access to them. amazingly, i managed to keep binary compatibility here although a large number of functions are deprecated (and core should eventually stop calling them).

NOTE: the JIT is now embeddable out-of-box and usable by other projects which is pretty cool. I will commit a shell app demonstrating this soon
     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <string.h>
     4 #include "engine2.h"
     5 #include "x86/jit_x86.h"
     6 #include "jit_version.h"
     7 #include "zlib/zlib.h"
     8 #include "BaseRuntime.h"
     9 #include "sp_vm_engine.h"
    10 
    11 using namespace SourcePawn;
    12 
    13 SourcePawnEngine2::SourcePawnEngine2()
    14 {
    15 	m_Profiler = NULL;
    16 }
    17 
    18 sp_plugin_t *_ReadPlugin(sp_file_hdr_t *hdr, uint8_t *base, sp_plugin_t *plugin, int *err)
    19 {
    20 	char *nameptr;
    21 	uint8_t sectnum = 0;
    22 	sp_file_section_t *secptr = (sp_file_section_t *)(base + sizeof(sp_file_hdr_t));
    23 
    24 	memset(plugin, 0, sizeof(sp_plugin_t));
    25 
    26 	plugin->base = base;
    27 
    28 	while (sectnum < hdr->sections)
    29 	{
    30 		nameptr = (char *)(base + hdr->stringtab + secptr->nameoffs);
    31 
    32 		if (!(plugin->pcode) && !strcmp(nameptr, ".code"))
    33 		{
    34 			sp_file_code_t *cod = (sp_file_code_t *)(base + secptr->dataoffs);
    35 			plugin->pcode = base + secptr->dataoffs + cod->code;
    36 			plugin->pcode_size = cod->codesize;
    37 			plugin->flags = cod->flags;
    38 		}
    39 		else if (!(plugin->data) && !strcmp(nameptr, ".data"))
    40 		{
    41 			sp_file_data_t *dat = (sp_file_data_t *)(base + secptr->dataoffs);
    42 			plugin->data = base + secptr->dataoffs + dat->data;
    43 			plugin->data_size = dat->datasize;
    44 			plugin->mem_size = dat->memsize;
    45 			plugin->memory = new uint8_t[plugin->mem_size];
    46 			memcpy(plugin->memory, plugin->data, plugin->data_size);
    47 		}
    48 		else if (!(plugin->info.publics) && !strcmp(nameptr, ".publics"))
    49 		{
    50 			plugin->info.publics_num = secptr->size / sizeof(sp_file_publics_t);
    51 			plugin->info.publics = (sp_file_publics_t *)(base + secptr->dataoffs);
    52 		}
    53 		else if (!(plugin->info.pubvars) && !strcmp(nameptr, ".pubvars"))
    54 		{
    55 			plugin->info.pubvars_num = secptr->size / sizeof(sp_file_pubvars_t);
    56 			plugin->info.pubvars = (sp_file_pubvars_t *)(base + secptr->dataoffs);
    57 		}
    58 		else if (!(plugin->info.natives) && !strcmp(nameptr, ".natives"))
    59 		{
    60 			plugin->info.natives_num = secptr->size / sizeof(sp_file_natives_t);
    61 			plugin->info.natives = (sp_file_natives_t *)(base + secptr->dataoffs);
    62 		}
    63 		else if (!(plugin->info.stringbase) && !strcmp(nameptr, ".names"))
    64 		{
    65 			plugin->info.stringbase = (const char *)(base + secptr->dataoffs);
    66 		}
    67 		else if (!(plugin->debug.files) && !strcmp(nameptr, ".dbg.files"))
    68 		{
    69 			plugin->debug.files = (sp_fdbg_file_t *)(base + secptr->dataoffs);
    70 		}
    71 		else if (!(plugin->debug.lines) && !strcmp(nameptr, ".dbg.lines"))
    72 		{
    73 			plugin->debug.lines = (sp_fdbg_line_t *)(base + secptr->dataoffs);
    74 		}
    75 		else if (!(plugin->debug.symbols) && !strcmp(nameptr, ".dbg.symbols"))
    76 		{
    77 			plugin->debug.symbols = (sp_fdbg_symbol_t *)(base + secptr->dataoffs);
    78 		}
    79 		else if (!(plugin->debug.lines_num) && !strcmp(nameptr, ".dbg.info"))
    80 		{
    81 			sp_fdbg_info_t *inf = (sp_fdbg_info_t *)(base + secptr->dataoffs);
    82 			plugin->debug.files_num = inf->num_files;
    83 			plugin->debug.lines_num = inf->num_lines;
    84 			plugin->debug.syms_num = inf->num_syms;
    85 		}
    86 		else if (!(plugin->debug.stringbase) && !strcmp(nameptr, ".dbg.strings"))
    87 		{
    88 			plugin->debug.stringbase = (const char *)(base + secptr->dataoffs);
    89 		}
    90 
    91 		secptr++;
    92 		sectnum++;
    93 	}
    94 
    95 	if (!(plugin->pcode) || !(plugin->data) || !(plugin->info.stringbase))
    96 	{
    97 		goto return_error;
    98 	}
    99 
   100 	if ((plugin->flags & SP_FLAG_DEBUG) && (!(plugin->debug.files) || !(plugin->debug.lines) || !(plugin->debug.symbols)))
   101 	{
   102 		goto return_error;
   103 	}
   104 
   105 	if (err)
   106 	{
   107 		*err = SP_ERROR_NONE;
   108 	}
   109 
   110 	return plugin;
   111 
   112 return_error:
   113 	if (err)
   114 	{
   115 		*err = SP_ERROR_FILE_FORMAT;
   116 	}
   117 
   118 	return NULL;
   119 }
   120 
   121 IPluginRuntime *SourcePawnEngine2::LoadPlugin(ICompilation *co, const char *file, int *err)
   122 {
   123 	sp_file_hdr_t hdr;
   124 	sp_plugin_t *plugin;
   125 	uint8_t *base;
   126 	int z_result;
   127 	int error;
   128 	BaseRuntime *pRuntime;
   129 
   130 	FILE *fp = fopen(file, "rb");
   131 
   132 	if (!fp)
   133 	{
   134 		error = SP_ERROR_NOT_FOUND;
   135 		goto return_error;
   136 	}
   137 
   138 	/* Rewind for safety */
   139 	fread(&hdr, sizeof(sp_file_hdr_t), 1, fp);
   140 
   141 	if (hdr.magic != SPFILE_MAGIC)
   142 	{
   143 		error = SP_ERROR_FILE_FORMAT;
   144 		goto return_error;
   145 	}
   146 
   147 	switch (hdr.compression)
   148 	{
   149 	case SPFILE_COMPRESSION_GZ:
   150 		{
   151 			uint32_t uncompsize = hdr.imagesize - hdr.dataoffs;
   152 			uint32_t compsize = hdr.disksize - hdr.dataoffs;
   153 			uint32_t sectsize = hdr.dataoffs - sizeof(sp_file_hdr_t);
   154 			uLongf destlen = uncompsize;
   155 
   156 			char *tempbuf = (char *)malloc(compsize);
   157 			void *uncompdata = malloc(uncompsize);
   158 			void *sectheader = malloc(sectsize);
   159 
   160 			fread(sectheader, sectsize, 1, fp);
   161 			fread(tempbuf, compsize, 1, fp);
   162 
   163 			z_result = uncompress((Bytef *)uncompdata, &destlen, (Bytef *)tempbuf, compsize);
   164 			free(tempbuf);
   165 			if (z_result != Z_OK)
   166 			{
   167 				free(sectheader);
   168 				free(uncompdata);
   169 				error = SP_ERROR_DECOMPRESSOR;
   170 				goto return_error;
   171 			}
   172 
   173 			base = (uint8_t *)malloc(hdr.imagesize);
   174 			memcpy(base, &hdr, sizeof(sp_file_hdr_t));
   175 			memcpy(base + sizeof(sp_file_hdr_t), sectheader, sectsize);
   176 			free(sectheader);
   177 			memcpy(base + hdr.dataoffs, uncompdata, uncompsize);
   178 			free(uncompdata);
   179 			break;
   180 		}
   181 	case SPFILE_COMPRESSION_NONE:
   182 		{
   183 			base = (uint8_t *)malloc(hdr.imagesize);
   184 			rewind(fp);
   185 			fread(base, hdr.imagesize, 1, fp);
   186 			break;
   187 		}
   188 	default:
   189 		{
   190 			error = SP_ERROR_DECOMPRESSOR;
   191 			goto return_error;
   192 		}
   193 	}
   194 
   195 	plugin = new sp_plugin_t;
   196 
   197 	memset(plugin, 0, sizeof(sp_plugin_t));
   198 
   199 	plugin->base_size = hdr.imagesize;
   200 	if (!_ReadPlugin(&hdr, base, plugin, err))
   201 	{
   202 		delete plugin;
   203 		free(base);
   204 		return NULL;
   205 	}
   206 
   207 	pRuntime = new BaseRuntime(plugin);
   208 
   209 	if (co == NULL)
   210 	{
   211 		co = g_Jit1.StartCompilation(pRuntime);
   212 	}
   213 
   214 
   215 	*err = pRuntime->ApplyCompilationOptions(co);
   216 	if (*err != SP_ERROR_NONE)
   217 	{
   218 		delete pRuntime;
   219 		return NULL;
   220 	}
   221 
   222 	return pRuntime;
   223 
   224 return_error:
   225 	*err = error;
   226 
   227 	return NULL;
   228 }
   229 
   230 SPVM_NATIVE_FUNC SourcePawnEngine2::CreateFakeNative(SPVM_FAKENATIVE_FUNC callback, void *pData)
   231 {
   232 	return g_Jit1.CreateFakeNative(callback, pData);
   233 }
   234 
   235 void SourcePawnEngine2::DestroyFakeNative(SPVM_NATIVE_FUNC func)
   236 {
   237 	g_Jit1.DestroyFakeNative(func);
   238 }
   239 
   240 const char *SourcePawnEngine2::GetEngineName()
   241 {
   242 	return "SourcePawn 1.1, jit-x86";
   243 }
   244 
   245 const char *SourcePawnEngine2::GetVersionString()
   246 {
   247 	return SVN_FULL_VERSION;
   248 }
   249 
   250 IProfiler *SourcePawnEngine2::GetProfiler()
   251 {
   252 	return m_Profiler;
   253 }
   254 
   255 void SourcePawnEngine2::SetProfiler(IProfiler *profiler)
   256 {
   257 	m_Profiler = profiler;
   258 }
   259 
   260 IDebugListener *SourcePawnEngine2::SetDebugListener(IDebugListener *listener)
   261 {
   262 	return g_engine1.SetDebugListener(listener);
   263 }
   264 
   265 unsigned int SourcePawnEngine2::GetAPIVersion()
   266 {
   267 	return SOURCEPAWN_ENGINE2_API_VERSION;
   268 }
   269 
   270 ICompilation *SourcePawnEngine2::StartCompilation()
   271 {
   272 	return g_Jit1.StartCompilation();
   273 }
   274 
   275 const char *SourcePawnEngine2::GetErrorString(int err)
   276 {
   277 	return g_engine1.GetErrorString(err);
   278 }