sourcepawn/jit/BaseRuntime.cpp
author David Anderson <dvander@alliedmods.net>
Fri Sep 05 06:15:54 2008 +0000 (2008-09-05)
changeset 2249 a1ce7e3f08b7
parent 2226 d10b38524be3
child 2377 6ee3bbd6fbdf
permissions -rw-r--r--
Fixed profiler being initialized at the wrong time, causing a paired callback mismatch (bug amb1977).
     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <string.h>
     4 #include <assert.h>
     5 #include "BaseRuntime.h"
     6 #include "sp_vm_engine.h"
     7 #include "x86/jit_x86.h"
     8 #include "sp_vm_basecontext.h"
     9 #include "engine2.h"
    10 
    11 using namespace SourcePawn;
    12 
    13 BaseRuntime::BaseRuntime() : m_Debug(&m_plugin), m_pPlugin(&m_plugin), m_pCtx(NULL), 
    14 m_PubFuncs(NULL), m_PubJitFuncs(NULL), m_pCo(NULL), m_CompSerial(0)
    15 {
    16 	memset(&m_plugin, 0, sizeof(m_plugin));
    17 
    18 	m_FuncCache = NULL;
    19 	m_MaxFuncs = 0;
    20 	m_NumFuncs = 0;
    21 }
    22 
    23 BaseRuntime::~BaseRuntime()
    24 {
    25 	for (uint32_t i = 0; i < m_pPlugin->num_publics; i++)
    26 	{
    27 		delete m_PubFuncs[i];
    28 		m_PubFuncs[i] = NULL;
    29 	}
    30 	delete [] m_PubFuncs;
    31 	delete [] m_PubJitFuncs;
    32 
    33 	for (unsigned int i = 0; i < m_NumFuncs; i++)
    34 	{
    35 		delete m_FuncCache[i];
    36 	}
    37 	free(m_FuncCache);
    38 
    39 	delete m_pCtx;
    40 	delete m_pCo;
    41 
    42 	free(m_pPlugin->base);
    43 	delete [] m_pPlugin->memory;
    44 	delete [] m_pPlugin->publics;
    45 	delete [] m_pPlugin->pubvars;
    46 	delete [] m_pPlugin->natives;
    47 	free(m_pPlugin->name);
    48 }
    49 
    50 static cell_t InvalidNative(IPluginContext *pCtx, const cell_t *params)
    51 {
    52 	return pCtx->ThrowNativeErrorEx(SP_ERROR_INVALID_NATIVE, "Invalid native");
    53 }
    54 
    55 int BaseRuntime::CreateFromMemory(sp_file_hdr_t *hdr, uint8_t *base)
    56 {
    57 	int set_err;
    58 	char *nameptr;
    59 	uint8_t sectnum = 0;
    60 	sp_plugin_t *plugin = m_pPlugin;
    61 	sp_file_section_t *secptr = (sp_file_section_t *)(base + sizeof(sp_file_hdr_t));
    62 
    63 	memset(plugin, 0, sizeof(sp_plugin_t));
    64 
    65 	plugin->base = base;
    66 	plugin->base_size = hdr->imagesize;
    67 	set_err = SP_ERROR_NONE;
    68 
    69 	/* We have to read the name section first */
    70 	for (sectnum = 0; sectnum < hdr->sections; sectnum++)
    71 	{
    72 		nameptr = (char *)(base + hdr->stringtab + secptr[sectnum].nameoffs);
    73 		if (strcmp(nameptr, ".names") == 0)
    74 		{
    75 			plugin->stringbase = (const char *)(base + secptr[sectnum].dataoffs);
    76 			break;
    77 		}
    78 	}
    79 
    80 	sectnum = 0;
    81 
    82 	/* Now read the rest of the sections */
    83 	while (sectnum < hdr->sections)
    84 	{
    85 		nameptr = (char *)(base + hdr->stringtab + secptr->nameoffs);
    86 
    87 		if (!(plugin->pcode) && !strcmp(nameptr, ".code"))
    88 		{
    89 			sp_file_code_t *cod = (sp_file_code_t *)(base + secptr->dataoffs);
    90 
    91 			if (cod->codeversion < SP_CODEVERS_JIT1)
    92 			{
    93 				return SP_ERROR_CODE_TOO_OLD;
    94 			}
    95 			else if (cod->codeversion > SP_CODEVERS_JIT2)
    96 			{
    97 				return SP_ERROR_CODE_TOO_NEW;
    98 			}
    99 
   100 			plugin->pcode = base + secptr->dataoffs + cod->code;
   101 			plugin->pcode_size = cod->codesize;
   102 			plugin->flags = cod->flags;
   103 			plugin->pcode_version = cod->codeversion;
   104 		}
   105 		else if (!(plugin->data) && !strcmp(nameptr, ".data"))
   106 		{
   107 			sp_file_data_t *dat = (sp_file_data_t *)(base + secptr->dataoffs);
   108 			plugin->data = base + secptr->dataoffs + dat->data;
   109 			plugin->data_size = dat->datasize;
   110 			plugin->mem_size = dat->memsize;
   111 			plugin->memory = new uint8_t[plugin->mem_size];
   112 			memcpy(plugin->memory, plugin->data, plugin->data_size);
   113 		}
   114 		else if ((plugin->publics == NULL) && !strcmp(nameptr, ".publics"))
   115 		{
   116 			sp_file_publics_t *publics;
   117 
   118 			publics = (sp_file_publics_t *)(base + secptr->dataoffs);
   119 			plugin->num_publics = secptr->size / sizeof(sp_file_publics_t);
   120 
   121 			if (plugin->num_publics > 0)
   122 			{
   123 				plugin->publics = new sp_public_t[plugin->num_publics];
   124 
   125 				for (uint32_t i = 0; i < plugin->num_publics; i++)
   126 				{
   127 					plugin->publics[i].code_offs = publics[i].address;
   128 					plugin->publics[i].funcid = (i << 1) | 1;
   129 					plugin->publics[i].name = plugin->stringbase + publics[i].name;
   130 				}
   131 			}
   132 		}
   133 		else if ((plugin->pubvars == NULL) && !strcmp(nameptr, ".pubvars"))
   134 		{
   135 			sp_file_pubvars_t *pubvars;
   136 
   137 			pubvars = (sp_file_pubvars_t *)(base + secptr->dataoffs);
   138 			plugin->num_pubvars = secptr->size / sizeof(sp_file_pubvars_t);
   139 
   140 			if (plugin->num_pubvars > 0)
   141 			{
   142 				plugin->pubvars = new sp_pubvar_t[plugin->num_pubvars];
   143 
   144 				for (uint32_t i = 0; i < plugin->num_pubvars; i++)
   145 				{
   146 					plugin->pubvars[i].name = plugin->stringbase + pubvars[i].name;
   147 					plugin->pubvars[i].offs = (cell_t *)(plugin->memory + pubvars[i].address);
   148 				}
   149 			}
   150 		}
   151 		else if ((plugin->natives == NULL) && !strcmp(nameptr, ".natives"))
   152 		{
   153 			sp_file_natives_t *natives;
   154 
   155 			natives = (sp_file_natives_t *)(base + secptr->dataoffs);
   156 			plugin->num_natives = secptr->size / sizeof(sp_file_natives_t);
   157 
   158 			if (plugin->num_natives > 0)
   159 			{
   160 				plugin->natives = new sp_native_t[plugin->num_natives];
   161 
   162 				for (uint32_t i = 0; i < plugin->num_natives; i++)
   163 				{
   164 					plugin->natives[i].flags = 0;
   165 					plugin->natives[i].pfn = InvalidNative;
   166 					plugin->natives[i].status = SP_NATIVE_UNBOUND;
   167 					plugin->natives[i].user = NULL;
   168 					plugin->natives[i].name = plugin->stringbase + natives[i].name;
   169 				}
   170 			}
   171 		}
   172 		else if (!(plugin->debug.files) && !strcmp(nameptr, ".dbg.files"))
   173 		{
   174 			plugin->debug.files = (sp_fdbg_file_t *)(base + secptr->dataoffs);
   175 		}
   176 		else if (!(plugin->debug.lines) && !strcmp(nameptr, ".dbg.lines"))
   177 		{
   178 			plugin->debug.lines = (sp_fdbg_line_t *)(base + secptr->dataoffs);
   179 		}
   180 		else if (!(plugin->debug.symbols) && !strcmp(nameptr, ".dbg.symbols"))
   181 		{
   182 			plugin->debug.symbols = (sp_fdbg_symbol_t *)(base + secptr->dataoffs);
   183 		}
   184 		else if (!(plugin->debug.lines_num) && !strcmp(nameptr, ".dbg.info"))
   185 		{
   186 			sp_fdbg_info_t *inf = (sp_fdbg_info_t *)(base + secptr->dataoffs);
   187 			plugin->debug.files_num = inf->num_files;
   188 			plugin->debug.lines_num = inf->num_lines;
   189 			plugin->debug.syms_num = inf->num_syms;
   190 		}
   191 		else if (!(plugin->debug.stringbase) && !strcmp(nameptr, ".dbg.strings"))
   192 		{
   193 			plugin->debug.stringbase = (const char *)(base + secptr->dataoffs);
   194 		}
   195 
   196 		secptr++;
   197 		sectnum++;
   198 	}
   199 
   200 	if (plugin->pcode == NULL || plugin->data == NULL)
   201 	{
   202 		return SP_ERROR_FILE_FORMAT;
   203 	}
   204 
   205 	if ((plugin->flags & SP_FLAG_DEBUG) && (!(plugin->debug.files) || !(plugin->debug.lines) || !(plugin->debug.symbols)))
   206 	{
   207 		return SP_ERROR_FILE_FORMAT;
   208 	}
   209 
   210 	if (m_pPlugin->num_publics > 0)
   211 	{
   212 		m_PubFuncs = new CFunction *[m_pPlugin->num_publics];
   213 		memset(m_PubFuncs, 0, sizeof(CFunction *) * m_pPlugin->num_publics);
   214 		m_PubJitFuncs = new JitFunction *[m_pPlugin->num_publics];
   215 		memset(m_PubJitFuncs, 0, sizeof(JitFunction *) * m_pPlugin->num_publics);
   216 	}
   217 
   218 	m_pPlugin->profiler = g_engine2.GetProfiler();
   219 	m_pCtx = new BaseContext(this);
   220 	m_pCo = g_Jit.StartCompilation(this);
   221 
   222 	return SP_ERROR_NONE;
   223 }
   224 
   225 int BaseRuntime::FindNativeByName(const char *name, uint32_t *index)
   226 {
   227 	int high;
   228 
   229 	high = m_pPlugin->num_natives - 1;
   230 
   231 	for (uint32_t i=0; i<m_pPlugin->num_natives; i++)
   232 	{
   233 		if (strcmp(m_pPlugin->natives[i].name, name) == 0)
   234 		{
   235 			if (index)
   236 			{
   237 				*index = i;
   238 			}
   239 			return SP_ERROR_NONE;
   240 		}
   241 	}
   242 
   243 	return SP_ERROR_NOT_FOUND;
   244 }
   245 
   246 int BaseRuntime::GetNativeByIndex(uint32_t index, sp_native_t **native)
   247 {
   248 	if (index >= m_pPlugin->num_natives)
   249 	{
   250 		return SP_ERROR_INDEX;
   251 	}
   252 
   253 	if (native)
   254 	{
   255 		*native = &(m_pPlugin->natives[index]);
   256 	}
   257 
   258 	return SP_ERROR_NONE;
   259 }
   260 
   261 
   262 uint32_t BaseRuntime::GetNativesNum()
   263 {
   264 	return m_pPlugin->num_natives;
   265 }
   266 
   267 int BaseRuntime::FindPublicByName(const char *name, uint32_t *index)
   268 {
   269 	int diff, high, low;
   270 	uint32_t mid;
   271 
   272 	high = m_pPlugin->num_publics - 1;
   273 	low = 0;
   274 
   275 	while (low <= high)
   276 	{
   277 		mid = (low + high) / 2;
   278 		diff = strcmp(m_pPlugin->publics[mid].name, name);
   279 		if (diff == 0)
   280 		{
   281 			if (index)
   282 			{
   283 				*index = mid;
   284 			}
   285 			return SP_ERROR_NONE;
   286 		} else if (diff < 0) {
   287 			low = mid + 1;
   288 		} else {
   289 			high = mid - 1;
   290 		}
   291 	}
   292 
   293 	return SP_ERROR_NOT_FOUND;
   294 }
   295 
   296 int BaseRuntime::GetPublicByIndex(uint32_t index, sp_public_t **pblic)
   297 {
   298 	if (index >= m_pPlugin->num_publics)
   299 	{
   300 		return SP_ERROR_INDEX;
   301 	}
   302 
   303 	if (pblic)
   304 	{
   305 		*pblic = &(m_pPlugin->publics[index]);
   306 	}
   307 
   308 	return SP_ERROR_NONE;
   309 }
   310 
   311 uint32_t BaseRuntime::GetPublicsNum()
   312 {
   313 	return m_pPlugin->num_publics;
   314 }
   315 
   316 int BaseRuntime::GetPubvarByIndex(uint32_t index, sp_pubvar_t **pubvar)
   317 {
   318 	if (index >= m_pPlugin->num_pubvars)
   319 	{
   320 		return SP_ERROR_INDEX;
   321 	}
   322 
   323 	if (pubvar)
   324 	{
   325 		*pubvar = &(m_pPlugin->pubvars[index]);
   326 	}
   327 
   328 	return SP_ERROR_NONE;
   329 }
   330 
   331 int BaseRuntime::FindPubvarByName(const char *name, uint32_t *index)
   332 {
   333 	int diff, high, low;
   334 	uint32_t mid;
   335 
   336 	high = m_pPlugin->num_pubvars - 1;
   337 	low = 0;
   338 
   339 	while (low <= high)
   340 	{
   341 		mid = (low + high) / 2;
   342 		diff = strcmp(m_pPlugin->pubvars[mid].name, name);
   343 		if (diff == 0)
   344 		{
   345 			if (index)
   346 			{
   347 				*index = mid;
   348 			}
   349 			return SP_ERROR_NONE;
   350 		}
   351 		else if (diff < 0)
   352 		{
   353 			low = mid + 1;
   354 		}
   355 		else
   356 		{
   357 			high = mid - 1;
   358 		}
   359 	}
   360 
   361 	return SP_ERROR_NOT_FOUND;
   362 }
   363 
   364 int BaseRuntime::GetPubvarAddrs(uint32_t index, cell_t *local_addr, cell_t **phys_addr)
   365 {
   366 	if (index >= m_pPlugin->num_pubvars)
   367 	{
   368 		return SP_ERROR_INDEX;
   369 	}
   370 
   371 	*local_addr = (uint8_t *)m_pPlugin->pubvars[index].offs - m_pPlugin->memory;
   372 	*phys_addr = m_pPlugin->pubvars[index].offs;
   373 
   374 	return SP_ERROR_NONE;
   375 }
   376 
   377 uint32_t BaseRuntime::GetPubVarsNum()
   378 {
   379 	return m_pPlugin->num_pubvars;
   380 }
   381 
   382 IPluginContext *BaseRuntime::GetDefaultContext()
   383 {
   384 	return m_pCtx;
   385 }
   386 
   387 IPluginDebugInfo *BaseRuntime::GetDebugInfo()
   388 {
   389 	return &m_Debug;
   390 }
   391 
   392 IPluginFunction *BaseRuntime::GetFunctionById(funcid_t func_id)
   393 {
   394 	CFunction *pFunc = NULL;
   395 
   396 	if (func_id & 1)
   397 	{
   398 		func_id >>= 1;
   399 		if (func_id >= m_pPlugin->num_publics)
   400 		{
   401 			return NULL;
   402 		}
   403 		pFunc = m_PubFuncs[func_id];
   404 		if (!pFunc)
   405 		{
   406 			m_PubFuncs[func_id] = new CFunction(this, 
   407 				(func_id << 1) | 1,
   408 				func_id);
   409 			pFunc = m_PubFuncs[func_id];
   410 		}
   411 	}
   412 
   413 	return pFunc;
   414 }
   415 
   416 IPluginFunction *BaseRuntime::GetFunctionByName(const char *public_name)
   417 {
   418 	uint32_t index;
   419 
   420 	if (FindPublicByName(public_name, &index) != SP_ERROR_NONE)
   421 	{
   422 		return NULL;
   423 	}
   424 
   425 	CFunction *pFunc = m_PubFuncs[index];
   426 	if (!pFunc)
   427 	{
   428 		sp_public_t *pub = NULL;
   429 		GetPublicByIndex(index, &pub);
   430 		if (pub)
   431 		{
   432 			m_PubFuncs[index] = new CFunction(this, (index << 1) | 1, index);
   433 		}
   434 		pFunc = m_PubFuncs[index];
   435 	}
   436 
   437 	return pFunc;
   438 }
   439 
   440 bool BaseRuntime::IsDebugging()
   441 {
   442 	return true;
   443 }
   444 
   445 void BaseRuntime::SetPauseState(bool paused)
   446 {
   447 	if (paused)
   448 	{
   449 		m_pPlugin->run_flags |= SPFLAG_PLUGIN_PAUSED;
   450 	}
   451 	else
   452 	{
   453 		m_pPlugin->run_flags &= ~SPFLAG_PLUGIN_PAUSED;
   454 	}
   455 }
   456 
   457 bool BaseRuntime::IsPaused()
   458 {
   459 	return ((m_pPlugin->run_flags & SPFLAG_PLUGIN_PAUSED) == SPFLAG_PLUGIN_PAUSED);
   460 }
   461 
   462 size_t BaseRuntime::GetMemUsage()
   463 {
   464 	size_t mem = 0;
   465 
   466 	mem += sizeof(this);
   467 	mem += sizeof(sp_plugin_t);
   468 	mem += sizeof(BaseContext);
   469 	mem += m_pPlugin->base_size;
   470 
   471 	return mem;
   472 }
   473 
   474 BaseContext *BaseRuntime::GetBaseContext()
   475 {
   476 	return m_pCtx;
   477 }
   478 
   479 int BaseRuntime::ApplyCompilationOptions(ICompilation *co)
   480 {
   481 	if (co == NULL)
   482 	{
   483 		return SP_ERROR_NONE;
   484 	}
   485 
   486 	m_pCo = g_Jit.ApplyOptions(m_pCo, co);
   487 	m_pPlugin->prof_flags = ((CompData *)m_pCo)->profile;
   488 
   489 	return SP_ERROR_NONE;
   490 }
   491 
   492 JitFunction *BaseRuntime::GetJittedFunction(uint32_t idx)
   493 {
   494 	assert(idx <= m_NumFuncs);
   495 
   496 	if (idx == 0 || idx > m_NumFuncs)
   497 	{
   498 		return NULL;
   499 	}
   500 
   501 	return m_FuncCache[idx - 1];
   502 }
   503 
   504 uint32_t BaseRuntime::AddJittedFunction(JitFunction *fn)
   505 {
   506 	if (m_NumFuncs + 1 > m_MaxFuncs)
   507 	{
   508 		if (m_MaxFuncs == 0)
   509 		{
   510 			m_MaxFuncs = 8;
   511 		}
   512 		else
   513 		{
   514 			m_MaxFuncs *= 2;
   515 		}
   516 
   517 		m_FuncCache = (JitFunction **)realloc(
   518 			m_FuncCache,
   519 			sizeof(JitFunction *) * m_MaxFuncs);
   520 	}
   521 
   522 	m_FuncCache[m_NumFuncs++] = fn;
   523 
   524 	return m_NumFuncs;
   525 }