diff options
-rw-r--r-- | src/lj_snap.c | 35 |
1 files changed, 32 insertions, 3 deletions
diff --git a/src/lj_snap.c b/src/lj_snap.c index b2b8450c..40bfad92 100644 --- a/src/lj_snap.c +++ b/src/lj_snap.c | |||
@@ -312,6 +312,31 @@ static BCReg snap_usedef(jit_State *J, uint8_t *udf, | |||
312 | return 0; /* unreachable */ | 312 | return 0; /* unreachable */ |
313 | } | 313 | } |
314 | 314 | ||
315 | /* Mark slots used by upvalues of child prototypes as used. */ | ||
316 | void snap_useuv(GCproto *pt, uint8_t *udf) | ||
317 | { | ||
318 | /* This is a coarse check, because it's difficult to correlate the lifetime | ||
319 | ** of slots and closures. But the number of false positives is quite low. | ||
320 | ** A false positive may cause a slot not to be purged, which is just | ||
321 | ** a missed optimization. | ||
322 | */ | ||
323 | if ((pt->flags & PROTO_CHILD)) { | ||
324 | ptrdiff_t i, j, n = pt->sizekgc; | ||
325 | GCRef *kr = mref(pt->k, GCRef) - 1; | ||
326 | for (i = 0; i < n; i++, kr--) { | ||
327 | GCobj *o = gcref(*kr); | ||
328 | if (o->gch.gct == ~LJ_TPROTO) { | ||
329 | for (j = 0; j < gco2pt(o)->sizeuv; j++) { | ||
330 | uint32_t v = proto_uv(gco2pt(o))[j]; | ||
331 | if ((v & PROTO_UV_LOCAL)) { | ||
332 | udf[(v & 0xff)] = 0; | ||
333 | } | ||
334 | } | ||
335 | } | ||
336 | } | ||
337 | } | ||
338 | } | ||
339 | |||
315 | /* Purge dead slots before the next snapshot. */ | 340 | /* Purge dead slots before the next snapshot. */ |
316 | void lj_snap_purge(jit_State *J) | 341 | void lj_snap_purge(jit_State *J) |
317 | { | 342 | { |
@@ -320,9 +345,12 @@ void lj_snap_purge(jit_State *J) | |||
320 | if (bc_op(*J->pc) == BC_FUNCV && maxslot > J->pt->numparams) | 345 | if (bc_op(*J->pc) == BC_FUNCV && maxslot > J->pt->numparams) |
321 | maxslot = J->pt->numparams; | 346 | maxslot = J->pt->numparams; |
322 | s = snap_usedef(J, udf, J->pc, maxslot); | 347 | s = snap_usedef(J, udf, J->pc, maxslot); |
323 | for (; s < maxslot; s++) | 348 | if (s < maxslot) { |
324 | if (udf[s] != 0) | 349 | snap_useuv(J->pt, udf); |
325 | J->base[s] = 0; /* Purge dead slots. */ | 350 | for (; s < maxslot; s++) |
351 | if (udf[s] != 0) | ||
352 | J->base[s] = 0; /* Purge dead slots. */ | ||
353 | } | ||
326 | } | 354 | } |
327 | 355 | ||
328 | /* Shrink last snapshot. */ | 356 | /* Shrink last snapshot. */ |
@@ -335,6 +363,7 @@ void lj_snap_shrink(jit_State *J) | |||
335 | BCReg maxslot = J->maxslot; | 363 | BCReg maxslot = J->maxslot; |
336 | BCReg baseslot = J->baseslot; | 364 | BCReg baseslot = J->baseslot; |
337 | BCReg minslot = snap_usedef(J, udf, snap_pc(&map[nent]), maxslot); | 365 | BCReg minslot = snap_usedef(J, udf, snap_pc(&map[nent]), maxslot); |
366 | if (minslot < maxslot) snap_useuv(J->pt, udf); | ||
338 | maxslot += baseslot; | 367 | maxslot += baseslot; |
339 | minslot += baseslot; | 368 | minslot += baseslot; |
340 | snap->nslots = (uint8_t)maxslot; | 369 | snap->nslots = (uint8_t)maxslot; |