-
Notifications
You must be signed in to change notification settings - Fork 931
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Double-emitting of IR_NEWREF
for the same key on the snap replay
#1128
Comments
Slightly simpler test case: local t2
for i = 1, 75 do
local t = {}
t.k = false
t.k = i > 0
if i > 60 then t2 = t end
end
for k, v in pairs(t2) do assert(v, k) end I also think that the patch can be simplified; While playing around with test case minimisation, I also spotted what looks like an optimisation opportunity for diff --git a/src/lj_ffrecord.c b/src/lj_ffrecord.c
index 1233e5f74e..4243098f1f 100644
--- a/src/lj_ffrecord.c
+++ b/src/lj_ffrecord.c
@@ -1444,6 +1456,15 @@ static void LJ_FASTCALL recff_table_new(jit_State *J, RecordFFData *rd)
{
TRef tra = lj_opt_narrow_toint(J, J->base[0]);
TRef trh = lj_opt_narrow_toint(J, J->base[1]);
+ if (tref_isk(tra) && tref_isk(trh)) {
+ int32_t a = IR(tref_ref(tra))->i;
+ if (a < 0x7fff) {
+ uint32_t hbits = hsize2hbits(IR(tref_ref(trh))->i);
+ a = a > 0 ? a+1 : 0;
+ J->base[0] = emitir(IRTG(IR_TNEW, IRT_TAB), (uint32_t)a, hbits);
+ return;
+ }
+ }
J->base[0] = lj_ir_call(J, IRCALL_lj_tab_new_ah, tra, trh);
UNUSED(rd);
} |
Hi, Peter! diff --git a/src/lj_snap.c b/src/lj_snap.c
index 68de208f..dc31524a 100644
--- a/src/lj_snap.c
+++ b/src/lj_snap.c
@@ -624,9 +624,25 @@ void lj_snap_replay(jit_State *J, GCtrace *T)
if (irr->o == IR_HREFK || irr->o == IR_AREF) {
IRIns *irf = &T->ir[irr->op1];
tmp = emitir(irf->ot, tmp, irf->op2);
+ } else if (irr->o == IR_NEWREF) {
+ IRRef allocref = tref_ref(tr);
+ IRRef keyref = tref_ref(key);
+ IRRef newref_ref = J->chain[IR_NEWREF];
+ IRIns *newref = &J->cur.ir[newref_ref];
+ lj_assertJ(irref_isk(keyref),
+ "sunk store for parent IR %04d with bad key %04d",
+ refp - REF_BIAS, keyref - REF_BIAS);
+ if (newref_ref > allocref && newref->op2 == keyref) {
+ lj_assertJ(newref->op1 == allocref,
+ "sunk store for parent IR %04d with bad tab %04d",
+ refp - REF_BIAS, allocref - REF_BIAS);
+ tmp = newref_ref;
+ goto skip_newref;
+ }
}
}
tmp = emitir(irr->ot, tmp, key);
+skip_newref:
val = snap_pref(J, T, map, nent, seen, irs->op2);
if (val == 0) {
IRIns *irc = &T->ir[irs->op2]; |
Thanks to Sergey Kaplun and Peter Cawley. #1128
Fixed. Thanks! |
The following script prints incorrect results with JIT enabled:
Returns
-1
instead of0
.The trace dump is the following:
As we can see, snapshot replaying emits
NEWREF
twice for the same key.As a possible approach, we can scan backwards already emitted
NEWREF
and take the one with the necessary operands:After the patch, the resulting IRs, as expected, are the following:
I can't come up with counter-examples for this approach:
table.clear()
calls aren't emitted in the side trace head.The text was updated successfully, but these errors were encountered: