Title: [98542] trunk/Source/WebCore
Revision
98542
Author
an...@apple.com
Date
2011-10-27 02:39:48 -0700 (Thu, 27 Oct 2011)

Log Message

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.

Modified Paths

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;
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to