Title: [276882] trunk
Revision
276882
Author
[email protected]
Date
2021-05-01 22:22:49 -0700 (Sat, 01 May 2021)

Log Message

Share style resolvers between author shadow trees with identical style
https://bugs.webkit.org/show_bug.cgi?id=225187
<rdar://problem/77317178>

Reviewed by Sam Weinig.

Source/WebCore:

Style resolvers own style resolution and invalidation rule sets, matched declarations cache, and other things.
With complex stylesheets that can be lot of data. We currently create a style resolver for each author
shadow tree. With web components it is common for a page to have large number of instances of the same
component, and so shadow trees with identical style.

We already deduplicate shadow tree stylesheets (including inline stylesheets based on string equality).
With this patch we'll use these stylesheets as keys for sharing the full style resolvers as well.

* style/StyleScope.cpp:
(WebCore::Style::Scope::createOrFindSharedShadowTreeResolver):

Expand the existing support for sharing between user agent shadow trees and author shadow trees with
empty style. Look up shareable resolvers from a map.

(WebCore::Style::Scope::unshareShadowTreeResolverBeforeMutation):
(WebCore::Style::Scope::makeResolverSharingKey):

Make a key from the active stylesheets and a bit indicating the shadow tree type.

(WebCore::Style::Scope::releaseMemory):
(WebCore::Style::Scope::didChangeStyleSheetEnvironment):
* style/StyleScope.h:

LayoutTests:

* fast/shadow-dom/style-resolver-sharing-expected.txt:
* fast/shadow-dom/style-resolver-sharing.html:

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (276881 => 276882)


--- trunk/LayoutTests/ChangeLog	2021-05-02 03:39:07 UTC (rev 276881)
+++ trunk/LayoutTests/ChangeLog	2021-05-02 05:22:49 UTC (rev 276882)
@@ -1,3 +1,14 @@
+2021-05-01  Antti Koivisto  <[email protected]>
+
+        Share style resolvers between author shadow trees with identical style
+        https://bugs.webkit.org/show_bug.cgi?id=225187
+        <rdar://problem/77317178>
+
+        Reviewed by Sam Weinig.
+
+        * fast/shadow-dom/style-resolver-sharing-expected.txt:
+        * fast/shadow-dom/style-resolver-sharing.html:
+
 2021-05-01  Sam Weinig  <[email protected]>
 
         Update operations in CanvasImageData.idl to use long rather than float as per spec

Modified: trunk/LayoutTests/fast/shadow-dom/style-resolver-sharing-expected.txt (276881 => 276882)


--- trunk/LayoutTests/fast/shadow-dom/style-resolver-sharing-expected.txt	2021-05-02 03:39:07 UTC (rev 276881)
+++ trunk/LayoutTests/fast/shadow-dom/style-resolver-sharing-expected.txt	2021-05-02 05:22:49 UTC (rev 276882)
@@ -7,9 +7,10 @@
 (shadow root resolver (author) (identifier=2) (author rule count=0))
 (shadow root resolver (author) (identifier=2) (author rule count=0))
 (shadow root resolver (author) (identifier=3) (author rule count=1))
-(shadow root resolver (author) (identifier=4) (author rule count=1))
-(shadow root resolver (author) (identifier=5) (author rule count=1))
-(shadow root resolver (author) (identifier=6) (author rule count=1))
+(shadow root resolver (author) (identifier=3) (author rule count=1))
+(shadow root resolver (author) (identifier=3) (author rule count=1))
+(shadow root resolver (author) (identifier=3) (author rule count=1))
+(shadow root resolver (author) (identifier=3) (author rule count=1))
 
 After style mutation
 (document resolver (identifier=0) (author rule count=0))
@@ -18,9 +19,10 @@
 (shadow root resolver (author) (identifier=2) (author rule count=0))
 (shadow root resolver (author) (identifier=2) (author rule count=0))
 (shadow root resolver (author) (identifier=3) (author rule count=1))
-(shadow root resolver (author) (identifier=4) (author rule count=1))
+(shadow root resolver (author) (identifier=3) (author rule count=1))
+(shadow root resolver (author) (identifier=4) (author rule count=2))
 (shadow root resolver (author) (identifier=5) (author rule count=2))
-(shadow root resolver (author) (identifier=6) (author rule count=2))
 (shadow root resolver (author) (identifier=2) (author rule count=0))
 (shadow root resolver (author) (identifier=2) (author rule count=0))
+(shadow root resolver (author) (identifier=3) (author rule count=1))
 

Modified: trunk/LayoutTests/fast/shadow-dom/style-resolver-sharing.html (276881 => 276882)


--- trunk/LayoutTests/fast/shadow-dom/style-resolver-sharing.html	2021-05-02 03:39:07 UTC (rev 276881)
+++ trunk/LayoutTests/fast/shadow-dom/style-resolver-sharing.html	2021-05-02 05:22:49 UTC (rev 276882)
@@ -9,6 +9,8 @@
 <div id=f></div>
 <div id=g></div>
 <div id=h></div>
+<div id=i></div>
+
 <pre id=log></pre>
 
 <script>
@@ -33,6 +35,7 @@
 attachShadowWithStyle("f", "div { color: green }");
 attachShadowWithStyle("g", "div { color: green }");
 attachShadowWithStyle("h", "div { color: green }");
+attachShadowWithStyle("i", "div { color: green }");
 
 if (window.internals) {
     log.textContent += internals.dumpStyleResolvers();

Modified: trunk/Source/WebCore/ChangeLog (276881 => 276882)


--- trunk/Source/WebCore/ChangeLog	2021-05-02 03:39:07 UTC (rev 276881)
+++ trunk/Source/WebCore/ChangeLog	2021-05-02 05:22:49 UTC (rev 276882)
@@ -1,3 +1,34 @@
+2021-05-01  Antti Koivisto  <[email protected]>
+
+        Share style resolvers between author shadow trees with identical style
+        https://bugs.webkit.org/show_bug.cgi?id=225187
+        <rdar://problem/77317178>
+
+        Reviewed by Sam Weinig.
+
+        Style resolvers own style resolution and invalidation rule sets, matched declarations cache, and other things.
+        With complex stylesheets that can be lot of data. We currently create a style resolver for each author
+        shadow tree. With web components it is common for a page to have large number of instances of the same
+        component, and so shadow trees with identical style.
+
+        We already deduplicate shadow tree stylesheets (including inline stylesheets based on string equality).
+        With this patch we'll use these stylesheets as keys for sharing the full style resolvers as well.
+
+        * style/StyleScope.cpp:
+        (WebCore::Style::Scope::createOrFindSharedShadowTreeResolver):
+
+        Expand the existing support for sharing between user agent shadow trees and author shadow trees with
+        empty style. Look up shareable resolvers from a map.
+
+        (WebCore::Style::Scope::unshareShadowTreeResolverBeforeMutation):
+        (WebCore::Style::Scope::makeResolverSharingKey):
+
+        Make a key from the active stylesheets and a bit indicating the shadow tree type.
+
+        (WebCore::Style::Scope::releaseMemory):
+        (WebCore::Style::Scope::didChangeStyleSheetEnvironment):
+        * style/StyleScope.h:
+
 2021-05-01  Sam Weinig  <[email protected]>
 
         Move PixelFormat into its own file

Modified: trunk/Source/WebCore/style/StyleScope.cpp (276881 => 276882)


--- trunk/Source/WebCore/style/StyleScope.cpp	2021-05-02 03:39:07 UTC (rev 276881)
+++ trunk/Source/WebCore/style/StyleScope.cpp	2021-05-02 05:22:49 UTC (rev 276882)
@@ -108,22 +108,23 @@
     ASSERT(!m_resolver);
     ASSERT(m_shadowRoot);
 
-    if (m_activeStyleSheets.isEmpty()) {
-        auto& sharedResolver = isForUserAgentShadowTree() ? documentScope().m_sharedUserAgentShadowTreeResolver : documentScope().m_sharedEmptyAuthorShadowTreeResolver;
-        if (!sharedResolver) {
-            sharedResolver = Resolver::create(m_document);
-            sharedResolver->ruleSets().setUsesSharedUserStyle(!isForUserAgentShadowTree());
-        } else
-            sharedResolver->setSharedBetweenShadowTrees();
+    auto key = makeResolverSharingKey();
 
-        m_resolver = sharedResolver;
-        return;
-    }
+    auto result = documentScope().m_sharedShadowTreeResolvers.ensure(WTFMove(key), [&] {
+        SetForScope<bool> isUpdatingStyleResolver { m_isUpdatingStyleResolver, true };
 
-    m_resolver = Resolver::create(m_document);
+        m_resolver = Resolver::create(m_document);
 
-    m_resolver->ruleSets().setUsesSharedUserStyle(!isForUserAgentShadowTree());
-    m_resolver->appendAuthorStyleSheets(m_activeStyleSheets);
+        m_resolver->ruleSets().setUsesSharedUserStyle(!isForUserAgentShadowTree());
+        m_resolver->appendAuthorStyleSheets(m_activeStyleSheets);
+
+        return makeRef(*m_resolver);
+    });
+
+    if (!result.isNewEntry) {
+        m_resolver = result.iterator->value.ptr();
+        m_resolver->setSharedBetweenShadowTrees();
+    }
 }
 
 void Scope::unshareShadowTreeResolverBeforeMutation()
@@ -131,12 +132,19 @@
     ASSERT(m_shadowRoot);
     ASSERT(!m_resolver->isSharedBetweenShadowTrees());
 
-    auto& sharedResolver = isForUserAgentShadowTree() ? documentScope().m_sharedUserAgentShadowTreeResolver : documentScope().m_sharedEmptyAuthorShadowTreeResolver;
-    
-    if (m_resolver == sharedResolver)
-        sharedResolver = nullptr;
+    documentScope().m_sharedShadowTreeResolvers.remove(makeResolverSharingKey());
 }
 
+auto Scope::makeResolverSharingKey() -> ResolverSharingKey
+{
+    constexpr bool isNonEmptyHashTableValue = true;
+    return {
+        m_activeStyleSheets.map([&](auto& sheet) { return makeRefPtr(sheet->contents()); }),
+        isForUserAgentShadowTree(),
+        isNonEmptyHashTableValue
+    };
+}
+
 void Scope::clearResolver()
 {
     m_resolver = nullptr;
@@ -160,8 +168,7 @@
 #endif
     clearResolver();
 
-    m_sharedUserAgentShadowTreeResolver = nullptr;
-    m_sharedEmptyAuthorShadowTreeResolver = nullptr;
+    m_sharedShadowTreeResolvers.clear();
 }
 
 Scope& Scope::forNode(Node& node)
@@ -687,8 +694,7 @@
 void Scope::didChangeStyleSheetEnvironment()
 {
     if (!m_shadowRoot) {
-        m_sharedUserAgentShadowTreeResolver = nullptr;
-        m_sharedEmptyAuthorShadowTreeResolver = nullptr;
+        m_sharedShadowTreeResolvers.clear();
 
         for (auto* descendantShadowRoot : m_document.inDocumentShadowRoots()) {
             // Stylesheets is author shadow roots are potentially affected.

Modified: trunk/Source/WebCore/style/StyleScope.h (276881 => 276882)


--- trunk/Source/WebCore/style/StyleScope.h	2021-05-02 03:39:07 UTC (rev 276881)
+++ trunk/Source/WebCore/style/StyleScope.h	2021-05-02 05:22:49 UTC (rev 276882)
@@ -165,6 +165,9 @@
     void createOrFindSharedShadowTreeResolver();
     void unshareShadowTreeResolverBeforeMutation();
 
+    using ResolverSharingKey = std::tuple<Vector<RefPtr<StyleSheetContents>>, bool, bool>;
+    ResolverSharingKey makeResolverSharingKey();
+
     Document& m_document;
     ShadowRoot* m_shadowRoot { nullptr };
 
@@ -194,8 +197,7 @@
     bool m_isUpdatingStyleResolver { false };
 
     // FIXME: These (and some things above) are only relevant for the root scope.
-    RefPtr<Resolver> m_sharedUserAgentShadowTreeResolver;
-    RefPtr<Resolver> m_sharedEmptyAuthorShadowTreeResolver;
+    HashMap<ResolverSharingKey, Ref<Resolver>> m_sharedShadowTreeResolvers;
 };
 
 inline bool Scope::hasPendingSheets() const
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to