mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 10:44:56 +00:00
Bug 1383982 (attempt 2) - Introduce a general mechanism for measuring memory usage of graph-like structures. r=erahm.
--HG-- extra : rebase_source : 7075f9570a4262158351ce9ac3ca8360ea4d5394
This commit is contained in:
parent
3075bc5440
commit
49eb219ff5
@ -67,6 +67,7 @@
|
||||
#include "mozilla/EventStates.h"
|
||||
#include "mozilla/InternalMutationEvent.h"
|
||||
#include "mozilla/MouseEvents.h"
|
||||
#include "mozilla/SizeOfState.h"
|
||||
#include "mozilla/TextEditor.h"
|
||||
#include "mozilla/TextEvents.h"
|
||||
#include "nsNodeUtils.h"
|
||||
@ -4137,3 +4138,14 @@ Element::SetCustomElementData(CustomElementData* aData)
|
||||
MOZ_ASSERT(!slots->mCustomElementData, "Custom element data may not be changed once set.");
|
||||
slots->mCustomElementData = aData;
|
||||
}
|
||||
|
||||
size_t
|
||||
Element::SizeOfExcludingThis(SizeOfState& aState) const
|
||||
{
|
||||
size_t n = FragmentOrElement::SizeOfExcludingThis(aState);
|
||||
|
||||
// XXX: measure mServoData.
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
|
@ -205,6 +205,8 @@ public:
|
||||
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_ELEMENT_IID)
|
||||
|
||||
NS_DECL_SIZEOF_EXCLUDING_THIS
|
||||
|
||||
NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) override;
|
||||
|
||||
/**
|
||||
|
@ -2497,15 +2497,15 @@ FragmentOrElement::FireNodeRemovedForChildren()
|
||||
}
|
||||
|
||||
size_t
|
||||
FragmentOrElement::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
|
||||
FragmentOrElement::SizeOfExcludingThis(SizeOfState& aState) const
|
||||
{
|
||||
size_t n = 0;
|
||||
n += nsIContent::SizeOfExcludingThis(aMallocSizeOf);
|
||||
n += mAttrsAndChildren.SizeOfExcludingThis(aMallocSizeOf);
|
||||
n += nsIContent::SizeOfExcludingThis(aState);
|
||||
n += mAttrsAndChildren.SizeOfExcludingThis(aState.mMallocSizeOf);
|
||||
|
||||
nsDOMSlots* slots = GetExistingDOMSlots();
|
||||
if (slots) {
|
||||
n += slots->SizeOfIncludingThis(aMallocSizeOf);
|
||||
n += slots->SizeOfIncludingThis(aState.mMallocSizeOf);
|
||||
}
|
||||
|
||||
return n;
|
||||
|
@ -830,14 +830,14 @@ Link::SetHrefAttribute(nsIURI *aURI)
|
||||
}
|
||||
|
||||
size_t
|
||||
Link::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
|
||||
Link::SizeOfExcludingThis(mozilla::SizeOfState& aState) const
|
||||
{
|
||||
size_t n = 0;
|
||||
|
||||
if (mCachedURI) {
|
||||
nsCOMPtr<nsISizeOf> iface = do_QueryInterface(mCachedURI);
|
||||
if (iface) {
|
||||
n += iface->SizeOfIncludingThis(aMallocSizeOf);
|
||||
n += iface->SizeOfIncludingThis(aState.mMallocSizeOf);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -114,7 +114,7 @@ public:
|
||||
virtual bool HasDeferredDNSPrefetchRequest() { return true; }
|
||||
|
||||
virtual size_t
|
||||
SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
|
||||
SizeOfExcludingThis(mozilla::SizeOfState& aState) const;
|
||||
|
||||
virtual bool ElementHasHref() const;
|
||||
|
||||
|
@ -12331,10 +12331,10 @@ nsDocument::GetVisibilityState(nsAString& aState)
|
||||
nsIDocument::DocAddSizeOfExcludingThis(nsWindowSizes* aWindowSizes) const
|
||||
{
|
||||
aWindowSizes->mDOMOtherSize +=
|
||||
nsINode::SizeOfExcludingThis(aWindowSizes->mMallocSizeOf);
|
||||
nsINode::SizeOfExcludingThis(aWindowSizes->mState);
|
||||
|
||||
if (mPresShell) {
|
||||
mPresShell->AddSizeOfIncludingThis(aWindowSizes->mMallocSizeOf,
|
||||
mPresShell->AddSizeOfIncludingThis(aWindowSizes->mState.mMallocSizeOf,
|
||||
&aWindowSizes->mArenaStats,
|
||||
&aWindowSizes->mLayoutPresShellSize,
|
||||
&aWindowSizes->mLayoutStyleSetsSize,
|
||||
@ -12344,11 +12344,12 @@ nsIDocument::DocAddSizeOfExcludingThis(nsWindowSizes* aWindowSizes) const
|
||||
}
|
||||
|
||||
aWindowSizes->mPropertyTablesSize +=
|
||||
mPropertyTable.SizeOfExcludingThis(aWindowSizes->mMallocSizeOf);
|
||||
mPropertyTable.SizeOfExcludingThis(aWindowSizes->mState.mMallocSizeOf);
|
||||
for (uint32_t i = 0, count = mExtraPropertyTables.Length();
|
||||
i < count; ++i) {
|
||||
aWindowSizes->mPropertyTablesSize +=
|
||||
mExtraPropertyTables[i]->SizeOfIncludingThis(aWindowSizes->mMallocSizeOf);
|
||||
mExtraPropertyTables[i]->SizeOfIncludingThis(
|
||||
aWindowSizes->mState.mMallocSizeOf);
|
||||
}
|
||||
|
||||
if (EventListenerManager* elm = GetExistingListenerManager()) {
|
||||
@ -12363,7 +12364,7 @@ nsIDocument::DocAddSizeOfExcludingThis(nsWindowSizes* aWindowSizes) const
|
||||
void
|
||||
nsIDocument::DocAddSizeOfIncludingThis(nsWindowSizes* aWindowSizes) const
|
||||
{
|
||||
aWindowSizes->mDOMOtherSize += aWindowSizes->mMallocSizeOf(this);
|
||||
aWindowSizes->mDOMOtherSize += aWindowSizes->mState.mMallocSizeOf(this);
|
||||
DocAddSizeOfExcludingThis(aWindowSizes);
|
||||
}
|
||||
|
||||
@ -12384,7 +12385,7 @@ SizeOfOwnedSheetArrayExcludingThis(const nsTArray<RefPtr<StyleSheet>>& aSheets,
|
||||
}
|
||||
|
||||
size_t
|
||||
nsDocument::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
|
||||
nsDocument::SizeOfExcludingThis(SizeOfState& aState) const
|
||||
{
|
||||
// This SizeOfExcludingThis() overrides the one from nsINode. But
|
||||
// nsDocuments can only appear at the top of the DOM tree, and we use the
|
||||
@ -12402,7 +12403,7 @@ nsDocument::DocAddSizeOfExcludingThis(nsWindowSizes* aWindowSizes) const
|
||||
node;
|
||||
node = node->GetNextNode(this))
|
||||
{
|
||||
size_t nodeSize = node->SizeOfIncludingThis(aWindowSizes->mMallocSizeOf);
|
||||
size_t nodeSize = node->SizeOfIncludingThis(aWindowSizes->mState);
|
||||
size_t* p;
|
||||
|
||||
switch (node->NodeType()) {
|
||||
@ -12432,33 +12433,34 @@ nsDocument::DocAddSizeOfExcludingThis(nsWindowSizes* aWindowSizes) const
|
||||
|
||||
aWindowSizes->mStyleSheetsSize +=
|
||||
SizeOfOwnedSheetArrayExcludingThis(mStyleSheets,
|
||||
aWindowSizes->mMallocSizeOf);
|
||||
aWindowSizes->mState.mMallocSizeOf);
|
||||
// Note that we do not own the sheets pointed to by mOnDemandBuiltInUASheets
|
||||
// (the nsLayoutStyleSheetCache singleton does).
|
||||
aWindowSizes->mStyleSheetsSize +=
|
||||
mOnDemandBuiltInUASheets.ShallowSizeOfExcludingThis(
|
||||
aWindowSizes->mMallocSizeOf);
|
||||
aWindowSizes->mState.mMallocSizeOf);
|
||||
for (auto& sheetArray : mAdditionalSheets) {
|
||||
aWindowSizes->mStyleSheetsSize +=
|
||||
SizeOfOwnedSheetArrayExcludingThis(sheetArray,
|
||||
aWindowSizes->mMallocSizeOf);
|
||||
aWindowSizes->mState.mMallocSizeOf);
|
||||
}
|
||||
// Lumping in the loader with the style-sheets size is not ideal,
|
||||
// but most of the things in there are in fact stylesheets, so it
|
||||
// doesn't seem worthwhile to separate it out.
|
||||
aWindowSizes->mStyleSheetsSize +=
|
||||
CSSLoader()->SizeOfIncludingThis(aWindowSizes->mMallocSizeOf);
|
||||
CSSLoader()->SizeOfIncludingThis(aWindowSizes->mState.mMallocSizeOf);
|
||||
|
||||
aWindowSizes->mDOMOtherSize += mAttrStyleSheet
|
||||
? mAttrStyleSheet->DOMSizeOfIncludingThis(
|
||||
aWindowSizes->mState.mMallocSizeOf)
|
||||
: 0;
|
||||
|
||||
aWindowSizes->mDOMOtherSize +=
|
||||
mAttrStyleSheet ?
|
||||
mAttrStyleSheet->DOMSizeOfIncludingThis(aWindowSizes->mMallocSizeOf) :
|
||||
0;
|
||||
mStyledLinks.ShallowSizeOfExcludingThis(
|
||||
aWindowSizes->mState.mMallocSizeOf);
|
||||
|
||||
aWindowSizes->mDOMOtherSize +=
|
||||
mStyledLinks.ShallowSizeOfExcludingThis(aWindowSizes->mMallocSizeOf);
|
||||
|
||||
aWindowSizes->mDOMOtherSize +=
|
||||
mIdentifierMap.SizeOfExcludingThis(aWindowSizes->mMallocSizeOf);
|
||||
mIdentifierMap.SizeOfExcludingThis(aWindowSizes->mState.mMallocSizeOf);
|
||||
|
||||
// Measurement of the following members may be added later if DMD finds it
|
||||
// is worthwhile:
|
||||
|
@ -1110,10 +1110,10 @@ nsGenericDOMDataNode::GetAttributeChangeHint(const nsIAtom* aAttribute,
|
||||
}
|
||||
|
||||
size_t
|
||||
nsGenericDOMDataNode::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
|
||||
nsGenericDOMDataNode::SizeOfExcludingThis(SizeOfState& aState) const
|
||||
{
|
||||
size_t n = nsIContent::SizeOfExcludingThis(aMallocSizeOf);
|
||||
n += mText.SizeOfExcludingThis(aMallocSizeOf);
|
||||
size_t n = nsIContent::SizeOfExcludingThis(aState);
|
||||
n += mText.SizeOfExcludingThis(aState.mMallocSizeOf);
|
||||
return n;
|
||||
}
|
||||
|
||||
|
@ -13778,13 +13778,13 @@ nsGlobalWindow::DisableTimeChangeNotifications()
|
||||
void
|
||||
nsGlobalWindow::AddSizeOfIncludingThis(nsWindowSizes* aWindowSizes) const
|
||||
{
|
||||
aWindowSizes->mDOMOtherSize += aWindowSizes->mMallocSizeOf(this);
|
||||
aWindowSizes->mDOMOtherSize += aWindowSizes->mState.mMallocSizeOf(this);
|
||||
|
||||
if (IsInnerWindow()) {
|
||||
EventListenerManager* elm = GetExistingListenerManager();
|
||||
if (elm) {
|
||||
aWindowSizes->mDOMOtherSize +=
|
||||
elm->SizeOfIncludingThis(aWindowSizes->mMallocSizeOf);
|
||||
elm->SizeOfIncludingThis(aWindowSizes->mState.mMallocSizeOf);
|
||||
aWindowSizes->mDOMEventListenersCount +=
|
||||
elm->ListenerCount();
|
||||
}
|
||||
@ -13801,17 +13801,19 @@ nsGlobalWindow::AddSizeOfIncludingThis(nsWindowSizes* aWindowSizes) const
|
||||
|
||||
if (mNavigator) {
|
||||
aWindowSizes->mDOMOtherSize +=
|
||||
mNavigator->SizeOfIncludingThis(aWindowSizes->mMallocSizeOf);
|
||||
mNavigator->SizeOfIncludingThis(aWindowSizes->mState.mMallocSizeOf);
|
||||
}
|
||||
|
||||
aWindowSizes->mDOMEventTargetsSize +=
|
||||
mEventTargetObjects.ShallowSizeOfExcludingThis(aWindowSizes->mMallocSizeOf);
|
||||
mEventTargetObjects.ShallowSizeOfExcludingThis(
|
||||
aWindowSizes->mState.mMallocSizeOf);
|
||||
|
||||
for (auto iter = mEventTargetObjects.ConstIter(); !iter.Done(); iter.Next()) {
|
||||
DOMEventTargetHelper* et = iter.Get()->GetKey();
|
||||
if (nsCOMPtr<nsISizeOfEventTarget> iSizeOf = do_QueryObject(et)) {
|
||||
aWindowSizes->mDOMEventTargetsSize +=
|
||||
iSizeOf->SizeOfEventTargetIncludingThis(aWindowSizes->mMallocSizeOf);
|
||||
iSizeOf->SizeOfEventTargetIncludingThis(
|
||||
aWindowSizes->mState.mMallocSizeOf);
|
||||
}
|
||||
if (EventListenerManager* elm = et->GetExistingListenerManager()) {
|
||||
aWindowSizes->mDOMEventListenersCount += elm->ListenerCount();
|
||||
@ -13821,9 +13823,9 @@ nsGlobalWindow::AddSizeOfIncludingThis(nsWindowSizes* aWindowSizes) const
|
||||
|
||||
if (IsInnerWindow() && mPerformance) {
|
||||
aWindowSizes->mDOMPerformanceUserEntries =
|
||||
mPerformance->SizeOfUserEntries(aWindowSizes->mMallocSizeOf);
|
||||
mPerformance->SizeOfUserEntries(aWindowSizes->mState.mMallocSizeOf);
|
||||
aWindowSizes->mDOMPerformanceResourceEntries =
|
||||
mPerformance->SizeOfResourceEntries(aWindowSizes->mMallocSizeOf);
|
||||
mPerformance->SizeOfResourceEntries(aWindowSizes->mState.mMallocSizeOf);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2579,12 +2579,12 @@ nsINode::GetAccessibleNode()
|
||||
}
|
||||
|
||||
size_t
|
||||
nsINode::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
|
||||
nsINode::SizeOfExcludingThis(SizeOfState& aState) const
|
||||
{
|
||||
size_t n = 0;
|
||||
EventListenerManager* elm = GetExistingListenerManager();
|
||||
if (elm) {
|
||||
n += elm->SizeOfIncludingThis(aMallocSizeOf);
|
||||
n += elm->SizeOfIncludingThis(aState.mMallocSizeOf);
|
||||
}
|
||||
|
||||
// Measurement of the following members may be added later if DMD finds it is
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "nsTObserverArray.h" // for member
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "mozilla/SizeOfState.h" // for SizeOfState
|
||||
#include "mozilla/dom/EventTarget.h" // for base class
|
||||
#include "js/TypeDecls.h" // for Handle, Value, JSObject, JSContext
|
||||
#include "mozilla/dom/DOMString.h"
|
||||
@ -268,7 +269,8 @@ private:
|
||||
// defined, it is inherited from nsINode.
|
||||
// This macro isn't actually specific to nodes, and bug 956400 will move it into MFBT.
|
||||
#define NS_DECL_SIZEOF_EXCLUDING_THIS \
|
||||
virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const override;
|
||||
virtual size_t SizeOfExcludingThis(mozilla::SizeOfState& aState) \
|
||||
const override;
|
||||
|
||||
// Categories of node properties
|
||||
// 0 is global.
|
||||
@ -326,15 +328,15 @@ public:
|
||||
// The following members don't need to be measured:
|
||||
// - nsIContent: mPrimaryFrame, because it's non-owning and measured elsewhere
|
||||
//
|
||||
virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
|
||||
virtual size_t SizeOfExcludingThis(mozilla::SizeOfState& aState) const;
|
||||
|
||||
// SizeOfIncludingThis doesn't need to be overridden by sub-classes because
|
||||
// sub-classes of nsINode are guaranteed to be laid out in memory in such a
|
||||
// way that |this| points to the start of the allocated object, even in
|
||||
// methods of nsINode's sub-classes, and so |aMallocSizeOf(this)| is always
|
||||
// methods of nsINode's sub-classes, so aState.mMallocSizeOf(this) is always
|
||||
// safe to call no matter which object it was invoked on.
|
||||
virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const {
|
||||
return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
|
||||
virtual size_t SizeOfIncludingThis(mozilla::SizeOfState& aState) const {
|
||||
return aState.mMallocSizeOf(this) + SizeOfExcludingThis(aState);
|
||||
}
|
||||
|
||||
friend class nsNodeUtils;
|
||||
|
@ -52,19 +52,19 @@ AddNonJSSizeOfWindowAndItsDescendents(nsGlobalWindow* aWindow,
|
||||
nsTabSizes* aSizes)
|
||||
{
|
||||
// Measure the window.
|
||||
nsWindowSizes windowSizes(moz_malloc_size_of);
|
||||
SizeOfState state(moz_malloc_size_of);
|
||||
nsWindowSizes windowSizes(state);
|
||||
aWindow->AddSizeOfIncludingThis(&windowSizes);
|
||||
windowSizes.addToTabSizes(aSizes);
|
||||
|
||||
// Measure the inner window, if there is one.
|
||||
nsWindowSizes innerWindowSizes(moz_malloc_size_of);
|
||||
nsGlobalWindow* inner = aWindow->IsOuterWindow() ? aWindow->GetCurrentInnerWindowInternal()
|
||||
: nullptr;
|
||||
if (inner) {
|
||||
inner->AddSizeOfIncludingThis(&innerWindowSizes);
|
||||
innerWindowSizes.addToTabSizes(aSizes);
|
||||
inner->AddSizeOfIncludingThis(&windowSizes);
|
||||
}
|
||||
|
||||
windowSizes.addToTabSizes(aSizes);
|
||||
|
||||
nsCOMPtr<nsIDOMWindowCollection> frames = aWindow->GetFrames();
|
||||
|
||||
uint32_t length;
|
||||
@ -309,7 +309,10 @@ CollectWindowReports(nsGlobalWindow *aWindow,
|
||||
ReportCount(censusWindowPath, _pathTail, _amount, NS_LITERAL_CSTRING(_desc), \
|
||||
aHandleReport, aData);
|
||||
|
||||
nsWindowSizes windowSizes(WindowsMallocSizeOf);
|
||||
// This SizeOfState contains the SeenPtrs used for all memory reporting of
|
||||
// this window.
|
||||
SizeOfState state(WindowsMallocSizeOf);
|
||||
nsWindowSizes windowSizes(state);
|
||||
aWindow->AddSizeOfIncludingThis(&windowSizes);
|
||||
|
||||
REPORT_SIZE("/dom/element-nodes", windowSizes.mDOMElementNodesSize,
|
||||
@ -518,7 +521,8 @@ nsWindowMemoryReporter::CollectReports(nsIHandleReportCallback* aHandleReport,
|
||||
WindowPaths topWindowPaths;
|
||||
|
||||
// Collect window memory usage.
|
||||
nsWindowSizes windowTotalSizes(nullptr);
|
||||
SizeOfState fakeState(nullptr); // this won't be used
|
||||
nsWindowSizes windowTotalSizes(fakeState);
|
||||
nsCOMPtr<amIAddonManager> addonManager;
|
||||
if (XRE_IsParentProcess()) {
|
||||
// Only try to access the service from the main process.
|
||||
|
@ -39,7 +39,7 @@ class nsWindowSizes {
|
||||
macro(Other, mPropertyTablesSize) \
|
||||
|
||||
public:
|
||||
explicit nsWindowSizes(mozilla::MallocSizeOf aMallocSizeOf)
|
||||
explicit nsWindowSizes(mozilla::SizeOfState& aState)
|
||||
:
|
||||
#define ZERO_SIZE(kind, mSize) mSize(0),
|
||||
FOR_EACH_SIZE(ZERO_SIZE)
|
||||
@ -47,7 +47,7 @@ public:
|
||||
mDOMEventTargetsCount(0),
|
||||
mDOMEventListenersCount(0),
|
||||
mArenaStats(),
|
||||
mMallocSizeOf(aMallocSizeOf)
|
||||
mState(aState)
|
||||
{}
|
||||
|
||||
void addToTabSizes(nsTabSizes *sizes) const {
|
||||
@ -75,7 +75,7 @@ public:
|
||||
uint32_t mDOMEventListenersCount;
|
||||
|
||||
nsArenaMemoryStats mArenaStats;
|
||||
mozilla::MallocSizeOf mMallocSizeOf;
|
||||
mozilla::SizeOfState& mState;
|
||||
|
||||
#undef FOR_EACH_SIZE
|
||||
};
|
||||
|
@ -406,10 +406,10 @@ HTMLAnchorElement::IntrinsicState() const
|
||||
}
|
||||
|
||||
size_t
|
||||
HTMLAnchorElement::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
|
||||
HTMLAnchorElement::SizeOfExcludingThis(mozilla::SizeOfState& aState) const
|
||||
{
|
||||
return nsGenericHTMLElement::SizeOfExcludingThis(aMallocSizeOf) +
|
||||
Link::SizeOfExcludingThis(aMallocSizeOf);
|
||||
return nsGenericHTMLElement::SizeOfExcludingThis(aState) +
|
||||
Link::SizeOfExcludingThis(aState);
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
|
@ -220,10 +220,10 @@ HTMLAreaElement::IntrinsicState() const
|
||||
}
|
||||
|
||||
size_t
|
||||
HTMLAreaElement::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
|
||||
HTMLAreaElement::SizeOfExcludingThis(mozilla::SizeOfState& aState) const
|
||||
{
|
||||
return nsGenericHTMLElement::SizeOfExcludingThis(aMallocSizeOf) +
|
||||
Link::SizeOfExcludingThis(aMallocSizeOf);
|
||||
return nsGenericHTMLElement::SizeOfExcludingThis(aState) +
|
||||
Link::SizeOfExcludingThis(aState);
|
||||
}
|
||||
|
||||
JSObject*
|
||||
|
@ -509,10 +509,10 @@ HTMLLinkElement::IntrinsicState() const
|
||||
}
|
||||
|
||||
size_t
|
||||
HTMLLinkElement::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
|
||||
HTMLLinkElement::SizeOfExcludingThis(mozilla::SizeOfState& aState) const
|
||||
{
|
||||
return nsGenericHTMLElement::SizeOfExcludingThis(aMallocSizeOf) +
|
||||
Link::SizeOfExcludingThis(aMallocSizeOf);
|
||||
return nsGenericHTMLElement::SizeOfExcludingThis(aState) +
|
||||
Link::SizeOfExcludingThis(aState);
|
||||
}
|
||||
|
||||
JSObject*
|
||||
|
@ -46,10 +46,10 @@ SVGPathElement::SVGPathElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeIn
|
||||
// memory reporting methods
|
||||
|
||||
size_t
|
||||
SVGPathElement::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
|
||||
SVGPathElement::SizeOfExcludingThis(mozilla::SizeOfState& aState) const
|
||||
{
|
||||
return SVGPathElementBase::SizeOfExcludingThis(aMallocSizeOf) +
|
||||
mD.SizeOfExcludingThis(aMallocSizeOf);
|
||||
return SVGPathElementBase::SizeOfExcludingThis(aState) +
|
||||
mD.SizeOfExcludingThis(aState.mMallocSizeOf);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
@ -32,7 +32,7 @@ DynamicImage::GetProgressTracker()
|
||||
}
|
||||
|
||||
size_t
|
||||
DynamicImage::SizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf) const
|
||||
DynamicImage::SizeOfSourceWithComputedFallback(SizeOfState& aState) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ public:
|
||||
nsresult GetNativeSizes(nsTArray<gfx::IntSize>& aNativeSizes) const override;
|
||||
virtual already_AddRefed<ProgressTracker> GetProgressTracker() override;
|
||||
virtual size_t SizeOfSourceWithComputedFallback(
|
||||
MallocSizeOf aMallocSizeOf) const override;
|
||||
SizeOfState& aState) const override;
|
||||
virtual void CollectSizeOfSurfaces(nsTArray<SurfaceMemoryCounter>& aCounters,
|
||||
MallocSizeOf aMallocSizeOf) const override;
|
||||
|
||||
|
@ -15,7 +15,7 @@ namespace image {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ImageMemoryCounter::ImageMemoryCounter(Image* aImage,
|
||||
MallocSizeOf aMallocSizeOf,
|
||||
SizeOfState& aState,
|
||||
bool aIsUsed)
|
||||
: mIsUsed(aIsUsed)
|
||||
{
|
||||
@ -36,8 +36,8 @@ ImageMemoryCounter::ImageMemoryCounter(Image* aImage,
|
||||
mType = aImage->GetType();
|
||||
|
||||
// Populate memory counters for source and decoded data.
|
||||
mValues.SetSource(aImage->SizeOfSourceWithComputedFallback(aMallocSizeOf));
|
||||
aImage->CollectSizeOfSurfaces(mSurfaces, aMallocSizeOf);
|
||||
mValues.SetSource(aImage->SizeOfSourceWithComputedFallback(aState));
|
||||
aImage->CollectSizeOfSurfaces(mSurfaces, aState.mMallocSizeOf);
|
||||
|
||||
// Compute totals.
|
||||
for (const SurfaceMemoryCounter& surfaceCounter : mSurfaces) {
|
||||
|
@ -94,9 +94,7 @@ private:
|
||||
|
||||
struct ImageMemoryCounter
|
||||
{
|
||||
ImageMemoryCounter(Image* aImage,
|
||||
MallocSizeOf aMallocSizeOf,
|
||||
bool aIsUsed);
|
||||
ImageMemoryCounter(Image* aImage, SizeOfState& aState, bool aIsUsed);
|
||||
|
||||
nsCString& URI() { return mURI; }
|
||||
const nsCString& URI() const { return mURI; }
|
||||
@ -167,7 +165,7 @@ public:
|
||||
* ensure that something reasonable is always returned.
|
||||
*/
|
||||
virtual size_t
|
||||
SizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf) const = 0;
|
||||
SizeOfSourceWithComputedFallback(SizeOfState& aState) const = 0;
|
||||
|
||||
/**
|
||||
* Collect an accounting of the memory occupied by the image's surfaces (which
|
||||
|
@ -30,9 +30,9 @@ ImageWrapper::GetProgressTracker()
|
||||
}
|
||||
|
||||
size_t
|
||||
ImageWrapper::SizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf) const
|
||||
ImageWrapper::SizeOfSourceWithComputedFallback(SizeOfState& aState) const
|
||||
{
|
||||
return mInnerImage->SizeOfSourceWithComputedFallback(aMallocSizeOf);
|
||||
return mInnerImage->SizeOfSourceWithComputedFallback(aState);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -26,7 +26,7 @@ public:
|
||||
virtual already_AddRefed<ProgressTracker> GetProgressTracker() override;
|
||||
|
||||
virtual size_t
|
||||
SizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf) const override;
|
||||
SizeOfSourceWithComputedFallback(SizeOfState& aState) const override;
|
||||
virtual void CollectSizeOfSurfaces(nsTArray<SurfaceMemoryCounter>& aCounters,
|
||||
MallocSizeOf aMallocSizeOf) const override;
|
||||
|
||||
|
@ -705,9 +705,10 @@ RasterImage::UpdateImageContainer()
|
||||
}
|
||||
|
||||
size_t
|
||||
RasterImage::SizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf) const
|
||||
RasterImage::SizeOfSourceWithComputedFallback(SizeOfState& aState) const
|
||||
{
|
||||
return mSourceBuffer->SizeOfIncludingThisWithComputedFallback(aMallocSizeOf);
|
||||
return mSourceBuffer->SizeOfIncludingThisWithComputedFallback(
|
||||
aState.mMallocSizeOf);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -167,7 +167,7 @@ public:
|
||||
// Methods inherited from Image
|
||||
virtual void OnSurfaceDiscarded(const SurfaceKey& aSurfaceKey) override;
|
||||
|
||||
virtual size_t SizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf)
|
||||
virtual size_t SizeOfSourceWithComputedFallback(SizeOfState& aState)
|
||||
const override;
|
||||
virtual void CollectSizeOfSurfaces(nsTArray<SurfaceMemoryCounter>& aCounters,
|
||||
MallocSizeOf aMallocSizeOf) const override;
|
||||
|
@ -380,7 +380,7 @@ VectorImage::Init(const char* aMimeType,
|
||||
}
|
||||
|
||||
size_t
|
||||
VectorImage::SizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf) const
|
||||
VectorImage::SizeOfSourceWithComputedFallback(SizeOfState& aState) const
|
||||
{
|
||||
if (!mSVGDocumentWrapper) {
|
||||
return 0; // No document, so no memory used for the document.
|
||||
@ -391,7 +391,7 @@ VectorImage::SizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf) const
|
||||
return 0; // No document, so no memory used for the document.
|
||||
}
|
||||
|
||||
nsWindowSizes windowSizes(aMallocSizeOf);
|
||||
nsWindowSizes windowSizes(aState);
|
||||
doc->DocAddSizeOfIncludingThis(&windowSizes);
|
||||
|
||||
if (windowSizes.getTotalSize() == 0) {
|
||||
|
@ -35,7 +35,7 @@ public:
|
||||
|
||||
// Methods inherited from Image
|
||||
nsresult GetNativeSizes(nsTArray<gfx::IntSize>& aNativeSizes) const override;
|
||||
virtual size_t SizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf)
|
||||
virtual size_t SizeOfSourceWithComputedFallback(SizeOfState& aState)
|
||||
const override;
|
||||
virtual void CollectSizeOfSurfaces(nsTArray<SurfaceMemoryCounter>& aCounters,
|
||||
MallocSizeOf aMallocSizeOf) const override;
|
||||
|
@ -140,7 +140,8 @@ public:
|
||||
// memory. This function's measurement is secondary -- the result doesn't
|
||||
// go in the "explicit" tree -- so we use moz_malloc_size_of instead of
|
||||
// ImagesMallocSizeOf to prevent DMD from seeing it reported twice.
|
||||
ImageMemoryCounter counter(image, moz_malloc_size_of, /* aIsUsed = */ true);
|
||||
SizeOfState state(moz_malloc_size_of);
|
||||
ImageMemoryCounter counter(image, state, /* aIsUsed = */ true);
|
||||
|
||||
n += counter.Values().DecodedHeap();
|
||||
n += counter.Values().DecodedNonHeap();
|
||||
@ -409,7 +410,8 @@ private:
|
||||
return;
|
||||
}
|
||||
|
||||
ImageMemoryCounter counter(image, ImagesMallocSizeOf, aIsUsed);
|
||||
SizeOfState state(ImagesMallocSizeOf);
|
||||
ImageMemoryCounter counter(image, state, aIsUsed);
|
||||
|
||||
aArray->AppendElement(Move(counter));
|
||||
}
|
||||
|
@ -617,7 +617,8 @@ imgRequest::UpdateCacheEntrySize()
|
||||
}
|
||||
|
||||
RefPtr<Image> image = GetImage();
|
||||
size_t size = image->SizeOfSourceWithComputedFallback(moz_malloc_size_of);
|
||||
SizeOfState state(moz_malloc_size_of);
|
||||
size_t size = image->SizeOfSourceWithComputedFallback(state);
|
||||
mCacheEntry->SetDataSize(size);
|
||||
}
|
||||
|
||||
|
@ -2119,11 +2119,11 @@ MOZ_DEFINE_MALLOC_SIZE_OF(OrphanMallocSizeOf)
|
||||
namespace xpc {
|
||||
|
||||
static size_t
|
||||
SizeOfTreeIncludingThis(nsINode* tree)
|
||||
SizeOfTreeIncludingThis(nsINode* tree, SizeOfState& aState)
|
||||
{
|
||||
size_t n = tree->SizeOfIncludingThis(OrphanMallocSizeOf);
|
||||
size_t n = tree->SizeOfIncludingThis(aState);
|
||||
for (nsIContent* child = tree->GetFirstChild(); child; child = child->GetNextNode(tree))
|
||||
n += child->SizeOfIncludingThis(OrphanMallocSizeOf);
|
||||
n += child->SizeOfIncludingThis(aState);
|
||||
|
||||
return n;
|
||||
}
|
||||
@ -2133,10 +2133,11 @@ class OrphanReporter : public JS::ObjectPrivateVisitor
|
||||
public:
|
||||
explicit OrphanReporter(GetISupportsFun aGetISupports)
|
||||
: JS::ObjectPrivateVisitor(aGetISupports)
|
||||
{
|
||||
}
|
||||
, mState(OrphanMallocSizeOf)
|
||||
{}
|
||||
|
||||
virtual size_t sizeOfIncludingThis(nsISupports* aSupports) override {
|
||||
virtual size_t sizeOfIncludingThis(nsISupports* aSupports) override
|
||||
{
|
||||
size_t n = 0;
|
||||
nsCOMPtr<nsINode> node = do_QueryInterface(aSupports);
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=773533#c11 explains
|
||||
@ -2149,21 +2150,15 @@ class OrphanReporter : public JS::ObjectPrivateVisitor
|
||||
// sub-tree that this node belongs to, measure the sub-tree's size
|
||||
// and then record its root so we don't measure it again.
|
||||
nsCOMPtr<nsINode> orphanTree = node->SubtreeRoot();
|
||||
if (orphanTree &&
|
||||
!mAlreadyMeasuredOrphanTrees.Contains(orphanTree)) {
|
||||
// If PutEntry() fails we don't measure this tree, which could
|
||||
// lead to under-measurement. But that's better than the
|
||||
// alternatives, which are over-measurement or an OOM abort.
|
||||
if (mAlreadyMeasuredOrphanTrees.PutEntry(orphanTree, fallible)) {
|
||||
n += SizeOfTreeIncludingThis(orphanTree);
|
||||
}
|
||||
if (orphanTree && !mState.HaveSeenPtr(orphanTree.get())) {
|
||||
n += SizeOfTreeIncludingThis(orphanTree, mState);
|
||||
}
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
private:
|
||||
nsTHashtable <nsISupportsHashKey> mAlreadyMeasuredOrphanTrees;
|
||||
SizeOfState mState;
|
||||
};
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -42,7 +42,8 @@ public:
|
||||
mDeathGrip = nullptr;
|
||||
}
|
||||
|
||||
virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const override
|
||||
virtual size_t SizeOfExcludingThis(mozilla::SizeOfState& aState)
|
||||
const override
|
||||
{
|
||||
return 0; // the value shouldn't matter
|
||||
}
|
||||
|
73
xpcom/base/SizeOfState.h
Normal file
73
xpcom/base/SizeOfState.h
Normal file
@ -0,0 +1,73 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef SizeOfState_h
|
||||
#define SizeOfState_h
|
||||
|
||||
#include "mozilla/fallible.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "mozilla/Unused.h"
|
||||
#include "nsTHashtable.h"
|
||||
#include "nsHashKeys.h"
|
||||
|
||||
// This file includes types that are useful during memory reporting, but which
|
||||
// cannot be put into mfbt/MemoryReporting.h because they depend on things that
|
||||
// are not in MFBT.
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
// A table of seen pointers. Useful when measuring structures that contain
|
||||
// nodes that may be pointed to from multiple places, e.g. via RefPtr (in C++
|
||||
// code) or Arc (in Rust code).
|
||||
class SeenPtrs : public nsTHashtable<nsPtrHashKey<const void>>
|
||||
{
|
||||
public:
|
||||
// Returns true if we have seen this pointer before, false otherwise. Also
|
||||
// remembers this pointer for later queries.
|
||||
bool HaveSeenPtr(const void* aPtr)
|
||||
{
|
||||
uint32_t oldCount = Count();
|
||||
|
||||
mozilla::Unused << PutEntry(aPtr, fallible);
|
||||
|
||||
// If the counts match, there are two possibilities.
|
||||
//
|
||||
// - Lookup succeeded: we've seen the pointer before, and didn't need to
|
||||
// add a new entry.
|
||||
//
|
||||
// - PutEntry() tried to add the entry and failed due to lack of memory. In
|
||||
// this case we can't tell if this pointer has been seen before (because
|
||||
// the table is in an unreliable state and may have dropped previous
|
||||
// insertions). When doing memory reporting it's better to err on the
|
||||
// side of under-reporting rather than over-reporting, so we assume we've
|
||||
// seen the pointer before.
|
||||
//
|
||||
return oldCount == Count();
|
||||
}
|
||||
};
|
||||
|
||||
// Memory reporting state. Some memory measuring functions
|
||||
// (SizeOfIncludingThis(), etc.) just need a MallocSizeOf parameter, but some
|
||||
// also need a record of pointers that have been seen and should not be
|
||||
// re-measured. This class encapsulates both of those things.
|
||||
class SizeOfState
|
||||
{
|
||||
public:
|
||||
explicit SizeOfState(MallocSizeOf aMallocSizeOf)
|
||||
: mMallocSizeOf(aMallocSizeOf)
|
||||
{}
|
||||
|
||||
bool HaveSeenPtr(const void* aPtr) { return mSeenPtrs.HaveSeenPtr(aPtr); }
|
||||
|
||||
MallocSizeOf mMallocSizeOf;
|
||||
SeenPtrs mSeenPtrs;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // SizeOfState_h
|
||||
|
@ -111,6 +111,7 @@ EXPORTS.mozilla += [
|
||||
'nsMemoryInfoDumper.h',
|
||||
'NSPRLogModulesParser.h',
|
||||
'OwningNonNull.h',
|
||||
'SizeOfState.h',
|
||||
'StaticMutex.h',
|
||||
'StaticPtr.h',
|
||||
'SystemMemoryReporter.h',
|
||||
|
@ -144,10 +144,9 @@ public:
|
||||
bool Contains(KeyType aKey) const { return !!GetEntry(aKey); }
|
||||
|
||||
/**
|
||||
* Get the entry associated with a key, or create a new entry,
|
||||
* Infallibly get the entry associated with a key, or create a new entry,
|
||||
* @param aKey the key to retrieve
|
||||
* @return pointer to the entry class retreived; nullptr only if memory
|
||||
can't be allocated
|
||||
* @return pointer to the entry retrieved; never nullptr
|
||||
*/
|
||||
EntryType* PutEntry(KeyType aKey)
|
||||
{
|
||||
@ -155,6 +154,12 @@ public:
|
||||
return static_cast<EntryType*>(mTable.Add(EntryType::KeyToPointer(aKey)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Fallibly get the entry associated with a key, or create a new entry,
|
||||
* @param aKey the key to retrieve
|
||||
* @return pointer to the entry retrieved; nullptr only if memory can't
|
||||
* be allocated
|
||||
*/
|
||||
MOZ_MUST_USE
|
||||
EntryType* PutEntry(KeyType aKey, const fallible_t&)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user