<!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>[170316] trunk/Source/WebKit2</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/170316">170316</a></dd>
<dt>Author</dt> <dd>timothy_horton@apple.com</dd>
<dt>Date</dt> <dd>2014-06-23 14:12:00 -0700 (Mon, 23 Jun 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>[iOS][wk2] Ensure that layers are marked volatile before allowing the process to suspend
https://bugs.webkit.org/show_bug.cgi?id=134004
&lt;rdar://problem/17186342&gt;

Reviewed by Simon Fraser.

WebKit tries to make layers volatile when unparented, but sometimes isn't given
a chance to do so before the process gets suspended, so we end up with lots of
non-volatile surfaces that should really be volatile.

* Shared/mac/RemoteLayerBackingStoreCollection.h:
* Shared/mac/RemoteLayerBackingStoreCollection.mm:
(WebKit::RemoteLayerBackingStoreCollection::markBackingStoreVolatileImmediately):
(WebKit::RemoteLayerBackingStoreCollection::markAllBackingStoreVolatileImmediatelyIfPossible):
Add markAllBackingStoreVolatileImmediatelyIfPossible, which tries to mark *all*
buffers of *all* backing store, (live and unreachable), (front, back, and secondary),
volatile right away. It returns false if any buffer isn't marked volatile (because it was in-use).

* UIProcess/ios/ProcessThrottler.h:
* UIProcess/ios/ProcessThrottler.mm:
(WebKit::ProcessThrottler::updateAssertion):
(WebKit::ProcessThrottler::processReadyToSuspend):
(WebKit::ProcessThrottler::didCancelProcessSuspension):
* UIProcess/ios/WebProcessProxyIOS.mm:
(WebKit::WebProcessProxy::sendCancelProcessWillSuspend):
(WebKit::WebProcessProxy::didCancelProcessSuspension):
* UIProcess/WebProcessProxy.h:
* UIProcess/WebProcessProxy.messages.in:
* WebProcess/WebProcess.h:
* WebProcess/WebProcess.messages.in:
If the UI process is waiting for the Web process to confirm that it can suspend
and something happens (the view is reparented) that cancels the suspension, inform
the Web process that this happened, so that it can cancel any cleanup that might still be taking place.

* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::viewStateDidChange):
If a view goes in-window, dispatch the view state change immediately without delay,
to minimize the latency between coming in-window and being ready to go.

* WebProcess/WebPage/DrawingArea.h:
(WebKit::DrawingArea::markLayersVolatileImmediatelyIfPossible):
* WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.h:
* WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.mm:
(WebKit::RemoteLayerTreeDrawingArea::setRootCompositingLayer):
Schedule a flush when we change the root layer; otherwise, we can end up
detaching the root layer but changing nothing else, and never committing that change.

(WebKit::RemoteLayerTreeDrawingArea::markLayersVolatileImmediatelyIfPossible):

* WebProcess/WebProcess.cpp:
(WebKit::WebProcess::WebProcess):
(WebKit::WebProcess::processWillSuspend):
(WebKit::WebProcess::cancelProcessWillSuspend):
(WebKit::WebProcess::markAllLayersVolatileIfPossible):
(WebKit::WebProcess::processSuspensionCleanupTimerFired):
When the UI process is going to suspend the process, it sends us ProcessWillSuspend,
and defers the suspension until we send a ProcessReadyToSuspend back.
Delay ProcessReadyToSuspend until all layers in our process have been marked volatile.
We'll keep trying every 20ms until they're all volatile. For safety, the UI process will eventually
stop waiting for us, but the volatility change is usually applied successfully within the first
or second timer callback.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2SharedmacRemoteLayerBackingStoreCollectionh">trunk/Source/WebKit2/Shared/mac/RemoteLayerBackingStoreCollection.h</a></li>
<li><a href="#trunkSourceWebKit2SharedmacRemoteLayerBackingStoreCollectionmm">trunk/Source/WebKit2/Shared/mac/RemoteLayerBackingStoreCollection.mm</a></li>
<li><a href="#trunkSourceWebKit2UIProcessWebPageProxycpp">trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp</a></li>
<li><a href="#trunkSourceWebKit2UIProcessWebProcessProxyh">trunk/Source/WebKit2/UIProcess/WebProcessProxy.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessWebProcessProxymessagesin">trunk/Source/WebKit2/UIProcess/WebProcessProxy.messages.in</a></li>
<li><a href="#trunkSourceWebKit2UIProcessiosProcessThrottlerh">trunk/Source/WebKit2/UIProcess/ios/ProcessThrottler.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessiosProcessThrottlermm">trunk/Source/WebKit2/UIProcess/ios/ProcessThrottler.mm</a></li>
<li><a href="#trunkSourceWebKit2UIProcessiosWebProcessProxyIOSmm">trunk/Source/WebKit2/UIProcess/ios/WebProcessProxyIOS.mm</a></li>
<li><a href="#trunkSourceWebKit2WebProcessWebPageDrawingAreah">trunk/Source/WebKit2/WebProcess/WebPage/DrawingArea.h</a></li>
<li><a href="#trunkSourceWebKit2WebProcessWebPagemacRemoteLayerTreeDrawingAreah">trunk/Source/WebKit2/WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.h</a></li>
<li><a href="#trunkSourceWebKit2WebProcessWebPagemacRemoteLayerTreeDrawingAreamm">trunk/Source/WebKit2/WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.mm</a></li>
<li><a href="#trunkSourceWebKit2WebProcessWebProcesscpp">trunk/Source/WebKit2/WebProcess/WebProcess.cpp</a></li>
<li><a href="#trunkSourceWebKit2WebProcessWebProcessh">trunk/Source/WebKit2/WebProcess/WebProcess.h</a></li>
<li><a href="#trunkSourceWebKit2WebProcessWebProcessmessagesin">trunk/Source/WebKit2/WebProcess/WebProcess.messages.in</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (170315 => 170316)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2014-06-23 21:01:19 UTC (rev 170315)
+++ trunk/Source/WebKit2/ChangeLog        2014-06-23 21:12:00 UTC (rev 170316)
</span><span class="lines">@@ -1,3 +1,67 @@
</span><ins>+2014-06-23  Timothy Horton  &lt;timothy_horton@apple.com&gt;
+
+        [iOS][wk2] Ensure that layers are marked volatile before allowing the process to suspend
+        https://bugs.webkit.org/show_bug.cgi?id=134004
+        &lt;rdar://problem/17186342&gt;
+
+        Reviewed by Simon Fraser.
+
+        WebKit tries to make layers volatile when unparented, but sometimes isn't given
+        a chance to do so before the process gets suspended, so we end up with lots of
+        non-volatile surfaces that should really be volatile.
+
+        * Shared/mac/RemoteLayerBackingStoreCollection.h:
+        * Shared/mac/RemoteLayerBackingStoreCollection.mm:
+        (WebKit::RemoteLayerBackingStoreCollection::markBackingStoreVolatileImmediately):
+        (WebKit::RemoteLayerBackingStoreCollection::markAllBackingStoreVolatileImmediatelyIfPossible):
+        Add markAllBackingStoreVolatileImmediatelyIfPossible, which tries to mark *all*
+        buffers of *all* backing store, (live and unreachable), (front, back, and secondary),
+        volatile right away. It returns false if any buffer isn't marked volatile (because it was in-use).
+
+        * UIProcess/ios/ProcessThrottler.h:
+        * UIProcess/ios/ProcessThrottler.mm:
+        (WebKit::ProcessThrottler::updateAssertion):
+        (WebKit::ProcessThrottler::processReadyToSuspend):
+        (WebKit::ProcessThrottler::didCancelProcessSuspension):
+        * UIProcess/ios/WebProcessProxyIOS.mm:
+        (WebKit::WebProcessProxy::sendCancelProcessWillSuspend):
+        (WebKit::WebProcessProxy::didCancelProcessSuspension):
+        * UIProcess/WebProcessProxy.h:
+        * UIProcess/WebProcessProxy.messages.in:
+        * WebProcess/WebProcess.h:
+        * WebProcess/WebProcess.messages.in:
+        If the UI process is waiting for the Web process to confirm that it can suspend
+        and something happens (the view is reparented) that cancels the suspension, inform
+        the Web process that this happened, so that it can cancel any cleanup that might still be taking place.
+
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::viewStateDidChange):
+        If a view goes in-window, dispatch the view state change immediately without delay,
+        to minimize the latency between coming in-window and being ready to go.
+
+        * WebProcess/WebPage/DrawingArea.h:
+        (WebKit::DrawingArea::markLayersVolatileImmediatelyIfPossible):
+        * WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.h:
+        * WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.mm:
+        (WebKit::RemoteLayerTreeDrawingArea::setRootCompositingLayer):
+        Schedule a flush when we change the root layer; otherwise, we can end up
+        detaching the root layer but changing nothing else, and never committing that change.
+
+        (WebKit::RemoteLayerTreeDrawingArea::markLayersVolatileImmediatelyIfPossible):
+
+        * WebProcess/WebProcess.cpp:
+        (WebKit::WebProcess::WebProcess):
+        (WebKit::WebProcess::processWillSuspend):
+        (WebKit::WebProcess::cancelProcessWillSuspend):
+        (WebKit::WebProcess::markAllLayersVolatileIfPossible):
+        (WebKit::WebProcess::processSuspensionCleanupTimerFired):
+        When the UI process is going to suspend the process, it sends us ProcessWillSuspend,
+        and defers the suspension until we send a ProcessReadyToSuspend back.
+        Delay ProcessReadyToSuspend until all layers in our process have been marked volatile.
+        We'll keep trying every 20ms until they're all volatile. For safety, the UI process will eventually
+        stop waiting for us, but the volatility change is usually applied successfully within the first
+        or second timer callback.
+
</ins><span class="cx"> 2014-06-23  Oliver Hunt  &lt;oliver@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Ensure that we always use symlink free paths when specifying cache directories
</span></span></pre></div>
<a id="trunkSourceWebKit2SharedmacRemoteLayerBackingStoreCollectionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/Shared/mac/RemoteLayerBackingStoreCollection.h (170315 => 170316)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/Shared/mac/RemoteLayerBackingStoreCollection.h        2014-06-23 21:01:19 UTC (rev 170315)
+++ trunk/Source/WebKit2/Shared/mac/RemoteLayerBackingStoreCollection.h        2014-06-23 21:12:00 UTC (rev 170316)
</span><span class="lines">@@ -53,11 +53,16 @@
</span><span class="cx">     void didFlushLayers();
</span><span class="cx"> 
</span><span class="cx">     void volatilityTimerFired(WebCore::Timer&lt;RemoteLayerBackingStoreCollection&gt;&amp;);
</span><ins>+    bool markAllBackingStoreVolatileImmediatelyIfPossible();
</ins><span class="cx"> 
</span><span class="cx">     void scheduleVolatilityTimer();
</span><span class="cx"> 
</span><span class="cx"> private:
</span><del>-    bool markBackingStoreVolatileImmediately(RemoteLayerBackingStore&amp;);
</del><ins>+    enum VolatilityMarkingFlag {
+        MarkBuffersIgnoringReachability = 1 &lt;&lt; 0
+    };
+    typedef unsigned VolatilityMarkingFlags;
+    bool markBackingStoreVolatileImmediately(RemoteLayerBackingStore&amp;, VolatilityMarkingFlags volatilityMarkingFlags = 0);
</ins><span class="cx">     bool markBackingStoreVolatile(RemoteLayerBackingStore&amp;, std::chrono::steady_clock::time_point now);
</span><span class="cx"> 
</span><span class="cx">     HashSet&lt;RemoteLayerBackingStore*&gt; m_liveBackingStore;
</span></span></pre></div>
<a id="trunkSourceWebKit2SharedmacRemoteLayerBackingStoreCollectionmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/Shared/mac/RemoteLayerBackingStoreCollection.mm (170315 => 170316)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/Shared/mac/RemoteLayerBackingStoreCollection.mm        2014-06-23 21:01:19 UTC (rev 170315)
+++ trunk/Source/WebKit2/Shared/mac/RemoteLayerBackingStoreCollection.mm        2014-06-23 21:12:00 UTC (rev 170316)
</span><span class="lines">@@ -100,7 +100,7 @@
</span><span class="cx">     m_unparentedBackingStore.remove(backingStoreIter);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool RemoteLayerBackingStoreCollection::markBackingStoreVolatileImmediately(RemoteLayerBackingStore&amp; backingStore)
</del><ins>+bool RemoteLayerBackingStoreCollection::markBackingStoreVolatileImmediately(RemoteLayerBackingStore&amp; backingStore, VolatilityMarkingFlags volatilityMarkingFlags)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(!m_inLayerFlush);
</span><span class="cx">     bool successfullyMadeBackingStoreVolatile = true;
</span><span class="lines">@@ -111,7 +111,7 @@
</span><span class="cx">     if (!backingStore.setBufferVolatility(RemoteLayerBackingStore::BufferType::Back, true))
</span><span class="cx">         successfullyMadeBackingStoreVolatile = false;
</span><span class="cx"> 
</span><del>-    if (!m_reachableBackingStoreInLatestFlush.contains(&amp;backingStore)) {
</del><ins>+    if (!m_reachableBackingStoreInLatestFlush.contains(&amp;backingStore) || (volatilityMarkingFlags &amp; MarkBuffersIgnoringReachability)) {
</ins><span class="cx">         if (!backingStore.setBufferVolatility(RemoteLayerBackingStore::BufferType::Front, true))
</span><span class="cx">             successfullyMadeBackingStoreVolatile = false;
</span><span class="cx">     }
</span><span class="lines">@@ -150,6 +150,19 @@
</span><span class="cx">     markBackingStoreVolatileImmediately(backingStore);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool RemoteLayerBackingStoreCollection::markAllBackingStoreVolatileImmediatelyIfPossible()
+{
+    bool successfullyMadeBackingStoreVolatile = true;
+
+    for (const auto&amp; backingStore : m_liveBackingStore)
+        successfullyMadeBackingStoreVolatile &amp;= markBackingStoreVolatileImmediately(*backingStore, MarkBuffersIgnoringReachability);
+
+    for (const auto&amp; backingStore : m_unparentedBackingStore)
+        successfullyMadeBackingStoreVolatile &amp;= markBackingStoreVolatileImmediately(*backingStore, MarkBuffersIgnoringReachability);
+
+    return successfullyMadeBackingStoreVolatile;
+}
+
</ins><span class="cx"> void RemoteLayerBackingStoreCollection::volatilityTimerFired(WebCore::Timer&lt;RemoteLayerBackingStoreCollection&gt;&amp;)
</span><span class="cx"> {
</span><span class="cx">     bool successfullyMadeBackingStoreVolatile = true;
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessWebPageProxycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp (170315 => 170316)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp        2014-06-23 21:01:19 UTC (rev 170315)
+++ trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp        2014-06-23 21:12:00 UTC (rev 170316)
</span><span class="lines">@@ -1106,6 +1106,11 @@
</span><span class="cx">     m_viewStateChangeWantsReply = (wantsReply == WantsReplyOrNot::DoesWantReply || m_viewStateChangeWantsReply == WantsReplyOrNot::DoesWantReply) ? WantsReplyOrNot::DoesWantReply : WantsReplyOrNot::DoesNotWantReply;
</span><span class="cx"> 
</span><span class="cx"> #if PLATFORM(COCOA)
</span><ins>+    bool isNewlyInWindow = !(m_viewState &amp; ViewState::IsInWindow) &amp;&amp; (mayHaveChanged &amp; ViewState::IsInWindow) &amp;&amp; m_pageClient.isViewInWindow();
+    if (isNewlyInWindow) {
+        dispatchViewStateChange();
+        return;
+    }
</ins><span class="cx">     m_viewStateChangeDispatcher-&gt;schedule();
</span><span class="cx"> #else
</span><span class="cx">     dispatchViewStateChange();
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessWebProcessProxyh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/WebProcessProxy.h (170315 => 170316)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/WebProcessProxy.h        2014-06-23 21:01:19 UTC (rev 170315)
+++ trunk/Source/WebKit2/UIProcess/WebProcessProxy.h        2014-06-23 21:12:00 UTC (rev 170316)
</span><span class="lines">@@ -138,6 +138,8 @@
</span><span class="cx"> #if PLATFORM(IOS)
</span><span class="cx">     void sendProcessWillSuspend();
</span><span class="cx">     void processReadyToSuspend();
</span><ins>+    void sendCancelProcessWillSuspend();
+    void didCancelProcessSuspension();
</ins><span class="cx">     
</span><span class="cx">     ProcessThrottler&amp; throttler() { return *m_throttler; }
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessWebProcessProxymessagesin"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/WebProcessProxy.messages.in (170315 => 170316)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/WebProcessProxy.messages.in        2014-06-23 21:01:19 UTC (rev 170315)
+++ trunk/Source/WebKit2/UIProcess/WebProcessProxy.messages.in        2014-06-23 21:12:00 UTC (rev 170316)
</span><span class="lines">@@ -49,5 +49,6 @@
</span><span class="cx"> #endif
</span><span class="cx"> #if PLATFORM(IOS)
</span><span class="cx">     ProcessReadyToSuspend()
</span><ins>+    DidCancelProcessSuspension()
</ins><span class="cx"> #endif
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessiosProcessThrottlerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/ios/ProcessThrottler.h (170315 => 170316)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/ios/ProcessThrottler.h        2014-06-23 21:01:19 UTC (rev 170315)
+++ trunk/Source/WebKit2/UIProcess/ios/ProcessThrottler.h        2014-06-23 21:12:00 UTC (rev 170316)
</span><span class="lines">@@ -61,6 +61,7 @@
</span><span class="cx">     
</span><span class="cx">     void didConnnectToProcess(pid_t);
</span><span class="cx">     void processReadyToSuspend();
</span><ins>+    void didCancelProcessSuspension();
</ins><span class="cx">     
</span><span class="cx"> private:
</span><span class="cx">     friend class ForegroundActivityToken;
</span><span class="lines">@@ -78,7 +79,7 @@
</span><span class="cx">     WebCore::Timer&lt;ProcessThrottler&gt; m_suspendTimer;
</span><span class="cx">     unsigned m_foregroundCount;
</span><span class="cx">     unsigned m_backgroundCount;
</span><del>-    unsigned m_suspendMessageCount;
</del><ins>+    int m_suspendMessageCount;
</ins><span class="cx"> };
</span><span class="cx">     
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessiosProcessThrottlermm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/ios/ProcessThrottler.mm (170315 => 170316)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/ios/ProcessThrottler.mm        2014-06-23 21:01:19 UTC (rev 170315)
+++ trunk/Source/WebKit2/UIProcess/ios/ProcessThrottler.mm        2014-06-23 21:12:00 UTC (rev 170316)
</span><span class="lines">@@ -102,8 +102,14 @@
</span><span class="cx">         m_process-&gt;sendProcessWillSuspend();
</span><span class="cx">         m_suspendTimer.startOneShot(processSuspensionTimeout);
</span><span class="cx">         m_assertion-&gt;setState(AssertionState::Background);
</span><del>-    } else
-        updateAssertionNow();
</del><ins>+        return;
+    }
+
+    // If we're currently waiting for the Web process to do suspension cleanup, but no longer need to be suspended, tell the Web process to cancel the cleanup.
+    if (m_suspendTimer.isActive() &amp;&amp; (m_foregroundCount || m_backgroundCount))
+        m_process-&gt;sendCancelProcessWillSuspend();
+
+    updateAssertionNow();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void ProcessThrottler::didConnnectToProcess(pid_t pid)
</span><span class="lines">@@ -121,8 +127,16 @@
</span><span class="cx"> {
</span><span class="cx">     if (!--m_suspendMessageCount)
</span><span class="cx">         updateAssertionNow();
</span><ins>+    ASSERT(m_suspendMessageCount &gt;= 0);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void ProcessThrottler::didCancelProcessSuspension()
+{
+    if (!--m_suspendMessageCount)
+        updateAssertionNow();
+    ASSERT(m_suspendMessageCount &gt;= 0);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+}
+
</ins><span class="cx"> #endif // PLATFORM(IOS)
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessiosWebProcessProxyIOSmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/ios/WebProcessProxyIOS.mm (170315 => 170316)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/ios/WebProcessProxyIOS.mm        2014-06-23 21:01:19 UTC (rev 170315)
+++ trunk/Source/WebKit2/UIProcess/ios/WebProcessProxyIOS.mm        2014-06-23 21:12:00 UTC (rev 170316)
</span><span class="lines">@@ -66,11 +66,22 @@
</span><span class="cx">     if (canSendMessage())
</span><span class="cx">         send(Messages::WebProcess::ProcessWillSuspend(), 0);
</span><span class="cx"> }
</span><ins>+
+void WebProcessProxy::sendCancelProcessWillSuspend()
+{
+    if (canSendMessage())
+        send(Messages::WebProcess::CancelProcessWillSuspend(), 0);
+}
</ins><span class="cx">     
</span><span class="cx"> void WebProcessProxy::processReadyToSuspend()
</span><span class="cx"> {
</span><span class="cx">     m_throttler-&gt;processReadyToSuspend();
</span><span class="cx"> }
</span><ins>+
+void WebProcessProxy::didCancelProcessSuspension()
+{
+    m_throttler-&gt;didCancelProcessSuspension();
+}
</ins><span class="cx">     
</span><span class="cx"> } // namespace WebKit
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessWebPageDrawingAreah"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/WebPage/DrawingArea.h (170315 => 170316)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/WebPage/DrawingArea.h        2014-06-23 21:01:19 UTC (rev 170315)
+++ trunk/Source/WebKit2/WebProcess/WebPage/DrawingArea.h        2014-06-23 21:12:00 UTC (rev 170316)
</span><span class="lines">@@ -117,6 +117,8 @@
</span><span class="cx">     virtual void viewStateDidChange(WebCore::ViewState::Flags) { }
</span><span class="cx">     virtual void setLayerHostingMode(LayerHostingMode) { }
</span><span class="cx"> 
</span><ins>+    virtual bool markLayersVolatileImmediatelyIfPossible() { return true; }
+
</ins><span class="cx"> protected:
</span><span class="cx">     DrawingArea(DrawingAreaType, WebPage&amp;);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessWebPagemacRemoteLayerTreeDrawingAreah"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.h (170315 => 170316)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.h        2014-06-23 21:01:19 UTC (rev 170315)
+++ trunk/Source/WebKit2/WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.h        2014-06-23 21:12:00 UTC (rev 170316)
</span><span class="lines">@@ -109,6 +109,8 @@
</span><span class="cx"> 
</span><span class="cx">     uint64_t takeNextTransactionID() { return ++m_currentTransactionID; }
</span><span class="cx"> 
</span><ins>+    virtual bool markLayersVolatileImmediatelyIfPossible() override;
+
</ins><span class="cx">     class BackingStoreFlusher : public ThreadSafeRefCounted&lt;BackingStoreFlusher&gt; {
</span><span class="cx">     public:
</span><span class="cx">         static PassRefPtr&lt;BackingStoreFlusher&gt; create(IPC::Connection*, std::unique_ptr&lt;IPC::MessageEncoder&gt;, Vector&lt;RetainPtr&lt;CGContextRef&gt;&gt;);
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessWebPagemacRemoteLayerTreeDrawingAreamm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.mm (170315 => 170316)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.mm        2014-06-23 21:01:19 UTC (rev 170315)
+++ trunk/Source/WebKit2/WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.mm        2014-06-23 21:12:00 UTC (rev 170316)
</span><span class="lines">@@ -112,12 +112,14 @@
</span><span class="cx"> 
</span><span class="cx"> void RemoteLayerTreeDrawingArea::setRootCompositingLayer(GraphicsLayer* rootLayer)
</span><span class="cx"> {
</span><del>-    Vector&lt;GraphicsLayer *&gt; children;
</del><ins>+    Vector&lt;GraphicsLayer*&gt; children;
</ins><span class="cx">     if (rootLayer) {
</span><span class="cx">         children.append(rootLayer);
</span><span class="cx">         children.append(m_webPage.pageOverlayController().viewOverlayRootLayer());
</span><span class="cx">     }
</span><span class="cx">     m_rootLayer-&gt;setChildren(children);
</span><ins>+
+    scheduleCompositingLayerFlush();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void RemoteLayerTreeDrawingArea::updateGeometry(const IntSize&amp; viewSize, const IntSize&amp; layerPosition)
</span><span class="lines">@@ -353,6 +355,11 @@
</span><span class="cx">     m_webPage.pageOverlayController().didChangeDocumentSize();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool RemoteLayerTreeDrawingArea::markLayersVolatileImmediatelyIfPossible()
+{
+    return m_remoteLayerTreeContext-&gt;backingStoreCollection().markAllBackingStoreVolatileImmediatelyIfPossible();
+}
+
</ins><span class="cx"> PassRefPtr&lt;RemoteLayerTreeDrawingArea::BackingStoreFlusher&gt; RemoteLayerTreeDrawingArea::BackingStoreFlusher::create(IPC::Connection* connection, std::unique_ptr&lt;IPC::MessageEncoder&gt; encoder, Vector&lt;RetainPtr&lt;CGContextRef&gt;&gt; contextsToFlush)
</span><span class="cx"> {
</span><span class="cx">     return adoptRef(new RemoteLayerTreeDrawingArea::BackingStoreFlusher(connection, std::move(encoder), std::move(contextsToFlush)));
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessWebProcesscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/WebProcess.cpp (170315 => 170316)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/WebProcess.cpp        2014-06-23 21:01:19 UTC (rev 170315)
+++ trunk/Source/WebKit2/WebProcess/WebProcess.cpp        2014-06-23 21:12:00 UTC (rev 170316)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;APIFrameHandle.h&quot;
</span><span class="cx"> #include &quot;AuthenticationManager.h&quot;
</span><ins>+#include &quot;DrawingArea.h&quot;
</ins><span class="cx"> #include &quot;EventDispatcher.h&quot;
</span><span class="cx"> #include &quot;InjectedBundle.h&quot;
</span><span class="cx"> #include &quot;InjectedBundleUserMessageCoders.h&quot;
</span><span class="lines">@@ -151,6 +152,7 @@
</span><span class="cx">     : m_eventDispatcher(EventDispatcher::create())
</span><span class="cx"> #if PLATFORM(IOS)
</span><span class="cx">     , m_viewUpdateDispatcher(ViewUpdateDispatcher::create())
</span><ins>+    , m_processSuspensionCleanupTimer(this, &amp;WebProcess::processSuspensionCleanupTimerFired)
</ins><span class="cx"> #endif // PLATFORM(IOS)
</span><span class="cx">     , m_inDidClose(false)
</span><span class="cx">     , m_hasSetCacheModel(false)
</span><span class="lines">@@ -1163,9 +1165,42 @@
</span><span class="cx"> void WebProcess::processWillSuspend()
</span><span class="cx"> {
</span><span class="cx">     memoryPressureHandler().releaseMemory(true);
</span><del>-    parentProcessConnection()-&gt;send(Messages::WebProcessProxy::ProcessReadyToSuspend(), 0);
</del><ins>+
+    if (!markAllLayersVolatileIfPossible())
+        m_processSuspensionCleanupTimer.startRepeating(std::chrono::milliseconds(20));
+    else
+        parentProcessConnection()-&gt;send(Messages::WebProcessProxy::ProcessReadyToSuspend(), 0);
</ins><span class="cx"> }
</span><del>-    
</del><ins>+
+void WebProcess::cancelProcessWillSuspend()
+{
+    // If we've already finished cleaning up and sent ProcessReadyToSuspend, we
+    // shouldn't send DidCancelProcessSuspension; the UI process strictly expects one or the other.
+    if (!m_processSuspensionCleanupTimer.isActive())
+        return;
+
+    m_processSuspensionCleanupTimer.stop();
+    parentProcessConnection()-&gt;send(Messages::WebProcessProxy::DidCancelProcessSuspension(), 0);
+}
+
+bool WebProcess::markAllLayersVolatileIfPossible()
+{
+    bool successfullyMarkedAllLayersVolatile = true;
+    for (auto&amp; page : m_pageMap.values()) {
+        if (auto drawingArea = page-&gt;drawingArea())
+            successfullyMarkedAllLayersVolatile &amp;= drawingArea-&gt;markLayersVolatileImmediatelyIfPossible();
+    }
+
+    return successfullyMarkedAllLayersVolatile;
+}
+
+void WebProcess::processSuspensionCleanupTimerFired(Timer&lt;WebProcess&gt;* timer)
+{
+    if (markAllLayersVolatileIfPossible()) {
+        parentProcessConnection()-&gt;send(Messages::WebProcessProxy::ProcessReadyToSuspend(), 0);
+        timer-&gt;stop();
+    }
+}
</ins><span class="cx"> #endif // PLATFORM(IOS)
</span><span class="cx"> 
</span><span class="cx"> void WebProcess::pageDidEnterWindow(uint64_t pageID)
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessWebProcessh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/WebProcess.h (170315 => 170316)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/WebProcess.h        2014-06-23 21:01:19 UTC (rev 170315)
+++ trunk/Source/WebKit2/WebProcess/WebProcess.h        2014-06-23 21:12:00 UTC (rev 170316)
</span><span class="lines">@@ -29,6 +29,7 @@
</span><span class="cx"> #include &quot;CacheModel.h&quot;
</span><span class="cx"> #include &quot;ChildProcess.h&quot;
</span><span class="cx"> #include &quot;DownloadManager.h&quot;
</span><ins>+#include &quot;DrawingArea.h&quot;
</ins><span class="cx"> #include &quot;PluginProcessConnectionManager.h&quot;
</span><span class="cx"> #include &quot;ResourceCachesToClear.h&quot;
</span><span class="cx"> #include &quot;SandboxExtension.h&quot;
</span><span class="lines">@@ -177,6 +178,9 @@
</span><span class="cx"> #if PLATFORM(IOS)
</span><span class="cx">     void resetAllGeolocationPermissions();
</span><span class="cx">     void processWillSuspend();
</span><ins>+    void cancelProcessWillSuspend();
+    bool markAllLayersVolatileIfPossible();
+    void processSuspensionCleanupTimerFired(WebCore::Timer&lt;WebProcess&gt;*);
</ins><span class="cx"> #endif // PLATFORM(IOS)
</span><span class="cx"> 
</span><span class="cx">     RefPtr&lt;API::Object&gt; apiObjectByConvertingFromHandles(API::Object*);
</span><span class="lines">@@ -286,6 +290,7 @@
</span><span class="cx">     RefPtr&lt;EventDispatcher&gt; m_eventDispatcher;
</span><span class="cx"> #if PLATFORM(IOS)
</span><span class="cx">     RefPtr&lt;ViewUpdateDispatcher&gt; m_viewUpdateDispatcher;
</span><ins>+    WebCore::Timer&lt;WebProcess&gt; m_processSuspensionCleanupTimer;
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     bool m_inDidClose;
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessWebProcessmessagesin"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/WebProcess.messages.in (170315 => 170316)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/WebProcess.messages.in        2014-06-23 21:01:19 UTC (rev 170315)
+++ trunk/Source/WebKit2/WebProcess/WebProcess.messages.in        2014-06-23 21:12:00 UTC (rev 170316)
</span><span class="lines">@@ -95,5 +95,6 @@
</span><span class="cx"> 
</span><span class="cx"> #if PLATFORM(IOS)
</span><span class="cx">     ProcessWillSuspend()
</span><ins>+    CancelProcessWillSuspend()
</ins><span class="cx"> #endif
</span><span class="cx"> }
</span></span></pre>
</div>
</div>

</body>
</html>