Branch: refs/heads/main
  Home:   https://github.com/WebKit/WebKit
  Commit: 69371bd0991ed38ae47d56b9bb2dc7f940e9a3e3
      
https://github.com/WebKit/WebKit/commit/69371bd0991ed38ae47d56b9bb2dc7f940e9a3e3
  Author: Mark Lam <mark....@apple.com>
  Date:   2025-08-25 (Mon, 25 Aug 2025)

  Changed paths:
    M Source/JavaScriptCore/jit/ExecutableAllocator.cpp
    M Source/WTF/wtf/OSAllocator.h
    M Source/WTF/wtf/PageAllocation.h
    M Source/WTF/wtf/PageBlock.h
    M Source/WTF/wtf/PageReservation.h
    M Source/WTF/wtf/playstation/OSAllocatorPlayStation.cpp
    M Source/WTF/wtf/posix/OSAllocatorPOSIX.cpp
    M Source/WTF/wtf/win/OSAllocatorWin.cpp

  Log Message:
  -----------
  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



To unsubscribe from these emails, change your notification settings at 
https://github.com/WebKit/WebKit/settings/notifications
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to