sourcepawn/jit/engine2.cpp
author David Anderson <dvander@alliedmods.net>
Fri Aug 15 05:22:26 2008 +0000 (2008-08-15)
changeset 2226 d10b38524be3
parent 2219 5ddd93671335
child 2242 cb53a313c38e
permissions -rw-r--r--
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.
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
IPluginRuntime *SourcePawnEngine2::LoadPlugin(ICompilation *co, const char *file, int *err)
dvander@2193
    19
{
dvander@2193
    20
	sp_file_hdr_t hdr;
dvander@2193
    21
	uint8_t *base;
dvander@2193
    22
	int z_result;
dvander@2193
    23
	int error;
dvander@2193
    24
	BaseRuntime *pRuntime;
dvander@2193
    25
dvander@2193
    26
	FILE *fp = fopen(file, "rb");
dvander@2193
    27
dvander@2193
    28
	if (!fp)
dvander@2193
    29
	{
dvander@2193
    30
		error = SP_ERROR_NOT_FOUND;
dvander@2193
    31
		goto return_error;
dvander@2193
    32
	}
dvander@2193
    33
dvander@2193
    34
	/* Rewind for safety */
dvander@2193
    35
	fread(&hdr, sizeof(sp_file_hdr_t), 1, fp);
dvander@2193
    36
dvander@2193
    37
	if (hdr.magic != SPFILE_MAGIC)
dvander@2193
    38
	{
dvander@2193
    39
		error = SP_ERROR_FILE_FORMAT;
dvander@2193
    40
		goto return_error;
dvander@2193
    41
	}
dvander@2193
    42
dvander@2193
    43
	switch (hdr.compression)
dvander@2193
    44
	{
dvander@2193
    45
	case SPFILE_COMPRESSION_GZ:
dvander@2193
    46
		{
dvander@2193
    47
			uint32_t uncompsize = hdr.imagesize - hdr.dataoffs;
dvander@2193
    48
			uint32_t compsize = hdr.disksize - hdr.dataoffs;
dvander@2193
    49
			uint32_t sectsize = hdr.dataoffs - sizeof(sp_file_hdr_t);
dvander@2193
    50
			uLongf destlen = uncompsize;
dvander@2193
    51
dvander@2193
    52
			char *tempbuf = (char *)malloc(compsize);
dvander@2193
    53
			void *uncompdata = malloc(uncompsize);
dvander@2193
    54
			void *sectheader = malloc(sectsize);
dvander@2193
    55
dvander@2193
    56
			fread(sectheader, sectsize, 1, fp);
dvander@2193
    57
			fread(tempbuf, compsize, 1, fp);
dvander@2193
    58
dvander@2193
    59
			z_result = uncompress((Bytef *)uncompdata, &destlen, (Bytef *)tempbuf, compsize);
dvander@2193
    60
			free(tempbuf);
dvander@2193
    61
			if (z_result != Z_OK)
dvander@2193
    62
			{
dvander@2193
    63
				free(sectheader);
dvander@2193
    64
				free(uncompdata);
dvander@2193
    65
				error = SP_ERROR_DECOMPRESSOR;
dvander@2193
    66
				goto return_error;
dvander@2193
    67
			}
dvander@2193
    68
dvander@2193
    69
			base = (uint8_t *)malloc(hdr.imagesize);
dvander@2193
    70
			memcpy(base, &hdr, sizeof(sp_file_hdr_t));
dvander@2193
    71
			memcpy(base + sizeof(sp_file_hdr_t), sectheader, sectsize);
dvander@2193
    72
			free(sectheader);
dvander@2193
    73
			memcpy(base + hdr.dataoffs, uncompdata, uncompsize);
dvander@2193
    74
			free(uncompdata);
dvander@2193
    75
			break;
dvander@2193
    76
		}
dvander@2193
    77
	case SPFILE_COMPRESSION_NONE:
dvander@2193
    78
		{
dvander@2193
    79
			base = (uint8_t *)malloc(hdr.imagesize);
dvander@2193
    80
			rewind(fp);
dvander@2193
    81
			fread(base, hdr.imagesize, 1, fp);
dvander@2193
    82
			break;
dvander@2193
    83
		}
dvander@2193
    84
	default:
dvander@2193
    85
		{
dvander@2193
    86
			error = SP_ERROR_DECOMPRESSOR;
dvander@2193
    87
			goto return_error;
dvander@2193
    88
		}
dvander@2193
    89
	}
dvander@2193
    90
pred@2219
    91
dvander@2226
    92
	pRuntime = new BaseRuntime();
dvander@2226
    93
	if ((error = pRuntime->CreateFromMemory(&hdr, base)) != SP_ERROR_NONE)
dvander@2193
    94
	{
dvander@2226
    95
		delete pRuntime;
dvander@2226
    96
		goto return_error;
dvander@2193
    97
	}
dvander@2193
    98
dvander@2226
    99
	size_t len;
dvander@2226
   100
	
dvander@2226
   101
	len = strlen(file);
dvander@2226
   102
	for (size_t i = len - 1; i >= 0 && i < len; i--)
dvander@2193
   103
	{
dvander@2226
   104
		if (file[i] == '/' 
dvander@2226
   105
		#if defined WIN32
dvander@2226
   106
			|| file[i] == '\\'
dvander@2226
   107
		#endif
dvander@2226
   108
		)
dvander@2226
   109
		{
dvander@2226
   110
			pRuntime->m_pPlugin->name = strdup(&file[i+1]);
dvander@2226
   111
			break;
dvander@2226
   112
		}
dvander@2193
   113
	}
dvander@2193
   114
dvander@2226
   115
	if (pRuntime->m_pPlugin->name == NULL)
dvander@2193
   116
	{
dvander@2226
   117
		pRuntime->m_pPlugin->name = strdup(file);
dvander@2193
   118
	}
dvander@2193
   119
dvander@2226
   120
	pRuntime->ApplyCompilationOptions(co);
dvander@2226
   121
dvander@2193
   122
	return pRuntime;
dvander@2193
   123
dvander@2193
   124
return_error:
dvander@2193
   125
	*err = error;
dvander@2193
   126
dvander@2193
   127
	return NULL;
dvander@2193
   128
}
dvander@2193
   129
dvander@2193
   130
SPVM_NATIVE_FUNC SourcePawnEngine2::CreateFakeNative(SPVM_FAKENATIVE_FUNC callback, void *pData)
dvander@2193
   131
{
dvander@2226
   132
	return g_Jit.CreateFakeNative(callback, pData);
dvander@2193
   133
}
dvander@2193
   134
dvander@2193
   135
void SourcePawnEngine2::DestroyFakeNative(SPVM_NATIVE_FUNC func)
dvander@2193
   136
{
dvander@2226
   137
	g_Jit.DestroyFakeNative(func);
dvander@2193
   138
}
dvander@2193
   139
dvander@2193
   140
const char *SourcePawnEngine2::GetEngineName()
dvander@2193
   141
{
dvander@2193
   142
	return "SourcePawn 1.1, jit-x86";
dvander@2193
   143
}
dvander@2193
   144
dvander@2193
   145
const char *SourcePawnEngine2::GetVersionString()
dvander@2193
   146
{
dvander@2193
   147
	return SVN_FULL_VERSION;
dvander@2193
   148
}
dvander@2193
   149
dvander@2193
   150
IProfiler *SourcePawnEngine2::GetProfiler()
dvander@2193
   151
{
dvander@2193
   152
	return m_Profiler;
dvander@2193
   153
}
dvander@2193
   154
dvander@2193
   155
void SourcePawnEngine2::SetProfiler(IProfiler *profiler)
dvander@2193
   156
{
dvander@2193
   157
	m_Profiler = profiler;
dvander@2193
   158
}
dvander@2193
   159
dvander@2193
   160
IDebugListener *SourcePawnEngine2::SetDebugListener(IDebugListener *listener)
dvander@2193
   161
{
dvander@2193
   162
	return g_engine1.SetDebugListener(listener);
dvander@2193
   163
}
dvander@2193
   164
dvander@2193
   165
unsigned int SourcePawnEngine2::GetAPIVersion()
dvander@2193
   166
{
dvander@2193
   167
	return SOURCEPAWN_ENGINE2_API_VERSION;
dvander@2193
   168
}
dvander@2193
   169
dvander@2193
   170
ICompilation *SourcePawnEngine2::StartCompilation()
dvander@2193
   171
{
dvander@2226
   172
	return g_Jit.StartCompilation();
dvander@2193
   173
}
dvander@2193
   174
dvander@2193
   175
const char *SourcePawnEngine2::GetErrorString(int err)
dvander@2193
   176
{
dvander@2193
   177
	return g_engine1.GetErrorString(err);
dvander@2193
   178
}
dvander@2226
   179
dvander@2226
   180
bool SourcePawnEngine2::Initialize()
dvander@2226
   181
{
dvander@2226
   182
	return g_Jit.InitializeJIT();
dvander@2226
   183
}
dvander@2226
   184
dvander@2226
   185
void SourcePawnEngine2::Shutdown()
dvander@2226
   186
{
dvander@2226
   187
	g_Jit.ShutdownJIT();
dvander@2226
   188
}