You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 69371bd
Browse filesBrowse the repository at this point in the historyBrowse files
Mark Lam
committed
Push guard page de/allocation down into OSAllocator.
https://bugs.webkit.org/show_bug.cgi?id=297841
rdar://159065710
Reviewed by Yusuke Suzuki.
Previously, PageReservation can increase the allocation size by 2 pages to include guard pages.
It then tells OSAllocator that there are guard pages included by passing a includesGuardPages
bool. Based on this includesGuardPages bool, OSAllocator also assumes that the allocation
size includes exactly 2 page sized guard regions on each end. Unfortunately, this treatment
is not applied consistents everywhere. For example,
1. OSAllocator::tryReserveUncommitted() calls tryReserveAndCommit() with includesGuardPages
being true. tryReserveAndCommit() allocates the buffer including the guard pages, and maps
the guard pages to be PROT_NONE. Then, tryReserveUncommitted() fails to account for the
Guard pages and madvise() the whole range as MADV_FREE_REUSABLE (including guard pages).
This madvise fails, because it's not allowed to do this to the PROT_NONE guard pages.
2. PageReservation::deallocate() calls OSAllocator::releaseDecommitted() on its base() for
size() bytes. base() is not the base of the allocation, but just the start of the usable
section after the guard page at the start. releaseDecommitted() munmaps that memory range.
However, if there are guard regions on each end, the pages for the guard regions are never
munmapped.
This change makes the division of labor and responsibility clearer:
1. PageReservation just specifies how many guard pages it wants on each end, if any.
2. OSAllocator takes care of allocation / deallocation, including for guard pages.
So, PageReservation will now pass in the number of pages it wants as guard on each end.
OSAllocator takes care of the rest. Similarly. PageReservation::deallocate() also passes in
the number of pages it requested as guard on each end, and OSAllocator::releaseDecommitted()
does the right thing to munmap the actual memory range including any guard regions.
This approach simplifies the logic significantly, and makes it easier to get right:
1. PageBlock::m_realBase was initialized but never used. It can not be removed. It also makes
it clear that PageBlock is not responsible for dealing with guard regions.
2. PageReservation can now think of its buffer size request without needing to do any padding
math to account for guard regions.
3. PageReservation can now think of its addressHint without needing to do any padding math to
account for guard regions.
PageReservation no longer needs to do any padding math for the guard regions. OSAllocator will
take care of that as needed. This is also fine from a performance angle. OSAllocator calls are
already dominated by the mmap and munmap calls. The extra arithmetic for the padding math is
not going to move the needle in terms of perf impact.
Two additional changes:
4. Change addressHints to be specified using a void* instead of a std::optional. There's no
value add with using a std::optional for it. An addressHint of nullptr would indicated that
no hint is specified. This is already consistent with the convention mmap and munmap expects.
5. Change Linux's OSAllocator::tryReserveUncommitted() to also forward to OSAllocator::tryReserveAndCommit()
to do the mapping just like for OS(DARWIN), instead of rolling its own. There were only 2
differences between the 2 implementations to begin with:
a. Linux's OSAllocator::tryReserveUncommitted() sets the MAP_NORESERVE flag for its call to
mmap(). We now achieve this by repurposing the unused usage parameter to pass a new
OSAllocator::UncommittedPages value. This value tells OSAllocator::tryReserveAndCommit()
to add the MAP_NORESERVE flag for Linux.
b. After the mmap call, Linux's OSAllocator::tryReserveUncommitted() does a madvise() with
MADV_DONTNEED instead of MADV_FREE_REUSABLE. We retain this behavior by keeping different
madvise() calls for the 2 ports.
* Source/JavaScriptCore/jit/ExecutableAllocator.cpp:
(JSC::initializeJITPageReservation):
* Source/WTF/wtf/OSAllocator.h:
(WTF::OSAllocator::decommitAndRelease):
* Source/WTF/wtf/PageAllocation.h:
(WTF::PageAllocation::PageAllocation):
* Source/WTF/wtf/PageBlock.h:
(WTF::PageBlock::operator bool const):
(WTF::PageBlock::PageBlock):
* Source/WTF/wtf/PageReservation.h:
(WTF::PageReservation::reserve):
(WTF::PageReservation::tryReserve):
(WTF::PageReservation::reserveWithGuardPages):
(WTF::PageReservation::tryReserveWithGuardPages):
(WTF::PageReservation::deallocate):
(WTF::PageReservation::PageReservation):
* Source/WTF/wtf/playstation/OSAllocatorPlayStation.cpp:
(WTF::OSAllocator::tryReserveAndCommit):
(WTF::OSAllocator::tryReserveUncommitted):
(WTF::OSAllocator::reserveUncommitted):
(WTF::OSAllocator::tryReserveUncommittedAligned):
(WTF::OSAllocator::reserveAndCommit):
(WTF::OSAllocator::releaseDecommitted):
* Source/WTF/wtf/posix/OSAllocatorPOSIX.cpp:
(WTF::OSAllocator::tryReserveAndCommit):
(WTF::OSAllocator::tryReserveUncommitted):
(WTF::OSAllocator::reserveUncommitted):
(WTF::OSAllocator::tryReserveUncommittedAligned):
(WTF::OSAllocator::reserveAndCommit):
(WTF::OSAllocator::releaseDecommitted):
* Source/WTF/wtf/win/OSAllocatorWin.cpp:
(WTF::OSAllocator::tryReserveUncommitted):
(WTF::OSAllocator::reserveUncommitted):
(WTF::OSAllocator::tryReserveUncommittedAligned):
(WTF::OSAllocator::tryReserveAndCommit):
(WTF::OSAllocator::reserveAndCommit):
(WTF::OSAllocator::releaseDecommitted):
Canonical link: https://commits.webkit.org/299145@main
RELEASE_ASSERT(reservation.pageReservation.base() == addressHint && "Failed to accomodate JSC_jitMemoryReservationAddress");
409
409
410
410
if (Options::verboseExecutablePoolAllocation())
411
411
dataLog(getpid(), ": Got executable pool reservation at ", RawPointer(reservation.pageReservation.base()), "...", RawPointer(reservation.pageReservation.end()), ", while I'm at ", RawPointer(reinterpret_cast<void*>(initializeJITPageReservation)), "\n");
0 commit comments