- 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