From d08e7bd5183c361f9ad2ecbeb5ae4426985f485c Mon Sep 17 00:00:00 2001 From: Mike Pall Date: Fri, 28 Sep 2012 19:30:08 +0200 Subject: [PATCH] From Lua 5.2: Allow mixed metamethods for ordered comparisons. Needs -DLUAJIT_ENABLE_LUA52COMPAT. --- src/lj_meta.c | 10 ++++++++-- src/lj_record.c | 15 ++++++++++++++- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/lj_meta.c b/src/lj_meta.c index de2b4068..ab5d1b54 100644 --- a/src/lj_meta.c +++ b/src/lj_meta.c @@ -386,7 +386,8 @@ TValue *lj_meta_comp(lua_State *L, cTValue *o1, cTValue *o2, int op) cTValue *mo = lj_meta_lookup(L, tviscdata(o1) ? o1 : o2, mm); if (LJ_UNLIKELY(tvisnil(mo))) goto err; return mmcall(L, cont, mo, o1, o2); - } else if (itype(o1) == itype(o2)) { /* Never called with two numbers. */ + } else if (LJ_52 || itype(o1) == itype(o2)) { + /* Never called with two numbers. */ if (tvisstr(o1) && tvisstr(o2)) { int32_t res = lj_str_cmp(strV(o1), strV(o2)); return (TValue *)(intptr_t)(((op&2) ? res <= 0 : res < 0) ^ (op&1)); @@ -396,8 +397,13 @@ TValue *lj_meta_comp(lua_State *L, cTValue *o1, cTValue *o2, int op) ASMFunction cont = (op & 1) ? lj_cont_condf : lj_cont_condt; MMS mm = (op & 2) ? MM_le : MM_lt; cTValue *mo = lj_meta_lookup(L, o1, mm); +#if LJ_52 + if (tvisnil(mo) && tvisnil((mo = lj_meta_lookup(L, o2, mm)))) +#else cTValue *mo2 = lj_meta_lookup(L, o2, mm); - if (tvisnil(mo) || !lj_obj_equal(mo, mo2)) { + if (tvisnil(mo) || !lj_obj_equal(mo, mo2)) +#endif + { if (op & 2) { /* MM_le not found: retry with MM_lt. */ cTValue *ot = o1; o1 = o2; o2 = ot; /* Swap operands. */ op ^= 3; /* Use LT and flip condition. */ diff --git a/src/lj_record.c b/src/lj_record.c index 5910dab4..956f3bed 100644 --- a/src/lj_record.c +++ b/src/lj_record.c @@ -969,6 +969,16 @@ static void rec_mm_comp(jit_State *J, RecordIndex *ix, int op) copyTV(J->L, &ix->tabv, &ix->valv); while (1) { MMS mm = (op & 2) ? MM_le : MM_lt; /* Try __le + __lt or only __lt. */ +#if LJ_52 + if (!lj_record_mm_lookup(J, ix, mm)) { /* Lookup mm on 1st operand. */ + ix->tab = ix->key; + copyTV(J->L, &ix->tabv, &ix->keyv); + if (!lj_record_mm_lookup(J, ix, mm)) /* Lookup mm on 2nd operand. */ + goto nomatch; + } + rec_mm_callcomp(J, ix, op); + return; +#else if (lj_record_mm_lookup(J, ix, mm)) { /* Lookup mm on 1st operand. */ cTValue *bv; TRef mo1 = ix->mobj; @@ -992,8 +1002,9 @@ static void rec_mm_comp(jit_State *J, RecordIndex *ix, int op) rec_mm_callcomp(J, ix, op); return; } +#endif nomatch: - /* First lookup failed. Retry with __lt and swapped operands. */ + /* Lookup failed. Retry with __lt and swapped operands. */ if (!(op & 2)) break; /* Already at __lt. Interpreter will throw. */ ix->tab = ix->key; ix->key = ix->val; ix->val = ix->tab; copyTV(J->L, &ix->tabv, &ix->keyv); @@ -1742,6 +1753,8 @@ void lj_record_ins(jit_State *J) ta = IRT_NUM; } else if (ta == IRT_NUM && tc == IRT_INT) { rc = emitir(IRTN(IR_CONV), rc, IRCONV_NUM_INT); + } else if (LJ_52) { + ta = IRT_NIL; /* Force metamethod for different types. */ } else if (!((ta == IRT_FALSE || ta == IRT_TRUE) && (tc == IRT_FALSE || tc == IRT_TRUE))) { break; /* Interpreter will throw for two different types. */