Skip to content

Commit

Permalink
Rollback due to HREFK + load fwd must restore guardemit state.
Browse files Browse the repository at this point in the history
Thanks to Vyacheslav Egorov.
  • Loading branch information
Mike Pall committed Jan 18, 2016
1 parent 22e7b00 commit 04d2806
Showing 1 changed file with 12 additions and 4 deletions.
16 changes: 12 additions & 4 deletions src/lj_record.c
Original file line number Diff line number Diff line change
Expand Up @@ -1236,12 +1236,14 @@ static void rec_idx_abc(jit_State *J, TRef asizeref, TRef ikey, uint32_t asize)
}

/* Record indexed key lookup. */
static TRef rec_idx_key(jit_State *J, RecordIndex *ix, IRRef *rbref)
static TRef rec_idx_key(jit_State *J, RecordIndex *ix, IRRef *rbref,
IRType1 *rbguard)
{
TRef key;
GCtab *t = tabV(&ix->tabv);
ix->oldv = lj_tab_get(J->L, t, &ix->keyv); /* Lookup previous value. */
*rbref = 0;
rbguard->irt = 0;

/* Integer keys are looked up in the array part first. */
key = ix->key;
Expand Down Expand Up @@ -1293,6 +1295,7 @@ static TRef rec_idx_key(jit_State *J, RecordIndex *ix, IRRef *rbref)
hslot <= 65535*(MSize)sizeof(Node)) {
TRef node, kslot, hm;
*rbref = J->cur.nins; /* Mark possible rollback point. */
*rbguard = J->guardemit;
hm = emitir(IRTI(IR_FLOAD), ix->tab, IRFL_TAB_HMASK);
emitir(IRTGI(IR_EQ), hm, lj_ir_kint(J, (int32_t)t->hmask));
node = emitir(IRT(IR_FLOAD, IRT_P32), ix->tab, IRFL_TAB_NODE);
Expand Down Expand Up @@ -1327,6 +1330,7 @@ TRef lj_record_idx(jit_State *J, RecordIndex *ix)
TRef xref;
IROp xrefop, loadop;
IRRef rbref;
IRType1 rbguard;
cTValue *oldv;

while (!tref_istab(ix->tab)) { /* Handle non-table lookup. */
Expand Down Expand Up @@ -1373,7 +1377,7 @@ TRef lj_record_idx(jit_State *J, RecordIndex *ix)
}

/* Record the key lookup. */
xref = rec_idx_key(J, ix, &rbref);
xref = rec_idx_key(J, ix, &rbref, &rbguard);
xrefop = IR(tref_ref(xref))->o;
loadop = xrefop == IR_AREF ? IR_ALOAD : IR_HLOAD;
/* The lj_meta_tset() inconsistency is gone, but better play safe. */
Expand All @@ -1388,17 +1392,21 @@ TRef lj_record_idx(jit_State *J, RecordIndex *ix)
} else {
res = emitir(IRTG(loadop, t), xref, 0);
}
if (tref_ref(res) < rbref) /* HREFK + load forwarded? */
if (tref_ref(res) < rbref) { /* HREFK + load forwarded? */
lj_ir_rollback(J, rbref); /* Rollback to eliminate hmask guard. */
J->guardemit = rbguard;
}
if (t == IRT_NIL && ix->idxchain && lj_record_mm_lookup(J, ix, MM_index))
goto handlemm;
if (irtype_ispri(t)) res = TREF_PRI(t); /* Canonicalize primitives. */
return res;
} else { /* Indexed store. */
GCtab *mt = tabref(tabV(&ix->tabv)->metatable);
int keybarrier = tref_isgcv(ix->key) && !tref_isnil(ix->val);
if (tref_ref(xref) < rbref) /* HREFK forwarded? */
if (tref_ref(xref) < rbref) { /* HREFK forwarded? */
lj_ir_rollback(J, rbref); /* Rollback to eliminate hmask guard. */
J->guardemit = rbguard;
}
if (tvisnil(oldv)) { /* Previous value was nil? */
/* Need to duplicate the hasmm check for the early guards. */
int hasmm = 0;
Expand Down

0 comments on commit 04d2806

Please sign in to comment.