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
+143 -93
View File
@@ -1,6 +1,6 @@
/*
** MIPS IR assembler (SSA IR -> machine code).
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
*/
/* -- Register allocator extensions --------------------------------------- */
@@ -64,19 +64,31 @@ static Reg ra_alloc2(ASMState *as, IRIns *ir, RegSet allow)
/* Setup spare long-range jump slots per mcarea. */
static void asm_sparejump_setup(ASMState *as)
{
MCode *mxp = as->mcbot;
if (((uintptr_t)mxp & (LJ_PAGESIZE-1)) == sizeof(MCLink)) {
MCode *mxp = as->mctop;
if ((char *)mxp == (char *)as->J->mcarea + as->J->szmcarea) {
mxp -= MIPS_SPAREJUMP*2;
lj_assertA(MIPSI_NOP == 0, "bad NOP");
memset(mxp, 0, MIPS_SPAREJUMP*2*sizeof(MCode));
mxp += MIPS_SPAREJUMP*2;
lj_assertA(mxp < as->mctop, "MIPS_SPAREJUMP too big");
lj_mcode_sync(as->mcbot, mxp);
lj_mcode_commitbot(as->J, mxp);
as->mcbot = mxp;
as->mclim = as->mcbot + MCLIM_REDZONE;
as->mctop = mxp;
}
}
static MCode *asm_sparejump_use(MCode *mcarea, MCode tjump)
{
MCode *mxp = (MCode *)((char *)mcarea + ((MCLink *)mcarea)->size);
int slot = MIPS_SPAREJUMP;
while (slot--) {
mxp -= 2;
if (*mxp == tjump) {
return mxp;
} else if (*mxp == MIPSI_NOP) {
*mxp = tjump;
return mxp;
}
}
return NULL;
}
/* Setup exit stub after the end of each trace. */
static void asm_exitstub_setup(ASMState *as)
{
@@ -181,6 +193,9 @@ static Reg asm_fuseahuref(ASMState *as, IRRef ref, int32_t *ofsp, RegSet allow)
return ra_allock(as, ofs-(int16_t)ofs, allow);
}
}
} else if (ir->o == IR_TMPREF) {
*ofsp = (int32_t)(offsetof(global_State, tmptv)-32768);
return RID_JGL;
}
}
*ofsp = 0;
@@ -336,19 +351,15 @@ static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args)
static void asm_setupresult(ASMState *as, IRIns *ir, const CCallInfo *ci)
{
RegSet drop = RSET_SCRATCH;
#if LJ_32
int hiop = ((ir+1)->o == IR_HIOP && !irt_isnil((ir+1)->t));
#endif
#if !LJ_SOFTFP
if ((ci->flags & CCI_NOFPRCLOBBER))
drop &= ~RSET_FPR;
#endif
if (ra_hasreg(ir->r))
rset_clear(drop, ir->r); /* Dest reg handled below. */
#if LJ_32
if (hiop && ra_hasreg((ir+1)->r))
rset_clear(drop, (ir+1)->r); /* Dest reg handled below. */
#endif
ra_evictset(as, drop); /* Evictions must be performed first. */
if (ra_used(ir)) {
lj_assertA(!irt_ispri(ir->t), "PRI dest");
@@ -377,10 +388,8 @@ static void asm_setupresult(ASMState *as, IRIns *ir, const CCallInfo *ci)
} else {
ra_destreg(as, ir, RID_FPRET);
}
#if LJ_32
} else if (hiop) {
ra_destpair(as, ir);
#endif
} else {
ra_destreg(as, ir, RID_RET);
}
@@ -450,6 +459,27 @@ static void asm_retf(ASMState *as, IRIns *ir)
emit_tsi(as, MIPSI_AL, RID_TMP, base, -8);
}
/* -- Buffer operations --------------------------------------------------- */
#if LJ_HASBUFFER
static void asm_bufhdr_write(ASMState *as, Reg sb)
{
Reg tmp = ra_scratch(as, rset_exclude(RSET_GPR, sb));
IRIns irgc;
irgc.ot = IRT(0, IRT_PGC); /* GC type. */
emit_storeofs(as, &irgc, RID_TMP, sb, offsetof(SBuf, L));
if ((as->flags & JIT_F_MIPSXXR2)) {
emit_tsml(as, LJ_64 ? MIPSI_DINS : MIPSI_INS, RID_TMP, tmp,
lj_fls(SBUF_MASK_FLAG), 0);
} else {
emit_dst(as, MIPSI_OR, RID_TMP, RID_TMP, tmp);
emit_tsi(as, MIPSI_ANDI, tmp, tmp, SBUF_MASK_FLAG);
}
emit_getgl(as, RID_TMP, cur_L);
emit_loadofs(as, &irgc, tmp, sb, offsetof(SBuf, L));
}
#endif
/* -- Type conversions ---------------------------------------------------- */
#if !LJ_SOFTFP
@@ -739,7 +769,7 @@ static void asm_conv(ASMState *as, IRIns *ir)
}
}
} else {
if (st64) {
if (st64 && !(ir->op2 & IRCONV_NONE)) {
/* This is either a 32 bit reg/reg mov which zeroes the hiword
** or a load of the loword from a 64 bit address.
*/
@@ -827,34 +857,63 @@ static void asm_tvstore64(ASMState *as, Reg base, int32_t ofs, IRRef ref)
#endif
/* Get pointer to TValue. */
static void asm_tvptr(ASMState *as, Reg dest, IRRef ref)
static void asm_tvptr(ASMState *as, Reg dest, IRRef ref, MSize mode)
{
IRIns *ir = IR(ref);
if (irt_isnum(ir->t)) {
if (irref_isk(ref)) /* Use the number constant itself as a TValue. */
ra_allockreg(as, igcptr(ir_knum(ir)), dest);
else /* Otherwise force a spill and use the spill slot. */
emit_tsi(as, MIPSI_AADDIU, dest, RID_SP, ra_spill(as, ir));
} else {
/* Otherwise use g->tmptv to hold the TValue. */
#if LJ_32
RegSet allow = rset_exclude(RSET_GPR, dest);
Reg type;
emit_tsi(as, MIPSI_ADDIU, dest, RID_JGL, (int32_t)(offsetof(global_State, tmptv)-32768));
if (!irt_ispri(ir->t)) {
Reg src = ra_alloc1(as, ref, allow);
emit_setgl(as, src, tmptv.gcr);
}
if (LJ_SOFTFP && (ir+1)->o == IR_HIOP)
type = ra_alloc1(as, ref+1, allow);
else
type = ra_allock(as, (int32_t)irt_toitype(ir->t), allow);
emit_setgl(as, type, tmptv.it);
int32_t tmpofs = (int32_t)(offsetof(global_State, tmptv)-32768);
if ((mode & IRTMPREF_IN1)) {
IRIns *ir = IR(ref);
if (irt_isnum(ir->t)) {
if ((mode & IRTMPREF_OUT1)) {
#if LJ_SOFTFP
emit_tsi(as, MIPSI_AADDIU, dest, RID_JGL, tmpofs);
#if LJ_64
emit_setgl(as, ra_alloc1(as, ref, RSET_GPR), tmptv.u64);
#else
asm_tvstore64(as, dest, 0, ref);
emit_tsi(as, MIPSI_DADDIU, dest, RID_JGL,
(int32_t)(offsetof(global_State, tmptv)-32768));
lj_assertA(irref_isk(ref), "unsplit FP op");
emit_setgl(as,
ra_allock(as, (int32_t)ir_knum(ir)->u32.lo, RSET_GPR),
tmptv.u32.lo);
emit_setgl(as,
ra_allock(as, (int32_t)ir_knum(ir)->u32.hi, RSET_GPR),
tmptv.u32.hi);
#endif
#else
Reg src = ra_alloc1(as, ref, RSET_FPR);
emit_tsi(as, MIPSI_AADDIU, dest, RID_JGL, tmpofs);
emit_tsi(as, MIPSI_SDC1, (src & 31), RID_JGL, tmpofs);
#endif
} else if (irref_isk(ref)) {
/* Use the number constant itself as a TValue. */
ra_allockreg(as, igcptr(ir_knum(ir)), dest);
} else {
#if LJ_SOFTFP32
lj_assertA(0, "unsplit FP op");
#else
/* Otherwise force a spill and use the spill slot. */
emit_tsi(as, MIPSI_AADDIU, dest, RID_SP, ra_spill(as, ir));
#endif
}
} else {
/* Otherwise use g->tmptv to hold the TValue. */
#if LJ_32
Reg type;
emit_tsi(as, MIPSI_ADDIU, dest, RID_JGL, tmpofs);
if (!irt_ispri(ir->t)) {
Reg src = ra_alloc1(as, ref, RSET_GPR);
emit_setgl(as, src, tmptv.gcr);
}
if (LJ_SOFTFP && (ir+1)->o == IR_HIOP && !irt_isnil((ir+1)->t))
type = ra_alloc1(as, ref+1, RSET_GPR);
else
type = ra_allock(as, (int32_t)irt_toitype(ir->t), RSET_GPR);
emit_setgl(as, type, tmptv.it);
#else
asm_tvstore64(as, dest, 0, ref);
emit_tsi(as, MIPSI_DADDIU, dest, RID_JGL, tmpofs);
#endif
}
} else {
emit_tsi(as, MIPSI_AADDIU, dest, RID_JGL, tmpofs);
}
}
@@ -909,11 +968,16 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge)
MCLabel l_end, l_loop, l_next;
rset_clear(allow, tab);
#if LJ_SOFTFP32
if (!isk) {
key = ra_alloc1(as, refkey, allow);
rset_clear(allow, key);
if (irkey[1].o == IR_HIOP) {
if (!LJ_SOFTFP && irt_isnum(kt)) {
key = ra_alloc1(as, refkey, RSET_FPR);
tmpnum = ra_scratch(as, rset_exclude(RSET_FPR, key));
} else {
if (!irt_ispri(kt)) {
key = ra_alloc1(as, refkey, allow);
rset_clear(allow, key);
}
#if LJ_32
if (LJ_SOFTFP && irkey[1].o == IR_HIOP) {
if (ra_hasreg((irkey+1)->r)) {
type = tmpnum = (irkey+1)->r;
tmp1 = ra_scratch(as, allow);
@@ -924,23 +988,11 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge)
}
rset_clear(allow, tmpnum);
} else {
type = ra_allock(as, (int32_t)irt_toitype(irkey->t), allow);
type = ra_allock(as, (int32_t)irt_toitype(kt), allow);
rset_clear(allow, type);
}
}
#else
if (!LJ_SOFTFP && irt_isnum(kt)) {
key = ra_alloc1(as, refkey, RSET_FPR);
tmpnum = ra_scratch(as, rset_exclude(RSET_FPR, key));
} else if (!irt_ispri(kt)) {
key = ra_alloc1(as, refkey, allow);
rset_clear(allow, key);
#if LJ_32
type = ra_allock(as, (int32_t)irt_toitype(irkey->t), allow);
rset_clear(allow, type);
#endif
}
#endif
tmp2 = ra_scratch(as, allow);
rset_clear(allow, tmp2);
#if LJ_64
@@ -953,10 +1005,10 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge)
} else {
int64_t k;
if (isk && irt_isaddr(kt)) {
k = ((int64_t)irt_toitype(irkey->t) << 47) | irkey[1].tv.u64;
k = ((int64_t)irt_toitype(kt) << 47) | irkey[1].tv.u64;
} else {
lj_assertA(irt_ispri(kt) && !irt_isnil(kt), "bad HREF key type");
k = ~((int64_t)~irt_toitype(ir->t) << 47);
k = ~((int64_t)~irt_toitype(kt) << 47);
}
cmp64 = ra_allock(as, k, allow);
rset_clear(allow, cmp64);
@@ -1352,6 +1404,7 @@ static void asm_ahuvload(ASMState *as, IRIns *ir)
#endif
}
idx = asm_fuseahuref(as, ir->op1, &ofs, allow);
if (ir->o == IR_VLOAD) ofs += 8 * ir->op2;
rset_clear(allow, idx);
if (irt_isnum(t)) {
asm_guard(as, MIPSI_BEQ, RID_TMP, RID_ZERO);
@@ -2327,15 +2380,15 @@ static void asm_comp64eq(ASMState *as, IRIns *ir)
}
#endif
/* -- Support for 64 bit ops in 32 bit mode ------------------------------- */
/* -- Split register ops -------------------------------------------------- */
/* Hiword op of a split 64 bit op. Previous op must be the loword op. */
/* Hiword op of a split 32/32 or 64/64 bit op. Previous op is the loword op. */
static void asm_hiop(ASMState *as, IRIns *ir)
{
#if LJ_32 && (LJ_HASFFI || LJ_SOFTFP)
/* HIOP is marked as a store because it needs its own DCE logic. */
int uselo = ra_used(ir-1), usehi = ra_used(ir); /* Loword/hiword used? */
if (LJ_UNLIKELY(!(as->flags & JIT_F_OPT_DCE))) uselo = usehi = 1;
#if LJ_32 && (LJ_HASFFI || LJ_SOFTFP)
if ((ir-1)->o == IR_CONV) { /* Conversions to/from 64 bit. */
as->curins--; /* Always skip the CONV. */
#if LJ_HASFFI && !LJ_SOFTFP
@@ -2382,38 +2435,33 @@ static void asm_hiop(ASMState *as, IRIns *ir)
}
return;
}
#endif
if (!usehi) return; /* Skip unused hiword op for all remaining ops. */
switch ((ir-1)->o) {
#if LJ_HASFFI
#if LJ_32 && LJ_HASFFI
case IR_ADD: as->curins--; asm_add64(as, ir); break;
case IR_SUB: as->curins--; asm_sub64(as, ir); break;
case IR_NEG: as->curins--; asm_neg64(as, ir); break;
case IR_CNEWI:
/* Nothing to do here. Handled by lo op itself. */
break;
#endif
#if LJ_SOFTFP
#if LJ_32 && LJ_SOFTFP
case IR_SLOAD: case IR_ALOAD: case IR_HLOAD: case IR_ULOAD: case IR_VLOAD:
case IR_STRTO:
if (!uselo)
ra_allocref(as, ir->op1, RSET_GPR); /* Mark lo op as used. */
break;
case IR_ASTORE: case IR_HSTORE: case IR_USTORE: case IR_TOSTR: case IR_TMPREF:
/* Nothing to do here. Handled by lo op itself. */
break;
#endif
case IR_CALLN:
case IR_CALLS:
case IR_CALLXS:
case IR_CALLN: case IR_CALLL: case IR_CALLS: case IR_CALLXS:
if (!uselo)
ra_allocref(as, ir->op1, RID2RSET(RID_RETLO)); /* Mark lo op as used. */
break;
#if LJ_SOFTFP
case IR_ASTORE: case IR_HSTORE: case IR_USTORE: case IR_TOSTR:
#endif
case IR_CNEWI:
/* Nothing to do here. Handled by lo op itself. */
break;
default: lj_assertA(0, "bad HIOP for op %d", (ir-1)->o); break;
}
#else
/* Unused on MIPS64 or without SOFTFP or FFI. */
UNUSED(as); UNUSED(ir); lj_assertA(0, "unexpected HIOP");
#endif
}
/* -- Profiling ----------------------------------------------------------- */
@@ -2513,6 +2561,8 @@ static void asm_stack_restore(ASMState *as, SnapShot *snap)
} else if ((sn & SNAP_SOFTFPNUM)) {
type = ra_alloc1(as, ref+1, rset_exclude(RSET_GPR, RID_BASE));
#endif
} else if ((sn & SNAP_KEYINDEX)) {
type = ra_allock(as, (int32_t)LJ_KEYINDEX, allow);
} else {
type = ra_allock(as, (int32_t)irt_toitype(ir->t), allow);
}
@@ -2575,6 +2625,12 @@ static void asm_loop_fixup(ASMState *as)
}
}
/* Fixup the tail of the loop. */
static void asm_loop_tail_fixup(ASMState *as)
{
if (as->loopinv) as->mctop--;
}
/* -- Head of trace ------------------------------------------------------- */
/* Coalesce BASE register for a root trace. */
@@ -2582,7 +2638,6 @@ static void asm_head_root_base(ASMState *as)
{
IRIns *ir = IR(REF_BASE);
Reg r = ir->r;
if (as->loopinv) as->mctop--;
if (ra_hasreg(r)) {
ra_free(as, r);
if (rset_test(as->modset, r) || irt_ismarked(ir->t))
@@ -2597,7 +2652,6 @@ static RegSet asm_head_side_base(ASMState *as, IRIns *irp, RegSet allow)
{
IRIns *ir = IR(REF_BASE);
Reg r = ir->r;
if (as->loopinv) as->mctop--;
if (ra_hasreg(r)) {
ra_free(as, r);
if (rset_test(as->modset, r) || irt_ismarked(ir->t))
@@ -2704,21 +2758,17 @@ void lj_asm_patchexit(jit_State *J, GCtrace *T, ExitNo exitno, MCode *target)
patchbranch:
p[-1] = (p[-1] & 0xffff0000u) | (delta & 0xffffu);
*p = MIPSI_NOP; /* Replace the load of the exit number. */
cstop = p;
cstop = p+1;
if (!cstart) cstart = p-1;
} else { /* Branch out of range. Use spare jump slot in mcarea. */
int i;
for (i = (int)(sizeof(MCLink)/sizeof(MCode));
i < (int)(sizeof(MCLink)/sizeof(MCode)+MIPS_SPAREJUMP*2);
i += 2) {
if (mcarea[i] == tjump) {
delta = mcarea+i - p;
goto patchbranch;
} else if (mcarea[i] == MIPSI_NOP) {
mcarea[i] = tjump;
cstart = mcarea+i;
delta = mcarea+i - p;
MCode *mcjump = asm_sparejump_use(mcarea, tjump);
if (mcjump) {
lj_mcode_sync(mcjump, mcjump+1);
delta = mcjump - p;
if (((delta + 0x8000) >> 16) == 0) {
goto patchbranch;
} else {
lj_assertJ(0, "spare jump out of range: -Osizemcode too big");
}
}
/* Ignore jump slot overflow. Child trace is simply not attached. */