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