Title: [198829] trunk/Source/bmalloc
Revision
198829
Author
[email protected]
Date
2016-03-29 23:42:36 -0700 (Tue, 29 Mar 2016)

Log Message

bmalloc: support physical page sizes that don't match the virtual page size (take 2)
https://bugs.webkit.org/show_bug.cgi?id=156003

Reviewed by Andreas Kling.

This is a memory savings on iOS devices where the virtual page size
is 16kB but the physical page size is 4kB.

Take 1 was a memory regression on 16kB virtual / 16kB physical systems
because it used a 4kB page size within a 16kB page size, allowing up to
4 different object types to mix within a physical page. Because objects
of the same type tend to deallocate at the same time, mixing objects of
different types made pages less likely to become completely empty.

(Take 1 also had a bug where it used a platform #ifdef that didn't exist.
Oops.)

Take 2 allocates units of SmallPages equal to the physical page size.

* bmalloc/Heap.cpp:
(bmalloc::Heap::Heap):
(bmalloc::Heap::initializeLineMetadata):
(bmalloc::Heap::allocateSmallBumpRanges):
(bmalloc::Heap::allocateSmallPage):
(bmalloc::Heap::allocateLarge):
(bmalloc::Heap::splitAndAllocate):
(bmalloc::Heap::tryAllocateXLarge):
(bmalloc::Heap::shrinkXLarge):
* bmalloc/Heap.h: Use the physical page size for our VM operations because
we're only concerned with returning physical pages to the OS.

* bmalloc/VMAllocate.h:
(bmalloc::vmPageSize):
(bmalloc::vmPageShift):
(bmalloc::vmSize):
(bmalloc::vmValidate):
(bmalloc::vmPageSizePhysical):
(bmalloc::vmValidatePhysical):
(bmalloc::tryVMAllocate):
(bmalloc::vmDeallocatePhysicalPages):
(bmalloc::vmAllocatePhysicalPages):
(bmalloc::vmDeallocatePhysicalPagesSloppy):
(bmalloc::vmAllocatePhysicalPagesSloppy): Use the physical page size.

Modified Paths

Diff

Modified: trunk/Source/bmalloc/ChangeLog (198828 => 198829)


--- trunk/Source/bmalloc/ChangeLog	2016-03-30 06:00:22 UTC (rev 198828)
+++ trunk/Source/bmalloc/ChangeLog	2016-03-30 06:42:36 UTC (rev 198829)
@@ -1,5 +1,51 @@
 2016-03-29  Geoffrey Garen  <[email protected]>
 
+        bmalloc: support physical page sizes that don't match the virtual page size (take 2)
+        https://bugs.webkit.org/show_bug.cgi?id=156003
+
+        Reviewed by Andreas Kling.
+
+        This is a memory savings on iOS devices where the virtual page size
+        is 16kB but the physical page size is 4kB.
+
+        Take 1 was a memory regression on 16kB virtual / 16kB physical systems
+        because it used a 4kB page size within a 16kB page size, allowing up to
+        4 different object types to mix within a physical page. Because objects
+        of the same type tend to deallocate at the same time, mixing objects of
+        different types made pages less likely to become completely empty.
+
+        (Take 1 also had a bug where it used a platform #ifdef that didn't exist.
+        Oops.)
+
+        Take 2 allocates units of SmallPages equal to the physical page size.
+
+        * bmalloc/Heap.cpp:
+        (bmalloc::Heap::Heap):
+        (bmalloc::Heap::initializeLineMetadata):
+        (bmalloc::Heap::allocateSmallBumpRanges):
+        (bmalloc::Heap::allocateSmallPage):
+        (bmalloc::Heap::allocateLarge):
+        (bmalloc::Heap::splitAndAllocate):
+        (bmalloc::Heap::tryAllocateXLarge):
+        (bmalloc::Heap::shrinkXLarge):
+        * bmalloc/Heap.h: Use the physical page size for our VM operations because
+        we're only concerned with returning physical pages to the OS.
+
+        * bmalloc/VMAllocate.h:
+        (bmalloc::vmPageSize):
+        (bmalloc::vmPageShift):
+        (bmalloc::vmSize):
+        (bmalloc::vmValidate):
+        (bmalloc::vmPageSizePhysical):
+        (bmalloc::vmValidatePhysical):
+        (bmalloc::tryVMAllocate):
+        (bmalloc::vmDeallocatePhysicalPages):
+        (bmalloc::vmAllocatePhysicalPages):
+        (bmalloc::vmDeallocatePhysicalPagesSloppy):
+        (bmalloc::vmAllocatePhysicalPagesSloppy): Use the physical page size.
+
+2016-03-29  Geoffrey Garen  <[email protected]>
+
         bmalloc: page size should be configurable at runtime
         https://bugs.webkit.org/show_bug.cgi?id=155993
 

Modified: trunk/Source/bmalloc/bmalloc/Heap.cpp (198828 => 198829)


--- trunk/Source/bmalloc/bmalloc/Heap.cpp	2016-03-30 06:00:22 UTC (rev 198828)
+++ trunk/Source/bmalloc/bmalloc/Heap.cpp	2016-03-30 06:42:36 UTC (rev 198829)
@@ -35,11 +35,15 @@
 namespace bmalloc {
 
 Heap::Heap(std::lock_guard<StaticMutex>&)
-    : m_vmPageSize(vmPageSize())
+    : m_vmPageSizePhysical(vmPageSizePhysical())
     , m_largeObjects(VMState::HasPhysical::True)
     , m_isAllocatingPages(false)
     , m_scavenger(*this, &Heap::concurrentScavenge)
 {
+    RELEASE_BASSERT(vmPageSizePhysical() >= smallPageSize);
+    RELEASE_BASSERT(vmPageSize() >= vmPageSizePhysical());
+    RELEASE_BASSERT(xLargeAlignment >= vmPageSize());
+
     initializeLineMetadata();
 }
 
@@ -47,7 +51,7 @@
 {
     // We assume that m_smallLineMetadata is zero-filled.
 
-    size_t smallLineCount = m_vmPageSize / smallLineSize;
+    size_t smallLineCount = m_vmPageSizePhysical / smallLineSize;
     m_smallLineMetadata.grow(sizeClassCount * smallLineCount);
 
     for (size_t sizeClass = 0; sizeClass < sizeClassCount; ++sizeClass) {
@@ -56,7 +60,7 @@
 
         size_t object = 0;
         size_t line = 0;
-        while (object < m_vmPageSize) {
+        while (object < m_vmPageSizePhysical) {
             line = object / smallLineSize;
             size_t leftover = object % smallLineSize;
 
@@ -70,7 +74,7 @@
         }
 
         // Don't allow the last object in a page to escape the page.
-        if (object > m_vmPageSize) {
+        if (object > m_vmPageSizePhysical) {
             BASSERT(pageMetadata[line].objectCount);
             --pageMetadata[line].objectCount;
         }
@@ -152,7 +156,7 @@
     SmallPage* page = allocateSmallPage(lock, sizeClass);
     SmallLine* lines = page->begin();
     BASSERT(page->hasFreeLines(lock));
-    size_t smallLineCount = m_vmPageSize / smallLineSize;
+    size_t smallLineCount = m_vmPageSizePhysical / smallLineSize;
     LineMetadata* pageMetadata = &m_smallLineMetadata[sizeClass * smallLineCount];
 
     // Find a free line.
@@ -211,8 +215,8 @@
         return page;
     }
 
-    size_t unalignedSize = largeMin + m_vmPageSize - largeAlignment + m_vmPageSize;
-    LargeObject largeObject = allocateLarge(lock, m_vmPageSize, m_vmPageSize, unalignedSize);
+    size_t unalignedSize = largeMin + m_vmPageSizePhysical - largeAlignment + m_vmPageSizePhysical;
+    LargeObject largeObject = allocateLarge(lock, m_vmPageSizePhysical, m_vmPageSizePhysical, unalignedSize);
     
     // Transform our large object into a small object page. We deref here
     // because our small objects will keep their own line refcounts.
@@ -222,10 +226,10 @@
 
     SmallPage* page = object.page();
     page->setSizeClass(sizeClass);
-    page->setSmallPageCount(m_vmPageSize / smallPageSize);
+    page->setSmallPageCount(m_vmPageSizePhysical / smallPageSize);
 
     // Set a slide() value on intermediate SmallPages so they hash to their
-    // vmPageSize-sized page.
+    // vmPageSizePhysical-sized page.
     for (size_t i = 1; i < page->smallPageCount(); ++i)
         page[i].setSlide(i);
 
@@ -326,7 +330,7 @@
     BASSERT(size >= largeMin);
     BASSERT(size == roundUpToMultipleOf<largeAlignment>(size));
     
-    if (size <= m_vmPageSize)
+    if (size <= m_vmPageSizePhysical)
         scavengeSmallPages(lock);
 
     LargeObject largeObject = m_largeObjects.take(size);
@@ -357,7 +361,7 @@
     BASSERT(alignment >= largeAlignment);
     BASSERT(isPowerOfTwo(alignment));
 
-    if (size <= m_vmPageSize)
+    if (size <= m_vmPageSizePhysical)
         scavengeSmallPages(lock);
 
     LargeObject largeObject = m_largeObjects.take(alignment, size, unalignedSize);
@@ -431,7 +435,7 @@
     // in the allocated list. This is an important optimization because it
     // keeps the free list short, speeding up allocation and merging.
 
-    std::pair<XLargeRange, XLargeRange> allocated = range.split(roundUpToMultipleOf(m_vmPageSize, size));
+    std::pair<XLargeRange, XLargeRange> allocated = range.split(roundUpToMultipleOf(m_vmPageSizePhysical, size));
     if (allocated.first.vmState().hasVirtual()) {
         vmAllocatePhysicalPagesSloppy(allocated.first.begin(), allocated.first.size());
         allocated.first.setVMState(VMState::Physical);
@@ -448,7 +452,7 @@
 
     m_isAllocatingPages = true;
 
-    size = std::max(m_vmPageSize, size);
+    size = std::max(m_vmPageSizePhysical, size);
     alignment = roundUpToMultipleOf<xLargeAlignment>(alignment);
 
     XLargeRange range = m_xLargeMap.takeFree(alignment, size);
@@ -475,7 +479,7 @@
 {
     BASSERT(object.size() > newSize);
 
-    if (object.size() - newSize < m_vmPageSize)
+    if (object.size() - newSize < m_vmPageSizePhysical)
         return;
     
     XLargeRange range = m_xLargeMap.takeAllocated(object.begin());

Modified: trunk/Source/bmalloc/bmalloc/Heap.h (198828 => 198829)


--- trunk/Source/bmalloc/bmalloc/Heap.h	2016-03-30 06:00:22 UTC (rev 198828)
+++ trunk/Source/bmalloc/bmalloc/Heap.h	2016-03-30 06:42:36 UTC (rev 198829)
@@ -93,7 +93,7 @@
     void scavengeLargeObjects(std::unique_lock<StaticMutex>&, std::chrono::milliseconds);
     void scavengeXLargeObjects(std::unique_lock<StaticMutex>&, std::chrono::milliseconds);
 
-    size_t m_vmPageSize;
+    size_t m_vmPageSizePhysical;
 
     Vector<LineMetadata> m_smallLineMetadata;
 

Modified: trunk/Source/bmalloc/bmalloc/VMAllocate.h (198828 => 198829)


--- trunk/Source/bmalloc/bmalloc/VMAllocate.h	2016-03-30 06:00:22 UTC (rev 198828)
+++ trunk/Source/bmalloc/bmalloc/VMAllocate.h	2016-03-30 06:42:36 UTC (rev 198829)
@@ -36,6 +36,7 @@
 #include <unistd.h>
 
 #if BOS(DARWIN)
+#include <mach/vm_page_size.h>
 #include <mach/vm_statistics.h>
 #endif
 
@@ -49,12 +50,18 @@
 
 inline size_t vmPageSize()
 {
-    return sysconf(_SC_PAGESIZE);
+    static size_t cached;
+    if (!cached)
+        cached = sysconf(_SC_PAGESIZE);
+    return cached;
 }
 
 inline size_t vmPageShift()
 {
-    return log2(vmPageSize());
+    static size_t cached;
+    if (!cached)
+        cached = log2(vmPageSize());
+    return cached;
 }
 
 inline size_t vmSize(size_t size)
@@ -78,6 +85,34 @@
     BASSERT(p == mask(p, ~(vmPageSize() - 1)));
 }
 
+inline size_t vmPageSizePhysical()
+{
+#if (BPLATFORM(IOS) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000)
+    return vm_kernel_page_size;
+#else
+    static size_t cached;
+    if (!cached)
+        cached = sysconf(_SC_PAGESIZE);
+    return cached;
+#endif
+}
+
+inline void vmValidatePhysical(size_t vmSize)
+{
+    UNUSED(vmSize);
+    BASSERT(vmSize);
+    BASSERT(vmSize == roundUpToMultipleOf(vmPageSizePhysical(), vmSize));
+}
+
+inline void vmValidatePhysical(void* p, size_t vmSize)
+{
+    vmValidatePhysical(vmSize);
+    
+    UNUSED(p);
+    BASSERT(p);
+    BASSERT(p == mask(p, ~(vmPageSizePhysical() - 1)));
+}
+
 inline void* tryVMAllocate(size_t vmSize)
 {
     vmValidate(vmSize);
@@ -139,7 +174,7 @@
 
 inline void vmDeallocatePhysicalPages(void* p, size_t vmSize)
 {
-    vmValidate(p, vmSize);
+    vmValidatePhysical(p, vmSize);
 #if BOS(DARWIN)
     SYSCALL(madvise(p, vmSize, MADV_FREE_REUSABLE));
 #else
@@ -149,7 +184,7 @@
 
 inline void vmAllocatePhysicalPages(void* p, size_t vmSize)
 {
-    vmValidate(p, vmSize);
+    vmValidatePhysical(p, vmSize);
 #if BOS(DARWIN)
     SYSCALL(madvise(p, vmSize, MADV_FREE_REUSE));
 #else
@@ -160,8 +195,8 @@
 // Trims requests that are un-page-aligned.
 inline void vmDeallocatePhysicalPagesSloppy(void* p, size_t size)
 {
-    char* begin = roundUpToMultipleOf(vmPageSize(), static_cast<char*>(p));
-    char* end = roundDownToMultipleOf(vmPageSize(), static_cast<char*>(p) + size);
+    char* begin = roundUpToMultipleOf(vmPageSizePhysical(), static_cast<char*>(p));
+    char* end = roundDownToMultipleOf(vmPageSizePhysical(), static_cast<char*>(p) + size);
 
     if (begin >= end)
         return;
@@ -172,8 +207,8 @@
 // Expands requests that are un-page-aligned.
 inline void vmAllocatePhysicalPagesSloppy(void* p, size_t size)
 {
-    char* begin = roundDownToMultipleOf(vmPageSize(), static_cast<char*>(p));
-    char* end = roundUpToMultipleOf(vmPageSize(), static_cast<char*>(p) + size);
+    char* begin = roundDownToMultipleOf(vmPageSizePhysical(), static_cast<char*>(p));
+    char* end = roundUpToMultipleOf(vmPageSizePhysical(), static_cast<char*>(p) + size);
 
     if (begin >= end)
         return;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to