LJ_FR2: Add support for trace recording and snapshots.
Contributed by Peter Cawley.
This commit is contained in:
231
src/lj_record.c
231
src/lj_record.c
@@ -87,30 +87,48 @@ static void rec_check_slots(jit_State *J)
|
||||
BCReg s, nslots = J->baseslot + J->maxslot;
|
||||
int32_t depth = 0;
|
||||
cTValue *base = J->L->base - J->baseslot;
|
||||
lua_assert(J->baseslot >= 1 && J->baseslot < LJ_MAX_JSLOTS);
|
||||
lua_assert(J->baseslot == 1 || (J->slot[J->baseslot-1] & TREF_FRAME));
|
||||
lua_assert(J->baseslot >= 1+LJ_FR2 && J->baseslot < LJ_MAX_JSLOTS);
|
||||
lua_assert(J->baseslot == 1+LJ_FR2 || (J->slot[J->baseslot-1] & TREF_FRAME));
|
||||
lua_assert(nslots < LJ_MAX_JSLOTS);
|
||||
for (s = 0; s < nslots; s++) {
|
||||
TRef tr = J->slot[s];
|
||||
if (tr) {
|
||||
cTValue *tv = &base[s];
|
||||
IRRef ref = tref_ref(tr);
|
||||
IRIns *ir;
|
||||
lua_assert(ref >= J->cur.nk && ref < J->cur.nins);
|
||||
ir = IR(ref);
|
||||
lua_assert(irt_t(ir->t) == tref_t(tr));
|
||||
IRIns *ir = NULL; /* Silence compiler. */
|
||||
if (!LJ_FR2 || ref || !(tr & (TREF_FRAME | TREF_CONT))) {
|
||||
lua_assert(ref >= J->cur.nk && ref < J->cur.nins);
|
||||
ir = IR(ref);
|
||||
lua_assert(irt_t(ir->t) == tref_t(tr));
|
||||
}
|
||||
if (s == 0) {
|
||||
lua_assert(tref_isfunc(tr));
|
||||
#if LJ_FR2
|
||||
} else if (s == 1) {
|
||||
lua_assert(0);
|
||||
#endif
|
||||
} else if ((tr & TREF_FRAME)) {
|
||||
GCfunc *fn = gco2func(frame_gc(tv));
|
||||
BCReg delta = (BCReg)(tv - frame_prev(tv));
|
||||
#if LJ_FR2
|
||||
if (ref)
|
||||
lua_assert(ir_knum(ir)->u64 == tv->u64);
|
||||
tr = J->slot[s-1];
|
||||
ir = IR(tref_ref(tr));
|
||||
#endif
|
||||
lua_assert(tref_isfunc(tr));
|
||||
if (tref_isk(tr)) lua_assert(fn == ir_kfunc(ir));
|
||||
lua_assert(s > delta ? (J->slot[s-delta] & TREF_FRAME) : (s == delta));
|
||||
lua_assert(s > delta + LJ_FR2 ? (J->slot[s-delta] & TREF_FRAME)
|
||||
: (s == delta + LJ_FR2));
|
||||
depth++;
|
||||
} else if ((tr & TREF_CONT)) {
|
||||
#if LJ_FR2
|
||||
if (ref)
|
||||
lua_assert(ir_knum(ir)->u64 == tv->u64);
|
||||
#else
|
||||
lua_assert(ir_kptr(ir) == gcrefp(tv->gcr, void));
|
||||
lua_assert((J->slot[s+1] & TREF_FRAME));
|
||||
#endif
|
||||
lua_assert((J->slot[s+1+LJ_FR2] & TREF_FRAME));
|
||||
depth++;
|
||||
} else {
|
||||
if (tvisnumber(tv))
|
||||
@@ -162,10 +180,10 @@ static TRef sload(jit_State *J, int32_t slot)
|
||||
/* Get TRef for current function. */
|
||||
static TRef getcurrf(jit_State *J)
|
||||
{
|
||||
if (J->base[-1])
|
||||
return J->base[-1];
|
||||
lua_assert(J->baseslot == 1);
|
||||
return sloadt(J, -1, IRT_FUNC, IRSLOAD_READONLY);
|
||||
if (J->base[-1-LJ_FR2])
|
||||
return J->base[-1-LJ_FR2];
|
||||
lua_assert(J->baseslot == 1+LJ_FR2);
|
||||
return sloadt(J, -1-LJ_FR2, IRT_FUNC, IRSLOAD_READONLY);
|
||||
}
|
||||
|
||||
/* Compare for raw object equality.
|
||||
@@ -509,7 +527,6 @@ static LoopEvent rec_for(jit_State *J, const BCIns *fori, int isforl)
|
||||
static LoopEvent rec_iterl(jit_State *J, const BCIns iterins)
|
||||
{
|
||||
BCReg ra = bc_a(iterins);
|
||||
lua_assert(!LJ_FR2); /* TODO_FR2: handle different frame setup. */
|
||||
if (!tref_isnil(getslot(J, ra))) { /* Looping back? */
|
||||
J->base[ra-1] = J->base[ra]; /* Copy result of ITERC to control var. */
|
||||
J->maxslot = ra-1+bc_b(J->pc[-1]);
|
||||
@@ -678,22 +695,31 @@ static void rec_call_setup(jit_State *J, BCReg func, ptrdiff_t nargs)
|
||||
{
|
||||
RecordIndex ix;
|
||||
TValue *functv = &J->L->base[func];
|
||||
TRef *fbase = &J->base[func];
|
||||
TRef kfunc, *fbase = &J->base[func];
|
||||
ptrdiff_t i;
|
||||
lua_assert(!LJ_FR2); /* TODO_FR2: handle different frame setup. */
|
||||
for (i = 0; i <= nargs; i++)
|
||||
(void)getslot(J, func+i); /* Ensure func and all args have a reference. */
|
||||
(void)getslot(J, func); /* Ensure func has a reference. */
|
||||
for (i = 1; i <= nargs; i++)
|
||||
(void)getslot(J, func+LJ_FR2+i); /* Ensure all args have a reference. */
|
||||
if (!tref_isfunc(fbase[0])) { /* Resolve __call metamethod. */
|
||||
ix.tab = fbase[0];
|
||||
copyTV(J->L, &ix.tabv, functv);
|
||||
if (!lj_record_mm_lookup(J, &ix, MM_call) || !tref_isfunc(ix.mobj))
|
||||
lj_trace_err(J, LJ_TRERR_NOMM);
|
||||
for (i = ++nargs; i > 0; i--) /* Shift arguments up. */
|
||||
fbase[i] = fbase[i-1];
|
||||
for (i = ++nargs; i > LJ_FR2; i--) /* Shift arguments up. */
|
||||
fbase[i+LJ_FR2] = fbase[i+LJ_FR2-1];
|
||||
#if LJ_FR2
|
||||
fbase[2] = fbase[0];
|
||||
#endif
|
||||
fbase[0] = ix.mobj; /* Replace function. */
|
||||
functv = &ix.mobjv;
|
||||
}
|
||||
fbase[0] = TREF_FRAME | rec_call_specialize(J, funcV(functv), fbase[0]);
|
||||
kfunc = rec_call_specialize(J, funcV(functv), fbase[0]);
|
||||
#if LJ_FR2
|
||||
fbase[0] = kfunc;
|
||||
fbase[1] = TREF_FRAME;
|
||||
#else
|
||||
fbase[0] = kfunc | TREF_FRAME;
|
||||
#endif
|
||||
J->maxslot = (BCReg)nargs;
|
||||
}
|
||||
|
||||
@@ -703,8 +729,8 @@ void lj_record_call(jit_State *J, BCReg func, ptrdiff_t nargs)
|
||||
rec_call_setup(J, func, nargs);
|
||||
/* Bump frame. */
|
||||
J->framedepth++;
|
||||
J->base += func+1;
|
||||
J->baseslot += func+1;
|
||||
J->base += func+1+LJ_FR2;
|
||||
J->baseslot += func+1+LJ_FR2;
|
||||
}
|
||||
|
||||
/* Record tail call. */
|
||||
@@ -720,7 +746,9 @@ void lj_record_tailcall(jit_State *J, BCReg func, ptrdiff_t nargs)
|
||||
func += cbase;
|
||||
}
|
||||
/* Move func + args down. */
|
||||
memmove(&J->base[-1], &J->base[func], sizeof(TRef)*(J->maxslot+1));
|
||||
if (LJ_FR2 && J->baseslot == 2)
|
||||
J->base[func+1] = 0;
|
||||
memmove(&J->base[-1-LJ_FR2], &J->base[func], sizeof(TRef)*(J->maxslot+1+LJ_FR2));
|
||||
/* Note: the new TREF_FRAME is now at J->base[-1] (even for slot #0). */
|
||||
/* Tailcalls can form a loop, so count towards the loop unroll limit. */
|
||||
if (++J->tailcalled > J->loopunroll)
|
||||
@@ -763,7 +791,7 @@ void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults)
|
||||
BCReg cbase = (BCReg)frame_delta(frame);
|
||||
if (--J->framedepth < 0)
|
||||
lj_trace_err(J, LJ_TRERR_NYIRETL);
|
||||
lua_assert(J->baseslot > 1);
|
||||
lua_assert(J->baseslot > 1+LJ_FR2);
|
||||
gotresults++;
|
||||
rbase += cbase;
|
||||
J->baseslot -= (BCReg)cbase;
|
||||
@@ -787,7 +815,7 @@ void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults)
|
||||
BCReg cbase = (BCReg)frame_delta(frame);
|
||||
if (--J->framedepth < 0) /* NYI: return of vararg func to lower frame. */
|
||||
lj_trace_err(J, LJ_TRERR_NYIRETL);
|
||||
lua_assert(J->baseslot > 1);
|
||||
lua_assert(J->baseslot > 1+LJ_FR2);
|
||||
rbase += cbase;
|
||||
J->baseslot -= (BCReg)cbase;
|
||||
J->base -= cbase;
|
||||
@@ -797,8 +825,7 @@ void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults)
|
||||
BCIns callins = *(frame_pc(frame)-1);
|
||||
ptrdiff_t nresults = bc_b(callins) ? (ptrdiff_t)bc_b(callins)-1 :gotresults;
|
||||
BCReg cbase = bc_a(callins);
|
||||
GCproto *pt = funcproto(frame_func(frame - (cbase+1-LJ_FR2)));
|
||||
lua_assert(!LJ_FR2); /* TODO_FR2: handle different frame teardown. */
|
||||
GCproto *pt = funcproto(frame_func(frame - (cbase+1+LJ_FR2)));
|
||||
if ((pt->flags & PROTO_NOJIT))
|
||||
lj_trace_err(J, LJ_TRERR_CJITOFF);
|
||||
if (J->framedepth == 0 && J->pt && frame == J->L->base - 1) {
|
||||
@@ -811,13 +838,13 @@ void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults)
|
||||
lj_snap_add(J);
|
||||
}
|
||||
for (i = 0; i < nresults; i++) /* Adjust results. */
|
||||
J->base[i-1] = i < gotresults ? J->base[rbase+i] : TREF_NIL;
|
||||
J->base[i-1-LJ_FR2] = i < gotresults ? J->base[rbase+i] : TREF_NIL;
|
||||
J->maxslot = cbase+(BCReg)nresults;
|
||||
if (J->framedepth > 0) { /* Return to a frame that is part of the trace. */
|
||||
J->framedepth--;
|
||||
lua_assert(J->baseslot > cbase+1);
|
||||
J->baseslot -= cbase+1;
|
||||
J->base -= cbase+1;
|
||||
lua_assert(J->baseslot > cbase+1+LJ_FR2);
|
||||
J->baseslot -= cbase+1+LJ_FR2;
|
||||
J->base -= cbase+1+LJ_FR2;
|
||||
} else if (J->parent == 0 && J->exitno == 0 &&
|
||||
!bc_isret(bc_op(J->cur.startins))) {
|
||||
/* Return to lower frame would leave the loop in a root trace. */
|
||||
@@ -827,13 +854,13 @@ void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults)
|
||||
} else { /* Return to lower frame. Guard for the target we return to. */
|
||||
TRef trpt = lj_ir_kgc(J, obj2gco(pt), IRT_PROTO);
|
||||
TRef trpc = lj_ir_kptr(J, (void *)frame_pc(frame));
|
||||
emitir(IRTG(IR_RETF, IRT_P32), trpt, trpc);
|
||||
emitir(IRTG(IR_RETF, IRT_PGC), trpt, trpc);
|
||||
J->retdepth++;
|
||||
J->needsnap = 1;
|
||||
lua_assert(J->baseslot == 1);
|
||||
lua_assert(J->baseslot == 1+LJ_FR2);
|
||||
/* Shift result slots up and clear the slots of the new frame below. */
|
||||
memmove(J->base + cbase, J->base-1, sizeof(TRef)*nresults);
|
||||
memset(J->base-1, 0, sizeof(TRef)*(cbase+1));
|
||||
memmove(J->base + cbase, J->base-1-LJ_FR2, sizeof(TRef)*nresults);
|
||||
memset(J->base-1-LJ_FR2, 0, sizeof(TRef)*(cbase+1+LJ_FR2));
|
||||
}
|
||||
} else if (frame_iscont(frame)) { /* Return to continuation frame. */
|
||||
ASMFunction cont = frame_contf(frame);
|
||||
@@ -842,32 +869,39 @@ void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults)
|
||||
lj_trace_err(J, LJ_TRERR_NYIRETL);
|
||||
J->baseslot -= (BCReg)cbase;
|
||||
J->base -= cbase;
|
||||
J->maxslot = cbase-2;
|
||||
J->maxslot = cbase-(2<<LJ_FR2);
|
||||
if (cont == lj_cont_ra) {
|
||||
/* Copy result to destination slot. */
|
||||
BCReg dst = bc_a(*(frame_contpc(frame)-1));
|
||||
J->base[dst] = gotresults ? J->base[cbase+rbase] : TREF_NIL;
|
||||
if (dst >= J->maxslot) J->maxslot = dst+1;
|
||||
if (dst >= J->maxslot) {
|
||||
J->maxslot = dst+1;
|
||||
}
|
||||
} else if (cont == lj_cont_nop) {
|
||||
/* Nothing to do here. */
|
||||
} else if (cont == lj_cont_cat) {
|
||||
BCReg bslot = bc_b(*(frame_contpc(frame)-1));
|
||||
TRef tr = gotresults ? J->base[cbase+rbase] : TREF_NIL;
|
||||
if (bslot != cbase-2) { /* Concatenate the remainder. */
|
||||
if (bslot != J->maxslot) { /* Concatenate the remainder. */
|
||||
TValue *b = J->L->base, save; /* Simulate lower frame and result. */
|
||||
J->base[cbase-2] = tr;
|
||||
copyTV(J->L, &save, b-2);
|
||||
if (gotresults) copyTV(J->L, b-2, b+rbase); else setnilV(b-2);
|
||||
J->base[J->maxslot] = tr;
|
||||
copyTV(J->L, &save, b-(2<<LJ_FR2));
|
||||
if (gotresults)
|
||||
copyTV(J->L, b-(2<<LJ_FR2), b+rbase);
|
||||
else
|
||||
setnilV(b-(2<<LJ_FR2));
|
||||
J->L->base = b - cbase;
|
||||
tr = rec_cat(J, bslot, cbase-2);
|
||||
tr = rec_cat(J, bslot, cbase-(2<<LJ_FR2));
|
||||
b = J->L->base + cbase; /* Undo. */
|
||||
J->L->base = b;
|
||||
copyTV(J->L, b-2, &save);
|
||||
copyTV(J->L, b-(2<<LJ_FR2), &save);
|
||||
}
|
||||
if (tr) { /* Store final result. */
|
||||
BCReg dst = bc_a(*(frame_contpc(frame)-1));
|
||||
J->base[dst] = tr;
|
||||
if (dst >= J->maxslot) J->maxslot = dst+1;
|
||||
if (dst >= J->maxslot) {
|
||||
J->maxslot = dst+1;
|
||||
}
|
||||
} /* Otherwise continue with another __concat call. */
|
||||
} else {
|
||||
/* Result type already specialized. */
|
||||
@@ -876,7 +910,7 @@ void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults)
|
||||
} else {
|
||||
lj_trace_err(J, LJ_TRERR_NYIRETL); /* NYI: handle return to C frame. */
|
||||
}
|
||||
lua_assert(J->baseslot >= 1);
|
||||
lua_assert(J->baseslot >= 1+LJ_FR2);
|
||||
}
|
||||
|
||||
/* -- Metamethod handling ------------------------------------------------- */
|
||||
@@ -885,11 +919,16 @@ void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults)
|
||||
static BCReg rec_mm_prep(jit_State *J, ASMFunction cont)
|
||||
{
|
||||
BCReg s, top = cont == lj_cont_cat ? J->maxslot : curr_proto(J->L)->framesize;
|
||||
#if LJ_FR2
|
||||
J->base[top] = lj_ir_k64(J, IR_KNUM, u64ptr(contptr(cont)));
|
||||
J->base[top+1] = TREF_CONT;
|
||||
#else
|
||||
J->base[top] = lj_ir_kptr(J, contptr(cont)) | TREF_CONT;
|
||||
#endif
|
||||
J->framedepth++;
|
||||
for (s = J->maxslot; s < top; s++)
|
||||
J->base[s] = 0; /* Clear frame gap to avoid resurrecting previous refs. */
|
||||
return top+1;
|
||||
return top+1+LJ_FR2;
|
||||
}
|
||||
|
||||
/* Record metamethod lookup. */
|
||||
@@ -967,9 +1006,9 @@ static TRef rec_mm_arith(jit_State *J, RecordIndex *ix, MMS mm)
|
||||
BCReg func = rec_mm_prep(J, mm == MM_concat ? lj_cont_cat : lj_cont_ra);
|
||||
TRef *base = J->base + func;
|
||||
TValue *basev = J->L->base + func;
|
||||
base[1] = ix->tab; base[2] = ix->key;
|
||||
copyTV(J->L, basev+1, &ix->tabv);
|
||||
copyTV(J->L, basev+2, &ix->keyv);
|
||||
base[1+LJ_FR2] = ix->tab; base[2+LJ_FR2] = ix->key;
|
||||
copyTV(J->L, basev+1+LJ_FR2, &ix->tabv);
|
||||
copyTV(J->L, basev+2+LJ_FR2, &ix->keyv);
|
||||
if (!lj_record_mm_lookup(J, ix, mm)) { /* Lookup mm on 1st operand. */
|
||||
if (mm != MM_unm) {
|
||||
ix->tab = ix->key;
|
||||
@@ -980,8 +1019,10 @@ static TRef rec_mm_arith(jit_State *J, RecordIndex *ix, MMS mm)
|
||||
lj_trace_err(J, LJ_TRERR_NOMM);
|
||||
}
|
||||
ok:
|
||||
lua_assert(!LJ_FR2); /* TODO_FR2: handle different frame setup. */
|
||||
base[0] = ix->mobj;
|
||||
#if LJ_FR2
|
||||
base[1] = 0;
|
||||
#endif
|
||||
copyTV(J->L, basev+0, &ix->mobjv);
|
||||
lj_record_call(J, func, 2);
|
||||
return 0; /* No result yet. */
|
||||
@@ -997,8 +1038,9 @@ static TRef rec_mm_len(jit_State *J, TRef tr, TValue *tv)
|
||||
BCReg func = rec_mm_prep(J, lj_cont_ra);
|
||||
TRef *base = J->base + func;
|
||||
TValue *basev = J->L->base + func;
|
||||
lua_assert(!LJ_FR2); /* TODO_FR2: handle different frame setup. */
|
||||
base[0] = ix.mobj; copyTV(J->L, basev+0, &ix.mobjv);
|
||||
base += LJ_FR2;
|
||||
basev += LJ_FR2;
|
||||
base[1] = tr; copyTV(J->L, basev+1, tv);
|
||||
#if LJ_52
|
||||
base[2] = tr; copyTV(J->L, basev+2, tv);
|
||||
@@ -1018,11 +1060,10 @@ static TRef rec_mm_len(jit_State *J, TRef tr, TValue *tv)
|
||||
static void rec_mm_callcomp(jit_State *J, RecordIndex *ix, int op)
|
||||
{
|
||||
BCReg func = rec_mm_prep(J, (op&1) ? lj_cont_condf : lj_cont_condt);
|
||||
TRef *base = J->base + func;
|
||||
TValue *tv = J->L->base + func;
|
||||
lua_assert(!LJ_FR2); /* TODO_FR2: handle different frame setup. */
|
||||
base[0] = ix->mobj; base[1] = ix->val; base[2] = ix->key;
|
||||
copyTV(J->L, tv+0, &ix->mobjv);
|
||||
TRef *base = J->base + func + LJ_FR2;
|
||||
TValue *tv = J->L->base + func + LJ_FR2;
|
||||
base[-LJ_FR2] = ix->mobj; base[1] = ix->val; base[2] = ix->key;
|
||||
copyTV(J->L, tv-LJ_FR2, &ix->mobjv);
|
||||
copyTV(J->L, tv+1, &ix->valv);
|
||||
copyTV(J->L, tv+2, &ix->keyv);
|
||||
lj_record_call(J, func, 2);
|
||||
@@ -1339,11 +1380,10 @@ TRef lj_record_idx(jit_State *J, RecordIndex *ix)
|
||||
handlemm:
|
||||
if (tref_isfunc(ix->mobj)) { /* Handle metamethod call. */
|
||||
BCReg func = rec_mm_prep(J, ix->val ? lj_cont_nop : lj_cont_ra);
|
||||
TRef *base = J->base + func;
|
||||
TValue *tv = J->L->base + func;
|
||||
lua_assert(!LJ_FR2); /* TODO_FR2: handle different frame setup. */
|
||||
base[0] = ix->mobj; base[1] = ix->tab; base[2] = ix->key;
|
||||
setfuncV(J->L, tv+0, funcV(&ix->mobjv));
|
||||
TRef *base = J->base + func + LJ_FR2;
|
||||
TValue *tv = J->L->base + func + LJ_FR2;
|
||||
base[-LJ_FR2] = ix->mobj; base[1] = ix->tab; base[2] = ix->key;
|
||||
setfuncV(J->L, tv-LJ_FR2, funcV(&ix->mobjv));
|
||||
copyTV(J->L, tv+1, &ix->tabv);
|
||||
copyTV(J->L, tv+2, &ix->keyv);
|
||||
if (ix->val) {
|
||||
@@ -1533,7 +1573,11 @@ static TRef rec_upvalue(jit_State *J, uint32_t uv, TRef val)
|
||||
goto noconstify;
|
||||
kfunc = lj_ir_kfunc(J, J->fn);
|
||||
emitir(IRTG(IR_EQ, IRT_FUNC), fn, kfunc);
|
||||
J->base[-1] = TREF_FRAME | kfunc;
|
||||
#if LJ_FR2
|
||||
J->base[-2] = kfunc;
|
||||
#else
|
||||
J->base[-1] = kfunc | TREF_FRAME;
|
||||
#endif
|
||||
fn = kfunc;
|
||||
}
|
||||
tr = lj_record_constify(J, uvval(uvp));
|
||||
@@ -1644,11 +1688,14 @@ static void rec_func_setup(jit_State *J)
|
||||
static void rec_func_vararg(jit_State *J)
|
||||
{
|
||||
GCproto *pt = J->pt;
|
||||
BCReg s, fixargs, vframe = J->maxslot+1;
|
||||
BCReg s, fixargs, vframe = J->maxslot+1+LJ_FR2;
|
||||
lua_assert((pt->flags & PROTO_VARARG));
|
||||
if (J->baseslot + vframe + pt->framesize >= LJ_MAX_JSLOTS)
|
||||
lj_trace_err(J, LJ_TRERR_STACKOV);
|
||||
J->base[vframe-1] = J->base[-1]; /* Copy function up. */
|
||||
J->base[vframe-1-LJ_FR2] = J->base[-1-LJ_FR2]; /* Copy function up. */
|
||||
#if LJ_FR2
|
||||
J->base[vframe-1] = TREF_FRAME;
|
||||
#endif
|
||||
/* Copy fixarg slots up and set their original slots to nil. */
|
||||
fixargs = pt->numparams < J->maxslot ? pt->numparams : J->maxslot;
|
||||
for (s = 0; s < fixargs; s++) {
|
||||
@@ -1710,7 +1757,7 @@ static int select_detect(jit_State *J)
|
||||
static void rec_varg(jit_State *J, BCReg dst, ptrdiff_t nresults)
|
||||
{
|
||||
int32_t numparams = J->pt->numparams;
|
||||
ptrdiff_t nvararg = frame_delta(J->L->base-1) - numparams - 1;
|
||||
ptrdiff_t nvararg = frame_delta(J->L->base-1) - numparams - 1 - LJ_FR2;
|
||||
lua_assert(frame_isvarg(J->L->base-1));
|
||||
if (J->framedepth > 0) { /* Simple case: varargs defined on-trace. */
|
||||
ptrdiff_t i;
|
||||
@@ -1722,10 +1769,10 @@ static void rec_varg(jit_State *J, BCReg dst, ptrdiff_t nresults)
|
||||
J->maxslot = dst + (BCReg)nresults;
|
||||
}
|
||||
for (i = 0; i < nresults; i++)
|
||||
J->base[dst+i] = i < nvararg ? getslot(J, i - nvararg - 1) : TREF_NIL;
|
||||
J->base[dst+i] = i < nvararg ? getslot(J, i - nvararg - 1 - LJ_FR2) : TREF_NIL;
|
||||
} else { /* Unknown number of varargs passed to trace. */
|
||||
TRef fr = emitir(IRTI(IR_SLOAD), 0, IRSLOAD_READONLY|IRSLOAD_FRAME);
|
||||
int32_t frofs = 8*(1+numparams)+FRAME_VARG;
|
||||
TRef fr = emitir(IRTI(IR_SLOAD), LJ_FR2, IRSLOAD_READONLY|IRSLOAD_FRAME);
|
||||
int32_t frofs = 8*(1+LJ_FR2+numparams)+FRAME_VARG;
|
||||
if (nresults >= 0) { /* Known fixed number of results. */
|
||||
ptrdiff_t i;
|
||||
if (nvararg > 0) {
|
||||
@@ -1739,7 +1786,7 @@ static void rec_varg(jit_State *J, BCReg dst, ptrdiff_t nresults)
|
||||
vbase = emitir(IRT(IR_SUB, IRT_IGC), REF_BASE, fr);
|
||||
vbase = emitir(IRT(IR_ADD, IRT_PGC), vbase, lj_ir_kint(J, frofs-8));
|
||||
for (i = 0; i < nload; i++) {
|
||||
IRType t = itype2irt(&J->L->base[i-1-nvararg]);
|
||||
IRType t = itype2irt(&J->L->base[i-1-LJ_FR2-nvararg]);
|
||||
TRef aref = emitir(IRT(IR_AREF, IRT_PGC),
|
||||
vbase, lj_ir_kint(J, (int32_t)i));
|
||||
TRef tr = emitir(IRTG(IR_VLOAD, t), aref, 0);
|
||||
@@ -1787,14 +1834,15 @@ static void rec_varg(jit_State *J, BCReg dst, ptrdiff_t nresults)
|
||||
if (idx != 0 && idx <= nvararg) {
|
||||
IRType t;
|
||||
TRef aref, vbase = emitir(IRT(IR_SUB, IRT_IGC), REF_BASE, fr);
|
||||
vbase = emitir(IRT(IR_ADD, IRT_PGC), vbase, lj_ir_kint(J, frofs-8));
|
||||
t = itype2irt(&J->L->base[idx-2-nvararg]);
|
||||
vbase = emitir(IRT(IR_ADD, IRT_PGC), vbase,
|
||||
lj_ir_kint(J, frofs-(8<<LJ_FR2)));
|
||||
t = itype2irt(&J->L->base[idx-2-LJ_FR2-nvararg]);
|
||||
aref = emitir(IRT(IR_AREF, IRT_PGC), vbase, tridx);
|
||||
tr = emitir(IRTG(IR_VLOAD, t), aref, 0);
|
||||
if (irtype_ispri(t)) tr = TREF_PRI(t); /* Canonicalize primitives. */
|
||||
}
|
||||
J->base[dst-2] = tr;
|
||||
J->maxslot = dst-1;
|
||||
J->base[dst-2-LJ_FR2] = tr;
|
||||
J->maxslot = dst-1-LJ_FR2;
|
||||
J->bcskip = 2; /* Skip CALLM + select. */
|
||||
} else {
|
||||
nyivarg:
|
||||
@@ -1887,7 +1935,15 @@ static void rec_comp_fixup(jit_State *J, const BCIns *pc, int cond)
|
||||
const BCIns *npc = pc + 2 + (cond ? bc_j(jmpins) : 0);
|
||||
SnapShot *snap = &J->cur.snap[J->cur.nsnap-1];
|
||||
/* Set PC to opposite target to avoid re-recording the comp. in side trace. */
|
||||
#if LJ_FR2
|
||||
SnapEntry *flink = &J->cur.snapmap[snap->mapofs + snap->nent];
|
||||
uint64_t pcbase;
|
||||
memcpy(&pcbase, flink, sizeof(uint64_t));
|
||||
pcbase = (pcbase & 0xff) | (u64ptr(npc) << 8);
|
||||
memcpy(flink, &pcbase, sizeof(uint64_t));
|
||||
#else
|
||||
J->cur.snapmap[snap->mapofs + snap->nent] = SNAP_MKPC(npc);
|
||||
#endif
|
||||
J->needsnap = 1;
|
||||
if (bc_a(jmpins) < J->maxslot) J->maxslot = bc_a(jmpins);
|
||||
lj_snap_shrink(J); /* Shrink last snapshot if possible. */
|
||||
@@ -2185,7 +2241,13 @@ void lj_record_ins(jit_State *J)
|
||||
|
||||
case BC_MOV:
|
||||
/* Clear gap of method call to avoid resurrecting previous refs. */
|
||||
if (ra > J->maxslot) J->base[ra-1] = 0;
|
||||
if (ra > J->maxslot) {
|
||||
#if LJ_FR2
|
||||
memset(J->base + J->maxslot, 0, (ra - J->maxslot) * sizeof(TRef));
|
||||
#else
|
||||
J->base[ra-1] = 0;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case BC_KSTR: case BC_KNUM: case BC_KPRI:
|
||||
break;
|
||||
@@ -2254,14 +2316,14 @@ void lj_record_ins(jit_State *J)
|
||||
/* -- Calls and vararg handling ----------------------------------------- */
|
||||
|
||||
case BC_ITERC:
|
||||
J->base[ra] = getslot(J, ra-3-LJ_FR2);
|
||||
J->base[ra+1] = getslot(J, ra-2-LJ_FR2);
|
||||
J->base[ra+2] = getslot(J, ra-1-LJ_FR2);
|
||||
J->base[ra] = getslot(J, ra-3);
|
||||
J->base[ra+1+LJ_FR2] = getslot(J, ra-2);
|
||||
J->base[ra+2+LJ_FR2] = getslot(J, ra-1);
|
||||
{ /* Do the actual copy now because lj_record_call needs the values. */
|
||||
TValue *b = &J->L->base[ra];
|
||||
copyTV(J->L, b, b-3-LJ_FR2);
|
||||
copyTV(J->L, b+1, b-2-LJ_FR2);
|
||||
copyTV(J->L, b+2, b-1-LJ_FR2);
|
||||
copyTV(J->L, b, b-3);
|
||||
copyTV(J->L, b+1+LJ_FR2, b-2);
|
||||
copyTV(J->L, b+2+LJ_FR2, b-1);
|
||||
}
|
||||
lj_record_call(J, ra, (ptrdiff_t)rc-1);
|
||||
break;
|
||||
@@ -2384,7 +2446,12 @@ void lj_record_ins(jit_State *J)
|
||||
/* rc == 0 if we have no result yet, e.g. pending __index metamethod call. */
|
||||
if (bcmode_a(op) == BCMdst && rc) {
|
||||
J->base[ra] = rc;
|
||||
if (ra >= J->maxslot) J->maxslot = ra+1;
|
||||
if (ra >= J->maxslot) {
|
||||
#if LJ_FR2
|
||||
if (ra > J->maxslot) J->base[ra-1] = 0;
|
||||
#endif
|
||||
J->maxslot = ra+1;
|
||||
}
|
||||
}
|
||||
|
||||
#undef rav
|
||||
@@ -2469,7 +2536,7 @@ void lj_record_setup(jit_State *J)
|
||||
J->scev.idx = REF_NIL;
|
||||
setmref(J->scev.pc, NULL);
|
||||
|
||||
J->baseslot = 1; /* Invoking function is at base[-1]. */
|
||||
J->baseslot = 1+LJ_FR2; /* Invoking function is at base[-1-LJ_FR2]. */
|
||||
J->base = J->slot + J->baseslot;
|
||||
J->maxslot = 0;
|
||||
J->framedepth = 0;
|
||||
|
||||
Reference in New Issue
Block a user