aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Pall <mike>2013-04-28 01:51:41 +0200
committerMike Pall <mike>2013-04-28 01:51:41 +0200
commit4ac25a9132b4a07402f0f4161397a4ebc88ca590 (patch)
treecc93d309e5cbf996e14837426400f63368c2627d
parent8b3a320089563b008e88deea2252e1111e44a2ae (diff)
downloadluajit-4ac25a9132b4a07402f0f4161397a4ebc88ca590.tar.gz
luajit-4ac25a9132b4a07402f0f4161397a4ebc88ca590.tar.bz2
luajit-4ac25a9132b4a07402f0f4161397a4ebc88ca590.zip
Compile __concat metamethod.
-rw-r--r--src/lj_record.c62
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
681static TRef rec_cat(jit_State *J, BCReg baseslot, BCReg topslot);
682
681/* Record return. */ 683/* Record return. */
682void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults) 684void 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. */
787static BCReg rec_mm_prep(jit_State *J, ASMFunction cont) 806static 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:
873static TRef rec_mm_arith(jit_State *J, RecordIndex *ix, MMS mm) 890static 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
1605static TRef rec_cat(jit_State *J, BCReg baseslot, BCReg topslot) 1622static 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 ------------------------------------------------- */