diff options
Diffstat (limited to '')
-rw-r--r-- | libraries/LuaJIT-1.1.7/src/ljit_backend.c | 342 |
1 files changed, 0 insertions, 342 deletions
diff --git a/libraries/LuaJIT-1.1.7/src/ljit_backend.c b/libraries/LuaJIT-1.1.7/src/ljit_backend.c deleted file mode 100644 index 698342f..0000000 --- a/libraries/LuaJIT-1.1.7/src/ljit_backend.c +++ /dev/null | |||
@@ -1,342 +0,0 @@ | |||
1 | /* | ||
2 | ** LuaJIT wrapper for architecture-specific compiler backend. | ||
3 | ** Copyright (C) 2005-2011 Mike Pall. See Copyright Notice in luajit.h | ||
4 | */ | ||
5 | |||
6 | #include <math.h> | ||
7 | #include <string.h> | ||
8 | |||
9 | #define ljit_backend_c | ||
10 | #define LUA_CORE | ||
11 | |||
12 | #include "lua.h" | ||
13 | |||
14 | #include "lobject.h" | ||
15 | #include "lstate.h" | ||
16 | #include "ldo.h" | ||
17 | #include "lfunc.h" | ||
18 | #include "lgc.h" | ||
19 | #include "lstring.h" | ||
20 | #include "ltable.h" | ||
21 | #include "ltm.h" | ||
22 | #include "lvm.h" | ||
23 | #include "lopcodes.h" | ||
24 | #include "ldebug.h" | ||
25 | #include "lzio.h" | ||
26 | |||
27 | #include "ljit.h" | ||
28 | #include "ljit_hints.h" | ||
29 | #include "ljit_dasm.h" | ||
30 | |||
31 | /* ------------------------------------------------------------------------ */ | ||
32 | |||
33 | /* Get target of combined JMP op. */ | ||
34 | static int jit_jmp_target(jit_State *J) | ||
35 | { | ||
36 | J->combine++; | ||
37 | jit_assert(GET_OPCODE(*J->nextins)==OP_JMP); | ||
38 | return J->nextpc + 1 + GETARG_sBx(*J->nextins); | ||
39 | } | ||
40 | |||
41 | /* ------------------------------------------------------------------------ */ | ||
42 | |||
43 | /* Include pre-processed architecture-specific backend. */ | ||
44 | #if defined(__i386) || defined(__i386__) || defined(_M_IX86) | ||
45 | #ifndef LUA_NUMBER_DOUBLE | ||
46 | #error "No support for other number types on x86 (yet)" | ||
47 | #endif | ||
48 | #include "ljit_x86.h" | ||
49 | #else | ||
50 | #error "No support for this architecture (yet)" | ||
51 | #endif | ||
52 | |||
53 | /* ------------------------------------------------------------------------ */ | ||
54 | |||
55 | /* Compile instruction range. */ | ||
56 | static void jit_compile_irange(jit_State *J, int firstpc, int lastpc) | ||
57 | { | ||
58 | J->combine = 0; | ||
59 | J->nextpc = firstpc; | ||
60 | J->nextins = J->pt->code + (firstpc-1); | ||
61 | while (J->nextpc <= lastpc) { | ||
62 | Instruction ins = *J->nextins++; | ||
63 | OpCode op = GET_OPCODE(ins); | ||
64 | int ra = GETARG_A(ins); | ||
65 | int rb = GETARG_B(ins); | ||
66 | int rc = GETARG_C(ins); | ||
67 | int rbx = GETARG_Bx(ins); | ||
68 | const TValue *combinehint; | ||
69 | |||
70 | jit_ins_start(J); | ||
71 | J->nextpc++; | ||
72 | |||
73 | combinehint = hint_get(J, COMBINE); | ||
74 | if (ttisboolean(combinehint)) { | ||
75 | if (bvalue(combinehint)) { /* COMBINE = true: combine with next ins. */ | ||
76 | if (!(J->flags & JIT_F_DEBUG)) /* But not when debugging. */ | ||
77 | J->combine = 1; | ||
78 | } else { /* COMBINE = false: dead instruction. */ | ||
79 | *J->mfm++ = JIT_MFM_DEAD; | ||
80 | continue; | ||
81 | } | ||
82 | } /* Other COMBINE hint value types are not defined (yet). */ | ||
83 | |||
84 | if (J->flags & JIT_F_DEBUG_INS) | ||
85 | jit_ins_debug(J, luaG_checkopenop(ins)); | ||
86 | |||
87 | switch (op) { | ||
88 | case OP_MOVE: jit_op_move(J, ra, rb); break; | ||
89 | case OP_LOADK: jit_op_loadk(J, ra, rbx); break; | ||
90 | case OP_LOADBOOL: jit_op_loadbool(J, ra, rb, rc); break; | ||
91 | case OP_LOADNIL: jit_op_loadnil(J, ra, rb); break; | ||
92 | |||
93 | case OP_GETUPVAL: jit_op_getupval(J, ra, rb); break; | ||
94 | case OP_SETUPVAL: jit_op_setupval(J, ra, rb); break; | ||
95 | |||
96 | case OP_GETGLOBAL: jit_op_getglobal(J, ra, rbx); break; | ||
97 | case OP_SETGLOBAL: jit_op_setglobal(J, ra, rbx); break; | ||
98 | |||
99 | case OP_NEWTABLE: jit_op_newtable(J, ra, rb, rc); break; | ||
100 | case OP_GETTABLE: jit_op_gettable(J, ra, rb, rc); break; | ||
101 | case OP_SETTABLE: jit_op_settable(J, ra, rb, rc); break; | ||
102 | case OP_SELF: jit_op_self(J, ra, rb, rc); break; | ||
103 | case OP_SETLIST: jit_op_setlist(J, ra, rb, rc); break; | ||
104 | |||
105 | case OP_ADD: jit_op_arith(J, ra, rb, rc, TM_ADD); break; | ||
106 | case OP_SUB: jit_op_arith(J, ra, rb, rc, TM_SUB); break; | ||
107 | case OP_MUL: jit_op_arith(J, ra, rb, rc, TM_MUL); break; | ||
108 | case OP_DIV: jit_op_arith(J, ra, rb, rc, TM_DIV); break; | ||
109 | case OP_MOD: jit_op_arith(J, ra, rb, rc, TM_MOD); break; | ||
110 | case OP_POW: jit_op_arith(J, ra, rb, rc, TM_POW); break; | ||
111 | case OP_UNM: jit_op_arith(J, ra, rb, rb, TM_UNM); break; /* rc unused. */ | ||
112 | |||
113 | case OP_LEN: jit_op_len(J, ra, rb); break; | ||
114 | case OP_NOT: jit_op_not(J, ra, rb); break; | ||
115 | |||
116 | case OP_CONCAT: jit_op_concat(J, ra, rb, rc); break; | ||
117 | |||
118 | case OP_EQ: jit_op_eq(J, ra, rb, rc); break; | ||
119 | case OP_LT: jit_op_arith(J, ra, rb, rc, TM_LT); break; | ||
120 | case OP_LE: jit_op_arith(J, ra, rb, rc, TM_LE); break; | ||
121 | |||
122 | case OP_TEST: jit_op_test(J, rc, ra, ra); break; | ||
123 | case OP_TESTSET: jit_op_test(J, rc, ra, rb); break; | ||
124 | |||
125 | case OP_JMP: jit_op_jmp(J, J->nextpc + rbx-MAXARG_sBx); break; | ||
126 | |||
127 | case OP_CALL: jit_op_call(J, ra, rb-1, rc-1); break; | ||
128 | case OP_TAILCALL: jit_op_tailcall(J, ra, rb-1); break; | ||
129 | case OP_RETURN: jit_op_return(J, ra, rb-1); break; | ||
130 | |||
131 | case OP_FORLOOP: jit_op_forloop(J, ra, J->nextpc + rbx-MAXARG_sBx); break; | ||
132 | case OP_FORPREP: jit_op_forprep(J, ra, J->nextpc + rbx-MAXARG_sBx); break; | ||
133 | |||
134 | case OP_TFORLOOP: jit_op_tforloop(J, ra, rc); break; | ||
135 | |||
136 | case OP_CLOSE: jit_op_close(J, ra); break; | ||
137 | case OP_CLOSURE: jit_op_closure(J, ra, rbx); break; | ||
138 | |||
139 | case OP_VARARG: jit_op_vararg(J, ra, rb-1); break; | ||
140 | |||
141 | default: jit_assert(0); break; | ||
142 | } | ||
143 | |||
144 | /* Convention: all opcodes start and end with the .code section. */ | ||
145 | if (dasm_checkstep(Dst, DASM_SECTION_CODE)) { J->nextpc--; return; } | ||
146 | |||
147 | *J->mfm++ = 0; /* Placeholder mfm entry. Replaced later. */ | ||
148 | if (J->combine > 0) { /* Combine next J->combine ins with prev ins. */ | ||
149 | J->nextpc += J->combine; | ||
150 | J->nextins += J->combine; | ||
151 | do { *J->mfm++ = JIT_MFM_COMBINE; } while (--J->combine); | ||
152 | } | ||
153 | } | ||
154 | } | ||
155 | |||
156 | /* Merge temporary mfm (forward) with PC labels to inverse mfm in mcode. */ | ||
157 | static void jit_mfm_merge(jit_State *J, jit_Mfm *from, jit_Mfm *to, int maxpc) | ||
158 | { | ||
159 | int pc = 1, ofs = 0; | ||
160 | for (;;) { | ||
161 | int m = *from++; | ||
162 | if (m & JIT_MFM_MARK) { | ||
163 | switch (m) { | ||
164 | default: pc = m ^ JIT_MFM_MARK; break; | ||
165 | case JIT_MFM_COMBINE: case JIT_MFM_DEAD: break; | ||
166 | case JIT_MFM_STOP: return; | ||
167 | } | ||
168 | } else { | ||
169 | int idx, nofs; | ||
170 | for (idx = 0; from[idx] == JIT_MFM_COMBINE; idx++) ; | ||
171 | idx += pc; | ||
172 | if (idx == J->nextpc) idx = maxpc + 1; | ||
173 | nofs = dasm_getpclabel(Dst, idx); | ||
174 | m = nofs - ofs; | ||
175 | ofs = nofs; | ||
176 | jit_assert(nofs >= 0 && m >= 0 && m < JIT_MFM_MAX); | ||
177 | } | ||
178 | pc++; | ||
179 | *to-- = m; | ||
180 | } | ||
181 | } | ||
182 | |||
183 | /* Compile function prototype. */ | ||
184 | static int jit_compile_proto(jit_State *J, Table *deopt) | ||
185 | { | ||
186 | jit_Mfm *tempmfm; | ||
187 | void *mcode; | ||
188 | size_t sz; | ||
189 | int firstpc = 0, maxpc = J->pt->sizecode; | ||
190 | int deoptidx = 1; | ||
191 | int status; | ||
192 | /* (Ab)use the global string concatenation buffer for the temporary mfm. */ | ||
193 | /* Caveat: the GC must not be run while the backend is active. */ | ||
194 | tempmfm = (jit_Mfm *)luaZ_openspace(J->L, &G(J->L)->buff, | ||
195 | (1+maxpc+1+1+1)*sizeof(jit_Mfm)); | ||
196 | nextdeopt: | ||
197 | J->mfm = tempmfm; | ||
198 | J->tflags = 0; | ||
199 | /* Setup DynASM. */ | ||
200 | dasm_growpc(Dst, 1+maxpc+2); /* See jit_ins_last(). */ | ||
201 | dasm_setup(Dst, jit_actionlist); | ||
202 | if (deopt) { /* Partial deoptimization. */ | ||
203 | /* TODO: check deopt chain length? problem: pairs TFOR_CTL migration. */ | ||
204 | int pc, lastpc; | ||
205 | lua_Number n; | ||
206 | const TValue *obj = luaH_getnum(deopt, deoptidx++); | ||
207 | if (ttisnil(obj) && deoptidx != 2) return JIT_S_OK; | ||
208 | if (!ttisnumber(obj)) return JIT_S_COMPILER_ERROR; | ||
209 | n = nvalue(obj); | ||
210 | lua_number2int(pc, n); | ||
211 | firstpc = JIT_IH_IDX(pc); | ||
212 | lastpc = firstpc + JIT_IH_LIB(pc); | ||
213 | if (firstpc < 1 || firstpc > maxpc || lastpc > maxpc || | ||
214 | J->pt->jit_szmcode == 0) | ||
215 | return JIT_S_COMPILER_ERROR; | ||
216 | *J->mfm++ = JIT_MFM_MARK+firstpc; /* Seek to firstpc. */ | ||
217 | jit_compile_irange(J, firstpc, lastpc); | ||
218 | jit_assert(J->nextpc == lastpc+1); /* Problem with combined ins? */ | ||
219 | if (J->nextpc <= maxpc) jit_ins_chainto(J, J->nextpc); | ||
220 | *J->mfm++ = JIT_MFM_MARK+maxpc+1; /* Seek to .deopt/.tail. */ | ||
221 | for (pc = 1; pc <= maxpc; pc++) | ||
222 | if (dasm_getpclabel(Dst, pc) == -1) { /* Undefind label referenced? */ | ||
223 | jit_ins_setpc(J, pc, luaJIT_findmcode(J->pt, pc)); /* => Old mcode. */ | ||
224 | } | ||
225 | } else { /* Full compile. */ | ||
226 | *J->mfm++ = 0; /* Placeholder mfm entry for prologue. */ | ||
227 | jit_prologue(J); | ||
228 | jit_compile_irange(J, 1, maxpc); | ||
229 | } | ||
230 | *J->mfm++ = 0; /* Placeholder mfm entry for .deopt/.tail. */ | ||
231 | *J->mfm = JIT_MFM_STOP; | ||
232 | jit_ins_last(J, maxpc, (char *)J->mfm - (char *)tempmfm); | ||
233 | |||
234 | status = luaJIT_link(J, &mcode, &sz); | ||
235 | if (status != JIT_S_OK) | ||
236 | return status; | ||
237 | |||
238 | jit_mfm_merge(J, tempmfm, JIT_MCMFM(mcode, sz), maxpc); | ||
239 | |||
240 | if (deopt) { | ||
241 | jit_MCTrailer tr; | ||
242 | /* Patch first instruction to jump to the deoptimized code. */ | ||
243 | jit_patch_jmp(J, luaJIT_findmcode(J->pt, firstpc), mcode); | ||
244 | /* Mark instruction as deoptimized in main mfm. */ | ||
245 | JIT_MCMFM(J->pt->jit_mcode, J->pt->jit_szmcode)[-firstpc] |= JIT_MFM_MARK; | ||
246 | /* Chain deopt mcode block between main mfm and existing mfms. */ | ||
247 | memcpy(JIT_MCTRAILER(mcode, sz), | ||
248 | JIT_MCTRAILER(J->pt->jit_mcode, J->pt->jit_szmcode), | ||
249 | sizeof(jit_MCTrailer)); | ||
250 | tr.mcode = (char *)mcode; | ||
251 | tr.sz = sz; | ||
252 | memcpy(JIT_MCTRAILER(J->pt->jit_mcode, J->pt->jit_szmcode), (void *)&tr, | ||
253 | sizeof(jit_MCTrailer)); | ||
254 | goto nextdeopt; | ||
255 | } | ||
256 | |||
257 | if (J->pt->jit_szmcode != 0) { /* Full recompile? */ | ||
258 | jit_MCTrailer tr; | ||
259 | /* Patch old mcode entry so other closures get the new callgate. */ | ||
260 | jit_patch_jmp(J, J->pt->jit_mcode, J->jsub[JSUB_GATE_JL]); | ||
261 | /* Chain old main mfm after new main mfm. */ | ||
262 | tr.mcode = (char *)J->pt->jit_mcode; | ||
263 | tr.sz = J->pt->jit_szmcode; | ||
264 | memcpy(JIT_MCTRAILER(mcode, sz), (void *)&tr, sizeof(jit_MCTrailer)); | ||
265 | } | ||
266 | /* Set new main mcode block. */ | ||
267 | J->pt->jit_mcode = mcode; | ||
268 | J->pt->jit_szmcode = sz; | ||
269 | return JIT_S_OK; | ||
270 | } | ||
271 | |||
272 | /* ------------------------------------------------------------------------ */ | ||
273 | |||
274 | /* Compiler backend. */ | ||
275 | int luaJIT_backend(lua_State *L) | ||
276 | { | ||
277 | jit_State *J = G(L)->jit_state; | ||
278 | const TValue *cl; | ||
279 | int status = JIT_S_COMPILER_ERROR; | ||
280 | lua_lock(L); | ||
281 | /* Remember compiler state table. */ | ||
282 | jit_assert(L->top > L->base && ttistable(L->top-1)); | ||
283 | J->comstate = hvalue(L->top-1); | ||
284 | /* Fetch prototoype. Better check this in case some handler screwed up. */ | ||
285 | cl = luaH_getstr(J->comstate, luaS_newliteral(L, "func")); | ||
286 | if (isLfunction(cl)) { | ||
287 | J->pt = clvalue(cl)->l.p; | ||
288 | if (J->pt->sizecode > LUAJIT_LIM_BYTECODE) { /* Hard backend limit. */ | ||
289 | status = JIT_S_TOOLARGE; | ||
290 | } else { | ||
291 | const TValue *obj = luaH_getstr(J->comstate, | ||
292 | luaS_newliteral(J->L, "deopt")); | ||
293 | status = jit_compile_proto(J, ttistable(obj) ? hvalue(obj) : (Table *)0); | ||
294 | } | ||
295 | } | ||
296 | lua_unlock(L); | ||
297 | J->comstate = NULL; /* Just in case. */ | ||
298 | J->pt = NULL; | ||
299 | if (status == JIT_S_OK) { | ||
300 | return 0; | ||
301 | } else { | ||
302 | if (status == JIT_S_DASM_ERROR) { | ||
303 | lua_pushinteger(L, J->nextpc); | ||
304 | lua_setfield(L, 1, "dasm_pc"); | ||
305 | lua_pushinteger(L, J->dasmstatus); | ||
306 | lua_setfield(L, 1, "dasm_err"); | ||
307 | } | ||
308 | lua_pushinteger(L, status); | ||
309 | return 1; | ||
310 | } | ||
311 | } | ||
312 | |||
313 | /* Initialize compiler backend. */ | ||
314 | int luaJIT_initbackend(lua_State *L) | ||
315 | { | ||
316 | jit_State *J = G(L)->jit_state; | ||
317 | J->L = L; | ||
318 | J->pt = NULL; /* Not in use. */ | ||
319 | J->D = NULL; | ||
320 | J->mcodeheap = NULL; | ||
321 | J->jsubmcode = NULL; | ||
322 | J->szjsubmcode = 0; | ||
323 | J->numjsub = JSUB__MAX; | ||
324 | J->jsub = luaM_newvector(J->L, JSUB__MAX, void *); | ||
325 | memset((void *)J->jsub, 0, JSUB__MAX*sizeof(void *)); /* Just in case. */ | ||
326 | dasm_init(Dst, DASM_MAXSECTION); | ||
327 | dasm_setupglobal(Dst, J->jsub, JSUB__MAX); | ||
328 | return jit_compile_jsub(J); | ||
329 | } | ||
330 | |||
331 | /* Free compiler backend. */ | ||
332 | void luaJIT_freebackend(lua_State *L) | ||
333 | { | ||
334 | jit_State *J = G(L)->jit_state; | ||
335 | J->L = L; | ||
336 | if (J->jsub) luaM_freearray(L, J->jsub, JSUB__MAX, void *); | ||
337 | luaJIT_freemcodeheap(J); /* Frees JSUB mcode, too. */ | ||
338 | dasm_free(Dst); | ||
339 | } | ||
340 | |||
341 | /* ------------------------------------------------------------------------ */ | ||
342 | |||