Diff
Modified: trunk/Source/WebCore/ChangeLog (98541 => 98542)
--- trunk/Source/WebCore/ChangeLog 2011-10-27 09:37:00 UTC (rev 98541)
+++ trunk/Source/WebCore/ChangeLog 2011-10-27 09:39:48 UTC (rev 98542)
@@ -1,3 +1,76 @@
+2011-10-27 Antti Koivisto <an...@apple.com>
+
+ Matched declaration cache
+ https://bugs.webkit.org/show_bug.cgi?id=70931
+
+ Reviewed by Darin Adler.
+
+ Sets of style declarations are applied repeatedly for different elements when calculating the document style.
+ The same set of applied declarations results in the same non-inherited style, independent of the element and
+ its context. We can use this to build a cache to speed up style applying and to share more style data for
+ reduced memory usage.
+
+ The patch reduces RenderStyle memory use ~40% and total memory use by ~7% over HTML5 spec load.
+ It is also ~10% progression in PerformanceTests/Parser/html5-full-render.html.
+
+ * css/CSSProperty.cpp:
+ (WebCore::CSSProperty::isInheritedProperty):
+ * css/CSSProperty.h:
+ (WebCore::CSSProperty::CSSProperty):
+ (WebCore::CSSProperty::isInherited):
+
+ We need to know which properties are inherited, something we didn't have available so far.
+
+ * css/CSSStyleSelector.cpp:
+ (WebCore::CSSStyleSelector::matchAllRules):
+
+ A set of declarations is only cacheable if it contains no element specific style. This way we
+ don't need to worry about cache invalidation. The whole style selector is reconstructed if the
+ stylesheets change, invalidating the cache too.
+
+ (WebCore::CSSStyleSelector::styleForElement):
+
+ Trigger image loads bit earlier so cached style will have them too.
+
+ (WebCore::CSSStyleSelector::applyDeclaration):
+ (WebCore::CSSStyleSelector::applyDeclarations):
+
+ Allow skipping over non-inherited properties.
+
+ (WebCore::CSSStyleSelector::computeDeclarationHash):
+
+ Hash function for declartion cache lookups.
+
+ (WebCore::operator==):
+ (WebCore::operator!=):
+ (WebCore::CSSStyleSelector::findFromMatchedDeclarationCache):
+
+ Lookup from cache.
+
+ (WebCore::CSSStyleSelector::addToMatchedDeclarationCache):
+
+ Add to cache.
+
+ (WebCore::CSSStyleSelector::applyMatchedDeclarations):
+
+ If cached style is found, copy the non-inherited properties from the cache and apply the inherited properties (if any) only.
+
+ Font and zoom changes force full applying as they can affect values of other properties (this can be relaxed later).
+
+ * css/CSSStyleSelector.h:
+ (WebCore::CSSStyleSelector::MatchResult::MatchResult):
+
+ Cacheability bit.
+
+ * rendering/style/RenderStyle.cpp:
+ (WebCore::RenderStyle::copyNonInheritedFrom):
+ * rendering/style/RenderStyle.h:
+ * rendering/style/SVGRenderStyle.cpp:
+ (WebCore::SVGRenderStyle::copyNonInheritedFrom):
+ * rendering/style/SVGRenderStyle.h:
+
+ Functions for assembling RenderStyle from non-inherited parts of the cached style.
+
2011-10-27 Andrey Kosyakov <ca...@chromium.org>
Web Inspector: [Extensions API] add ignoreCache flag to options of inspectedWindow.reload()
Modified: trunk/Source/WebCore/css/CSSProperty.cpp (98541 => 98542)
--- trunk/Source/WebCore/css/CSSProperty.cpp 2011-10-27 09:37:00 UTC (rev 98541)
+++ trunk/Source/WebCore/css/CSSProperty.cpp 2011-10-27 09:39:48 UTC (rev 98542)
@@ -282,4 +282,383 @@
}
}
+bool CSSProperty::isInheritedProperty(unsigned propertyID)
+{
+ switch (static_cast<CSSPropertyID>(propertyID)) {
+ case CSSPropertyBorderCollapse:
+ case CSSPropertyBorderSpacing:
+ case CSSPropertyCaptionSide:
+ case CSSPropertyColor:
+ case CSSPropertyCursor:
+ case CSSPropertyDirection:
+ case CSSPropertyEmptyCells:
+ case CSSPropertyFont:
+ case CSSPropertyFontFamily:
+ case CSSPropertyFontSize:
+ case CSSPropertyFontStyle:
+ case CSSPropertyFontVariant:
+ case CSSPropertyFontWeight:
+ case CSSPropertyImageRendering:
+ case CSSPropertyLetterSpacing:
+ case CSSPropertyLineHeight:
+ case CSSPropertyListStyle:
+ case CSSPropertyListStyleImage:
+ case CSSPropertyListStyleType:
+ case CSSPropertyListStylePosition:
+ case CSSPropertyOrphans:
+ case CSSPropertyPointerEvents:
+ case CSSPropertyQuotes:
+ case CSSPropertyResize:
+ case CSSPropertySpeak:
+ case CSSPropertyTextAlign:
+ case CSSPropertyTextDecoration:
+ case CSSPropertyTextIndent:
+ case CSSPropertyTextRendering:
+ case CSSPropertyTextShadow:
+ case CSSPropertyTextTransform:
+ case CSSPropertyVisibility:
+ case CSSPropertyWebkitBorderHorizontalSpacing:
+ case CSSPropertyWebkitBorderVerticalSpacing:
+ case CSSPropertyWebkitBoxDirection:
+ case CSSPropertyWebkitColorCorrection:
+ case CSSPropertyWebkitLocale:
+ case CSSPropertyWebkitHighlight:
+ case CSSPropertyWebkitHyphenateCharacter:
+ case CSSPropertyWebkitHyphenateLimitAfter:
+ case CSSPropertyWebkitHyphenateLimitBefore:
+ case CSSPropertyWebkitHyphenateLimitLines:
+ case CSSPropertyWebkitHyphens:
+ case CSSPropertyWebkitLineBoxContain:
+ case CSSPropertyWebkitLineBreak:
+ case CSSPropertyWebkitNbspMode:
+ case CSSPropertyWebkitRtlOrdering:
+ case CSSPropertyWebkitTextCombine:
+ case CSSPropertyWebkitTextDecorationsInEffect:
+ case CSSPropertyWebkitTextEmphasis:
+ case CSSPropertyWebkitTextEmphasisColor:
+ case CSSPropertyWebkitTextEmphasisPosition:
+ case CSSPropertyWebkitTextEmphasisStyle:
+ case CSSPropertyWebkitTextFillColor:
+ case CSSPropertyWebkitTextSecurity:
+ case CSSPropertyWebkitTextSizeAdjust:
+ case CSSPropertyWebkitTextStroke:
+ case CSSPropertyWebkitTextStrokeColor:
+ case CSSPropertyWebkitTextStrokeWidth:
+ case CSSPropertyWebkitUserModify:
+ case CSSPropertyWebkitUserSelect:
+ case CSSPropertyWebkitWritingMode:
+ case CSSPropertyWhiteSpace:
+ case CSSPropertyWidows:
+ case CSSPropertyWordBreak:
+ case CSSPropertyWordSpacing:
+ case CSSPropertyWordWrap:
+#if ENABLE(SVG)
+ case CSSPropertyClipRule:
+ case CSSPropertyColorInterpolation:
+ case CSSPropertyColorInterpolationFilters:
+ case CSSPropertyColorRendering:
+ case CSSPropertyFill:
+ case CSSPropertyFillOpacity:
+ case CSSPropertyFillRule:
+ case CSSPropertyGlyphOrientationHorizontal:
+ case CSSPropertyGlyphOrientationVertical:
+ case CSSPropertyKerning:
+ case CSSPropertyMarker:
+ case CSSPropertyMarkerEnd:
+ case CSSPropertyMarkerMid:
+ case CSSPropertyMarkerStart:
+ case CSSPropertyStroke:
+ case CSSPropertyStrokeDasharray:
+ case CSSPropertyStrokeDashoffset:
+ case CSSPropertyStrokeLinecap:
+ case CSSPropertyStrokeLinejoin:
+ case CSSPropertyStrokeMiterlimit:
+ case CSSPropertyStrokeOpacity:
+ case CSSPropertyStrokeWidth:
+ case CSSPropertyShapeRendering:
+ case CSSPropertyTextAnchor:
+ case CSSPropertyWritingMode:
+#endif
+#if ENABLE(TOUCH_EVENTS)
+ case CSSPropertyWebkitTapHighlightColor:
+#endif
+ return true;
+ case CSSPropertyDisplay:
+ case CSSPropertyWebkitFontFeatureSettings:
+ case CSSPropertyWebkitFontSmoothing:
+ case CSSPropertyWebkitTextOrientation:
+ case CSSPropertyZoom:
+ case CSSPropertyBackground:
+ case CSSPropertyBackgroundAttachment:
+ case CSSPropertyBackgroundClip:
+ case CSSPropertyBackgroundColor:
+ case CSSPropertyBackgroundImage:
+ case CSSPropertyBackgroundOrigin:
+ case CSSPropertyBackgroundPosition:
+ case CSSPropertyBackgroundPositionX:
+ case CSSPropertyBackgroundPositionY:
+ case CSSPropertyBackgroundRepeat:
+ case CSSPropertyBackgroundRepeatX:
+ case CSSPropertyBackgroundRepeatY:
+ case CSSPropertyBackgroundSize:
+ case CSSPropertyBorder:
+ case CSSPropertyBorderBottom:
+ case CSSPropertyBorderBottomColor:
+ case CSSPropertyBorderBottomLeftRadius:
+ case CSSPropertyBorderBottomRightRadius:
+ case CSSPropertyBorderBottomStyle:
+ case CSSPropertyBorderBottomWidth:
+ case CSSPropertyBorderColor:
+ case CSSPropertyBorderImage:
+ case CSSPropertyBorderImageOutset:
+ case CSSPropertyBorderImageRepeat:
+ case CSSPropertyBorderImageSlice:
+ case CSSPropertyBorderImageSource:
+ case CSSPropertyBorderImageWidth:
+ case CSSPropertyBorderLeft:
+ case CSSPropertyBorderLeftColor:
+ case CSSPropertyBorderLeftStyle:
+ case CSSPropertyBorderLeftWidth:
+ case CSSPropertyBorderRadius:
+ case CSSPropertyBorderRight:
+ case CSSPropertyBorderRightColor:
+ case CSSPropertyBorderRightStyle:
+ case CSSPropertyBorderRightWidth:
+ case CSSPropertyBorderStyle:
+ case CSSPropertyBorderTop:
+ case CSSPropertyBorderTopColor:
+ case CSSPropertyBorderTopLeftRadius:
+ case CSSPropertyBorderTopRightRadius:
+ case CSSPropertyBorderTopStyle:
+ case CSSPropertyBorderTopWidth:
+ case CSSPropertyBorderWidth:
+ case CSSPropertyBottom:
+ case CSSPropertyBoxShadow:
+ case CSSPropertyBoxSizing:
+ case CSSPropertyClear:
+ case CSSPropertyClip:
+ case CSSPropertyContent:
+ case CSSPropertyCounterIncrement:
+ case CSSPropertyCounterReset:
+ case CSSPropertyFloat:
+ case CSSPropertyFontStretch:
+ case CSSPropertyHeight:
+ case CSSPropertyLeft:
+ case CSSPropertyMargin:
+ case CSSPropertyMarginBottom:
+ case CSSPropertyMarginLeft:
+ case CSSPropertyMarginRight:
+ case CSSPropertyMarginTop:
+ case CSSPropertyMaxHeight:
+ case CSSPropertyMaxWidth:
+ case CSSPropertyMinHeight:
+ case CSSPropertyMinWidth:
+ case CSSPropertyOpacity:
+ case CSSPropertyOutline:
+ case CSSPropertyOutlineColor:
+ case CSSPropertyOutlineOffset:
+ case CSSPropertyOutlineStyle:
+ case CSSPropertyOutlineWidth:
+ case CSSPropertyOverflow:
+ case CSSPropertyOverflowX:
+ case CSSPropertyOverflowY:
+ case CSSPropertyPadding:
+ case CSSPropertyPaddingBottom:
+ case CSSPropertyPaddingLeft:
+ case CSSPropertyPaddingRight:
+ case CSSPropertyPaddingTop:
+ case CSSPropertyPage:
+ case CSSPropertyPageBreakAfter:
+ case CSSPropertyPageBreakBefore:
+ case CSSPropertyPageBreakInside:
+ case CSSPropertyPosition:
+ case CSSPropertyRight:
+ case CSSPropertySize:
+ case CSSPropertySrc:
+ case CSSPropertyTableLayout:
+ case CSSPropertyTextLineThrough:
+ case CSSPropertyTextLineThroughColor:
+ case CSSPropertyTextLineThroughMode:
+ case CSSPropertyTextLineThroughStyle:
+ case CSSPropertyTextLineThroughWidth:
+ case CSSPropertyTextOverflow:
+ case CSSPropertyTextOverline:
+ case CSSPropertyTextOverlineColor:
+ case CSSPropertyTextOverlineMode:
+ case CSSPropertyTextOverlineStyle:
+ case CSSPropertyTextOverlineWidth:
+ case CSSPropertyTextUnderline:
+ case CSSPropertyTextUnderlineColor:
+ case CSSPropertyTextUnderlineMode:
+ case CSSPropertyTextUnderlineStyle:
+ case CSSPropertyTextUnderlineWidth:
+ case CSSPropertyTop:
+ case CSSPropertyUnicodeBidi:
+ case CSSPropertyUnicodeRange:
+ case CSSPropertyVerticalAlign:
+ case CSSPropertyWidth:
+ case CSSPropertyZIndex:
+ case CSSPropertyWebkitAnimation:
+ case CSSPropertyWebkitAnimationDelay:
+ case CSSPropertyWebkitAnimationDirection:
+ case CSSPropertyWebkitAnimationDuration:
+ case CSSPropertyWebkitAnimationFillMode:
+ case CSSPropertyWebkitAnimationIterationCount:
+ case CSSPropertyWebkitAnimationName:
+ case CSSPropertyWebkitAnimationPlayState:
+ case CSSPropertyWebkitAnimationTimingFunction:
+ case CSSPropertyWebkitAppearance:
+ case CSSPropertyWebkitBackfaceVisibility:
+ case CSSPropertyWebkitBackgroundClip:
+ case CSSPropertyWebkitBackgroundComposite:
+ case CSSPropertyWebkitBackgroundOrigin:
+ case CSSPropertyWebkitBackgroundSize:
+ case CSSPropertyWebkitBorderAfter:
+ case CSSPropertyWebkitBorderAfterColor:
+ case CSSPropertyWebkitBorderAfterStyle:
+ case CSSPropertyWebkitBorderAfterWidth:
+ case CSSPropertyWebkitBorderBefore:
+ case CSSPropertyWebkitBorderBeforeColor:
+ case CSSPropertyWebkitBorderBeforeStyle:
+ case CSSPropertyWebkitBorderBeforeWidth:
+ case CSSPropertyWebkitBorderEnd:
+ case CSSPropertyWebkitBorderEndColor:
+ case CSSPropertyWebkitBorderEndStyle:
+ case CSSPropertyWebkitBorderEndWidth:
+ case CSSPropertyWebkitBorderFit:
+ case CSSPropertyWebkitBorderImage:
+ case CSSPropertyWebkitBorderRadius:
+ case CSSPropertyWebkitBorderStart:
+ case CSSPropertyWebkitBorderStartColor:
+ case CSSPropertyWebkitBorderStartStyle:
+ case CSSPropertyWebkitBorderStartWidth:
+ case CSSPropertyWebkitBoxAlign:
+ case CSSPropertyWebkitBoxFlex:
+ case CSSPropertyWebkitBoxFlexGroup:
+ case CSSPropertyWebkitBoxLines:
+ case CSSPropertyWebkitBoxOrdinalGroup:
+ case CSSPropertyWebkitBoxOrient:
+ case CSSPropertyWebkitBoxPack:
+ case CSSPropertyWebkitBoxReflect:
+ case CSSPropertyWebkitBoxShadow:
+ case CSSPropertyWebkitColumnBreakAfter:
+ case CSSPropertyWebkitColumnBreakBefore:
+ case CSSPropertyWebkitColumnBreakInside:
+ case CSSPropertyWebkitColumnCount:
+ case CSSPropertyWebkitColumnGap:
+ case CSSPropertyWebkitColumnRule:
+ case CSSPropertyWebkitColumnRuleColor:
+ case CSSPropertyWebkitColumnRuleStyle:
+ case CSSPropertyWebkitColumnRuleWidth:
+ case CSSPropertyWebkitColumnSpan:
+ case CSSPropertyWebkitColumnWidth:
+ case CSSPropertyWebkitColumns:
+#if ENABLE(CSS_FILTERS)
+ case CSSPropertyWebkitFilter:
+#endif
+#if ENABLE(CSS3_FLEXBOX)
+ case CSSPropertyWebkitFlexOrder:
+ case CSSPropertyWebkitFlexPack:
+ case CSSPropertyWebkitFlexAlign:
+ case CSSPropertyWebkitFlexFlow:
+#endif
+ case CSSPropertyWebkitFontSizeDelta:
+ case CSSPropertyWebkitLineClamp:
+ case CSSPropertyWebkitLogicalWidth:
+ case CSSPropertyWebkitLogicalHeight:
+ case CSSPropertyWebkitMarginAfterCollapse:
+ case CSSPropertyWebkitMarginBeforeCollapse:
+ case CSSPropertyWebkitMarginBottomCollapse:
+ case CSSPropertyWebkitMarginTopCollapse:
+ case CSSPropertyWebkitMarginCollapse:
+ case CSSPropertyWebkitMarginAfter:
+ case CSSPropertyWebkitMarginBefore:
+ case CSSPropertyWebkitMarginEnd:
+ case CSSPropertyWebkitMarginStart:
+ case CSSPropertyWebkitMarquee:
+ case CSSPropertyWebkitMarqueeDirection:
+ case CSSPropertyWebkitMarqueeIncrement:
+ case CSSPropertyWebkitMarqueeRepetition:
+ case CSSPropertyWebkitMarqueeSpeed:
+ case CSSPropertyWebkitMarqueeStyle:
+ case CSSPropertyWebkitMask:
+ case CSSPropertyWebkitMaskAttachment:
+ case CSSPropertyWebkitMaskBoxImage:
+ case CSSPropertyWebkitMaskBoxImageOutset:
+ case CSSPropertyWebkitMaskBoxImageRepeat:
+ case CSSPropertyWebkitMaskBoxImageSlice:
+ case CSSPropertyWebkitMaskBoxImageSource:
+ case CSSPropertyWebkitMaskBoxImageWidth:
+ case CSSPropertyWebkitMaskClip:
+ case CSSPropertyWebkitMaskComposite:
+ case CSSPropertyWebkitMaskImage:
+ case CSSPropertyWebkitMaskOrigin:
+ case CSSPropertyWebkitMaskPosition:
+ case CSSPropertyWebkitMaskPositionX:
+ case CSSPropertyWebkitMaskPositionY:
+ case CSSPropertyWebkitMaskRepeat:
+ case CSSPropertyWebkitMaskRepeatX:
+ case CSSPropertyWebkitMaskRepeatY:
+ case CSSPropertyWebkitMaskSize:
+ case CSSPropertyWebkitMatchNearestMailBlockquoteColor:
+ case CSSPropertyWebkitMaxLogicalWidth:
+ case CSSPropertyWebkitMaxLogicalHeight:
+ case CSSPropertyWebkitMinLogicalWidth:
+ case CSSPropertyWebkitMinLogicalHeight:
+ case CSSPropertyWebkitPaddingAfter:
+ case CSSPropertyWebkitPaddingBefore:
+ case CSSPropertyWebkitPaddingEnd:
+ case CSSPropertyWebkitPaddingStart:
+ case CSSPropertyWebkitPerspective:
+ case CSSPropertyWebkitPerspectiveOrigin:
+ case CSSPropertyWebkitPerspectiveOriginX:
+ case CSSPropertyWebkitPerspectiveOriginY:
+ case CSSPropertyWebkitTransform:
+ case CSSPropertyWebkitTransformOrigin:
+ case CSSPropertyWebkitTransformOriginX:
+ case CSSPropertyWebkitTransformOriginY:
+ case CSSPropertyWebkitTransformOriginZ:
+ case CSSPropertyWebkitTransformStyle:
+ case CSSPropertyWebkitTransition:
+ case CSSPropertyWebkitTransitionDelay:
+ case CSSPropertyWebkitTransitionDuration:
+ case CSSPropertyWebkitTransitionProperty:
+ case CSSPropertyWebkitTransitionTimingFunction:
+ case CSSPropertyWebkitUserDrag:
+ case CSSPropertyWebkitFlowInto:
+ case CSSPropertyWebkitFlowFrom:
+ case CSSPropertyWebkitRegionOverflow:
+ case CSSPropertyWebkitWrapShape:
+ case CSSPropertyWebkitRegionBreakAfter:
+ case CSSPropertyWebkitRegionBreakBefore:
+ case CSSPropertyWebkitRegionBreakInside:
+#if ENABLE(SVG)
+ case CSSPropertyClipPath:
+ case CSSPropertyMask:
+ case CSSPropertyEnableBackground:
+ case CSSPropertyFilter:
+ case CSSPropertyFloodColor:
+ case CSSPropertyFloodOpacity:
+ case CSSPropertyLightingColor:
+ case CSSPropertyStopColor:
+ case CSSPropertyStopOpacity:
+ case CSSPropertyColorProfile:
+ case CSSPropertyAlignmentBaseline:
+ case CSSPropertyBaselineShift:
+ case CSSPropertyDominantBaseline:
+ case CSSPropertyVectorEffect:
+ case CSSPropertyWebkitSvgShadow:
+#endif
+#if ENABLE(DASHBOARD_SUPPORT)
+ case CSSPropertyWebkitDashboardRegion:
+#endif
+ return false;
+ case CSSPropertyInvalid:
+ ASSERT_NOT_REACHED();
+ return false;
+ }
+ ASSERT_NOT_REACHED();
+ return false;
+}
+
} // namespace WebCore
Modified: trunk/Source/WebCore/css/CSSProperty.h (98541 => 98542)
--- trunk/Source/WebCore/css/CSSProperty.h 2011-10-27 09:37:00 UTC (rev 98541)
+++ trunk/Source/WebCore/css/CSSProperty.h 2011-10-27 09:39:48 UTC (rev 98542)
@@ -32,11 +32,12 @@
class CSSProperty {
WTF_MAKE_FAST_ALLOCATED;
public:
- CSSProperty(int propID, PassRefPtr<CSSValue> value, bool important = false, int shorthandID = 0, bool implicit = false)
+ CSSProperty(unsigned propID, PassRefPtr<CSSValue> value, bool important = false, int shorthandID = 0, bool implicit = false)
: m_id(propID)
, m_shorthandID(shorthandID)
, m_important(important)
, m_implicit(implicit)
+ , m_inherited(isInheritedProperty(propID))
, m_value(value)
{
}
@@ -56,20 +57,23 @@
bool isImportant() const { return m_important; }
bool isImplicit() const { return m_implicit; }
+ bool isInherited() const { return m_inherited; }
CSSValue* value() const { return m_value.get(); }
String cssText() const;
static int resolveDirectionAwareProperty(int propertyID, TextDirection, WritingMode);
+ static bool isInheritedProperty(unsigned propertyID);
friend bool operator==(const CSSProperty&, const CSSProperty&);
// Make sure the following fits in 4 bytes. Really.
- signed m_id : 15;
- signed m_shorthandID : 15; // If this property was set as part of a shorthand, gives the shorthand.
+ unsigned m_id : 14;
+ unsigned m_shorthandID : 14; // If this property was set as part of a shorthand, gives the shorthand.
bool m_important : 1;
bool m_implicit : 1; // Whether or not the property was set implicitly as the result of a shorthand.
+ bool m_inherited : 1;
RefPtr<CSSValue> m_value;
};
Modified: trunk/Source/WebCore/css/CSSStyleSelector.cpp (98541 => 98542)
--- trunk/Source/WebCore/css/CSSStyleSelector.cpp 2011-10-27 09:37:00 UTC (rev 98541)
+++ trunk/Source/WebCore/css/CSSStyleSelector.cpp 2011-10-27 09:39:48 UTC (rev 98542)
@@ -766,6 +766,7 @@
if (result.firstAuthorRule == -1)
result.firstAuthorRule = result.lastAuthorRule;
addMatchedDeclaration(attr->decl());
+ result.isCacheable = false;
}
}
}
@@ -783,6 +784,7 @@
result.lastAuthorRule = m_matchedDecls.size() + additionalDeclsSize - 1;
for (unsigned i = 0; i < additionalDeclsSize; ++i)
addMatchedDeclaration(m_additionalAttributeStyleDecls[i]);
+ result.isCacheable = false;
}
}
if (m_styledElement->isHTMLElement()) {
@@ -805,6 +807,7 @@
if (result.firstAuthorRule == -1)
result.firstAuthorRule = result.lastAuthorRule;
addMatchedDeclaration(inlineDecl);
+ result.isCacheable = false;
}
}
}
@@ -1241,9 +1244,6 @@
// Clean up our style object's display and text decorations (among other fixups).
adjustRenderStyle(style(), m_parentStyle, element);
- // Start loading images referenced by this style.
- loadPendingImages();
-
initElement(0); // Clear out for the next resolve.
// Now return the style.
@@ -2080,22 +2080,20 @@
}
template <bool applyFirst>
-void CSSStyleSelector::applyDeclaration(CSSMutableStyleDeclaration* styleDeclaration, bool isImportant)
+void CSSStyleSelector::applyDeclaration(CSSMutableStyleDeclaration* styleDeclaration, bool isImportant, bool inheritedOnly)
{
CSSMutableStyleDeclaration::const_iterator end = styleDeclaration->end();
for (CSSMutableStyleDeclaration::const_iterator it = styleDeclaration->begin(); it != end; ++it) {
const CSSProperty& current = *it;
-
if (isImportant != current.isImportant())
continue;
-
+ if (inheritedOnly && !current.isInherited() && current.value()->cssValueType() != CSSValue::CSS_INHERIT)
+ continue;
int property = current.id();
-
if (applyFirst) {
COMPILE_ASSERT(firstCSSProperty == CSSPropertyColor, CSS_color_is_first_property);
COMPILE_ASSERT(CSSPropertyZoom == CSSPropertyColor + 16, CSS_zoom_is_end_of_first_prop_range);
COMPILE_ASSERT(CSSPropertyLineHeight == CSSPropertyZoom + 1, CSS_line_height_is_after_zoom);
-
// give special priority to font-xxx, color properties, etc
if (property > CSSPropertyLineHeight)
continue;
@@ -2113,7 +2111,7 @@
}
template <bool applyFirst>
-void CSSStyleSelector::applyDeclarations(bool isImportant, int startIndex, int endIndex)
+void CSSStyleSelector::applyDeclarations(bool isImportant, int startIndex, int endIndex, bool inheritedOnly)
{
if (startIndex == -1)
return;
@@ -2126,48 +2124,158 @@
m_applyPropertyToRegularStyle = linkMatchType & SelectorChecker::MatchLink;
m_applyPropertyToVisitedLinkStyle = linkMatchType & SelectorChecker::MatchVisited;
- applyDeclaration<applyFirst>(styleDeclaration, isImportant);
+ applyDeclaration<applyFirst>(styleDeclaration, isImportant, inheritedOnly);
}
m_applyPropertyToRegularStyle = true;
m_applyPropertyToVisitedLinkStyle = false;
return;
}
for (int i = startIndex; i <= endIndex; ++i)
- applyDeclaration<applyFirst>(m_matchedDecls[i].styleDeclaration, isImportant);
+ applyDeclaration<applyFirst>(m_matchedDecls[i].styleDeclaration, isImportant, inheritedOnly);
}
+unsigned CSSStyleSelector::computeDeclarationHash(MatchedStyleDeclaration* declarations, unsigned size)
+{
+ unsigned hash = 0;
+ for (unsigned i = 0; i < size; ++i) {
+ unsigned ptrHash = PtrHash<CSSMutableStyleDeclaration*>::hash(declarations[i].styleDeclaration);
+ ptrHash ^= IntHash<unsigned>::hash(declarations[i].linkMatchType);
+ // Make the position matter.
+ hash ^= (ptrHash << i) | (ptrHash >> (32 - i));
+ }
+ return hash;
+}
+
+bool operator==(const CSSStyleSelector::MatchResult& a, const CSSStyleSelector::MatchResult& b)
+{
+ return a.firstUARule == b.firstUARule
+ && a.lastUARule == b.lastUARule
+ && a.firstAuthorRule == b.firstAuthorRule
+ && a.lastAuthorRule == b.lastAuthorRule
+ && a.firstUserRule == b.firstUserRule
+ && a.lastUserRule == b.lastUserRule
+ && a.isCacheable == b.isCacheable;
+}
+
+bool operator!=(const CSSStyleSelector::MatchResult& a, const CSSStyleSelector::MatchResult& b)
+{
+ return !(a == b);
+}
+
+bool operator==(const CSSStyleSelector::MatchedStyleDeclaration& a, const CSSStyleSelector::MatchedStyleDeclaration& b)
+{
+ return a.styleDeclaration == b.styleDeclaration && a.linkMatchType == b.linkMatchType;
+}
+
+bool operator!=(const CSSStyleSelector::MatchedStyleDeclaration& a, const CSSStyleSelector::MatchedStyleDeclaration& b)
+{
+ return !(a == b);
+}
+
+const RenderStyle* CSSStyleSelector::findFromMatchedDeclarationCache(unsigned hash, const MatchResult& matchResult)
+{
+ ASSERT(hash);
+
+ MatchedStyleDeclarationCache::iterator it = m_matchStyleDeclarationCache.find(hash);
+ if (it == m_matchStyleDeclarationCache.end())
+ return 0;
+ MatchedStyleDeclarationCacheItem& cacheItem = it->second;
+ ASSERT(cacheItem.matchResult.isCacheable);
+
+ size_t size = m_matchedDecls.size();
+ if (size != cacheItem.matchedStyleDeclarations.size())
+ return 0;
+ for (size_t i = 0; i < size; ++i) {
+ if (m_matchedDecls[i] != cacheItem.matchedStyleDeclarations[i])
+ return 0;
+ }
+ if (cacheItem.matchResult != matchResult)
+ return 0;
+ return cacheItem.renderStyle.get();
+}
+
+void CSSStyleSelector::addToMatchedDeclarationCache(const RenderStyle* style, unsigned hash, const MatchResult& matchResult)
+{
+ ASSERT(hash);
+ MatchedStyleDeclarationCacheItem cacheItem;
+ cacheItem.matchedStyleDeclarations.append(m_matchedDecls);
+ cacheItem.matchResult = matchResult;
+ // Note that we don't cache the original RenderStyle instance. It may be further modified.
+ // The RenderStyle in the cache is really just a holder for the non-inherited substructures and never used as-is.
+ cacheItem.renderStyle = RenderStyle::clone(style);
+ m_matchStyleDeclarationCache.add(hash, cacheItem);
+}
+
+static bool isCacheableInMatchedDeclarationCache(const RenderStyle* style, const RenderStyle* parentStyle)
+{
+ if (style->unique() || (style->styleType() != NOPSEUDO && parentStyle->unique()))
+ return false;
+ if (style->hasAppearance())
+ return false;
+ if (style->zoom() != RenderStyle::initialZoom())
+ return false;
+ return true;
+}
+
void CSSStyleSelector::applyMatchedDeclarations(const MatchResult& matchResult)
{
+ unsigned cacheHash = matchResult.isCacheable ? computeDeclarationHash(m_matchedDecls.data(), m_matchedDecls.size()) : 0;
+ bool applyInheritedOnly = false;
+ const RenderStyle* cachedStyle = 0;
+ if (cacheHash && (cachedStyle = findFromMatchedDeclarationCache(cacheHash, matchResult))) {
+ // We can build up the style by copying non-inherited properties from an earlier style object built using the same exact
+ // style declarations. We then only need to apply the inherited properties, if any, as their values can depend on the
+ // element context. This is fast and saves memory by reusing the style data structures.
+ m_style->copyNonInheritedFrom(cachedStyle);
+ applyInheritedOnly = true;
+ }
// Now we have all of the matched rules in the appropriate order. Walk the rules and apply
// high-priority properties first, i.e., those properties that other properties depend on.
// The order is (1) high-priority not important, (2) high-priority important, (3) normal not important
// and (4) normal important.
m_lineHeightValue = 0;
- applyDeclarations<true>(false, 0, m_matchedDecls.size() - 1);
- applyDeclarations<true>(true, matchResult.firstAuthorRule, matchResult.lastAuthorRule);
- applyDeclarations<true>(true, matchResult.firstUserRule, matchResult.lastUserRule);
- applyDeclarations<true>(true, matchResult.firstUARule, matchResult.lastUARule);
-
+ applyDeclarations<true>(false, 0, m_matchedDecls.size() - 1, applyInheritedOnly);
+ applyDeclarations<true>(true, matchResult.firstAuthorRule, matchResult.lastAuthorRule, applyInheritedOnly);
+ applyDeclarations<true>(true, matchResult.firstUserRule, matchResult.lastUserRule, applyInheritedOnly);
+ applyDeclarations<true>(true, matchResult.firstUARule, matchResult.lastUARule, applyInheritedOnly);
+
+ if (cachedStyle && cachedStyle->effectiveZoom() != m_style->effectiveZoom()) {
+ m_fontDirty = true;
+ applyInheritedOnly = false;
+ }
+
// If our font got dirtied, go ahead and update it now.
updateFont();
// Line-height is set when we are sure we decided on the font-size.
if (m_lineHeightValue)
applyProperty(CSSPropertyLineHeight, m_lineHeightValue);
-
+
+ // Many properties depend on the font. If it changes we just apply all properties.
+ if (cachedStyle && cachedStyle->fontDescription() != m_style->fontDescription())
+ applyInheritedOnly = false;
+
// Now do the normal priority UA properties.
- applyDeclarations<false>(false, matchResult.firstUARule, matchResult.lastUARule);
+ applyDeclarations<false>(false, matchResult.firstUARule, matchResult.lastUARule, applyInheritedOnly);
// Cache our border and background so that we can examine them later.
cacheBorderAndBackground();
// Now do the author and user normal priority properties and all the !important properties.
- applyDeclarations<false>(false, matchResult.lastUARule + 1, m_matchedDecls.size() - 1);
- applyDeclarations<false>(true, matchResult.firstAuthorRule, matchResult.lastAuthorRule);
- applyDeclarations<false>(true, matchResult.firstUserRule, matchResult.lastUserRule);
- applyDeclarations<false>(true, matchResult.firstUARule, matchResult.lastUARule);
+ applyDeclarations<false>(false, matchResult.lastUARule + 1, m_matchedDecls.size() - 1, applyInheritedOnly);
+ applyDeclarations<false>(true, matchResult.firstAuthorRule, matchResult.lastAuthorRule, applyInheritedOnly);
+ applyDeclarations<false>(true, matchResult.firstUserRule, matchResult.lastUserRule, applyInheritedOnly);
+ applyDeclarations<false>(true, matchResult.firstUARule, matchResult.lastUARule, applyInheritedOnly);
+ loadPendingImages();
+
ASSERT(!m_fontDirty);
+
+ if (cachedStyle || !cacheHash)
+ return;
+ if (!isCacheableInMatchedDeclarationCache(m_style.get(), m_parentStyle))
+ return;
+ addToMatchedDeclarationCache(m_style.get(), cacheHash, matchResult);
}
void CSSStyleSelector::matchPageRules(RuleSet* rules, bool isLeftPage, bool isFirstPage, const String& pageName)
Modified: trunk/Source/WebCore/css/CSSStyleSelector.h (98541 => 98542)
--- trunk/Source/WebCore/css/CSSStyleSelector.h 2011-10-27 09:37:00 UTC (rev 98541)
+++ trunk/Source/WebCore/css/CSSStyleSelector.h 2011-10-27 09:39:48 UTC (rev 98542)
@@ -226,13 +226,14 @@
void addMatchedDeclaration(CSSMutableStyleDeclaration*, unsigned linkMatchType = SelectorChecker::MatchAll);
struct MatchResult {
- MatchResult() : firstUARule(-1), lastUARule(-1), firstAuthorRule(-1), lastAuthorRule(-1), firstUserRule(-1), lastUserRule(-1) { }
+ MatchResult() : firstUARule(-1), lastUARule(-1), firstAuthorRule(-1), lastAuthorRule(-1), firstUserRule(-1), lastUserRule(-1), isCacheable(true) { }
int firstUARule;
int lastUARule;
int firstAuthorRule;
int lastAuthorRule;
int firstUserRule;
int lastUserRule;
+ bool isCacheable;
};
void matchAllRules(MatchResult&);
void matchUARules(MatchResult&);
@@ -245,9 +246,9 @@
void applyMatchedDeclarations(const MatchResult&);
template <bool firstPass>
- void applyDeclarations(bool important, int startIndex, int endIndex);
+ void applyDeclarations(bool important, int startIndex, int endIndex, bool inheritedOnly = false);
template <bool firstPass>
- void applyDeclaration(CSSMutableStyleDeclaration*, bool isImportant);
+ void applyDeclaration(CSSMutableStyleDeclaration*, bool isImportant, bool inheritedOnly);
void matchPageRules(RuleSet*, bool isLeftPage, bool isFirstPage, const String& pageName);
void matchPageRulesForList(const Vector<RuleData>*, bool isLeftPage, bool isFirstPage, const String& pageName);
@@ -271,6 +272,7 @@
typedef Vector<RefPtr<CSSRegionStyleRule> > RegionStyleRules;
RegionStyleRules m_regionStyleRules;
+
public:
static RenderStyle* styleNotYetAvailable() { return s_styleNotYetAvailable; }
@@ -325,16 +327,28 @@
void loadPendingImages();
- // We collect the set of decls that match in |m_matchedDecls|. We then walk the
- // set of matched decls four times, once for those properties that others depend on (like font-size),
- // and then a second time for all the remaining properties. We then do the same two passes
- // for any !important rules.
struct MatchedStyleDeclaration {
MatchedStyleDeclaration(CSSMutableStyleDeclaration* decl, unsigned type) : styleDeclaration(decl), linkMatchType(type) { }
CSSMutableStyleDeclaration* styleDeclaration;
unsigned linkMatchType;
};
+ static unsigned computeDeclarationHash(MatchedStyleDeclaration*, unsigned size);
+ const RenderStyle* findFromMatchedDeclarationCache(unsigned hash, const MatchResult&);
+ void addToMatchedDeclarationCache(const RenderStyle*, unsigned hash, const MatchResult&);
+
+ // We collect the set of decls that match in |m_matchedDecls|. We then walk the
+ // set of matched decls four times, once for those properties that others depend on (like font-size),
+ // and then a second time for all the remaining properties. We then do the same two passes
+ // for any !important rules.
Vector<MatchedStyleDeclaration, 64> m_matchedDecls;
+
+ struct MatchedStyleDeclarationCacheItem {
+ Vector<MatchedStyleDeclaration> matchedStyleDeclarations;
+ MatchResult matchResult;
+ RefPtr<RenderStyle> renderStyle;
+ };
+ typedef HashMap<unsigned, MatchedStyleDeclarationCacheItem> MatchedStyleDeclarationCache;
+ MatchedStyleDeclarationCache m_matchStyleDeclarationCache;
// A buffer used to hold the set of matched rules for an element, and a temporary buffer used for
// merge sorting.
@@ -372,6 +386,10 @@
const CSSStyleApplyProperty& m_applyProperty;
friend class CSSStyleApplyProperty;
+ friend bool operator==(const MatchedStyleDeclaration&, const MatchedStyleDeclaration&);
+ friend bool operator!=(const MatchedStyleDeclaration&, const MatchedStyleDeclaration&);
+ friend bool operator==(const MatchResult&, const MatchResult&);
+ friend bool operator!=(const MatchResult&, const MatchResult&);
};
} // namespace WebCore
Modified: trunk/Source/WebCore/rendering/style/RenderStyle.cpp (98541 => 98542)
--- trunk/Source/WebCore/rendering/style/RenderStyle.cpp 2011-10-27 09:37:00 UTC (rev 98541)
+++ trunk/Source/WebCore/rendering/style/RenderStyle.cpp 2011-10-27 09:39:48 UTC (rev 98542)
@@ -181,6 +181,34 @@
#endif
}
+void RenderStyle::copyNonInheritedFrom(const RenderStyle* other)
+{
+ m_box = other->m_box;
+ visual = other->visual;
+ m_background = other->m_background;
+ surround = other->surround;
+ rareNonInheritedData = other->rareNonInheritedData;
+ // The flags are copied one-by-one because noninherited_flags contains a bunch of stuff other than real style data.
+ noninherited_flags._effectiveDisplay = other->noninherited_flags._effectiveDisplay;
+ noninherited_flags._originalDisplay = other->noninherited_flags._originalDisplay;
+ noninherited_flags._overflowX = other->noninherited_flags._overflowX;
+ noninherited_flags._overflowY = other->noninherited_flags._overflowY;
+ noninherited_flags._vertical_align = other->noninherited_flags._vertical_align;
+ noninherited_flags._clear = other->noninherited_flags._clear;
+ noninherited_flags._position = other->noninherited_flags._position;
+ noninherited_flags._floating = other->noninherited_flags._floating;
+ noninherited_flags._table_layout = other->noninherited_flags._table_layout;
+ noninherited_flags._page_break_before = other->noninherited_flags._page_break_before;
+ noninherited_flags._page_break_after = other->noninherited_flags._page_break_after;
+ noninherited_flags._page_break_inside = other->noninherited_flags._page_break_inside;
+ noninherited_flags._unicodeBidi = other->noninherited_flags._unicodeBidi;
+#if ENABLE(SVG)
+ if (m_svgStyle != other->m_svgStyle)
+ m_svgStyle.access()->copyNonInheritedFrom(other->m_svgStyle.get());
+#endif
+ ASSERT(zoom() == initialZoom());
+}
+
RenderStyle::~RenderStyle()
{
}
Modified: trunk/Source/WebCore/rendering/style/RenderStyle.h (98541 => 98542)
--- trunk/Source/WebCore/rendering/style/RenderStyle.h 2011-10-27 09:37:00 UTC (rev 98541)
+++ trunk/Source/WebCore/rendering/style/RenderStyle.h 2011-10-27 09:39:48 UTC (rev 98542)
@@ -266,6 +266,7 @@
unsigned char _pseudoBits : 7;
unsigned char _unicodeBidi : 3; // EUnicodeBidi
bool _isLink : 1;
+ // If you add more style bits here, you will also need to update RenderStyle::copyNonInheritedFrom()
// 53 bits
} noninherited_flags;
@@ -328,6 +329,7 @@
~RenderStyle();
void inheritFrom(const RenderStyle* inheritParent);
+ void copyNonInheritedFrom(const RenderStyle*);
PseudoId styleType() const { return static_cast<PseudoId>(noninherited_flags._styleType); }
void setStyleType(PseudoId styleType) { noninherited_flags._styleType = styleType; }
Modified: trunk/Source/WebCore/rendering/style/SVGRenderStyle.cpp (98541 => 98542)
--- trunk/Source/WebCore/rendering/style/SVGRenderStyle.cpp 2011-10-27 09:37:00 UTC (rev 98541)
+++ trunk/Source/WebCore/rendering/style/SVGRenderStyle.cpp 2011-10-27 09:39:48 UTC (rev 98542)
@@ -126,6 +126,15 @@
svg_inherited_flags = svgInheritParent->svg_inherited_flags;
}
+void SVGRenderStyle::copyNonInheritedFrom(const SVGRenderStyle* other)
+{
+ svg_noninherited_flags = other->svg_noninherited_flags;
+ stops = other->stops;
+ misc = other->misc;
+ shadowSVG = other->shadowSVG;
+ resources = other->resources;
+}
+
StyleDifference SVGRenderStyle::diff(const SVGRenderStyle* other) const
{
// NOTE: All comparisions that may return StyleDifferenceLayout have to go before those who return StyleDifferenceRepaint
Modified: trunk/Source/WebCore/rendering/style/SVGRenderStyle.h (98541 => 98542)
--- trunk/Source/WebCore/rendering/style/SVGRenderStyle.h 2011-10-27 09:37:00 UTC (rev 98541)
+++ trunk/Source/WebCore/rendering/style/SVGRenderStyle.h 2011-10-27 09:39:48 UTC (rev 98542)
@@ -46,6 +46,7 @@
bool inheritedNotEqual(const SVGRenderStyle*) const;
void inheritFrom(const SVGRenderStyle*);
+ void copyNonInheritedFrom(const SVGRenderStyle*);
StyleDifference diff(const SVGRenderStyle*) const;