Skip to content
This repository was archived by the owner on Jul 9, 2025. It is now read-only.

Commit 5c3abe8

Browse files
committed
Bug 1383982 - Introduce a general mechanism for measuring memory usage of graph-like structures. r=erahm.
All the SizeOf{In,Ex}cludingThis() functions take a MallocSizeOf function which measures memory blocks. This patch introduces a new type, SizeOfState, which includes a MallocSizeOf function *and* a table of already-measured pointers, called SeenPtrs. This gives us a general mechanism to measure graph-like data structures, by recording which nodes have already been measured. (This approach is used in a number of existing reporters, but not in a uniform fashion.) The patch also converts the window memory reporting to use SizeOfState in a lot of places, all the way through to the measurement of Elements. This is a precursor for bug 1383977 which will measure Stylo elements, which involve Arcs. The patch also converts the existing mAlreadyMeasuredOrphanTrees table in the OrphanReporter to use the new mechanism. --HG-- extra : rebase_source : 2c23285f8b6c3b667560a9d14014efc4633aed51
1 parent 305c5b2 commit 5c3abe8

33 files changed

Lines changed: 202 additions & 101 deletions

dom/base/Element.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
#include "mozilla/EventStates.h"
6868
#include "mozilla/InternalMutationEvent.h"
6969
#include "mozilla/MouseEvents.h"
70+
#include "mozilla/SizeOfState.h"
7071
#include "mozilla/TextEditor.h"
7172
#include "mozilla/TextEvents.h"
7273
#include "nsNodeUtils.h"
@@ -4137,3 +4138,14 @@ Element::SetCustomElementData(CustomElementData* aData)
41374138
MOZ_ASSERT(!slots->mCustomElementData, "Custom element data may not be changed once set.");
41384139
slots->mCustomElementData = aData;
41394140
}
4141+
4142+
size_t
4143+
Element::SizeOfExcludingThis(SizeOfState& aState) const
4144+
{
4145+
size_t n = FragmentOrElement::SizeOfExcludingThis(aState);
4146+
4147+
// XXX: measure mServoData.
4148+
4149+
return n;
4150+
}
4151+

dom/base/Element.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,8 @@ class Element : public FragmentOrElement
205205

206206
NS_DECLARE_STATIC_IID_ACCESSOR(NS_ELEMENT_IID)
207207

208+
NS_DECL_SIZEOF_EXCLUDING_THIS
209+
208210
NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) override;
209211

210212
/**

dom/base/FragmentOrElement.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2497,15 +2497,15 @@ FragmentOrElement::FireNodeRemovedForChildren()
24972497
}
24982498

24992499
size_t
2500-
FragmentOrElement::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
2500+
FragmentOrElement::SizeOfExcludingThis(SizeOfState& aState) const
25012501
{
25022502
size_t n = 0;
2503-
n += nsIContent::SizeOfExcludingThis(aMallocSizeOf);
2504-
n += mAttrsAndChildren.SizeOfExcludingThis(aMallocSizeOf);
2503+
n += nsIContent::SizeOfExcludingThis(aState);
2504+
n += mAttrsAndChildren.SizeOfExcludingThis(aState.mMallocSizeOf);
25052505

25062506
nsDOMSlots* slots = GetExistingDOMSlots();
25072507
if (slots) {
2508-
n += slots->SizeOfIncludingThis(aMallocSizeOf);
2508+
n += slots->SizeOfIncludingThis(aState.mMallocSizeOf);
25092509
}
25102510

25112511
return n;

dom/base/Link.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -830,14 +830,14 @@ Link::SetHrefAttribute(nsIURI *aURI)
830830
}
831831

832832
size_t
833-
Link::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
833+
Link::SizeOfExcludingThis(mozilla::SizeOfState& aState) const
834834
{
835835
size_t n = 0;
836836

837837
if (mCachedURI) {
838838
nsCOMPtr<nsISizeOf> iface = do_QueryInterface(mCachedURI);
839839
if (iface) {
840-
n += iface->SizeOfIncludingThis(aMallocSizeOf);
840+
n += iface->SizeOfIncludingThis(aState.mMallocSizeOf);
841841
}
842842
}
843843

dom/base/Link.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ class Link : public nsISupports
114114
virtual bool HasDeferredDNSPrefetchRequest() { return true; }
115115

116116
virtual size_t
117-
SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
117+
SizeOfExcludingThis(mozilla::SizeOfState& aState) const;
118118

119119
virtual bool ElementHasHref() const;
120120

dom/base/nsDocument.cpp

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12332,10 +12332,10 @@ nsDocument::GetVisibilityState(nsAString& aState)
1233212332
nsIDocument::DocAddSizeOfExcludingThis(nsWindowSizes* aWindowSizes) const
1233312333
{
1233412334
aWindowSizes->mDOMOtherSize +=
12335-
nsINode::SizeOfExcludingThis(aWindowSizes->mMallocSizeOf);
12335+
nsINode::SizeOfExcludingThis(aWindowSizes->mState);
1233612336

1233712337
if (mPresShell) {
12338-
mPresShell->AddSizeOfIncludingThis(aWindowSizes->mMallocSizeOf,
12338+
mPresShell->AddSizeOfIncludingThis(aWindowSizes->mState.mMallocSizeOf,
1233912339
&aWindowSizes->mArenaStats,
1234012340
&aWindowSizes->mLayoutPresShellSize,
1234112341
&aWindowSizes->mLayoutStyleSetsSize,
@@ -12345,11 +12345,12 @@ nsIDocument::DocAddSizeOfExcludingThis(nsWindowSizes* aWindowSizes) const
1234512345
}
1234612346

1234712347
aWindowSizes->mPropertyTablesSize +=
12348-
mPropertyTable.SizeOfExcludingThis(aWindowSizes->mMallocSizeOf);
12348+
mPropertyTable.SizeOfExcludingThis(aWindowSizes->mState.mMallocSizeOf);
1234912349
for (uint32_t i = 0, count = mExtraPropertyTables.Length();
1235012350
i < count; ++i) {
1235112351
aWindowSizes->mPropertyTablesSize +=
12352-
mExtraPropertyTables[i]->SizeOfIncludingThis(aWindowSizes->mMallocSizeOf);
12352+
mExtraPropertyTables[i]->SizeOfIncludingThis(
12353+
aWindowSizes->mState.mMallocSizeOf);
1235312354
}
1235412355

1235512356
if (EventListenerManager* elm = GetExistingListenerManager()) {
@@ -12364,7 +12365,7 @@ nsIDocument::DocAddSizeOfExcludingThis(nsWindowSizes* aWindowSizes) const
1236412365
void
1236512366
nsIDocument::DocAddSizeOfIncludingThis(nsWindowSizes* aWindowSizes) const
1236612367
{
12367-
aWindowSizes->mDOMOtherSize += aWindowSizes->mMallocSizeOf(this);
12368+
aWindowSizes->mDOMOtherSize += aWindowSizes->mState.mMallocSizeOf(this);
1236812369
DocAddSizeOfExcludingThis(aWindowSizes);
1236912370
}
1237012371

@@ -12385,7 +12386,7 @@ SizeOfOwnedSheetArrayExcludingThis(const nsTArray<RefPtr<StyleSheet>>& aSheets,
1238512386
}
1238612387

1238712388
size_t
12388-
nsDocument::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
12389+
nsDocument::SizeOfExcludingThis(SizeOfState& aState) const
1238912390
{
1239012391
// This SizeOfExcludingThis() overrides the one from nsINode. But
1239112392
// nsDocuments can only appear at the top of the DOM tree, and we use the
@@ -12403,7 +12404,7 @@ nsDocument::DocAddSizeOfExcludingThis(nsWindowSizes* aWindowSizes) const
1240312404
node;
1240412405
node = node->GetNextNode(this))
1240512406
{
12406-
size_t nodeSize = node->SizeOfIncludingThis(aWindowSizes->mMallocSizeOf);
12407+
size_t nodeSize = node->SizeOfIncludingThis(aWindowSizes->mState);
1240712408
size_t* p;
1240812409

1240912410
switch (node->NodeType()) {
@@ -12433,33 +12434,34 @@ nsDocument::DocAddSizeOfExcludingThis(nsWindowSizes* aWindowSizes) const
1243312434

1243412435
aWindowSizes->mStyleSheetsSize +=
1243512436
SizeOfOwnedSheetArrayExcludingThis(mStyleSheets,
12436-
aWindowSizes->mMallocSizeOf);
12437+
aWindowSizes->mState.mMallocSizeOf);
1243712438
// Note that we do not own the sheets pointed to by mOnDemandBuiltInUASheets
1243812439
// (the nsLayoutStyleSheetCache singleton does).
1243912440
aWindowSizes->mStyleSheetsSize +=
1244012441
mOnDemandBuiltInUASheets.ShallowSizeOfExcludingThis(
12441-
aWindowSizes->mMallocSizeOf);
12442+
aWindowSizes->mState.mMallocSizeOf);
1244212443
for (auto& sheetArray : mAdditionalSheets) {
1244312444
aWindowSizes->mStyleSheetsSize +=
1244412445
SizeOfOwnedSheetArrayExcludingThis(sheetArray,
12445-
aWindowSizes->mMallocSizeOf);
12446+
aWindowSizes->mState.mMallocSizeOf);
1244612447
}
1244712448
// Lumping in the loader with the style-sheets size is not ideal,
1244812449
// but most of the things in there are in fact stylesheets, so it
1244912450
// doesn't seem worthwhile to separate it out.
1245012451
aWindowSizes->mStyleSheetsSize +=
12451-
CSSLoader()->SizeOfIncludingThis(aWindowSizes->mMallocSizeOf);
12452+
CSSLoader()->SizeOfIncludingThis(aWindowSizes->mState.mMallocSizeOf);
1245212453

12453-
aWindowSizes->mDOMOtherSize +=
12454-
mAttrStyleSheet ?
12455-
mAttrStyleSheet->DOMSizeOfIncludingThis(aWindowSizes->mMallocSizeOf) :
12456-
0;
12454+
aWindowSizes->mDOMOtherSize += mAttrStyleSheet
12455+
? mAttrStyleSheet->DOMSizeOfIncludingThis(
12456+
aWindowSizes->mState.mMallocSizeOf)
12457+
: 0;
1245712458

1245812459
aWindowSizes->mDOMOtherSize +=
12459-
mStyledLinks.ShallowSizeOfExcludingThis(aWindowSizes->mMallocSizeOf);
12460+
mStyledLinks.ShallowSizeOfExcludingThis(
12461+
aWindowSizes->mState.mMallocSizeOf);
1246012462

1246112463
aWindowSizes->mDOMOtherSize +=
12462-
mIdentifierMap.SizeOfExcludingThis(aWindowSizes->mMallocSizeOf);
12464+
mIdentifierMap.SizeOfExcludingThis(aWindowSizes->mState.mMallocSizeOf);
1246312465

1246412466
// Measurement of the following members may be added later if DMD finds it
1246512467
// is worthwhile:

dom/base/nsGenericDOMDataNode.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1110,10 +1110,10 @@ nsGenericDOMDataNode::GetAttributeChangeHint(const nsIAtom* aAttribute,
11101110
}
11111111

11121112
size_t
1113-
nsGenericDOMDataNode::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
1113+
nsGenericDOMDataNode::SizeOfExcludingThis(SizeOfState& aState) const
11141114
{
1115-
size_t n = nsIContent::SizeOfExcludingThis(aMallocSizeOf);
1116-
n += mText.SizeOfExcludingThis(aMallocSizeOf);
1115+
size_t n = nsIContent::SizeOfExcludingThis(aState);
1116+
n += mText.SizeOfExcludingThis(aState.mMallocSizeOf);
11171117
return n;
11181118
}
11191119

dom/base/nsGlobalWindow.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13778,13 +13778,13 @@ nsGlobalWindow::DisableTimeChangeNotifications()
1377813778
void
1377913779
nsGlobalWindow::AddSizeOfIncludingThis(nsWindowSizes* aWindowSizes) const
1378013780
{
13781-
aWindowSizes->mDOMOtherSize += aWindowSizes->mMallocSizeOf(this);
13781+
aWindowSizes->mDOMOtherSize += aWindowSizes->mState.mMallocSizeOf(this);
1378213782

1378313783
if (IsInnerWindow()) {
1378413784
EventListenerManager* elm = GetExistingListenerManager();
1378513785
if (elm) {
1378613786
aWindowSizes->mDOMOtherSize +=
13787-
elm->SizeOfIncludingThis(aWindowSizes->mMallocSizeOf);
13787+
elm->SizeOfIncludingThis(aWindowSizes->mState.mMallocSizeOf);
1378813788
aWindowSizes->mDOMEventListenersCount +=
1378913789
elm->ListenerCount();
1379013790
}
@@ -13801,17 +13801,19 @@ nsGlobalWindow::AddSizeOfIncludingThis(nsWindowSizes* aWindowSizes) const
1380113801

1380213802
if (mNavigator) {
1380313803
aWindowSizes->mDOMOtherSize +=
13804-
mNavigator->SizeOfIncludingThis(aWindowSizes->mMallocSizeOf);
13804+
mNavigator->SizeOfIncludingThis(aWindowSizes->mState.mMallocSizeOf);
1380513805
}
1380613806

1380713807
aWindowSizes->mDOMEventTargetsSize +=
13808-
mEventTargetObjects.ShallowSizeOfExcludingThis(aWindowSizes->mMallocSizeOf);
13808+
mEventTargetObjects.ShallowSizeOfExcludingThis(
13809+
aWindowSizes->mState.mMallocSizeOf);
1380913810

1381013811
for (auto iter = mEventTargetObjects.ConstIter(); !iter.Done(); iter.Next()) {
1381113812
DOMEventTargetHelper* et = iter.Get()->GetKey();
1381213813
if (nsCOMPtr<nsISizeOfEventTarget> iSizeOf = do_QueryObject(et)) {
1381313814
aWindowSizes->mDOMEventTargetsSize +=
13814-
iSizeOf->SizeOfEventTargetIncludingThis(aWindowSizes->mMallocSizeOf);
13815+
iSizeOf->SizeOfEventTargetIncludingThis(
13816+
aWindowSizes->mState.mMallocSizeOf);
1381513817
}
1381613818
if (EventListenerManager* elm = et->GetExistingListenerManager()) {
1381713819
aWindowSizes->mDOMEventListenersCount += elm->ListenerCount();

dom/base/nsINode.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2579,12 +2579,12 @@ nsINode::GetAccessibleNode()
25792579
}
25802580

25812581
size_t
2582-
nsINode::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
2582+
nsINode::SizeOfExcludingThis(SizeOfState& aState) const
25832583
{
25842584
size_t n = 0;
25852585
EventListenerManager* elm = GetExistingListenerManager();
25862586
if (elm) {
2587-
n += elm->SizeOfIncludingThis(aMallocSizeOf);
2587+
n += elm->SizeOfIncludingThis(aState.mMallocSizeOf);
25882588
}
25892589

25902590
// Measurement of the following members may be added later if DMD finds it is

dom/base/nsINode.h

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "nsTObserverArray.h" // for member
2020
#include "mozilla/ErrorResult.h"
2121
#include "mozilla/MemoryReporting.h"
22+
#include "mozilla/SizeOfState.h" // for SizeOfState
2223
#include "mozilla/dom/EventTarget.h" // for base class
2324
#include "js/TypeDecls.h" // for Handle, Value, JSObject, JSContext
2425
#include "mozilla/dom/DOMString.h"
@@ -268,7 +269,8 @@ class nsMutationGuard {
268269
// defined, it is inherited from nsINode.
269270
// This macro isn't actually specific to nodes, and bug 956400 will move it into MFBT.
270271
#define NS_DECL_SIZEOF_EXCLUDING_THIS \
271-
virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const override;
272+
virtual size_t SizeOfExcludingThis(mozilla::SizeOfState& aState) \
273+
const override;
272274

273275
// Categories of node properties
274276
// 0 is global.
@@ -326,15 +328,15 @@ class nsINode : public mozilla::dom::EventTarget
326328
// The following members don't need to be measured:
327329
// - nsIContent: mPrimaryFrame, because it's non-owning and measured elsewhere
328330
//
329-
virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
331+
virtual size_t SizeOfExcludingThis(mozilla::SizeOfState& aState) const;
330332

331333
// SizeOfIncludingThis doesn't need to be overridden by sub-classes because
332334
// sub-classes of nsINode are guaranteed to be laid out in memory in such a
333335
// way that |this| points to the start of the allocated object, even in
334-
// methods of nsINode's sub-classes, and so |aMallocSizeOf(this)| is always
336+
// methods of nsINode's sub-classes, so aState.mMallocSizeOf(this) is always
335337
// safe to call no matter which object it was invoked on.
336-
virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const {
337-
return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
338+
virtual size_t SizeOfIncludingThis(mozilla::SizeOfState& aState) const {
339+
return aState.mMallocSizeOf(this) + SizeOfExcludingThis(aState);
338340
}
339341

340342
friend class nsNodeUtils;

0 commit comments

Comments
 (0)