diff options
author | Mike Pall <mike> | 2013-04-28 01:51:41 +0200 |
---|---|---|
committer | Mike Pall <mike> | 2013-04-28 01:51:41 +0200 |
commit | 4ac25a9132b4a07402f0f4161397a4ebc88ca590 (patch) | |
tree | cc93d309e5cbf996e14837426400f63368c2627d | |
parent | 8b3a320089563b008e88deea2252e1111e44a2ae (diff) | |
download | luajit-4ac25a9132b4a07402f0f4161397a4ebc88ca590.tar.gz luajit-4ac25a9132b4a07402f0f4161397a4ebc88ca590.tar.bz2 luajit-4ac25a9132b4a07402f0f4161397a4ebc88ca590.zip |
Compile __concat metamethod.
-rw-r--r-- | src/lj_record.c | 62 |
1 files changed, 48 insertions, 14 deletions
diff --git a/src/lj_record.c b/src/lj_record.c index 8dc102e9..76309acd 100644 --- a/src/lj_record.c +++ b/src/lj_record.c | |||
@@ -678,6 +678,8 @@ static int check_downrec_unroll(jit_State *J, GCproto *pt) | |||
678 | return 0; | 678 | return 0; |
679 | } | 679 | } |
680 | 680 | ||
681 | static TRef rec_cat(jit_State *J, BCReg baseslot, BCReg topslot); | ||
682 | |||
681 | /* Record return. */ | 683 | /* Record return. */ |
682 | void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults) | 684 | void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults) |
683 | { | 685 | { |
@@ -770,7 +772,24 @@ void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults) | |||
770 | } else if (cont == lj_cont_nop) { | 772 | } else if (cont == lj_cont_nop) { |
771 | /* Nothing to do here. */ | 773 | /* Nothing to do here. */ |
772 | } else if (cont == lj_cont_cat) { | 774 | } else if (cont == lj_cont_cat) { |
773 | lua_assert(0); | 775 | BCReg bslot = bc_b(*(frame_contpc(frame)-1)); |
776 | TRef tr = gotresults ? J->base[cbase+rbase] : TREF_NIL; | ||
777 | if (bslot != cbase-2) { /* Concatenate the remainder. */ | ||
778 | TValue *b = J->L->base, save; /* Simulate lower frame and result. */ | ||
779 | J->base[cbase-2] = tr; | ||
780 | copyTV(J->L, &save, b-2); | ||
781 | if (gotresults) copyTV(J->L, b-2, b+rbase); else setnilV(b-2); | ||
782 | J->L->base = b - cbase; | ||
783 | tr = rec_cat(J, bslot, cbase-2); | ||
784 | b = J->L->base + cbase; /* Undo. */ | ||
785 | J->L->base = b; | ||
786 | copyTV(J->L, b-2, &save); | ||
787 | } | ||
788 | if (tr) { /* Store final result. */ | ||
789 | BCReg dst = bc_a(*(frame_contpc(frame)-1)); | ||
790 | J->base[dst] = tr; | ||
791 | if (dst >= J->maxslot) J->maxslot = dst+1; | ||
792 | } /* Otherwise continue with another __concat call. */ | ||
774 | } else { | 793 | } else { |
775 | /* Result type already specialized. */ | 794 | /* Result type already specialized. */ |
776 | lua_assert(cont == lj_cont_condf || cont == lj_cont_condt); | 795 | lua_assert(cont == lj_cont_condf || cont == lj_cont_condt); |
@@ -786,13 +805,11 @@ void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults) | |||
786 | /* Prepare to record call to metamethod. */ | 805 | /* Prepare to record call to metamethod. */ |
787 | static BCReg rec_mm_prep(jit_State *J, ASMFunction cont) | 806 | static BCReg rec_mm_prep(jit_State *J, ASMFunction cont) |
788 | { | 807 | { |
789 | BCReg s, top = curr_proto(J->L)->framesize; | 808 | BCReg s, top = cont == lj_cont_cat ? J->maxslot : curr_proto(J->L)->framesize; |
790 | TRef trcont; | ||
791 | setcont(&J->L->base[top], cont); | ||
792 | #if LJ_64 | 809 | #if LJ_64 |
793 | trcont = lj_ir_kptr(J, (void *)((int64_t)cont - (int64_t)lj_vm_asm_begin)); | 810 | TRef trcont = lj_ir_kptr(J, (void *)((int64_t)cont-(int64_t)lj_vm_asm_begin)); |
794 | #else | 811 | #else |
795 | trcont = lj_ir_kptr(J, (void *)cont); | 812 | TRef trcont = lj_ir_kptr(J, (void *)cont); |
796 | #endif | 813 | #endif |
797 | J->base[top] = trcont | TREF_CONT; | 814 | J->base[top] = trcont | TREF_CONT; |
798 | J->framedepth++; | 815 | J->framedepth++; |
@@ -873,7 +890,7 @@ nocheck: | |||
873 | static TRef rec_mm_arith(jit_State *J, RecordIndex *ix, MMS mm) | 890 | static TRef rec_mm_arith(jit_State *J, RecordIndex *ix, MMS mm) |
874 | { | 891 | { |
875 | /* Set up metamethod call first to save ix->tab and ix->tabv. */ | 892 | /* Set up metamethod call first to save ix->tab and ix->tabv. */ |
876 | BCReg func = rec_mm_prep(J, lj_cont_ra); | 893 | BCReg func = rec_mm_prep(J, mm == MM_concat ? lj_cont_cat : lj_cont_ra); |
877 | TRef *base = J->base + func; | 894 | TRef *base = J->base + func; |
878 | TValue *basev = J->L->base + func; | 895 | TValue *basev = J->L->base + func; |
879 | base[1] = ix->tab; base[2] = ix->key; | 896 | base[1] = ix->tab; base[2] = ix->key; |
@@ -1604,10 +1621,15 @@ static TRef rec_tnew(jit_State *J, uint32_t ah) | |||
1604 | 1621 | ||
1605 | static TRef rec_cat(jit_State *J, BCReg baseslot, BCReg topslot) | 1622 | static TRef rec_cat(jit_State *J, BCReg baseslot, BCReg topslot) |
1606 | { | 1623 | { |
1607 | TRef *top = &J->base[topslot], tr = *top; | 1624 | TRef *top = &J->base[topslot]; |
1625 | TValue savetv[5]; | ||
1626 | BCReg s; | ||
1627 | RecordIndex ix; | ||
1608 | lua_assert(baseslot < topslot); | 1628 | lua_assert(baseslot < topslot); |
1609 | if (tref_isnumber_str(tr) && tref_isnumber_str(*(top-1))) { | 1629 | for (s = baseslot; s <= topslot; s++) |
1610 | TRef hdr, *trp, *xbase, *base = &J->base[baseslot]; | 1630 | (void)getslot(J, s); /* Ensure all arguments have a reference. */ |
1631 | if (tref_isnumber_str(top[0]) && tref_isnumber_str(top[-1])) { | ||
1632 | TRef tr, hdr, *trp, *xbase, *base = &J->base[baseslot]; | ||
1611 | /* First convert numbers to strings. */ | 1633 | /* First convert numbers to strings. */ |
1612 | for (trp = top; trp >= base; trp--) { | 1634 | for (trp = top; trp >= base; trp--) { |
1613 | if (tref_isnumber(*trp)) | 1635 | if (tref_isnumber(*trp)) |
@@ -1624,11 +1646,23 @@ static TRef rec_cat(jit_State *J, BCReg baseslot, BCReg topslot) | |||
1624 | } while (trp <= top); | 1646 | } while (trp <= top); |
1625 | tr = emitir(IRT(IR_BUFSTR, IRT_STR), tr, hdr); | 1647 | tr = emitir(IRT(IR_BUFSTR, IRT_STR), tr, hdr); |
1626 | J->maxslot = (BCReg)(xbase - J->base); | 1648 | J->maxslot = (BCReg)(xbase - J->base); |
1627 | if (xbase == base) return tr; | 1649 | if (xbase == base) return tr; /* Return simple concatenation result. */ |
1650 | /* Pass partial result. */ | ||
1651 | topslot = J->maxslot--; | ||
1652 | *xbase = tr; | ||
1653 | top = xbase; | ||
1654 | setstrV(J->L, &ix.keyv, &J2G(J)->strempty); /* Simulate string result. */ | ||
1655 | } else { | ||
1656 | J->maxslot = topslot-1; | ||
1657 | copyTV(J->L, &ix.keyv, &J->L->base[topslot]); | ||
1628 | } | 1658 | } |
1629 | setintV(&J->errinfo, BC_CAT); | 1659 | copyTV(J->L, &ix.tabv, &J->L->base[topslot-1]); |
1630 | lj_trace_err_info(J, LJ_TRERR_NYIBC); /* __concat metamethod. */ | 1660 | ix.tab = top[-1]; |
1631 | return 0; | 1661 | ix.key = top[0]; |
1662 | memcpy(savetv, &J->L->base[topslot-1], sizeof(savetv)); /* Save slots. */ | ||
1663 | rec_mm_arith(J, &ix, MM_concat); /* Call __concat metamethod. */ | ||
1664 | memcpy(&J->L->base[topslot-1], savetv, sizeof(savetv)); /* Restore slots. */ | ||
1665 | return 0; /* No result yet. */ | ||
1632 | } | 1666 | } |
1633 | 1667 | ||
1634 | /* -- Record bytecode ops ------------------------------------------------- */ | 1668 | /* -- Record bytecode ops ------------------------------------------------- */ |