Changeset 276882 in webkit


Ignore:
Timestamp:
May 1, 2021 10:22:49 PM (15 months ago)
Author:
Antti Koivisto
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:
Location:
trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r276877 r276882  
     12021-05-01  Antti Koivisto  <antti@apple.com>
     2
     3        Share style resolvers between author shadow trees with identical style
     4        https://bugs.webkit.org/show_bug.cgi?id=225187
     5        <rdar://problem/77317178>
     6
     7        Reviewed by Sam Weinig.
     8
     9        * fast/shadow-dom/style-resolver-sharing-expected.txt:
     10        * fast/shadow-dom/style-resolver-sharing.html:
     11
    1122021-05-01  Sam Weinig  <weinig@apple.com>
    213
  • trunk/LayoutTests/fast/shadow-dom/style-resolver-sharing-expected.txt

    r276836 r276882  
    88(shadow root resolver (author) (identifier=2) (author rule count=0))
    99(shadow root resolver (author) (identifier=3) (author rule count=1))
    10 (shadow root resolver (author) (identifier=4) (author rule count=1))
    11 (shadow root resolver (author) (identifier=5) (author rule count=1))
    12 (shadow root resolver (author) (identifier=6) (author rule count=1))
     10(shadow root resolver (author) (identifier=3) (author rule count=1))
     11(shadow root resolver (author) (identifier=3) (author rule count=1))
     12(shadow root resolver (author) (identifier=3) (author rule count=1))
     13(shadow root resolver (author) (identifier=3) (author rule count=1))
    1314
    1415After style mutation
     
    1920(shadow root resolver (author) (identifier=2) (author rule count=0))
    2021(shadow root resolver (author) (identifier=3) (author rule count=1))
    21 (shadow root resolver (author) (identifier=4) (author rule count=1))
     22(shadow root resolver (author) (identifier=3) (author rule count=1))
     23(shadow root resolver (author) (identifier=4) (author rule count=2))
    2224(shadow root resolver (author) (identifier=5) (author rule count=2))
    23 (shadow root resolver (author) (identifier=6) (author rule count=2))
    2425(shadow root resolver (author) (identifier=2) (author rule count=0))
    2526(shadow root resolver (author) (identifier=2) (author rule count=0))
     27(shadow root resolver (author) (identifier=3) (author rule count=1))
    2628
  • trunk/LayoutTests/fast/shadow-dom/style-resolver-sharing.html

    r276836 r276882  
    1010<div id=g></div>
    1111<div id=h></div>
     12<div id=i></div>
     13
    1214<pre id=log></pre>
    1315
     
    3436attachShadowWithStyle("g", "div { color: green }");
    3537attachShadowWithStyle("h", "div { color: green }");
     38attachShadowWithStyle("i", "div { color: green }");
    3639
    3740if (window.internals) {
  • trunk/Source/WebCore/ChangeLog

    r276881 r276882  
     12021-05-01  Antti Koivisto  <antti@apple.com>
     2
     3        Share style resolvers between author shadow trees with identical style
     4        https://bugs.webkit.org/show_bug.cgi?id=225187
     5        <rdar://problem/77317178>
     6
     7        Reviewed by Sam Weinig.
     8
     9        Style resolvers own style resolution and invalidation rule sets, matched declarations cache, and other things.
     10        With complex stylesheets that can be lot of data. We currently create a style resolver for each author
     11        shadow tree. With web components it is common for a page to have large number of instances of the same
     12        component, and so shadow trees with identical style.
     13
     14        We already deduplicate shadow tree stylesheets (including inline stylesheets based on string equality).
     15        With this patch we'll use these stylesheets as keys for sharing the full style resolvers as well.
     16
     17        * style/StyleScope.cpp:
     18        (WebCore::Style::Scope::createOrFindSharedShadowTreeResolver):
     19
     20        Expand the existing support for sharing between user agent shadow trees and author shadow trees with
     21        empty style. Look up shareable resolvers from a map.
     22
     23        (WebCore::Style::Scope::unshareShadowTreeResolverBeforeMutation):
     24        (WebCore::Style::Scope::makeResolverSharingKey):
     25
     26        Make a key from the active stylesheets and a bit indicating the shadow tree type.
     27
     28        (WebCore::Style::Scope::releaseMemory):
     29        (WebCore::Style::Scope::didChangeStyleSheetEnvironment):
     30        * style/StyleScope.h:
     31
    1322021-05-01  Sam Weinig  <weinig@apple.com>
    233
  • trunk/Source/WebCore/style/StyleScope.cpp

    r276836 r276882  
    109109    ASSERT(m_shadowRoot);
    110110
    111     if (m_activeStyleSheets.isEmpty()) {
    112         auto& sharedResolver = isForUserAgentShadowTree() ? documentScope().m_sharedUserAgentShadowTreeResolver : documentScope().m_sharedEmptyAuthorShadowTreeResolver;
    113         if (!sharedResolver) {
    114             sharedResolver = Resolver::create(m_document);
    115             sharedResolver->ruleSets().setUsesSharedUserStyle(!isForUserAgentShadowTree());
    116         } else
    117             sharedResolver->setSharedBetweenShadowTrees();
    118 
    119         m_resolver = sharedResolver;
    120         return;
    121     }
    122 
    123     m_resolver = Resolver::create(m_document);
    124 
    125     m_resolver->ruleSets().setUsesSharedUserStyle(!isForUserAgentShadowTree());
    126     m_resolver->appendAuthorStyleSheets(m_activeStyleSheets);
     111    auto key = makeResolverSharingKey();
     112
     113    auto result = documentScope().m_sharedShadowTreeResolvers.ensure(WTFMove(key), [&] {
     114        SetForScope<bool> isUpdatingStyleResolver { m_isUpdatingStyleResolver, true };
     115
     116        m_resolver = Resolver::create(m_document);
     117
     118        m_resolver->ruleSets().setUsesSharedUserStyle(!isForUserAgentShadowTree());
     119        m_resolver->appendAuthorStyleSheets(m_activeStyleSheets);
     120
     121        return makeRef(*m_resolver);
     122    });
     123
     124    if (!result.isNewEntry) {
     125        m_resolver = result.iterator->value.ptr();
     126        m_resolver->setSharedBetweenShadowTrees();
     127    }
    127128}
    128129
     
    132133    ASSERT(!m_resolver->isSharedBetweenShadowTrees());
    133134
    134     auto& sharedResolver = isForUserAgentShadowTree() ? documentScope().m_sharedUserAgentShadowTreeResolver : documentScope().m_sharedEmptyAuthorShadowTreeResolver;
    135    
    136     if (m_resolver == sharedResolver)
    137         sharedResolver = nullptr;
     135    documentScope().m_sharedShadowTreeResolvers.remove(makeResolverSharingKey());
     136}
     137
     138auto Scope::makeResolverSharingKey() -> ResolverSharingKey
     139{
     140    constexpr bool isNonEmptyHashTableValue = true;
     141    return {
     142        m_activeStyleSheets.map([&](auto& sheet) { return makeRefPtr(sheet->contents()); }),
     143        isForUserAgentShadowTree(),
     144        isNonEmptyHashTableValue
     145    };
    138146}
    139147
     
    161169    clearResolver();
    162170
    163     m_sharedUserAgentShadowTreeResolver = nullptr;
    164     m_sharedEmptyAuthorShadowTreeResolver = nullptr;
     171    m_sharedShadowTreeResolvers.clear();
    165172}
    166173
     
    688695{
    689696    if (!m_shadowRoot) {
    690         m_sharedUserAgentShadowTreeResolver = nullptr;
    691         m_sharedEmptyAuthorShadowTreeResolver = nullptr;
     697        m_sharedShadowTreeResolvers.clear();
    692698
    693699        for (auto* descendantShadowRoot : m_document.inDocumentShadowRoots()) {
  • trunk/Source/WebCore/style/StyleScope.h

    r276836 r276882  
    166166    void unshareShadowTreeResolverBeforeMutation();
    167167
     168    using ResolverSharingKey = std::tuple<Vector<RefPtr<StyleSheetContents>>, bool, bool>;
     169    ResolverSharingKey makeResolverSharingKey();
     170
    168171    Document& m_document;
    169172    ShadowRoot* m_shadowRoot { nullptr };
     
    195198
    196199    // FIXME: These (and some things above) are only relevant for the root scope.
    197     RefPtr<Resolver> m_sharedUserAgentShadowTreeResolver;
    198     RefPtr<Resolver> m_sharedEmptyAuthorShadowTreeResolver;
     200    HashMap<ResolverSharingKey, Ref<Resolver>> m_sharedShadowTreeResolvers;
    199201};
    200202
Note: See TracChangeset for help on using the changeset viewer.