aboutsummaryrefslogtreecommitdiff
path: root/src/lj_record.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/lj_record.c130
1 files changed, 125 insertions, 5 deletions
diff --git a/src/lj_record.c b/src/lj_record.c
index a1471aae..e51c98ba 100644
--- a/src/lj_record.c
+++ b/src/lj_record.c
@@ -156,6 +156,9 @@ static void rec_check_slots(jit_State *J)
156 lj_assertJ((J->slot[s+1+LJ_FR2] & TREF_FRAME), 156 lj_assertJ((J->slot[s+1+LJ_FR2] & TREF_FRAME),
157 "cont slot %d not followed by frame", s); 157 "cont slot %d not followed by frame", s);
158 depth++; 158 depth++;
159 } else if ((tr & TREF_KEYINDEX)) {
160 lj_assertJ(tref_isint(tr), "keyindex slot %d bad type %d",
161 s, tref_type(tr));
159 } else { 162 } else {
160 /* Number repr. may differ, but other types must be the same. */ 163 /* Number repr. may differ, but other types must be the same. */
161 lj_assertJ(tvisnumber(tv) ? tref_isnumber(tr) : 164 lj_assertJ(tvisnumber(tv) ? tref_isnumber(tr) :
@@ -283,9 +286,9 @@ static void canonicalize_slots(jit_State *J)
283 if (LJ_DUALNUM) return; 286 if (LJ_DUALNUM) return;
284 for (s = J->baseslot+J->maxslot-1; s >= 1; s--) { 287 for (s = J->baseslot+J->maxslot-1; s >= 1; s--) {
285 TRef tr = J->slot[s]; 288 TRef tr = J->slot[s];
286 if (tref_isinteger(tr)) { 289 if (tref_isinteger(tr) && !(tr & TREF_KEYINDEX)) {
287 IRIns *ir = IR(tref_ref(tr)); 290 IRIns *ir = IR(tref_ref(tr));
288 if (!(ir->o == IR_SLOAD && (ir->op2 & IRSLOAD_READONLY))) 291 if (!(ir->o == IR_SLOAD && (ir->op2 & (IRSLOAD_READONLY))))
289 J->slot[s] = emitir(IRTN(IR_CONV), tr, IRCONV_NUM_INT); 292 J->slot[s] = emitir(IRTN(IR_CONV), tr, IRCONV_NUM_INT);
290 } 293 }
291 } 294 }
@@ -606,6 +609,7 @@ static void rec_loop_interp(jit_State *J, const BCIns *pc, LoopEvent ev)
606{ 609{
607 if (J->parent == 0 && J->exitno == 0) { 610 if (J->parent == 0 && J->exitno == 0) {
608 if (pc == J->startpc && J->framedepth + J->retdepth == 0) { 611 if (pc == J->startpc && J->framedepth + J->retdepth == 0) {
612 if (bc_op(J->cur.startins) == BC_ITERN) return; /* See rec_itern(). */
609 /* Same loop? */ 613 /* Same loop? */
610 if (ev == LOOPEV_LEAVE) /* Must loop back to form a root trace. */ 614 if (ev == LOOPEV_LEAVE) /* Must loop back to form a root trace. */
611 lj_trace_err(J, LJ_TRERR_LLEAVE); 615 lj_trace_err(J, LJ_TRERR_LLEAVE);
@@ -646,6 +650,68 @@ static void rec_loop_jit(jit_State *J, TraceNo lnk, LoopEvent ev)
646 } /* Side trace continues across a loop that's left or not entered. */ 650 } /* Side trace continues across a loop that's left or not entered. */
647} 651}
648 652
653/* Record ITERN. */
654static LoopEvent rec_itern(jit_State *J, BCReg ra, BCReg rb)
655{
656#if LJ_BE
657 /* YAGNI: Disabled on big-endian due to issues with lj_vm_next,
658 ** IR_HIOP, RID_RETLO/RID_RETHI and ra_destpair.
659 */
660 UNUSED(ra); UNUSED(rb);
661 setintV(&J->errinfo, (int32_t)BC_ITERN);
662 lj_trace_err_info(J, LJ_TRERR_NYIBC);
663#else
664 RecordIndex ix;
665 /* Since ITERN is recorded at the start, we need our own loop detection. */
666 if (J->pc == J->startpc && J->cur.nins > REF_FIRST &&
667 J->framedepth + J->retdepth == 0 && J->parent == 0 && J->exitno == 0) {
668 lj_record_stop(J, LJ_TRLINK_LOOP, J->cur.traceno); /* Looping trace. */
669 return LOOPEV_ENTER;
670 }
671 J->maxslot = ra;
672 lj_snap_add(J); /* Required to make JLOOP the first ins in a side-trace. */
673 ix.tab = getslot(J, ra-2);
674 ix.key = J->base[ra-1] ? J->base[ra-1] :
675 sloadt(J, (int32_t)(ra-1), IRT_INT, IRSLOAD_KEYINDEX);
676 copyTV(J->L, &ix.tabv, &J->L->base[ra-2]);
677 copyTV(J->L, &ix.keyv, &J->L->base[ra-1]);
678 ix.idxchain = (rb < 3); /* Omit value type check, if unused. */
679 ix.mobj = 1; /* We need the next index, too. */
680 J->maxslot = ra + lj_record_next(J, &ix);
681 J->needsnap = 1;
682 if (!tref_isnil(ix.key)) { /* Looping back? */
683 J->base[ra-1] = ix.mobj | TREF_KEYINDEX; /* Control var has next index. */
684 J->base[ra] = ix.key;
685 J->base[ra+1] = ix.val;
686 J->pc += bc_j(J->pc[1])+2;
687 return LOOPEV_ENTER;
688 } else {
689 J->maxslot = ra-3;
690 J->pc += 2;
691 return LOOPEV_LEAVE;
692 }
693#endif
694}
695
696/* Record ISNEXT. */
697static void rec_isnext(jit_State *J, BCReg ra)
698{
699 cTValue *b = &J->L->base[ra-3];
700 if (tvisfunc(b) && funcV(b)->c.ffid == FF_next &&
701 tvistab(b+1) && tvisnil(b+2)) {
702 /* These checks are folded away for a compiled pairs(). */
703 TRef func = getslot(J, ra-3);
704 TRef trid = emitir(IRT(IR_FLOAD, IRT_U8), func, IRFL_FUNC_FFID);
705 emitir(IRTGI(IR_EQ), trid, lj_ir_kint(J, FF_next));
706 (void)getslot(J, ra-2); /* Type check for table. */
707 (void)getslot(J, ra-1); /* Type check for nil key. */
708 J->base[ra-1] = lj_ir_kint(J, 0) | TREF_KEYINDEX;
709 J->maxslot = ra;
710 } else { /* Abort trace. Interpreter will despecialize bytecode. */
711 lj_trace_err(J, LJ_TRERR_RECERR);
712 }
713}
714
649/* -- Record profiler hook checks ----------------------------------------- */ 715/* -- Record profiler hook checks ----------------------------------------- */
650 716
651#if LJ_HASPROFILE 717#if LJ_HASPROFILE
@@ -716,7 +782,7 @@ static TRef rec_call_specialize(jit_State *J, GCfunc *fn, TRef tr)
716 /* NYI: io_file_iter doesn't have an ffid, yet. */ 782 /* NYI: io_file_iter doesn't have an ffid, yet. */
717 { /* Specialize to the ffid. */ 783 { /* Specialize to the ffid. */
718 TRef trid = emitir(IRT(IR_FLOAD, IRT_U8), tr, IRFL_FUNC_FFID); 784 TRef trid = emitir(IRT(IR_FLOAD, IRT_U8), tr, IRFL_FUNC_FFID);
719 emitir(IRTG(IR_EQ, IRT_INT), trid, lj_ir_kint(J, fn->c.ffid)); 785 emitir(IRTGI(IR_EQ), trid, lj_ir_kint(J, fn->c.ffid));
720 } 786 }
721 return tr; 787 return tr;
722 default: 788 default:
@@ -1565,6 +1631,47 @@ TRef lj_record_idx(jit_State *J, RecordIndex *ix)
1565 } 1631 }
1566} 1632}
1567 1633
1634/* Determine result type of table traversal. */
1635static IRType rec_next_types(GCtab *t, uint32_t idx)
1636{
1637 for (; idx < t->asize; idx++) {
1638 cTValue *a = arrayslot(t, idx);
1639 if (LJ_LIKELY(!tvisnil(a)))
1640 return (LJ_DUALNUM ? IRT_INT : IRT_NUM) + (itype2irt(a) << 8);
1641 }
1642 idx -= t->asize;
1643 for (; idx <= t->hmask; idx++) {
1644 Node *n = &noderef(t->node)[idx];
1645 if (!tvisnil(&n->val))
1646 return itype2irt(&n->key) + (itype2irt(&n->val) << 8);
1647 }
1648 return IRT_NIL + (IRT_NIL << 8);
1649}
1650
1651/* Record a table traversal step aka next(). */
1652int lj_record_next(jit_State *J, RecordIndex *ix)
1653{
1654 IRType t, tkey, tval;
1655 TRef trvk;
1656 t = rec_next_types(tabV(&ix->tabv), ix->keyv.u32.lo);
1657 tkey = (t & 0xff); tval = (t >> 8);
1658 trvk = lj_ir_call(J, IRCALL_lj_vm_next, ix->tab, ix->key);
1659 if (ix->mobj || tkey == IRT_NIL) {
1660 TRef idx = emitir(IRTI(IR_HIOP), trvk, trvk);
1661 /* Always check for invalid key from next() for nil result. */
1662 if (!ix->mobj) emitir(IRTGI(IR_NE), idx, lj_ir_kint(J, -1));
1663 ix->mobj = idx;
1664 }
1665 ix->key = lj_record_vload(J, trvk, 1, tkey);
1666 if (tkey == IRT_NIL || ix->idxchain) { /* Omit value type check. */
1667 ix->val = TREF_NIL;
1668 return 1;
1669 } else { /* Need value. */
1670 ix->val = lj_record_vload(J, trvk, 0, tval);
1671 return 2;
1672 }
1673}
1674
1568static void rec_tsetm(jit_State *J, BCReg ra, BCReg rn, int32_t i) 1675static void rec_tsetm(jit_State *J, BCReg ra, BCReg rn, int32_t i)
1569{ 1676{
1570 RecordIndex ix; 1677 RecordIndex ix;
@@ -2440,6 +2547,9 @@ void lj_record_ins(jit_State *J)
2440 case BC_ITERL: 2547 case BC_ITERL:
2441 rec_loop_interp(J, pc, rec_iterl(J, *pc)); 2548 rec_loop_interp(J, pc, rec_iterl(J, *pc));
2442 break; 2549 break;
2550 case BC_ITERN:
2551 rec_loop_interp(J, pc, rec_itern(J, ra, rb));
2552 break;
2443 case BC_LOOP: 2553 case BC_LOOP:
2444 rec_loop_interp(J, pc, rec_loop(J, ra, 1)); 2554 rec_loop_interp(J, pc, rec_loop(J, ra, 1));
2445 break; 2555 break;
@@ -2468,6 +2578,10 @@ void lj_record_ins(jit_State *J)
2468 J->maxslot = ra; /* Shrink used slots. */ 2578 J->maxslot = ra; /* Shrink used slots. */
2469 break; 2579 break;
2470 2580
2581 case BC_ISNEXT:
2582 rec_isnext(J, ra);
2583 break;
2584
2471 /* -- Function headers -------------------------------------------------- */ 2585 /* -- Function headers -------------------------------------------------- */
2472 2586
2473 case BC_FUNCF: 2587 case BC_FUNCF:
@@ -2497,8 +2611,6 @@ void lj_record_ins(jit_State *J)
2497 break; 2611 break;
2498 } 2612 }
2499 /* fallthrough */ 2613 /* fallthrough */
2500 case BC_ITERN:
2501 case BC_ISNEXT:
2502 case BC_UCLO: 2614 case BC_UCLO:
2503 case BC_FNEW: 2615 case BC_FNEW:
2504 setintV(&J->errinfo, (int32_t)op); 2616 setintV(&J->errinfo, (int32_t)op);
@@ -2550,6 +2662,13 @@ static const BCIns *rec_setup_root(jit_State *J)
2550 lj_assertJ(bc_op(pc[-1]) == BC_JMP, "ITERL does not point to JMP+1"); 2662 lj_assertJ(bc_op(pc[-1]) == BC_JMP, "ITERL does not point to JMP+1");
2551 J->bc_min = pc; 2663 J->bc_min = pc;
2552 break; 2664 break;
2665 case BC_ITERN:
2666 lj_assertJ(bc_op(pc[1]) == BC_ITERL, "no ITERL after ITERN");
2667 J->maxslot = ra;
2668 J->bc_extent = (MSize)(-bc_j(pc[1]))*sizeof(BCIns);
2669 J->bc_min = pc+2 + bc_j(pc[1]);
2670 J->state = LJ_TRACE_RECORD_1ST; /* Record the first ITERN, too. */
2671 break;
2553 case BC_LOOP: 2672 case BC_LOOP:
2554 /* Only check BC range for real loops, but not for "repeat until true". */ 2673 /* Only check BC range for real loops, but not for "repeat until true". */
2555 pcj = pc + bc_j(ins); 2674 pcj = pc + bc_j(ins);
@@ -2657,6 +2776,7 @@ void lj_record_setup(jit_State *J)
2657 J->pc = rec_setup_root(J); 2776 J->pc = rec_setup_root(J);
2658 /* Note: the loop instruction itself is recorded at the end and not 2777 /* Note: the loop instruction itself is recorded at the end and not
2659 ** at the start! So snapshot #0 needs to point to the *next* instruction. 2778 ** at the start! So snapshot #0 needs to point to the *next* instruction.
2779 ** The one exception is BC_ITERN, which sets LJ_TRACE_RECORD_1ST.
2660 */ 2780 */
2661 lj_snap_add(J); 2781 lj_snap_add(J);
2662 if (bc_op(J->cur.startins) == BC_FORL) 2782 if (bc_op(J->cur.startins) == BC_FORL)