diff options
author | Mike Pall <mike> | 2010-01-09 23:59:43 +0100 |
---|---|---|
committer | Mike Pall <mike> | 2010-01-09 23:59:43 +0100 |
commit | 99d153bef9725db226614558d01df829afafee3c (patch) | |
tree | ec5c4778a0ac5e054fc8c3d337381e1d52f626bc /src | |
parent | 2cc554db0cb37ac3600cccab97c657bb532e3c4e (diff) | |
download | luajit-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.c | 6 | ||||
-rw-r--r-- | src/lj_func.c | 3 | ||||
-rw-r--r-- | src/lj_obj.h | 2 | ||||
-rw-r--r-- | src/lj_opt_fold.c | 4 | ||||
-rw-r--r-- | src/lj_opt_mem.c | 17 | ||||
-rw-r--r-- | src/lj_record.c | 11 |
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. */ | ||
785 | static 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. */ |
785 | static TRef rec_upvalue(jit_State *J, uint32_t uv, TRef val) | 794 | static 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) { |