Commit 62e3c1aa authored by adamk@chromium.org's avatar adamk@chromium.org

Move inline stylesheet cache decision making from StyleSheetContents to StyleEngine

This separates the decisions about caching StyleSheetContents for <style> elements
from those related to <link> elements. This makes the code clearer as there are
fewer conditions that could cause uncacheability (for example, the StyleSheetContents
for <style> elements could never be for an @import rule).

And since the <style> cache is per-StyleEngine (and thus per-Document), the
<style> case can now safely cache stylesheets that include @media rules.
This speeds up the included performance test from ~90ms on my Z620 to ~50ms,
and improves the biggest block of chromestatus.com load performance by ~20%.

This patch also cleans up StyleSheetContents a bit, collapsing the maybeCacheable()
method into isCacheable() and making appropriate accessors const.

BUG=342507

Review URL: https://codereview.chromium.org/196133034

git-svn-id: svn://svn.chromium.org/blink/trunk@169610 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent 83b6d615
<!doctype html>
<script src="../resources/runner.js"></script>
<script>
var listSize = 1000;
window.onload = function() {
PerfTestRunner.measureTime({
run: function() {
var list = document.querySelector('#list');
var tmpl = document.querySelector("#tmpl");
list.innerHTML = '';
var start = PerfTestRunner.now();
var i = 0;
do {
var host = document.createElement('div');
var root = host.createShadowRoot();
root.appendChild(tmpl.content.cloneNode(true));
var light = document.createElement('div');
list.appendChild(host);
} while (++i < listSize);
document.body.offsetHeight;
return PerfTestRunner.now() - start;
}
});
}
</script>
<template id="tmpl">
<style>
@media (max-width: 600px) {
div { color: red; }
}
.foo { color: black; }
.bar { color: blue; }
.baz { color: green; }
.bat { color: orange; }
</style>
<div>item</div>
</template>
<section id="list"></section>
......@@ -113,8 +113,11 @@ void StyleSheetContents::setHasSyntacticallyValidCSSHeader(bool isValidCss)
m_hasSyntacticallyValidCSSHeader = isValidCss;
}
bool StyleSheetContents::maybeCacheable() const
bool StyleSheetContents::isCacheable() const
{
// This would require dealing with multiple clients for load callbacks.
if (!loadCompleted())
return false;
// FIXME: StyleSheets with media queries can't be cached because their RuleSet
// is processed differently based off the media queries, which might resolve
// differently depending on the context of the parent CSSStyleSheet (e.g.
......@@ -140,14 +143,6 @@ bool StyleSheetContents::maybeCacheable() const
return true;
}
bool StyleSheetContents::isCacheable() const
{
// This would require dealing with multiple clients for load callbacks.
if (!loadCompleted())
return false;
return maybeCacheable();
}
void StyleSheetContents::parserAppendRule(PassRefPtrWillBeRawPtr<StyleRuleBase> rule)
{
ASSERT(!rule->isCharsetRule());
......@@ -589,8 +584,6 @@ void StyleSheetContents::clientLoadStarted(CSSStyleSheet* sheet)
void StyleSheetContents::removeSheetFromCache(Document* document)
{
ASSERT(document);
if (!maybeCacheable())
return;
document->styleEngine()->removeSheet(this);
}
......
......@@ -71,7 +71,6 @@ public:
bool parseStringAtPosition(const String&, const TextPosition&, bool);
bool isCacheable() const;
bool maybeCacheable() const;
bool isLoading() const;
......@@ -154,7 +153,9 @@ public:
void removedFromMemoryCache();
void setHasMediaQueries();
bool hasMediaQueries() { return m_hasMediaQueries; }
bool hasMediaQueries() const { return m_hasMediaQueries; }
bool didLoadErrorOccur() const { return m_didLoadErrorOccur; }
void shrinkToFit();
RuleSet& ruleSet() { ASSERT(m_ruleSet); return *m_ruleSet.get(); }
......
......@@ -562,6 +562,21 @@ void StyleEngine::markDocumentDirty()
m_document.import()->master()->styleEngine()->markDocumentDirty();
}
static bool isCacheableForStyleElement(const StyleSheetContents& contents)
{
// FIXME: Support copying import rules.
if (!contents.importRules().isEmpty())
return false;
// Until import rules are supported in cached sheets it's not possible for loading to fail.
ASSERT(!contents.didLoadErrorOccur());
// It is not the original sheet anymore.
if (contents.isMutable())
return false;
if (!contents.hasSyntacticallyValidCSSHeader())
return false;
return true;
}
PassRefPtrWillBeRawPtr<CSSStyleSheet> StyleEngine::createSheet(Element* e, const String& text, TextPosition startPosition, bool createdByParser)
{
RefPtrWillBeRawPtr<CSSStyleSheet> styleSheet;
......@@ -574,14 +589,16 @@ PassRefPtrWillBeRawPtr<CSSStyleSheet> StyleEngine::createSheet(Element* e, const
HashMap<AtomicString, StyleSheetContents*>::AddResult result = m_textToSheetCache.add(textContent, 0);
if (result.isNewEntry || !result.storedValue->value) {
styleSheet = StyleEngine::parseSheet(e, text, startPosition, createdByParser);
if (result.isNewEntry && styleSheet->contents()->maybeCacheable()) {
if (result.isNewEntry && isCacheableForStyleElement(*styleSheet->contents())) {
result.storedValue->value = styleSheet->contents();
m_sheetToTextCache.add(styleSheet->contents(), textContent);
}
} else {
ASSERT(result.storedValue->value->maybeCacheable());
ASSERT(result.storedValue->value->singleOwnerDocument() == e->document());
styleSheet = CSSStyleSheet::createInline(result.storedValue->value, e, startPosition);
StyleSheetContents* contents = result.storedValue->value;
ASSERT(contents);
ASSERT(isCacheableForStyleElement(*contents));
ASSERT(contents->singleOwnerDocument() == e->document());
styleSheet = CSSStyleSheet::createInline(contents, e, startPosition);
}
} else {
// FIXME: currently we don't cache StyleSheetContents inQuirksMode.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment