mps icon indicating copy to clipboard operation
mps copied to clipboard

Large segments cannot be reclaimed if the padding object is pinned

Open gareth-rees opened this issue 2 years ago • 0 comments

To reduce external fragmentation, AMC pools have a "large size", such that allocations that are at least this big are given their own "large segment", with the remainder of the segment occupied by a padding object, as described in design.mps.poolamc.

However, there is a downside to this: if the padding object is pinned by an ambiguous reference, then the whole segment cannot be freed, as described under design.mps.poolamc.large.lsp-no-retain.

The suggestion in the design is to add a flag to amcSegStruct indicating whether the last object in the segment is subject to pinning in amcSegReclaimNailed. At the moment we determine whether to preserve an object as follows:

if(amcSegHasNailboard(seg)) {
  preserve = (*amc->pinned)(amc, amcSegNailboard(seg), clientP, clientQ);
} else {
  /* There's no nailboard, so preserve everything that hasn't been
   * forwarded. In this case, preservedInPlace* become somewhat
   * overstated. */
  preserve = !(*format->isMoved)(clientP);
}

but under the suggested change this becomes something like:

if (amcSegHasNailboard(seg)) {
  preserve = (amc->lastObjectPinnable || clientQ != SegLimit(seg))
    && (*amc->pinned)(amc, amcSegNailboard(seg), clientP, clientQ);
} else {
  /* There's no nailboard, so preserve everything that hasn't been
   * forwarded. In this case, preservedInPlace* become somewhat
   * overstated. */
  preserve = !(*format->isMoved)(clientP);
}

Note that the large segment case isn't the only case where an ambiguous reference to a padding object could cause retention: even in the small segment case, a segment could be retained due to some objects being pinned, with the other objects being replaced by padding objects, but then if one of the padding objects subsequently becomes pinned, and then all the pins of genuine objects go away, then this would cause the segment to be wrongly retained.

The underlying problem here is that we can't distinguish padding objects from genuine client objects: if we could distinguish them, then we could do things like merge adjacent padding objects as we reclaim the segment, and then we wouldn't need anything like the lastObjectPinnable flag as we could just notice at the end that the whole segment is filled with a single padding object and then free it.

Unfortunately we can't simply require clients to add an isPad method to object formats, as that would break backwards compatibility. But we could let them add it optionally and take advantage of it if present. Alternatively (as suggested in job003797) we could use forwarding objects that forward to some special value.

gareth-rees avatar Aug 21 '22 17:08 gareth-rees