Changeset 133138 in webkit


Ignore:
Timestamp:
Nov 1, 2012 1:55:58 AM (11 years ago)
Author:
kling@webkit.org
Message:

Pack immutable StylePropertySets harder on 64-bit.
<http://webkit.org/b/100753>
<rdar://problem/12599155>

Reviewed by Antti Koivisto.

Move away from using CSSProperty as internal storage for immutable StylePropertySets.
Instead use two arrays, one for property metadata (ID, shorthand ID, !important, ...)
and one for the CSSValue pointers. This saves 4 bytes per property on 64-bit.

Old object layout:

Ref count (4 bytes)
Metadata (4 bytes)
CSSProperty [N] (16 bytes each)

New object layout:

Ref count (4 bytes)
Metadata (4 bytes)
CSSValue* [N] (8 bytes each)
StylePropertyMetadata [N] (4 bytes each)

901kB progress on Membuster3 (22% overall reduction in StylePropertySet memory.)

The CSSProperty class sticks around for now, it's still used in mutable StylePropertySets
and by the StylePropertySet constructors.

  • css/CSSProperty.cpp:
  • css/CSSProperty.h:

(CSSProperty):
(WebCore::CSSProperty::CSSProperty):
(WebCore::CSSProperty::id):
(WebCore::CSSProperty::shorthandID):
(WebCore::CSSProperty::isImportant):
(WebCore::CSSProperty::metadata):

Break the bitfield from CSSProperty out into a StylePropertyMetadata class (actually a union.)

  • css/StylePropertySet.cpp:

(WebCore::immutableStylePropertySetSize):

Updated size calculation for immutable StylePropertySets, 1/4 smaller!

(WebCore::ImmutableStylePropertySet::ImmutableStylePropertySet):
(WebCore::ImmutableStylePropertySet::~ImmutableStylePropertySet):
(WebCore::MutableStylePropertySet::MutableStylePropertySet):
(WebCore::StylePropertySet::mergeAndOverrideOnConflict):
(WebCore::StylePropertySet::reportMemoryUsage):
(WebCore::StylePropertySet::PropertyReference::cssName):
(WebCore::StylePropertySet::PropertyReference::cssText):

  • css/StylePropertySet.h:

(WebCore::StylePropertySet::PropertyReference::id):
(WebCore::StylePropertySet::PropertyReference::shorthandID):
(WebCore::StylePropertySet::PropertyReference::isImportant):
(WebCore::StylePropertySet::PropertyReference::isInherited):
(WebCore::StylePropertySet::PropertyReference::isImplicit):
(PropertyReference):
(WebCore::StylePropertySet::PropertyReference::value):
(WebCore::StylePropertySet::PropertyReference::toCSSProperty):
(WebCore::StylePropertySet::PropertyReference::propertyMetadata):
(WebCore::StylePropertySet::PropertyReference::propertyValue):
(StylePropertySet):
(ImmutableStylePropertySet):
(WebCore::StylePropertySet::immutableValueArray):
(WebCore::StylePropertySet::immutableMetadataArray):

Refactored internal storage for StylePropertySet.

Location:
trunk/Source/WebCore
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r133134 r133138  
     12012-11-01  Andreas Kling  <kling@webkit.org>
     2
     3        Pack immutable StylePropertySets harder on 64-bit.
     4        <http://webkit.org/b/100753>
     5        <rdar://problem/12599155>
     6
     7        Reviewed by Antti Koivisto.
     8
     9        Move away from using CSSProperty as internal storage for immutable StylePropertySets.
     10        Instead use two arrays, one for property metadata (ID, shorthand ID, !important, ...)
     11        and one for the CSSValue pointers. This saves 4 bytes per property on 64-bit.
     12
     13        Old object layout:
     14
     15            Ref count                   (4 bytes)
     16            Metadata                    (4 bytes)
     17            CSSProperty [N]             (16 bytes each)
     18
     19        New object layout:
     20
     21            Ref count                   (4 bytes)
     22            Metadata                    (4 bytes)
     23            CSSValue* [N]               (8 bytes each)
     24            StylePropertyMetadata [N]   (4 bytes each)
     25
     26        901kB progress on Membuster3 (22% overall reduction in StylePropertySet memory.)
     27
     28        The CSSProperty class sticks around for now, it's still used in mutable StylePropertySets
     29        and by the StylePropertySet constructors.
     30
     31        * css/CSSProperty.cpp:
     32        * css/CSSProperty.h:
     33        (CSSProperty):
     34        (WebCore::CSSProperty::CSSProperty):
     35        (WebCore::CSSProperty::id):
     36        (WebCore::CSSProperty::shorthandID):
     37        (WebCore::CSSProperty::isImportant):
     38        (WebCore::CSSProperty::metadata):
     39
     40            Break the bitfield from CSSProperty out into a StylePropertyMetadata class (actually a union.)
     41
     42        * css/StylePropertySet.cpp:
     43        (WebCore::immutableStylePropertySetSize):
     44
     45            Updated size calculation for immutable StylePropertySets, 1/4 smaller!
     46
     47        (WebCore::ImmutableStylePropertySet::ImmutableStylePropertySet):
     48        (WebCore::ImmutableStylePropertySet::~ImmutableStylePropertySet):
     49        (WebCore::MutableStylePropertySet::MutableStylePropertySet):
     50        (WebCore::StylePropertySet::mergeAndOverrideOnConflict):
     51        (WebCore::StylePropertySet::reportMemoryUsage):
     52        (WebCore::StylePropertySet::PropertyReference::cssName):
     53        (WebCore::StylePropertySet::PropertyReference::cssText):
     54        * css/StylePropertySet.h:
     55        (WebCore::StylePropertySet::PropertyReference::id):
     56        (WebCore::StylePropertySet::PropertyReference::shorthandID):
     57        (WebCore::StylePropertySet::PropertyReference::isImportant):
     58        (WebCore::StylePropertySet::PropertyReference::isInherited):
     59        (WebCore::StylePropertySet::PropertyReference::isImplicit):
     60        (PropertyReference):
     61        (WebCore::StylePropertySet::PropertyReference::value):
     62        (WebCore::StylePropertySet::PropertyReference::toCSSProperty):
     63        (WebCore::StylePropertySet::PropertyReference::propertyMetadata):
     64        (WebCore::StylePropertySet::PropertyReference::propertyValue):
     65        (StylePropertySet):
     66        (ImmutableStylePropertySet):
     67        (WebCore::StylePropertySet::immutableValueArray):
     68        (WebCore::StylePropertySet::immutableMetadataArray):
     69
     70            Refactored internal storage for StylePropertySet.
     71
    1722012-11-01  Kent Tamura  <tkent@chromium.org>
    273
  • trunk/Source/WebCore/css/CSSProperty.cpp

    r131925 r133138  
    4141
    4242COMPILE_ASSERT(sizeof(CSSProperty) == sizeof(SameSizeAsCSSProperty), CSSProperty_should_stay_small);
    43 
    44 String CSSProperty::cssName() const
    45 {
    46 #if ENABLE(CSS_VARIABLES)
    47     if (id() == CSSPropertyVariable) {
    48         ASSERT(value()->isVariableValue());
    49         return "-webkit-var-" + static_cast<CSSVariableValue*>(value())->name();
    50     }
    51 #endif
    52     return getPropertyNameString(id());
    53 }
    54 
    55 String CSSProperty::cssText() const
    56 {
    57     StringBuilder result;
    58     result.append(cssName());
    59     result.appendLiteral(": ");
    60     result.append(m_value->cssText());
    61     if (isImportant())
    62         result.appendLiteral(" !important");
    63     result.append(';');
    64     return result.toString();
    65 }
    6643
    6744void CSSProperty::wrapValueInCommaSeparatedList()
  • trunk/Source/WebCore/css/CSSProperty.h

    r128418 r133138  
    3232namespace WebCore {
    3333
    34 class CSSProperty {
    35 public:
    36     CSSProperty(CSSPropertyID propID, PassRefPtr<CSSValue> value, bool important = false, CSSPropertyID shorthandID = CSSPropertyInvalid, bool implicit = false)
    37         : m_id(propID)
     34union StylePropertyMetadata {
     35    StylePropertyMetadata(CSSPropertyID propertyID, CSSPropertyID shorthandID, bool important, bool implicit, bool inherited)
     36        : m_propertyID(propertyID)
    3837        , m_shorthandID(shorthandID)
    3938        , m_important(important)
    4039        , m_implicit(implicit)
    41         , m_inherited(isInheritedProperty(propID))
     40        , m_inherited(inherited)
     41    {
     42    }
     43
     44    unsigned m_bits;
     45    struct {
     46        unsigned m_propertyID : 14;
     47        unsigned m_shorthandID : 14; // If this property was set as part of a shorthand, gives the shorthand.
     48        unsigned m_important : 1;
     49        unsigned m_implicit : 1; // Whether or not the property was set implicitly as the result of a shorthand.
     50        unsigned m_inherited : 1;
     51    };
     52};
     53
     54class CSSProperty {
     55public:
     56    CSSProperty(CSSPropertyID propertyID, PassRefPtr<CSSValue> value, bool important = false, CSSPropertyID shorthandID = CSSPropertyInvalid, bool implicit = false)
     57        : m_metadata(propertyID, shorthandID, important, implicit, isInheritedProperty(propertyID))
    4258        , m_value(value)
    4359    {
    4460    }
    4561
    46     CSSPropertyID id() const { return static_cast<CSSPropertyID>(m_id); }
    47     CSSPropertyID shorthandID() const { return static_cast<CSSPropertyID>(m_shorthandID); }
     62    // FIXME: Remove this.
     63    CSSProperty(StylePropertyMetadata metadata, CSSValue* value)
     64        : m_metadata(metadata)
     65        , m_value(value)
     66    {
     67    }
    4868
    49     bool isImportant() const { return m_important; }
    50     bool isImplicit() const { return m_implicit; }
    51     bool isInherited() const { return m_inherited; }
     69    CSSPropertyID id() const { return static_cast<CSSPropertyID>(m_metadata.m_propertyID); }
     70    CSSPropertyID shorthandID() const { return static_cast<CSSPropertyID>(m_metadata.m_shorthandID); }
     71    bool isImportant() const { return m_metadata.m_important; }
    5272
    5373    CSSValue* value() const { return m_value.get(); }
    54 
    55     String cssName() const;
    56     String cssText() const;
    5774
    5875    void wrapValueInCommaSeparatedList();
     
    6380    void reportMemoryUsage(MemoryObjectInfo*) const;
    6481
     82    StylePropertyMetadata metadata() const { return m_metadata; }
     83
    6584private:
    66     // Make sure the following fits in 4 bytes. Really.
    67     unsigned m_id : 14;
    68     unsigned m_shorthandID : 14; // If this property was set as part of a shorthand, gives the shorthand.
    69     unsigned m_important : 1;
    70     unsigned m_implicit : 1; // Whether or not the property was set implicitly as the result of a shorthand.
    71     unsigned m_inherited : 1;
    72 
     85    StylePropertyMetadata m_metadata;
    7386    RefPtr<CSSValue> m_value;
    7487};
  • trunk/Source/WebCore/css/StylePropertySet.cpp

    r132952 r133138  
    3535#include <wtf/text/StringBuilder.h>
    3636
     37#if ENABLE(CSS_VARIABLES)
     38#include "CSSVariableValue.h"
     39#endif
     40
    3741#ifndef NDEBUG
    3842#include <stdio.h>
     
    5458static size_t immutableStylePropertySetSize(unsigned count)
    5559{
    56     return sizeof(StylePropertySet) + sizeof(CSSProperty) * count;
     60    return sizeof(StylePropertySet) + sizeof(CSSValue*) * count + sizeof(StylePropertyMetadata) * count;
    5761}
    5862
     
    8185    : StylePropertySet(cssParserMode, length)
    8286{
    83     for (unsigned i = 0; i < length; ++i)
    84         new (&reinterpret_cast<CSSProperty*>(&m_propertyArray)[i]) CSSProperty(properties[i]);
     87    StylePropertyMetadata* metadataArray = const_cast<StylePropertyMetadata*>(immutableMetadataArray());
     88    CSSValue** valueArray = const_cast<CSSValue**>(immutableValueArray());
     89    for (unsigned i = 0; i < length; ++i) {
     90        metadataArray[i] = properties[i].metadata();
     91        valueArray[i] = properties[i].value();
     92        valueArray[i]->ref();
     93    }
     94}
     95
     96ImmutableStylePropertySet::~ImmutableStylePropertySet()
     97{
     98    CSSValue** valueArray = const_cast<CSSValue**>(immutableValueArray());
     99    for (unsigned i = 0; i < m_arraySize; ++i)
     100        valueArray[i]->deref();
    85101}
    86102
     
    93109        m_propertyVector.reserveInitialCapacity(other.propertyCount());
    94110        for (unsigned i = 0; i < other.propertyCount(); ++i)
    95             m_propertyVector.uncheckedAppend(other.immutablePropertyArray()[i]);
    96     }
    97 }
    98 
    99 ImmutableStylePropertySet::~ImmutableStylePropertySet()
    100 {
    101     for (unsigned i = 0; i < m_arraySize; ++i)
    102         immutablePropertyArray()[i].~CSSProperty();
     111            m_propertyVector.uncheckedAppend(other.propertyAt(i).toCSSProperty());
     112    }
    103113}
    104114
     
    915925    unsigned size = other->propertyCount();
    916926    for (unsigned n = 0; n < size; ++n) {
    917         const CSSProperty& toMerge = other->propertyAtInternal(n);
     927        PropertyReference toMerge = other->propertyAt(n);
    918928        CSSProperty* old = findMutableCSSPropertyWithID(toMerge.id());
    919929        if (old)
    920             setProperty(toMerge, old);
     930            setProperty(toMerge.toCSSProperty(), old);
    921931        else
    922             mutablePropertyVector().append(toMerge);
     932            mutablePropertyVector().append(toMerge.toCSSProperty());
    923933    }
    924934}
     
    11331143    if (m_isMutable)
    11341144        info.addMember(mutablePropertyVector());
    1135 
    1136     unsigned count = propertyCount();
    1137     for (unsigned i = 0; i < count; ++i)
    1138         info.addMember(propertyAtInternal(i));
     1145    else {
     1146        for (unsigned i = 0; i < propertyCount(); ++i)
     1147            info.addMember(propertyAt(i).value());
     1148    }
    11391149}
    11401150
     
    11621172}
    11631173
     1174String StylePropertySet::PropertyReference::cssName() const
     1175{
     1176#if ENABLE(CSS_VARIABLES)
     1177    if (id() == CSSPropertyVariable) {
     1178        ASSERT(propertyValue()->isVariableValue());
     1179        return "-webkit-var-" + static_cast<const CSSVariableValue*>(propertyValue())->name();
     1180    }
     1181#endif
     1182    return getPropertyNameString(id());
     1183}
     1184
     1185String StylePropertySet::PropertyReference::cssText() const
     1186{
     1187    StringBuilder result;
     1188    result.append(cssName());
     1189    result.appendLiteral(": ");
     1190    result.append(propertyValue()->cssText());
     1191    if (isImportant())
     1192        result.appendLiteral(" !important");
     1193    result.append(';');
     1194    return result.toString();
     1195}
     1196
     1197
    11641198} // namespace WebCore
  • trunk/Source/WebCore/css/StylePropertySet.h

    r132952 r133138  
    6060            : m_propertySet(propertySet)
    6161            , m_index(index)
    62         { }
    63 
    64         CSSPropertyID id() const { return propertyInternal().id(); }
    65         CSSPropertyID shorthandID() const { return propertyInternal().shorthandID(); }
    66         bool isImportant() const { return propertyInternal().isImportant(); }
    67         bool isImplicit() const { return propertyInternal().isImplicit(); }
    68         bool isInherited() const { return propertyInternal().isInherited(); }
    69 
    70         String cssName() const { return propertyInternal().cssName(); }
    71         String cssText() const { return propertyInternal().cssText(); }
    72 
    73         const CSSValue* value() const { return propertyInternal().value(); }
     62        {
     63        }
     64
     65        CSSPropertyID id() const { return static_cast<CSSPropertyID>(propertyMetadata().m_propertyID); }
     66        CSSPropertyID shorthandID() const { return static_cast<CSSPropertyID>(propertyMetadata().m_shorthandID); }
     67
     68        bool isImportant() const { return propertyMetadata().m_important; }
     69        bool isInherited() const { return propertyMetadata().m_inherited; }
     70        bool isImplicit() const { return propertyMetadata().m_implicit; }
     71
     72        String cssName() const;
     73        String cssText() const;
     74
     75        const CSSValue* value() const { return propertyValue(); }
    7476        // FIXME: We should try to remove this mutable overload.
    75         CSSValue* value() { return const_cast<CSSValue*>(propertyInternal().value()); }
     77        CSSValue* value() { return const_cast<CSSValue*>(propertyValue()); }
     78
     79        // FIXME: Remove this.
     80        CSSProperty toCSSProperty() const { return CSSProperty(propertyMetadata(), const_cast<CSSValue*>(propertyValue())); }
    7681
    7782    private:
    78         const CSSProperty& propertyInternal() const { return m_propertySet.propertyAtInternal(m_index); }
     83        StylePropertyMetadata propertyMetadata() const
     84        {
     85            if (m_propertySet.isMutable())
     86                return m_propertySet.mutablePropertyVector().at(m_index).metadata();
     87            return m_propertySet.immutableMetadataArray()[m_index];
     88        }
     89
     90        const CSSValue* propertyValue() const
     91        {
     92            if (m_propertySet.isMutable())
     93                return m_propertySet.mutablePropertyVector().at(m_index).value();
     94            return m_propertySet.immutableValueArray()[m_index];
     95        }
    7996
    8097        const StylePropertySet& m_propertySet;
     
    143160#endif
    144161
    145     const CSSProperty* immutablePropertyArray() const;
     162    const CSSValue** immutableValueArray() const;
     163    const StylePropertyMetadata* immutableMetadataArray() const;
    146164
    147165protected:
     
    187205    CSSProperty* findMutableCSSPropertyWithID(CSSPropertyID);
    188206
    189     CSSProperty& propertyAtInternal(unsigned index);
    190     const CSSProperty& propertyAtInternal(unsigned index) const;
    191 
    192207    friend class PropertySetCSSStyleDeclaration;
    193208};
     
    198213    ~ImmutableStylePropertySet();
    199214
    200     void* m_propertyArray;
     215    void* m_storage;
    201216};
     217
     218inline const CSSValue** StylePropertySet::immutableValueArray() const
     219{
     220    ASSERT(!m_isMutable);
     221    return reinterpret_cast<const CSSValue**>(const_cast<const void**>((&static_cast<const ImmutableStylePropertySet*>(this)->m_storage)));
     222}
     223
     224inline const StylePropertyMetadata* StylePropertySet::immutableMetadataArray() const
     225{
     226    ASSERT(!m_isMutable);
     227    return reinterpret_cast<const StylePropertyMetadata*>(&reinterpret_cast<const char*>((&static_cast<const ImmutableStylePropertySet*>(this)->m_storage))[m_arraySize * sizeof(CSSValue*)]);
     228}
    202229
    203230class MutableStylePropertySet : public StylePropertySet {
     
    212239};
    213240
    214 inline CSSProperty& StylePropertySet::propertyAtInternal(unsigned index)
    215 {
    216     if (m_isMutable)
    217         return mutablePropertyVector().at(index);
    218     return const_cast<CSSProperty*>(immutablePropertyArray())[index];
    219 }
    220 
    221 inline const CSSProperty& StylePropertySet::propertyAtInternal(unsigned index) const
    222 {
    223     if (m_isMutable)
    224         return mutablePropertyVector().at(index);
    225     return immutablePropertyArray()[index];
    226 }
    227 
    228241inline Vector<CSSProperty, 4>& StylePropertySet::mutablePropertyVector()
    229242{
     
    236249    ASSERT(m_isMutable);
    237250    return static_cast<const MutableStylePropertySet*>(this)->m_propertyVector;
    238 }
    239 
    240 inline const CSSProperty* StylePropertySet::immutablePropertyArray() const
    241 {
    242     ASSERT(!m_isMutable);
    243     return reinterpret_cast<const CSSProperty*>(&static_cast<const ImmutableStylePropertySet*>(this)->m_propertyArray);
    244251}
    245252
Note: See TracChangeset for help on using the changeset viewer.