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