aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMike Pall <mike>2010-01-09 23:59:43 +0100
committerMike Pall <mike>2010-01-09 23:59:43 +0100
commit99d153bef9725db226614558d01df829afafee3c (patch)
treeec5c4778a0ac5e054fc8c3d337381e1d52f626bc /src
parent2cc554db0cb37ac3600cccab97c657bb532e3c4e (diff)
downloadluajit-99d153bef9725db226614558d01df829afafee3c.tar.gz
luajit-99d153bef9725db226614558d01df829afafee3c.tar.bz2
luajit-99d153bef9725db226614558d01df829afafee3c.zip
Improve alias analysis of upvalues using a disambiguation hash value.
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.
Diffstat (limited to 'src')
-rw-r--r--src/lj_asm.c6
-rw-r--r--src/lj_func.c3
-rw-r--r--src/lj_obj.h2
-rw-r--r--src/lj_opt_fold.c4
-rw-r--r--src/lj_opt_mem.c17
-rw-r--r--src/lj_record.c11
6 files changed, 30 insertions, 13 deletions
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)
1105 case IR_UREFC: 1105 case IR_UREFC:
1106 if (irref_isk(ir->op1)) { 1106 if (irref_isk(ir->op1)) {
1107 GCfunc *fn = ir_kfunc(IR(ir->op1)); 1107 GCfunc *fn = ir_kfunc(IR(ir->op1));
1108 GCupval *uv = &gcref(fn->l.uvptr[ir->op2])->uv; 1108 GCupval *uv = &gcref(fn->l.uvptr[(ir->op2 >> 8)])->uv;
1109 as->mrm.ofs = ptr2addr(&uv->tv); 1109 as->mrm.ofs = ptr2addr(&uv->tv);
1110 as->mrm.base = as->mrm.idx = RID_NONE; 1110 as->mrm.base = as->mrm.idx = RID_NONE;
1111 return; 1111 return;
@@ -1702,7 +1702,7 @@ static void asm_uref(ASMState *as, IRIns *ir)
1702 Reg dest = ra_dest(as, ir, RSET_GPR); 1702 Reg dest = ra_dest(as, ir, RSET_GPR);
1703 if (irref_isk(ir->op1)) { 1703 if (irref_isk(ir->op1)) {
1704 GCfunc *fn = ir_kfunc(IR(ir->op1)); 1704 GCfunc *fn = ir_kfunc(IR(ir->op1));
1705 MRef *v = &gcref(fn->l.uvptr[ir->op2])->uv.v; 1705 MRef *v = &gcref(fn->l.uvptr[(ir->op2 >> 8)])->uv.v;
1706 emit_rma(as, XO_MOV, dest, v); 1706 emit_rma(as, XO_MOV, dest, v);
1707 } else { 1707 } else {
1708 Reg uv = ra_scratch(as, RSET_GPR); 1708 Reg uv = ra_scratch(as, RSET_GPR);
@@ -1716,7 +1716,7 @@ static void asm_uref(ASMState *as, IRIns *ir)
1716 emit_rmro(as, XO_MOV, dest, uv, offsetof(GCupval, v)); 1716 emit_rmro(as, XO_MOV, dest, uv, offsetof(GCupval, v));
1717 } 1717 }
1718 emit_rmro(as, XO_MOV, uv, func, 1718 emit_rmro(as, XO_MOV, uv, func,
1719 (int32_t)offsetof(GCfuncL, uvptr) + 4*(int32_t)ir->op2); 1719 (int32_t)offsetof(GCfuncL, uvptr) + 4*(int32_t)(ir->op2 >> 8));
1720 } 1720 }
1721 } 1721 }
1722} 1722}
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)
169 nuv = fn->l.nupvalues; 169 nuv = fn->l.nupvalues;
170 base = L->base; 170 base = L->base;
171 for (i = 0; i < nuv; i++) { 171 for (i = 0; i < nuv; i++) {
172 ptrdiff_t v = pt->uv[i]; 172 uint32_t v = pt->uv[i];
173 GCupval *uv; 173 GCupval *uv;
174 if ((v & 0x8000)) { 174 if ((v & 0x8000)) {
175 uv = func_finduv(L, base + (v & 0xff)); 175 uv = func_finduv(L, base + (v & 0xff));
176 uv->dhash = (uint32_t)(uintptr_t)gcref(parent->pt) ^ (v << 24);
176 } else { 177 } else {
177 uv = &gcref(puv[v])->uv; 178 uv = &gcref(puv[v])->uv;
178 } 179 }
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 {
397 }; 397 };
398 }; 398 };
399 MRef v; /* Points to stack slot (open) or above (closed). */ 399 MRef v; /* Points to stack slot (open) or above (closed). */
400 int32_t unusedv; /* For consistent alignment. */ 400 uint32_t dhash; /* Disambiguation hash: dh1 != dh2 => cannot alias. */
401} GCupval; 401} GCupval;
402 402
403#define uvprev(uv_) (&gcref((uv_)->prev)->uv) 403#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)
1146 if (LJ_LIKELY(J->flags & JIT_F_OPT_CSE)) { 1146 if (LJ_LIKELY(J->flags & JIT_F_OPT_CSE)) {
1147 IRRef ref = J->chain[fins->o]; 1147 IRRef ref = J->chain[fins->o];
1148 GCfunc *fn = ir_kfunc(fleft); 1148 GCfunc *fn = ir_kfunc(fleft);
1149 GCupval *uv = gco2uv(gcref(fn->l.uvptr[fins->op2])); 1149 GCupval *uv = gco2uv(gcref(fn->l.uvptr[(fins->op2 >> 8)]));
1150 while (ref > 0) { 1150 while (ref > 0) {
1151 IRIns *ir = IR(ref); 1151 IRIns *ir = IR(ref);
1152 if (irref_isk(ir->op1)) { 1152 if (irref_isk(ir->op1)) {
1153 GCfunc *fn2 = ir_kfunc(IR(ir->op1)); 1153 GCfunc *fn2 = ir_kfunc(IR(ir->op1));
1154 if (gco2uv(gcref(fn2->l.uvptr[ir->op2])) == uv) { 1154 if (gco2uv(gcref(fn2->l.uvptr[(ir->op2 >> 8)])) == uv) {
1155 if (fins->o == IR_UREFO && gcstep_barrier(J, ref)) 1155 if (fins->o == IR_UREFO && gcstep_barrier(J, ref))
1156 break; 1156 break;
1157 return ref; 1157 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)
277{ 277{
278 if (refa->o != refb->o) 278 if (refa->o != refb->o)
279 return ALIAS_NO; /* Different UREFx type. */ 279 return ALIAS_NO; /* Different UREFx type. */
280 if (refa->op1 != refb->op1) 280 if (refa->op1 == refb->op1) { /* Same function. */
281 return ALIAS_MAY; /* Different function. */ 281 if (refa->op2 == refb->op2)
282 else if (refa->op2 == refb->op2) 282 return ALIAS_MUST; /* Same function, same upvalue idx. */
283 return ALIAS_MUST; /* Same function, same upvalue idx. */ 283 else
284 else 284 return ALIAS_NO; /* Same function, different upvalue idx. */
285 return ALIAS_NO; /* Same function, different upvalue idx. */ 285 } else { /* Different functions, check disambiguation hash values. */
286 if (((refa->op2 ^ refb->op2) & 0xff))
287 return ALIAS_NO; /* Upvalues with different hash values cannot alias. */
288 else
289 return ALIAS_MAY; /* No conclusion can be drawn for same hash value. */
290 }
286} 291}
287 292
288/* ULOAD forwarding. */ 293/* 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)
781 781
782/* -- Upvalue access ------------------------------------------------------ */ 782/* -- Upvalue access ------------------------------------------------------ */
783 783
784/* Shrink disambiguation hash into an 8 bit value. */
785static uint32_t shrink_dhash(uint32_t lo, uint32_t hi)
786{
787 lo ^= hi; hi = lj_rol(hi, 14);
788 lo -= hi; hi = lj_rol(hi, 5);
789 hi ^= lo; hi -= lj_rol(lo, 27);
790 return (hi & 0xff);
791}
792
784/* Record upvalue load/store. */ 793/* Record upvalue load/store. */
785static TRef rec_upvalue(jit_State *J, uint32_t uv, TRef val) 794static TRef rec_upvalue(jit_State *J, uint32_t uv, TRef val)
786{ 795{
@@ -788,6 +797,8 @@ static TRef rec_upvalue(jit_State *J, uint32_t uv, TRef val)
788 TRef fn = getcurrf(J); 797 TRef fn = getcurrf(J);
789 IRRef uref; 798 IRRef uref;
790 int needbarrier = 0; 799 int needbarrier = 0;
800 /* Note: this effectively limits LJ_MAX_UPVAL to 127. */
801 uv = (uv << 8) | shrink_dhash(uvp->dhash, uvp->dhash-0x04c11db7);
791 if (!uvp->closed) { 802 if (!uvp->closed) {
792 /* In current stack? */ 803 /* In current stack? */
793 if (uvval(uvp) >= J->L->stack && uvval(uvp) < J->L->maxstack) { 804 if (uvval(uvp) >= J->L->stack && uvval(uvp) < J->L->maxstack) {