aboutsummaryrefslogtreecommitdiff
path: root/src/lj_record.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lj_record.c')
-rw-r--r--src/lj_record.c102
1 files changed, 94 insertions, 8 deletions
diff --git a/src/lj_record.c b/src/lj_record.c
index 7336e0ac..bdf0212a 100644
--- a/src/lj_record.c
+++ b/src/lj_record.c
@@ -677,6 +677,8 @@ static int check_downrec_unroll(jit_State *J, GCproto *pt)
677 return 0; 677 return 0;
678} 678}
679 679
680static TRef rec_cat(jit_State *J, BCReg baseslot, BCReg topslot);
681
680/* Record return. */ 682/* Record return. */
681void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults) 683void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults)
682{ 684{
@@ -769,7 +771,24 @@ void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults)
769 } else if (cont == lj_cont_nop) { 771 } else if (cont == lj_cont_nop) {
770 /* Nothing to do here. */ 772 /* Nothing to do here. */
771 } else if (cont == lj_cont_cat) { 773 } else if (cont == lj_cont_cat) {
772 lua_assert(0); 774 BCReg bslot = bc_b(*(frame_contpc(frame)-1));
775 TRef tr = gotresults ? J->base[cbase+rbase] : TREF_NIL;
776 if (bslot != cbase-2) { /* Concatenate the remainder. */
777 TValue *b = J->L->base, save; /* Simulate lower frame and result. */
778 J->base[cbase-2] = tr;
779 copyTV(J->L, &save, b-2);
780 if (gotresults) copyTV(J->L, b-2, b+rbase); else setnilV(b-2);
781 J->L->base = b - cbase;
782 tr = rec_cat(J, bslot, cbase-2);
783 b = J->L->base + cbase; /* Undo. */
784 J->L->base = b;
785 copyTV(J->L, b-2, &save);
786 }
787 if (tr) { /* Store final result. */
788 BCReg dst = bc_a(*(frame_contpc(frame)-1));
789 J->base[dst] = tr;
790 if (dst >= J->maxslot) J->maxslot = dst+1;
791 } /* Otherwise continue with another __concat call. */
773 } else { 792 } else {
774 /* Result type already specialized. */ 793 /* Result type already specialized. */
775 lua_assert(cont == lj_cont_condf || cont == lj_cont_condt); 794 lua_assert(cont == lj_cont_condf || cont == lj_cont_condt);
@@ -785,13 +804,11 @@ void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults)
785/* Prepare to record call to metamethod. */ 804/* Prepare to record call to metamethod. */
786static BCReg rec_mm_prep(jit_State *J, ASMFunction cont) 805static BCReg rec_mm_prep(jit_State *J, ASMFunction cont)
787{ 806{
788 BCReg s, top = curr_proto(J->L)->framesize; 807 BCReg s, top = cont == lj_cont_cat ? J->maxslot : curr_proto(J->L)->framesize;
789 TRef trcont;
790 setcont(&J->L->base[top], cont);
791#if LJ_64 808#if LJ_64
792 trcont = lj_ir_kptr(J, (void *)((int64_t)cont - (int64_t)lj_vm_asm_begin)); 809 TRef trcont = lj_ir_kptr(J, (void *)((int64_t)cont-(int64_t)lj_vm_asm_begin));
793#else 810#else
794 trcont = lj_ir_kptr(J, (void *)cont); 811 TRef trcont = lj_ir_kptr(J, (void *)cont);
795#endif 812#endif
796 J->base[top] = trcont | TREF_CONT; 813 J->base[top] = trcont | TREF_CONT;
797 J->framedepth++; 814 J->framedepth++;
@@ -872,7 +889,7 @@ nocheck:
872static TRef rec_mm_arith(jit_State *J, RecordIndex *ix, MMS mm) 889static TRef rec_mm_arith(jit_State *J, RecordIndex *ix, MMS mm)
873{ 890{
874 /* Set up metamethod call first to save ix->tab and ix->tabv. */ 891 /* Set up metamethod call first to save ix->tab and ix->tabv. */
875 BCReg func = rec_mm_prep(J, lj_cont_ra); 892 BCReg func = rec_mm_prep(J, mm == MM_concat ? lj_cont_cat : lj_cont_ra);
876 TRef *base = J->base + func; 893 TRef *base = J->base + func;
877 TValue *basev = J->L->base + func; 894 TValue *basev = J->L->base + func;
878 base[1] = ix->tab; base[2] = ix->key; 895 base[1] = ix->tab; base[2] = ix->key;
@@ -1599,6 +1616,54 @@ static TRef rec_tnew(jit_State *J, uint32_t ah)
1599 return emitir(IRTG(IR_TNEW, IRT_TAB), asize, hbits); 1616 return emitir(IRTG(IR_TNEW, IRT_TAB), asize, hbits);
1600} 1617}
1601 1618
1619/* -- Concatenation ------------------------------------------------------- */
1620
1621static TRef rec_cat(jit_State *J, BCReg baseslot, BCReg topslot)
1622{
1623 TRef *top = &J->base[topslot];
1624 TValue savetv[5];
1625 BCReg s;
1626 RecordIndex ix;
1627 lua_assert(baseslot < topslot);
1628 for (s = baseslot; s <= topslot; s++)
1629 (void)getslot(J, s); /* Ensure all arguments have a reference. */
1630 if (tref_isnumber_str(top[0]) && tref_isnumber_str(top[-1])) {
1631 TRef tr, hdr, *trp, *xbase, *base = &J->base[baseslot];
1632 /* First convert numbers to strings. */
1633 for (trp = top; trp >= base; trp--) {
1634 if (tref_isnumber(*trp))
1635 *trp = emitir(IRT(IR_TOSTR, IRT_STR), *trp,
1636 tref_isnum(*trp) ? IRTOSTR_NUM : IRTOSTR_INT);
1637 else if (!tref_isstr(*trp))
1638 break;
1639 }
1640 xbase = ++trp;
1641 tr = hdr = emitir(IRT(IR_BUFHDR, IRT_P32),
1642 lj_ir_kptr(J, &J2G(J)->tmpbuf), IRBUFHDR_RESET);
1643 do {
1644 tr = emitir(IRT(IR_BUFPUT, IRT_P32), tr, *trp++);
1645 } while (trp <= top);
1646 tr = emitir(IRT(IR_BUFSTR, IRT_STR), tr, hdr);
1647 J->maxslot = (BCReg)(xbase - J->base);
1648 if (xbase == base) return tr; /* Return simple concatenation result. */
1649 /* Pass partial result. */
1650 topslot = J->maxslot--;
1651 *xbase = tr;
1652 top = xbase;
1653 setstrV(J->L, &ix.keyv, &J2G(J)->strempty); /* Simulate string result. */
1654 } else {
1655 J->maxslot = topslot-1;
1656 copyTV(J->L, &ix.keyv, &J->L->base[topslot]);
1657 }
1658 copyTV(J->L, &ix.tabv, &J->L->base[topslot-1]);
1659 ix.tab = top[-1];
1660 ix.key = top[0];
1661 memcpy(savetv, &J->L->base[topslot-1], sizeof(savetv)); /* Save slots. */
1662 rec_mm_arith(J, &ix, MM_concat); /* Call __concat metamethod. */
1663 memcpy(&J->L->base[topslot-1], savetv, sizeof(savetv)); /* Restore slots. */
1664 return 0; /* No result yet. */
1665}
1666
1602/* -- Record bytecode ops ------------------------------------------------- */ 1667/* -- Record bytecode ops ------------------------------------------------- */
1603 1668
1604/* Prepare for comparison. */ 1669/* Prepare for comparison. */
@@ -1826,6 +1891,18 @@ void lj_record_ins(jit_State *J)
1826 J->maxslot = bc_a(pc[1]); /* Shrink used slots. */ 1891 J->maxslot = bc_a(pc[1]); /* Shrink used slots. */
1827 break; 1892 break;
1828 1893
1894 case BC_ISTYPE: case BC_ISNUM:
1895 /* These coercions need to correspond with lj_meta_istype(). */
1896 if (LJ_DUALNUM && rc == ~LJ_TNUMX+1)
1897 ra = lj_opt_narrow_toint(J, ra);
1898 else if (rc == ~LJ_TNUMX+2)
1899 ra = lj_ir_tonum(J, ra);
1900 else if (rc == ~LJ_TSTR+1)
1901 ra = lj_ir_tostr(J, ra);
1902 /* else: type specialization suffices. */
1903 J->base[bc_a(ins)] = ra;
1904 break;
1905
1829 /* -- Unary ops --------------------------------------------------------- */ 1906 /* -- Unary ops --------------------------------------------------------- */
1830 1907
1831 case BC_NOT: 1908 case BC_NOT:
@@ -1889,6 +1966,12 @@ void lj_record_ins(jit_State *J)
1889 rc = rec_mm_arith(J, &ix, MM_pow); 1966 rc = rec_mm_arith(J, &ix, MM_pow);
1890 break; 1967 break;
1891 1968
1969 /* -- Miscellaneous ops ------------------------------------------------- */
1970
1971 case BC_CAT:
1972 rc = rec_cat(J, rb, rc);
1973 break;
1974
1892 /* -- Constant and move ops --------------------------------------------- */ 1975 /* -- Constant and move ops --------------------------------------------- */
1893 1976
1894 case BC_MOV: 1977 case BC_MOV:
@@ -1937,6 +2020,10 @@ void lj_record_ins(jit_State *J)
1937 ix.idxchain = LJ_MAX_IDXCHAIN; 2020 ix.idxchain = LJ_MAX_IDXCHAIN;
1938 rc = lj_record_idx(J, &ix); 2021 rc = lj_record_idx(J, &ix);
1939 break; 2022 break;
2023 case BC_TGETR: case BC_TSETR:
2024 ix.idxchain = 0;
2025 rc = lj_record_idx(J, &ix);
2026 break;
1940 2027
1941 case BC_TNEW: 2028 case BC_TNEW:
1942 rc = rec_tnew(J, rc); 2029 rc = rec_tnew(J, rc);
@@ -2066,7 +2153,6 @@ void lj_record_ins(jit_State *J)
2066 /* fallthrough */ 2153 /* fallthrough */
2067 case BC_ITERN: 2154 case BC_ITERN:
2068 case BC_ISNEXT: 2155 case BC_ISNEXT:
2069 case BC_CAT:
2070 case BC_UCLO: 2156 case BC_UCLO:
2071 case BC_FNEW: 2157 case BC_FNEW:
2072 case BC_TSETM: 2158 case BC_TSETM: