From 19b69f21d409375ad8362c04186b246c1749fc8e Mon Sep 17 00:00:00 2001 From: Mike Pall Date: Tue, 1 Apr 2014 00:30:22 +0200 Subject: [PATCH] FFI: Allow non-scalar cdata to be compared for equality by address. --- src/lj_carith.c | 6 +++-- src/lj_crecord.c | 61 +++++++++++++++++++++++++++--------------------- 2 files changed, 38 insertions(+), 29 deletions(-) diff --git a/src/lj_carith.c b/src/lj_carith.c index 9f94091d..92fe5597 100644 --- a/src/lj_carith.c +++ b/src/lj_carith.c @@ -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++) { diff --git a/src/lj_crecord.c b/src/lj_crecord.c index da9013f0..71f3d069 100644 --- a/src/lj_crecord.c +++ b/src/lj_crecord.c @@ -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); } } }