diff --git a/compiler-rt/lib/scudo/standalone/primary32.h b/compiler-rt/lib/scudo/standalone/primary32.h --- a/compiler-rt/lib/scudo/standalone/primary32.h +++ b/compiler-rt/lib/scudo/standalone/primary32.h @@ -725,6 +725,9 @@ Context.markFreeBlocks(BG.Batches, DecompactPtr, Base); } + if (!Context.hasBlockMarked()) + return 0; + auto SkipRegion = [this, First, ClassId](uptr RegionIndex) { return (PossibleRegions[First + RegionIndex] - 1U) != ClassId; }; diff --git a/compiler-rt/lib/scudo/standalone/primary64.h b/compiler-rt/lib/scudo/standalone/primary64.h --- a/compiler-rt/lib/scudo/standalone/primary64.h +++ b/compiler-rt/lib/scudo/standalone/primary64.h @@ -728,6 +728,9 @@ Context.markFreeBlocks(BG.Batches, DecompactPtr, Region->RegionBeg); } + if (!Context.hasBlockMarked()) + return 0; + auto SkipRegion = [](UNUSED uptr RegionIndex) { return false; }; releaseFreeMemoryToOS(Context, Recorder, SkipRegion); diff --git a/compiler-rt/lib/scudo/standalone/release.h b/compiler-rt/lib/scudo/standalone/release.h --- a/compiler-rt/lib/scudo/standalone/release.h +++ b/compiler-rt/lib/scudo/standalone/release.h @@ -258,7 +258,16 @@ PageSizeLog = getLog2(PageSize); RoundedRegionSize = PagesCount << PageSizeLog; RoundedSize = NumberOfRegions * RoundedRegionSize; + } + + // PageMap is lazily allocated when markFreeBlocks() is invoked. + bool hasBlockMarked() const { + return PageMap.isAllocated(); + } + void ensurePageMapAllocated() { + if (PageMap.isAllocated()) + return; PageMap.reset(NumberOfRegions, PagesCount, FullPagesBlockCountMax); DCHECK(PageMap.isAllocated()); } @@ -266,6 +275,8 @@ template void markFreeBlocks(const IntrusiveList &FreeList, DecompactPtrT DecompactPtr, uptr Base) { + ensurePageMapAllocated(); + // Iterate over free chunks and count how many free chunks affect each // allocated page. if (BlockSize <= PageSize && PageSize % BlockSize == 0) { diff --git a/compiler-rt/lib/scudo/standalone/tests/release_test.cpp b/compiler-rt/lib/scudo/standalone/tests/release_test.cpp --- a/compiler-rt/lib/scudo/standalone/tests/release_test.cpp +++ b/compiler-rt/lib/scudo/standalone/tests/release_test.cpp @@ -199,7 +199,9 @@ scudo::PageReleaseContext Context(BlockSize, /*RegionSize=*/MaxBlocks * BlockSize, /*NumberOfRegions=*/1U); + ASSERT_FALSE(Context.hasBlockMarked()); Context.markFreeBlocks(FreeList, DecompactPtr, Recorder.getBase()); + ASSERT_TRUE(Context.hasBlockMarked()); releaseFreeMemoryToOS(Context, Recorder, SkipRegion); scudo::RegionPageMap &PageMap = Context.PageMap;