From f385af7084f300380167bf2261e8109927bd1e18 Mon Sep 17 00:00:00 2001 From: Mike Pall Date: Mon, 17 Jan 2011 01:23:04 +0100 Subject: [PATCH] FFI: Record 64 bit integer comparisons and pointer comparisons. --- src/lib_ffi.c | 17 ++++++++------- src/lj_asm.c | 2 +- src/lj_crecord.c | 57 ++++++++++++++++++++++++++++++++---------------- src/lj_record.c | 1 + 4 files changed, 49 insertions(+), 28 deletions(-) diff --git a/src/lib_ffi.c b/src/lib_ffi.c index 89baa356..42d71153 100644 --- a/src/lib_ffi.c +++ b/src/lib_ffi.c @@ -157,14 +157,13 @@ static int ffi_arith_ptr(lua_State *L, CTState *cts, FFIArith *fa, MMS mm) return 1; } } - if (!((mm == MM_add || mm == MM_sub) && - ctype_isnum(fa->ct[1]->info))) return 0; + if (!((mm == MM_add || mm == MM_sub) && ctype_isnum(fa->ct[1]->info))) + return 0; lj_cconv_ct_ct(cts, ctype_get(cts, CTID_INT_PSZ), fa->ct[1], (uint8_t *)&idx, fa->p[1], 0); if (mm == MM_sub) idx = -idx; - } else if (mm == MM_add && + } else if (mm == MM_add && ctype_isnum(ctp->info) && (ctype_isptr(fa->ct[1]->info) || ctype_isrefarray(fa->ct[1]->info))) { - if (!ctype_isnum(ctp->info)) return 0; /* Swap pointer and index. */ ctp = fa->ct[1]; pp = fa->p[1]; lj_cconv_ct_ct(cts, ctype_get(cts, CTID_INT_PSZ), fa->ct[0], @@ -264,8 +263,10 @@ static int ffi_arith(lua_State *L) FFIArith fa; MMS mm = (MMS)(curr_func(L)->c.ffid - (int)FF_ffi_meta___eq + (int)MM_eq); if (ffi_checkarith(L, cts, &fa)) { - if (ffi_arith_int64(L, cts, &fa, mm) || ffi_arith_ptr(L, cts, &fa, mm)) + if (ffi_arith_int64(L, cts, &fa, mm) || ffi_arith_ptr(L, cts, &fa, mm)) { + copyTV(L, &G(L)->tmptv2, L->top-1); /* Remember for trace recorder. */ return 1; + } } /* NYI: per-cdata metamethods. */ { @@ -319,7 +320,7 @@ LJLIB_CF(ffi_meta___newindex) LJLIB_REC(cdata_index 1) } /* The following functions must be in contiguous ORDER MM. */ -LJLIB_CF(ffi_meta___eq) +LJLIB_CF(ffi_meta___eq) LJLIB_REC(cdata_arith MM_eq) { return ffi_arith(L); } @@ -329,12 +330,12 @@ LJLIB_CF(ffi_meta___len) return ffi_arith(L); } -LJLIB_CF(ffi_meta___lt) +LJLIB_CF(ffi_meta___lt) LJLIB_REC(cdata_arith MM_lt) { return ffi_arith(L); } -LJLIB_CF(ffi_meta___le) +LJLIB_CF(ffi_meta___le) LJLIB_REC(cdata_arith MM_le) { return ffi_arith(L); } diff --git a/src/lj_asm.c b/src/lj_asm.c index af8ac51b..db126d74 100644 --- a/src/lj_asm.c +++ b/src/lj_asm.c @@ -2927,7 +2927,7 @@ static void asm_comp_(ASMState *as, IRIns *ir, int cc) IROp leftop = (IROp)(IR(lref)->o); Reg r64 = REX_64IR(ir, 0); int32_t imm = 0; - lua_assert(irt_isint(ir->t) || irt_isaddr(ir->t)); + lua_assert(irt_is64(ir->t) || irt_isint(ir->t) || irt_isaddr(ir->t)); /* Swap constants (only for ABC) and fusable loads to the right. */ if (irref_isk(lref) || (!irref_isk(rref) && opisfusableload(leftop))) { if ((cc & 0xc) == 0xc) cc ^= 3; /* L <-> G, LE <-> GE */ diff --git a/src/lj_crecord.c b/src/lj_crecord.c index e2b3e8af..c6577975 100644 --- a/src/lj_crecord.c +++ b/src/lj_crecord.c @@ -663,7 +663,20 @@ static TRef crec_arith_int64(jit_State *J, TRef *sp, CType **s, MMS mm) sp[i] = emitconv(sp[i], dt, IRT_INT, ((st - IRT_I8) & 1) ? 0 : IRCONV_SEXT); } - if (mm == MM_pow) { + if (mm < MM_add) { + /* Assume true comparison. Fixup and emit pending guard later. */ + IROp op; + if (mm == MM_eq) { + op = IR_EQ; + } else { + op = mm == MM_lt ? IR_LT : IR_LE; + if (dt == IRT_U64) + op += (IR_ULT-IR_LT); + } + lj_ir_set(J, IRTG(op, dt), sp[0], sp[1]); + J->postproc = LJ_POST_FIXGUARD; + return TREF_TRUE; + } else if (mm == MM_pow) { tr = lj_ir_call(J, IRCALL_lj_cdata_powi64, sp[0], sp[1], lj_ir_kint(J, (int)dt-(int)IRT_I64)); } else { @@ -683,35 +696,41 @@ static TRef crec_arith_ptr(jit_State *J, TRef *sp, CType **s, MMS mm) { CTState *cts = ctype_ctsG(J2G(J)); CType *ctp = s[0]; - CTSize sz; - if (!(mm == MM_add || mm == MM_sub)) - return 0; - if (ctype_ispointer(ctp->info)) { - sz = lj_ctype_size(cts, ctype_cid(ctp->info)); - if (mm == MM_sub && ctype_ispointer(s[1]->info)) { - /* Pointer difference. */ - TRef tr; - if (sz == 0 || (sz & (sz-1)) != 0) - return 0; /* NYI: integer division. */ - tr = emitir(IRT(IR_SUB, IRT_PTR), sp[0], sp[1]); - tr = emitir(IRT(IR_BSAR, IRT_INTP), tr, lj_ir_kint(J, lj_fls(sz))); + if (ctype_isptr(ctp->info) || ctype_isrefarray(ctp->info)) { + if ((mm == MM_sub || mm == MM_eq || mm == MM_lt || mm == MM_le) && + (ctype_isptr(s[1]->info) || ctype_isrefarray(s[1]->info))) { + if (mm == MM_sub) { /* Pointer difference. */ + TRef tr; + CTSize sz = lj_ctype_size(cts, ctype_cid(ctp->info)); + if (sz == 0 || (sz & (sz-1)) != 0) + return 0; /* NYI: integer division. */ + tr = emitir(IRT(IR_SUB, IRT_PTR), sp[0], sp[1]); + tr = emitir(IRT(IR_BSAR, IRT_INTP), tr, lj_ir_kint(J, lj_fls(sz))); #if LJ_64 - tr = emitconv(tr, IRT_NUM, IRT_INTP, 0); + tr = emitconv(tr, IRT_NUM, IRT_INTP, 0); #endif - return tr; + return tr; + } else { /* Pointer comparison (unsigned). */ + /* Assume true comparison. Fixup and emit pending guard later. */ + IROp op = mm == MM_eq ? IR_EQ : mm == MM_lt ? IR_ULT : IR_ULE; + lj_ir_set(J, IRTG(op, IRT_PTR), sp[0], sp[1]); + J->postproc = LJ_POST_FIXGUARD; + return TREF_TRUE; + } } - if (!ctype_isnum(s[1]->info)) return 0; - } else if (mm == MM_add && - ctype_isnum(ctp->info) && ctype_ispointer(s[1]->info)) { + if (!((mm == MM_add || mm == MM_sub) && ctype_isnum(s[1]->info))) + return 0; + } else if (mm == MM_add && ctype_isnum(ctp->info) && + (ctype_isptr(s[1]->info) || ctype_isrefarray(s[1]->info))) { TRef tr = sp[0]; sp[0] = sp[1]; sp[1] = tr; /* Swap pointer and index. */ ctp = s[1]; - sz = lj_ctype_size(cts, ctype_cid(ctp->info)); } else { return 0; } { TRef tr = sp[1]; IRType t = tref_type(tr); + CTSize sz = lj_ctype_size(cts, ctype_cid(ctp->info)); CTypeID id; #if LJ_64 if (t == IRT_NUM || t == IRT_FLOAT) diff --git a/src/lj_record.c b/src/lj_record.c index 1669fde1..c150e2e4 100644 --- a/src/lj_record.c +++ b/src/lj_record.c @@ -819,6 +819,7 @@ static void rec_mm_comp(jit_State *J, RecordIndex *ix, int op) /* Setup call to cdata comparison metamethod. */ static void rec_mm_comp_cdata(jit_State *J, RecordIndex *ix, int op, MMS mm) { + lj_snap_add(J); if (tref_iscdata(ix->val)) { ix->tab = ix->val; copyTV(J->L, &ix->tabv, &ix->valv);