aboutsummaryrefslogtreecommitdiff
path: root/src/lj_ir.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lj_ir.c')
-rw-r--r--src/lj_ir.c175
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. */
151TRef 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*/
184static 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. */
167TRef LJ_FASTCALL lj_ir_kint(jit_State *J, int32_t k) 200TRef 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 219TRef 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*/
195typedef 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. */
202void 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. */
213cTValue *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. */
244TRef 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;
260found: 235found:
@@ -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. */
265TRef lj_ir_knum_u64(jit_State *J, uint64_t u64) 240TRef 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. */
271TRef lj_ir_kint64(jit_State *J, uint64_t u64) 246TRef 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). */
301TRef 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. */
325TRef lj_ir_kptr_(jit_State *J, IROp op, void *ptr) 314TRef 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;
340found: 336found:
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:
388void lj_ir_kvalue(lua_State *L, TValue *tv, const IRIns *ir) 385void 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