Title: [293953] trunk/Source/WebCore
Revision
293953
Author
simon.fra...@apple.com
Date
2022-05-07 20:47:40 -0700 (Sat, 07 May 2022)

Log Message

Use an OptionSet iterator to skip directly to GraphicsContextState::Change bits to handle
https://bugs.webkit.org/show_bug.cgi?id=239954
<rdar://problem/92593424>

Patch by Cameron McCormack <hey...@apple.com> on 2022-05-07
Reviewed by Simon Fraser.

It would be rare for display list SetState items to have many Change
bits set on them. Instead of checking for all 15 bits in mergeChanges,
we can use OptionSet's iterator to skip directly to each changed bit.

Using ctz to turn the Change bit into a bit position helps the
compiler generate compact code to jump to each case in the switch
statement.

On an iPad I tested with, this is a ~2% win on the MotionMark Design
subtest, 5.5% on Leaves, and 1.4% overall.

* platform/graphics/GraphicsContextState.cpp:
(WebCore::toIndex):
(WebCore::GraphicsContextState::mergeChanges):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (293952 => 293953)


--- trunk/Source/WebCore/ChangeLog	2022-05-08 02:41:37 UTC (rev 293952)
+++ trunk/Source/WebCore/ChangeLog	2022-05-08 03:47:40 UTC (rev 293953)
@@ -1,5 +1,28 @@
 2022-05-07  Cameron McCormack  <hey...@apple.com>
 
+        Use an OptionSet iterator to skip directly to GraphicsContextState::Change bits to handle
+        https://bugs.webkit.org/show_bug.cgi?id=239954
+        <rdar://problem/92593424>
+
+        Reviewed by Simon Fraser.
+
+        It would be rare for display list SetState items to have many Change
+        bits set on them. Instead of checking for all 15 bits in mergeChanges,
+        we can use OptionSet's iterator to skip directly to each changed bit.
+
+        Using ctz to turn the Change bit into a bit position helps the
+        compiler generate compact code to jump to each case in the switch
+        statement.
+
+        On an iPad I tested with, this is a ~2% win on the MotionMark Design
+        subtest, 5.5% on Leaves, and 1.4% overall.
+
+        * platform/graphics/GraphicsContextState.cpp:
+        (WebCore::toIndex):
+        (WebCore::GraphicsContextState::mergeChanges):
+
+2022-05-07  Cameron McCormack  <hey...@apple.com>
+
         Don't propagate GraphicsContextState change bits into TextPainter's glyph display list recorder
         https://bugs.webkit.org/show_bug.cgi?id=239952
         <rdar://problem/92635604>

Modified: trunk/Source/WebCore/platform/graphics/GraphicsContextState.cpp (293952 => 293953)


--- trunk/Source/WebCore/platform/graphics/GraphicsContextState.cpp	2022-05-08 02:41:37 UTC (rev 293952)
+++ trunk/Source/WebCore/platform/graphics/GraphicsContextState.cpp	2022-05-08 03:47:40 UTC (rev 293953)
@@ -26,6 +26,7 @@
 #include "config.h"
 #include "GraphicsContextState.h"
 
+#include <wtf/MathExtras.h>
 #include <wtf/text/TextStream.h>
 
 namespace WebCore {
@@ -57,37 +58,46 @@
     return true;
 }
 
+constexpr unsigned toIndex(GraphicsContextState::Change change)
+{
+    return WTF::ctzConstexpr(WTF::enumToUnderlyingType(change));
+}
+
 void GraphicsContextState::mergeChanges(const GraphicsContextState& state, const std::optional<GraphicsContextState>& lastDrawingState)
 {
-    auto mergeChange = [&](Change change, auto GraphicsContextState::*property) {
-        if (!state.changes().contains(change) || this->*property == state.*property)
-            return;
-        this->*property = state.*property;
-        m_changeFlags.set(change, !lastDrawingState || (*lastDrawingState).*property != this->*property);
-    };
+    for (auto change : state.changes()) {
+        auto mergeChange = [&](auto GraphicsContextState::*property) {
+            if (this->*property == state.*property)
+                return;
+            this->*property = state.*property;
+            m_changeFlags.set(change, !lastDrawingState || (*lastDrawingState).*property != this->*property);
+        };
 
-    mergeChange(Change::FillBrush,                      &GraphicsContextState::m_fillBrush);
-    mergeChange(Change::FillRule,                       &GraphicsContextState::m_fillRule);
+        switch (toIndex(change)) {
+        case toIndex(Change::FillBrush):                   mergeChange(&GraphicsContextState::m_fillBrush); break;
+        case toIndex(Change::FillRule):                    mergeChange(&GraphicsContextState::m_fillRule); break;
 
-    mergeChange(Change::StrokeBrush,                    &GraphicsContextState::m_strokeBrush);
-    mergeChange(Change::StrokeThickness,                &GraphicsContextState::m_strokeThickness);
-    mergeChange(Change::StrokeStyle,                    &GraphicsContextState::m_strokeStyle);
+        case toIndex(Change::StrokeBrush):                 mergeChange(&GraphicsContextState::m_strokeBrush); break;
+        case toIndex(Change::StrokeThickness):             mergeChange(&GraphicsContextState::m_strokeThickness); break;
+        case toIndex(Change::StrokeStyle):                 mergeChange(&GraphicsContextState::m_strokeStyle); break;
 
-    mergeChange(Change::CompositeMode,                  &GraphicsContextState::m_compositeMode);
-    mergeChange(Change::DropShadow,                     &GraphicsContextState::m_dropShadow);
+        case toIndex(Change::CompositeMode):               mergeChange(&GraphicsContextState::m_compositeMode); break;
+        case toIndex(Change::DropShadow):                  mergeChange(&GraphicsContextState::m_dropShadow); break;
 
-    mergeChange(Change::Alpha,                          &GraphicsContextState::m_alpha);
-    mergeChange(Change::ImageInterpolationQuality,      &GraphicsContextState::m_imageInterpolationQuality);
-    mergeChange(Change::TextDrawingMode,                &GraphicsContextState::m_textDrawingMode);
+        case toIndex(Change::Alpha):                       mergeChange(&GraphicsContextState::m_alpha); break;
+        case toIndex(Change::TextDrawingMode):             mergeChange(&GraphicsContextState::m_textDrawingMode); break;
+        case toIndex(Change::ImageInterpolationQuality):   mergeChange(&GraphicsContextState::m_imageInterpolationQuality); break;
 
-    mergeChange(Change::ShouldAntialias,                &GraphicsContextState::m_shouldAntialias);
-    mergeChange(Change::ShouldSmoothFonts,              &GraphicsContextState::m_shouldSmoothFonts);
-    mergeChange(Change::ShouldSubpixelQuantizeFonts,    &GraphicsContextState::m_shouldSubpixelQuantizeFonts);
-    mergeChange(Change::ShadowsIgnoreTransforms,        &GraphicsContextState::m_shadowsIgnoreTransforms);
-    mergeChange(Change::DrawLuminanceMask,              &GraphicsContextState::m_drawLuminanceMask);
+        case toIndex(Change::ShouldAntialias):             mergeChange(&GraphicsContextState::m_shouldAntialias); break;
+        case toIndex(Change::ShouldSmoothFonts):           mergeChange(&GraphicsContextState::m_shouldSmoothFonts); break;
+        case toIndex(Change::ShouldSubpixelQuantizeFonts): mergeChange(&GraphicsContextState::m_shouldSubpixelQuantizeFonts); break;
+        case toIndex(Change::ShadowsIgnoreTransforms):     mergeChange(&GraphicsContextState::m_shadowsIgnoreTransforms); break;
+        case toIndex(Change::DrawLuminanceMask):           mergeChange(&GraphicsContextState::m_drawLuminanceMask); break;
 #if HAVE(OS_DARK_MODE_SUPPORT)
-    mergeChange(Change::UseDarkAppearance,              &GraphicsContextState::m_useDarkAppearance);
+        case toIndex(Change::UseDarkAppearance):           mergeChange(&GraphicsContextState::m_useDarkAppearance); break;
 #endif
+        }
+    }
 }
 
 void GraphicsContextState::didBeginTransparencyLayer()
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to