diff options
Diffstat (limited to 'src/lj_record.c')
-rw-r--r-- | src/lj_record.c | 102 |
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 | ||
680 | static TRef rec_cat(jit_State *J, BCReg baseslot, BCReg topslot); | ||
681 | |||
680 | /* Record return. */ | 682 | /* Record return. */ |
681 | void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults) | 683 | void 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. */ |
786 | static BCReg rec_mm_prep(jit_State *J, ASMFunction cont) | 805 | static 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: | |||
872 | static TRef rec_mm_arith(jit_State *J, RecordIndex *ix, MMS mm) | 889 | static 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 | |||
1621 | static 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: |