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

@ -767,9 +767,16 @@ static void build_subroutines(BuildCtx *ctx)
| mov CARG1, L
| str PC, SAVE_PC
| bl extern lj_meta_len // (lua_State *L, TValue *o)
| // Returns TValue * (metamethod base).
| // Returns NULL (retry) or TValue * (metamethod base).
| IOS ldr BASE, L->base
#ifdef LUAJIT_ENABLE_LUA52COMPAT
| cmp CRET1, #0
| bne ->vmeta_binop // Binop call for compatibility.
| ldr TAB:CARG1, [BASE, RC]
| b ->BC_LEN_Z
#else
| b ->vmeta_binop // Binop call for compatibility.
#endif
|
|//-- Call metamethod ----------------------------------------------------
|
@ -2546,11 +2553,25 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
| ins_next3
|2:
| checktab CARG2, ->vmeta_len
#ifdef LUAJIT_ENABLE_LUA52COMPAT
| ldr TAB:CARG3, TAB:CARG1->metatable
| cmp TAB:CARG3, #0
| bne >9
|3:
#endif
|->BC_LEN_Z:
| IOS mov RC, BASE
| bl extern lj_tab_len // (GCtab *t)
| // Returns uint32_t (but less than 2^31).
| IOS mov BASE, RC
| b <1
#ifdef LUAJIT_ENABLE_LUA52COMPAT
|9:
| ldrb CARG4, TAB:CARG3->nomm
| tst CARG4, #1<<MM_len
| bne <3 // 'no __len' flag set: done.
| b ->vmeta_len
#endif
break;
/* -- Binary ops -------------------------------------------------------- */

File diff suppressed because it is too large Load Diff

View File

@ -818,13 +818,23 @@ static void build_subroutines(BuildCtx *ctx)
| b ->vm_call_dispatch
|
|->vmeta_len:
#ifdef LUAJIT_ENABLE_LUA52COMPAT
| mr SAVE0, CARG1
#endif
| add CARG2, BASE, RD
| stw BASE, L->base
| mr CARG1, L
| stw PC, SAVE_PC
| bl extern lj_meta_len // (lua_State *L, TValue *o)
| // Returns TValue * (metamethod base).
| // Returns NULL (retry) or TValue * (metamethod base).
#ifdef LUAJIT_ENABLE_LUA52COMPAT
| cmplwi CRET1, 0
| bne ->vmeta_binop // Binop call for compatibility.
| mr CARG1, SAVE0
| b ->BC_LEN_Z
#else
| b ->vmeta_binop // Binop call for compatibility.
#endif
|
|//-- Call metamethod ----------------------------------------------------
|
@ -2337,9 +2347,23 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
|2:
| checktab CARG1
| checkfail ->vmeta_len
#ifdef LUAJIT_ENABLE_LUA52COMPAT
| lwz TAB:TMP2, TAB:CARG1->metatable
| cmplwi TAB:TMP2, 0
| bne >9
|3:
#endif
|->BC_LEN_Z:
| bl extern lj_tab_len // (GCtab *t)
| // Returns uint32_t (but less than 2^31).
| b <1
#ifdef LUAJIT_ENABLE_LUA52COMPAT
|9:
| lbz TMP0, TAB:TMP2->nomm
| andi. TMP0, TMP0, 1<<MM_len
| bne <3 // 'no __len' flag set: done.
| b ->vmeta_len
#endif
break;
/* -- Binary ops -------------------------------------------------------- */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1167,9 +1167,17 @@ static void build_subroutines(BuildCtx *ctx, int cmov, int sse)
| mov L:FCARG1, L:RB
| mov SAVE_PC, PC
| call extern lj_meta_len@8 // (lua_State *L, TValue *o)
| // TValue * (metamethod) returned in eax (RC).
| // NULL (retry) or TValue * (metamethod) returned in eax (RC).
| mov BASE, L:RB->base
#ifdef LUAJIT_ENABLE_LUA52COMPAT
| test RC, RC
| jne ->vmeta_binop // Binop call for compatibility.
| movzx RD, PC_RD
| mov TAB:FCARG1, [BASE+RD*8]
| jmp ->BC_LEN_Z
#else
| jmp ->vmeta_binop // Binop call for compatibility.
#endif
|
|//-- Call metamethod ----------------------------------------------------
|
@ -4244,6 +4252,13 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop, int cmov, int sse)
|2:
| checktab RD, ->vmeta_len
| mov TAB:FCARG1, [BASE+RD*8]
#ifdef LUAJIT_ENABLE_LUA52COMPAT
| mov TAB:RB, TAB:FCARG1->metatable
| cmp TAB:RB, 0
| jnz >9
|3:
#endif
|->BC_LEN_Z:
| mov RB, BASE // Save BASE.
| call extern lj_tab_len@4 // (GCtab *t)
| // Length of table returned in eax (RD).
@ -4260,6 +4275,12 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop, int cmov, int sse)
| mov BASE, RB // Restore BASE.
| movzx RA, PC_RA
| jmp <1
#ifdef LUAJIT_ENABLE_LUA52COMPAT
|9: // Check for __len.
| test byte TAB:RB->nomm, 1<<MM_len
| jnz <3
| jmp ->vmeta_len // 'no __len' flag NOT set: check.
#endif
break;
/* -- Binary ops -------------------------------------------------------- */

File diff suppressed because it is too large Load Diff

View File

@ -309,10 +309,19 @@ TValue * LJ_FASTCALL lj_meta_len(lua_State *L, cTValue *o)
{
cTValue *mo = lj_meta_lookup(L, o, MM_len);
if (tvisnil(mo)) {
#ifdef LUAJIT_ENABLE_LUA52COMPAT
if (tvistab(o))
tabref(tabV(o)->metatable)->nomm |= (uint8_t)(1u<<MM_len);
else
#endif
lj_err_optype(L, o, LJ_ERR_OPLEN);
return NULL; /* unreachable */
return NULL;
}
#ifdef LUAJIT_ENABLE_LUA52COMPAT
return mmcall(L, lj_cont_ra, mo, o, o);
#else
return mmcall(L, lj_cont_ra, mo, o, niltv(L));
#endif
}
/* Helper for equality comparisons. __eq metamethod. */

View File

@ -441,9 +441,9 @@ enum {
#endif
#define MMDEF(_) \
_(index) _(newindex) _(gc) _(mode) _(eq) \
_(index) _(newindex) _(gc) _(mode) _(eq) _(len) \
/* Only the above (fast) metamethods are negative cached (max. 8). */ \
_(len) _(lt) _(le) _(concat) _(call) \
_(lt) _(le) _(concat) _(call) \
/* The following must be in ORDER ARITH. */ \
_(add) _(sub) _(mul) _(div) _(mod) _(pow) _(unm) \
/* The following are used in the standard libraries. */ \
@ -455,7 +455,7 @@ MMDEF(MMENUM)
#undef MMENUM
MM__MAX,
MM____ = MM__MAX,
MM_FAST = MM_eq
MM_FAST = MM_len
} MMS;
/* GC root IDs. */

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 ---------------------------------------------------- */