diff options
Diffstat (limited to 'src')
| -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; |
