<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[248687] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/248687">248687</a></dd>
<dt>Author</dt> <dd>ysuzuki@apple.com</dd>
<dt>Date</dt> <dd>2019-08-14 13:33:14 -0700 (Wed, 14 Aug 2019)</dd>
</dl>

<h3>Log Message</h3>
<pre>[JSC] Less contended MetaAllocator
https://bugs.webkit.org/show_bug.cgi?id=200278

Reviewed by Mark Lam.

Source/JavaScriptCore:

The profiler result of JetStream2/bomb-workers shows that we are having contention under MetaAllocator::currentStatistics.
This function is called in ExecutableAllocator::memoryPressureMultiplier, and it is called from ExecutableCounter's threshold
calculation. But MetaAllocator::currentStatistics takes a global lock inside MetaAllocator and causes contention. However,
we do not need to have a lock actually: clients of MetaAllocator::currentStatistics typically use bytesReserved and bytesAllocated
information. However, since our executable allocator is fixed-sized, bytesReserved is always the fixed size. So just reading bytesAllocated
racily is enough.

This patch attempts to reduce the contention by the following two things.

1. Read bytesAllocated racily instead of calling MetaAllocator::currentStatistics. Then ExecutableCounter does not need to take a lock.
2. page lifetime management APIs of MetaAllocator should take a second `count` parameter to batch the system calls.

* jit/ExecutableAllocator.cpp:
(JSC::ExecutableAllocator::underMemoryPressure):
(JSC::ExecutableAllocator::memoryPressureMultiplier):
(JSC::ExecutableAllocator::allocate):
(JSC::FixedVMPoolExecutableAllocator::FixedVMPoolExecutableAllocator): Deleted.
(JSC::FixedVMPoolExecutableAllocator::memoryStart): Deleted.
(JSC::FixedVMPoolExecutableAllocator::memoryEnd): Deleted.
(JSC::FixedVMPoolExecutableAllocator::isJITPC): Deleted.
(JSC::FixedVMPoolExecutableAllocator::initializeSeparatedWXHeaps): Deleted.
(JSC::FixedVMPoolExecutableAllocator::jitWriteThunkGenerator): Deleted.
(JSC::FixedVMPoolExecutableAllocator::genericWriteToJITRegion): Deleted.

Source/WTF:

* wtf/MetaAllocator.cpp:
(WTF::MetaAllocator::incrementPageOccupancy):
(WTF::MetaAllocator::decrementPageOccupancy):
* wtf/MetaAllocator.h:

Tools:

Update the interface.

* TestWebKitAPI/Tests/WTF/MetaAllocator.cpp:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCorejitExecutableAllocatorcpp">trunk/Source/JavaScriptCore/jit/ExecutableAllocator.cpp</a></li>
<li><a href="#trunkSourceWTFChangeLog">trunk/Source/WTF/ChangeLog</a></li>
<li><a href="#trunkSourceWTFwtfMetaAllocatorcpp">trunk/Source/WTF/wtf/MetaAllocator.cpp</a></li>
<li><a href="#trunkSourceWTFwtfMetaAllocatorh">trunk/Source/WTF/wtf/MetaAllocator.h</a></li>
<li><a href="#trunkToolsChangeLog">trunk/Tools/ChangeLog</a></li>
<li><a href="#trunkToolsTestWebKitAPITestsWTFMetaAllocatorcpp">trunk/Tools/TestWebKitAPI/Tests/WTF/MetaAllocator.cpp</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (248686 => 248687)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog    2019-08-14 20:15:04 UTC (rev 248686)
+++ trunk/Source/JavaScriptCore/ChangeLog       2019-08-14 20:33:14 UTC (rev 248687)
</span><span class="lines">@@ -1,5 +1,36 @@
</span><span class="cx"> 2019-08-14  Yusuke Suzuki  <ysuzuki@apple.com>
</span><span class="cx"> 
</span><ins>+        [JSC] Less contended MetaAllocator
+        https://bugs.webkit.org/show_bug.cgi?id=200278
+
+        Reviewed by Mark Lam.
+
+        The profiler result of JetStream2/bomb-workers shows that we are having contention under MetaAllocator::currentStatistics.
+        This function is called in ExecutableAllocator::memoryPressureMultiplier, and it is called from ExecutableCounter's threshold
+        calculation. But MetaAllocator::currentStatistics takes a global lock inside MetaAllocator and causes contention. However,
+        we do not need to have a lock actually: clients of MetaAllocator::currentStatistics typically use bytesReserved and bytesAllocated
+        information. However, since our executable allocator is fixed-sized, bytesReserved is always the fixed size. So just reading bytesAllocated
+        racily is enough.
+
+        This patch attempts to reduce the contention by the following two things.
+
+        1. Read bytesAllocated racily instead of calling MetaAllocator::currentStatistics. Then ExecutableCounter does not need to take a lock.
+        2. page lifetime management APIs of MetaAllocator should take a second `count` parameter to batch the system calls.
+
+        * jit/ExecutableAllocator.cpp:
+        (JSC::ExecutableAllocator::underMemoryPressure):
+        (JSC::ExecutableAllocator::memoryPressureMultiplier):
+        (JSC::ExecutableAllocator::allocate):
+        (JSC::FixedVMPoolExecutableAllocator::FixedVMPoolExecutableAllocator): Deleted.
+        (JSC::FixedVMPoolExecutableAllocator::memoryStart): Deleted.
+        (JSC::FixedVMPoolExecutableAllocator::memoryEnd): Deleted.
+        (JSC::FixedVMPoolExecutableAllocator::isJITPC): Deleted.
+        (JSC::FixedVMPoolExecutableAllocator::initializeSeparatedWXHeaps): Deleted.
+        (JSC::FixedVMPoolExecutableAllocator::jitWriteThunkGenerator): Deleted.
+        (JSC::FixedVMPoolExecutableAllocator::genericWriteToJITRegion): Deleted.
+
+2019-08-14  Yusuke Suzuki  <ysuzuki@apple.com>
+
</ins><span class="cx">         [JSC] Make PAC jump and return more explicit
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=200703
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitExecutableAllocatorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/ExecutableAllocator.cpp (248686 => 248687)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/ExecutableAllocator.cpp  2019-08-14 20:15:04 UTC (rev 248686)
+++ trunk/Source/JavaScriptCore/jit/ExecutableAllocator.cpp     2019-08-14 20:33:14 UTC (rev 248687)
</span><span class="lines">@@ -154,7 +154,7 @@
</span><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-class FixedVMPoolExecutableAllocator : public MetaAllocator {
</del><ins>+class FixedVMPoolExecutableAllocator final : public MetaAllocator {
</ins><span class="cx">     WTF_MAKE_FAST_ALLOCATED;
</span><span class="cx"> public:
</span><span class="cx">     FixedVMPoolExecutableAllocator()
</span><span class="lines">@@ -208,6 +208,8 @@
</span><span class="cx"> 
</span><span class="cx">             addFreshFreeSpace(reservationBase, reservationSize);
</span><span class="cx"> 
</span><ins>+            ASSERT(bytesReserved() == reservationSize); // Since our executable memory is fixed-sized, bytesReserved is never changed after initialization.
+
</ins><span class="cx">             void* reservationEnd = reinterpret_cast<uint8_t*>(reservationBase) + reservationSize;
</span><span class="cx"> 
</span><span class="cx">             m_memoryStart = MacroAssemblerCodePtr<ExecutableMemoryPtrTag>(tagCodePtr<ExecutableMemoryPtrTag>(reservationBase));
</span><span class="lines">@@ -228,20 +230,21 @@
</span><span class="cx">         return nullptr;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    void notifyNeedPage(void* page) override
</del><ins>+    void notifyNeedPage(void* page, size_t count) override
</ins><span class="cx">     {
</span><span class="cx"> #if USE(MADV_FREE_FOR_JIT_MEMORY)
</span><span class="cx">         UNUSED_PARAM(page);
</span><ins>+        UNUSED_PARAM(count);
</ins><span class="cx"> #else
</span><del>-        m_reservation.commit(page, pageSize());
</del><ins>+        m_reservation.commit(page, pageSize() * count);
</ins><span class="cx"> #endif
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    void notifyPageIsFree(void* page) override
</del><ins>+    void notifyPageIsFree(void* page, size_t count) override
</ins><span class="cx">     {
</span><span class="cx"> #if USE(MADV_FREE_FOR_JIT_MEMORY)
</span><span class="cx">         for (;;) {
</span><del>-            int result = madvise(page, pageSize(), MADV_FREE);
</del><ins>+            int result = madvise(page, pageSize() * count, MADV_FREE);
</ins><span class="cx">             if (!result)
</span><span class="cx">                 return;
</span><span class="cx">             ASSERT(result == -1);
</span><span class="lines">@@ -251,7 +254,7 @@
</span><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx"> #else
</span><del>-        m_reservation.decommit(page, pageSize());
</del><ins>+        m_reservation.decommit(page, pageSize() * count);
</ins><span class="cx"> #endif
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -431,8 +434,7 @@
</span><span class="cx"> {
</span><span class="cx">     if (!allocator)
</span><span class="cx">         return Base::underMemoryPressure();
</span><del>-    MetaAllocator::Statistics statistics = allocator->currentStatistics();
-    return statistics.bytesAllocated > statistics.bytesReserved / 2;
</del><ins>+    return allocator->bytesAllocated() > allocator->bytesReserved() / 2;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> double ExecutableAllocator::memoryPressureMultiplier(size_t addedMemoryUsage)
</span><span class="lines">@@ -439,11 +441,10 @@
</span><span class="cx"> {
</span><span class="cx">     if (!allocator)
</span><span class="cx">         return Base::memoryPressureMultiplier(addedMemoryUsage);
</span><del>-    MetaAllocator::Statistics statistics = allocator->currentStatistics();
-    ASSERT(statistics.bytesAllocated <= statistics.bytesReserved);
-    size_t bytesAllocated = statistics.bytesAllocated + addedMemoryUsage;
</del><ins>+    ASSERT(allocator->bytesAllocated() <= allocator->bytesReserved());
+    size_t bytesAllocated = allocator->bytesAllocated() + addedMemoryUsage;
</ins><span class="cx">     size_t bytesAvailable = static_cast<size_t>(
</span><del>-        statistics.bytesReserved * (1 - executablePoolReservationFraction));
</del><ins>+        allocator->bytesReserved() * (1 - executablePoolReservationFraction));
</ins><span class="cx">     if (bytesAllocated >= bytesAvailable)
</span><span class="cx">         bytesAllocated = bytesAvailable;
</span><span class="cx">     double result = 1.0;
</span><span class="lines">@@ -475,10 +476,9 @@
</span><span class="cx"> 
</span><span class="cx">     if (effort == JITCompilationCanFail) {
</span><span class="cx">         // Don't allow allocations if we are down to reserve.
</span><del>-        MetaAllocator::Statistics statistics = allocator->currentStatistics();
-        size_t bytesAllocated = statistics.bytesAllocated + sizeInBytes;
</del><ins>+        size_t bytesAllocated = allocator->bytesAllocated() + sizeInBytes;
</ins><span class="cx">         size_t bytesAvailable = static_cast<size_t>(
</span><del>-            statistics.bytesReserved * (1 - executablePoolReservationFraction));
</del><ins>+            allocator->bytesReserved() * (1 - executablePoolReservationFraction));
</ins><span class="cx">         if (bytesAllocated > bytesAvailable) {
</span><span class="cx">             if (Options::logExecutableAllocation())
</span><span class="cx">                 dataLog("Allocation failed because bytes allocated ", bytesAllocated,  " > ", bytesAvailable, " bytes available.\n");
</span></span></pre></div>
<a id="trunkSourceWTFChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/ChangeLog (248686 => 248687)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/ChangeLog       2019-08-14 20:15:04 UTC (rev 248686)
+++ trunk/Source/WTF/ChangeLog  2019-08-14 20:33:14 UTC (rev 248687)
</span><span class="lines">@@ -1,3 +1,15 @@
</span><ins>+2019-08-14  Yusuke Suzuki  <ysuzuki@apple.com>
+
+        [JSC] Less contended MetaAllocator
+        https://bugs.webkit.org/show_bug.cgi?id=200278
+
+        Reviewed by Mark Lam.
+
+        * wtf/MetaAllocator.cpp:
+        (WTF::MetaAllocator::incrementPageOccupancy):
+        (WTF::MetaAllocator::decrementPageOccupancy):
+        * wtf/MetaAllocator.h:
+
</ins><span class="cx"> 2019-08-14  Samuel GroƟ  <saelo@google.com>
</span><span class="cx"> 
</span><span class="cx">         [JSCOnly] JSCOnly port doesn't build on macOS
</span></span></pre></div>
<a id="trunkSourceWTFwtfMetaAllocatorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/MetaAllocator.cpp (248686 => 248687)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/MetaAllocator.cpp   2019-08-14 20:15:04 UTC (rev 248686)
+++ trunk/Source/WTF/wtf/MetaAllocator.cpp      2019-08-14 20:33:14 UTC (rev 248687)
</span><span class="lines">@@ -397,16 +397,30 @@
</span><span class="cx"> {
</span><span class="cx">     uintptr_t firstPage = reinterpret_cast<uintptr_t>(address) >> m_logPageSize;
</span><span class="cx">     uintptr_t lastPage = (reinterpret_cast<uintptr_t>(address) + sizeInBytes - 1) >> m_logPageSize;
</span><ins>+
+    uintptr_t currentPageStart = 0;
+    size_t count = 0;
+    auto flushNeedPages = [&] {
+        if (!currentPageStart)
+            return;
+        notifyNeedPage(reinterpret_cast<void*>(currentPageStart << m_logPageSize), count);
+        currentPageStart = 0;
+        count = 0;
+    };
</ins><span class="cx">     
</span><span class="cx">     for (uintptr_t page = firstPage; page <= lastPage; ++page) {
</span><del>-        HashMap<uintptr_t, size_t>::iterator iter = m_pageOccupancyMap.find(page);
-        if (iter == m_pageOccupancyMap.end()) {
-            m_pageOccupancyMap.add(page, 1);
</del><ins>+        auto result = m_pageOccupancyMap.add(page, 1);
+        if (result.isNewEntry) {
</ins><span class="cx">             m_bytesCommitted += m_pageSize;
</span><del>-            notifyNeedPage(reinterpret_cast<void*>(page << m_logPageSize));
-        } else
-            iter->value++;
</del><ins>+            if (!currentPageStart)
+                currentPageStart = page;
+            ++count;
+        } else {
+            result.iterator->value++;
+            flushNeedPages();
+        }
</ins><span class="cx">     }
</span><ins>+    flushNeedPages();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void MetaAllocator::decrementPageOccupancy(void* address, size_t sizeInBytes)
</span><span class="lines">@@ -413,6 +427,16 @@
</span><span class="cx"> {
</span><span class="cx">     uintptr_t firstPage = reinterpret_cast<uintptr_t>(address) >> m_logPageSize;
</span><span class="cx">     uintptr_t lastPage = (reinterpret_cast<uintptr_t>(address) + sizeInBytes - 1) >> m_logPageSize;
</span><ins>+
+    uintptr_t currentPageStart = 0;
+    size_t count = 0;
+    auto flushFreePages = [&] {
+        if (!currentPageStart)
+            return;
+        notifyPageIsFree(reinterpret_cast<void*>(currentPageStart << m_logPageSize), count);
+        currentPageStart = 0;
+        count = 0;
+    };
</ins><span class="cx">     
</span><span class="cx">     for (uintptr_t page = firstPage; page <= lastPage; ++page) {
</span><span class="cx">         HashMap<uintptr_t, size_t>::iterator iter = m_pageOccupancyMap.find(page);
</span><span class="lines">@@ -420,9 +444,13 @@
</span><span class="cx">         if (!--(iter->value)) {
</span><span class="cx">             m_pageOccupancyMap.remove(iter);
</span><span class="cx">             m_bytesCommitted -= m_pageSize;
</span><del>-            notifyPageIsFree(reinterpret_cast<void*>(page << m_logPageSize));
-        }
</del><ins>+            if (!currentPageStart)
+                currentPageStart = page;
+            ++count;
+        } else
+            flushFreePages();
</ins><span class="cx">     }
</span><ins>+    flushFreePages();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool MetaAllocator::isInAllocatedMemory(const AbstractLocker&, void* address)
</span></span></pre></div>
<a id="trunkSourceWTFwtfMetaAllocatorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/MetaAllocator.h (248686 => 248687)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/MetaAllocator.h     2019-08-14 20:15:04 UTC (rev 248686)
+++ trunk/Source/WTF/wtf/MetaAllocator.h        2019-08-14 20:33:14 UTC (rev 248687)
</span><span class="lines">@@ -114,10 +114,10 @@
</span><span class="cx">     virtual FreeSpacePtr allocateNewSpace(size_t& numPages) = 0;
</span><span class="cx"> 
</span><span class="cx">     // Commit a page.
</span><del>-    virtual void notifyNeedPage(void* page) = 0;
</del><ins>+    virtual void notifyNeedPage(void* page, size_t) = 0;
</ins><span class="cx">     
</span><span class="cx">     // Uncommit a page.
</span><del>-    virtual void notifyPageIsFree(void* page) = 0;
</del><ins>+    virtual void notifyPageIsFree(void* page, size_t) = 0;
</ins><span class="cx">     
</span><span class="cx">     // NOTE: none of the above methods are called during allocator
</span><span class="cx">     // destruction, in part because a MetaAllocator cannot die so long
</span></span></pre></div>
<a id="trunkToolsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Tools/ChangeLog (248686 => 248687)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/ChangeLog    2019-08-14 20:15:04 UTC (rev 248686)
+++ trunk/Tools/ChangeLog       2019-08-14 20:33:14 UTC (rev 248687)
</span><span class="lines">@@ -1,3 +1,14 @@
</span><ins>+2019-08-14  Yusuke Suzuki  <ysuzuki@apple.com>
+
+        [JSC] Less contended MetaAllocator
+        https://bugs.webkit.org/show_bug.cgi?id=200278
+
+        Reviewed by Mark Lam.
+
+        Update the interface.
+
+        * TestWebKitAPI/Tests/WTF/MetaAllocator.cpp:
+
</ins><span class="cx"> 2019-08-14  Jonathan Bedard  <jbedard@apple.com>
</span><span class="cx"> 
</span><span class="cx">         results.webkit.org: 500 errors on API endpoints don't return JSON
</span></span></pre></div>
<a id="trunkToolsTestWebKitAPITestsWTFMetaAllocatorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Tools/TestWebKitAPI/Tests/WTF/MetaAllocator.cpp (248686 => 248687)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestWebKitAPI/Tests/WTF/MetaAllocator.cpp    2019-08-14 20:15:04 UTC (rev 248686)
+++ trunk/Tools/TestWebKitAPI/Tests/WTF/MetaAllocator.cpp       2019-08-14 20:33:14 UTC (rev 248687)
</span><span class="lines">@@ -105,23 +105,27 @@
</span><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx">         
</span><del>-        virtual void notifyNeedPage(void* page)
</del><ins>+        virtual void notifyNeedPage(void* page, size_t count)
</ins><span class="cx">         {
</span><span class="cx">             // the page should be both free and unmapped.
</span><del>-            EXPECT_TRUE(!m_parent->pageState(reinterpret_cast<uintptr_t>(page) / pageSize()));
-            for (uintptr_t address = reinterpret_cast<uintptr_t>(page); address < reinterpret_cast<uintptr_t>(page) + pageSize(); ++address)
</del><ins>+            for (size_t i = 0; i < count; ++i)
+                EXPECT_TRUE(!m_parent->pageState(reinterpret_cast<uintptr_t>(page) / pageSize() + i));
+            for (uintptr_t address = reinterpret_cast<uintptr_t>(page); address < reinterpret_cast<uintptr_t>(page) + pageSize() * count; ++address)
</ins><span class="cx">                 EXPECT_TRUE(!m_parent->byteState(reinterpret_cast<void*>(address)));
</span><del>-            m_parent->pageState(reinterpret_cast<uintptr_t>(page) / pageSize()) = true;
</del><ins>+            for (size_t i = 0; i < count; ++i)
+                m_parent->pageState(reinterpret_cast<uintptr_t>(page) / pageSize() + i) = true;
</ins><span class="cx">         }
</span><span class="cx">         
</span><del>-        virtual void notifyPageIsFree(void* page)
</del><ins>+        virtual void notifyPageIsFree(void* page, size_t count)
</ins><span class="cx">         {
</span><span class="cx">             // the page should be free of objects at this point, but it should still
</span><span class="cx">             // be mapped.
</span><del>-            EXPECT_TRUE(m_parent->pageState(reinterpret_cast<uintptr_t>(page) / pageSize()));
-            for (uintptr_t address = reinterpret_cast<uintptr_t>(page); address < reinterpret_cast<uintptr_t>(page) + pageSize(); ++address)
</del><ins>+            for (size_t i = 0; i < count; ++i)
+                EXPECT_TRUE(m_parent->pageState(reinterpret_cast<uintptr_t>(page) / pageSize() + i));
+            for (uintptr_t address = reinterpret_cast<uintptr_t>(page); address < reinterpret_cast<uintptr_t>(page) + pageSize() * count; ++address)
</ins><span class="cx">                 EXPECT_TRUE(!m_parent->byteState(reinterpret_cast<void*>(address)));
</span><del>-            m_parent->pageState(reinterpret_cast<uintptr_t>(page) / pageSize()) = false;
</del><ins>+            for (size_t i = 0; i < count; ++i)
+                m_parent->pageState(reinterpret_cast<uintptr_t>(page) / pageSize() + i) = false;
</ins><span class="cx">         }
</span><span class="cx">         
</span><span class="cx">     private:
</span></span></pre>
</div>
</div>

</body>
</html>