Changeset 207339 in webkit
- Timestamp:
- Oct 14, 2016, 8:39:04 AM (8 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r207338 r207339 1 2016-10-14 Antti Koivisto <antti@apple.com> 2 3 Share inline stylesheets between shadow trees 4 https://bugs.webkit.org/show_bug.cgi?id=163353 5 6 Reviewed by Ryosuke Niwa and Andreas Kling. 7 8 If shadow trees have identical inline stylesheets the data structures can be shared. 9 In future this will also allow sharing style resolvers. 10 11 * css/CSSStyleSheet.cpp: 12 (WebCore::CSSStyleSheet::createInline): 13 14 Move StyleSheetContents construction to the client. 15 16 * css/parser/CSSParserMode.h: 17 (WebCore::CSSParserContextHash::hash): 18 (WebCore::CSSParserContextHash::equal): 19 (WTF::HashTraits<WebCore::CSSParserContext>::constructDeletedValue): 20 (WTF::HashTraits<WebCore::CSSParserContext>::isDeletedValue): 21 (WTF::HashTraits<WebCore::CSSParserContext>::emptyValue): 22 23 Make CSSParserContext hashable. 24 25 * dom/ExtensionStyleSheets.cpp: 26 (WebCore::createExtensionsStyleSheet): 27 (WebCore::ExtensionStyleSheets::pageUserSheet): 28 (WebCore::ExtensionStyleSheets::updateInjectedStyleSheetCache): 29 30 Don't use CSSStyleSheet::createInline, these are not really inline stylesheets. 31 Code cleanups. 32 33 * dom/InlineStyleSheetOwner.cpp: 34 (WebCore::parserContextForForElement): 35 (WebCore::makeInlineStyleSheetCacheKey): 36 (WebCore::inlineStyleSheetCache): 37 38 Implement a simple cache for sharing stylesheets with identical text and context. 39 40 (WebCore::InlineStyleSheetOwner::createSheet): 41 (WebCore::InlineStyleSheetOwner::clearCache): 42 * dom/InlineStyleSheetOwner.h: 43 * platform/MemoryPressureHandler.cpp: 44 (WebCore::MemoryPressureHandler::releaseNoncriticalMemory): 45 1 46 2016-10-14 Chris Dumez <cdumez@apple.com> 2 47 -
trunk/Source/WebCore/css/CSSStyleSheet.cpp
r206951 r207339 90 90 } 91 91 92 Ref<CSSStyleSheet> CSSStyleSheet::createInline(Node& ownerNode, const URL& baseURL, const TextPosition& startPosition, const String& encoding) 93 { 94 CSSParserContext parserContext(ownerNode.document(), baseURL, encoding); 95 return adoptRef(*new CSSStyleSheet(StyleSheetContents::create(baseURL.string(), parserContext), ownerNode, startPosition, true, true)); 92 Ref<CSSStyleSheet> CSSStyleSheet::createInline(Ref<StyleSheetContents>&& sheet, Element& owner, const TextPosition& startPosition) 93 { 94 return adoptRef(*new CSSStyleSheet(WTFMove(sheet), owner, startPosition, true, true)); 96 95 } 97 96 -
trunk/Source/WebCore/css/CSSStyleSheet.h
r206917 r207339 40 40 class CachedCSSStyleSheet; 41 41 class Document; 42 class Element; 42 43 class MediaQuerySet; 43 44 class SecurityOrigin; … … 55 56 static Ref<CSSStyleSheet> create(Ref<StyleSheetContents>&&, CSSImportRule* ownerRule = 0); 56 57 static Ref<CSSStyleSheet> create(Ref<StyleSheetContents>&&, Node& ownerNode, const Optional<bool>& isOriginClean = Nullopt); 57 static Ref<CSSStyleSheet> createInline( Node&, const URL&, const TextPosition& startPosition = TextPosition::minimumPosition(), const String& encoding = String());58 static Ref<CSSStyleSheet> createInline(Ref<StyleSheetContents>&&, Element& owner, const TextPosition& startPosition); 58 59 59 60 virtual ~CSSStyleSheet(); -
trunk/Source/WebCore/css/parser/CSSParserMode.h
r207291 r207339 33 33 34 34 #include "URL.h" 35 #include "URLHash.h" 36 #include <wtf/HashFunctions.h> 37 #include <wtf/text/StringHash.h> 35 38 36 39 namespace WebCore { … … 115 118 WEBCORE_EXPORT const CSSParserContext& strictCSSParserContext(); 116 119 120 struct CSSParserContextHash { 121 static unsigned hash(const CSSParserContext& key) 122 { 123 auto hash = URLHash::hash(key.baseURL); 124 hash ^= StringHash::hash(key.charset); 125 unsigned bits = key.isHTMLDocument << 0 126 & key.isHTMLDocument << 1 127 #if ENABLE(CSS_GRID_LAYOUT) 128 & key.cssGridLayoutEnabled << 2 129 #endif 130 #if ENABLE(TEXT_AUTOSIZING) 131 & key.textAutosizingEnabled << 3 132 #endif 133 & key.needsSiteSpecificQuirks << 4 134 & key.enforcesCSSMIMETypeInNoQuirksMode << 5 135 & key.useLegacyBackgroundSizeShorthandBehavior << 6 136 & key.springTimingFunctionEnabled << 7 137 & key.useNewParser << 8 138 #if ENABLE(VARIATION_FONTS) 139 & key.variationFontsEnabled << 9 140 #endif 141 & key.mode << 10; 142 hash ^= WTF::intHash(bits); 143 return hash; 144 } 145 static bool equal(const CSSParserContext& a, const CSSParserContext& b) 146 { 147 return a == b; 148 } 149 static const bool safeToCompareToEmptyOrDeleted = false; 117 150 }; 118 151 152 } 153 154 namespace WTF { 155 template<> struct HashTraits<WebCore::CSSParserContext> : GenericHashTraits<WebCore::CSSParserContext> { 156 static void constructDeletedValue(WebCore::CSSParserContext& slot) { new (NotNull, &slot.baseURL) WebCore::URL(WTF::HashTableDeletedValue); } 157 static bool isDeletedValue(const WebCore::CSSParserContext& value) { return value.baseURL.isHashTableDeletedValue(); } 158 static WebCore::CSSParserContext emptyValue() { return WebCore::CSSParserContext(WebCore::HTMLStandardMode); } 159 }; 160 161 template<> struct DefaultHash<WebCore::CSSParserContext> { 162 typedef WebCore::CSSParserContextHash Hash; 163 }; 164 } 165 119 166 #endif // CSSParserMode_h -
trunk/Source/WebCore/dom/ExtensionStyleSheets.cpp
r206917 r207339 60 60 } 61 61 62 static Ref<CSSStyleSheet> createExtensionsStyleSheet(Document& document, URL url, const String& text, UserStyleLevel level) 63 { 64 auto contents = StyleSheetContents::create(url, CSSParserContext(document, url)); 65 auto styleSheet = CSSStyleSheet::create(contents.get(), document, true); 66 67 contents->setIsUserStyleSheet(level == UserStyleUserLevel); 68 contents->parseString(text); 69 70 return styleSheet; 71 } 72 62 73 CSSStyleSheet* ExtensionStyleSheets::pageUserSheet() 63 74 { … … 73 84 return 0; 74 85 75 // Parse the sheet and cache it. 76 m_pageUserSheet = CSSStyleSheet::createInline(m_document, m_document.settings()->userStyleSheetLocation()); 77 m_pageUserSheet->contents().setIsUserStyleSheet(true); 78 m_pageUserSheet->contents().parseString(userSheetText); 86 m_pageUserSheet = createExtensionsStyleSheet(m_document, m_document.settings()->userStyleSheetLocation(), userSheetText, UserStyleUserLevel); 87 79 88 return m_pageUserSheet.get(); 80 89 } … … 126 135 return; 127 136 128 RefPtr<CSSStyleSheet> sheet = CSSStyleSheet::createInline(const_cast<Document&>(m_document), userStyleSheet.url());129 bool isUserStyleSheet = userStyleSheet.level() == UserStyleUserLevel; 130 if ( isUserStyleSheet)131 m_injectedUserStyleSheets.append( sheet);137 auto sheet = createExtensionsStyleSheet(const_cast<Document&>(m_document), userStyleSheet.url(), userStyleSheet.source(), userStyleSheet.level()); 138 139 if (userStyleSheet.level() == UserStyleUserLevel) 140 m_injectedUserStyleSheets.append(WTFMove(sheet)); 132 141 else 133 m_injectedAuthorStyleSheets.append(sheet); 134 135 sheet->contents().setIsUserStyleSheet(isUserStyleSheet); 136 sheet->contents().parseString(userStyleSheet.source()); 142 m_injectedAuthorStyleSheets.append(WTFMove(sheet)); 137 143 }); 138 144 … … 141 147 static NeverDestroyed<URL> captionsStyleSheetURL(ParsedURLString, "user-captions-override:01F6AF12-C3B0-4F70-AF5E-A3E00234DC23"); 142 148 143 RefPtr<CSSStyleSheet> sheet = CSSStyleSheet::createInline(const_cast<Document&>(m_document), captionsStyleSheetURL.get()); 144 m_injectedAuthorStyleSheets.append(sheet); 145 146 sheet->contents().setIsUserStyleSheet(false); 147 sheet->contents().parseString(owningPage->captionUserPreferencesStyleSheet()); 149 auto sheet = createExtensionsStyleSheet(const_cast<Document&>(m_document), captionsStyleSheetURL, owningPage->captionUserPreferencesStyleSheet(), UserStyleAuthorLevel); 150 151 m_injectedAuthorStyleSheets.append(WTFMove(sheet)); 148 152 } 149 153 } -
trunk/Source/WebCore/dom/InlineStyleSheetOwner.cpp
r207291 r207339 31 31 #include "StyleSheetContents.h" 32 32 #include "TextNodeTraversal.h" 33 #include <wtf/HashMap.h> 33 34 #include <wtf/NeverDestroyed.h> 34 35 35 36 namespace WebCore { 37 38 using InlineStyleSheetCacheKey = std::pair<String, CSSParserContext>; 39 using InlineStyleSheetCache = HashMap<InlineStyleSheetCacheKey, RefPtr<StyleSheetContents>>; 40 41 static InlineStyleSheetCache& inlineStyleSheetCache() 42 { 43 static NeverDestroyed<InlineStyleSheetCache> cache; 44 return cache; 45 } 46 47 static CSSParserContext parserContextForForElement(const Element& element) 48 { 49 auto* shadowRoot = element.containingShadowRoot(); 50 // User agent shadow trees can't contain document-relative URLs. Use blank URL as base allowing cross-document sharing. 51 auto& baseURL = shadowRoot && shadowRoot->mode() == ShadowRoot::Mode::UserAgent ? blankURL() : element.document().baseURL(); 52 53 return CSSParserContext { element.document(), baseURL, element.document().encoding() }; 54 } 55 56 static Optional<InlineStyleSheetCacheKey> makeInlineStyleSheetCacheKey(const String& text, const Element& element) 57 { 58 // Only cache for shadow trees. Main document inline stylesheets are generally unique and can't be shared between documents. 59 // FIXME: This could be relaxed when a stylesheet does not contain document-relative URLs (or #urls). 60 if (!element.isInShadowTree()) 61 return { }; 62 63 return std::make_pair(text, parserContextForForElement(element)); 64 } 36 65 37 66 InlineStyleSheetOwner::InlineStyleSheetOwner(Document& document, bool createdByParser) … … 153 182 m_styleScope->addPendingSheet(); 154 183 184 auto cacheKey = makeInlineStyleSheetCacheKey(text, element); 185 if (cacheKey) { 186 if (auto* cachedSheet = inlineStyleSheetCache().get(*cacheKey)) { 187 ASSERT(cachedSheet->isCacheable()); 188 m_sheet = CSSStyleSheet::createInline(*cachedSheet, element, m_startTextPosition); 189 m_sheet->setMediaQueries(mediaQueries.releaseNonNull()); 190 m_sheet->setTitle(element.title()); 191 192 sheetLoaded(element); 193 element.notifyLoadedSheetAndAllCriticalSubresources(false); 194 return; 195 } 196 } 197 155 198 m_loading = true; 156 199 157 m_sheet = CSSStyleSheet::createInline(element, URL(), m_startTextPosition, document.encoding()); 200 auto contents = StyleSheetContents::create(String(), parserContextForForElement(element)); 201 202 m_sheet = CSSStyleSheet::createInline(contents.get(), element, m_startTextPosition); 158 203 m_sheet->setMediaQueries(mediaQueries.releaseNonNull()); 159 204 m_sheet->setTitle(element.title()); 160 m_sheet->contents().parseStringAtPosition(text, m_startTextPosition, m_isParsingChildren); 205 206 contents->parseStringAtPosition(text, m_startTextPosition, m_isParsingChildren); 161 207 162 208 m_loading = false; 163 209 164 if (m_sheet) 165 m_sheet->contents().checkLoaded(); 210 contents->checkLoaded(); 211 212 if (cacheKey && contents->isCacheable()) { 213 inlineStyleSheetCache().add(*cacheKey, &m_sheet->contents()); 214 215 // Prevent pathological growth. 216 const size_t maximumInlineStyleSheetCacheSize = 50; 217 if (inlineStyleSheetCache().size() > maximumInlineStyleSheetCacheSize) 218 inlineStyleSheetCache().remove(inlineStyleSheetCache().begin()); 219 } 166 220 } 167 221 … … 190 244 } 191 245 192 } 246 void InlineStyleSheetOwner::clearCache() 247 { 248 inlineStyleSheetCache().clear(); 249 } 250 251 } -
trunk/Source/WebCore/dom/InlineStyleSheetOwner.h
r207291 r207339 53 53 Style::Scope* styleScope() { return m_styleScope; } 54 54 55 static void clearCache(); 56 55 57 private: 56 58 void createSheet(Element&, const String& text); -
trunk/Source/WebCore/platform/MemoryPressureHandler.cpp
r207291 r207339 34 34 #include "GCController.h" 35 35 #include "HTMLMediaElement.h" 36 #include "InlineStyleSheetOwner.h" 36 37 #include "InspectorInstrumentation.h" 37 38 #include "Logging.h" … … 104 105 StyledElement::clearPresentationAttributeCache(); 105 106 } 107 108 { 109 ReliefLogger log("Clear inline stylesheet cache"); 110 InlineStyleSheetOwner::clearCache(); 111 } 106 112 } 107 113
Note:
See TracChangeset
for help on using the changeset viewer.