tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 2eace0bcf051f82ee6c6a679ed743ee57534e736
parent 9d46a4ed09733f321860f3c16d92f5e5efc87be4
Author: Paul Bone <paul@bone.id.au>
Date:   Tue, 18 Nov 2025 02:07:24 +0000

Bug 1987055 - pt 6. Better purging edge cases r=glandium

Make purging smarter around edge cases.  If the first or last dirty page
is not aligned with the hardware page size it will now attempt to purge
extra clean (but unused!) pages in order to capture the dirty pages.

This change also replaces some modulus operators with bitmasks.

Differential Revision: https://phabricator.services.mozilla.com/D264016

Diffstat:
Mmemory/build/mozjemalloc.cpp | 36+++++++++++++++++++++++++-----------
1 file changed, 25 insertions(+), 11 deletions(-)

diff --git a/memory/build/mozjemalloc.cpp b/memory/build/mozjemalloc.cpp @@ -2206,7 +2206,7 @@ bool arena_t::PurgeInfo::ScanForFirstDirtyPage() { mFreeRunInd = run_idx; mFreeRunLen = run_pages; - + mDirtyInd = 0; // Scan for dirty pages. for (size_t page_idx = run_idx; page_idx < run_idx + run_pages; page_idx++) { @@ -2215,17 +2215,24 @@ bool arena_t::PurgeInfo::ScanForFirstDirtyPage() { // the dirty list. MOZ_ASSERT((page_bits & CHUNK_MAP_BUSY) == 0); + // gPagesPerRealPage is a power of two, use a bitmask to check if page_idx + // is a multiple. + if ((page_idx & (gPagesPerRealPage - 1)) == 0) { + // A system call can be aligned here. + mDirtyInd = page_idx; + } + if (page_bits & CHUNK_MAP_DIRTY) { MOZ_ASSERT((page_bits & CHUNK_MAP_FRESH_MADVISED_OR_DECOMMITTED) == 0); MOZ_ASSERT(mChunk->mDirtyRunHint <= run_idx); mChunk->mDirtyRunHint = run_idx; - if ((page_idx & (gPagesPerRealPage - 1)) == 0) { - mDirtyInd = page_idx; + if (mDirtyInd) { return true; } - // This dirty page isn't aligned and can't be purged. + // This dirty page occurs before a page we can align on, + // so it can't be purged. mPurgeStats.pages_unpurgable++; } } @@ -2238,17 +2245,24 @@ bool arena_t::PurgeInfo::ScanForLastDirtyPage() { mDirtyLen = 0; for (size_t i = FreeRunLastInd(); i >= mDirtyInd; i--) { size_t& bits = mChunk->mPageMap[i].bits; - if (bits & CHUNK_MAP_DIRTY) { - // We must not find any busy pages because this chunk shouldn't be in the - // dirty list. - MOZ_ASSERT(!(bits & CHUNK_MAP_BUSY)); + // We must not find any busy pages because this chunk shouldn't be in the + // dirty list. + MOZ_ASSERT(!(bits & CHUNK_MAP_BUSY)); + + // gPagesPerRealPage is a power of two, use a bitmask to check if page_idx + // is a multiple minus one. + if ((i & (gPagesPerRealPage - 1)) == gPagesPerRealPage - 1) { + // A system call can be aligned here. + mDirtyLen = i - mDirtyInd + 1; + } - if ((i & (gPagesPerRealPage - 1)) == gPagesPerRealPage - 1) { - mDirtyLen = i - mDirtyInd + 1; + if (bits & CHUNK_MAP_DIRTY) { + if (mDirtyLen) { return true; } - // This dirty page's end isn't aligned with a real page's end. + // This dirty page occurs after a page we can align on, + // so it can't be purged. mPurgeStats.pages_unpurgable++; } }