Merge branch 'master' into v2.1

This commit is contained in:
Mike Pall 2014-04-01 00:34:13 +02:00
commit caefd06871
2 changed files with 38 additions and 29 deletions

View File

@ -75,7 +75,7 @@ static int carith_checkarg(lua_State *L, CTState *cts, CDArith *ca)
ok = 1; ok = 1;
} else { } else {
ca->ct[1-i] = ct; /* Use enum to improve error message. */ 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; break;
} }
} }
@ -236,7 +236,9 @@ static int lj_carith_meta(lua_State *L, CTState *cts, CDArith *ca, MMS mm)
const char *repr[2]; const char *repr[2];
int i, isenum = -1, isstr = -1; int i, isenum = -1, isstr = -1;
if (mm == MM_eq) { /* Equality checks never raise an error. */ 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; return 1;
} }
for (i = 0; i < 2; i++) { for (i = 0; i < 2; i++) {

View File

@ -1349,7 +1349,8 @@ static TRef crec_arith_ptr(jit_State *J, TRef *sp, CType **s, MMS mm)
} }
/* Record ctype arithmetic metamethods. */ /* 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; cTValue *tv = NULL;
if (J->base[0]) { if (J->base[0]) {
@ -1370,13 +1371,20 @@ static void crec_arith_meta(jit_State *J, CTState *cts, RecordFFData *rd)
if (tvisfunc(tv)) { if (tvisfunc(tv)) {
J->base[-1] = lj_ir_kfunc(J, funcV(tv)) | TREF_FRAME; J->base[-1] = lj_ir_kfunc(J, funcV(tv)) | TREF_FRAME;
rd->nres = -1; /* Pending tailcall. */ rd->nres = -1; /* Pending tailcall. */
return; return 0;
} /* NYI: non-function metamethods. */ } /* NYI: non-function metamethods. */
} else if ((MMS)rd->data == MM_eq) { } else if ((MMS)rd->data == MM_eq) { /* Fallback cdata pointer comparison. */
J->base[0] = TREF_FALSE; if (sp[0] && sp[1]) {
return; /* 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); lj_trace_err(J, LJ_TRERR_BADTYPE);
return 0;
} }
void LJ_FASTCALL recff_cdata_arith(jit_State *J, RecordFFData *rd) void LJ_FASTCALL recff_cdata_arith(jit_State *J, RecordFFData *rd)
@ -1389,7 +1397,7 @@ void LJ_FASTCALL recff_cdata_arith(jit_State *J, RecordFFData *rd)
TRef tr = J->base[i]; TRef tr = J->base[i];
CType *ct = ctype_get(cts, CTID_DOUBLE); CType *ct = ctype_get(cts, CTID_DOUBLE);
if (!tr) { if (!tr) {
goto trymeta; lj_trace_err(J, LJ_TRERR_BADTYPE);
} else if (tref_iscdata(tr)) { } else if (tref_iscdata(tr)) {
CTypeID id = argv2cdata(J, tr, &rd->argv[i])->ctypeid; CTypeID id = argv2cdata(J, tr, &rd->argv[i])->ctypeid;
IRType t; IRType t;
@ -1419,11 +1427,12 @@ void LJ_FASTCALL recff_cdata_arith(jit_State *J, RecordFFData *rd)
} }
if (ctype_isenum(ct->info)) ct = ctype_child(cts, ct); if (ctype_isenum(ct->info)) ct = ctype_child(cts, ct);
if (ctype_isnum(ct->info)) { if (ctype_isnum(ct->info)) {
if (t == IRT_CDATA) goto trymeta; if (t == IRT_CDATA) {
if (t == IRT_I64 || t == IRT_U64) lj_needsplit(J); tr = 0;
tr = emitir(IRT(IR_XLOAD, t), tr, 0); } else {
} else if (!(ctype_isptr(ct->info) || ctype_isrefarray(ct->info))) { if (t == IRT_I64 || t == IRT_U64) lj_needsplit(J);
goto trymeta; tr = emitir(IRT(IR_XLOAD, t), tr, 0);
}
} }
} else if (tref_isnil(tr)) { } else if (tref_isnil(tr)) {
tr = lj_ir_kptr(J, NULL); tr = lj_ir_kptr(J, NULL);
@ -1446,7 +1455,7 @@ void LJ_FASTCALL recff_cdata_arith(jit_State *J, RecordFFData *rd)
} /* else: interpreter will throw. */ } /* else: interpreter will throw. */
} /* else: interpreter will throw. */ } /* else: interpreter will throw. */
} else if (!tref_isnum(tr)) { } else if (!tref_isnum(tr)) {
goto trymeta; tr = 0;
} }
ok: ok:
s[i] = ct; s[i] = ct;
@ -1454,22 +1463,20 @@ void LJ_FASTCALL recff_cdata_arith(jit_State *J, RecordFFData *rd)
} }
{ {
TRef tr; TRef tr;
if ((tr = crec_arith_int64(J, sp, s, (MMS)rd->data)) || if (!(tr = crec_arith_int64(J, sp, s, (MMS)rd->data)) &&
(tr = crec_arith_ptr(J, sp, s, (MMS)rd->data))) { !(tr = crec_arith_ptr(J, sp, s, (MMS)rd->data)) &&
J->base[0] = tr; !(tr = crec_arith_meta(J, sp, cts, rd)))
/* Fixup cdata comparisons, too. Avoids some cdata escapes. */ return;
if (J->postproc == LJ_POST_FIXGUARD && frame_iscont(J->L->base-1) && J->base[0] = tr;
!irt_isguard(J->guardemit)) { /* Fixup cdata comparisons, too. Avoids some cdata escapes. */
const BCIns *pc = frame_contpc(J->L->base-1) - 1; if (J->postproc == LJ_POST_FIXGUARD && frame_iscont(J->L->base-1) &&
if (bc_op(*pc) <= BC_ISNEP) { !irt_isguard(J->guardemit)) {
setframe_pc(&J2G(J)->tmptv, pc); const BCIns *pc = frame_contpc(J->L->base-1) - 1;
J2G(J)->tmptv.u32.lo = ((tref_istrue(tr) ^ bc_op(*pc)) & 1); if (bc_op(*pc) <= BC_ISNEP) {
J->postproc = LJ_POST_FIXCOMP; 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);
} }
} }
} }