]> git.ipfire.org Git - thirdparty/LuaJIT.git/commitdiff
Improve alias analysis of upvalues using a disambiguation hash value.
authorMike Pall <mike>
Sat, 9 Jan 2010 22:59:43 +0000 (23:59 +0100)
committerMike Pall <mike>
Sat, 9 Jan 2010 22:59:43 +0000 (23:59 +0100)
All upvalue objects hold a disambiguation hash value now.
It's built from the parent prototype and the slot number.
Different hash values imply the upvalues cannot alias.
Same hash values don't imply anything (collision or different closures).
Upvalue disambiguation makes use of a reduced hash due to IR contraints.

lib/dump.lua
src/lj_asm.c
src/lj_func.c
src/lj_obj.h
src/lj_opt_fold.c
src/lj_opt_mem.c
src/lj_record.c

index 41feff443ed3cc8020520212bd103e8633064c0e..00f59977339580d692b494c350a2a1cc107f424f 100644 (file)
@@ -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
index 50f877e7553710b88ffb61538af5e3f92469b3d8..20d262782cafbb1a7a125c216b395696797abfa5 100644 (file)
@@ -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));
     }
   }
 }
index 231701db7010f7c70f1a6ff2ad6a9b22a7b2a262..078ced925abdb38896e3b589ee917008a6fa9158 100644 (file)
@@ -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;
     }
index 85d904f329ce13d2987055cc47b767244839c655..ecce03ed7f327fd21ddfa11a456e274bb08a537b 100644 (file)
@@ -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)
index 41c87e2fcac10761bc4f7b8cefab9fd4d98c1ff6..a8550e1f55b50ad2e56b2b23f9b79ee1c2e70c9e 100644 (file)
@@ -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;
index 521c8590c8bb8b421ea51b0cc630290415544bc5..5794831120a85347838c5ab51611cbe5974b2d78 100644 (file)
@@ -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. */
index 0dfd1f73976ab581a93b4a560ce869e8543d4043..b998c020e03ae1e472eb4c693061ecffe7351931 100644 (file)
@@ -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) {