Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(281)

Side by Side Diff: third_party/WebKit/Source/core/css/parser/CSSParserImpl.cpp

Issue 2315923002: Lazy Parse CSS (Closed)
Patch Set: CL for src perf tryjob to run page_cycler_v2.typical_25 benchmark on all-android platform(s) Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "core/css/parser/CSSParserImpl.h" 5 #include "core/css/parser/CSSParserImpl.h"
6 6
7 #include "core/css/CSSCustomIdentValue.h" 7 #include "core/css/CSSCustomIdentValue.h"
8 #include "core/css/CSSCustomPropertyDeclaration.h" 8 #include "core/css/CSSCustomPropertyDeclaration.h"
9 #include "core/css/CSSKeyframesRule.h" 9 #include "core/css/CSSKeyframesRule.h"
10 #include "core/css/CSSStyleSheet.h" 10 #include "core/css/CSSStyleSheet.h"
(...skipping 16 matching lines...) Expand all
27 #include "core/dom/Element.h" 27 #include "core/dom/Element.h"
28 #include "core/frame/Deprecation.h" 28 #include "core/frame/Deprecation.h"
29 #include "core/frame/UseCounter.h" 29 #include "core/frame/UseCounter.h"
30 #include "platform/TraceEvent.h" 30 #include "platform/TraceEvent.h"
31 #include "wtf/PtrUtil.h" 31 #include "wtf/PtrUtil.h"
32 #include <bitset> 32 #include <bitset>
33 #include <memory> 33 #include <memory>
34 34
35 namespace blink { 35 namespace blink {
36 36
37 CSSParserImpl::CSSParserImpl(const CSSParserContext& context, StyleSheetContents * styleSheet) 37 CSSParserImpl::CSSParserImpl(const CSSParserContext& context, StyleSheetContents * styleSheet, bool deferPropertyParsing)
38 : m_context(context) 38 : m_context(context)
39 , m_styleSheet(styleSheet) 39 , m_styleSheet(styleSheet)
40 , m_observerWrapper(nullptr) 40 , m_observerWrapper(nullptr)
41 , m_deferPropertyParsing(deferPropertyParsing)
41 { 42 {
42 } 43 }
43 44
44 bool CSSParserImpl::parseValue(MutableStylePropertySet* declaration, CSSProperty ID unresolvedProperty, const String& string, bool important, const CSSParserCont ext& context) 45 bool CSSParserImpl::parseValue(MutableStylePropertySet* declaration, CSSProperty ID unresolvedProperty, const String& string, bool important, const CSSParserCont ext& context)
45 { 46 {
46 CSSParserImpl parser(context); 47 CSSParserImpl parser(context);
47 StyleRule::RuleType ruleType = StyleRule::Style; 48 StyleRule::RuleType ruleType = StyleRule::Style;
48 if (declaration->cssParserMode() == CSSViewportRuleMode) 49 if (declaration->cssParserMode() == CSSViewportRuleMode)
49 ruleType = StyleRule::Viewport; 50 ruleType = StyleRule::Viewport;
50 CSSTokenizer::Scope scope(string); 51 CSSTokenizer::Scope scope(string);
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
152 else 153 else
153 rule = parser.consumeQualifiedRule(range, allowedRules); 154 rule = parser.consumeQualifiedRule(range, allowedRules);
154 if (!rule) 155 if (!rule)
155 return nullptr; // Parse error, failed to consume rule 156 return nullptr; // Parse error, failed to consume rule
156 range.consumeWhitespace(); 157 range.consumeWhitespace();
157 if (!rule || !range.atEnd()) 158 if (!rule || !range.atEnd())
158 return nullptr; // Parse error, trailing garbage 159 return nullptr; // Parse error, trailing garbage
159 return rule; 160 return rule;
160 } 161 }
161 162
162 void CSSParserImpl::parseStyleSheet(const String& string, const CSSParserContext & context, StyleSheetContents* styleSheet) 163 void CSSParserImpl::parseStyleSheet(const String& string, const CSSParserContext & context, StyleSheetContents* styleSheet, bool deferPropertyParsing)
163 { 164 {
164 TRACE_EVENT_BEGIN2( 165 TRACE_EVENT_BEGIN2(
165 "blink,blink_style", "CSSParserImpl::parseStyleSheet", 166 "blink,blink_style", "CSSParserImpl::parseStyleSheet",
166 "baseUrl", context.baseURL().getString().utf8(), 167 "baseUrl", context.baseURL().getString().utf8(),
167 "mode", context.mode()); 168 "mode", context.mode());
168 169
169 TRACE_EVENT_BEGIN0("blink,blink_style", "CSSParserImpl::parseStyleSheet.toke nize"); 170 TRACE_EVENT_BEGIN0("blink,blink_style", "CSSParserImpl::parseStyleSheet.toke nize");
170 CSSTokenizer::Scope scope(string); 171 CSSTokenizer::Scope scope(string);
171 TRACE_EVENT_END0("blink,blink_style", "CSSParserImpl::parseStyleSheet.tokeni ze"); 172 TRACE_EVENT_END0("blink,blink_style", "CSSParserImpl::parseStyleSheet.tokeni ze");
172 173
173 TRACE_EVENT_BEGIN0("blink,blink_style", "CSSParserImpl::parseStyleSheet.pars e"); 174 TRACE_EVENT_BEGIN0("blink,blink_style", "CSSParserImpl::parseStyleSheet.pars e");
174 CSSParserImpl parser(context, styleSheet); 175 CSSParserImpl parser(context, styleSheet, deferPropertyParsing);
175 bool firstRuleValid = parser.consumeRuleList(scope.tokenRange(), TopLevelRul eList, [&styleSheet](StyleRuleBase* rule) { 176 bool firstRuleValid = parser.consumeRuleList(scope.tokenRange(), TopLevelRul eList, [&styleSheet](StyleRuleBase* rule) {
176 if (rule->isCharsetRule()) 177 if (rule->isCharsetRule())
177 return; 178 return;
178 styleSheet->parserAppendRule(rule); 179 styleSheet->parserAppendRule(rule);
179 }); 180 });
180 styleSheet->setHasSyntacticallyValidCSSHeader(firstRuleValid); 181 styleSheet->setHasSyntacticallyValidCSSHeader(firstRuleValid);
182
183 // For lazy parsing the owning contents requires ownership of strings the
184 // scope allocates.
185 if (deferPropertyParsing)
186 styleSheet->takeEscapedStrings(scope.releaseEscapedStrings());
187
181 TRACE_EVENT_END0("blink,blink_style", "CSSParserImpl::parseStyleSheet.parse" ); 188 TRACE_EVENT_END0("blink,blink_style", "CSSParserImpl::parseStyleSheet.parse" );
182 189
183 TRACE_EVENT_END2( 190 TRACE_EVENT_END2(
184 "blink,blink_style", "CSSParserImpl::parseStyleSheet", 191 "blink,blink_style", "CSSParserImpl::parseStyleSheet",
185 "tokenCount", scope.tokenCount(), 192 "tokenCount", scope.tokenCount(),
186 "length", string.length()); 193 "length", string.length());
187 } 194 }
188 195
189 CSSSelectorList CSSParserImpl::parsePageSelector(CSSParserTokenRange range, Styl eSheetContents* styleSheet) 196 CSSSelectorList CSSParserImpl::parsePageSelector(CSSParserTokenRange range, Styl eSheetContents* styleSheet)
190 { 197 {
(...skipping 476 matching lines...) Expand 10 before | Expand all | Expand 10 after
667 selectors.consumeComponentValue(); 674 selectors.consumeComponentValue();
668 CSSParserTokenRange selector = selectors.makeSubRange(selectorStart, &se lectors.peek()); 675 CSSParserTokenRange selector = selectors.makeSubRange(selectorStart, &se lectors.peek());
669 selectors.consumeIncludingWhitespace(); 676 selectors.consumeIncludingWhitespace();
670 677
671 wrapper.observer().observeSelector(wrapper.startOffset(selector), wrappe r.endOffset(selector)); 678 wrapper.observer().observeSelector(wrapper.startOffset(selector), wrappe r.endOffset(selector));
672 } 679 }
673 680
674 wrapper.observer().endRuleHeader(wrapper.endOffset(originalRange)); 681 wrapper.observer().endRuleHeader(wrapper.endOffset(originalRange));
675 } 682 }
676 683
677
678 StyleRule* CSSParserImpl::consumeStyleRule(CSSParserTokenRange prelude, CSSParse rTokenRange block) 684 StyleRule* CSSParserImpl::consumeStyleRule(CSSParserTokenRange prelude, CSSParse rTokenRange block)
679 { 685 {
680 CSSSelectorList selectorList = CSSSelectorParser::parseSelector(prelude, m_c ontext, m_styleSheet); 686 CSSSelectorList selectorList = CSSSelectorParser::parseSelector(prelude, m_c ontext, m_styleSheet);
681 if (!selectorList.isValid()) 687 if (!selectorList.isValid())
682 return nullptr; // Parse error, invalid selector list 688 return nullptr; // Parse error, invalid selector list
683 689
684 if (m_observerWrapper) 690 // TODO(csharrison): How should we lazily parse css that needs the observer?
691 if (m_observerWrapper) {
685 observeSelectors(*m_observerWrapper, prelude); 692 observeSelectors(*m_observerWrapper, prelude);
686 693 } else if (m_deferPropertyParsing && shouldLazilyParseProperties(selectorLis t, block)) {
694 DCHECK(m_styleSheet);
695 return StyleRule::createLazy(std::move(selectorList), createDeferredProp ertiesClosure(block, m_styleSheet->parserContext(), m_context.useCounter()));
696 }
687 consumeDeclarationList(block, StyleRule::Style); 697 consumeDeclarationList(block, StyleRule::Style);
688
689 return StyleRule::create(std::move(selectorList), createStylePropertySet(m_p arsedProperties, m_context.mode())); 698 return StyleRule::create(std::move(selectorList), createStylePropertySet(m_p arsedProperties, m_context.mode()));
690 } 699 }
691 700
692 void CSSParserImpl::consumeDeclarationList(CSSParserTokenRange range, StyleRule: :RuleType ruleType) 701 void CSSParserImpl::consumeDeclarationList(CSSParserTokenRange range, StyleRule: :RuleType ruleType)
693 { 702 {
694 ASSERT(m_parsedProperties.isEmpty()); 703 ASSERT(m_parsedProperties.isEmpty());
695 704
696 bool useObserver = m_observerWrapper && (ruleType == StyleRule::Style || rul eType == StyleRule::Keyframe); 705 bool useObserver = m_observerWrapper && (ruleType == StyleRule::Style || rul eType == StyleRule::Keyframe);
697 if (useObserver) { 706 if (useObserver) {
698 m_observerWrapper->observer().startRuleBody(m_observerWrapper->previousT okenStartOffset(range)); 707 m_observerWrapper->observer().startRuleBody(m_observerWrapper->previousT okenStartOffset(range));
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
813 result->append(1); 822 result->append(1);
814 else 823 else
815 return nullptr; // Parser error, invalid value in keyframe selector 824 return nullptr; // Parser error, invalid value in keyframe selector
816 if (range.atEnd()) 825 if (range.atEnd())
817 return result; 826 return result;
818 if (range.consume().type() != CommaToken) 827 if (range.consume().type() != CommaToken)
819 return nullptr; // Parser error 828 return nullptr; // Parser error
820 } 829 }
821 } 830 }
822 831
832 // The closure created here must not outlive the underlying StyleSheetContents,
833 // as it has non retaining references to the strings backing the tokens, as
834 // well as the parser context.
835 std::unique_ptr<DeferredPropertiesClosure> CSSParserImpl::createDeferredProperti esClosure(CSSParserTokenRange block, const CSSParserContext& sheetContext, UseCo unter* counter)
836 {
837 // Note: there may be optimizations to be had in allocating so many Vectors
838 // to store the token copies. One idea is to allocate a large Vector in
839 // parseStyleSheet and immediately free it, so we don't go through the slow
840 // path in PartitionAlloc.
841 Vector<CSSParserToken, 0u> tokens;
842
843 // Reserve capacity to minimize heap bloat.
844 size_t length = block.end() - block.begin();
845 tokens.reserveCapacity(length);
846 tokens.append(block.begin(), length);
847
848 return WTF::bind(&CSSParserImpl::parseDeclarationListForLazyStyle, WTF::pass ed(std::move(tokens)), WTF::unretained(&sheetContext), WTF::unretained(counter)) ;
849 }
850
851 StylePropertySet* CSSParserImpl::parseDeclarationListForLazyStyle(Vector<CSSPars erToken> block, const CSSParserContext* sheetContext, UseCounter* counter)
852 {
853 CSSParserContext context(*sheetContext, counter);
854 CSSParserImpl parser(context);
855 parser.consumeDeclarationList(block, StyleRule::Style);
856 return createStylePropertySet(parser.m_parsedProperties, context.mode());
857 }
858
859 // Disallow lazy parsing for blocks which have
860 // - before/after in their selector list. This ensures we don't cause a
861 // collectFeatures() when we trigger parsing for attr() functions which would
862 // trigger expensive invalidation propagation.
863 // - Empty property sets (so that emptiness can be established without forcing
864 // a strict point.
865 bool CSSParserImpl::shouldLazilyParseProperties(const CSSSelectorList& selectors , CSSParserTokenRange block)
Timothy Loh 2016/09/27 05:15:45 Could just be static and not on CSSParserImpl I gu
Charlie Harrison 2016/09/27 13:22:01 Do you mean in an anonymous namespace? It's alread
866 {
867 if (static_cast<size_t>(block.end() - block.begin()) == 0)
Timothy Loh 2016/09/27 05:15:45 if (block.atEnd()), but see other comment.
Charlie Harrison 2016/09/27 13:22:01 Deleted this code.
868 return false;
869 for (const auto* s = selectors.first(); s; s = CSSSelectorList::next(*s)) {
870 const CSSSelector::PseudoType type(s->getPseudoType());
871 if (type == CSSSelector::PseudoBefore || type == CSSSelector::PseudoAfte r)
872 return false;
873 }
874 return true;
875 }
876
823 } // namespace blink 877 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698