diff options
Diffstat (limited to 'src/lj_record.c')
-rw-r--r-- | src/lj_record.c | 9 |
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)) { |