diff --git a/src/lj_jit.h b/src/lj_jit.h index 6c930034..55d6d0df 100644 --- a/src/lj_jit.h +++ b/src/lj_jit.h @@ -104,9 +104,15 @@ typedef enum { LJ_TRACE_START, /* New trace started. */ LJ_TRACE_END, /* End of trace. */ LJ_TRACE_ASM, /* Assemble trace. */ - LJ_TRACE_ERR, /* Trace aborted with error. */ + LJ_TRACE_ERR /* Trace aborted with error. */ } TraceState; +/* Post-processing action. */ +typedef enum { + LJ_POST_NONE, /* No action. */ + LJ_POST_FIXGUARD /* Fixup and emit pending guard. */ +} PostProc; + /* Machine code type. */ typedef uint8_t MCode; @@ -284,6 +290,8 @@ typedef struct jit_State { SnapEntry *snapmapbuf; /* Temp. snapshot map buffer. */ MSize sizesnapmap; /* Size of temp. snapshot map buffer. */ + PostProc postproc; /* Required post-processing after execution. */ + GCRef *trace; /* Array of traces. */ TraceNo freetrace; /* Start of scan for next free trace. */ MSize sizetrace; /* Size of trace array. */ diff --git a/src/lj_record.c b/src/lj_record.c index dc3f3df0..1669fde1 100644 --- a/src/lj_record.c +++ b/src/lj_record.c @@ -1365,6 +1365,26 @@ void lj_record_ins(jit_State *J) BCOp op; TRef ra, rb, rc; + /* Perform post-processing action before recording the next instruction. */ + if (LJ_UNLIKELY(J->postproc != LJ_POST_NONE)) { + switch (J->postproc) { + case LJ_POST_FIXGUARD: /* Fixup and emit pending guard. */ + if (!tvistruecond(&J2G(J)->tmptv2)) { + BCReg s; + J->fold.ins.o ^= 1; /* Flip guard to opposite. */ + for (s = 0; s < J->maxslot; s++) /* Fixup stack slot (if any). */ + if (J->base[s] == TREF_TRUE && tvisfalse(&J->L->base[s])) { + J->base[s] = TREF_FALSE; + break; + } + } + lj_opt_fold(J); /* Emit pending guard. */ + break; + default: lua_assert(0); break; + } + J->postproc = LJ_POST_NONE; + } + /* Need snapshot before recording next bytecode (e.g. after a store). */ if (J->needsnap) { J->needsnap = 0; diff --git a/src/lj_trace.c b/src/lj_trace.c index c508c02a..421278e1 100644 --- a/src/lj_trace.c +++ b/src/lj_trace.c @@ -388,6 +388,7 @@ static void trace_start(jit_State *J) J->needsnap = 0; J->bcskip = 0; J->guardemit.irt = 0; + J->postproc = LJ_POST_NONE; setgcref(J->cur.startpt, obj2gco(J->pt)); L = J->L; @@ -454,6 +455,7 @@ static void trace_stop(jit_State *J) /* Commit new mcode only after all patching is done. */ lj_mcode_commit(J, J->cur.mcode); + J->postproc = LJ_POST_NONE; trace_save(J); L = J->L; @@ -485,6 +487,7 @@ static int trace_abort(jit_State *J) TraceError e = LJ_TRERR_RECERR; TraceNo traceno; + J->postproc = LJ_POST_NONE; lj_mcode_abort(J); if (tvisnum(L->top-1)) e = (TraceError)lj_num2int(numV(L->top-1));