diff options
author | Mike Pall <mike> | 2011-03-10 01:57:24 +0100 |
---|---|---|
committer | Mike Pall <mike> | 2011-03-10 01:57:24 +0100 |
commit | bfce3c1127fd57fe0c935c92bcf45b4737041edd (patch) | |
tree | 2bd2d9e08c70608de63c7a69df7f00cfab07f6be /src/lj_record.c | |
parent | 3f26e3a89d54dfb761ca02fc89aaf15326f5f514 (diff) | |
download | luajit-bfce3c1127fd57fe0c935c92bcf45b4737041edd.tar.gz luajit-bfce3c1127fd57fe0c935c92bcf45b4737041edd.tar.bz2 luajit-bfce3c1127fd57fe0c935c92bcf45b4737041edd.zip |
DUALNUM: Handle integer type in JIT compiler.
Diffstat (limited to 'src/lj_record.c')
-rw-r--r-- | src/lj_record.c | 280 |
1 files changed, 156 insertions, 124 deletions
diff --git a/src/lj_record.c b/src/lj_record.c index 2bfd2608..613e458e 100644 --- a/src/lj_record.c +++ b/src/lj_record.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include "lj_err.h" | 13 | #include "lj_err.h" |
14 | #include "lj_str.h" | 14 | #include "lj_str.h" |
15 | #include "lj_tab.h" | 15 | #include "lj_tab.h" |
16 | #include "lj_meta.h" | ||
16 | #include "lj_frame.h" | 17 | #include "lj_frame.h" |
17 | #include "lj_bc.h" | 18 | #include "lj_bc.h" |
18 | #include "lj_ff.h" | 19 | #include "lj_ff.h" |
@@ -102,7 +103,7 @@ static void rec_check_slots(jit_State *J) | |||
102 | lua_assert((J->slot[s+1] & TREF_FRAME)); | 103 | lua_assert((J->slot[s+1] & TREF_FRAME)); |
103 | depth++; | 104 | depth++; |
104 | } else { | 105 | } else { |
105 | if (tvisnum(tv)) | 106 | if (tvisnumber(tv)) |
106 | lua_assert(tref_isnumber(tr)); /* Could be IRT_INT etc., too. */ | 107 | lua_assert(tref_isnumber(tr)); /* Could be IRT_INT etc., too. */ |
107 | else | 108 | else |
108 | lua_assert(itype2irt(tv) == tref_type(tr)); | 109 | lua_assert(itype2irt(tv) == tref_type(tr)); |
@@ -197,6 +198,7 @@ typedef enum { | |||
197 | static void canonicalize_slots(jit_State *J) | 198 | static void canonicalize_slots(jit_State *J) |
198 | { | 199 | { |
199 | BCReg s; | 200 | BCReg s; |
201 | if (LJ_DUALNUM) return; | ||
200 | for (s = J->baseslot+J->maxslot-1; s >= 1; s--) { | 202 | for (s = J->baseslot+J->maxslot-1; s >= 1; s--) { |
201 | TRef tr = J->slot[s]; | 203 | TRef tr = J->slot[s]; |
202 | if (tref_isinteger(tr)) { | 204 | if (tref_isinteger(tr)) { |
@@ -254,16 +256,16 @@ static TRef find_kinit(jit_State *J, const BCIns *endpc, BCReg slot, IRType t) | |||
254 | } | 256 | } |
255 | if (op == BC_KSHORT) { | 257 | if (op == BC_KSHORT) { |
256 | int32_t k = (int32_t)(int16_t)bc_d(ins); | 258 | int32_t k = (int32_t)(int16_t)bc_d(ins); |
257 | return t == IRT_INT ? lj_ir_kint(J, k) : lj_ir_knum(J, cast_num(k)); | 259 | return t == IRT_INT ? lj_ir_kint(J, k) : lj_ir_knum(J, (lua_Number)k); |
258 | } else { | 260 | } else { |
259 | lua_Number n = proto_knum(J->pt, bc_d(ins)); | 261 | cTValue *tv = proto_knumtv(J->pt, bc_d(ins)); |
260 | if (t == IRT_INT) { | 262 | if (t == IRT_INT) { |
261 | int32_t k = lj_num2int(n); | 263 | int32_t k = numberVint(tv); |
262 | if (n == cast_num(k)) /* -0 is ok here. */ | 264 | if (tvisint(tv) || numV(tv) == (lua_Number)k) /* -0 is ok here. */ |
263 | return lj_ir_kint(J, k); | 265 | return lj_ir_kint(J, k); |
264 | return 0; /* Type mismatch. */ | 266 | return 0; /* Type mismatch. */ |
265 | } else { | 267 | } else { |
266 | return lj_ir_knum(J, n); | 268 | return lj_ir_knum(J, numberVnum(tv)); |
267 | } | 269 | } |
268 | } | 270 | } |
269 | } | 271 | } |
@@ -273,41 +275,47 @@ static TRef find_kinit(jit_State *J, const BCIns *endpc, BCReg slot, IRType t) | |||
273 | return 0; /* No assignment to this slot found? */ | 275 | return 0; /* No assignment to this slot found? */ |
274 | } | 276 | } |
275 | 277 | ||
278 | /* Load and optionally convert a FORI argument from a slot. */ | ||
279 | static TRef fori_load(jit_State *J, BCReg slot, IRType t, int mode) | ||
280 | { | ||
281 | int conv = (tvisint(&J->L->base[slot]) != (t==IRT_INT)) ? IRSLOAD_CONVERT : 0; | ||
282 | return sloadt(J, (int32_t)slot, | ||
283 | t + (((mode & IRSLOAD_TYPECHECK) || | ||
284 | (conv && t == IRT_INT && !(mode >> 16))) ? | ||
285 | IRT_GUARD : 0), | ||
286 | mode + conv); | ||
287 | } | ||
288 | |||
276 | /* Peek before FORI to find a const initializer. Otherwise load from slot. */ | 289 | /* Peek before FORI to find a const initializer. Otherwise load from slot. */ |
277 | static TRef fori_arg(jit_State *J, const BCIns *fori, BCReg slot, IRType t) | 290 | static TRef fori_arg(jit_State *J, const BCIns *fori, BCReg slot, |
291 | IRType t, int mode) | ||
278 | { | 292 | { |
279 | TRef tr = J->base[slot]; | 293 | TRef tr = J->base[slot]; |
280 | if (!tr) { | 294 | if (!tr) { |
281 | tr = find_kinit(J, fori, slot, t); | 295 | tr = find_kinit(J, fori, slot, t); |
282 | if (!tr) | 296 | if (!tr) |
283 | tr = sloadt(J, (int32_t)slot, | 297 | tr = fori_load(J, slot, t, mode); |
284 | t == IRT_INT ? (IRT_INT|IRT_GUARD) : t, | ||
285 | t == IRT_INT ? (IRSLOAD_CONVERT|IRSLOAD_READONLY|IRSLOAD_INHERIT) : | ||
286 | (IRSLOAD_READONLY|IRSLOAD_INHERIT)); | ||
287 | } | 298 | } |
288 | return tr; | 299 | return tr; |
289 | } | 300 | } |
290 | 301 | ||
291 | /* In-place coercion of FORI arguments. */ | 302 | /* Return the direction of the FOR loop iterator. |
292 | static lua_Number for_coerce(jit_State *J, TValue *o) | 303 | ** It's important to exactly reproduce the semantics of the interpreter. |
304 | */ | ||
305 | static int rec_for_direction(cTValue *o) | ||
293 | { | 306 | { |
294 | if (!tvisnum(o) && !(tvisstr(o) && lj_str_tonum(strV(o), o))) | 307 | return (tvisint(o) ? intV(o) : (int32_t)o->u32.hi) >= 0; |
295 | lj_trace_err(J, LJ_TRERR_BADTYPE); | ||
296 | return numV(o); | ||
297 | } | 308 | } |
298 | 309 | ||
299 | /* Simulate the runtime behavior of the FOR loop iterator. | 310 | /* Simulate the runtime behavior of the FOR loop iterator. */ |
300 | ** It's important to exactly reproduce the semantics of the interpreter. | 311 | static LoopEvent rec_for_iter(IROp *op, cTValue *o, int isforl) |
301 | */ | ||
302 | static LoopEvent for_iter(jit_State *J, IROp *op, BCReg ra, int isforl) | ||
303 | { | 312 | { |
304 | TValue *forbase = &J->L->base[ra]; | 313 | lua_Number stopv = numberVnum(&o[FORL_STOP]); |
305 | lua_Number stopv = for_coerce(J, &forbase[FORL_STOP]); | 314 | lua_Number idxv = numberVnum(&o[FORL_IDX]); |
306 | lua_Number idxv = for_coerce(J, &forbase[FORL_IDX]); | 315 | lua_Number stepv = numberVnum(&o[FORL_STEP]); |
307 | lua_Number stepv = for_coerce(J, &forbase[FORL_STEP]); | ||
308 | if (isforl) | 316 | if (isforl) |
309 | idxv += stepv; | 317 | idxv += stepv; |
310 | if ((int32_t)forbase[FORL_STEP].u32.hi >= 0) { | 318 | if (rec_for_direction(&o[FORL_STEP])) { |
311 | if (idxv <= stopv) { *op = IR_LE; return LOOPEV_ENTER; } | 319 | if (idxv <= stopv) { *op = IR_LE; return LOOPEV_ENTER; } |
312 | *op = IR_GT; return LOOPEV_LEAVE; | 320 | *op = IR_GT; return LOOPEV_LEAVE; |
313 | } else { | 321 | } else { |
@@ -316,44 +324,123 @@ static LoopEvent for_iter(jit_State *J, IROp *op, BCReg ra, int isforl) | |||
316 | } | 324 | } |
317 | } | 325 | } |
318 | 326 | ||
327 | /* Record checks for FOR loop overflow and step direction. */ | ||
328 | static void rec_for_check(jit_State *J, IRType t, int dir, TRef stop, TRef step) | ||
329 | { | ||
330 | if (!tref_isk(step)) { | ||
331 | /* Non-constant step: need a guard for the direction. */ | ||
332 | TRef zero = (t == IRT_INT) ? lj_ir_kint(J, 0) : lj_ir_knum_zero(J); | ||
333 | emitir(IRTG(dir ? IR_GE : IR_LT, t), step, zero); | ||
334 | /* Add hoistable overflow checks for a narrowed FORL index. */ | ||
335 | if (t == IRT_INT) { | ||
336 | if (tref_isk(stop)) { | ||
337 | /* Constant stop: optimize check away or to a range check for step. */ | ||
338 | int32_t k = IR(tref_ref(stop))->i; | ||
339 | if (dir) { | ||
340 | if (k > 0) | ||
341 | emitir(IRTGI(IR_LE), step, lj_ir_kint(J, (int32_t)0x7fffffff-k)); | ||
342 | } else { | ||
343 | if (k < 0) | ||
344 | emitir(IRTGI(IR_GE), step, lj_ir_kint(J, (int32_t)0x80000000-k)); | ||
345 | } | ||
346 | } else { | ||
347 | /* Stop+step variable: need full overflow check. */ | ||
348 | TRef tr = emitir(IRTGI(IR_ADDOV), step, stop); | ||
349 | emitir(IRTI(IR_USE), tr, 0); /* ADDOV is weak. Avoid dead result. */ | ||
350 | } | ||
351 | } | ||
352 | } else if (t == IRT_INT && !tref_isk(stop)) { | ||
353 | /* Constant step: optimize overflow check to a range check for stop. */ | ||
354 | int32_t k = IR(tref_ref(step))->i; | ||
355 | k = (int32_t)(dir ? 0x7fffffff : 0x80000000) - k; | ||
356 | emitir(IRTGI(dir ? IR_LE : IR_GE), stop, lj_ir_kint(J, k)); | ||
357 | } | ||
358 | } | ||
359 | |||
360 | /* Record a FORL instruction. */ | ||
361 | static void rec_for_loop(jit_State *J, const BCIns *fori, ScEvEntry *scev, | ||
362 | int init) | ||
363 | { | ||
364 | BCReg ra = bc_a(*fori); | ||
365 | cTValue *tv = &J->L->base[ra]; | ||
366 | TRef idx = J->base[ra+FORL_IDX]; | ||
367 | IRType t = idx ? tref_type(idx) : | ||
368 | (init || LJ_DUALNUM) ? lj_opt_narrow_forl(J, tv) : IRT_NUM; | ||
369 | int mode = IRSLOAD_INHERIT + | ||
370 | ((!LJ_DUALNUM || tvisint(tv) == (t == IRT_INT)) ? IRSLOAD_READONLY : 0); | ||
371 | TRef stop = fori_arg(J, fori, ra+FORL_STOP, t, mode); | ||
372 | TRef step = fori_arg(J, fori, ra+FORL_STEP, t, mode); | ||
373 | int tc, dir = rec_for_direction(&tv[FORL_STEP]); | ||
374 | lua_assert(bc_op(*fori) == BC_FORI || bc_op(*fori) == BC_JFORI); | ||
375 | scev->t.irt = t; | ||
376 | scev->dir = dir; | ||
377 | scev->stop = tref_ref(stop); | ||
378 | scev->step = tref_ref(step); | ||
379 | if (init) | ||
380 | rec_for_check(J, t, dir, stop, step); | ||
381 | scev->start = tref_ref(find_kinit(J, fori, ra+FORL_IDX, IRT_INT)); | ||
382 | tc = (LJ_DUALNUM && | ||
383 | !(scev->start && irref_isk(scev->stop) && irref_isk(scev->step))) ? | ||
384 | IRSLOAD_TYPECHECK : 0; | ||
385 | if (tc) { | ||
386 | J->base[ra+FORL_STOP] = stop; | ||
387 | J->base[ra+FORL_STEP] = step; | ||
388 | } | ||
389 | if (!idx) | ||
390 | idx = fori_load(J, ra+FORL_IDX, t, | ||
391 | IRSLOAD_INHERIT + tc + (J->scev.start << 16)); | ||
392 | if (!init) | ||
393 | J->base[ra+FORL_IDX] = idx = emitir(IRT(IR_ADD, t), idx, step); | ||
394 | J->base[ra+FORL_EXT] = idx; | ||
395 | scev->idx = tref_ref(idx); | ||
396 | J->maxslot = ra+FORL_EXT+1; | ||
397 | } | ||
398 | |||
319 | /* Record FORL/JFORL or FORI/JFORI. */ | 399 | /* Record FORL/JFORL or FORI/JFORI. */ |
320 | static LoopEvent rec_for(jit_State *J, const BCIns *fori, int isforl) | 400 | static LoopEvent rec_for(jit_State *J, const BCIns *fori, int isforl) |
321 | { | 401 | { |
322 | BCReg ra = bc_a(*fori); | 402 | BCReg ra = bc_a(*fori); |
323 | IROp op; | 403 | TValue *tv = &J->L->base[ra]; |
324 | LoopEvent ev = for_iter(J, &op, ra, isforl); | ||
325 | TRef *tr = &J->base[ra]; | 404 | TRef *tr = &J->base[ra]; |
326 | TRef idx, stop; | 405 | IROp op; |
406 | LoopEvent ev; | ||
407 | TRef stop; | ||
327 | IRType t; | 408 | IRType t; |
328 | if (isforl) { /* Handle FORL/JFORL opcodes. */ | 409 | if (isforl) { /* Handle FORL/JFORL opcodes. */ |
329 | TRef step; | 410 | TRef idx = tr[FORL_IDX]; |
330 | idx = tr[FORL_IDX]; | ||
331 | if (tref_ref(idx) == J->scev.idx) { | 411 | if (tref_ref(idx) == J->scev.idx) { |
332 | t = J->scev.t.irt; | 412 | t = J->scev.t.irt; |
333 | stop = J->scev.stop; | 413 | stop = J->scev.stop; |
334 | step = J->scev.step; | 414 | idx = emitir(IRT(IR_ADD, t), idx, J->scev.step); |
415 | tr[FORL_EXT] = tr[FORL_IDX] = idx; | ||
335 | } else { | 416 | } else { |
336 | if (!idx) idx = sloadt(J, (int32_t)(ra+FORL_IDX), IRT_NUM, 0); | 417 | ScEvEntry scev; |
337 | t = tref_type(idx); | 418 | rec_for_loop(J, fori, &scev, 0); |
338 | stop = fori_arg(J, fori, ra+FORL_STOP, t); | 419 | t = scev.t.irt; |
339 | step = fori_arg(J, fori, ra+FORL_STEP, t); | 420 | stop = scev.stop; |
340 | } | 421 | } |
341 | tr[FORL_IDX] = idx = emitir(IRT(IR_ADD, t), idx, step); | ||
342 | } else { /* Handle FORI/JFORI opcodes. */ | 422 | } else { /* Handle FORI/JFORI opcodes. */ |
343 | BCReg i; | 423 | BCReg i; |
344 | t = IRT_NUM; | 424 | lj_meta_for(J->L, tv); |
425 | t = lj_opt_narrow_forl(J, tv); | ||
345 | for (i = FORL_IDX; i <= FORL_STEP; i++) { | 426 | for (i = FORL_IDX; i <= FORL_STEP; i++) { |
346 | lua_assert(J->base[ra+i] != 0); /* Assumes the slots are already set. */ | 427 | lua_assert(tref_isnumber_str(tr[i])); |
347 | tr[i] = lj_ir_tonum(J, J->base[ra+i]); | 428 | if (tref_isstr(tr[i])) |
429 | tr[i] = emitir(IRTG(IR_STRTO, IRT_NUM), tr[i], 0); | ||
430 | if (t == IRT_INT) { | ||
431 | if (!tref_isinteger(tr[i])) | ||
432 | tr[i] = emitir(IRTI(IR_CONV), tr[i], IRCONV_INT_NUM|IRCONV_CHECK); | ||
433 | } else { | ||
434 | if (!tref_isnum(tr[i])) | ||
435 | tr[i] = emitir(IRTN(IR_CONV), tr[i], IRCONV_NUM_INT); | ||
436 | } | ||
348 | } | 437 | } |
349 | idx = tr[FORL_IDX]; | 438 | tr[FORL_EXT] = tr[FORL_IDX]; |
350 | stop = tr[FORL_STOP]; | 439 | stop = tr[FORL_STOP]; |
351 | if (!tref_isk(tr[FORL_STEP])) /* Non-const step: need direction guard. */ | 440 | rec_for_check(J, t, rec_for_direction(&tv[FORL_STEP]), stop, tr[FORL_STEP]); |
352 | emitir(IRTG(((op-IR_LT)>>1)+IR_LT, IRT_NUM), | ||
353 | tr[FORL_STEP], lj_ir_knum_zero(J)); | ||
354 | } | 441 | } |
355 | 442 | ||
356 | tr[FORL_EXT] = idx; | 443 | ev = rec_for_iter(&op, tv, isforl); |
357 | if (ev == LOOPEV_LEAVE) { | 444 | if (ev == LOOPEV_LEAVE) { |
358 | J->maxslot = ra+FORL_EXT+1; | 445 | J->maxslot = ra+FORL_EXT+1; |
359 | J->pc = fori+1; | 446 | J->pc = fori+1; |
@@ -363,7 +450,7 @@ static LoopEvent rec_for(jit_State *J, const BCIns *fori, int isforl) | |||
363 | } | 450 | } |
364 | lj_snap_add(J); | 451 | lj_snap_add(J); |
365 | 452 | ||
366 | emitir(IRTG(op, t), idx, stop); | 453 | emitir(IRTG(op, t), tr[FORL_IDX], stop); |
367 | 454 | ||
368 | if (ev == LOOPEV_LEAVE) { | 455 | if (ev == LOOPEV_LEAVE) { |
369 | J->maxslot = ra; | 456 | J->maxslot = ra; |
@@ -870,7 +957,7 @@ static void rec_idx_abc(jit_State *J, TRef asizeref, TRef ikey, uint32_t asize) | |||
870 | if (ref == J->scev.idx) { | 957 | if (ref == J->scev.idx) { |
871 | int32_t stop; | 958 | int32_t stop; |
872 | lua_assert(irt_isint(J->scev.t) && ir->o == IR_SLOAD); | 959 | lua_assert(irt_isint(J->scev.t) && ir->o == IR_SLOAD); |
873 | stop = lj_num2int(numV(&(J->L->base - J->baseslot)[ir->op1 + FORL_STOP])); | 960 | stop = numberVint(&(J->L->base - J->baseslot)[ir->op1 + FORL_STOP]); |
874 | /* Runtime value for stop of loop is within bounds? */ | 961 | /* Runtime value for stop of loop is within bounds? */ |
875 | if ((int64_t)stop + ofs < (int64_t)asize) { | 962 | if ((int64_t)stop + ofs < (int64_t)asize) { |
876 | /* Emit invariant bounds check for stop. */ | 963 | /* Emit invariant bounds check for stop. */ |
@@ -897,15 +984,12 @@ static TRef rec_idx_key(jit_State *J, RecordIndex *ix) | |||
897 | /* Integer keys are looked up in the array part first. */ | 984 | /* Integer keys are looked up in the array part first. */ |
898 | key = ix->key; | 985 | key = ix->key; |
899 | if (tref_isnumber(key)) { | 986 | if (tref_isnumber(key)) { |
900 | lua_Number n = numV(&ix->keyv); | 987 | int32_t k = numberVint(&ix->keyv); |
901 | int32_t k = lj_num2int(n); | 988 | if (!tvisint(&ix->keyv) && numV(&ix->keyv) != (lua_Number)k) |
902 | lua_assert(tvisnum(&ix->keyv)); | 989 | k = LJ_MAX_ASIZE; |
903 | /* Potential array key? */ | 990 | if ((MSize)k < LJ_MAX_ASIZE) { /* Potential array key? */ |
904 | if ((MSize)k < LJ_MAX_ASIZE && n == cast_num(k)) { | 991 | TRef ikey = lj_opt_narrow_index(J, key); |
905 | TRef asizeref, ikey = key; | 992 | TRef asizeref = emitir(IRTI(IR_FLOAD), ix->tab, IRFL_TAB_ASIZE); |
906 | if (!tref_isinteger(ikey)) | ||
907 | ikey = emitir(IRTGI(IR_CONV), ikey, IRCONV_INT_NUM|IRCONV_INDEX); | ||
908 | asizeref = emitir(IRTI(IR_FLOAD), ix->tab, IRFL_TAB_ASIZE); | ||
909 | if ((MSize)k < t->asize) { /* Currently an array key? */ | 993 | if ((MSize)k < t->asize) { /* Currently an array key? */ |
910 | TRef arrayref; | 994 | TRef arrayref; |
911 | rec_idx_abc(J, asizeref, ikey, t->asize); | 995 | rec_idx_abc(J, asizeref, ikey, t->asize); |
@@ -1081,7 +1165,8 @@ TRef lj_record_idx(jit_State *J, RecordIndex *ix) | |||
1081 | } else { | 1165 | } else { |
1082 | keybarrier = 0; /* Previous non-nil value kept the key alive. */ | 1166 | keybarrier = 0; /* Previous non-nil value kept the key alive. */ |
1083 | } | 1167 | } |
1084 | if (tref_isinteger(ix->val)) /* Convert int to number before storing. */ | 1168 | /* Convert int to number before storing. */ |
1169 | if (!LJ_DUALNUM && tref_isinteger(ix->val)) | ||
1085 | ix->val = emitir(IRTN(IR_CONV), ix->val, IRCONV_NUM_INT); | 1170 | ix->val = emitir(IRTN(IR_CONV), ix->val, IRCONV_NUM_INT); |
1086 | emitir(IRT(loadop+IRDELTA_L2S, tref_type(ix->val)), xref, ix->val); | 1171 | emitir(IRT(loadop+IRDELTA_L2S, tref_type(ix->val)), xref, ix->val); |
1087 | if (keybarrier || tref_isgcv(ix->val)) | 1172 | if (keybarrier || tref_isgcv(ix->val)) |
@@ -1135,7 +1220,8 @@ static TRef rec_upvalue(jit_State *J, uint32_t uv, TRef val) | |||
1135 | if (irtype_ispri(t)) res = TREF_PRI(t); /* Canonicalize primitive refs. */ | 1220 | if (irtype_ispri(t)) res = TREF_PRI(t); /* Canonicalize primitive refs. */ |
1136 | return res; | 1221 | return res; |
1137 | } else { /* Upvalue store. */ | 1222 | } else { /* Upvalue store. */ |
1138 | if (tref_isinteger(val)) /* Convert int to number before storing. */ | 1223 | /* Convert int to number before storing. */ |
1224 | if (!LJ_DUALNUM && tref_isinteger(val)) | ||
1139 | val = emitir(IRTN(IR_CONV), val, IRCONV_NUM_INT); | 1225 | val = emitir(IRTN(IR_CONV), val, IRCONV_NUM_INT); |
1140 | emitir(IRT(IR_USTORE, tref_type(val)), uref, val); | 1226 | emitir(IRT(IR_USTORE, tref_type(val)), uref, val); |
1141 | if (needbarrier && tref_isgcv(val)) | 1227 | if (needbarrier && tref_isgcv(val)) |
@@ -1455,16 +1541,15 @@ void lj_record_ins(jit_State *J) | |||
1455 | case BCMnone: rb = 0; rc = bc_d(ins); break; /* Upgrade rc to 'rd'. */ | 1541 | case BCMnone: rb = 0; rc = bc_d(ins); break; /* Upgrade rc to 'rd'. */ |
1456 | case BCMvar: | 1542 | case BCMvar: |
1457 | copyTV(J->L, rbv, &lbase[rb]); ix.tab = rb = getslot(J, rb); break; | 1543 | copyTV(J->L, rbv, &lbase[rb]); ix.tab = rb = getslot(J, rb); break; |
1458 | case BCMnum: { lua_Number n = proto_knum(J->pt, rb); | ||
1459 | setnumV(rbv, n); ix.tab = rb = lj_ir_knumint(J, n); } break; | ||
1460 | default: break; /* Handled later. */ | 1544 | default: break; /* Handled later. */ |
1461 | } | 1545 | } |
1462 | switch (bcmode_c(op)) { | 1546 | switch (bcmode_c(op)) { |
1463 | case BCMvar: | 1547 | case BCMvar: |
1464 | copyTV(J->L, rcv, &lbase[rc]); ix.key = rc = getslot(J, rc); break; | 1548 | copyTV(J->L, rcv, &lbase[rc]); ix.key = rc = getslot(J, rc); break; |
1465 | case BCMpri: setitype(rcv, ~rc); ix.key = rc = TREF_PRI(IRT_NIL+rc); break; | 1549 | case BCMpri: setitype(rcv, ~rc); ix.key = rc = TREF_PRI(IRT_NIL+rc); break; |
1466 | case BCMnum: { lua_Number n = proto_knum(J->pt, rc); | 1550 | case BCMnum: { cTValue *tv = proto_knumtv(J->pt, rc); |
1467 | setnumV(rcv, n); ix.key = rc = lj_ir_knumint(J, n); } break; | 1551 | copyTV(J->L, rcv, tv); ix.key = rc = tvisint(tv) ? lj_ir_kint(J, intV(tv)) : |
1552 | lj_ir_knumint(J, numV(tv)); } break; | ||
1468 | case BCMstr: { GCstr *s = gco2str(proto_kgc(J->pt, ~(ptrdiff_t)rc)); | 1553 | case BCMstr: { GCstr *s = gco2str(proto_kgc(J->pt, ~(ptrdiff_t)rc)); |
1469 | setstrV(J->L, rcv, s); ix.key = rc = lj_ir_kstr(J, s); } break; | 1554 | setstrV(J->L, rcv, s); ix.key = rc = lj_ir_kstr(J, s); } break; |
1470 | default: break; /* Handled later. */ | 1555 | default: break; /* Handled later. */ |
@@ -1502,9 +1587,11 @@ void lj_record_ins(jit_State *J) | |||
1502 | irop = (int)op - (int)BC_ISLT + (int)IR_LT; | 1587 | irop = (int)op - (int)BC_ISLT + (int)IR_LT; |
1503 | if (ta == IRT_NUM) { | 1588 | if (ta == IRT_NUM) { |
1504 | if ((irop & 1)) irop ^= 4; /* ISGE/ISGT are unordered. */ | 1589 | if ((irop & 1)) irop ^= 4; /* ISGE/ISGT are unordered. */ |
1505 | if (!lj_ir_numcmp(numV(rav), numV(rcv), (IROp)irop)) irop ^= 5; | 1590 | if (!lj_ir_numcmp(numberVnum(rav), numberVnum(rcv), (IROp)irop)) |
1591 | irop ^= 5; | ||
1506 | } else if (ta == IRT_INT) { | 1592 | } else if (ta == IRT_INT) { |
1507 | if (!lj_ir_numcmp(numV(rav), numV(rcv), (IROp)irop)) irop ^= 1; | 1593 | if (!lj_ir_numcmp(numberVnum(rav), numberVnum(rcv), (IROp)irop)) |
1594 | irop ^= 1; | ||
1508 | } else if (ta == IRT_STR) { | 1595 | } else if (ta == IRT_STR) { |
1509 | if (!lj_ir_strcmp(strV(rav), strV(rcv), (IROp)irop)) irop ^= 1; | 1596 | if (!lj_ir_strcmp(strV(rav), strV(rcv), (IROp)irop)) irop ^= 1; |
1510 | ra = lj_ir_call(J, IRCALL_lj_str_cmp, ra, rc); | 1597 | ra = lj_ir_call(J, IRCALL_lj_str_cmp, ra, rc); |
@@ -1599,13 +1686,11 @@ void lj_record_ins(jit_State *J) | |||
1599 | case BC_ADDVN: case BC_SUBVN: case BC_MULVN: case BC_DIVVN: | 1686 | case BC_ADDVN: case BC_SUBVN: case BC_MULVN: case BC_DIVVN: |
1600 | case BC_ADDVV: case BC_SUBVV: case BC_MULVV: case BC_DIVVV: { | 1687 | case BC_ADDVV: case BC_SUBVV: case BC_MULVV: case BC_DIVVV: { |
1601 | MMS mm = bcmode_mm(op); | 1688 | MMS mm = bcmode_mm(op); |
1602 | if (tref_isnumber_str(rb) && tref_isnumber_str(rc)) { | 1689 | if (tref_isnumber_str(rb) && tref_isnumber_str(rc)) |
1603 | rb = lj_ir_tonum(J, rb); | 1690 | rc = lj_opt_narrow_arith(J, rb, rc, &ix.tabv, &ix.keyv, |
1604 | rc = lj_ir_tonum(J, rc); | 1691 | (int)mm - (int)MM_add + (int)IR_ADD); |
1605 | rc = emitir(IRTN((int)mm - (int)MM_add + (int)IR_ADD), rb, rc); | 1692 | else |
1606 | } else { | ||
1607 | rc = rec_mm_arith(J, &ix, mm); | 1693 | rc = rec_mm_arith(J, &ix, mm); |
1608 | } | ||
1609 | break; | 1694 | break; |
1610 | } | 1695 | } |
1611 | 1696 | ||
@@ -1827,59 +1912,6 @@ void lj_record_ins(jit_State *J) | |||
1827 | 1912 | ||
1828 | /* -- Recording setup ----------------------------------------------------- */ | 1913 | /* -- Recording setup ----------------------------------------------------- */ |
1829 | 1914 | ||
1830 | /* Setup recording for a FORL loop. */ | ||
1831 | static void rec_setup_forl(jit_State *J, const BCIns *fori) | ||
1832 | { | ||
1833 | BCReg ra = bc_a(*fori); | ||
1834 | cTValue *forbase = &J->L->base[ra]; | ||
1835 | IRType t = (J->flags & JIT_F_OPT_NARROW) ? lj_opt_narrow_forl(forbase) | ||
1836 | : IRT_NUM; | ||
1837 | TRef start; | ||
1838 | TRef stop = fori_arg(J, fori, ra+FORL_STOP, t); | ||
1839 | TRef step = fori_arg(J, fori, ra+FORL_STEP, t); | ||
1840 | int dir = (0 <= numV(&forbase[FORL_STEP])); | ||
1841 | lua_assert(bc_op(*fori) == BC_FORI || bc_op(*fori) == BC_JFORI); | ||
1842 | J->scev.t.irt = t; | ||
1843 | J->scev.dir = dir; | ||
1844 | J->scev.stop = tref_ref(stop); | ||
1845 | J->scev.step = tref_ref(step); | ||
1846 | if (!tref_isk(step)) { | ||
1847 | /* Non-constant step: need a guard for the direction. */ | ||
1848 | TRef zero = (t == IRT_INT) ? lj_ir_kint(J, 0) : lj_ir_knum_zero(J); | ||
1849 | emitir(IRTG(dir ? IR_GE : IR_LT, t), step, zero); | ||
1850 | /* Add hoistable overflow checks for a narrowed FORL index. */ | ||
1851 | if (t == IRT_INT) { | ||
1852 | if (tref_isk(stop)) { | ||
1853 | /* Constant stop: optimize check away or to a range check for step. */ | ||
1854 | int32_t k = IR(tref_ref(stop))->i; | ||
1855 | if (dir) { | ||
1856 | if (k > 0) | ||
1857 | emitir(IRTGI(IR_LE), step, lj_ir_kint(J, (int32_t)0x7fffffff-k)); | ||
1858 | } else { | ||
1859 | if (k < 0) | ||
1860 | emitir(IRTGI(IR_GE), step, lj_ir_kint(J, (int32_t)0x80000000-k)); | ||
1861 | } | ||
1862 | } else { | ||
1863 | /* Stop+step variable: need full overflow check. */ | ||
1864 | TRef tr = emitir(IRTGI(IR_ADDOV), step, stop); | ||
1865 | emitir(IRTI(IR_USE), tr, 0); /* ADDOV is weak. Avoid dead result. */ | ||
1866 | } | ||
1867 | } | ||
1868 | } else if (t == IRT_INT && !tref_isk(stop)) { | ||
1869 | /* Constant step: optimize overflow check to a range check for stop. */ | ||
1870 | int32_t k = IR(tref_ref(step))->i; | ||
1871 | k = (int32_t)(dir ? 0x7fffffff : 0x80000000) - k; | ||
1872 | emitir(IRTGI(dir ? IR_LE : IR_GE), stop, lj_ir_kint(J, k)); | ||
1873 | } | ||
1874 | J->scev.start = tref_ref(find_kinit(J, fori, ra+FORL_IDX, IRT_INT)); | ||
1875 | start = sloadt(J, (int32_t)(ra+FORL_IDX), | ||
1876 | (t == IRT_INT && !J->scev.start) ? (IRT_INT|IRT_GUARD) : t, | ||
1877 | t == IRT_INT ? (IRSLOAD_CONVERT|IRSLOAD_INHERIT) : IRSLOAD_INHERIT); | ||
1878 | J->base[ra+FORL_EXT] = start; | ||
1879 | J->scev.idx = tref_ref(start); | ||
1880 | J->maxslot = ra+FORL_EXT+1; | ||
1881 | } | ||
1882 | |||
1883 | /* Setup recording for a root trace started by a hot loop. */ | 1915 | /* Setup recording for a root trace started by a hot loop. */ |
1884 | static const BCIns *rec_setup_root(jit_State *J) | 1916 | static const BCIns *rec_setup_root(jit_State *J) |
1885 | { | 1917 | { |
@@ -2033,7 +2065,7 @@ void lj_record_setup(jit_State *J) | |||
2033 | if (J->pc > proto_bc(J->pt) && bc_op(J->pc[-1]) == BC_JFORI && | 2065 | if (J->pc > proto_bc(J->pt) && bc_op(J->pc[-1]) == BC_JFORI && |
2034 | bc_d(J->pc[bc_j(J->pc[-1])-1]) == root) { | 2066 | bc_d(J->pc[bc_j(J->pc[-1])-1]) == root) { |
2035 | lj_snap_add(J); | 2067 | lj_snap_add(J); |
2036 | rec_setup_forl(J, J->pc-1); | 2068 | rec_for_loop(J, J->pc-1, &J->scev, 1); |
2037 | goto sidecheck; | 2069 | goto sidecheck; |
2038 | } | 2070 | } |
2039 | } else { | 2071 | } else { |
@@ -2054,7 +2086,7 @@ void lj_record_setup(jit_State *J) | |||
2054 | */ | 2086 | */ |
2055 | lj_snap_add(J); | 2087 | lj_snap_add(J); |
2056 | if (bc_op(J->cur.startins) == BC_FORL) | 2088 | if (bc_op(J->cur.startins) == BC_FORL) |
2057 | rec_setup_forl(J, J->pc-1); | 2089 | rec_for_loop(J, J->pc-1, &J->scev, 1); |
2058 | if (1 + J->pt->framesize >= LJ_MAX_JSLOTS) | 2090 | if (1 + J->pt->framesize >= LJ_MAX_JSLOTS) |
2059 | lj_trace_err(J, LJ_TRERR_STACKOV); | 2091 | lj_trace_err(J, LJ_TRERR_STACKOV); |
2060 | } | 2092 | } |