|
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@2193
|
50 |
delete m_pPlugin; |
|
dvander@2193
|
51 |
} |
|
dvander@2193
|
52 |
|
|
dvander@2193
|
53 |
void BaseRuntime::ClearCompile() |
|
dvander@2193
|
54 |
{ |
|
dvander@2193
|
55 |
g_Jit1.FreeContextVars(m_pCtx->GetCtx()); |
|
dvander@2193
|
56 |
g_Jit1.FreePluginVars(m_pPlugin); |
|
dvander@2193
|
57 |
} |
|
dvander@2193
|
58 |
|
|
dvander@2193
|
59 |
int BaseRuntime::FindNativeByName(const char *name, uint32_t *index) |
|
dvander@2193
|
60 |
{ |
|
dvander@2193
|
61 |
int high; |
|
dvander@2193
|
62 |
|
|
dvander@2193
|
63 |
high = m_pPlugin->info.natives_num - 1; |
|
dvander@2193
|
64 |
|
|
dvander@2193
|
65 |
for (uint32_t i=0; i<m_pPlugin->info.natives_num; i++) |
|
dvander@2193
|
66 |
{ |
|
dvander@2193
|
67 |
if (strcmp(m_pPlugin->natives[i].name, name) == 0) |
|
dvander@2193
|
68 |
{ |
|
dvander@2193
|
69 |
if (index) |
|
dvander@2193
|
70 |
{ |
|
dvander@2193
|
71 |
*index = i; |
|
dvander@2193
|
72 |
} |
|
dvander@2193
|
73 |
return SP_ERROR_NONE; |
|
dvander@2193
|
74 |
} |
|
dvander@2193
|
75 |
} |
|
dvander@2193
|
76 |
|
|
dvander@2193
|
77 |
return SP_ERROR_NOT_FOUND; |
|
dvander@2193
|
78 |
} |
|
dvander@2193
|
79 |
|
|
dvander@2193
|
80 |
int BaseRuntime::GetNativeByIndex(uint32_t index, sp_native_t **native) |
|
dvander@2193
|
81 |
{ |
|
dvander@2193
|
82 |
if (index >= m_pPlugin->info.natives_num) |
|
dvander@2193
|
83 |
{ |
|
dvander@2193
|
84 |
return SP_ERROR_INDEX; |
|
dvander@2193
|
85 |
} |
|
dvander@2193
|
86 |
|
|
dvander@2193
|
87 |
if (native) |
|
dvander@2193
|
88 |
{ |
|
dvander@2193
|
89 |
*native = &(m_pPlugin->natives[index]); |
|
dvander@2193
|
90 |
} |
|
dvander@2193
|
91 |
|
|
dvander@2193
|
92 |
return SP_ERROR_NONE; |
|
dvander@2193
|
93 |
} |
|
dvander@2193
|
94 |
|
|
dvander@2193
|
95 |
|
|
dvander@2193
|
96 |
uint32_t BaseRuntime::GetNativesNum() |
|
dvander@2193
|
97 |
{ |
|
dvander@2193
|
98 |
return m_pPlugin->info.natives_num; |
|
dvander@2193
|
99 |
} |
|
dvander@2193
|
100 |
|
|
dvander@2193
|
101 |
int BaseRuntime::FindPublicByName(const char *name, uint32_t *index) |
|
dvander@2193
|
102 |
{ |
|
dvander@2193
|
103 |
int diff, high, low; |
|
dvander@2193
|
104 |
uint32_t mid; |
|
dvander@2193
|
105 |
|
|
dvander@2193
|
106 |
high = m_pPlugin->info.publics_num - 1; |
|
dvander@2193
|
107 |
low = 0; |
|
dvander@2193
|
108 |
|
|
dvander@2193
|
109 |
while (low <= high) |
|
dvander@2193
|
110 |
{ |
|
dvander@2193
|
111 |
mid = (low + high) / 2; |
|
dvander@2193
|
112 |
diff = strcmp(m_pPlugin->publics[mid].name, name); |
|
dvander@2193
|
113 |
if (diff == 0) |
|
dvander@2193
|
114 |
{ |
|
dvander@2193
|
115 |
if (index) |
|
dvander@2193
|
116 |
{ |
|
dvander@2193
|
117 |
*index = mid; |
|
dvander@2193
|
118 |
} |
|
dvander@2193
|
119 |
return SP_ERROR_NONE; |
|
dvander@2193
|
120 |
} else if (diff < 0) { |
|
dvander@2193
|
121 |
low = mid + 1; |
|
dvander@2193
|
122 |
} else { |
|
dvander@2193
|
123 |
high = mid - 1; |
|
dvander@2193
|
124 |
} |
|
dvander@2193
|
125 |
} |
|
dvander@2193
|
126 |
|
|
dvander@2193
|
127 |
return SP_ERROR_NOT_FOUND; |
|
dvander@2193
|
128 |
} |
|
dvander@2193
|
129 |
|
|
dvander@2193
|
130 |
int BaseRuntime::GetPublicByIndex(uint32_t index, sp_public_t **pblic) |
|
dvander@2193
|
131 |
{ |
|
dvander@2193
|
132 |
if (index >= m_pPlugin->info.publics_num) |
|
dvander@2193
|
133 |
{ |
|
dvander@2193
|
134 |
return SP_ERROR_INDEX; |
|
dvander@2193
|
135 |
} |
|
dvander@2193
|
136 |
|
|
dvander@2193
|
137 |
if (pblic) |
|
dvander@2193
|
138 |
{ |
|
dvander@2193
|
139 |
*pblic = &(m_pPlugin->publics[index]); |
|
dvander@2193
|
140 |
} |
|
dvander@2193
|
141 |
|
|
dvander@2193
|
142 |
return SP_ERROR_NONE; |
|
dvander@2193
|
143 |
} |
|
dvander@2193
|
144 |
|
|
dvander@2193
|
145 |
uint32_t BaseRuntime::GetPublicsNum() |
|
dvander@2193
|
146 |
{ |
|
dvander@2193
|
147 |
return m_pPlugin->info.publics_num; |
|
dvander@2193
|
148 |
} |
|
dvander@2193
|
149 |
|
|
dvander@2193
|
150 |
int BaseRuntime::GetPubvarByIndex(uint32_t index, sp_pubvar_t **pubvar) |
|
dvander@2193
|
151 |
{ |
|
dvander@2193
|
152 |
if (index >= m_pPlugin->info.pubvars_num) |
|
dvander@2193
|
153 |
{ |
|
dvander@2193
|
154 |
return SP_ERROR_INDEX; |
|
dvander@2193
|
155 |
} |
|
dvander@2193
|
156 |
|
|
dvander@2193
|
157 |
if (pubvar) |
|
dvander@2193
|
158 |
{ |
|
dvander@2193
|
159 |
*pubvar = &(m_pPlugin->pubvars[index]); |
|
dvander@2193
|
160 |
} |
|
dvander@2193
|
161 |
|
|
dvander@2193
|
162 |
return SP_ERROR_NONE; |
|
dvander@2193
|
163 |
} |
|
dvander@2193
|
164 |
|
|
dvander@2193
|
165 |
int BaseRuntime::FindPubvarByName(const char *name, uint32_t *index) |
|
dvander@2193
|
166 |
{ |
|
dvander@2193
|
167 |
int diff, high, low; |
|
dvander@2193
|
168 |
uint32_t mid; |
|
dvander@2193
|
169 |
|
|
dvander@2193
|
170 |
high = m_pPlugin->info.pubvars_num - 1; |
|
dvander@2193
|
171 |
low = 0; |
|
dvander@2193
|
172 |
|
|
dvander@2193
|
173 |
while (low <= high) |
|
dvander@2193
|
174 |
{ |
|
dvander@2193
|
175 |
mid = (low + high) / 2; |
|
dvander@2193
|
176 |
diff = strcmp(m_pPlugin->pubvars[mid].name, name); |
|
dvander@2193
|
177 |
if (diff == 0) |
|
dvander@2193
|
178 |
{ |
|
dvander@2193
|
179 |
if (index) |
|
dvander@2193
|
180 |
{ |
|
dvander@2193
|
181 |
*index = mid; |
|
dvander@2193
|
182 |
} |
|
dvander@2193
|
183 |
return SP_ERROR_NONE; |
|
dvander@2193
|
184 |
} else if (diff < 0) { |
|
dvander@2193
|
185 |
low = mid + 1; |
|
dvander@2193
|
186 |
} else { |
|
dvander@2193
|
187 |
high = mid - 1; |
|
dvander@2193
|
188 |
} |
|
dvander@2193
|
189 |
} |
|
dvander@2193
|
190 |
|
|
dvander@2193
|
191 |
return SP_ERROR_NOT_FOUND; |
|
dvander@2193
|
192 |
} |
|
dvander@2193
|
193 |
|
|
dvander@2193
|
194 |
int BaseRuntime::GetPubvarAddrs(uint32_t index, cell_t *local_addr, cell_t **phys_addr) |
|
dvander@2193
|
195 |
{ |
|
dvander@2193
|
196 |
if (index >= m_pPlugin->info.pubvars_num) |
|
dvander@2193
|
197 |
{ |
|
dvander@2193
|
198 |
return SP_ERROR_INDEX; |
|
dvander@2193
|
199 |
} |
|
dvander@2193
|
200 |
|
|
dvander@2193
|
201 |
*local_addr = m_pPlugin->info.pubvars[index].address; |
|
dvander@2193
|
202 |
*phys_addr = m_pPlugin->pubvars[index].offs; |
|
dvander@2193
|
203 |
|
|
dvander@2193
|
204 |
return SP_ERROR_NONE; |
|
dvander@2193
|
205 |
} |
|
dvander@2193
|
206 |
|
|
dvander@2193
|
207 |
uint32_t BaseRuntime::GetPubVarsNum() |
|
dvander@2193
|
208 |
{ |
|
dvander@2193
|
209 |
return m_pPlugin->info.pubvars_num; |
|
dvander@2193
|
210 |
} |
|
dvander@2193
|
211 |
|
|
dvander@2193
|
212 |
IPluginContext *BaseRuntime::GetDefaultContext() |
|
dvander@2193
|
213 |
{ |
|
dvander@2193
|
214 |
return m_pCtx; |
|
dvander@2193
|
215 |
} |
|
dvander@2193
|
216 |
|
|
dvander@2193
|
217 |
IPluginDebugInfo *BaseRuntime::GetDebugInfo() |
|
dvander@2193
|
218 |
{ |
|
dvander@2193
|
219 |
if (!IsDebugging()) |
|
dvander@2193
|
220 |
{ |
|
dvander@2193
|
221 |
return NULL; |
|
dvander@2193
|
222 |
} |
|
dvander@2193
|
223 |
|
|
dvander@2193
|
224 |
return &m_Debug; |
|
dvander@2193
|
225 |
} |
|
dvander@2193
|
226 |
|
|
dvander@2193
|
227 |
void BaseRuntime::RefreshFunctionCache() |
|
dvander@2193
|
228 |
{ |
|
dvander@2193
|
229 |
if (m_PubFuncs != NULL) |
|
dvander@2193
|
230 |
{ |
|
dvander@2193
|
231 |
sp_public_t *pub; |
|
dvander@2193
|
232 |
for (uint32_t i = 0; i < m_pPlugin->info.publics_num; i++) |
|
dvander@2193
|
233 |
{ |
|
dvander@2193
|
234 |
if (m_PubFuncs[i] == NULL) |
|
dvander@2193
|
235 |
{ |
|
dvander@2193
|
236 |
continue; |
|
dvander@2193
|
237 |
} |
|
dvander@2193
|
238 |
if (GetPublicByIndex(i, &pub) != SP_ERROR_NONE) |
|
dvander@2193
|
239 |
{ |
|
dvander@2193
|
240 |
continue; |
|
dvander@2193
|
241 |
} |
|
dvander@2193
|
242 |
m_PubFuncs[i]->Set(pub->code_offs, this, (i << 1) | 1, i); |
|
dvander@2193
|
243 |
} |
|
dvander@2193
|
244 |
} |
|
dvander@2193
|
245 |
|
|
dvander@2193
|
246 |
} |
|
dvander@2193
|
247 |
|
|
dvander@2193
|
248 |
IPluginFunction *BaseRuntime::GetFunctionById(funcid_t func_id) |
|
dvander@2193
|
249 |
{ |
|
dvander@2193
|
250 |
CFunction *pFunc = NULL; |
|
dvander@2193
|
251 |
|
|
dvander@2193
|
252 |
if (func_id & 1) |
|
dvander@2193
|
253 |
{ |
|
dvander@2193
|
254 |
func_id >>= 1; |
|
dvander@2193
|
255 |
if (func_id >= m_pPlugin->info.publics_num) |
|
dvander@2193
|
256 |
{ |
|
dvander@2193
|
257 |
return NULL; |
|
dvander@2193
|
258 |
} |
|
dvander@2193
|
259 |
pFunc = m_PubFuncs[func_id]; |
|
dvander@2193
|
260 |
if (!pFunc) |
|
dvander@2193
|
261 |
{ |
|
dvander@2193
|
262 |
m_PubFuncs[func_id] = new CFunction(m_pPlugin->publics[func_id].code_offs, |
|
dvander@2193
|
263 |
this, |
|
dvander@2193
|
264 |
(func_id << 1) | 1, |
|
dvander@2193
|
265 |
func_id); |
|
dvander@2193
|
266 |
pFunc = m_PubFuncs[func_id]; |
|
dvander@2193
|
267 |
} |
|
dvander@2193
|
268 |
else if (pFunc->IsInvalidated()) |
|
dvander@2193
|
269 |
{ |
|
dvander@2193
|
270 |
pFunc->Set(m_pPlugin->publics[func_id].code_offs, |
|
dvander@2193
|
271 |
this, |
|
dvander@2193
|
272 |
(func_id << 1) | 1, |
|
dvander@2193
|
273 |
func_id); |
|
dvander@2193
|
274 |
} |
|
dvander@2193
|
275 |
} |
|
dvander@2193
|
276 |
|
|
dvander@2193
|
277 |
return pFunc; |
|
dvander@2193
|
278 |
} |
|
dvander@2193
|
279 |
|
|
dvander@2193
|
280 |
IPluginFunction *BaseRuntime::GetFunctionByName(const char *public_name) |
|
dvander@2193
|
281 |
{ |
|
dvander@2193
|
282 |
uint32_t index; |
|
dvander@2193
|
283 |
|
|
dvander@2193
|
284 |
if (FindPublicByName(public_name, &index) != SP_ERROR_NONE) |
|
dvander@2193
|
285 |
{ |
|
dvander@2193
|
286 |
return NULL; |
|
dvander@2193
|
287 |
} |
|
dvander@2193
|
288 |
|
|
dvander@2193
|
289 |
CFunction *pFunc = m_PubFuncs[index]; |
|
dvander@2193
|
290 |
if (!pFunc) |
|
dvander@2193
|
291 |
{ |
|
dvander@2193
|
292 |
sp_public_t *pub = NULL; |
|
dvander@2193
|
293 |
GetPublicByIndex(index, &pub); |
|
dvander@2193
|
294 |
if (pub) |
|
dvander@2193
|
295 |
{ |
|
dvander@2193
|
296 |
m_PubFuncs[index] = new CFunction(pub->code_offs, this, (index << 1) | 1, index); |
|
dvander@2193
|
297 |
} |
|
dvander@2193
|
298 |
pFunc = m_PubFuncs[index]; |
|
dvander@2193
|
299 |
} |
|
dvander@2193
|
300 |
else if (pFunc->IsInvalidated()) |
|
dvander@2193
|
301 |
{ |
|
dvander@2193
|
302 |
sp_public_t *pub = NULL; |
|
dvander@2193
|
303 |
GetPublicByIndex(index, &pub); |
|
dvander@2193
|
304 |
if (pub) |
|
dvander@2193
|
305 |
{ |
|
dvander@2193
|
306 |
pFunc->Set(pub->code_offs, this, (index << 1) | 1, index); |
|
dvander@2193
|
307 |
} |
|
dvander@2193
|
308 |
else |
|
dvander@2193
|
309 |
{ |
|
dvander@2193
|
310 |
pFunc = NULL; |
|
dvander@2193
|
311 |
} |
|
dvander@2193
|
312 |
} |
|
dvander@2193
|
313 |
|
|
dvander@2193
|
314 |
return pFunc; |
|
dvander@2193
|
315 |
} |
|
dvander@2193
|
316 |
|
|
dvander@2193
|
317 |
bool BaseRuntime::IsDebugging() |
|
dvander@2193
|
318 |
{ |
|
dvander@2193
|
319 |
return ((m_pPlugin->run_flags & SPFLAG_PLUGIN_DEBUG) == SPFLAG_PLUGIN_DEBUG); |
|
dvander@2193
|
320 |
} |
|
dvander@2193
|
321 |
|
|
dvander@2193
|
322 |
void BaseRuntime::SetPauseState(bool paused) |
|
dvander@2193
|
323 |
{ |
|
dvander@2193
|
324 |
if (paused) |
|
dvander@2193
|
325 |
{ |
|
dvander@2193
|
326 |
m_pPlugin->run_flags |= SPFLAG_PLUGIN_PAUSED; |
|
dvander@2193
|
327 |
} |
|
dvander@2193
|
328 |
else |
|
dvander@2193
|
329 |
{ |
|
dvander@2193
|
330 |
m_pPlugin->run_flags &= ~SPFLAG_PLUGIN_PAUSED; |
|
dvander@2193
|
331 |
} |
|
dvander@2193
|
332 |
} |
|
dvander@2193
|
333 |
|
|
dvander@2193
|
334 |
bool BaseRuntime::IsPaused() |
|
dvander@2193
|
335 |
{ |
|
dvander@2193
|
336 |
return ((m_pPlugin->run_flags & SPFLAG_PLUGIN_PAUSED) == SPFLAG_PLUGIN_PAUSED); |
|
dvander@2193
|
337 |
} |
|
dvander@2193
|
338 |
|
|
dvander@2193
|
339 |
size_t BaseRuntime::GetMemUsage() |
|
dvander@2193
|
340 |
{ |
|
dvander@2193
|
341 |
size_t mem = 0; |
|
dvander@2193
|
342 |
|
|
dvander@2193
|
343 |
mem += sizeof(this); |
|
dvander@2193
|
344 |
mem += sizeof(sp_plugin_t); |
|
dvander@2193
|
345 |
mem += sizeof(BaseContext); |
|
dvander@2193
|
346 |
mem += m_pPlugin->base_size; |
|
dvander@2193
|
347 |
mem += m_pPlugin->jit_codesize; |
|
dvander@2193
|
348 |
mem += m_pPlugin->jit_memsize; |
|
dvander@2193
|
349 |
|
|
dvander@2193
|
350 |
return mem; |
|
dvander@2193
|
351 |
} |
|
dvander@2193
|
352 |
|
|
dvander@2193
|
353 |
BaseContext *BaseRuntime::GetBaseContext() |
|
dvander@2193
|
354 |
{ |
|
dvander@2193
|
355 |
return m_pCtx; |
|
dvander@2193
|
356 |
} |
|
dvander@2193
|
357 |
|