diff options
Diffstat (limited to 'src/lj_record.c')
-rw-r--r-- | src/lj_record.c | 47 |
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. */ |
823 | static TRef rec_mm_arith(jit_State *J, RecordIndex *ix, MMS mm) | 823 | static 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. */ | ||
849 | static 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. */ |
849 | static void rec_mm_callcomp(jit_State *J, RecordIndex *ix, int op) | 877 | static 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 ---------------------------------------------------- */ |