sourcepawn/jit/BaseRuntime.cpp
author David Anderson <dvander@alliedmods.net>
Mon Jul 07 06:24:54 2008 +0000 (2008-07-07)
branchrefac-jit
changeset 2174 01c5adfae757
parent 2171 0885b66fcf81
child 2188 24b170ea6ce7
permissions -rw-r--r--
more api for core
sets profiler+debugger now
dvander@2171
     1
#include <stdio.h>
dvander@2171
     2
#include <stdlib.h>
dvander@2171
     3
#include <string.h>
dvander@2171
     4
#include "BaseRuntime.h"
dvander@2171
     5
#include "sp_vm_engine.h"
dvander@2171
     6
#include "x86/jit_x86.h"
dvander@2171
     7
#include "sp_vm_basecontext.h"
dvander@2174
     8
#include "engine2.h"
dvander@2171
     9
dvander@2171
    10
using namespace SourcePawn;
dvander@2171
    11
dvander@2171
    12
int GlobalDebugBreak(BaseContext *ctx, uint32_t frm, uint32_t cip)
dvander@2171
    13
{
dvander@2171
    14
	g_engine1.RunTracer(ctx, frm, cip);
dvander@2171
    15
dvander@2171
    16
	return SP_ERROR_NONE;
dvander@2171
    17
}
dvander@2171
    18
dvander@2171
    19
BaseRuntime::BaseRuntime(sp_plugin_t *pl) : m_Debug(pl), m_pPlugin(pl)
dvander@2171
    20
{
dvander@2171
    21
	m_pCtx = new BaseContext(this);
dvander@2171
    22
dvander@2171
    23
	if (m_pPlugin->info.publics_num > 0)
dvander@2171
    24
	{
dvander@2171
    25
		m_PubFuncs = new CFunction *[m_pPlugin->info.publics_num];
dvander@2171
    26
		memset(m_PubFuncs, 0, sizeof(CFunction *) * m_pPlugin->info.publics_num);
dvander@2171
    27
	}
dvander@2171
    28
	else
dvander@2171
    29
	{
dvander@2171
    30
		m_PubFuncs = NULL;
dvander@2171
    31
	}
dvander@2174
    32
dvander@2174
    33
	m_pPlugin->dbreak = GlobalDebugBreak;
dvander@2174
    34
	m_pPlugin->profiler = g_engine2.GetProfiler();
dvander@2171
    35
}
dvander@2171
    36
dvander@2171
    37
BaseRuntime::~BaseRuntime()
dvander@2171
    38
{
dvander@2171
    39
	for (uint32_t i = 0; i < m_pPlugin->info.publics_num; i++)
dvander@2171
    40
	{
dvander@2171
    41
		delete m_PubFuncs[i];
dvander@2171
    42
		m_PubFuncs[i] = NULL;
dvander@2171
    43
	}
dvander@2171
    44
	delete [] m_PubFuncs;
dvander@2171
    45
dvander@2171
    46
	ClearCompile();
dvander@2171
    47
dvander@2171
    48
	free(m_pPlugin->base);
dvander@2171
    49
	delete [] m_pPlugin->memory;
dvander@2171
    50
	delete m_pPlugin;
dvander@2171
    51
}
dvander@2171
    52
dvander@2171
    53
void BaseRuntime::ClearCompile()
dvander@2171
    54
{
dvander@2171
    55
	g_Jit1.FreeContextVars(m_pCtx->GetContext());
dvander@2171
    56
	g_Jit1.FreePluginVars(m_pPlugin);
dvander@2171
    57
}
dvander@2171
    58
dvander@2171
    59
int BaseRuntime::FindNativeByName(const char *name, uint32_t *index)
dvander@2171
    60
{
dvander@2171
    61
	int high;
dvander@2171
    62
dvander@2171
    63
	high = m_pPlugin->info.natives_num - 1;
dvander@2171
    64
dvander@2171
    65
	for (uint32_t i=0; i<m_pPlugin->info.natives_num; i++)
dvander@2171
    66
	{
dvander@2171
    67
		if (strcmp(m_pPlugin->natives[i].name, name) == 0)
dvander@2171
    68
		{
dvander@2171
    69
			if (index)
dvander@2171
    70
			{
dvander@2171
    71
				*index = i;
dvander@2171
    72
			}
dvander@2171
    73
			return SP_ERROR_NONE;
dvander@2171
    74
		}
dvander@2171
    75
	}
dvander@2171
    76
dvander@2171
    77
	return SP_ERROR_NOT_FOUND;
dvander@2171
    78
}
dvander@2171
    79
dvander@2171
    80
int BaseRuntime::GetNativeByIndex(uint32_t index, sp_native_t **native)
dvander@2171
    81
{
dvander@2171
    82
	if (index >= m_pPlugin->info.natives_num)
dvander@2171
    83
	{
dvander@2171
    84
		return SP_ERROR_INDEX;
dvander@2171
    85
	}
dvander@2171
    86
dvander@2171
    87
	if (native)
dvander@2171
    88
	{
dvander@2171
    89
		*native = &(m_pPlugin->natives[index]);
dvander@2171
    90
	}
dvander@2171
    91
dvander@2171
    92
	return SP_ERROR_NONE;
dvander@2171
    93
}
dvander@2171
    94
dvander@2171
    95
dvander@2171
    96
uint32_t BaseRuntime::GetNativesNum()
dvander@2171
    97
{
dvander@2171
    98
	return m_pPlugin->info.natives_num;
dvander@2171
    99
}
dvander@2171
   100
dvander@2171
   101
int BaseRuntime::FindPublicByName(const char *name, uint32_t *index)
dvander@2171
   102
{
dvander@2171
   103
	int diff, high, low;
dvander@2171
   104
	uint32_t mid;
dvander@2171
   105
dvander@2171
   106
	high = m_pPlugin->info.publics_num - 1;
dvander@2171
   107
	low = 0;
dvander@2171
   108
dvander@2171
   109
	while (low <= high)
dvander@2171
   110
	{
dvander@2171
   111
		mid = (low + high) / 2;
dvander@2171
   112
		diff = strcmp(m_pPlugin->publics[mid].name, name);
dvander@2171
   113
		if (diff == 0)
dvander@2171
   114
		{
dvander@2171
   115
			if (index)
dvander@2171
   116
			{
dvander@2171
   117
				*index = mid;
dvander@2171
   118
			}
dvander@2171
   119
			return SP_ERROR_NONE;
dvander@2171
   120
		} else if (diff < 0) {
dvander@2171
   121
			low = mid + 1;
dvander@2171
   122
		} else {
dvander@2171
   123
			high = mid - 1;
dvander@2171
   124
		}
dvander@2171
   125
	}
dvander@2171
   126
dvander@2171
   127
	return SP_ERROR_NOT_FOUND;
dvander@2171
   128
}
dvander@2171
   129
dvander@2171
   130
int BaseRuntime::GetPublicByIndex(uint32_t index, sp_public_t **pblic)
dvander@2171
   131
{
dvander@2171
   132
	if (index >= m_pPlugin->info.publics_num)
dvander@2171
   133
	{
dvander@2171
   134
		return SP_ERROR_INDEX;
dvander@2171
   135
	}
dvander@2171
   136
dvander@2171
   137
	if (pblic)
dvander@2171
   138
	{
dvander@2171
   139
		*pblic = &(m_pPlugin->publics[index]);
dvander@2171
   140
	}
dvander@2171
   141
dvander@2171
   142
	return SP_ERROR_NONE;
dvander@2171
   143
}
dvander@2171
   144
dvander@2171
   145
uint32_t BaseRuntime::GetPublicsNum()
dvander@2171
   146
{
dvander@2171
   147
	return m_pPlugin->info.publics_num;
dvander@2171
   148
}
dvander@2171
   149
dvander@2171
   150
int BaseRuntime::GetPubvarByIndex(uint32_t index, sp_pubvar_t **pubvar)
dvander@2171
   151
{
dvander@2171
   152
	if (index >= m_pPlugin->info.pubvars_num)
dvander@2171
   153
	{
dvander@2171
   154
		return SP_ERROR_INDEX;
dvander@2171
   155
	}
dvander@2171
   156
dvander@2171
   157
	if (pubvar)
dvander@2171
   158
	{
dvander@2171
   159
		*pubvar = &(m_pPlugin->pubvars[index]);
dvander@2171
   160
	}
dvander@2171
   161
dvander@2171
   162
	return SP_ERROR_NONE;
dvander@2171
   163
}
dvander@2171
   164
dvander@2171
   165
int BaseRuntime::FindPubvarByName(const char *name, uint32_t *index)
dvander@2171
   166
{
dvander@2171
   167
	int diff, high, low;
dvander@2171
   168
	uint32_t mid;
dvander@2171
   169
dvander@2171
   170
	high = m_pPlugin->info.pubvars_num - 1;
dvander@2171
   171
	low = 0;
dvander@2171
   172
dvander@2171
   173
	while (low <= high)
dvander@2171
   174
	{
dvander@2171
   175
		mid = (low + high) / 2;
dvander@2171
   176
		diff = strcmp(m_pPlugin->pubvars[mid].name, name);
dvander@2171
   177
		if (diff == 0)
dvander@2171
   178
		{
dvander@2171
   179
			if (index)
dvander@2171
   180
			{
dvander@2171
   181
				*index = mid;
dvander@2171
   182
			}
dvander@2171
   183
			return SP_ERROR_NONE;
dvander@2171
   184
		} else if (diff < 0) {
dvander@2171
   185
			low = mid + 1;
dvander@2171
   186
		} else {
dvander@2171
   187
			high = mid - 1;
dvander@2171
   188
		}
dvander@2171
   189
	}
dvander@2171
   190
dvander@2171
   191
	return SP_ERROR_NOT_FOUND;
dvander@2171
   192
}
dvander@2171
   193
dvander@2171
   194
int BaseRuntime::GetPubvarAddrs(uint32_t index, cell_t *local_addr, cell_t **phys_addr)
dvander@2171
   195
{
dvander@2171
   196
	if (index >= m_pPlugin->info.pubvars_num)
dvander@2171
   197
	{
dvander@2171
   198
		return SP_ERROR_INDEX;
dvander@2171
   199
	}
dvander@2171
   200
dvander@2171
   201
	*local_addr = m_pPlugin->info.pubvars[index].address;
dvander@2171
   202
	*phys_addr = m_pPlugin->pubvars[index].offs;
dvander@2171
   203
dvander@2171
   204
	return SP_ERROR_NONE;
dvander@2171
   205
}
dvander@2171
   206
dvander@2171
   207
uint32_t BaseRuntime::GetPubVarsNum()
dvander@2171
   208
{
dvander@2171
   209
	return m_pPlugin->info.pubvars_num;
dvander@2171
   210
}
dvander@2171
   211
dvander@2171
   212
IPluginContext *BaseRuntime::GetDefaultContext()
dvander@2171
   213
{
dvander@2171
   214
	return m_pCtx;
dvander@2171
   215
}
dvander@2171
   216
dvander@2171
   217
IPluginDebugInfo *BaseRuntime::GetDebugInfo()
dvander@2171
   218
{
dvander@2171
   219
	if (!IsDebugging())
dvander@2171
   220
	{
dvander@2171
   221
		return NULL;
dvander@2171
   222
	}
dvander@2171
   223
dvander@2171
   224
	return &m_Debug;
dvander@2171
   225
}
dvander@2171
   226
dvander@2171
   227
void BaseRuntime::RefreshFunctionCache()
dvander@2171
   228
{
dvander@2171
   229
	if (m_PubFuncs != NULL)
dvander@2171
   230
	{
dvander@2171
   231
		sp_public_t *pub;
dvander@2171
   232
		for (uint32_t i = 0; i < m_pPlugin->info.publics_num; i++)
dvander@2171
   233
		{
dvander@2171
   234
			if (m_PubFuncs[i] == NULL)
dvander@2171
   235
			{
dvander@2171
   236
				continue;
dvander@2171
   237
			}
dvander@2171
   238
			if (GetPublicByIndex(i, &pub) != SP_ERROR_NONE)
dvander@2171
   239
			{
dvander@2171
   240
				continue;
dvander@2171
   241
			}
dvander@2171
   242
			m_PubFuncs[i]->Set(pub->code_offs, this, pub->funcid, i);
dvander@2171
   243
		}
dvander@2171
   244
	}
dvander@2171
   245
dvander@2171
   246
}
dvander@2171
   247
dvander@2171
   248
IPluginFunction *BaseRuntime::GetFunctionById(funcid_t func_id)
dvander@2171
   249
{
dvander@2171
   250
	CFunction *pFunc = NULL;
dvander@2171
   251
dvander@2171
   252
	if (func_id & 1)
dvander@2171
   253
	{
dvander@2171
   254
		func_id >>= 1;
dvander@2171
   255
		if (func_id >= m_pPlugin->info.publics_num)
dvander@2171
   256
		{
dvander@2171
   257
			return NULL;
dvander@2171
   258
		}
dvander@2171
   259
		pFunc = m_PubFuncs[func_id];
dvander@2171
   260
		if (!pFunc)
dvander@2171
   261
		{
dvander@2171
   262
			m_PubFuncs[func_id] = new CFunction(m_pPlugin->publics[func_id].code_offs, 
dvander@2171
   263
				this, 
dvander@2171
   264
				m_pPlugin->publics[func_id].funcid,
dvander@2171
   265
				func_id);
dvander@2171
   266
			pFunc = m_PubFuncs[func_id];
dvander@2171
   267
		}
dvander@2171
   268
		else if (pFunc->IsInvalidated())
dvander@2171
   269
		{
dvander@2171
   270
			pFunc->Set(m_pPlugin->publics[func_id].code_offs, 
dvander@2171
   271
				this,
dvander@2171
   272
				m_pPlugin->publics[func_id].funcid,
dvander@2171
   273
				func_id);
dvander@2171
   274
		}
dvander@2171
   275
	}
dvander@2171
   276
dvander@2171
   277
	return pFunc;
dvander@2171
   278
}
dvander@2171
   279
dvander@2171
   280
IPluginFunction *BaseRuntime::GetFunctionByName(const char *public_name)
dvander@2171
   281
{
dvander@2171
   282
	uint32_t index;
dvander@2171
   283
dvander@2171
   284
	if (FindPublicByName(public_name, &index) != SP_ERROR_NONE)
dvander@2171
   285
	{
dvander@2171
   286
		return NULL;
dvander@2171
   287
	}
dvander@2171
   288
dvander@2171
   289
	CFunction *pFunc = m_PubFuncs[index];
dvander@2171
   290
	if (!pFunc)
dvander@2171
   291
	{
dvander@2171
   292
		sp_public_t *pub = NULL;
dvander@2171
   293
		GetPublicByIndex(index, &pub);
dvander@2171
   294
		if (pub)
dvander@2171
   295
		{
dvander@2171
   296
			m_PubFuncs[index] = new CFunction(pub->code_offs, this, pub->funcid, index);
dvander@2171
   297
		}
dvander@2171
   298
		pFunc = m_PubFuncs[index];
dvander@2171
   299
	}
dvander@2171
   300
	else if (pFunc->IsInvalidated())
dvander@2171
   301
	{
dvander@2171
   302
		sp_public_t *pub = NULL;
dvander@2171
   303
		GetPublicByIndex(index, &pub);
dvander@2171
   304
		if (pub)
dvander@2171
   305
		{
dvander@2171
   306
			pFunc->Set(pub->code_offs, this, pub->funcid, index);
dvander@2171
   307
		}
dvander@2171
   308
		else
dvander@2171
   309
		{
dvander@2171
   310
			pFunc = NULL;
dvander@2171
   311
		}
dvander@2171
   312
	}
dvander@2171
   313
dvander@2171
   314
	return pFunc;
dvander@2171
   315
}
dvander@2171
   316
dvander@2171
   317
bool BaseRuntime::IsDebugging()
dvander@2171
   318
{
dvander@2171
   319
	return ((m_pPlugin->run_flags & SPFLAG_PLUGIN_DEBUG) == SPFLAG_PLUGIN_DEBUG);
dvander@2171
   320
}
dvander@2171
   321
dvander@2171
   322
void BaseRuntime::SetPauseState(bool paused)
dvander@2171
   323
{
dvander@2171
   324
	if (paused)
dvander@2171
   325
	{
dvander@2171
   326
		m_pPlugin->run_flags |= SPFLAG_PLUGIN_PAUSED;
dvander@2171
   327
	}
dvander@2171
   328
	else
dvander@2171
   329
	{
dvander@2171
   330
		m_pPlugin->run_flags &= ~SPFLAG_PLUGIN_PAUSED;
dvander@2171
   331
	}
dvander@2171
   332
}
dvander@2171
   333
dvander@2171
   334
bool BaseRuntime::IsPaused()
dvander@2171
   335
{
dvander@2171
   336
	return ((m_pPlugin->run_flags & SPFLAG_PLUGIN_PAUSED) == SPFLAG_PLUGIN_PAUSED);
dvander@2171
   337
}
dvander@2174
   338
dvander@2174
   339
size_t BaseRuntime::GetMemUsage()
dvander@2174
   340
{
dvander@2174
   341
	size_t mem = 0;
dvander@2174
   342
dvander@2174
   343
	mem += sizeof(this);
dvander@2174
   344
	mem += sizeof(sp_plugin_t);
dvander@2174
   345
	mem += sizeof(BaseContext);
dvander@2174
   346
	mem += m_pPlugin->base_size;
dvander@2174
   347
	mem += m_pPlugin->jit_codesize;
dvander@2174
   348
	mem += m_pPlugin->jit_memsize;
dvander@2174
   349
dvander@2174
   350
	return mem;
dvander@2174
   351
}