diff options
Diffstat (limited to 'src/lj_ir.c')
-rw-r--r-- | src/lj_ir.c | 153 |
1 files changed, 73 insertions, 80 deletions
diff --git a/src/lj_ir.c b/src/lj_ir.c index 38f289cb..1dd25f23 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,6 +30,7 @@ | |||
29 | #endif | 30 | #endif |
30 | #include "lj_vm.h" | 31 | #include "lj_vm.h" |
31 | #include "lj_strscan.h" | 32 | #include "lj_strscan.h" |
33 | #include "lj_strfmt.h" | ||
32 | #include "lj_lib.h" | 34 | #include "lj_lib.h" |
33 | 35 | ||
34 | /* Some local macros to save typing. Undef'd at the end. */ | 36 | /* Some local macros to save typing. Undef'd at the end. */ |
@@ -89,7 +91,7 @@ static void lj_ir_growbot(jit_State *J) | |||
89 | IRIns *baseir = J->irbuf + J->irbotlim; | 91 | IRIns *baseir = J->irbuf + J->irbotlim; |
90 | MSize szins = J->irtoplim - J->irbotlim; | 92 | MSize szins = J->irtoplim - J->irbotlim; |
91 | lua_assert(szins != 0); | 93 | lua_assert(szins != 0); |
92 | lua_assert(J->cur.nk == J->irbotlim); | 94 | lua_assert(J->cur.nk == J->irbotlim || J->cur.nk-1 == J->irbotlim); |
93 | if (J->cur.nins + (szins >> 1) < J->irtoplim) { | 95 | if (J->cur.nins + (szins >> 1) < J->irtoplim) { |
94 | /* More than half of the buffer is free on top: shift up by a quarter. */ | 96 | /* More than half of the buffer is free on top: shift up by a quarter. */ |
95 | MSize ofs = szins >> 2; | 97 | MSize ofs = szins >> 2; |
@@ -143,6 +145,16 @@ TRef lj_ir_call(jit_State *J, IRCallID id, ...) | |||
143 | return emitir(CCI_OPTYPE(ci), tr, id); | 145 | return emitir(CCI_OPTYPE(ci), tr, id); |
144 | } | 146 | } |
145 | 147 | ||
148 | /* Load field of type t from GG_State + offset. Must be 32 bit aligned. */ | ||
149 | LJ_FUNC TRef lj_ir_ggfload(jit_State *J, IRType t, uintptr_t ofs) | ||
150 | { | ||
151 | lua_assert((ofs & 3) == 0); | ||
152 | ofs >>= 2; | ||
153 | lua_assert(ofs >= IRFL__MAX && ofs <= 0x3ff); /* 10 bit FOLD key limit. */ | ||
154 | lj_ir_set(J, IRT(IR_FLOAD, t), REF_NIL, ofs); | ||
155 | return lj_opt_fold(J); | ||
156 | } | ||
157 | |||
146 | /* -- Interning of constants ---------------------------------------------- */ | 158 | /* -- Interning of constants ---------------------------------------------- */ |
147 | 159 | ||
148 | /* | 160 | /* |
@@ -163,6 +175,24 @@ static LJ_AINLINE IRRef ir_nextk(jit_State *J) | |||
163 | return ref; | 175 | return ref; |
164 | } | 176 | } |
165 | 177 | ||
178 | /* Get ref of next 64 bit IR constant and optionally grow IR. | ||
179 | ** Note: this may invalidate all IRIns *! | ||
180 | */ | ||
181 | static LJ_AINLINE IRRef ir_nextk64(jit_State *J) | ||
182 | { | ||
183 | IRRef ref = J->cur.nk - 2; | ||
184 | lua_assert(J->state != LJ_TRACE_ASM); | ||
185 | if (LJ_UNLIKELY(ref < J->irbotlim)) lj_ir_growbot(J); | ||
186 | J->cur.nk = ref; | ||
187 | return ref; | ||
188 | } | ||
189 | |||
190 | #if LJ_GC64 | ||
191 | #define ir_nextkgc ir_nextk64 | ||
192 | #else | ||
193 | #define ir_nextkgc ir_nextk | ||
194 | #endif | ||
195 | |||
166 | /* Intern int32_t constant. */ | 196 | /* Intern int32_t constant. */ |
167 | TRef LJ_FASTCALL lj_ir_kint(jit_State *J, int32_t k) | 197 | TRef LJ_FASTCALL lj_ir_kint(jit_State *J, int32_t k) |
168 | { | 198 | { |
@@ -182,79 +212,21 @@ found: | |||
182 | return TREF(ref, IRT_INT); | 212 | return TREF(ref, IRT_INT); |
183 | } | 213 | } |
184 | 214 | ||
185 | /* The MRef inside the KNUM/KINT64 IR instructions holds the address of the | 215 | /* Intern 64 bit constant, given by its 64 bit pattern. */ |
186 | ** 64 bit constant. The constants themselves are stored in a chained array | 216 | 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 | { | 217 | { |
246 | IRIns *ir, *cir = J->cur.ir; | 218 | IRIns *ir, *cir = J->cur.ir; |
247 | IRRef ref; | 219 | IRRef ref; |
248 | IRType t = op == IR_KNUM ? IRT_NUM : IRT_I64; | 220 | IRType t = op == IR_KNUM ? IRT_NUM : IRT_I64; |
249 | for (ref = J->chain[op]; ref; ref = cir[ref].prev) | 221 | for (ref = J->chain[op]; ref; ref = cir[ref].prev) |
250 | if (ir_k64(&cir[ref]) == tv) | 222 | if (ir_k64(&cir[ref])->u64 == u64) |
251 | goto found; | 223 | goto found; |
252 | ref = ir_nextk(J); | 224 | ref = ir_nextk64(J); |
253 | ir = IR(ref); | 225 | ir = IR(ref); |
254 | lua_assert(checkptr32(tv)); | 226 | ir[1].tv.u64 = u64; |
255 | setmref(ir->ptr, tv); | ||
256 | ir->t.irt = t; | 227 | ir->t.irt = t; |
257 | ir->o = op; | 228 | ir->o = op; |
229 | ir->op12 = 0; | ||
258 | ir->prev = J->chain[op]; | 230 | ir->prev = J->chain[op]; |
259 | J->chain[op] = (IRRef1)ref; | 231 | J->chain[op] = (IRRef1)ref; |
260 | found: | 232 | found: |
@@ -264,13 +236,13 @@ found: | |||
264 | /* Intern FP constant, given by its 64 bit pattern. */ | 236 | /* Intern FP constant, given by its 64 bit pattern. */ |
265 | TRef lj_ir_knum_u64(jit_State *J, uint64_t u64) | 237 | TRef lj_ir_knum_u64(jit_State *J, uint64_t u64) |
266 | { | 238 | { |
267 | return lj_ir_k64(J, IR_KNUM, lj_ir_k64_find(J, u64)); | 239 | return lj_ir_k64(J, IR_KNUM, u64); |
268 | } | 240 | } |
269 | 241 | ||
270 | /* Intern 64 bit integer constant. */ | 242 | /* Intern 64 bit integer constant. */ |
271 | TRef lj_ir_kint64(jit_State *J, uint64_t u64) | 243 | TRef lj_ir_kint64(jit_State *J, uint64_t u64) |
272 | { | 244 | { |
273 | return lj_ir_k64(J, IR_KINT64, lj_ir_k64_find(J, u64)); | 245 | return lj_ir_k64(J, IR_KINT64, u64); |
274 | } | 246 | } |
275 | 247 | ||
276 | /* Check whether a number is int and return it. -0 is NOT considered an int. */ | 248 | /* Check whether a number is int and return it. -0 is NOT considered an int. */ |
@@ -309,10 +281,11 @@ TRef lj_ir_kgc(jit_State *J, GCobj *o, IRType t) | |||
309 | for (ref = J->chain[IR_KGC]; ref; ref = cir[ref].prev) | 281 | for (ref = J->chain[IR_KGC]; ref; ref = cir[ref].prev) |
310 | if (ir_kgc(&cir[ref]) == o) | 282 | if (ir_kgc(&cir[ref]) == o) |
311 | goto found; | 283 | goto found; |
312 | ref = ir_nextk(J); | 284 | ref = ir_nextkgc(J); |
313 | ir = IR(ref); | 285 | ir = IR(ref); |
314 | /* NOBARRIER: Current trace is a GC root. */ | 286 | /* NOBARRIER: Current trace is a GC root. */ |
315 | setgcref(ir->gcr, o); | 287 | ir->op12 = 0; |
288 | setgcref(ir[LJ_GC64].gcr, o); | ||
316 | ir->t.irt = (uint8_t)t; | 289 | ir->t.irt = (uint8_t)t; |
317 | ir->o = IR_KGC; | 290 | ir->o = IR_KGC; |
318 | ir->prev = J->chain[IR_KGC]; | 291 | ir->prev = J->chain[IR_KGC]; |
@@ -321,24 +294,44 @@ found: | |||
321 | return TREF(ref, t); | 294 | return TREF(ref, t); |
322 | } | 295 | } |
323 | 296 | ||
324 | /* Intern 32 bit pointer constant. */ | 297 | /* Allocate GCtrace constant placeholder (no interning). */ |
298 | TRef lj_ir_ktrace(jit_State *J) | ||
299 | { | ||
300 | IRRef ref = ir_nextkgc(J); | ||
301 | IRIns *ir = IR(ref); | ||
302 | lua_assert(irt_toitype_(IRT_P64) == LJ_TTRACE); | ||
303 | ir->t.irt = IRT_P64; | ||
304 | ir->o = LJ_GC64 ? IR_KNUM : IR_KNULL; /* Not IR_KGC yet, but same size. */ | ||
305 | ir->op12 = 0; | ||
306 | ir->prev = 0; | ||
307 | return TREF(ref, IRT_P64); | ||
308 | } | ||
309 | |||
310 | /* Intern pointer constant. */ | ||
325 | TRef lj_ir_kptr_(jit_State *J, IROp op, void *ptr) | 311 | TRef lj_ir_kptr_(jit_State *J, IROp op, void *ptr) |
326 | { | 312 | { |
327 | IRIns *ir, *cir = J->cur.ir; | 313 | IRIns *ir, *cir = J->cur.ir; |
328 | IRRef ref; | 314 | IRRef ref; |
329 | lua_assert((void *)(intptr_t)i32ptr(ptr) == ptr); | 315 | #if LJ_64 && !LJ_GC64 |
316 | lua_assert((void *)(uintptr_t)u32ptr(ptr) == ptr); | ||
317 | #endif | ||
330 | for (ref = J->chain[op]; ref; ref = cir[ref].prev) | 318 | for (ref = J->chain[op]; ref; ref = cir[ref].prev) |
331 | if (mref(cir[ref].ptr, void) == ptr) | 319 | if (ir_kptr(&cir[ref]) == ptr) |
332 | goto found; | 320 | goto found; |
321 | #if LJ_GC64 | ||
322 | ref = ir_nextk64(J); | ||
323 | #else | ||
333 | ref = ir_nextk(J); | 324 | ref = ir_nextk(J); |
325 | #endif | ||
334 | ir = IR(ref); | 326 | ir = IR(ref); |
335 | setmref(ir->ptr, ptr); | 327 | ir->op12 = 0; |
336 | ir->t.irt = IRT_P32; | 328 | setmref(ir[LJ_GC64].ptr, ptr); |
329 | ir->t.irt = IRT_PGC; | ||
337 | ir->o = op; | 330 | ir->o = op; |
338 | ir->prev = J->chain[op]; | 331 | ir->prev = J->chain[op]; |
339 | J->chain[op] = (IRRef1)ref; | 332 | J->chain[op] = (IRRef1)ref; |
340 | found: | 333 | found: |
341 | return TREF(ref, IRT_P32); | 334 | return TREF(ref, IRT_PGC); |
342 | } | 335 | } |
343 | 336 | ||
344 | /* Intern typed NULL constant. */ | 337 | /* Intern typed NULL constant. */ |
@@ -390,12 +383,11 @@ void lj_ir_kvalue(lua_State *L, TValue *tv, const IRIns *ir) | |||
390 | UNUSED(L); | 383 | UNUSED(L); |
391 | lua_assert(ir->o != IR_KSLOT); /* Common mistake. */ | 384 | lua_assert(ir->o != IR_KSLOT); /* Common mistake. */ |
392 | switch (ir->o) { | 385 | switch (ir->o) { |
393 | case IR_KPRI: setitype(tv, irt_toitype(ir->t)); break; | 386 | case IR_KPRI: setpriV(tv, irt_toitype(ir->t)); break; |
394 | case IR_KINT: setintV(tv, ir->i); break; | 387 | case IR_KINT: setintV(tv, ir->i); break; |
395 | case IR_KGC: setgcV(L, tv, ir_kgc(ir), irt_toitype(ir->t)); break; | 388 | case IR_KGC: setgcV(L, tv, ir_kgc(ir), irt_toitype(ir->t)); break; |
396 | case IR_KPTR: case IR_KKPTR: case IR_KNULL: | 389 | case IR_KPTR: case IR_KKPTR: setlightudV(tv, ir_kptr(ir)); break; |
397 | setlightudV(tv, mref(ir->ptr, void)); | 390 | case IR_KNULL: setlightudV(tv, NULL); break; |
398 | break; | ||
399 | case IR_KNUM: setnumV(tv, ir_knum(ir)->n); break; | 391 | case IR_KNUM: setnumV(tv, ir_knum(ir)->n); break; |
400 | #if LJ_HASFFI | 392 | #if LJ_HASFFI |
401 | case IR_KINT64: { | 393 | case IR_KINT64: { |
@@ -443,7 +435,8 @@ TRef LJ_FASTCALL lj_ir_tostr(jit_State *J, TRef tr) | |||
443 | if (!tref_isstr(tr)) { | 435 | if (!tref_isstr(tr)) { |
444 | if (!tref_isnumber(tr)) | 436 | if (!tref_isnumber(tr)) |
445 | lj_trace_err(J, LJ_TRERR_BADTYPE); | 437 | lj_trace_err(J, LJ_TRERR_BADTYPE); |
446 | tr = emitir(IRT(IR_TOSTR, IRT_STR), tr, 0); | 438 | tr = emitir(IRT(IR_TOSTR, IRT_STR), tr, |
439 | tref_isnum(tr) ? IRTOSTR_NUM : IRTOSTR_INT); | ||
447 | } | 440 | } |
448 | return tr; | 441 | return tr; |
449 | } | 442 | } |