RenderStyle should use copy-on-write inheritance for NinePieceImage.
authorakling@apple.com <akling@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 10 Feb 2013 16:04:43 +0000 (16:04 +0000)
committerakling@apple.com <akling@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 10 Feb 2013 16:04:43 +0000 (16:04 +0000)
<http://webkit.org/b/109366>

Reviewed by Antti Koivisto.

Refactor NinePieceImage to hold a copy-on-write DataRef like other RenderStyle substructures.
This allows us to avoids copying the NinePieceImageData when one RenderStyle inherits from another
but modifies something in the substructure holding the NinePieceImage (typically StyleSurroundData.)

Also made RenderStyle not copy-on-write its StyleSurroundData prematurely when doing a no-op write
to a border-image related value.

1.23 MB progression on Membuster3.

* rendering/style/NinePieceImage.cpp:
(WebCore::defaultData):
(WebCore::NinePieceImage::NinePieceImage):
(WebCore::NinePieceImageData::NinePieceImageData):
(WebCore::NinePieceImageData::operator==):
* rendering/style/NinePieceImage.h:
(WebCore::NinePieceImageData::create):
(WebCore::NinePieceImageData::copy):
(NinePieceImageData):
(NinePieceImage):
(WebCore::NinePieceImage::operator==):
(WebCore::NinePieceImage::operator!=):
(WebCore::NinePieceImage::hasImage):
(WebCore::NinePieceImage::image):
(WebCore::NinePieceImage::setImage):
(WebCore::NinePieceImage::imageSlices):
(WebCore::NinePieceImage::setImageSlices):
(WebCore::NinePieceImage::fill):
(WebCore::NinePieceImage::setFill):
(WebCore::NinePieceImage::borderSlices):
(WebCore::NinePieceImage::setBorderSlices):
(WebCore::NinePieceImage::outset):
(WebCore::NinePieceImage::setOutset):
(WebCore::NinePieceImage::horizontalRule):
(WebCore::NinePieceImage::setHorizontalRule):
(WebCore::NinePieceImage::verticalRule):
(WebCore::NinePieceImage::setVerticalRule):
(WebCore::NinePieceImage::copyImageSlicesFrom):
(WebCore::NinePieceImage::copyBorderSlicesFrom):
(WebCore::NinePieceImage::copyOutsetFrom):
(WebCore::NinePieceImage::copyRepeatFrom):
(WebCore::NinePieceImage::setMaskDefaults):
(WebCore::NinePieceImage::computeOutset):
* rendering/style/RenderStyle.cpp:
(WebCore::RenderStyle::setBorderImageSource):
(WebCore::RenderStyle::setBorderImageSlices):
(WebCore::RenderStyle::setBorderImageWidth):
(WebCore::RenderStyle::setBorderImageOutset):
* rendering/style/RenderStyle.h:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@142404 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/rendering/style/NinePieceImage.cpp
Source/WebCore/rendering/style/NinePieceImage.h
Source/WebCore/rendering/style/RenderStyle.cpp
Source/WebCore/rendering/style/RenderStyle.h

index 84a87f73ca7d6727698acf118d8039c338e8b0e0..eb0ba3a4b3345d7961ab52cf901060a0233dd3cb 100644 (file)
@@ -1,3 +1,59 @@
+2013-02-10  Andreas Kling  <akling@apple.com>
+
+        RenderStyle should use copy-on-write inheritance for NinePieceImage.
+        <http://webkit.org/b/109366>
+
+        Reviewed by Antti Koivisto.
+
+        Refactor NinePieceImage to hold a copy-on-write DataRef like other RenderStyle substructures.
+        This allows us to avoids copying the NinePieceImageData when one RenderStyle inherits from another
+        but modifies something in the substructure holding the NinePieceImage (typically StyleSurroundData.)
+
+        Also made RenderStyle not copy-on-write its StyleSurroundData prematurely when doing a no-op write
+        to a border-image related value.
+
+        1.23 MB progression on Membuster3.
+
+        * rendering/style/NinePieceImage.cpp:
+        (WebCore::defaultData):
+        (WebCore::NinePieceImage::NinePieceImage):
+        (WebCore::NinePieceImageData::NinePieceImageData):
+        (WebCore::NinePieceImageData::operator==):
+        * rendering/style/NinePieceImage.h:
+        (WebCore::NinePieceImageData::create):
+        (WebCore::NinePieceImageData::copy):
+        (NinePieceImageData):
+        (NinePieceImage):
+        (WebCore::NinePieceImage::operator==):
+        (WebCore::NinePieceImage::operator!=):
+        (WebCore::NinePieceImage::hasImage):
+        (WebCore::NinePieceImage::image):
+        (WebCore::NinePieceImage::setImage):
+        (WebCore::NinePieceImage::imageSlices):
+        (WebCore::NinePieceImage::setImageSlices):
+        (WebCore::NinePieceImage::fill):
+        (WebCore::NinePieceImage::setFill):
+        (WebCore::NinePieceImage::borderSlices):
+        (WebCore::NinePieceImage::setBorderSlices):
+        (WebCore::NinePieceImage::outset):
+        (WebCore::NinePieceImage::setOutset):
+        (WebCore::NinePieceImage::horizontalRule):
+        (WebCore::NinePieceImage::setHorizontalRule):
+        (WebCore::NinePieceImage::verticalRule):
+        (WebCore::NinePieceImage::setVerticalRule):
+        (WebCore::NinePieceImage::copyImageSlicesFrom):
+        (WebCore::NinePieceImage::copyBorderSlicesFrom):
+        (WebCore::NinePieceImage::copyOutsetFrom):
+        (WebCore::NinePieceImage::copyRepeatFrom):
+        (WebCore::NinePieceImage::setMaskDefaults):
+        (WebCore::NinePieceImage::computeOutset):
+        * rendering/style/RenderStyle.cpp:
+        (WebCore::RenderStyle::setBorderImageSource):
+        (WebCore::RenderStyle::setBorderImageSlices):
+        (WebCore::RenderStyle::setBorderImageWidth):
+        (WebCore::RenderStyle::setBorderImageOutset):
+        * rendering/style/RenderStyle.h:
+
 2013-02-10  Kent Tamura  <tkent@chromium.org>
 
         Unreviewed, rolling out r142343.
index 18a107e8a6743b45d68d3cd88215cbf38664e187..a463d815b4a3e3dd6c27e8259f10fc2277266ec1 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
  *           (C) 2000 Antti Koivisto (koivisto@kde.org)
  *           (C) 2000 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008, 2013 Apple Inc. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
 
 namespace WebCore {
 
-bool NinePieceImageData::operator==(const NinePieceImageData& o) const
+static DataRef<NinePieceImageData>& defaultData()
 {
-    return StyleImage::imagesEquivalent(m_image.get(), o.m_image.get()) && m_imageSlices == o.m_imageSlices && m_fill == o.m_fill
-           && m_borderSlices == o.m_borderSlices && m_outset == o.m_outset && m_horizontalRule == o.m_horizontalRule && m_verticalRule == o.m_verticalRule;
+    static DataRef<NinePieceImageData>* data = new DataRef<NinePieceImageData>;
+    if (!data->get())
+        data->init();
+    return *data;
 }
 
-const NinePieceImageData& NinePieceImage::defaultData()
+NinePieceImage::NinePieceImage()
+    : m_data(defaultData())
 {
-    DEFINE_STATIC_LOCAL(NinePieceImageData, data, ());
-    return data;
+}
+
+NinePieceImage::NinePieceImage(PassRefPtr<StyleImage> image, LengthBox imageSlices, bool fill, LengthBox borderSlices, LengthBox outset, ENinePieceImageRule horizontalRule, ENinePieceImageRule verticalRule)
+{
+    m_data.init();
+    m_data.access()->image = image;
+    m_data.access()->imageSlices = imageSlices;
+    m_data.access()->borderSlices = borderSlices;
+    m_data.access()->outset = outset;
+    m_data.access()->fill = fill;
+    m_data.access()->horizontalRule = horizontalRule;
+    m_data.access()->verticalRule = verticalRule;
+}
+
+NinePieceImageData::NinePieceImageData()
+    : fill(false)
+    , horizontalRule(StretchImageRule)
+    , verticalRule(StretchImageRule)
+    , image(0)
+    , imageSlices(Length(100, Percent), Length(100, Percent), Length(100, Percent), Length(100, Percent))
+    , borderSlices(Length(1, Relative), Length(1, Relative), Length(1, Relative), Length(1, Relative))
+    , outset(0)
+{
+}
+
+NinePieceImageData::NinePieceImageData(const NinePieceImageData& other)
+    : RefCounted<NinePieceImageData>()
+    , fill(other.fill)
+    , horizontalRule(other.horizontalRule)
+    , verticalRule(other.verticalRule)
+    , image(other.image)
+    , imageSlices(other.imageSlices)
+    , borderSlices(other.borderSlices)
+    , outset(other.outset)
+{
+}
+
+bool NinePieceImageData::operator==(const NinePieceImageData& other) const
+{
+    return StyleImage::imagesEquivalent(image.get(), other.image.get())
+        && imageSlices == other.imageSlices
+        && fill == other.fill
+        && borderSlices == other.borderSlices
+        && outset == other.outset
+        && horizontalRule == other.horizontalRule
+        && verticalRule == other.verticalRule;
 }
 
 }
index fd007cea1f93508ce90006ed49791faa08b46248..0f3b339eaa0fbed089ade57a83eb29e1c5af9575 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
  *           (C) 2000 Antti Koivisto (koivisto@kde.org)
  *           (C) 2000 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008, 2013 Apple Inc. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -24,6 +24,7 @@
 #ifndef NinePieceImage_h
 #define NinePieceImage_h
 
+#include "DataRef.h"
 #include "LayoutUnit.h"
 #include "LengthBox.h"
 #include "StyleImage.h"
@@ -34,149 +35,95 @@ enum ENinePieceImageRule {
     StretchImageRule, RoundImageRule, SpaceImageRule, RepeatImageRule
 };
 
-class NinePieceImageData {
-    WTF_MAKE_FAST_ALLOCATED;
+class NinePieceImageData : public RefCounted<NinePieceImageData> {
 public:
-    NinePieceImageData()
-        : m_image(0)
-        , m_imageSlices(Length(100, Percent), Length(100, Percent), Length(100, Percent), Length(100, Percent))
-        , m_borderSlices(Length(1, Relative), Length(1, Relative), Length(1, Relative), Length(1, Relative))
-        , m_outset(0)
-        , m_fill(false)
-        , m_horizontalRule(StretchImageRule)
-        , m_verticalRule(StretchImageRule)
-    {
-    }
-
-    NinePieceImageData(PassRefPtr<StyleImage> image, LengthBox imageSlices, bool fill, LengthBox borderSlices, LengthBox outset, ENinePieceImageRule h, ENinePieceImageRule v)
-      : m_image(image)
-      , m_imageSlices(imageSlices)
-      , m_borderSlices(borderSlices)
-      , m_outset(outset)
-      , m_fill(fill)
-      , m_horizontalRule(h)
-      , m_verticalRule(v)
-    {
-    }
+    static PassRefPtr<NinePieceImageData> create() { return adoptRef(new NinePieceImageData); }
+    PassRefPtr<NinePieceImageData> copy() const { return adoptRef(new NinePieceImageData(*this)); }
 
     bool operator==(const NinePieceImageData&) const;
     bool operator!=(const NinePieceImageData& o) const { return !(*this == o); }
 
-    RefPtr<StyleImage> m_image;
-    LengthBox m_imageSlices;
-    LengthBox m_borderSlices;
-    LengthBox m_outset;
-    bool m_fill : 1;
-    unsigned m_horizontalRule : 2; // ENinePieceImageRule
-    unsigned m_verticalRule : 2; // ENinePieceImageRule
+    bool fill : 1;
+    unsigned horizontalRule : 2; // ENinePieceImageRule
+    unsigned verticalRule : 2; // ENinePieceImageRule
+    RefPtr<StyleImage> image;
+    LengthBox imageSlices;
+    LengthBox borderSlices;
+    LengthBox outset;
+
+private:
+    NinePieceImageData();
+    NinePieceImageData(const NinePieceImageData&);
 };
 
 class NinePieceImage {
 public:
-    NinePieceImage() { }
-
-    NinePieceImage(PassRefPtr<StyleImage> image, LengthBox imageSlices, bool fill, LengthBox borderSlices, LengthBox outset, ENinePieceImageRule h, ENinePieceImageRule v)
-        : m_data(adoptPtr(new NinePieceImageData(image, imageSlices, fill, borderSlices, outset, h, v)))
-    { }
+    NinePieceImage();
+    NinePieceImage(PassRefPtr<StyleImage>, LengthBox imageSlices, bool fill, LengthBox borderSlices, LengthBox outset, ENinePieceImageRule horizontalRule, ENinePieceImageRule verticalRule);
 
-    NinePieceImage(const NinePieceImage& other)
-    {
-        *this = other;
-    }
-
-    void operator=(const NinePieceImage& other)
-    {
-        if (!other.m_data) {
-            m_data.clear();
-            return;
-        }
-        const NinePieceImageData& otherData = other.data();
-        m_data = adoptPtr(new NinePieceImageData(otherData.m_image, otherData.m_imageSlices, otherData.m_fill, otherData.m_borderSlices, otherData.m_outset, static_cast<ENinePieceImageRule>(otherData.m_horizontalRule), static_cast<ENinePieceImageRule>(otherData.m_verticalRule)));
-    }
-
-    bool operator==(const NinePieceImage& other) const { return data() == other.data(); }
-    bool operator!=(const NinePieceImage& other) const { return !(*this == other); }
+    bool operator==(const NinePieceImage& other) const { return m_data == other.m_data; }
+    bool operator!=(const NinePieceImage& other) const { return m_data != other.m_data; }
 
-    bool hasImage() const { return m_data && m_data->m_image; }
-    StyleImage* image() const { return m_data ? m_data->m_image.get() : 0; }
-    void setImage(PassRefPtr<StyleImage> image) { ensureData(); m_data->m_image = image; }
+    bool hasImage() const { return m_data->image; }
+    StyleImage* image() const { return m_data->image.get(); }
+    void setImage(PassRefPtr<StyleImage> image) { m_data.access()->image = image; }
     
-    const LengthBox& imageSlices() const { return data().m_imageSlices; }
-    void setImageSlices(const LengthBox& slices) { ensureData(); m_data->m_imageSlices = slices; }
+    const LengthBox& imageSlices() const { return m_data->imageSlices; }
+    void setImageSlices(const LengthBox& slices) { m_data.access()->imageSlices = slices; }
 
-    bool fill() const { return data().m_fill; }
-    void setFill(bool fill) { ensureData(); m_data->m_fill = fill; }
+    bool fill() const { return m_data->fill; }
+    void setFill(bool fill) { m_data.access()->fill = fill; }
 
-    const LengthBox& borderSlices() const { return data().m_borderSlices; }
-    void setBorderSlices(const LengthBox& slices) { ensureData(); m_data->m_borderSlices = slices; }
+    const LengthBox& borderSlices() const { return m_data->borderSlices; }
+    void setBorderSlices(const LengthBox& slices) { m_data.access()->borderSlices = slices; }
 
-    const LengthBox& outset() const { return data().m_outset; }
-    void setOutset(const LengthBox& outset) { ensureData(); m_data->m_outset = outset; }
-    
-    static LayoutUnit computeOutset(Length outsetSide, LayoutUnit borderSide)
-    {
-        if (outsetSide.isRelative())
-            return outsetSide.value() * borderSide;
-        return outsetSide.value();
-    }
+    const LengthBox& outset() const { return m_data->outset; }
+    void setOutset(const LengthBox& outset) { m_data.access()->outset = outset; }
 
-    ENinePieceImageRule horizontalRule() const { return static_cast<ENinePieceImageRule>(data().m_horizontalRule); }
-    void setHorizontalRule(ENinePieceImageRule rule) { ensureData(); m_data->m_horizontalRule = rule; }
+    ENinePieceImageRule horizontalRule() const { return static_cast<ENinePieceImageRule>(m_data->horizontalRule); }
+    void setHorizontalRule(ENinePieceImageRule rule) { m_data.access()->horizontalRule = rule; }
     
-    ENinePieceImageRule verticalRule() const { return static_cast<ENinePieceImageRule>(data().m_verticalRule); }
-    void setVerticalRule(ENinePieceImageRule rule) { ensureData(); m_data->m_verticalRule = rule; }
+    ENinePieceImageRule verticalRule() const { return static_cast<ENinePieceImageRule>(m_data->verticalRule); }
+    void setVerticalRule(ENinePieceImageRule rule) { m_data.access()->verticalRule = rule; }
 
     void copyImageSlicesFrom(const NinePieceImage& other)
     {
-        ensureData();
-        m_data->m_imageSlices = other.data().m_imageSlices;
-        m_data->m_fill = other.data().m_fill;
+        m_data.access()->imageSlices = other.m_data->imageSlices;
+        m_data.access()->fill = other.m_data->fill;
     }
 
     void copyBorderSlicesFrom(const NinePieceImage& other)
     {
-        ensureData();
-        m_data->m_borderSlices = other.data().m_borderSlices;
+        m_data.access()->borderSlices = other.m_data->borderSlices;
     }
     
     void copyOutsetFrom(const NinePieceImage& other)
     {
-        ensureData();
-        m_data->m_outset = other.data().m_outset;
+        m_data.access()->outset = other.m_data->outset;
     }
 
     void copyRepeatFrom(const NinePieceImage& other)
     {
-        ensureData();
-        m_data->m_horizontalRule = other.data().m_horizontalRule;
-        m_data->m_verticalRule = other.data().m_verticalRule;
+        m_data.access()->horizontalRule = other.m_data->horizontalRule;
+        m_data.access()->verticalRule = other.m_data->verticalRule;
     }
 
     void setMaskDefaults()
     {
-        ensureData();
-        m_data->m_imageSlices = LengthBox(0);
-        m_data->m_fill = true;
-        m_data->m_borderSlices = LengthBox();
+        m_data.access()->imageSlices = LengthBox(0);
+        m_data.access()->fill = true;
+        m_data.access()->borderSlices = LengthBox();
     }
 
-private:
-    static const NinePieceImageData& defaultData();
-
-    void ensureData()
-    {
-        if (!m_data)
-            m_data = adoptPtr(new NinePieceImageData);
-    }
-
-    const NinePieceImageData& data() const
+    static LayoutUnit computeOutset(Length outsetSide, LayoutUnit borderSide)
     {
-        if (m_data)
-            return *m_data;
-        return defaultData();
+        if (outsetSide.isRelative())
+            return outsetSide.value() * borderSide;
+        return outsetSide.value();
     }
 
-    OwnPtr<NinePieceImageData> m_data;
+private:
+    DataRef<NinePieceImageData> m_data;
 };
 
 } // namespace WebCore
index e89093a0dec84704f8760012a209ac526efd47b9..cefc3c120e1988debaa7216e13ca7c07a9934b21 100644 (file)
@@ -1606,6 +1606,34 @@ LayoutBoxExtent RenderStyle::imageOutsets(const NinePieceImage& image) const
                            NinePieceImage::computeOutset(image.outset().left(), borderLeftWidth()));
 }
 
+void RenderStyle::setBorderImageSource(PassRefPtr<StyleImage> image)
+{
+    if (surround->border.m_image.image() == image.get())
+        return;
+    surround.access()->border.m_image.setImage(image);
+}
+
+void RenderStyle::setBorderImageSlices(LengthBox slices)
+{
+    if (surround->border.m_image.imageSlices() == slices)
+        return;
+    surround.access()->border.m_image.setImageSlices(slices);
+}
+
+void RenderStyle::setBorderImageWidth(LengthBox slices)
+{
+    if (surround->border.m_image.borderSlices() == slices)
+        return;
+    surround.access()->border.m_image.setBorderSlices(slices);
+}
+
+void RenderStyle::setBorderImageOutset(LengthBox outset)
+{
+    if (surround->border.m_image.outset() == outset)
+        return;
+    surround.access()->border.m_image.setOutset(outset);
+}
+
 void RenderStyle::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
 {
     MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::CSS);
index f5e5cd37cbfd9fe838d10429744ab35c9cdd8ebc..02cf0c9971779b197f0b0a8846fd9e57118ec232 100644 (file)
@@ -1020,10 +1020,10 @@ public:
     void setBackgroundSizeLength(LengthSize s) { SET_VAR(m_background, m_background.m_sizeLength, s); }
     
     void setBorderImage(const NinePieceImage& b) { SET_VAR(surround, border.m_image, b); }
-    void setBorderImageSource(PassRefPtr<StyleImage> v) { surround.access()->border.m_image.setImage(v); }
-    void setBorderImageSlices(LengthBox slices) { surround.access()->border.m_image.setImageSlices(slices); }
-    void setBorderImageWidth(LengthBox slices) { surround.access()->border.m_image.setBorderSlices(slices); }
-    void setBorderImageOutset(LengthBox outset) { surround.access()->border.m_image.setOutset(outset); }
+    void setBorderImageSource(PassRefPtr<StyleImage>);
+    void setBorderImageSlices(LengthBox);
+    void setBorderImageWidth(LengthBox);
+    void setBorderImageOutset(LengthBox);
 
     void setBorderTopLeftRadius(LengthSize s) { SET_VAR(surround, border.m_topLeft, s); }
     void setBorderTopRightRadius(LengthSize s) { SET_VAR(surround, border.m_topRight, s); }