diff options
author | David Walter Seikel | 2012-01-23 23:36:30 +1000 |
---|---|---|
committer | David Walter Seikel | 2012-01-23 23:36:30 +1000 |
commit | 6523585c66c04cea54df50013df8886b589847d8 (patch) | |
tree | 0b22aee7064166d88595eda260ca2d17c0773da5 /libraries/LuaJIT-1.1.7/src/ljit_core.c | |
parent | Update the EFL to what I'm actually using, coz I'm using some stuff not yet r... (diff) | |
download | SledjHamr-6523585c66c04cea54df50013df8886b589847d8.zip SledjHamr-6523585c66c04cea54df50013df8886b589847d8.tar.gz SledjHamr-6523585c66c04cea54df50013df8886b589847d8.tar.bz2 SledjHamr-6523585c66c04cea54df50013df8886b589847d8.tar.xz |
Add luaproc and LuaJIT libraries.
Two versions of LuaJIT, the stable release, and the dev version. Try the dev version first, until ih fails badly.
Diffstat (limited to 'libraries/LuaJIT-1.1.7/src/ljit_core.c')
-rw-r--r-- | libraries/LuaJIT-1.1.7/src/ljit_core.c | 385 |
1 files changed, 385 insertions, 0 deletions
diff --git a/libraries/LuaJIT-1.1.7/src/ljit_core.c b/libraries/LuaJIT-1.1.7/src/ljit_core.c new file mode 100644 index 0000000..f7385f2 --- /dev/null +++ b/libraries/LuaJIT-1.1.7/src/ljit_core.c | |||
@@ -0,0 +1,385 @@ | |||
1 | /* | ||
2 | ** Interface to JIT engine. | ||
3 | ** Copyright (C) 2005-2011 Mike Pall. See Copyright Notice in luajit.h | ||
4 | */ | ||
5 | |||
6 | #define ljit_core_c | ||
7 | #define LUA_CORE | ||
8 | |||
9 | #include <string.h> | ||
10 | |||
11 | #include "lua.h" | ||
12 | |||
13 | #include "lobject.h" | ||
14 | #include "lstate.h" | ||
15 | #include "ldo.h" | ||
16 | #include "lstring.h" | ||
17 | #include "ltable.h" | ||
18 | #include "ldebug.h" | ||
19 | #include "lopcodes.h" | ||
20 | |||
21 | #include "ljit.h" | ||
22 | #include "ljit_hints.h" | ||
23 | #include "luajit.h" | ||
24 | |||
25 | const char luajit_ident[] = | ||
26 | "$LuaJIT: " LUAJIT_VERSION " " LUAJIT_COPYRIGHT " " LUAJIT_URL " $\n"; | ||
27 | |||
28 | /* ------------------------------------------------------------------------ */ | ||
29 | |||
30 | /* Initialize JIT engine state. */ | ||
31 | void luaJIT_initstate(lua_State *L) | ||
32 | { | ||
33 | jit_State *J = luaM_new(L, jit_State); | ||
34 | G(L)->jit_state = J; | ||
35 | /* Clear JIT engine fields. */ | ||
36 | J->frontwrap = NULL; /* Filled in by ljitlib before enabling the engine. */ | ||
37 | J->flags = 0; /* Disable the JIT engine by default. */ | ||
38 | /* Try to initialize the backend. */ | ||
39 | if (luaJIT_initbackend(L) != JIT_S_OK) | ||
40 | J->flags = JIT_F_INIT_FAILED; | ||
41 | J->L = NULL; /* No compiler thread allocated, yet. */ | ||
42 | } | ||
43 | |||
44 | /* Free JIT engine state. */ | ||
45 | void luaJIT_freestate(lua_State *L) | ||
46 | { | ||
47 | jit_State *J = G(L)->jit_state; | ||
48 | if (J == NULL) return; | ||
49 | luaJIT_freebackend(L); | ||
50 | luaM_free(L, J); | ||
51 | G(L)->jit_state = NULL; | ||
52 | } | ||
53 | |||
54 | /* ------------------------------------------------------------------------ */ | ||
55 | |||
56 | /* Find relative PC (0 based) for a bytecode pointer or a JIT mcode address. */ | ||
57 | int luaJIT_findpc(Proto *pt, const Instruction *savedpc) | ||
58 | { | ||
59 | ptrdiff_t pcdiff = savedpc - pt->code; | ||
60 | if (pcdiff >= 0 && pcdiff <= pt->sizecode) { /* Bytecode pointer? */ | ||
61 | return (int)pcdiff-1; | ||
62 | } else { /* Else translate JIT mcode address to PC. */ | ||
63 | char *addr = (char *)savedpc; | ||
64 | jit_MCTrailer tr; | ||
65 | tr.mcode = (char *)pt->jit_mcode; | ||
66 | tr.sz = pt->jit_szmcode; | ||
67 | /* Follow trailer chain until addr is part of an mcode block. */ | ||
68 | while (!((size_t)(addr - tr.mcode) < tr.sz)) { | ||
69 | memcpy((void *)&tr, JIT_MCTRAILER(tr.mcode, tr.sz), | ||
70 | sizeof(jit_MCTrailer)); | ||
71 | if (tr.mcode == NULL) return -1; /* Not in chain. */ | ||
72 | } | ||
73 | { | ||
74 | jit_Mfm *mfm = JIT_MCMFM(tr.mcode, tr.sz); | ||
75 | int ofs = (int)(addr - tr.mcode); | ||
76 | int isdeopt = !jit_mfm_ismain(mfm); | ||
77 | int pc = 0; /* Prologue fragment is at start of main mfm. */ | ||
78 | while (pc <= pt->sizecode) { | ||
79 | int m = *mfm--; | ||
80 | switch (m) { | ||
81 | default: | ||
82 | if (m & JIT_MFM_MARK) { | ||
83 | m ^= JIT_MFM_MARK; | ||
84 | if (isdeopt) { pc = m; continue; } /* Seek. */ | ||
85 | } | ||
86 | ofs -= m; | ||
87 | if (ofs <= 0) return pc-1; /* Found! */ | ||
88 | case JIT_MFM_COMBINE: | ||
89 | case JIT_MFM_DEAD: | ||
90 | pc++; | ||
91 | break; | ||
92 | case JIT_MFM_STOP: | ||
93 | jit_assert(0); /* Premature STOP found. */ | ||
94 | return -1; | ||
95 | } | ||
96 | } | ||
97 | jit_assert(0); /* Address is in .tail. */ | ||
98 | return -1; | ||
99 | } | ||
100 | } | ||
101 | } | ||
102 | |||
103 | /* Lookup mcode address for PC (1 based) in mfm. */ | ||
104 | static void *jit_mfmlookup(jit_Mfm *mfm, char *addr, int mpc) | ||
105 | { | ||
106 | int isdeopt = !jit_mfm_ismain(mfm); | ||
107 | int pc = 0; /* Prologue fragment is at start of main mfm. */ | ||
108 | while (pc != mpc) { | ||
109 | int m = *mfm--; | ||
110 | switch (m) { | ||
111 | default: | ||
112 | if (m & JIT_MFM_MARK) { | ||
113 | m ^= JIT_MFM_MARK; | ||
114 | if (isdeopt) { pc = m; continue; } /* Seek. */ | ||
115 | } | ||
116 | addr += m; | ||
117 | case JIT_MFM_COMBINE: | ||
118 | case JIT_MFM_DEAD: | ||
119 | pc++; | ||
120 | break; | ||
121 | case JIT_MFM_STOP: | ||
122 | return NULL; | ||
123 | } | ||
124 | } | ||
125 | return (void *)addr; | ||
126 | } | ||
127 | |||
128 | /* Find mcode address for PC (1 based). */ | ||
129 | void *luaJIT_findmcode(Proto *pt, int pc) | ||
130 | { | ||
131 | void *addr = NULL; | ||
132 | jit_Mfm *mfm; | ||
133 | jit_MCTrailer tr; | ||
134 | tr.mcode = (char *)pt->jit_mcode; | ||
135 | tr.sz = pt->jit_szmcode; | ||
136 | mfm = JIT_MCMFM(tr.mcode, tr.sz); | ||
137 | jit_assert(pc >= 1 && pc <= pt->sizecode); | ||
138 | while (mfm[-pc] == JIT_MFM_COMBINE) pc--; | ||
139 | while (mfm[-pc] == JIT_MFM_DEAD) pc++; | ||
140 | jit_assert(pc >= 1 && mfm[-pc] < (JIT_MFM_MARK|JIT_MFM_MAX)); /* Valid? */ | ||
141 | if (jit_mfm_isdeoptpc(mfm, pc)) { /* Deoptimized instruction. */ | ||
142 | do { /* Search through deopt mfm chain. */ | ||
143 | memcpy((void *)&tr, JIT_MCTRAILER(tr.mcode, tr.sz), | ||
144 | sizeof(jit_MCTrailer)); | ||
145 | if (tr.mcode == NULL) break; /* Deopt ins missing in chain. */ | ||
146 | mfm = JIT_MCMFM(tr.mcode, tr.sz); | ||
147 | if (jit_mfm_ismain(mfm)) break; /* Old main mfm stops search, too. */ | ||
148 | addr = jit_mfmlookup(mfm, tr.mcode, pc); | ||
149 | } while (addr == NULL); | ||
150 | } else { /* Not deoptimized. Lookup in main mfm. */ | ||
151 | addr = jit_mfmlookup(mfm, tr.mcode, pc); | ||
152 | } | ||
153 | jit_assert(addr != NULL); /* Corrupt mfm chain. */ | ||
154 | return addr; | ||
155 | } | ||
156 | |||
157 | /* ------------------------------------------------------------------------ */ | ||
158 | |||
159 | /* Compile a prototype. */ | ||
160 | /* Note: func pointer may be invalidated because of stack reallocation. */ | ||
161 | static int jit_compile(lua_State *L, StkId func, Table *st, int force) | ||
162 | { | ||
163 | jit_State *J = G(L)->jit_state; | ||
164 | Closure *cl = clvalue(func); | ||
165 | Proto *pt = cl->l.p; | ||
166 | int status; | ||
167 | |||
168 | /* Check if JIT engine is enabled and prevent recursive invocation. */ | ||
169 | if ((J->flags & JIT_F_INIT_FAILED) || | ||
170 | (!force && !(J->flags & JIT_F_ON)) || | ||
171 | !J->frontwrap) { | ||
172 | status = JIT_S_ENGINE_OFF; | ||
173 | } else if (J->flags & JIT_F_COMPILING) { | ||
174 | status = JIT_S_DELAYED; | ||
175 | } else if (pt->jit_szmcode != 0 && force < 2) { /* Prevent recompile. */ | ||
176 | /* TODO: Allow recompiles? Use case? Extra flag for jit.compile()? */ | ||
177 | status = JIT_S_OK; | ||
178 | } else { | ||
179 | setclvalue(L, luaH_setstr(L, st, luaS_newliteral(L, "func")), cl); | ||
180 | /* Call frontend wrapper. */ | ||
181 | J->flags |= JIT_F_COMPILING; | ||
182 | lua_unlock(L); | ||
183 | status = J->frontwrap(L, st); | ||
184 | lua_lock(L); | ||
185 | J->flags &= ~JIT_F_COMPILING; | ||
186 | } | ||
187 | |||
188 | /* Better sanity check what the frontend returns. */ | ||
189 | if ((status == JIT_S_OK && pt->jit_szmcode == 0) || status == JIT_S_NONE) | ||
190 | status = JIT_S_COMPILER_ERROR; | ||
191 | |||
192 | /* Update closure callgate and prototype status. */ | ||
193 | cl->l.jit_gate = (status == JIT_S_OK) ? (lua_CFunction)pt->jit_mcode : | ||
194 | G(L)->jit_gateJL; | ||
195 | pt->jit_status = status; | ||
196 | return status; | ||
197 | } | ||
198 | |||
199 | /* Create the state table and copy the arguments. */ | ||
200 | static Table *jit_createstate(lua_State *L, StkId arg, int nargs) | ||
201 | { | ||
202 | Table *st = luaH_new(L, nargs, COMSTATE_PREALLOC); | ||
203 | int i; | ||
204 | for (i = 0; i < nargs; i++) | ||
205 | setobj2t(L, luaH_setnum(L, st, i+1), arg+i); | ||
206 | return st; | ||
207 | } | ||
208 | |||
209 | /* ------------------------------------------------------------------------ */ | ||
210 | |||
211 | /* Compile and run a function. To be used by luaD_precall() only. */ | ||
212 | int luaJIT_run(lua_State *L, StkId func, int nresults) | ||
213 | { | ||
214 | ptrdiff_t funcr = savestack(L, func); | ||
215 | Table *st = jit_createstate(L, func+1, L->top-(func+1)); | ||
216 | int status = jit_compile(L, func, st, 0); /* Compile function. */ | ||
217 | func = restorestack(L, funcr); | ||
218 | |||
219 | /* Run the compiled function on success. Fallback to bytecode on failure. */ | ||
220 | if (status == JIT_S_OK) | ||
221 | return G(L)->jit_gateLJ(L, func, nresults); | ||
222 | else | ||
223 | return luaD_precall(L, func, nresults); | ||
224 | /* Note: We are called from luaD_precall and we call it again. */ | ||
225 | /* So jit_compile makes sure pt->jit_status != JIT_S_NONE. */ | ||
226 | } | ||
227 | |||
228 | /* ------------------------------------------------------------------------ */ | ||
229 | |||
230 | /* No more than two ranges for a single deoptimization right now. */ | ||
231 | #define DEOPTRANGE_ALLOC 2 | ||
232 | |||
233 | /* Find PC range of combined instructions and return a range hint. */ | ||
234 | static int combinedrange(jit_Mfm *mfm, int pc) | ||
235 | { | ||
236 | int lastpc = pc; | ||
237 | while (mfm[-pc] == JIT_MFM_COMBINE) pc--; /* 1st comb. ins. */ | ||
238 | while (mfm[-(lastpc+1)] == JIT_MFM_COMBINE) lastpc++; /* Last comb. ins. */ | ||
239 | return JIT_IH_MKIDX(lastpc-pc, pc); /* (#ins-1, pc) in hint format. */ | ||
240 | } | ||
241 | |||
242 | /* Process deoptimization hints for the given PC range. */ | ||
243 | static int deopthints(Proto *pt, jit_Mfm *dh, TValue *dhint, int pcrange) | ||
244 | { | ||
245 | int m; | ||
246 | setnvalue(dhint++, (lua_Number)pcrange); | ||
247 | while ((m = *dh--) != JIT_MFM_STOP) { | ||
248 | if ((unsigned int)(m - JIT_IH_IDX(pcrange)) <= | ||
249 | (unsigned int)JIT_IH_LIB(pcrange)) { | ||
250 | switch (*dh--) { | ||
251 | case JIT_MFM_DEOPT_PAIRS: /* CALL [i]pairs(): deopt TFORLOOP+JMP. */ | ||
252 | if (GET_OPCODE(pt->code[m+1-1]) == OP_JMP) { | ||
253 | int tfpc = m+2 + GETARG_sBx(pt->code[m+1-1]); | ||
254 | if ((unsigned)tfpc < (unsigned)pt->sizecode && | ||
255 | GET_OPCODE(pt->code[tfpc-1]) == OP_TFORLOOP) { | ||
256 | setnvalue(dhint++, (lua_Number)JIT_IH_MKIDX(1, tfpc)); | ||
257 | break; | ||
258 | } | ||
259 | } | ||
260 | return 1; /* Bad hint. */ | ||
261 | default: | ||
262 | return 1; /* Cannot tolerate unknown deoptimization hints. */ | ||
263 | } | ||
264 | } | ||
265 | } | ||
266 | return 0; /* Ok. */ | ||
267 | } | ||
268 | |||
269 | /* Deoptimize the current instruction. Return new mcode addr to continue. */ | ||
270 | void *luaJIT_deoptimize(lua_State *L) | ||
271 | { | ||
272 | StkId func = L->ci->func; | ||
273 | Proto *pt = clvalue(func)->l.p; | ||
274 | int pc = luaJIT_findpc(pt, L->savedpc)+1; /* Get prev. PC (1 based). */ | ||
275 | jit_Mfm *mfm = JIT_MCMFM(pt->jit_mcode, pt->jit_szmcode); | ||
276 | int pcrange = combinedrange(mfm, pc); | ||
277 | if (!jit_mfm_isdeoptpc(mfm, JIT_IH_IDX(pcrange))) { /* Not deopt. yet? */ | ||
278 | Table *st = jit_createstate(L, NULL, 0); /* Don't know original args. */ | ||
279 | Table *deopt = luaH_new(L, DEOPTRANGE_ALLOC, 0); | ||
280 | sethvalue(L, luaH_setstr(L, st, luaS_newliteral(L, "deopt")), deopt); | ||
281 | if (deopthints(pt, mfm-(pt->sizecode+2), deopt->array, pcrange) || | ||
282 | jit_compile(L, func, st, 2) != JIT_S_OK) | ||
283 | luaG_runerror(L, "deoptimization failed"); | ||
284 | } | ||
285 | return luaJIT_findmcode(pt, pc); | ||
286 | } | ||
287 | |||
288 | /* ------------------------------------------------------------------------ */ | ||
289 | |||
290 | /* API function: Compile a Lua function. Pass arguments as hints. */ | ||
291 | LUA_API int luaJIT_compile(lua_State *L, int nargs) | ||
292 | { | ||
293 | StkId func; | ||
294 | Table *st; | ||
295 | int status; | ||
296 | lua_lock(L); | ||
297 | api_check(L, (nargs+1) <= (L->top - L->base)); | ||
298 | func = L->top - (nargs+1); | ||
299 | st = jit_createstate(L, func+1, nargs); | ||
300 | status = isLfunction(func) ? jit_compile(L, func, st, 1) : -1; | ||
301 | lua_unlock(L); | ||
302 | return status; | ||
303 | } | ||
304 | |||
305 | /* Recursively set the mode for all subroutines. */ | ||
306 | static void rec_setmode(Proto *pt, int on) | ||
307 | { | ||
308 | int i; | ||
309 | for (i = 0; i < pt->sizep; i++) { | ||
310 | Proto *pti = pt->p[i]; | ||
311 | pti->jit_status = on ? (pti->jit_szmcode?JIT_S_OK:JIT_S_NONE) : JIT_S_OFF; | ||
312 | rec_setmode(pti, on); /* Recurse into proto. */ | ||
313 | } | ||
314 | } | ||
315 | |||
316 | /* API function: Set the JIT mode for the whole engine or a function+subs. */ | ||
317 | LUA_API int luaJIT_setmode(lua_State *L, int idx, int mode) | ||
318 | { | ||
319 | jit_State *J = G(L)->jit_state; | ||
320 | int mm = mode & LUAJIT_MODE_MASK; | ||
321 | if (J->flags & JIT_F_INIT_FAILED) return -1; /* Init failed. */ | ||
322 | switch (mm) { | ||
323 | case LUAJIT_MODE_ENGINE: /* Set mode for JIT engine. */ | ||
324 | if (mode & LUAJIT_MODE_ON) | ||
325 | J->flags |= JIT_F_ON; | ||
326 | else | ||
327 | J->flags &= ~JIT_F_ON; | ||
328 | break; | ||
329 | case LUAJIT_MODE_DEBUG: { /* Set debug mode. */ | ||
330 | int dbg; | ||
331 | switch (idx) { | ||
332 | case 0: dbg = 0; break; | ||
333 | case 1: dbg = JIT_F_DEBUG_CALL; break; | ||
334 | case 2: default: dbg = JIT_F_DEBUG_CALL | JIT_F_DEBUG_INS; break; | ||
335 | } | ||
336 | J->flags = (J->flags & ~JIT_F_DEBUG) | dbg; | ||
337 | luaJIT_debugnotify(J); | ||
338 | break; | ||
339 | } | ||
340 | case LUAJIT_MODE_FUNC: /* Set mode for function. */ | ||
341 | case LUAJIT_MODE_ALLFUNC: /* Set mode for function + subfuncs. */ | ||
342 | case LUAJIT_MODE_ALLSUBFUNC: { /* Set mode for subfunctions. */ | ||
343 | StkId func; | ||
344 | lua_lock(L); | ||
345 | func = idx == 0 ? (L->ci-1)->func : | ||
346 | (idx > 0 ? L->base + (idx-1) : L->top + idx); | ||
347 | if (isLfunction(func)) { | ||
348 | Closure *cl = clvalue(func); | ||
349 | Proto *pt = cl->l.p; | ||
350 | if (mm != LUAJIT_MODE_ALLSUBFUNC) { | ||
351 | if (mode & LUAJIT_MODE_ON) { | ||
352 | if (pt->jit_szmcode) { /* Already compiled? */ | ||
353 | cl->l.jit_gate = (lua_CFunction)pt->jit_mcode; /* Reenable. */ | ||
354 | pt->jit_status = JIT_S_OK; | ||
355 | } else { | ||
356 | pt->jit_status = JIT_S_NONE; /* (Re-)enable proto compilation */ | ||
357 | } | ||
358 | } else { | ||
359 | cl->l.jit_gate = G(L)->jit_gateJL; /* Default callgate. */ | ||
360 | pt->jit_status = JIT_S_OFF; /* Disable proto compilation. */ | ||
361 | /* Note: compiled code must be retained for suspended threads. */ | ||
362 | } | ||
363 | } | ||
364 | if (mm != LUAJIT_MODE_FUNC) | ||
365 | rec_setmode(pt, mode & LUAJIT_MODE_ON); | ||
366 | lua_unlock(L); | ||
367 | } else { | ||
368 | lua_unlock(L); | ||
369 | return 0; /* Failed. */ | ||
370 | } | ||
371 | break; | ||
372 | } | ||
373 | default: | ||
374 | return 0; /* Failed. */ | ||
375 | } | ||
376 | return 1; /* OK. */ | ||
377 | } | ||
378 | |||
379 | /* Enforce (dynamic) linker error for version mismatches. See lua.c. */ | ||
380 | LUA_API void LUAJIT_VERSION_SYM(void) | ||
381 | { | ||
382 | } | ||
383 | |||
384 | /* ------------------------------------------------------------------------ */ | ||
385 | |||