diff options
| author | Mike Pall <mike> | 2016-01-18 11:58:13 +0100 |
|---|---|---|
| committer | Mike Pall <mike> | 2016-01-18 11:58:13 +0100 |
| commit | 04d28068233a8ddb28842c22f1b831f2ced8fe1a (patch) | |
| tree | b901ef8cb6cec3c92b1eb6b7dc24fea2c5303c30 /src | |
| parent | 22e7b00ddbc2adcc351f9d3656956c5937fc8ee8 (diff) | |
| download | luajit-04d28068233a8ddb28842c22f1b831f2ced8fe1a.tar.gz luajit-04d28068233a8ddb28842c22f1b831f2ced8fe1a.tar.bz2 luajit-04d28068233a8ddb28842c22f1b831f2ced8fe1a.zip | |
Rollback due to HREFK + load fwd must restore guardemit state.
Thanks to Vyacheslav Egorov.
Diffstat (limited to 'src')
| -rw-r--r-- | src/lj_record.c | 16 |
1 files changed, 12 insertions, 4 deletions
diff --git a/src/lj_record.c b/src/lj_record.c index dc5f2d54..480c80c1 100644 --- a/src/lj_record.c +++ b/src/lj_record.c | |||
| @@ -1236,12 +1236,14 @@ static void rec_idx_abc(jit_State *J, TRef asizeref, TRef ikey, uint32_t asize) | |||
| 1236 | } | 1236 | } |
| 1237 | 1237 | ||
| 1238 | /* Record indexed key lookup. */ | 1238 | /* Record indexed key lookup. */ |
| 1239 | static TRef rec_idx_key(jit_State *J, RecordIndex *ix, IRRef *rbref) | 1239 | static TRef rec_idx_key(jit_State *J, RecordIndex *ix, IRRef *rbref, |
| 1240 | IRType1 *rbguard) | ||
| 1240 | { | 1241 | { |
| 1241 | TRef key; | 1242 | TRef key; |
| 1242 | GCtab *t = tabV(&ix->tabv); | 1243 | GCtab *t = tabV(&ix->tabv); |
| 1243 | ix->oldv = lj_tab_get(J->L, t, &ix->keyv); /* Lookup previous value. */ | 1244 | ix->oldv = lj_tab_get(J->L, t, &ix->keyv); /* Lookup previous value. */ |
| 1244 | *rbref = 0; | 1245 | *rbref = 0; |
| 1246 | rbguard->irt = 0; | ||
| 1245 | 1247 | ||
| 1246 | /* Integer keys are looked up in the array part first. */ | 1248 | /* Integer keys are looked up in the array part first. */ |
| 1247 | key = ix->key; | 1249 | key = ix->key; |
| @@ -1293,6 +1295,7 @@ static TRef rec_idx_key(jit_State *J, RecordIndex *ix, IRRef *rbref) | |||
| 1293 | hslot <= 65535*(MSize)sizeof(Node)) { | 1295 | hslot <= 65535*(MSize)sizeof(Node)) { |
| 1294 | TRef node, kslot, hm; | 1296 | TRef node, kslot, hm; |
| 1295 | *rbref = J->cur.nins; /* Mark possible rollback point. */ | 1297 | *rbref = J->cur.nins; /* Mark possible rollback point. */ |
| 1298 | *rbguard = J->guardemit; | ||
| 1296 | hm = emitir(IRTI(IR_FLOAD), ix->tab, IRFL_TAB_HMASK); | 1299 | hm = emitir(IRTI(IR_FLOAD), ix->tab, IRFL_TAB_HMASK); |
| 1297 | emitir(IRTGI(IR_EQ), hm, lj_ir_kint(J, (int32_t)t->hmask)); | 1300 | emitir(IRTGI(IR_EQ), hm, lj_ir_kint(J, (int32_t)t->hmask)); |
| 1298 | node = emitir(IRT(IR_FLOAD, IRT_P32), ix->tab, IRFL_TAB_NODE); | 1301 | node = emitir(IRT(IR_FLOAD, IRT_P32), ix->tab, IRFL_TAB_NODE); |
| @@ -1327,6 +1330,7 @@ TRef lj_record_idx(jit_State *J, RecordIndex *ix) | |||
| 1327 | TRef xref; | 1330 | TRef xref; |
| 1328 | IROp xrefop, loadop; | 1331 | IROp xrefop, loadop; |
| 1329 | IRRef rbref; | 1332 | IRRef rbref; |
| 1333 | IRType1 rbguard; | ||
| 1330 | cTValue *oldv; | 1334 | cTValue *oldv; |
| 1331 | 1335 | ||
| 1332 | while (!tref_istab(ix->tab)) { /* Handle non-table lookup. */ | 1336 | while (!tref_istab(ix->tab)) { /* Handle non-table lookup. */ |
| @@ -1373,7 +1377,7 @@ TRef lj_record_idx(jit_State *J, RecordIndex *ix) | |||
| 1373 | } | 1377 | } |
| 1374 | 1378 | ||
| 1375 | /* Record the key lookup. */ | 1379 | /* Record the key lookup. */ |
| 1376 | xref = rec_idx_key(J, ix, &rbref); | 1380 | xref = rec_idx_key(J, ix, &rbref, &rbguard); |
| 1377 | xrefop = IR(tref_ref(xref))->o; | 1381 | xrefop = IR(tref_ref(xref))->o; |
| 1378 | loadop = xrefop == IR_AREF ? IR_ALOAD : IR_HLOAD; | 1382 | loadop = xrefop == IR_AREF ? IR_ALOAD : IR_HLOAD; |
| 1379 | /* The lj_meta_tset() inconsistency is gone, but better play safe. */ | 1383 | /* The lj_meta_tset() inconsistency is gone, but better play safe. */ |
| @@ -1388,8 +1392,10 @@ TRef lj_record_idx(jit_State *J, RecordIndex *ix) | |||
| 1388 | } else { | 1392 | } else { |
| 1389 | res = emitir(IRTG(loadop, t), xref, 0); | 1393 | res = emitir(IRTG(loadop, t), xref, 0); |
| 1390 | } | 1394 | } |
| 1391 | if (tref_ref(res) < rbref) /* HREFK + load forwarded? */ | 1395 | if (tref_ref(res) < rbref) { /* HREFK + load forwarded? */ |
| 1392 | lj_ir_rollback(J, rbref); /* Rollback to eliminate hmask guard. */ | 1396 | lj_ir_rollback(J, rbref); /* Rollback to eliminate hmask guard. */ |
| 1397 | J->guardemit = rbguard; | ||
| 1398 | } | ||
| 1393 | if (t == IRT_NIL && ix->idxchain && lj_record_mm_lookup(J, ix, MM_index)) | 1399 | if (t == IRT_NIL && ix->idxchain && lj_record_mm_lookup(J, ix, MM_index)) |
| 1394 | goto handlemm; | 1400 | goto handlemm; |
| 1395 | if (irtype_ispri(t)) res = TREF_PRI(t); /* Canonicalize primitives. */ | 1401 | if (irtype_ispri(t)) res = TREF_PRI(t); /* Canonicalize primitives. */ |
| @@ -1397,8 +1403,10 @@ TRef lj_record_idx(jit_State *J, RecordIndex *ix) | |||
| 1397 | } else { /* Indexed store. */ | 1403 | } else { /* Indexed store. */ |
| 1398 | GCtab *mt = tabref(tabV(&ix->tabv)->metatable); | 1404 | GCtab *mt = tabref(tabV(&ix->tabv)->metatable); |
| 1399 | int keybarrier = tref_isgcv(ix->key) && !tref_isnil(ix->val); | 1405 | int keybarrier = tref_isgcv(ix->key) && !tref_isnil(ix->val); |
| 1400 | if (tref_ref(xref) < rbref) /* HREFK forwarded? */ | 1406 | if (tref_ref(xref) < rbref) { /* HREFK forwarded? */ |
| 1401 | lj_ir_rollback(J, rbref); /* Rollback to eliminate hmask guard. */ | 1407 | lj_ir_rollback(J, rbref); /* Rollback to eliminate hmask guard. */ |
| 1408 | J->guardemit = rbguard; | ||
| 1409 | } | ||
| 1402 | if (tvisnil(oldv)) { /* Previous value was nil? */ | 1410 | if (tvisnil(oldv)) { /* Previous value was nil? */ |
| 1403 | /* Need to duplicate the hasmm check for the early guards. */ | 1411 | /* Need to duplicate the hasmm check for the early guards. */ |
| 1404 | int hasmm = 0; | 1412 | int hasmm = 0; |
