dvander@2171: #include dvander@2171: #include dvander@2171: #include dvander@2171: #include "BaseRuntime.h" dvander@2171: #include "sp_vm_engine.h" dvander@2171: #include "x86/jit_x86.h" dvander@2171: #include "sp_vm_basecontext.h" dvander@2174: #include "engine2.h" dvander@2171: dvander@2171: using namespace SourcePawn; dvander@2171: dvander@2171: int GlobalDebugBreak(BaseContext *ctx, uint32_t frm, uint32_t cip) dvander@2171: { dvander@2171: g_engine1.RunTracer(ctx, frm, cip); dvander@2171: dvander@2171: return SP_ERROR_NONE; dvander@2171: } dvander@2171: dvander@2171: BaseRuntime::BaseRuntime(sp_plugin_t *pl) : m_Debug(pl), m_pPlugin(pl) dvander@2171: { dvander@2171: m_pCtx = new BaseContext(this); dvander@2171: dvander@2171: if (m_pPlugin->info.publics_num > 0) dvander@2171: { dvander@2171: m_PubFuncs = new CFunction *[m_pPlugin->info.publics_num]; dvander@2171: memset(m_PubFuncs, 0, sizeof(CFunction *) * m_pPlugin->info.publics_num); dvander@2171: } dvander@2171: else dvander@2171: { dvander@2171: m_PubFuncs = NULL; dvander@2171: } dvander@2174: dvander@2174: m_pPlugin->dbreak = GlobalDebugBreak; dvander@2174: m_pPlugin->profiler = g_engine2.GetProfiler(); dvander@2171: } dvander@2171: dvander@2171: BaseRuntime::~BaseRuntime() dvander@2171: { dvander@2171: for (uint32_t i = 0; i < m_pPlugin->info.publics_num; i++) dvander@2171: { dvander@2171: delete m_PubFuncs[i]; dvander@2171: m_PubFuncs[i] = NULL; dvander@2171: } dvander@2171: delete [] m_PubFuncs; dvander@2171: dvander@2171: ClearCompile(); dvander@2171: dvander@2171: free(m_pPlugin->base); dvander@2171: delete [] m_pPlugin->memory; dvander@2171: delete m_pPlugin; dvander@2171: } dvander@2171: dvander@2171: void BaseRuntime::ClearCompile() dvander@2171: { dvander@2190: g_Jit1.FreeContextVars(m_pCtx->GetCtx()); dvander@2171: g_Jit1.FreePluginVars(m_pPlugin); dvander@2171: } dvander@2171: dvander@2171: int BaseRuntime::FindNativeByName(const char *name, uint32_t *index) dvander@2171: { dvander@2171: int high; dvander@2171: dvander@2171: high = m_pPlugin->info.natives_num - 1; dvander@2171: dvander@2171: for (uint32_t i=0; iinfo.natives_num; i++) dvander@2171: { dvander@2171: if (strcmp(m_pPlugin->natives[i].name, name) == 0) dvander@2171: { dvander@2171: if (index) dvander@2171: { dvander@2171: *index = i; dvander@2171: } dvander@2171: return SP_ERROR_NONE; dvander@2171: } dvander@2171: } dvander@2171: dvander@2171: return SP_ERROR_NOT_FOUND; dvander@2171: } dvander@2171: dvander@2171: int BaseRuntime::GetNativeByIndex(uint32_t index, sp_native_t **native) dvander@2171: { dvander@2171: if (index >= m_pPlugin->info.natives_num) dvander@2171: { dvander@2171: return SP_ERROR_INDEX; dvander@2171: } dvander@2171: dvander@2171: if (native) dvander@2171: { dvander@2171: *native = &(m_pPlugin->natives[index]); dvander@2171: } dvander@2171: dvander@2171: return SP_ERROR_NONE; dvander@2171: } dvander@2171: dvander@2171: dvander@2171: uint32_t BaseRuntime::GetNativesNum() dvander@2171: { dvander@2171: return m_pPlugin->info.natives_num; dvander@2171: } dvander@2171: dvander@2171: int BaseRuntime::FindPublicByName(const char *name, uint32_t *index) dvander@2171: { dvander@2171: int diff, high, low; dvander@2171: uint32_t mid; dvander@2171: dvander@2171: high = m_pPlugin->info.publics_num - 1; dvander@2171: low = 0; dvander@2171: dvander@2171: while (low <= high) dvander@2171: { dvander@2171: mid = (low + high) / 2; dvander@2171: diff = strcmp(m_pPlugin->publics[mid].name, name); dvander@2171: if (diff == 0) dvander@2171: { dvander@2171: if (index) dvander@2171: { dvander@2171: *index = mid; dvander@2171: } dvander@2171: return SP_ERROR_NONE; dvander@2171: } else if (diff < 0) { dvander@2171: low = mid + 1; dvander@2171: } else { dvander@2171: high = mid - 1; dvander@2171: } dvander@2171: } dvander@2171: dvander@2171: return SP_ERROR_NOT_FOUND; dvander@2171: } dvander@2171: dvander@2171: int BaseRuntime::GetPublicByIndex(uint32_t index, sp_public_t **pblic) dvander@2171: { dvander@2171: if (index >= m_pPlugin->info.publics_num) dvander@2171: { dvander@2171: return SP_ERROR_INDEX; dvander@2171: } dvander@2171: dvander@2171: if (pblic) dvander@2171: { dvander@2171: *pblic = &(m_pPlugin->publics[index]); dvander@2171: } dvander@2171: dvander@2171: return SP_ERROR_NONE; dvander@2171: } dvander@2171: dvander@2171: uint32_t BaseRuntime::GetPublicsNum() dvander@2171: { dvander@2171: return m_pPlugin->info.publics_num; dvander@2171: } dvander@2171: dvander@2171: int BaseRuntime::GetPubvarByIndex(uint32_t index, sp_pubvar_t **pubvar) dvander@2171: { dvander@2171: if (index >= m_pPlugin->info.pubvars_num) dvander@2171: { dvander@2171: return SP_ERROR_INDEX; dvander@2171: } dvander@2171: dvander@2171: if (pubvar) dvander@2171: { dvander@2171: *pubvar = &(m_pPlugin->pubvars[index]); dvander@2171: } dvander@2171: dvander@2171: return SP_ERROR_NONE; dvander@2171: } dvander@2171: dvander@2171: int BaseRuntime::FindPubvarByName(const char *name, uint32_t *index) dvander@2171: { dvander@2171: int diff, high, low; dvander@2171: uint32_t mid; dvander@2171: dvander@2171: high = m_pPlugin->info.pubvars_num - 1; dvander@2171: low = 0; dvander@2171: dvander@2171: while (low <= high) dvander@2171: { dvander@2171: mid = (low + high) / 2; dvander@2171: diff = strcmp(m_pPlugin->pubvars[mid].name, name); dvander@2171: if (diff == 0) dvander@2171: { dvander@2171: if (index) dvander@2171: { dvander@2171: *index = mid; dvander@2171: } dvander@2171: return SP_ERROR_NONE; dvander@2171: } else if (diff < 0) { dvander@2171: low = mid + 1; dvander@2171: } else { dvander@2171: high = mid - 1; dvander@2171: } dvander@2171: } dvander@2171: dvander@2171: return SP_ERROR_NOT_FOUND; dvander@2171: } dvander@2171: dvander@2171: int BaseRuntime::GetPubvarAddrs(uint32_t index, cell_t *local_addr, cell_t **phys_addr) dvander@2171: { dvander@2171: if (index >= m_pPlugin->info.pubvars_num) dvander@2171: { dvander@2171: return SP_ERROR_INDEX; dvander@2171: } dvander@2171: dvander@2171: *local_addr = m_pPlugin->info.pubvars[index].address; dvander@2171: *phys_addr = m_pPlugin->pubvars[index].offs; dvander@2171: dvander@2171: return SP_ERROR_NONE; dvander@2171: } dvander@2171: dvander@2171: uint32_t BaseRuntime::GetPubVarsNum() dvander@2171: { dvander@2171: return m_pPlugin->info.pubvars_num; dvander@2171: } dvander@2171: dvander@2171: IPluginContext *BaseRuntime::GetDefaultContext() dvander@2171: { dvander@2171: return m_pCtx; dvander@2171: } dvander@2171: dvander@2171: IPluginDebugInfo *BaseRuntime::GetDebugInfo() dvander@2171: { dvander@2171: if (!IsDebugging()) dvander@2171: { dvander@2171: return NULL; dvander@2171: } dvander@2171: dvander@2171: return &m_Debug; dvander@2171: } dvander@2171: dvander@2171: void BaseRuntime::RefreshFunctionCache() dvander@2171: { dvander@2171: if (m_PubFuncs != NULL) dvander@2171: { dvander@2171: sp_public_t *pub; dvander@2171: for (uint32_t i = 0; i < m_pPlugin->info.publics_num; i++) dvander@2171: { dvander@2171: if (m_PubFuncs[i] == NULL) dvander@2171: { dvander@2171: continue; dvander@2171: } dvander@2171: if (GetPublicByIndex(i, &pub) != SP_ERROR_NONE) dvander@2171: { dvander@2171: continue; dvander@2171: } dvander@2188: m_PubFuncs[i]->Set(pub->code_offs, this, (i << 1) | 1, i); dvander@2171: } dvander@2171: } dvander@2171: dvander@2171: } dvander@2171: dvander@2171: IPluginFunction *BaseRuntime::GetFunctionById(funcid_t func_id) dvander@2171: { dvander@2171: CFunction *pFunc = NULL; dvander@2171: dvander@2171: if (func_id & 1) dvander@2171: { dvander@2171: func_id >>= 1; dvander@2171: if (func_id >= m_pPlugin->info.publics_num) dvander@2171: { dvander@2171: return NULL; dvander@2171: } dvander@2171: pFunc = m_PubFuncs[func_id]; dvander@2171: if (!pFunc) dvander@2171: { dvander@2171: m_PubFuncs[func_id] = new CFunction(m_pPlugin->publics[func_id].code_offs, dvander@2171: this, dvander@2188: (func_id << 1) | 1, dvander@2171: func_id); dvander@2171: pFunc = m_PubFuncs[func_id]; dvander@2171: } dvander@2171: else if (pFunc->IsInvalidated()) dvander@2171: { dvander@2171: pFunc->Set(m_pPlugin->publics[func_id].code_offs, dvander@2171: this, dvander@2188: (func_id << 1) | 1, dvander@2171: func_id); dvander@2171: } dvander@2171: } dvander@2171: dvander@2171: return pFunc; dvander@2171: } dvander@2171: dvander@2171: IPluginFunction *BaseRuntime::GetFunctionByName(const char *public_name) dvander@2171: { dvander@2171: uint32_t index; dvander@2171: dvander@2171: if (FindPublicByName(public_name, &index) != SP_ERROR_NONE) dvander@2171: { dvander@2171: return NULL; dvander@2171: } dvander@2171: dvander@2171: CFunction *pFunc = m_PubFuncs[index]; dvander@2171: if (!pFunc) dvander@2171: { dvander@2171: sp_public_t *pub = NULL; dvander@2171: GetPublicByIndex(index, &pub); dvander@2171: if (pub) dvander@2171: { dvander@2188: m_PubFuncs[index] = new CFunction(pub->code_offs, this, (index << 1) | 1, index); dvander@2171: } dvander@2171: pFunc = m_PubFuncs[index]; dvander@2171: } dvander@2171: else if (pFunc->IsInvalidated()) dvander@2171: { dvander@2171: sp_public_t *pub = NULL; dvander@2171: GetPublicByIndex(index, &pub); dvander@2171: if (pub) dvander@2171: { dvander@2188: pFunc->Set(pub->code_offs, this, (index << 1) | 1, index); dvander@2171: } dvander@2171: else dvander@2171: { dvander@2171: pFunc = NULL; dvander@2171: } dvander@2171: } dvander@2171: dvander@2171: return pFunc; dvander@2171: } dvander@2171: dvander@2171: bool BaseRuntime::IsDebugging() dvander@2171: { dvander@2171: return ((m_pPlugin->run_flags & SPFLAG_PLUGIN_DEBUG) == SPFLAG_PLUGIN_DEBUG); dvander@2171: } dvander@2171: dvander@2171: void BaseRuntime::SetPauseState(bool paused) dvander@2171: { dvander@2171: if (paused) dvander@2171: { dvander@2171: m_pPlugin->run_flags |= SPFLAG_PLUGIN_PAUSED; dvander@2171: } dvander@2171: else dvander@2171: { dvander@2171: m_pPlugin->run_flags &= ~SPFLAG_PLUGIN_PAUSED; dvander@2171: } dvander@2171: } dvander@2171: dvander@2171: bool BaseRuntime::IsPaused() dvander@2171: { dvander@2171: return ((m_pPlugin->run_flags & SPFLAG_PLUGIN_PAUSED) == SPFLAG_PLUGIN_PAUSED); dvander@2171: } dvander@2174: dvander@2174: size_t BaseRuntime::GetMemUsage() dvander@2174: { dvander@2174: size_t mem = 0; dvander@2174: dvander@2174: mem += sizeof(this); dvander@2174: mem += sizeof(sp_plugin_t); dvander@2174: mem += sizeof(BaseContext); dvander@2174: mem += m_pPlugin->base_size; dvander@2174: mem += m_pPlugin->jit_codesize; dvander@2174: mem += m_pPlugin->jit_memsize; dvander@2174: dvander@2174: return mem; dvander@2174: } dvander@2190: dvander@2190: BaseContext *BaseRuntime::GetBaseContext() dvander@2190: { dvander@2190: return m_pCtx; dvander@2190: } dvander@2190: