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 /src | |
| parent | 8b3a320089563b008e88deea2252e1111e44a2ae (diff) | |
| download | luajit-4ac25a9132b4a07402f0f4161397a4ebc88ca590.tar.gz luajit-4ac25a9132b4a07402f0f4161397a4ebc88ca590.tar.bz2 luajit-4ac25a9132b4a07402f0f4161397a4ebc88ca590.zip | |
Compile __concat metamethod.
Diffstat (limited to 'src')
| -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 ------------------------------------------------- */ |
