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

Unified 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, 3 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 side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/core/css/parser/CSSParserImpl.cpp
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParserImpl.cpp b/third_party/WebKit/Source/core/css/parser/CSSParserImpl.cpp
index f5bd2e8b8f5f2e1f04e700fea4bbf5833d8ffc5c..42262eb30a6bed4ec3cddd330083f3d09c9c1328 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSParserImpl.cpp
+++ b/third_party/WebKit/Source/core/css/parser/CSSParserImpl.cpp
@@ -34,10 +34,11 @@
namespace blink {
-CSSParserImpl::CSSParserImpl(const CSSParserContext& context, StyleSheetContents* styleSheet)
-: m_context(context)
-, m_styleSheet(styleSheet)
-, m_observerWrapper(nullptr)
+CSSParserImpl::CSSParserImpl(const CSSParserContext& context, StyleSheetContents* styleSheet, bool deferPropertyParsing)
+ : m_context(context)
+ , m_styleSheet(styleSheet)
+ , m_observerWrapper(nullptr)
+ , m_deferPropertyParsing(deferPropertyParsing)
{
}
@@ -159,7 +160,7 @@ StyleRuleBase* CSSParserImpl::parseRule(const String& string, const CSSParserCon
return rule;
}
-void CSSParserImpl::parseStyleSheet(const String& string, const CSSParserContext& context, StyleSheetContents* styleSheet)
+void CSSParserImpl::parseStyleSheet(const String& string, const CSSParserContext& context, StyleSheetContents* styleSheet, bool deferPropertyParsing)
{
TRACE_EVENT_BEGIN2(
"blink,blink_style", "CSSParserImpl::parseStyleSheet",
@@ -171,13 +172,19 @@ void CSSParserImpl::parseStyleSheet(const String& string, const CSSParserContext
TRACE_EVENT_END0("blink,blink_style", "CSSParserImpl::parseStyleSheet.tokenize");
TRACE_EVENT_BEGIN0("blink,blink_style", "CSSParserImpl::parseStyleSheet.parse");
- CSSParserImpl parser(context, styleSheet);
+ CSSParserImpl parser(context, styleSheet, deferPropertyParsing);
bool firstRuleValid = parser.consumeRuleList(scope.tokenRange(), TopLevelRuleList, [&styleSheet](StyleRuleBase* rule) {
if (rule->isCharsetRule())
return;
styleSheet->parserAppendRule(rule);
});
styleSheet->setHasSyntacticallyValidCSSHeader(firstRuleValid);
+
+ // For lazy parsing the owning contents requires ownership of strings the
+ // scope allocates.
+ if (deferPropertyParsing)
+ styleSheet->takeEscapedStrings(scope.releaseEscapedStrings());
+
TRACE_EVENT_END0("blink,blink_style", "CSSParserImpl::parseStyleSheet.parse");
TRACE_EVENT_END2(
@@ -674,18 +681,20 @@ static void observeSelectors(CSSParserObserverWrapper& wrapper, CSSParserTokenRa
wrapper.observer().endRuleHeader(wrapper.endOffset(originalRange));
}
-
StyleRule* CSSParserImpl::consumeStyleRule(CSSParserTokenRange prelude, CSSParserTokenRange block)
{
CSSSelectorList selectorList = CSSSelectorParser::parseSelector(prelude, m_context, m_styleSheet);
if (!selectorList.isValid())
return nullptr; // Parse error, invalid selector list
- if (m_observerWrapper)
+ // TODO(csharrison): How should we lazily parse css that needs the observer?
+ if (m_observerWrapper) {
observeSelectors(*m_observerWrapper, prelude);
-
+ } else if (m_deferPropertyParsing && shouldLazilyParseProperties(selectorList, block)) {
+ DCHECK(m_styleSheet);
+ return StyleRule::createLazy(std::move(selectorList), createDeferredPropertiesClosure(block, m_styleSheet->parserContext(), m_context.useCounter()));
+ }
consumeDeclarationList(block, StyleRule::Style);
-
return StyleRule::create(std::move(selectorList), createStylePropertySet(m_parsedProperties, m_context.mode()));
}
@@ -820,4 +829,49 @@ std::unique_ptr<Vector<double>> CSSParserImpl::consumeKeyframeKeyList(CSSParserT
}
}
+// The closure created here must not outlive the underlying StyleSheetContents,
+// as it has non retaining references to the strings backing the tokens, as
+// well as the parser context.
+std::unique_ptr<DeferredPropertiesClosure> CSSParserImpl::createDeferredPropertiesClosure(CSSParserTokenRange block, const CSSParserContext& sheetContext, UseCounter* counter)
+{
+ // Note: there may be optimizations to be had in allocating so many Vectors
+ // to store the token copies. One idea is to allocate a large Vector in
+ // parseStyleSheet and immediately free it, so we don't go through the slow
+ // path in PartitionAlloc.
+ Vector<CSSParserToken, 0u> tokens;
+
+ // Reserve capacity to minimize heap bloat.
+ size_t length = block.end() - block.begin();
+ tokens.reserveCapacity(length);
+ tokens.append(block.begin(), length);
+
+ return WTF::bind(&CSSParserImpl::parseDeclarationListForLazyStyle, WTF::passed(std::move(tokens)), WTF::unretained(&sheetContext), WTF::unretained(counter));
+}
+
+StylePropertySet* CSSParserImpl::parseDeclarationListForLazyStyle(Vector<CSSParserToken> block, const CSSParserContext* sheetContext, UseCounter* counter)
+{
+ CSSParserContext context(*sheetContext, counter);
+ CSSParserImpl parser(context);
+ parser.consumeDeclarationList(block, StyleRule::Style);
+ return createStylePropertySet(parser.m_parsedProperties, context.mode());
+}
+
+// Disallow lazy parsing for blocks which have
+// - before/after in their selector list. This ensures we don't cause a
+// collectFeatures() when we trigger parsing for attr() functions which would
+// trigger expensive invalidation propagation.
+// - Empty property sets (so that emptiness can be established without forcing
+// a strict point.
+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
+{
+ 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.
+ return false;
+ for (const auto* s = selectors.first(); s; s = CSSSelectorList::next(*s)) {
+ const CSSSelector::PseudoType type(s->getPseudoType());
+ if (type == CSSSelector::PseudoBefore || type == CSSSelector::PseudoAfter)
+ return false;
+ }
+ return true;
+}
+
} // namespace blink

Powered by Google App Engine
This is Rietveld 408576698