mirror of
https://github.com/LuaJIT/LuaJIT.git
synced 2025-02-07 23:24:09 +00:00
From Lua 5.2: __len for tables. Needs -DLUAJIT_ENABLE_LUA52COMPAT.
This commit is contained in:
parent
0f55b46b0b
commit
31d566428f
@ -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 -------------------------------------------------------- */
|
||||
|
2043
src/buildvm_arm.h
2043
src/buildvm_arm.h
File diff suppressed because it is too large
Load Diff
@ -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 -------------------------------------------------------- */
|
||||
|
1374
src/buildvm_ppcspe.h
1374
src/buildvm_ppcspe.h
File diff suppressed because it is too large
Load Diff
2347
src/buildvm_x64.h
2347
src/buildvm_x64.h
File diff suppressed because it is too large
Load Diff
2339
src/buildvm_x64win.h
2339
src/buildvm_x64win.h
File diff suppressed because it is too large
Load Diff
@ -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 -------------------------------------------------------- */
|
||||
|
2634
src/buildvm_x86.h
2634
src/buildvm_x86.h
File diff suppressed because it is too large
Load Diff
@ -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)) {
|
||||
lj_err_optype(L, o, LJ_ERR_OPLEN);
|
||||
return NULL; /* unreachable */
|
||||
#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;
|
||||
}
|
||||
#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. */
|
||||
|
@ -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. */
|
||||
|
@ -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 ---------------------------------------------------- */
|
||||
|
Loading…
Reference in New Issue
Block a user