diff --git a/lib/dump.lua b/lib/dump.lua index 41feff44..00f59977 100644 --- a/lib/dump.lua +++ b/lib/dump.lua @@ -397,6 +397,8 @@ local function dump_ir(tr, dumpsnap, dumpreg) local litn = litname[op] if litn and litn[op2] then out:write(" ", litn[op2]) + elseif op == "UREFO " or op == "UREFC " then + out:write(format(" #%-3d", shr(op2, 8))) else out:write(format(" #%-3d", op2)) end diff --git a/src/lj_asm.c b/src/lj_asm.c index 50f877e7..20d26278 100644 --- a/src/lj_asm.c +++ b/src/lj_asm.c @@ -1105,7 +1105,7 @@ static void asm_fuseahuref(ASMState *as, IRRef ref, RegSet allow) case IR_UREFC: if (irref_isk(ir->op1)) { GCfunc *fn = ir_kfunc(IR(ir->op1)); - GCupval *uv = &gcref(fn->l.uvptr[ir->op2])->uv; + GCupval *uv = &gcref(fn->l.uvptr[(ir->op2 >> 8)])->uv; as->mrm.ofs = ptr2addr(&uv->tv); as->mrm.base = as->mrm.idx = RID_NONE; return; @@ -1702,7 +1702,7 @@ static void asm_uref(ASMState *as, IRIns *ir) Reg dest = ra_dest(as, ir, RSET_GPR); if (irref_isk(ir->op1)) { GCfunc *fn = ir_kfunc(IR(ir->op1)); - MRef *v = &gcref(fn->l.uvptr[ir->op2])->uv.v; + MRef *v = &gcref(fn->l.uvptr[(ir->op2 >> 8)])->uv.v; emit_rma(as, XO_MOV, dest, v); } else { Reg uv = ra_scratch(as, RSET_GPR); @@ -1716,7 +1716,7 @@ static void asm_uref(ASMState *as, IRIns *ir) emit_rmro(as, XO_MOV, dest, uv, offsetof(GCupval, v)); } emit_rmro(as, XO_MOV, uv, func, - (int32_t)offsetof(GCfuncL, uvptr) + 4*(int32_t)ir->op2); + (int32_t)offsetof(GCfuncL, uvptr) + 4*(int32_t)(ir->op2 >> 8)); } } } diff --git a/src/lj_func.c b/src/lj_func.c index 231701db..078ced92 100644 --- a/src/lj_func.c +++ b/src/lj_func.c @@ -169,10 +169,11 @@ GCfunc *lj_func_newL_gc(lua_State *L, GCproto *pt, GCfuncL *parent) nuv = fn->l.nupvalues; base = L->base; for (i = 0; i < nuv; i++) { - ptrdiff_t v = pt->uv[i]; + uint32_t v = pt->uv[i]; GCupval *uv; if ((v & 0x8000)) { uv = func_finduv(L, base + (v & 0xff)); + uv->dhash = (uint32_t)(uintptr_t)gcref(parent->pt) ^ (v << 24); } else { uv = &gcref(puv[v])->uv; } diff --git a/src/lj_obj.h b/src/lj_obj.h index 85d904f3..ecce03ed 100644 --- a/src/lj_obj.h +++ b/src/lj_obj.h @@ -397,7 +397,7 @@ typedef struct GCupval { }; }; MRef v; /* Points to stack slot (open) or above (closed). */ - int32_t unusedv; /* For consistent alignment. */ + uint32_t dhash; /* Disambiguation hash: dh1 != dh2 => cannot alias. */ } GCupval; #define uvprev(uv_) (&gcref((uv_)->prev)->uv) diff --git a/src/lj_opt_fold.c b/src/lj_opt_fold.c index 41c87e2f..a8550e1f 100644 --- a/src/lj_opt_fold.c +++ b/src/lj_opt_fold.c @@ -1146,12 +1146,12 @@ LJFOLDF(cse_uref) if (LJ_LIKELY(J->flags & JIT_F_OPT_CSE)) { IRRef ref = J->chain[fins->o]; GCfunc *fn = ir_kfunc(fleft); - GCupval *uv = gco2uv(gcref(fn->l.uvptr[fins->op2])); + GCupval *uv = gco2uv(gcref(fn->l.uvptr[(fins->op2 >> 8)])); while (ref > 0) { IRIns *ir = IR(ref); if (irref_isk(ir->op1)) { GCfunc *fn2 = ir_kfunc(IR(ir->op1)); - if (gco2uv(gcref(fn2->l.uvptr[ir->op2])) == uv) { + if (gco2uv(gcref(fn2->l.uvptr[(ir->op2 >> 8)])) == uv) { if (fins->o == IR_UREFO && gcstep_barrier(J, ref)) break; return ref; diff --git a/src/lj_opt_mem.c b/src/lj_opt_mem.c index 521c8590..57948311 100644 --- a/src/lj_opt_mem.c +++ b/src/lj_opt_mem.c @@ -277,12 +277,17 @@ static AliasRet aa_uref(IRIns *refa, IRIns *refb) { if (refa->o != refb->o) return ALIAS_NO; /* Different UREFx type. */ - if (refa->op1 != refb->op1) - return ALIAS_MAY; /* Different function. */ - else if (refa->op2 == refb->op2) - return ALIAS_MUST; /* Same function, same upvalue idx. */ - else - return ALIAS_NO; /* Same function, different upvalue idx. */ + if (refa->op1 == refb->op1) { /* Same function. */ + if (refa->op2 == refb->op2) + return ALIAS_MUST; /* Same function, same upvalue idx. */ + else + return ALIAS_NO; /* Same function, different upvalue idx. */ + } else { /* Different functions, check disambiguation hash values. */ + if (((refa->op2 ^ refb->op2) & 0xff)) + return ALIAS_NO; /* Upvalues with different hash values cannot alias. */ + else + return ALIAS_MAY; /* No conclusion can be drawn for same hash value. */ + } } /* ULOAD forwarding. */ diff --git a/src/lj_record.c b/src/lj_record.c index 0dfd1f73..b998c020 100644 --- a/src/lj_record.c +++ b/src/lj_record.c @@ -781,6 +781,15 @@ static TRef rec_idx(jit_State *J, RecordIndex *ix) /* -- Upvalue access ------------------------------------------------------ */ +/* Shrink disambiguation hash into an 8 bit value. */ +static uint32_t shrink_dhash(uint32_t lo, uint32_t hi) +{ + lo ^= hi; hi = lj_rol(hi, 14); + lo -= hi; hi = lj_rol(hi, 5); + hi ^= lo; hi -= lj_rol(lo, 27); + return (hi & 0xff); +} + /* Record upvalue load/store. */ static TRef rec_upvalue(jit_State *J, uint32_t uv, TRef val) { @@ -788,6 +797,8 @@ static TRef rec_upvalue(jit_State *J, uint32_t uv, TRef val) TRef fn = getcurrf(J); IRRef uref; int needbarrier = 0; + /* Note: this effectively limits LJ_MAX_UPVAL to 127. */ + uv = (uv << 8) | shrink_dhash(uvp->dhash, uvp->dhash-0x04c11db7); if (!uvp->closed) { /* In current stack? */ if (uvval(uvp) >= J->L->stack && uvval(uvp) < J->L->maxstack) {