From 3a654999c6f00de4cb9e61232d23579442e544a0 Mon Sep 17 00:00:00 2001 From: Mike Pall Date: Tue, 27 Jul 2021 14:47:41 +0200 Subject: [PATCH] Consider slots used by upvalues in use-def analysis. Reported by XmiliaH. --- src/lj_snap.c | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/src/lj_snap.c b/src/lj_snap.c index 91880fcf..333812fd 100644 --- a/src/lj_snap.c +++ b/src/lj_snap.c @@ -272,6 +272,31 @@ static BCReg snap_usedef(jit_State *J, uint8_t *udf, return 0; /* unreachable */ } +/* Mark slots used by upvalues of child prototypes as used. */ +void snap_useuv(GCproto *pt, uint8_t *udf) +{ + /* This is a coarse check, because it's difficult to correlate the lifetime + ** of slots and closures. But the number of false positives is quite low. + ** A false positive may cause a slot not to be purged, which is just + ** a missed optimization. + */ + if ((pt->flags & PROTO_CHILD)) { + ptrdiff_t i, j, n = pt->sizekgc; + GCRef *kr = mref(pt->k, GCRef) - 1; + for (i = 0; i < n; i++, kr--) { + GCobj *o = gcref(*kr); + if (o->gch.gct == ~LJ_TPROTO) { + for (j = 0; j < gco2pt(o)->sizeuv; j++) { + uint32_t v = proto_uv(gco2pt(o))[j]; + if ((v & PROTO_UV_LOCAL)) { + udf[(v & 0xff)] = 0; + } + } + } + } + } +} + /* Purge dead slots before the next snapshot. */ void lj_snap_purge(jit_State *J) { @@ -280,9 +305,12 @@ void lj_snap_purge(jit_State *J) if (bc_op(*J->pc) == BC_FUNCV && maxslot > J->pt->numparams) maxslot = J->pt->numparams; s = snap_usedef(J, udf, J->pc, maxslot); - for (; s < maxslot; s++) - if (udf[s] != 0) - J->base[s] = 0; /* Purge dead slots. */ + if (s < maxslot) { + snap_useuv(J->pt, udf); + for (; s < maxslot; s++) + if (udf[s] != 0) + J->base[s] = 0; /* Purge dead slots. */ + } } /* Shrink last snapshot. */ @@ -295,6 +323,7 @@ void lj_snap_shrink(jit_State *J) BCReg maxslot = J->maxslot; BCReg minslot = snap_usedef(J, udf, snap_pc(map[nent]), maxslot); BCReg baseslot = J->baseslot; + if (minslot < maxslot) snap_useuv(J->pt, udf); maxslot += baseslot; minslot += baseslot; snap->nslots = (uint8_t)maxslot;