diff options
Diffstat (limited to 'src/lj_ir.c')
-rw-r--r-- | src/lj_ir.c | 175 |
1 files changed, 87 insertions, 88 deletions
diff --git a/src/lj_ir.c b/src/lj_ir.c index b2846680..65901510 100644 --- a/src/lj_ir.c +++ b/src/lj_ir.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #if LJ_HASJIT | 15 | #if LJ_HASJIT |
16 | 16 | ||
17 | #include "lj_gc.h" | 17 | #include "lj_gc.h" |
18 | #include "lj_buf.h" | ||
18 | #include "lj_str.h" | 19 | #include "lj_str.h" |
19 | #include "lj_tab.h" | 20 | #include "lj_tab.h" |
20 | #include "lj_ir.h" | 21 | #include "lj_ir.h" |
@@ -29,14 +30,16 @@ | |||
29 | #endif | 30 | #endif |
30 | #include "lj_vm.h" | 31 | #include "lj_vm.h" |
31 | #include "lj_strscan.h" | 32 | #include "lj_strscan.h" |
32 | #include "lj_lib.h" | 33 | #include "lj_serialize.h" |
34 | #include "lj_strfmt.h" | ||
35 | #include "lj_prng.h" | ||
33 | 36 | ||
34 | /* Some local macros to save typing. Undef'd at the end. */ | 37 | /* Some local macros to save typing. Undef'd at the end. */ |
35 | #define IR(ref) (&J->cur.ir[(ref)]) | 38 | #define IR(ref) (&J->cur.ir[(ref)]) |
36 | #define fins (&J->fold.ins) | 39 | #define fins (&J->fold.ins) |
37 | 40 | ||
38 | /* Pass IR on to next optimization in chain (FOLD). */ | 41 | /* Pass IR on to next optimization in chain (FOLD). */ |
39 | #define emitir(ot, a, b) (lj_ir_set(J, (ot), (a), (b)), lj_opt_fold(J)) | 42 | #define emitir(ot, a, b) (lj_ir_set(J, (ot), (a), (b)), lj_opt_fold(J)) |
40 | 43 | ||
41 | /* -- IR tables ----------------------------------------------------------- */ | 44 | /* -- IR tables ----------------------------------------------------------- */ |
42 | 45 | ||
@@ -88,8 +91,9 @@ static void lj_ir_growbot(jit_State *J) | |||
88 | { | 91 | { |
89 | IRIns *baseir = J->irbuf + J->irbotlim; | 92 | IRIns *baseir = J->irbuf + J->irbotlim; |
90 | MSize szins = J->irtoplim - J->irbotlim; | 93 | MSize szins = J->irtoplim - J->irbotlim; |
91 | lua_assert(szins != 0); | 94 | lj_assertJ(szins != 0, "zero IR size"); |
92 | lua_assert(J->cur.nk == J->irbotlim); | 95 | lj_assertJ(J->cur.nk == J->irbotlim || J->cur.nk-1 == J->irbotlim, |
96 | "unexpected IR growth"); | ||
93 | if (J->cur.nins + (szins >> 1) < J->irtoplim) { | 97 | if (J->cur.nins + (szins >> 1) < J->irtoplim) { |
94 | /* More than half of the buffer is free on top: shift up by a quarter. */ | 98 | /* More than half of the buffer is free on top: shift up by a quarter. */ |
95 | MSize ofs = szins >> 2; | 99 | MSize ofs = szins >> 2; |
@@ -143,6 +147,17 @@ TRef lj_ir_call(jit_State *J, IRCallID id, ...) | |||
143 | return emitir(CCI_OPTYPE(ci), tr, id); | 147 | return emitir(CCI_OPTYPE(ci), tr, id); |
144 | } | 148 | } |
145 | 149 | ||
150 | /* Load field of type t from GG_State + offset. Must be 32 bit aligned. */ | ||
151 | TRef lj_ir_ggfload(jit_State *J, IRType t, uintptr_t ofs) | ||
152 | { | ||
153 | lj_assertJ((ofs & 3) == 0, "unaligned GG_State field offset"); | ||
154 | ofs >>= 2; | ||
155 | lj_assertJ(ofs >= IRFL__MAX && ofs <= 0x3ff, | ||
156 | "GG_State field offset breaks 10 bit FOLD key limit"); | ||
157 | lj_ir_set(J, IRT(IR_FLOAD, t), REF_NIL, ofs); | ||
158 | return lj_opt_fold(J); | ||
159 | } | ||
160 | |||
146 | /* -- Interning of constants ---------------------------------------------- */ | 161 | /* -- Interning of constants ---------------------------------------------- */ |
147 | 162 | ||
148 | /* | 163 | /* |
@@ -163,6 +178,24 @@ static LJ_AINLINE IRRef ir_nextk(jit_State *J) | |||
163 | return ref; | 178 | return ref; |
164 | } | 179 | } |
165 | 180 | ||
181 | /* Get ref of next 64 bit IR constant and optionally grow IR. | ||
182 | ** Note: this may invalidate all IRIns *! | ||
183 | */ | ||
184 | static LJ_AINLINE IRRef ir_nextk64(jit_State *J) | ||
185 | { | ||
186 | IRRef ref = J->cur.nk - 2; | ||
187 | lj_assertJ(J->state != LJ_TRACE_ASM, "bad JIT state"); | ||
188 | if (LJ_UNLIKELY(ref < J->irbotlim)) lj_ir_growbot(J); | ||
189 | J->cur.nk = ref; | ||
190 | return ref; | ||
191 | } | ||
192 | |||
193 | #if LJ_GC64 | ||
194 | #define ir_nextkgc ir_nextk64 | ||
195 | #else | ||
196 | #define ir_nextkgc ir_nextk | ||
197 | #endif | ||
198 | |||
166 | /* Intern int32_t constant. */ | 199 | /* Intern int32_t constant. */ |
167 | TRef LJ_FASTCALL lj_ir_kint(jit_State *J, int32_t k) | 200 | TRef LJ_FASTCALL lj_ir_kint(jit_State *J, int32_t k) |
168 | { | 201 | { |
@@ -182,79 +215,21 @@ found: | |||
182 | return TREF(ref, IRT_INT); | 215 | return TREF(ref, IRT_INT); |
183 | } | 216 | } |
184 | 217 | ||
185 | /* The MRef inside the KNUM/KINT64 IR instructions holds the address of the | 218 | /* Intern 64 bit constant, given by its 64 bit pattern. */ |
186 | ** 64 bit constant. The constants themselves are stored in a chained array | 219 | TRef lj_ir_k64(jit_State *J, IROp op, uint64_t u64) |
187 | ** and shared across traces. | ||
188 | ** | ||
189 | ** Rationale for choosing this data structure: | ||
190 | ** - The address of the constants is embedded in the generated machine code | ||
191 | ** and must never move. A resizable array or hash table wouldn't work. | ||
192 | ** - Most apps need very few non-32 bit integer constants (less than a dozen). | ||
193 | ** - Linear search is hard to beat in terms of speed and low complexity. | ||
194 | */ | ||
195 | typedef struct K64Array { | ||
196 | MRef next; /* Pointer to next list. */ | ||
197 | MSize numk; /* Number of used elements in this array. */ | ||
198 | TValue k[LJ_MIN_K64SZ]; /* Array of constants. */ | ||
199 | } K64Array; | ||
200 | |||
201 | /* Free all chained arrays. */ | ||
202 | void lj_ir_k64_freeall(jit_State *J) | ||
203 | { | ||
204 | K64Array *k; | ||
205 | for (k = mref(J->k64, K64Array); k; ) { | ||
206 | K64Array *next = mref(k->next, K64Array); | ||
207 | lj_mem_free(J2G(J), k, sizeof(K64Array)); | ||
208 | k = next; | ||
209 | } | ||
210 | } | ||
211 | |||
212 | /* Find 64 bit constant in chained array or add it. */ | ||
213 | cTValue *lj_ir_k64_find(jit_State *J, uint64_t u64) | ||
214 | { | ||
215 | K64Array *k, *kp = NULL; | ||
216 | TValue *ntv; | ||
217 | MSize idx; | ||
218 | /* Search for the constant in the whole chain of arrays. */ | ||
219 | for (k = mref(J->k64, K64Array); k; k = mref(k->next, K64Array)) { | ||
220 | kp = k; /* Remember previous element in list. */ | ||
221 | for (idx = 0; idx < k->numk; idx++) { /* Search one array. */ | ||
222 | TValue *tv = &k->k[idx]; | ||
223 | if (tv->u64 == u64) /* Needed for +-0/NaN/absmask. */ | ||
224 | return tv; | ||
225 | } | ||
226 | } | ||
227 | /* Constant was not found, need to add it. */ | ||
228 | if (!(kp && kp->numk < LJ_MIN_K64SZ)) { /* Allocate a new array. */ | ||
229 | K64Array *kn = lj_mem_newt(J->L, sizeof(K64Array), K64Array); | ||
230 | setmref(kn->next, NULL); | ||
231 | kn->numk = 0; | ||
232 | if (kp) | ||
233 | setmref(kp->next, kn); /* Chain to the end of the list. */ | ||
234 | else | ||
235 | setmref(J->k64, kn); /* Link first array. */ | ||
236 | kp = kn; | ||
237 | } | ||
238 | ntv = &kp->k[kp->numk++]; /* Add to current array. */ | ||
239 | ntv->u64 = u64; | ||
240 | return ntv; | ||
241 | } | ||
242 | |||
243 | /* Intern 64 bit constant, given by its address. */ | ||
244 | TRef lj_ir_k64(jit_State *J, IROp op, cTValue *tv) | ||
245 | { | 220 | { |
246 | IRIns *ir, *cir = J->cur.ir; | 221 | IRIns *ir, *cir = J->cur.ir; |
247 | IRRef ref; | 222 | IRRef ref; |
248 | IRType t = op == IR_KNUM ? IRT_NUM : IRT_I64; | 223 | IRType t = op == IR_KNUM ? IRT_NUM : IRT_I64; |
249 | for (ref = J->chain[op]; ref; ref = cir[ref].prev) | 224 | for (ref = J->chain[op]; ref; ref = cir[ref].prev) |
250 | if (ir_k64(&cir[ref]) == tv) | 225 | if (ir_k64(&cir[ref])->u64 == u64) |
251 | goto found; | 226 | goto found; |
252 | ref = ir_nextk(J); | 227 | ref = ir_nextk64(J); |
253 | ir = IR(ref); | 228 | ir = IR(ref); |
254 | lua_assert(checkptr32(tv)); | 229 | ir[1].tv.u64 = u64; |
255 | setmref(ir->ptr, tv); | ||
256 | ir->t.irt = t; | 230 | ir->t.irt = t; |
257 | ir->o = op; | 231 | ir->o = op; |
232 | ir->op12 = 0; | ||
258 | ir->prev = J->chain[op]; | 233 | ir->prev = J->chain[op]; |
259 | J->chain[op] = (IRRef1)ref; | 234 | J->chain[op] = (IRRef1)ref; |
260 | found: | 235 | found: |
@@ -264,13 +239,13 @@ found: | |||
264 | /* Intern FP constant, given by its 64 bit pattern. */ | 239 | /* Intern FP constant, given by its 64 bit pattern. */ |
265 | TRef lj_ir_knum_u64(jit_State *J, uint64_t u64) | 240 | TRef lj_ir_knum_u64(jit_State *J, uint64_t u64) |
266 | { | 241 | { |
267 | return lj_ir_k64(J, IR_KNUM, lj_ir_k64_find(J, u64)); | 242 | return lj_ir_k64(J, IR_KNUM, u64); |
268 | } | 243 | } |
269 | 244 | ||
270 | /* Intern 64 bit integer constant. */ | 245 | /* Intern 64 bit integer constant. */ |
271 | TRef lj_ir_kint64(jit_State *J, uint64_t u64) | 246 | TRef lj_ir_kint64(jit_State *J, uint64_t u64) |
272 | { | 247 | { |
273 | return lj_ir_k64(J, IR_KINT64, lj_ir_k64_find(J, u64)); | 248 | return lj_ir_k64(J, IR_KINT64, u64); |
274 | } | 249 | } |
275 | 250 | ||
276 | /* Check whether a number is int and return it. -0 is NOT considered an int. */ | 251 | /* Check whether a number is int and return it. -0 is NOT considered an int. */ |
@@ -305,14 +280,15 @@ TRef lj_ir_kgc(jit_State *J, GCobj *o, IRType t) | |||
305 | { | 280 | { |
306 | IRIns *ir, *cir = J->cur.ir; | 281 | IRIns *ir, *cir = J->cur.ir; |
307 | IRRef ref; | 282 | IRRef ref; |
308 | lua_assert(!isdead(J2G(J), o)); | 283 | lj_assertJ(!isdead(J2G(J), o), "interning of dead GC object"); |
309 | for (ref = J->chain[IR_KGC]; ref; ref = cir[ref].prev) | 284 | for (ref = J->chain[IR_KGC]; ref; ref = cir[ref].prev) |
310 | if (ir_kgc(&cir[ref]) == o) | 285 | if (ir_kgc(&cir[ref]) == o) |
311 | goto found; | 286 | goto found; |
312 | ref = ir_nextk(J); | 287 | ref = ir_nextkgc(J); |
313 | ir = IR(ref); | 288 | ir = IR(ref); |
314 | /* NOBARRIER: Current trace is a GC root. */ | 289 | /* NOBARRIER: Current trace is a GC root. */ |
315 | setgcref(ir->gcr, o); | 290 | ir->op12 = 0; |
291 | setgcref(ir[LJ_GC64].gcr, o); | ||
316 | ir->t.irt = (uint8_t)t; | 292 | ir->t.irt = (uint8_t)t; |
317 | ir->o = IR_KGC; | 293 | ir->o = IR_KGC; |
318 | ir->prev = J->chain[IR_KGC]; | 294 | ir->prev = J->chain[IR_KGC]; |
@@ -321,24 +297,44 @@ found: | |||
321 | return TREF(ref, t); | 297 | return TREF(ref, t); |
322 | } | 298 | } |
323 | 299 | ||
324 | /* Intern 32 bit pointer constant. */ | 300 | /* Allocate GCtrace constant placeholder (no interning). */ |
301 | TRef lj_ir_ktrace(jit_State *J) | ||
302 | { | ||
303 | IRRef ref = ir_nextkgc(J); | ||
304 | IRIns *ir = IR(ref); | ||
305 | lj_assertJ(irt_toitype_(IRT_P64) == LJ_TTRACE, "mismatched type mapping"); | ||
306 | ir->t.irt = IRT_P64; | ||
307 | ir->o = LJ_GC64 ? IR_KNUM : IR_KNULL; /* Not IR_KGC yet, but same size. */ | ||
308 | ir->op12 = 0; | ||
309 | ir->prev = 0; | ||
310 | return TREF(ref, IRT_P64); | ||
311 | } | ||
312 | |||
313 | /* Intern pointer constant. */ | ||
325 | TRef lj_ir_kptr_(jit_State *J, IROp op, void *ptr) | 314 | TRef lj_ir_kptr_(jit_State *J, IROp op, void *ptr) |
326 | { | 315 | { |
327 | IRIns *ir, *cir = J->cur.ir; | 316 | IRIns *ir, *cir = J->cur.ir; |
328 | IRRef ref; | 317 | IRRef ref; |
329 | lua_assert((void *)(intptr_t)i32ptr(ptr) == ptr); | 318 | #if LJ_64 && !LJ_GC64 |
319 | lj_assertJ((void *)(uintptr_t)u32ptr(ptr) == ptr, "out-of-range GC pointer"); | ||
320 | #endif | ||
330 | for (ref = J->chain[op]; ref; ref = cir[ref].prev) | 321 | for (ref = J->chain[op]; ref; ref = cir[ref].prev) |
331 | if (mref(cir[ref].ptr, void) == ptr) | 322 | if (ir_kptr(&cir[ref]) == ptr) |
332 | goto found; | 323 | goto found; |
324 | #if LJ_GC64 | ||
325 | ref = ir_nextk64(J); | ||
326 | #else | ||
333 | ref = ir_nextk(J); | 327 | ref = ir_nextk(J); |
328 | #endif | ||
334 | ir = IR(ref); | 329 | ir = IR(ref); |
335 | setmref(ir->ptr, ptr); | 330 | ir->op12 = 0; |
336 | ir->t.irt = IRT_P32; | 331 | setmref(ir[LJ_GC64].ptr, ptr); |
332 | ir->t.irt = IRT_PGC; | ||
337 | ir->o = op; | 333 | ir->o = op; |
338 | ir->prev = J->chain[op]; | 334 | ir->prev = J->chain[op]; |
339 | J->chain[op] = (IRRef1)ref; | 335 | J->chain[op] = (IRRef1)ref; |
340 | found: | 336 | found: |
341 | return TREF(ref, IRT_P32); | 337 | return TREF(ref, IRT_PGC); |
342 | } | 338 | } |
343 | 339 | ||
344 | /* Intern typed NULL constant. */ | 340 | /* Intern typed NULL constant. */ |
@@ -367,7 +363,8 @@ TRef lj_ir_kslot(jit_State *J, TRef key, IRRef slot) | |||
367 | IRRef2 op12 = IRREF2((IRRef1)key, (IRRef1)slot); | 363 | IRRef2 op12 = IRREF2((IRRef1)key, (IRRef1)slot); |
368 | IRRef ref; | 364 | IRRef ref; |
369 | /* Const part is not touched by CSE/DCE, so 0-65535 is ok for IRMlit here. */ | 365 | /* Const part is not touched by CSE/DCE, so 0-65535 is ok for IRMlit here. */ |
370 | lua_assert(tref_isk(key) && slot == (IRRef)(IRRef1)slot); | 366 | lj_assertJ(tref_isk(key) && slot == (IRRef)(IRRef1)slot, |
367 | "out-of-range key/slot"); | ||
371 | for (ref = J->chain[IR_KSLOT]; ref; ref = cir[ref].prev) | 368 | for (ref = J->chain[IR_KSLOT]; ref; ref = cir[ref].prev) |
372 | if (cir[ref].op12 == op12) | 369 | if (cir[ref].op12 == op12) |
373 | goto found; | 370 | goto found; |
@@ -388,14 +385,15 @@ found: | |||
388 | void lj_ir_kvalue(lua_State *L, TValue *tv, const IRIns *ir) | 385 | void lj_ir_kvalue(lua_State *L, TValue *tv, const IRIns *ir) |
389 | { | 386 | { |
390 | UNUSED(L); | 387 | UNUSED(L); |
391 | lua_assert(ir->o != IR_KSLOT); /* Common mistake. */ | 388 | lj_assertL(ir->o != IR_KSLOT, "unexpected KSLOT"); /* Common mistake. */ |
392 | switch (ir->o) { | 389 | switch (ir->o) { |
393 | case IR_KPRI: setitype(tv, irt_toitype(ir->t)); break; | 390 | case IR_KPRI: setpriV(tv, irt_toitype(ir->t)); break; |
394 | case IR_KINT: setintV(tv, ir->i); break; | 391 | case IR_KINT: setintV(tv, ir->i); break; |
395 | case IR_KGC: setgcV(L, tv, ir_kgc(ir), irt_toitype(ir->t)); break; | 392 | case IR_KGC: setgcV(L, tv, ir_kgc(ir), irt_toitype(ir->t)); break; |
396 | case IR_KPTR: case IR_KKPTR: case IR_KNULL: | 393 | case IR_KPTR: case IR_KKPTR: |
397 | setlightudV(tv, mref(ir->ptr, void)); | 394 | setnumV(tv, (lua_Number)(uintptr_t)ir_kptr(ir)); |
398 | break; | 395 | break; |
396 | case IR_KNULL: setintV(tv, 0); break; | ||
399 | case IR_KNUM: setnumV(tv, ir_knum(ir)->n); break; | 397 | case IR_KNUM: setnumV(tv, ir_knum(ir)->n); break; |
400 | #if LJ_HASFFI | 398 | #if LJ_HASFFI |
401 | case IR_KINT64: { | 399 | case IR_KINT64: { |
@@ -405,7 +403,7 @@ void lj_ir_kvalue(lua_State *L, TValue *tv, const IRIns *ir) | |||
405 | break; | 403 | break; |
406 | } | 404 | } |
407 | #endif | 405 | #endif |
408 | default: lua_assert(0); break; | 406 | default: lj_assertL(0, "bad IR constant op %d", ir->o); break; |
409 | } | 407 | } |
410 | } | 408 | } |
411 | 409 | ||
@@ -443,7 +441,8 @@ TRef LJ_FASTCALL lj_ir_tostr(jit_State *J, TRef tr) | |||
443 | if (!tref_isstr(tr)) { | 441 | if (!tref_isstr(tr)) { |
444 | if (!tref_isnumber(tr)) | 442 | if (!tref_isnumber(tr)) |
445 | lj_trace_err(J, LJ_TRERR_BADTYPE); | 443 | lj_trace_err(J, LJ_TRERR_BADTYPE); |
446 | tr = emitir(IRT(IR_TOSTR, IRT_STR), tr, 0); | 444 | tr = emitir(IRT(IR_TOSTR, IRT_STR), tr, |
445 | tref_isnum(tr) ? IRTOSTR_NUM : IRTOSTR_INT); | ||
447 | } | 446 | } |
448 | return tr; | 447 | return tr; |
449 | } | 448 | } |
@@ -464,7 +463,7 @@ int lj_ir_numcmp(lua_Number a, lua_Number b, IROp op) | |||
464 | case IR_UGE: return !(a < b); | 463 | case IR_UGE: return !(a < b); |
465 | case IR_ULE: return !(a > b); | 464 | case IR_ULE: return !(a > b); |
466 | case IR_UGT: return !(a <= b); | 465 | case IR_UGT: return !(a <= b); |
467 | default: lua_assert(0); return 0; | 466 | default: lj_assertX(0, "bad IR op %d", op); return 0; |
468 | } | 467 | } |
469 | } | 468 | } |
470 | 469 | ||
@@ -477,7 +476,7 @@ int lj_ir_strcmp(GCstr *a, GCstr *b, IROp op) | |||
477 | case IR_GE: return (res >= 0); | 476 | case IR_GE: return (res >= 0); |
478 | case IR_LE: return (res <= 0); | 477 | case IR_LE: return (res <= 0); |
479 | case IR_GT: return (res > 0); | 478 | case IR_GT: return (res > 0); |
480 | default: lua_assert(0); return 0; | 479 | default: lj_assertX(0, "bad IR op %d", op); return 0; |
481 | } | 480 | } |
482 | } | 481 | } |
483 | 482 | ||