summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Pall <mike>2021-07-27 14:47:41 +0200
committerMike Pall <mike>2021-07-27 14:47:41 +0200
commit3a654999c6f00de4cb9e61232d23579442e544a0 (patch)
tree7fb3854907e4453decc44c94d3cc15bd5c3619dc
parent0e66fc96377853d898390f1a02723c54ec3a42f7 (diff)
downloadluajit2-3a654999c6f00de4cb9e61232d23579442e544a0.tar.gz
Consider slots used by upvalues in use-def analysis.
Reported by XmiliaH.
-rw-r--r--src/lj_snap.c35
1 files 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;