From Lua 5.2: __len for tables. Needs -DLUAJIT_ENABLE_LUA52COMPAT.

This commit is contained in:
Mike Pall
2011-06-20 20:45:41 +02:00
parent 0f55b46b0b
commit 31d566428f
11 changed files with 5558 additions and 5317 deletions

View File

@@ -819,7 +819,7 @@ nocheck:
return 0; /* No metamethod. */
}
/* Record call to arithmetic metamethod (and MM_len). */
/* Record call to arithmetic metamethod. */
static TRef rec_mm_arith(jit_State *J, RecordIndex *ix, MMS mm)
{
/* 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)
copyTV(J->L, basev+1, &ix->tabv);
copyTV(J->L, basev+2, &ix->keyv);
if (!lj_record_mm_lookup(J, ix, mm)) { /* Lookup mm on 1st operand. */
if (mm != MM_len) {
if (mm != MM_unm) {
ix->tab = ix->key;
copyTV(J->L, &ix->tabv, &ix->keyv);
if (lj_record_mm_lookup(J, ix, mm)) /* Lookup mm on 2nd operand. */
@@ -845,6 +845,34 @@ ok:
return 0; /* No result yet. */
}
/* Record call to __len metamethod. */
static TRef rec_mm_len(jit_State *J, TRef tr, TValue *tv)
{
RecordIndex ix;
ix.tab = tr;
copyTV(J->L, &ix.tabv, tv);
if (lj_record_mm_lookup(J, &ix, MM_len)) {
BCReg func = rec_mm_prep(J, lj_cont_ra);
TRef *base = J->base + func;
TValue *basev = J->L->base + func;
base[0] = ix.mobj; copyTV(J->L, basev+0, &ix.mobjv);
base[1] = tr; copyTV(J->L, basev+1, tv);
#ifdef LUAJIT_ENABLE_LUA52COMPAT
base[2] = tr; copyTV(J->L, basev+2, tv);
#else
base[2] = TREF_NIL; setnilV(basev+2);
#endif
lj_record_call(J, func, 2);
} else {
#ifdef LUAJIT_ENABLE_LUA52COMPAT
if (tref_istab(tr))
return lj_ir_call(J, IRCALL_lj_tab_len, tr);
#endif
lj_trace_err(J, LJ_TRERR_NOMM);
}
return 0; /* No result yet. */
}
/* Call a comparison metamethod. */
static void rec_mm_callcomp(jit_State *J, RecordIndex *ix, int op)
{
@@ -1667,17 +1695,14 @@ void lj_record_ins(jit_State *J)
break;
case BC_LEN:
if (tref_isstr(rc)) {
if (tref_isstr(rc))
rc = emitir(IRTI(IR_FLOAD), rc, IRFL_STR_LEN);
} else if (tref_istab(rc)) {
#ifndef LUAJIT_ENABLE_LUA52COMPAT
else if (tref_istab(rc))
rc = lj_ir_call(J, IRCALL_lj_tab_len, rc);
} else {
ix.tab = rc;
copyTV(J->L, &ix.tabv, rcv);
ix.key = TREF_NIL;
setnilV(&ix.keyv);
rc = rec_mm_arith(J, &ix, MM_len);
}
#endif
else
rc = rec_mm_len(J, rc, rcv);
break;
/* -- Arithmetic ops ---------------------------------------------------- */