- Revision
- 201561
- Author
- [email protected]
- Date
- 2016-06-01 11:50:09 -0700 (Wed, 01 Jun 2016)
Log Message
SVGImage should report its memory cost to JS garbage collector
https://bugs.webkit.org/show_bug.cgi?id=158139
Patch by Said Abou-Hallawa <[email protected]> on 2016-06-01
Reviewed by Geoffrey Garen.
Like what we do in HTMLImageLoader::notifyFinished() by reporting the memory
cost of the BitmapImage, we need to do something similar for the SVGImage. In
SVGImage::dataChange() and when allDataReceived is true, we can calculate
the size of all DOM nodes and their renderers. The size of the encoded data
has to be added as well to the total memory cost. An approximation for the
memory cost has to be used since it is costly to get an accurate number.
* bindings/js/JSDocumentCustom.cpp:
(WebCore::reportMemoryForDocumentIfFrameless): Use Node::approximateMemoryCost()
instead of sizeof(Node). A Node's descendant can override this function and
return a more accurate memory cost.
* dom/Node.h:
(WebCore::Node::approximateMemoryCost): Define this new virtual function in the
Node class. Its default value is sizeof(Node) but any descendant can return a
more accurate number.
* platform/graphics/Image.h:
(WebCore::Image::data): Define a const version of data() so it can be called
the const function SVGImage::reportApproximateMemoryCost().
* svg/SVGGraphicsElement.h: Override approximateMemoryCost() to return
sizeof(SVGGraphicsElement).
* svg/SVGPathElement.cpp:
(WebCore::SVGPathElement::approximateMemoryCost): Override this function to return
the memory cost of the points and the m_path of the renderer.
* svg/SVGPathElement.h:
* svg/SVGPolyElement.cpp:
(WebCore::SVGPolyElement::approximateMemoryCost): Override this function to return
the memory cost of the points and the m_path of the renderer.
* svg/SVGPolyElement.h:
* svg/graphics/SVGImage.cpp:
(WebCore::SVGImage::reportApproximateMemoryCost): Calculate the memory cost of the
nodes in the SVGDocument of an SVGImage. Then report this number to the JS garbage
collector.
(WebCore::SVGImage::dataChanged): After loading all the SVG encoded data and building
its DOM tree and the render tree, report the total memory cost to the JS garbage collector.
* svg/graphics/SVGImage.h:
Modified Paths
Diff
Modified: trunk/Source/WebCore/ChangeLog (201560 => 201561)
--- trunk/Source/WebCore/ChangeLog 2016-06-01 18:17:06 UTC (rev 201560)
+++ trunk/Source/WebCore/ChangeLog 2016-06-01 18:50:09 UTC (rev 201561)
@@ -1,3 +1,53 @@
+2016-06-01 Said Abou-Hallawa <[email protected]>
+
+ SVGImage should report its memory cost to JS garbage collector
+ https://bugs.webkit.org/show_bug.cgi?id=158139
+
+ Reviewed by Geoffrey Garen.
+
+ Like what we do in HTMLImageLoader::notifyFinished() by reporting the memory
+ cost of the BitmapImage, we need to do something similar for the SVGImage. In
+ SVGImage::dataChange() and when allDataReceived is true, we can calculate
+ the size of all DOM nodes and their renderers. The size of the encoded data
+ has to be added as well to the total memory cost. An approximation for the
+ memory cost has to be used since it is costly to get an accurate number.
+
+ * bindings/js/JSDocumentCustom.cpp:
+ (WebCore::reportMemoryForDocumentIfFrameless): Use Node::approximateMemoryCost()
+ instead of sizeof(Node). A Node's descendant can override this function and
+ return a more accurate memory cost.
+
+ * dom/Node.h:
+ (WebCore::Node::approximateMemoryCost): Define this new virtual function in the
+ Node class. Its default value is sizeof(Node) but any descendant can return a
+ more accurate number.
+
+ * platform/graphics/Image.h:
+ (WebCore::Image::data): Define a const version of data() so it can be called
+ the const function SVGImage::reportApproximateMemoryCost().
+
+ * svg/SVGGraphicsElement.h: Override approximateMemoryCost() to return
+ sizeof(SVGGraphicsElement).
+
+ * svg/SVGPathElement.cpp:
+ (WebCore::SVGPathElement::approximateMemoryCost): Override this function to return
+ the memory cost of the points and the m_path of the renderer.
+ * svg/SVGPathElement.h:
+
+ * svg/SVGPolyElement.cpp:
+ (WebCore::SVGPolyElement::approximateMemoryCost): Override this function to return
+ the memory cost of the points and the m_path of the renderer.
+ * svg/SVGPolyElement.h:
+
+ * svg/graphics/SVGImage.cpp:
+ (WebCore::SVGImage::reportApproximateMemoryCost): Calculate the memory cost of the
+ nodes in the SVGDocument of an SVGImage. Then report this number to the JS garbage
+ collector.
+
+ (WebCore::SVGImage::dataChanged): After loading all the SVG encoded data and building
+ its DOM tree and the render tree, report the total memory cost to the JS garbage collector.
+ * svg/graphics/SVGImage.h:
+
2016-06-01 Andreas Kling <[email protected]>
Use inline capacity for StylePropertyShorthand Vectors.
Modified: trunk/Source/WebCore/bindings/js/JSDocumentCustom.cpp (201560 => 201561)
--- trunk/Source/WebCore/bindings/js/JSDocumentCustom.cpp 2016-06-01 18:17:06 UTC (rev 201560)
+++ trunk/Source/WebCore/bindings/js/JSDocumentCustom.cpp 2016-06-01 18:50:09 UTC (rev 201561)
@@ -89,13 +89,13 @@
if (document.frame())
return;
- size_t nodeCount = 0;
+ size_t memoryCost = 0;
for (Node* node = &document; node; node = NodeTraversal::next(*node))
- ++nodeCount;
+ memoryCost += node->approximateMemoryCost();
// FIXME: Adopt reportExtraMemoryVisited, and switch to reportExtraMemoryAllocated.
// https://bugs.webkit.org/show_bug.cgi?id=142595
- state.heap()->deprecatedReportExtraMemory(nodeCount * sizeof(Node));
+ state.heap()->deprecatedReportExtraMemory(memoryCost);
}
JSValue toJSNewlyCreated(ExecState* state, JSDOMGlobalObject* globalObject, Ref<Document>&& document)
Modified: trunk/Source/WebCore/dom/Node.h (201560 => 201561)
--- trunk/Source/WebCore/dom/Node.h 2016-06-01 18:17:06 UTC (rev 201560)
+++ trunk/Source/WebCore/dom/Node.h 2016-06-01 18:50:09 UTC (rev 201561)
@@ -143,6 +143,7 @@
virtual String nodeValue() const;
virtual void setNodeValue(const String&, ExceptionCode&);
virtual NodeType nodeType() const = 0;
+ virtual size_t approximateMemoryCost() const { return sizeof(*this); }
ContainerNode* parentNode() const;
static ptrdiff_t parentNodeMemoryOffset() { return OBJECT_OFFSETOF(Node, m_parentNode); }
Element* parentElement() const;
Modified: trunk/Source/WebCore/platform/graphics/Image.h (201560 => 201561)
--- trunk/Source/WebCore/platform/graphics/Image.h 2016-06-01 18:17:06 UTC (rev 201560)
+++ trunk/Source/WebCore/platform/graphics/Image.h 2016-06-01 18:50:09 UTC (rev 201561)
@@ -122,6 +122,7 @@
virtual void destroyDecodedData(bool destroyAll = true) = 0;
SharedBuffer* data() { return m_encodedImageData.get(); }
+ const SharedBuffer* data() const { return m_encodedImageData.get(); }
// Animation begins whenever someone draws the image, so startAnimation() is not normally called.
// It will automatically pause once all observers no longer want to render the image anywhere.
Modified: trunk/Source/WebCore/svg/SVGGraphicsElement.h (201560 => 201561)
--- trunk/Source/WebCore/svg/SVGGraphicsElement.h 2016-06-01 18:17:06 UTC (rev 201560)
+++ trunk/Source/WebCore/svg/SVGGraphicsElement.h 2016-06-01 18:50:09 UTC (rev 201561)
@@ -53,6 +53,8 @@
virtual void toClipPath(Path&);
RenderPtr<RenderElement> createElementRenderer(RenderStyle&&, const RenderTreePosition&) override;
+ size_t approximateMemoryCost() const override { return sizeof(*this); }
+
protected:
SVGGraphicsElement(const QualifiedName&, Document&);
Modified: trunk/Source/WebCore/svg/SVGPathElement.cpp (201560 => 201561)
--- trunk/Source/WebCore/svg/SVGPathElement.cpp 2016-06-01 18:17:06 UTC (rev 201560)
+++ trunk/Source/WebCore/svg/SVGPathElement.cpp 2016-06-01 18:50:09 UTC (rev 201561)
@@ -363,6 +363,14 @@
return nullptr;
}
+size_t SVGPathElement::approximateMemoryCost() const
+{
+ // This is an approximation for path memory cost since the path is parsed on demand.
+ size_t pathMemoryCost = (m_pathByteStream.size() / 10) * sizeof(FloatPoint);
+ // We need to account for the memory which is allocated by the RenderSVGPath::m_path.
+ return sizeof(*this) + (renderer() ? pathMemoryCost * 2 + sizeof(RenderSVGPath) : pathMemoryCost);
+}
+
void SVGPathElement::pathSegListChanged(SVGPathSegRole role, ListModification listModification)
{
switch (role) {
Modified: trunk/Source/WebCore/svg/SVGPathElement.h (201560 => 201561)
--- trunk/Source/WebCore/svg/SVGPathElement.h 2016-06-01 18:17:06 UTC (rev 201560)
+++ trunk/Source/WebCore/svg/SVGPathElement.h 2016-06-01 18:50:09 UTC (rev 201561)
@@ -101,6 +101,8 @@
void animatedPropertyWillBeDeleted();
+ size_t approximateMemoryCost() const override;
+
private:
SVGPathElement(const QualifiedName&, Document&);
Modified: trunk/Source/WebCore/svg/SVGPolyElement.cpp (201560 => 201561)
--- trunk/Source/WebCore/svg/SVGPolyElement.cpp 2016-06-01 18:17:06 UTC (rev 201560)
+++ trunk/Source/WebCore/svg/SVGPolyElement.cpp 2016-06-01 18:50:09 UTC (rev 201561)
@@ -130,4 +130,11 @@
return static_cast<SVGListPropertyTearOff<SVGPointList>*>(static_reference_cast<SVGAnimatedPointList>(lookupOrCreatePointsWrapper(this))->animVal().get());
}
+size_t SVGPolyElement::approximateMemoryCost() const
+{
+ size_t pointsCost = pointList().size() * sizeof(FloatPoint);
+ // We need to account for the memory which is allocated by the RenderSVGPath::m_path.
+ return sizeof(*this) + (renderer() ? pointsCost * 2 + sizeof(RenderSVGPath) : pointsCost);
}
+
+}
Modified: trunk/Source/WebCore/svg/SVGPolyElement.h (201560 => 201561)
--- trunk/Source/WebCore/svg/SVGPolyElement.h 2016-06-01 18:17:06 UTC (rev 201560)
+++ trunk/Source/WebCore/svg/SVGPolyElement.h 2016-06-01 18:50:09 UTC (rev 201561)
@@ -38,6 +38,8 @@
static const SVGPropertyInfo* pointsPropertyInfo();
+ size_t approximateMemoryCost() const override;
+
protected:
SVGPolyElement(const QualifiedName&, Document&);
Modified: trunk/Source/WebCore/svg/graphics/SVGImage.cpp (201560 => 201561)
--- trunk/Source/WebCore/svg/graphics/SVGImage.cpp 2016-06-01 18:17:06 UTC (rev 201560)
+++ trunk/Source/WebCore/svg/graphics/SVGImage.cpp 2016-06-01 18:50:09 UTC (rev 201561)
@@ -29,6 +29,7 @@
#include "SVGImage.h"
#include "Chrome.h"
+#include "DOMWindow.h"
#include "DocumentLoader.h"
#include "ElementIterator.h"
#include "FrameLoader.h"
@@ -36,6 +37,7 @@
#include "ImageBuffer.h"
#include "ImageObserver.h"
#include "IntRect.h"
+#include "JSDOMWindowBase.h"
#include "MainFrame.h"
#include "PageConfiguration.h"
#include "RenderSVGRoot.h"
@@ -48,6 +50,8 @@
#include "SVGSVGElement.h"
#include "Settings.h"
#include "TextStream.h"
+#include <runtime/JSCInlines.h>
+#include <runtime/JSLock.h>
namespace WebCore {
@@ -353,6 +357,21 @@
stopAnimation();
}
+void SVGImage::reportApproximateMemoryCost() const
+{
+ Document* document = m_page->mainFrame().document();
+ size_t decodedImageMemoryCost = 0;
+
+ for (Node* node = document; node; node = NodeTraversal::next(*node))
+ decodedImageMemoryCost += node->approximateMemoryCost();
+
+ JSC::VM& vm = JSDOMWindowBase::commonVM();
+ JSC::JSLockHolder lock(vm);
+ // FIXME: Adopt reportExtraMemoryVisited, and switch to reportExtraMemoryAllocated.
+ // https://bugs.webkit.org/show_bug.cgi?id=142595
+ vm.heap.deprecatedReportExtraMemory(decodedImageMemoryCost + data()->size());
+}
+
bool SVGImage::dataChanged(bool allDataReceived)
{
// Don't do anything if is an empty image.
@@ -393,6 +412,7 @@
// Set the intrinsic size before a container size is available.
m_intrinsicSize = containerSize();
+ reportApproximateMemoryCost();
}
return m_page != nullptr;
Modified: trunk/Source/WebCore/svg/graphics/SVGImage.h (201560 => 201561)
--- trunk/Source/WebCore/svg/graphics/SVGImage.h 2016-06-01 18:17:06 UTC (rev 201560)
+++ trunk/Source/WebCore/svg/graphics/SVGImage.h 2016-06-01 18:50:09 UTC (rev 201561)
@@ -82,6 +82,7 @@
bool usesContainerSize() const override { return true; }
void computeIntrinsicDimensions(Length& intrinsicWidth, Length& intrinsicHeight, FloatSize& intrinsicRatio) override;
+ void reportApproximateMemoryCost() const;
bool dataChanged(bool allDataReceived) override;
// FIXME: SVGImages will be unable to prune because this function is not implemented yet.