diff --git a/src/Makefile.dep b/src/Makefile.dep index b9d0df47..afcf5c12 100644 --- a/src/Makefile.dep +++ b/src/Makefile.dep @@ -93,7 +93,7 @@ lj_crecord.o: lj_crecord.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_frame.h lj_bc.h lj_ctype.h \ lj_gc.h lj_cdata.h lj_cparse.h lj_cconv.h lj_clib.h lj_ccall.h lj_ir.h \ lj_jit.h lj_ircall.h lj_iropt.h lj_trace.h lj_dispatch.h lj_traceerr.h \ - lj_record.h lj_ffrecord.h lj_crecord.h + lj_record.h lj_ffrecord.h lj_snap.h lj_crecord.h lj_ctype.o: lj_ctype.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_ctype.h lj_ccallback.h lj_debug.o: lj_debug.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ diff --git a/src/lj_cconv.c b/src/lj_cconv.c index d73984f4..9d478355 100644 --- a/src/lj_cconv.c +++ b/src/lj_cconv.c @@ -391,7 +391,7 @@ int lj_cconv_tv_ct(CTState *cts, CType *s, CTypeID sid, lua_assert(tvisnum(o)); } } else { - uint32_t b = ((*sp) & 1); + uint32_t b = (*sp != 0); setboolV(o, b); setboolV(&cts->g->tmptv2, b); /* Remember for trace recorder. */ } diff --git a/src/lj_crecord.c b/src/lj_crecord.c index 9457b519..313bee81 100644 --- a/src/lj_crecord.c +++ b/src/lj_crecord.c @@ -27,6 +27,7 @@ #include "lj_trace.h" #include "lj_record.h" #include "lj_ffrecord.h" +#include "lj_snap.h" #include "lj_crecord.h" #include "lj_dispatch.h" @@ -839,6 +840,26 @@ static TRef crec_call_args(jit_State *J, RecordFFData *rd, return tr; } +/* Create a snapshot for the caller, simulating a 'false' return value. */ +static void crec_snap_caller(jit_State *J) +{ + lua_State *L = J->L; + TValue *base = L->base, *top = L->top; + const BCIns *pc = J->pc; + TRef ftr = J->base[-1]; + ptrdiff_t delta; + if (!frame_islua(base-1)) + lj_trace_err(J, LJ_TRERR_NYICALL); + J->pc = frame_pc(base-1); delta = 1+bc_a(J->pc[-1]); + L->top = base; L->base = base - delta; + J->base[-1] = TREF_FALSE; + J->base -= delta; J->baseslot -= delta; J->maxslot = delta; J->framedepth--; + lj_snap_add(J); + L->base = base; L->top = top; + J->framedepth++; J->base += delta; J->baseslot += delta; J->maxslot = 1; + J->base[-1] = ftr; J->pc = pc; +} + /* Record function call. */ static int crec_call(jit_State *J, RecordFFData *rd, GCcdata *cd) { @@ -867,8 +888,7 @@ static int crec_call(jit_State *J, RecordFFData *rd, GCcdata *cd) ctr = ctype_child(cts, ctr); } if (!(ctype_isnum(ctr->info) || ctype_isptr(ctr->info) || - ctype_isvoid(ctr->info)) || - ctype_isbool(ctr->info) || t == IRT_CDATA) + ctype_isvoid(ctr->info)) || t == IRT_CDATA) lj_trace_err(J, LJ_TRERR_NYICALL); if ((ct->info & CTF_VARARG) #if LJ_TARGET_X86 @@ -878,7 +898,12 @@ static int crec_call(jit_State *J, RecordFFData *rd, GCcdata *cd) func = emitir(IRT(IR_CARG, IRT_NIL), func, lj_ir_kint(J, ctype_typeid(cts, ct))); tr = emitir(IRT(IR_CALLXS, t), crec_call_args(J, rd, cts, ct), func); - if (t == IRT_FLOAT || t == IRT_U32) { + if (ctype_isbool(ctr->info)) { + crec_snap_caller(J); + lj_ir_set(J, IRTGI(IR_NE), tr, lj_ir_kint(J, 0)); + J->postproc = LJ_POST_FIXGUARDSNAP; + tr = TREF_TRUE; + } else if (t == IRT_FLOAT || t == IRT_U32) { tr = emitconv(tr, IRT_NUM, t, 0); } else if (t == IRT_I8 || t == IRT_I16) { tr = emitconv(tr, IRT_INT, t, IRCONV_SEXT); diff --git a/src/lj_jit.h b/src/lj_jit.h index 11dc9737..8a4c04c8 100644 --- a/src/lj_jit.h +++ b/src/lj_jit.h @@ -122,6 +122,7 @@ typedef enum { LJ_POST_NONE, /* No action. */ LJ_POST_FIXCOMP, /* Fixup comparison and emit pending guard. */ LJ_POST_FIXGUARD, /* Fixup and emit pending guard. */ + LJ_POST_FIXGUARDSNAP, /* Fixup and emit pending guard and snapshot. */ LJ_POST_FIXBOOL, /* Fixup boolean result. */ LJ_POST_FFRETRY /* Suppress recording of retried fast functions. */ } PostProc; diff --git a/src/lj_record.c b/src/lj_record.c index a76f5d94..2c27a718 100644 --- a/src/lj_record.c +++ b/src/lj_record.c @@ -1573,8 +1573,14 @@ void lj_record_ins(jit_State *J) rec_comp_fixup(J, pc, (!tvistruecond(&J2G(J)->tmptv2) ^ (bc_op(*pc)&1))); /* fallthrough */ case LJ_POST_FIXGUARD: /* Fixup and emit pending guard. */ - if (!tvistruecond(&J2G(J)->tmptv2)) + case LJ_POST_FIXGUARDSNAP: /* Fixup and emit pending guard and snapshot. */ + if (!tvistruecond(&J2G(J)->tmptv2)) { J->fold.ins.o ^= 1; /* Flip guard to opposite. */ + if (J->postproc == LJ_POST_FIXGUARDSNAP) { + SnapShot *snap = &J->cur.snap[J->cur.nsnap-1]; + J->cur.snapmap[snap->mapofs+snap->nent-1]--; /* False -> true. */ + } + } lj_opt_fold(J); /* Emit pending guard. */ /* fallthrough */ case LJ_POST_FIXBOOL: