aboutsummaryrefslogtreecommitdiff
path: root/src/lj_snap.c
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 /src/lj_snap.c
parent0e66fc96377853d898390f1a02723c54ec3a42f7 (diff)
downloadluajit-3a654999c6f00de4cb9e61232d23579442e544a0.tar.gz
luajit-3a654999c6f00de4cb9e61232d23579442e544a0.tar.bz2
luajit-3a654999c6f00de4cb9e61232d23579442e544a0.zip
Consider slots used by upvalues in use-def analysis.
Reported by XmiliaH.
Diffstat (limited to 'src/lj_snap.c')
-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,
272 return 0; /* unreachable */ 272 return 0; /* unreachable */
273} 273}
274 274
275/* Mark slots used by upvalues of child prototypes as used. */
276void snap_useuv(GCproto *pt, uint8_t *udf)
277{
278 /* This is a coarse check, because it's difficult to correlate the lifetime
279 ** of slots and closures. But the number of false positives is quite low.
280 ** A false positive may cause a slot not to be purged, which is just
281 ** a missed optimization.
282 */
283 if ((pt->flags & PROTO_CHILD)) {
284 ptrdiff_t i, j, n = pt->sizekgc;
285 GCRef *kr = mref(pt->k, GCRef) - 1;
286 for (i = 0; i < n; i++, kr--) {
287 GCobj *o = gcref(*kr);
288 if (o->gch.gct == ~LJ_TPROTO) {
289 for (j = 0; j < gco2pt(o)->sizeuv; j++) {
290 uint32_t v = proto_uv(gco2pt(o))[j];
291 if ((v & PROTO_UV_LOCAL)) {
292 udf[(v & 0xff)] = 0;
293 }
294 }
295 }
296 }
297 }
298}
299
275/* Purge dead slots before the next snapshot. */ 300/* Purge dead slots before the next snapshot. */
276void lj_snap_purge(jit_State *J) 301void lj_snap_purge(jit_State *J)
277{ 302{
@@ -280,9 +305,12 @@ void lj_snap_purge(jit_State *J)
280 if (bc_op(*J->pc) == BC_FUNCV && maxslot > J->pt->numparams) 305 if (bc_op(*J->pc) == BC_FUNCV && maxslot > J->pt->numparams)
281 maxslot = J->pt->numparams; 306 maxslot = J->pt->numparams;
282 s = snap_usedef(J, udf, J->pc, maxslot); 307 s = snap_usedef(J, udf, J->pc, maxslot);
283 for (; s < maxslot; s++) 308 if (s < maxslot) {
284 if (udf[s] != 0) 309 snap_useuv(J->pt, udf);
285 J->base[s] = 0; /* Purge dead slots. */ 310 for (; s < maxslot; s++)
311 if (udf[s] != 0)
312 J->base[s] = 0; /* Purge dead slots. */
313 }
286} 314}
287 315
288/* Shrink last snapshot. */ 316/* Shrink last snapshot. */
@@ -295,6 +323,7 @@ void lj_snap_shrink(jit_State *J)
295 BCReg maxslot = J->maxslot; 323 BCReg maxslot = J->maxslot;
296 BCReg minslot = snap_usedef(J, udf, snap_pc(map[nent]), maxslot); 324 BCReg minslot = snap_usedef(J, udf, snap_pc(map[nent]), maxslot);
297 BCReg baseslot = J->baseslot; 325 BCReg baseslot = J->baseslot;
326 if (minslot < maxslot) snap_useuv(J->pt, udf);
298 maxslot += baseslot; 327 maxslot += baseslot;
299 minslot += baseslot; 328 minslot += baseslot;
300 snap->nslots = (uint8_t)maxslot; 329 snap->nslots = (uint8_t)maxslot;