summaryrefslogtreecommitdiff
path: root/src/lj_record.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lj_record.c')
-rw-r--r--src/lj_record.c47
1 files changed, 36 insertions, 11 deletions
diff --git a/src/lj_record.c b/src/lj_record.c
index 1a18724a..edfff50b 100644
--- a/src/lj_record.c
+++ b/src/lj_record.c
@@ -819,7 +819,7 @@ nocheck:
819 return 0; /* No metamethod. */ 819 return 0; /* No metamethod. */
820} 820}
821 821
822/* Record call to arithmetic metamethod (and MM_len). */ 822/* Record call to arithmetic metamethod. */
823static TRef rec_mm_arith(jit_State *J, RecordIndex *ix, MMS mm) 823static TRef rec_mm_arith(jit_State *J, RecordIndex *ix, MMS mm)
824{ 824{
825 /* Set up metamethod call first to save ix->tab and ix->tabv. */ 825 /* Set up metamethod call first to save ix->tab and ix->tabv. */
@@ -830,7 +830,7 @@ static TRef rec_mm_arith(jit_State *J, RecordIndex *ix, MMS mm)
830 copyTV(J->L, basev+1, &ix->tabv); 830 copyTV(J->L, basev+1, &ix->tabv);
831 copyTV(J->L, basev+2, &ix->keyv); 831 copyTV(J->L, basev+2, &ix->keyv);
832 if (!lj_record_mm_lookup(J, ix, mm)) { /* Lookup mm on 1st operand. */ 832 if (!lj_record_mm_lookup(J, ix, mm)) { /* Lookup mm on 1st operand. */
833 if (mm != MM_len) { 833 if (mm != MM_unm) {
834 ix->tab = ix->key; 834 ix->tab = ix->key;
835 copyTV(J->L, &ix->tabv, &ix->keyv); 835 copyTV(J->L, &ix->tabv, &ix->keyv);
836 if (lj_record_mm_lookup(J, ix, mm)) /* Lookup mm on 2nd operand. */ 836 if (lj_record_mm_lookup(J, ix, mm)) /* Lookup mm on 2nd operand. */
@@ -845,6 +845,34 @@ ok:
845 return 0; /* No result yet. */ 845 return 0; /* No result yet. */
846} 846}
847 847
848/* Record call to __len metamethod. */
849static TRef rec_mm_len(jit_State *J, TRef tr, TValue *tv)
850{
851 RecordIndex ix;
852 ix.tab = tr;
853 copyTV(J->L, &ix.tabv, tv);
854 if (lj_record_mm_lookup(J, &ix, MM_len)) {
855 BCReg func = rec_mm_prep(J, lj_cont_ra);
856 TRef *base = J->base + func;
857 TValue *basev = J->L->base + func;
858 base[0] = ix.mobj; copyTV(J->L, basev+0, &ix.mobjv);
859 base[1] = tr; copyTV(J->L, basev+1, tv);
860#ifdef LUAJIT_ENABLE_LUA52COMPAT
861 base[2] = tr; copyTV(J->L, basev+2, tv);
862#else
863 base[2] = TREF_NIL; setnilV(basev+2);
864#endif
865 lj_record_call(J, func, 2);
866 } else {
867#ifdef LUAJIT_ENABLE_LUA52COMPAT
868 if (tref_istab(tr))
869 return lj_ir_call(J, IRCALL_lj_tab_len, tr);
870#endif
871 lj_trace_err(J, LJ_TRERR_NOMM);
872 }
873 return 0; /* No result yet. */
874}
875
848/* Call a comparison metamethod. */ 876/* Call a comparison metamethod. */
849static void rec_mm_callcomp(jit_State *J, RecordIndex *ix, int op) 877static void rec_mm_callcomp(jit_State *J, RecordIndex *ix, int op)
850{ 878{
@@ -1667,17 +1695,14 @@ void lj_record_ins(jit_State *J)
1667 break; 1695 break;
1668 1696
1669 case BC_LEN: 1697 case BC_LEN:
1670 if (tref_isstr(rc)) { 1698 if (tref_isstr(rc))
1671 rc = emitir(IRTI(IR_FLOAD), rc, IRFL_STR_LEN); 1699 rc = emitir(IRTI(IR_FLOAD), rc, IRFL_STR_LEN);
1672 } else if (tref_istab(rc)) { 1700#ifndef LUAJIT_ENABLE_LUA52COMPAT
1701 else if (tref_istab(rc))
1673 rc = lj_ir_call(J, IRCALL_lj_tab_len, rc); 1702 rc = lj_ir_call(J, IRCALL_lj_tab_len, rc);
1674 } else { 1703#endif
1675 ix.tab = rc; 1704 else
1676 copyTV(J->L, &ix.tabv, rcv); 1705 rc = rec_mm_len(J, rc, rcv);
1677 ix.key = TREF_NIL;
1678 setnilV(&ix.keyv);
1679 rc = rec_mm_arith(J, &ix, MM_len);
1680 }
1681 break; 1706 break;
1682 1707
1683 /* -- Arithmetic ops ---------------------------------------------------- */ 1708 /* -- Arithmetic ops ---------------------------------------------------- */