summaryrefslogtreecommitdiff
path: root/src/lj_record.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lj_record.c')
-rw-r--r--src/lj_record.c9
1 files changed, 7 insertions, 2 deletions
diff --git a/src/lj_record.c b/src/lj_record.c
index 206eedca..c13c67fd 100644
--- a/src/lj_record.c
+++ b/src/lj_record.c
@@ -994,6 +994,7 @@ static TRef rec_idx(jit_State *J, RecordIndex *ix)
994 return res; 994 return res;
995 } else { /* Indexed store. */ 995 } else { /* Indexed store. */
996 GCtab *mt = tabref(tabV(&ix->tabv)->metatable); 996 GCtab *mt = tabref(tabV(&ix->tabv)->metatable);
997 int keybarrier = tref_isgcv(ix->key) && !tref_isnil(ix->val);
997 if (tvisnil(oldv)) { /* Previous value was nil? */ 998 if (tvisnil(oldv)) { /* Previous value was nil? */
998 /* Need to duplicate the hasmm check for the early guards. */ 999 /* Need to duplicate the hasmm check for the early guards. */
999 int hasmm = 0; 1000 int hasmm = 0;
@@ -1004,7 +1005,8 @@ static TRef rec_idx(jit_State *J, RecordIndex *ix)
1004 if (hasmm) 1005 if (hasmm)
1005 emitir(IRTG(loadop, IRT_NIL), xref, 0); /* Guard for nil value. */ 1006 emitir(IRTG(loadop, IRT_NIL), xref, 0); /* Guard for nil value. */
1006 else if (xrefop == IR_HREF) 1007 else if (xrefop == IR_HREF)
1007 emitir(IRTG(oldv == niltvg(J2G(J)) ? IR_EQ : IR_NE, IRT_PTR), xref, lj_ir_kptr(J, niltvg(J2G(J)))); 1008 emitir(IRTG(oldv == niltvg(J2G(J)) ? IR_EQ : IR_NE, IRT_PTR),
1009 xref, lj_ir_kptr(J, niltvg(J2G(J))));
1008 if (ix->idxchain && rec_mm_lookup(J, ix, MM_newindex)) { /* Metamethod? */ 1010 if (ix->idxchain && rec_mm_lookup(J, ix, MM_newindex)) { /* Metamethod? */
1009 lua_assert(hasmm); 1011 lua_assert(hasmm);
1010 goto handlemm; 1012 goto handlemm;
@@ -1015,6 +1017,7 @@ static TRef rec_idx(jit_State *J, RecordIndex *ix)
1015 if (tref_isinteger(key)) /* NEWREF needs a TValue as a key. */ 1017 if (tref_isinteger(key)) /* NEWREF needs a TValue as a key. */
1016 key = emitir(IRTN(IR_TONUM), key, 0); 1018 key = emitir(IRTN(IR_TONUM), key, 0);
1017 xref = emitir(IRT(IR_NEWREF, IRT_PTR), ix->tab, key); 1019 xref = emitir(IRT(IR_NEWREF, IRT_PTR), ix->tab, key);
1020 keybarrier = 0; /* NEWREF already takes care of the key barrier. */
1018 } 1021 }
1019 } else if (!lj_opt_fwd_wasnonnil(J, loadop, tref_ref(xref))) { 1022 } else if (!lj_opt_fwd_wasnonnil(J, loadop, tref_ref(xref))) {
1020 /* Cannot derive that the previous value was non-nil, must do checks. */ 1023 /* Cannot derive that the previous value was non-nil, must do checks. */
@@ -1030,11 +1033,13 @@ static TRef rec_idx(jit_State *J, RecordIndex *ix)
1030 emitir(IRTG(loadop, t), xref, 0); /* Guard for non-nil value. */ 1033 emitir(IRTG(loadop, t), xref, 0); /* Guard for non-nil value. */
1031 } 1034 }
1032 } 1035 }
1036 } else {
1037 keybarrier = 0; /* Previous non-nil value kept the key alive. */
1033 } 1038 }
1034 if (tref_isinteger(ix->val)) /* Convert int to number before storing. */ 1039 if (tref_isinteger(ix->val)) /* Convert int to number before storing. */
1035 ix->val = emitir(IRTN(IR_TONUM), ix->val, 0); 1040 ix->val = emitir(IRTN(IR_TONUM), ix->val, 0);
1036 emitir(IRT(loadop+IRDELTA_L2S, tref_type(ix->val)), xref, ix->val); 1041 emitir(IRT(loadop+IRDELTA_L2S, tref_type(ix->val)), xref, ix->val);
1037 if (tref_isgcv(ix->val)) 1042 if (keybarrier || tref_isgcv(ix->val))
1038 emitir(IRT(IR_TBAR, IRT_NIL), ix->tab, 0); 1043 emitir(IRT(IR_TBAR, IRT_NIL), ix->tab, 0);
1039 /* Invalidate neg. metamethod cache for stores with certain string keys. */ 1044 /* Invalidate neg. metamethod cache for stores with certain string keys. */
1040 if (!nommstr(J, ix->key)) { 1045 if (!nommstr(J, ix->key)) {