FFI: Allow non-scalar cdata to be compared for equality by address.

This commit is contained in:
Mike Pall 2014-04-01 00:30:22 +02:00
parent c735293921
commit 19b69f21d4
2 changed files with 38 additions and 29 deletions

View File

@ -73,7 +73,7 @@ static int carith_checkarg(lua_State *L, CTState *cts, CDArith *ca)
ok = 1;
} else {
ca->ct[1-i] = ct; /* Use enum to improve error message. */
ca->p[1-i] = NULL;
ca->p[1-i] = (void *)(intptr_t)1; /* To make it unequal. */
break;
}
}
@ -234,7 +234,9 @@ static int lj_carith_meta(lua_State *L, CTState *cts, CDArith *ca, MMS mm)
const char *repr[2];
int i, isenum = -1, isstr = -1;
if (mm == MM_eq) { /* Equality checks never raise an error. */
setboolV(L->top-1, 0);
int eq = ca->p[0] == ca->p[1];
setboolV(L->top-1, eq);
setboolV(&G(L)->tmptv2, eq); /* Remember for trace recorder. */
return 1;
}
for (i = 0; i < 2; i++) {

View File

@ -1317,7 +1317,8 @@ static TRef crec_arith_ptr(jit_State *J, TRef *sp, CType **s, MMS mm)
}
/* Record ctype arithmetic metamethods. */
static void crec_arith_meta(jit_State *J, CTState *cts, RecordFFData *rd)
static TRef crec_arith_meta(jit_State *J, TRef *sp, CTState *cts,
RecordFFData *rd)
{
cTValue *tv = NULL;
if (J->base[0]) {
@ -1338,13 +1339,20 @@ static void crec_arith_meta(jit_State *J, CTState *cts, RecordFFData *rd)
if (tvisfunc(tv)) {
J->base[-1] = lj_ir_kfunc(J, funcV(tv)) | TREF_FRAME;
rd->nres = -1; /* Pending tailcall. */
return;
return 0;
} /* NYI: non-function metamethods. */
} else if ((MMS)rd->data == MM_eq) {
J->base[0] = TREF_FALSE;
return;
} else if ((MMS)rd->data == MM_eq) { /* Fallback cdata pointer comparison. */
if (sp[0] && sp[1]) {
/* Assume true comparison. Fixup and emit pending guard later. */
lj_ir_set(J, IRTG(IR_EQ, IRT_PTR), sp[0], sp[1]);
J->postproc = LJ_POST_FIXGUARD;
return TREF_TRUE;
} else {
return TREF_FALSE;
}
}
lj_trace_err(J, LJ_TRERR_BADTYPE);
return 0;
}
void LJ_FASTCALL recff_cdata_arith(jit_State *J, RecordFFData *rd)
@ -1357,7 +1365,7 @@ void LJ_FASTCALL recff_cdata_arith(jit_State *J, RecordFFData *rd)
TRef tr = J->base[i];
CType *ct = ctype_get(cts, CTID_DOUBLE);
if (!tr) {
goto trymeta;
lj_trace_err(J, LJ_TRERR_BADTYPE);
} else if (tref_iscdata(tr)) {
CTypeID id = argv2cdata(J, tr, &rd->argv[i])->ctypeid;
IRType t;
@ -1387,11 +1395,12 @@ void LJ_FASTCALL recff_cdata_arith(jit_State *J, RecordFFData *rd)
}
if (ctype_isenum(ct->info)) ct = ctype_child(cts, ct);
if (ctype_isnum(ct->info)) {
if (t == IRT_CDATA) goto trymeta;
if (t == IRT_I64 || t == IRT_U64) lj_needsplit(J);
tr = emitir(IRT(IR_XLOAD, t), tr, 0);
} else if (!(ctype_isptr(ct->info) || ctype_isrefarray(ct->info))) {
goto trymeta;
if (t == IRT_CDATA) {
tr = 0;
} else {
if (t == IRT_I64 || t == IRT_U64) lj_needsplit(J);
tr = emitir(IRT(IR_XLOAD, t), tr, 0);
}
}
} else if (tref_isnil(tr)) {
tr = lj_ir_kptr(J, NULL);
@ -1414,7 +1423,7 @@ void LJ_FASTCALL recff_cdata_arith(jit_State *J, RecordFFData *rd)
} /* else: interpreter will throw. */
} /* else: interpreter will throw. */
} else if (!tref_isnum(tr)) {
goto trymeta;
tr = 0;
}
ok:
s[i] = ct;
@ -1422,22 +1431,20 @@ void LJ_FASTCALL recff_cdata_arith(jit_State *J, RecordFFData *rd)
}
{
TRef tr;
if ((tr = crec_arith_int64(J, sp, s, (MMS)rd->data)) ||
(tr = crec_arith_ptr(J, sp, s, (MMS)rd->data))) {
J->base[0] = tr;
/* Fixup cdata comparisons, too. Avoids some cdata escapes. */
if (J->postproc == LJ_POST_FIXGUARD && frame_iscont(J->L->base-1) &&
!irt_isguard(J->guardemit)) {
const BCIns *pc = frame_contpc(J->L->base-1) - 1;
if (bc_op(*pc) <= BC_ISNEP) {
setframe_pc(&J2G(J)->tmptv, pc);
J2G(J)->tmptv.u32.lo = ((tref_istrue(tr) ^ bc_op(*pc)) & 1);
J->postproc = LJ_POST_FIXCOMP;
}
if (!(tr = crec_arith_int64(J, sp, s, (MMS)rd->data)) &&
!(tr = crec_arith_ptr(J, sp, s, (MMS)rd->data)) &&
!(tr = crec_arith_meta(J, sp, cts, rd)))
return;
J->base[0] = tr;
/* Fixup cdata comparisons, too. Avoids some cdata escapes. */
if (J->postproc == LJ_POST_FIXGUARD && frame_iscont(J->L->base-1) &&
!irt_isguard(J->guardemit)) {
const BCIns *pc = frame_contpc(J->L->base-1) - 1;
if (bc_op(*pc) <= BC_ISNEP) {
setframe_pc(&J2G(J)->tmptv, pc);
J2G(J)->tmptv.u32.lo = ((tref_istrue(tr) ^ bc_op(*pc)) & 1);
J->postproc = LJ_POST_FIXCOMP;
}
} else {
trymeta:
crec_arith_meta(J, cts, rd);
}
}
}