[scudo] Slightly improve the handling of last block in a region
Instead of going through all those trailing blocks, just count the
number and increase the counter at once.
Reviewed By: cferris
Differential Revision: https://reviews.llvm.org/D145419
GitOrigin-RevId: e4efa885387e2df3a5e9abb3d64f232d2b4e9025
Change-Id: I4ac5eb1992b3db54c715a2f04d099a5fb14a3572
diff --git a/standalone/primary32.h b/standalone/primary32.h
index 1f06214..5d157f0 100644
--- a/standalone/primary32.h
+++ b/standalone/primary32.h
@@ -788,8 +788,12 @@
continue;
const uptr GroupBase = decompactGroupBase(BG.CompactPtrGroupBase);
- uptr AllocatedGroupSize =
- GroupBase == CurGroupBase ? Sci->CurrentRegionAllocated : GroupSize;
+ // The `GroupSize` may not be divided by `BlockSize`, which means there is
+ // an unused space at the end of Region. Exclude that space to avoid
+ // unused page map entry.
+ uptr AllocatedGroupSize = GroupBase == CurGroupBase
+ ? Sci->CurrentRegionAllocated
+ : roundDownSlow(GroupSize, BlockSize);
if (AllocatedGroupSize == 0)
continue;
diff --git a/standalone/release.h b/standalone/release.h
index c3b0a77..bb66a5d2 100644
--- a/standalone/release.h
+++ b/standalone/release.h
@@ -498,12 +498,28 @@
((RegionSize / BlockSize) - 1U) * BlockSize;
// The last block in a region may not use the entire page, we mark the
// following "pretend" memory block(s) as free in advance.
+ //
+ // Region Boundary
+ // v
+ // -----+-----------------------+
+ // | Last Page | <- Rounded Region Boundary
+ // -----+-----------------------+
+ // |-----||- trailing blocks -|
+ // ^
+ // last block
const uptr RoundedRegionSize = roundUp(RegionSize, PageSize);
- uptr PInRegion = LastBlockInRegion + BlockSize;
- while (PInRegion < RoundedRegionSize) {
- PageMap.incRange(RegionIndex, getPageIndex(PInRegion),
- getPageIndex(PInRegion + BlockSize - 1));
- PInRegion += BlockSize;
+ const uptr TrailingBlockBase = LastBlockInRegion + BlockSize;
+ // Only the last page touched by the last block needs to mark the trailing
+ // blocks. If the difference between `RoundedRegionSize` and
+ // `TrailingBlockBase` is larger than a page, that implies the reported
+ // `RegionSize` may not be accurate.
+ DCHECK_LT(RoundedRegionSize - TrailingBlockBase, PageSize);
+ uptr NumTrailingBlocks =
+ roundUpSlow(RoundedRegionSize - TrailingBlockBase, BlockSize) /
+ BlockSize;
+ if (NumTrailingBlocks > 0) {
+ PageMap.incN(RegionIndex, getPageIndex(TrailingBlockBase),
+ NumTrailingBlocks);
}
}