Fix WebContent jetsam when pinch-zooming reddit.com
Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp
WebKit's compositing layer tree uses Core Animation layers backed by IOSurfaces for GPU-accelerated rendering. Layers below a size threshold use a single full-resolution backing store ("non-tiled"); layers exceeding the threshold switch to a tile cache that only rasterizes the visible region. The switch is governed by requiresTiledLayer(), which evaluates effective resolution at the current zoom level.
The bug was a scale factor mismatch between two related code paths. requiresTiledLayer() checked only pageScaleFactor (logical zoom) against the tiling threshold, while updateContentsScale() used the full pageScaleFactor × deviceScaleFactor (pixel density) for the actual backing store allocation. On a 3x Retina device at 5x page zoom, a 398×398 CSS-pixel layer required a backing store at 15x scale — roughly 5,970×5,970 actual pixels, or ~65MB per IOSurface. With 40+ such layers on an image-heavy page like reddit.com, total IOSurface memory reached ~2.6GB and triggered iOS jetsam (OS-level process termination for memory pressure). The fix corrects requiresTiledLayer() to include deviceScaleFactor in its check and adds a hard 16MB byte-size ceiling before promoting any layer to tiled backing.
Scale path (before fix):
requiresTiledLayer(): pageScaleFactor >= threshold ← wrong
updateContentsScale(): pageScaleFactor × deviceScaleFactor ← correct
Result: 65MB IOSurface × 40 layers → 2.6GB → jetsam
Scale path (after fix):
requiresTiledLayer(): pageScaleFactor × deviceScaleFactor ← corrected
updateContentsScale(): 16MB byte-size cap enforced
Result: layer promoted to tiled before huge allocation
Significance
The fix reduces peak IOSurface memory from ~2.6GB to ~1.4GB under the reproducing conditions by enforcing a 16MB cap and correcting the tier-promotion logic. The root cause — a scale factor applied inconsistently across two related but separate code paths — is a recurring class of WebKit compositing bug.