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
|
| mov CARG1, L
|
||||||
| str PC, SAVE_PC
|
| str PC, SAVE_PC
|
||||||
| bl extern lj_meta_len // (lua_State *L, TValue *o)
|
| 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
|
| 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.
|
| b ->vmeta_binop // Binop call for compatibility.
|
||||||
|
#endif
|
||||||
|
|
|
|
||||||
|//-- Call metamethod ----------------------------------------------------
|
|//-- Call metamethod ----------------------------------------------------
|
||||||
|
|
|
|
||||||
@ -2546,11 +2553,25 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
|
|||||||
| ins_next3
|
| ins_next3
|
||||||
|2:
|
|2:
|
||||||
| checktab CARG2, ->vmeta_len
|
| 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
|
| IOS mov RC, BASE
|
||||||
| bl extern lj_tab_len // (GCtab *t)
|
| bl extern lj_tab_len // (GCtab *t)
|
||||||
| // Returns uint32_t (but less than 2^31).
|
| // Returns uint32_t (but less than 2^31).
|
||||||
| IOS mov BASE, RC
|
| IOS mov BASE, RC
|
||||||
| b <1
|
| 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;
|
break;
|
||||||
|
|
||||||
/* -- Binary ops -------------------------------------------------------- */
|
/* -- 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
|
| b ->vm_call_dispatch
|
||||||
|
|
|
|
||||||
|->vmeta_len:
|
|->vmeta_len:
|
||||||
|
#ifdef LUAJIT_ENABLE_LUA52COMPAT
|
||||||
|
| mr SAVE0, CARG1
|
||||||
|
#endif
|
||||||
| add CARG2, BASE, RD
|
| add CARG2, BASE, RD
|
||||||
| stw BASE, L->base
|
| stw BASE, L->base
|
||||||
| mr CARG1, L
|
| mr CARG1, L
|
||||||
| stw PC, SAVE_PC
|
| stw PC, SAVE_PC
|
||||||
| bl extern lj_meta_len // (lua_State *L, TValue *o)
|
| 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.
|
| b ->vmeta_binop // Binop call for compatibility.
|
||||||
|
#endif
|
||||||
|
|
|
|
||||||
|//-- Call metamethod ----------------------------------------------------
|
|//-- Call metamethod ----------------------------------------------------
|
||||||
|
|
|
|
||||||
@ -2337,9 +2347,23 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
|
|||||||
|2:
|
|2:
|
||||||
| checktab CARG1
|
| checktab CARG1
|
||||||
| checkfail ->vmeta_len
|
| 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)
|
| bl extern lj_tab_len // (GCtab *t)
|
||||||
| // Returns uint32_t (but less than 2^31).
|
| // Returns uint32_t (but less than 2^31).
|
||||||
| b <1
|
| 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;
|
break;
|
||||||
|
|
||||||
/* -- Binary ops -------------------------------------------------------- */
|
/* -- 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 L:FCARG1, L:RB
|
||||||
| mov SAVE_PC, PC
|
| mov SAVE_PC, PC
|
||||||
| call extern lj_meta_len@8 // (lua_State *L, TValue *o)
|
| 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
|
| 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.
|
| jmp ->vmeta_binop // Binop call for compatibility.
|
||||||
|
#endif
|
||||||
|
|
|
|
||||||
|//-- Call metamethod ----------------------------------------------------
|
|//-- Call metamethod ----------------------------------------------------
|
||||||
|
|
|
|
||||||
@ -4244,6 +4252,13 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop, int cmov, int sse)
|
|||||||
|2:
|
|2:
|
||||||
| checktab RD, ->vmeta_len
|
| checktab RD, ->vmeta_len
|
||||||
| mov TAB:FCARG1, [BASE+RD*8]
|
| 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.
|
| mov RB, BASE // Save BASE.
|
||||||
| call extern lj_tab_len@4 // (GCtab *t)
|
| call extern lj_tab_len@4 // (GCtab *t)
|
||||||
| // Length of table returned in eax (RD).
|
| // 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.
|
| mov BASE, RB // Restore BASE.
|
||||||
| movzx RA, PC_RA
|
| movzx RA, PC_RA
|
||||||
| jmp <1
|
| 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;
|
break;
|
||||||
|
|
||||||
/* -- Binary ops -------------------------------------------------------- */
|
/* -- 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);
|
cTValue *mo = lj_meta_lookup(L, o, MM_len);
|
||||||
if (tvisnil(mo)) {
|
if (tvisnil(mo)) {
|
||||||
lj_err_optype(L, o, LJ_ERR_OPLEN);
|
#ifdef LUAJIT_ENABLE_LUA52COMPAT
|
||||||
return NULL; /* unreachable */
|
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));
|
return mmcall(L, lj_cont_ra, mo, o, niltv(L));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Helper for equality comparisons. __eq metamethod. */
|
/* Helper for equality comparisons. __eq metamethod. */
|
||||||
|
@ -441,9 +441,9 @@ enum {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define MMDEF(_) \
|
#define MMDEF(_) \
|
||||||
_(index) _(newindex) _(gc) _(mode) _(eq) \
|
_(index) _(newindex) _(gc) _(mode) _(eq) _(len) \
|
||||||
/* Only the above (fast) metamethods are negative cached (max. 8). */ \
|
/* 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. */ \
|
/* The following must be in ORDER ARITH. */ \
|
||||||
_(add) _(sub) _(mul) _(div) _(mod) _(pow) _(unm) \
|
_(add) _(sub) _(mul) _(div) _(mod) _(pow) _(unm) \
|
||||||
/* The following are used in the standard libraries. */ \
|
/* The following are used in the standard libraries. */ \
|
||||||
@ -455,7 +455,7 @@ MMDEF(MMENUM)
|
|||||||
#undef MMENUM
|
#undef MMENUM
|
||||||
MM__MAX,
|
MM__MAX,
|
||||||
MM____ = MM__MAX,
|
MM____ = MM__MAX,
|
||||||
MM_FAST = MM_eq
|
MM_FAST = MM_len
|
||||||
} MMS;
|
} MMS;
|
||||||
|
|
||||||
/* GC root IDs. */
|
/* GC root IDs. */
|
||||||
|
@ -819,7 +819,7 @@ nocheck:
|
|||||||
return 0; /* No metamethod. */
|
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)
|
static TRef rec_mm_arith(jit_State *J, RecordIndex *ix, MMS mm)
|
||||||
{
|
{
|
||||||
/* Set up metamethod call first to save ix->tab and ix->tabv. */
|
/* 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+1, &ix->tabv);
|
||||||
copyTV(J->L, basev+2, &ix->keyv);
|
copyTV(J->L, basev+2, &ix->keyv);
|
||||||
if (!lj_record_mm_lookup(J, ix, mm)) { /* Lookup mm on 1st operand. */
|
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;
|
ix->tab = ix->key;
|
||||||
copyTV(J->L, &ix->tabv, &ix->keyv);
|
copyTV(J->L, &ix->tabv, &ix->keyv);
|
||||||
if (lj_record_mm_lookup(J, ix, mm)) /* Lookup mm on 2nd operand. */
|
if (lj_record_mm_lookup(J, ix, mm)) /* Lookup mm on 2nd operand. */
|
||||||
@ -845,6 +845,34 @@ ok:
|
|||||||
return 0; /* No result yet. */
|
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. */
|
/* Call a comparison metamethod. */
|
||||||
static void rec_mm_callcomp(jit_State *J, RecordIndex *ix, int op)
|
static void rec_mm_callcomp(jit_State *J, RecordIndex *ix, int op)
|
||||||
{
|
{
|
||||||
@ -1667,17 +1695,14 @@ void lj_record_ins(jit_State *J)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case BC_LEN:
|
case BC_LEN:
|
||||||
if (tref_isstr(rc)) {
|
if (tref_isstr(rc))
|
||||||
rc = emitir(IRTI(IR_FLOAD), rc, IRFL_STR_LEN);
|
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);
|
rc = lj_ir_call(J, IRCALL_lj_tab_len, rc);
|
||||||
} else {
|
#endif
|
||||||
ix.tab = rc;
|
else
|
||||||
copyTV(J->L, &ix.tabv, rcv);
|
rc = rec_mm_len(J, rc, rcv);
|
||||||
ix.key = TREF_NIL;
|
|
||||||
setnilV(&ix.keyv);
|
|
||||||
rc = rec_mm_arith(J, &ix, MM_len);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* -- Arithmetic ops ---------------------------------------------------- */
|
/* -- Arithmetic ops ---------------------------------------------------- */
|
||||||
|
Loading…
Reference in New Issue
Block a user