diff options
-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; |