Update LuaJIT to the latest 2.1.0 source (f3c8569)

This commit is contained in:
Alex Szpakowski
2021-12-03 20:50:23 -04:00
parent 4f24e5473f
commit c3986a9541
216 changed files with 6026 additions and 1838 deletions
+163 -19
View File
@@ -1,6 +1,6 @@
/*
** Trace recorder (bytecode -> SSA IR).
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
*/
#define lj_record_c
@@ -156,6 +156,9 @@ static void rec_check_slots(jit_State *J)
lj_assertJ((J->slot[s+1+LJ_FR2] & TREF_FRAME),
"cont slot %d not followed by frame", s);
depth++;
} else if ((tr & TREF_KEYINDEX)) {
lj_assertJ(tref_isint(tr), "keyindex slot %d bad type %d",
s, tref_type(tr));
} else {
/* Number repr. may differ, but other types must be the same. */
lj_assertJ(tvisnumber(tv) ? tref_isnumber(tr) :
@@ -259,6 +262,14 @@ TRef lj_record_constify(jit_State *J, cTValue *o)
return 0; /* Can't represent lightuserdata (pointless). */
}
/* Emit a VLOAD with the correct type. */
TRef lj_record_vload(jit_State *J, TRef ref, MSize idx, IRType t)
{
TRef tr = emitir(IRTG(IR_VLOAD, t), ref, idx);
if (irtype_ispri(t)) tr = TREF_PRI(t); /* Canonicalize primitives. */
return tr;
}
/* -- Record loop ops ----------------------------------------------------- */
/* Loop event. */
@@ -275,9 +286,9 @@ static void canonicalize_slots(jit_State *J)
if (LJ_DUALNUM) return;
for (s = J->baseslot+J->maxslot-1; s >= 1; s--) {
TRef tr = J->slot[s];
if (tref_isinteger(tr)) {
if (tref_isinteger(tr) && !(tr & TREF_KEYINDEX)) {
IRIns *ir = IR(tref_ref(tr));
if (!(ir->o == IR_SLOAD && (ir->op2 & IRSLOAD_READONLY)))
if (!(ir->o == IR_SLOAD && (ir->op2 & (IRSLOAD_READONLY))))
J->slot[s] = emitir(IRTN(IR_CONV), tr, IRCONV_NUM_INT);
}
}
@@ -598,6 +609,7 @@ static void rec_loop_interp(jit_State *J, const BCIns *pc, LoopEvent ev)
{
if (J->parent == 0 && J->exitno == 0) {
if (pc == J->startpc && J->framedepth + J->retdepth == 0) {
if (bc_op(J->cur.startins) == BC_ITERN) return; /* See rec_itern(). */
/* Same loop? */
if (ev == LOOPEV_LEAVE) /* Must loop back to form a root trace. */
lj_trace_err(J, LJ_TRERR_LLEAVE);
@@ -638,6 +650,70 @@ static void rec_loop_jit(jit_State *J, TraceNo lnk, LoopEvent ev)
} /* Side trace continues across a loop that's left or not entered. */
}
/* Record ITERN. */
static LoopEvent rec_itern(jit_State *J, BCReg ra, BCReg rb)
{
#if LJ_BE
/* YAGNI: Disabled on big-endian due to issues with lj_vm_next,
** IR_HIOP, RID_RETLO/RID_RETHI and ra_destpair.
*/
UNUSED(ra); UNUSED(rb);
setintV(&J->errinfo, (int32_t)BC_ITERN);
lj_trace_err_info(J, LJ_TRERR_NYIBC);
#else
RecordIndex ix;
/* Since ITERN is recorded at the start, we need our own loop detection. */
if (J->pc == J->startpc &&
(J->cur.nins > REF_FIRST+1 ||
(J->cur.nins == REF_FIRST+1 && J->cur.ir[REF_FIRST].o != IR_PROF)) &&
J->framedepth + J->retdepth == 0 && J->parent == 0 && J->exitno == 0) {
lj_record_stop(J, LJ_TRLINK_LOOP, J->cur.traceno); /* Looping trace. */
return LOOPEV_ENTER;
}
J->maxslot = ra;
lj_snap_add(J); /* Required to make JLOOP the first ins in a side-trace. */
ix.tab = getslot(J, ra-2);
ix.key = J->base[ra-1] ? J->base[ra-1] :
sloadt(J, (int32_t)(ra-1), IRT_INT, IRSLOAD_KEYINDEX);
copyTV(J->L, &ix.tabv, &J->L->base[ra-2]);
copyTV(J->L, &ix.keyv, &J->L->base[ra-1]);
ix.idxchain = (rb < 3); /* Omit value type check, if unused. */
ix.mobj = 1; /* We need the next index, too. */
J->maxslot = ra + lj_record_next(J, &ix);
J->needsnap = 1;
if (!tref_isnil(ix.key)) { /* Looping back? */
J->base[ra-1] = ix.mobj | TREF_KEYINDEX; /* Control var has next index. */
J->base[ra] = ix.key;
J->base[ra+1] = ix.val;
J->pc += bc_j(J->pc[1])+2;
return LOOPEV_ENTER;
} else {
J->maxslot = ra-3;
J->pc += 2;
return LOOPEV_LEAVE;
}
#endif
}
/* Record ISNEXT. */
static void rec_isnext(jit_State *J, BCReg ra)
{
cTValue *b = &J->L->base[ra-3];
if (tvisfunc(b) && funcV(b)->c.ffid == FF_next &&
tvistab(b+1) && tvisnil(b+2)) {
/* These checks are folded away for a compiled pairs(). */
TRef func = getslot(J, ra-3);
TRef trid = emitir(IRT(IR_FLOAD, IRT_U8), func, IRFL_FUNC_FFID);
emitir(IRTGI(IR_EQ), trid, lj_ir_kint(J, FF_next));
(void)getslot(J, ra-2); /* Type check for table. */
(void)getslot(J, ra-1); /* Type check for nil key. */
J->base[ra-1] = lj_ir_kint(J, 0) | TREF_KEYINDEX;
J->maxslot = ra;
} else { /* Abort trace. Interpreter will despecialize bytecode. */
lj_trace_err(J, LJ_TRERR_RECERR);
}
}
/* -- Record profiler hook checks ----------------------------------------- */
#if LJ_HASPROFILE
@@ -708,7 +784,7 @@ static TRef rec_call_specialize(jit_State *J, GCfunc *fn, TRef tr)
/* NYI: io_file_iter doesn't have an ffid, yet. */
{ /* Specialize to the ffid. */
TRef trid = emitir(IRT(IR_FLOAD, IRT_U8), tr, IRFL_FUNC_FFID);
emitir(IRTG(IR_EQ, IRT_INT), trid, lj_ir_kint(J, fn->c.ffid));
emitir(IRTGI(IR_EQ), trid, lj_ir_kint(J, fn->c.ffid));
}
return tr;
default:
@@ -832,6 +908,7 @@ void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults)
J->base -= cbase;
J->base[--rbase] = TREF_TRUE; /* Prepend true to results. */
frame = frame_prevd(frame);
J->needsnap = 1; /* Stop catching on-trace errors. */
}
/* Return to lower frame via interpreter for unhandled cases. */
if (J->framedepth == 0 && J->pt && bc_isret(bc_op(*J->pc)) &&
@@ -918,6 +995,9 @@ void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults)
TRef tr = gotresults ? J->base[cbase+rbase] : TREF_NIL;
if (bslot != J->maxslot) { /* Concatenate the remainder. */
TValue *b = J->L->base, save; /* Simulate lower frame and result. */
/* Can't handle MM_concat + CALLT + fast func side-effects. */
if (J->postproc != LJ_POST_NONE)
lj_trace_err(J, LJ_TRERR_NYIRETL);
J->base[J->maxslot] = tr;
copyTV(J->L, &save, b-(2<<LJ_FR2));
if (gotresults)
@@ -1433,6 +1513,16 @@ TRef lj_record_idx(jit_State *J, RecordIndex *ix)
return 0; /* No result yet. */
}
}
#if LJ_HASBUFFER
/* The index table of buffer objects is treated as immutable. */
if (ix->mt == TREF_NIL && !ix->val &&
tref_isudata(ix->tab) && udataV(&ix->tabv)->udtype == UDTYPE_BUFFER &&
tref_istab(ix->mobj) && tref_isstr(ix->key) && tref_isk(ix->key)) {
cTValue *val = lj_tab_getstr(tabV(&ix->mobjv), strV(&ix->keyv));
TRef tr = lj_record_constify(J, val);
if (tr) return tr; /* Specialize to the value, i.e. a method. */
}
#endif
/* Otherwise retry lookup with metaobject. */
ix->tab = ix->mobj;
copyTV(J->L, &ix->tabv, &ix->mobjv);
@@ -1543,6 +1633,47 @@ TRef lj_record_idx(jit_State *J, RecordIndex *ix)
}
}
/* Determine result type of table traversal. */
static IRType rec_next_types(GCtab *t, uint32_t idx)
{
for (; idx < t->asize; idx++) {
cTValue *a = arrayslot(t, idx);
if (LJ_LIKELY(!tvisnil(a)))
return (LJ_DUALNUM ? IRT_INT : IRT_NUM) + (itype2irt(a) << 8);
}
idx -= t->asize;
for (; idx <= t->hmask; idx++) {
Node *n = &noderef(t->node)[idx];
if (!tvisnil(&n->val))
return itype2irt(&n->key) + (itype2irt(&n->val) << 8);
}
return IRT_NIL + (IRT_NIL << 8);
}
/* Record a table traversal step aka next(). */
int lj_record_next(jit_State *J, RecordIndex *ix)
{
IRType t, tkey, tval;
TRef trvk;
t = rec_next_types(tabV(&ix->tabv), ix->keyv.u32.lo);
tkey = (t & 0xff); tval = (t >> 8);
trvk = lj_ir_call(J, IRCALL_lj_vm_next, ix->tab, ix->key);
if (ix->mobj || tkey == IRT_NIL) {
TRef idx = emitir(IRTI(IR_HIOP), trvk, trvk);
/* Always check for invalid key from next() for nil result. */
if (!ix->mobj) emitir(IRTGI(IR_NE), idx, lj_ir_kint(J, -1));
ix->mobj = idx;
}
ix->key = lj_record_vload(J, trvk, 1, tkey);
if (tkey == IRT_NIL || ix->idxchain) { /* Omit value type check. */
ix->val = TREF_NIL;
return 1;
} else { /* Need value. */
ix->val = lj_record_vload(J, trvk, 0, tval);
return 2;
}
}
static void rec_tsetm(jit_State *J, BCReg ra, BCReg rn, int32_t i)
{
RecordIndex ix;
@@ -1826,11 +1957,7 @@ static void rec_varg(jit_State *J, BCReg dst, ptrdiff_t nresults)
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-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);
if (irtype_ispri(t)) tr = TREF_PRI(t); /* Canonicalize primitives. */
J->base[dst+i] = tr;
J->base[dst+i] = lj_record_vload(J, vbase, i, t);
}
} else {
emitir(IRTGI(IR_LE), fr, lj_ir_kint(J, frofs));
@@ -1877,8 +2004,7 @@ static void rec_varg(jit_State *J, BCReg dst, ptrdiff_t nresults)
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. */
tr = lj_record_vload(J, aref, 0, t);
}
J->base[dst-2-LJ_FR2] = tr;
J->maxslot = dst-1-LJ_FR2;
@@ -1935,9 +2061,9 @@ static TRef rec_cat(jit_State *J, BCReg baseslot, BCReg topslot)
tr = hdr = emitir(IRT(IR_BUFHDR, IRT_PGC),
lj_ir_kptr(J, &J2G(J)->tmpbuf), IRBUFHDR_RESET);
do {
tr = emitir(IRT(IR_BUFPUT, IRT_PGC), tr, *trp++);
tr = emitir(IRTG(IR_BUFPUT, IRT_PGC), tr, *trp++);
} while (trp <= top);
tr = emitir(IRT(IR_BUFSTR, IRT_STR), tr, hdr);
tr = emitir(IRTG(IR_BUFSTR, IRT_STR), tr, hdr);
J->maxslot = (BCReg)(xbase - J->base);
if (xbase == base) return tr; /* Return simple concatenation result. */
/* Pass partial result. */
@@ -2050,7 +2176,7 @@ void lj_record_ins(jit_State *J)
/* Need snapshot before recording next bytecode (e.g. after a store). */
if (J->needsnap) {
J->needsnap = 0;
lj_snap_purge(J);
if (J->pt) lj_snap_purge(J);
lj_snap_add(J);
J->mergesnap = 1;
}
@@ -2423,6 +2549,9 @@ void lj_record_ins(jit_State *J)
case BC_ITERL:
rec_loop_interp(J, pc, rec_iterl(J, *pc));
break;
case BC_ITERN:
rec_loop_interp(J, pc, rec_itern(J, ra, rb));
break;
case BC_LOOP:
rec_loop_interp(J, pc, rec_loop(J, ra, 1));
break;
@@ -2451,6 +2580,10 @@ void lj_record_ins(jit_State *J)
J->maxslot = ra; /* Shrink used slots. */
break;
case BC_ISNEXT:
rec_isnext(J, ra);
break;
/* -- Function headers -------------------------------------------------- */
case BC_FUNCF:
@@ -2480,8 +2613,6 @@ void lj_record_ins(jit_State *J)
break;
}
/* fallthrough */
case BC_ITERN:
case BC_ISNEXT:
case BC_UCLO:
case BC_FNEW:
setintV(&J->errinfo, (int32_t)op);
@@ -2533,6 +2664,13 @@ static const BCIns *rec_setup_root(jit_State *J)
lj_assertJ(bc_op(pc[-1]) == BC_JMP, "ITERL does not point to JMP+1");
J->bc_min = pc;
break;
case BC_ITERN:
lj_assertJ(bc_op(pc[1]) == BC_ITERL, "no ITERL after ITERN");
J->maxslot = ra;
J->bc_extent = (MSize)(-bc_j(pc[1]))*sizeof(BCIns);
J->bc_min = pc+2 + bc_j(pc[1]);
J->state = LJ_TRACE_RECORD_1ST; /* Record the first ITERN, too. */
break;
case BC_LOOP:
/* Only check BC range for real loops, but not for "repeat until true". */
pcj = pc + bc_j(ins);
@@ -2629,9 +2767,14 @@ void lj_record_setup(jit_State *J)
}
lj_snap_replay(J, T);
sidecheck:
if (traceref(J, J->cur.root)->nchild >= J->param[JIT_P_maxside] ||
T->snap[J->exitno].count >= J->param[JIT_P_hotexit] +
J->param[JIT_P_tryside]) {
if ((traceref(J, J->cur.root)->nchild >= J->param[JIT_P_maxside] ||
T->snap[J->exitno].count >= J->param[JIT_P_hotexit] +
J->param[JIT_P_tryside])) {
if (bc_op(*J->pc) == BC_JLOOP) {
BCIns startins = traceref(J, bc_d(*J->pc))->startins;
if (bc_op(startins) == BC_ITERN)
rec_itern(J, bc_a(startins), bc_b(startins));
}
lj_record_stop(J, LJ_TRLINK_INTERP, 0);
}
} else { /* Root trace. */
@@ -2640,6 +2783,7 @@ void lj_record_setup(jit_State *J)
J->pc = rec_setup_root(J);
/* Note: the loop instruction itself is recorded at the end and not
** at the start! So snapshot #0 needs to point to the *next* instruction.
** The one exception is BC_ITERN, which sets LJ_TRACE_RECORD_1ST.
*/
lj_snap_add(J);
if (bc_op(J->cur.startins) == BC_FORL)