aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/LuaJIT-1.1.7/src/ljit_backend.c
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/LuaJIT-1.1.7/src/ljit_backend.c')
-rw-r--r--libraries/LuaJIT-1.1.7/src/ljit_backend.c342
1 files changed, 342 insertions, 0 deletions
diff --git a/libraries/LuaJIT-1.1.7/src/ljit_backend.c b/libraries/LuaJIT-1.1.7/src/ljit_backend.c
new file mode 100644
index 0000000..698342f
--- /dev/null
+++ b/libraries/LuaJIT-1.1.7/src/ljit_backend.c
@@ -0,0 +1,342 @@
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. */
34static 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. */
56static 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. */
157static 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. */
184static 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));
196nextdeopt:
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. */
275int 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. */
314int 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. */
332void 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