WebKit memory management: Safari jetsams on some websites when zooming and scrolling
authorantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 31 May 2018 17:55:43 +0000 (17:55 +0000)
committerantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 31 May 2018 17:55:43 +0000 (17:55 +0000)
https://bugs.webkit.org/show_bug.cgi?id=186091
<rdar://problem/36315010>

Reviewed by Geoff Garen.

When zooming a page rapidly the visible rect and the page zoom level may get momentarily out of sync.
When this happens we may generate tiles for a much larger area than needed and run out of memory
building the next layer tree transaction. Running out of memory is more likely if the page has lots of
tiled layers in addition to the main content layer.

We already have code for dealing with the scale mismatch for zoom-out case (where this would cause
visibly missing tiles). This patch enables the same exact adjustment for zoom-in case (where the
symptom is creating too many tiles).

* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::adjustExposedRectForNewScale):

Do some renames to make it clear that this can both expand and contract the visible rect.
Bail out if there is nothing to do.

(WebKit::WebPage::updateVisibleContentRects):

Call adjustExposedRectForNewScale directly and unconditionally.

(WebKit::adjustExposedRectForBoundedScale): Deleted.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@232356 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebKit/ChangeLog
Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm

index 23de5dd..dc9918f 100644 (file)
@@ -1,3 +1,32 @@
+2018-05-31  Antti Koivisto  <antti@apple.com>
+
+        WebKit memory management: Safari jetsams on some websites when zooming and scrolling
+        https://bugs.webkit.org/show_bug.cgi?id=186091
+        <rdar://problem/36315010>
+
+        Reviewed by Geoff Garen.
+
+        When zooming a page rapidly the visible rect and the page zoom level may get momentarily out of sync.
+        When this happens we may generate tiles for a much larger area than needed and run out of memory
+        building the next layer tree transaction. Running out of memory is more likely if the page has lots of
+        tiled layers in addition to the main content layer.
+
+        We already have code for dealing with the scale mismatch for zoom-out case (where this would cause
+        visibly missing tiles). This patch enables the same exact adjustment for zoom-in case (where the
+        symptom is creating too many tiles).
+
+        * WebProcess/WebPage/ios/WebPageIOS.mm:
+        (WebKit::adjustExposedRectForNewScale):
+
+        Do some renames to make it clear that this can both expand and contract the visible rect.
+        Bail out if there is nothing to do.
+
+        (WebKit::WebPage::updateVisibleContentRects):
+
+        Call adjustExposedRectForNewScale directly and unconditionally.
+
+        (WebKit::adjustExposedRectForBoundedScale): Deleted.
+
 2018-05-30  Yusuke Suzuki  <utatane.tea@gmail.com>
 
         [JSC] Pass VM& parameter as much as possible
index 2474130..5b844e3 100644 (file)
@@ -299,13 +299,15 @@ static FloatPoint relativeCenterAfterContentSizeChange(const FloatRect& original
 
 static inline FloatRect adjustExposedRectForNewScale(const FloatRect& exposedRect, double exposedRectScale, double newScale)
 {
-    double overscaledWidth = exposedRect.width();
-    double missingHorizonalMargin = exposedRect.width() * exposedRectScale / newScale - overscaledWidth;
+    if (exposedRectScale == newScale)
+        return exposedRect;
 
-    double overscaledHeight = exposedRect.height();
-    double missingVerticalMargin = exposedRect.height() * exposedRectScale / newScale - overscaledHeight;
+    float horizontalChange = exposedRect.width() * exposedRectScale / newScale - exposedRect.width();
+    float verticalChange = exposedRect.height() * exposedRectScale / newScale - exposedRect.height();
 
-    return FloatRect(exposedRect.x() - missingHorizonalMargin / 2, exposedRect.y() - missingVerticalMargin / 2, exposedRect.width() + missingHorizonalMargin, exposedRect.height() + missingVerticalMargin);
+    auto adjustedRect = exposedRect;
+    adjustedRect.inflate({ horizontalChange / 2, verticalChange / 2 });
+    return adjustedRect;
 }
 
 void WebPage::restorePageState(const HistoryItem& historyItem)
@@ -2808,14 +2810,6 @@ static inline void adjustVelocityDataForBoundedScale(double& horizontalVelocity,
         scaleChangeRate = 0;
 }
 
-static inline FloatRect adjustExposedRectForBoundedScale(const FloatRect& exposedRect, double exposedRectScale, double newScale)
-{
-    if (exposedRectScale < newScale)
-        return exposedRect;
-
-    return adjustExposedRectForNewScale(exposedRect, exposedRectScale, newScale);
-}
-
 std::optional<float> WebPage::scaleFromUIProcess(const VisibleContentRectUpdateInfo& visibleContentRectUpdateInfo) const
 {
     auto transactionIDForLastScaleSentToUIProcess = downcast<RemoteLayerTreeDrawingArea>(*m_drawingArea).lastCommittedTransactionID();
@@ -2886,7 +2880,7 @@ void WebPage::updateVisibleContentRects(const VisibleContentRectUpdateInfo& visi
 
     float scaleToUse = scaleFromUIProcess.value_or(m_page->pageScaleFactor());
     FloatRect exposedContentRect = visibleContentRectUpdateInfo.exposedContentRect();
-    FloatRect adjustedExposedContentRect = adjustExposedRectForBoundedScale(exposedContentRect, visibleContentRectUpdateInfo.scale(), scaleToUse);
+    FloatRect adjustedExposedContentRect = adjustExposedRectForNewScale(exposedContentRect, visibleContentRectUpdateInfo.scale(), scaleToUse);
     m_drawingArea->setExposedContentRect(adjustedExposedContentRect);
 
     IntPoint scrollPosition = roundedIntPoint(visibleContentRectUpdateInfo.unobscuredContentRect().location());