зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1387956 - Overhaul ComputedValues measurement, and add style structs measurement. r=bholley.
This patch moves measurement of ComputedValues objects from Rust to C++. Measurement now happens (a) via DOM elements and (b) remaining elements via the frame tree. Likewise for the style structs hanging off ComputedValues objects. Here is an example of the output. > ├──27,600,448 B (26.49%) -- active/window(https://en.wikipedia.org/wiki/Barack_Obama) > │ ├──12,772,544 B (12.26%) -- layout > │ │ ├───4,483,744 B (04.30%) -- frames > │ │ │ ├──1,653,552 B (01.59%) ── nsInlineFrame > │ │ │ ├──1,415,760 B (01.36%) ── nsTextFrame > │ │ │ ├────431,376 B (00.41%) ── nsBlockFrame > │ │ │ ├────340,560 B (00.33%) ── nsHTMLScrollFrame > │ │ │ ├────302,544 B (00.29%) ── nsContinuingTextFrame > │ │ │ ├────156,408 B (00.15%) ── nsBulletFrame > │ │ │ ├─────73,024 B (00.07%) ── nsPlaceholderFrame > │ │ │ ├─────27,656 B (00.03%) ── sundries > │ │ │ ├─────23,520 B (00.02%) ── nsTableCellFrame > │ │ │ ├─────16,704 B (00.02%) ── nsImageFrame > │ │ │ ├─────15,488 B (00.01%) ── nsTableRowFrame > │ │ │ ├─────13,776 B (00.01%) ── nsTableColFrame > │ │ │ └─────13,376 B (00.01%) ── nsTableFrame > │ │ ├───3,412,192 B (03.28%) -- servo-style-structs > │ │ │ ├──1,288,224 B (01.24%) ── Display > │ │ │ ├────742,400 B (00.71%) ── Position > │ │ │ ├────308,736 B (00.30%) ── Font > │ │ │ ├────226,512 B (00.22%) ── Background > │ │ │ ├────218,304 B (00.21%) ── TextReset > │ │ │ ├────214,896 B (00.21%) ── Text > │ │ │ ├────130,560 B (00.13%) ── Border > │ │ │ ├─────81,408 B (00.08%) ── UIReset > │ │ │ ├─────61,440 B (00.06%) ── Padding > │ │ │ ├─────38,176 B (00.04%) ── UserInterface > │ │ │ ├─────29,232 B (00.03%) ── Margin > │ │ │ ├─────21,824 B (00.02%) ── sundries > │ │ │ ├─────20,080 B (00.02%) ── Color > │ │ │ ├─────20,080 B (00.02%) ── Column > │ │ │ └─────10,320 B (00.01%) ── Effects > │ │ ├───2,227,680 B (02.14%) -- computed-values > │ │ │ ├──1,182,928 B (01.14%) ── non-dom > │ │ │ └──1,044,752 B (01.00%) ── dom > │ │ ├───1,500,016 B (01.44%) ── text-runs > │ │ ├─────492,640 B (00.47%) ── line-boxes > │ │ ├─────326,688 B (00.31%) ── frame-properties > │ │ ├─────301,760 B (00.29%) ── pres-shell > │ │ ├──────27,648 B (00.03%) ── pres-contexts > │ │ └─────────176 B (00.00%) ── style-sets The 'servo-style-structs' and 'computed-values' sub-trees are new. (Prior to this patch, ComputedValues under DOM elements were tallied under the the 'dom/element-nodes' sub-tree, and ComputedValues not under DOM element were ignored.) 'servo-style-structs/sundries' aggregates all the style structs that are smaller than 8 KiB. Other notable things done by the patch are as follows. - It significantly changes the signatures of the methods measuring nsINode and its subclasses, in order to handle the tallying of style structs separately from element-nodes. Likewise for nsIFrame. - It renames the 'layout/style-structs' sub-tree as 'layout/gecko-style-structs', to clearly distinguish it from the new 'layout/servo-style-structs' sub-tree. - It adds some FFI functions to access various Rust-side data structures from C++ code. - There is a nasty hack used twice to measure Arcs, by stepping backwards from an interior pointer to a base pointer. It works, but I want to replace it with something better eventually. The "XXX WARNING" comments have details. - It makes DMD print a line to the console if it sees a pointer it doesn't recognise. This is useful for detecting when we are measuring an interior pointer instead of a base pointer, which is bad but easy to do when Arcs are involved. - It removes the Rust code for measuring CVs, because it's now all done on the C++ side. MozReview-Commit-ID: BKebACLKtCi --HG-- extra : rebase_source : 4d9a8c6b198a0ff025b811759a6bfa9f33a260ba
This commit is contained in:
Родитель
cb12286e7a
Коммит
57c26c9834
|
@ -4143,19 +4143,40 @@ Element::SetCustomElementData(CustomElementData* aData)
|
|||
|
||||
MOZ_DEFINE_MALLOC_SIZE_OF(ServoElementMallocSizeOf)
|
||||
|
||||
size_t
|
||||
Element::SizeOfExcludingThis(SizeOfState& aState) const
|
||||
void
|
||||
Element::AddSizeOfExcludingThis(SizeOfState& aState, nsStyleSizes& aSizes,
|
||||
size_t* aNodeSize) const
|
||||
{
|
||||
size_t n = FragmentOrElement::SizeOfExcludingThis(aState);
|
||||
FragmentOrElement::AddSizeOfExcludingThis(aState, aSizes, aNodeSize);
|
||||
|
||||
// Measure mServoData. We use ServoElementMallocSizeOf rather than
|
||||
// |aState.mMallocSizeOf| to distinguish in DMD's output the memory
|
||||
// measured within Servo code.
|
||||
if (mServoData.Get()) {
|
||||
n += Servo_Element_SizeOfExcludingThis(ServoElementMallocSizeOf,
|
||||
&aState.mSeenPtrs, this);
|
||||
if (HasServoData()) {
|
||||
// Measure mServoData, excluding the ComputedValues. This measurement
|
||||
// counts towards the element's size. We use ServoElementMallocSizeOf
|
||||
// rather thang |aState.mMallocSizeOf| to better distinguish in DMD's
|
||||
// output the memory measured within Servo code.
|
||||
*aNodeSize +=
|
||||
Servo_Element_SizeOfExcludingThisAndCVs(ServoElementMallocSizeOf,
|
||||
&aState.mSeenPtrs, this);
|
||||
|
||||
// Now measure just the ComputedValues (and style structs) under
|
||||
// mServoData. This counts towards the relevant fields in |aSizes|.
|
||||
RefPtr<ServoStyleContext> sc;
|
||||
if (Servo_Element_HasPrimaryComputedValues(this)) {
|
||||
sc = Servo_Element_GetPrimaryComputedValues(this).Consume();
|
||||
if (!aState.HaveSeenPtr(sc.get())) {
|
||||
sc->AddSizeOfIncludingThis(aState, aSizes, /* isDOM = */ true);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < nsCSSPseudoElements::kEagerPseudoCount; i++) {
|
||||
if (Servo_Element_HasPseudoComputedValues(this, i)) {
|
||||
sc = Servo_Element_GetPseudoComputedValues(this, i).Consume();
|
||||
if (!aState.HaveSeenPtr(sc.get())) {
|
||||
sc->AddSizeOfIncludingThis(aState, aSizes, /* isDOM = */ true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
struct DirtyDescendantsBit {
|
||||
|
|
|
@ -205,7 +205,7 @@ public:
|
|||
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_ELEMENT_IID)
|
||||
|
||||
NS_DECL_SIZEOF_EXCLUDING_THIS
|
||||
NS_DECL_ADDSIZEOFEXCLUDINGTHIS
|
||||
|
||||
NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) override;
|
||||
|
||||
|
|
|
@ -2502,19 +2502,18 @@ FragmentOrElement::FireNodeRemovedForChildren()
|
|||
}
|
||||
}
|
||||
|
||||
size_t
|
||||
FragmentOrElement::SizeOfExcludingThis(SizeOfState& aState) const
|
||||
void
|
||||
FragmentOrElement::AddSizeOfExcludingThis(SizeOfState& aState,
|
||||
nsStyleSizes& aSizes,
|
||||
size_t* aNodeSize) const
|
||||
{
|
||||
size_t n = 0;
|
||||
n += nsIContent::SizeOfExcludingThis(aState);
|
||||
n += mAttrsAndChildren.SizeOfExcludingThis(aState.mMallocSizeOf);
|
||||
nsIContent::AddSizeOfExcludingThis(aState, aSizes, aNodeSize);
|
||||
*aNodeSize += mAttrsAndChildren.SizeOfExcludingThis(aState.mMallocSizeOf);
|
||||
|
||||
nsDOMSlots* slots = GetExistingDOMSlots();
|
||||
if (slots) {
|
||||
n += slots->SizeOfIncludingThis(aState.mMallocSizeOf);
|
||||
*aNodeSize += slots->SizeOfIncludingThis(aState.mMallocSizeOf);
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -118,7 +118,7 @@ public:
|
|||
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
|
||||
NS_DECL_SIZEOF_EXCLUDING_THIS
|
||||
NS_DECL_ADDSIZEOFEXCLUDINGTHIS
|
||||
|
||||
// nsINode interface methods
|
||||
virtual uint32_t GetChildCount() const override;
|
||||
|
|
|
@ -12390,26 +12390,25 @@ nsDocument::GetVisibilityState(nsAString& aState)
|
|||
}
|
||||
|
||||
/* virtual */ void
|
||||
nsIDocument::DocAddSizeOfExcludingThis(nsWindowSizes& aWindowSizes) const
|
||||
nsIDocument::DocAddSizeOfExcludingThis(nsWindowSizes& aSizes) const
|
||||
{
|
||||
aWindowSizes.mDOMOtherSize +=
|
||||
nsINode::SizeOfExcludingThis(aWindowSizes.mState);
|
||||
nsINode::AddSizeOfExcludingThis(aSizes.mState, aSizes.mStyleSizes,
|
||||
&aSizes.mDOMOtherSize);
|
||||
|
||||
if (mPresShell) {
|
||||
mPresShell->AddSizeOfIncludingThis(aWindowSizes);
|
||||
mPresShell->AddSizeOfIncludingThis(aSizes);
|
||||
}
|
||||
|
||||
aWindowSizes.mPropertyTablesSize +=
|
||||
mPropertyTable.SizeOfExcludingThis(aWindowSizes.mState.mMallocSizeOf);
|
||||
aSizes.mPropertyTablesSize +=
|
||||
mPropertyTable.SizeOfExcludingThis(aSizes.mState.mMallocSizeOf);
|
||||
for (uint32_t i = 0, count = mExtraPropertyTables.Length();
|
||||
i < count; ++i) {
|
||||
aWindowSizes.mPropertyTablesSize +=
|
||||
mExtraPropertyTables[i]->SizeOfIncludingThis(
|
||||
aWindowSizes.mState.mMallocSizeOf);
|
||||
aSizes.mPropertyTablesSize +=
|
||||
mExtraPropertyTables[i]->SizeOfIncludingThis(aSizes.mState.mMallocSizeOf);
|
||||
}
|
||||
|
||||
if (EventListenerManager* elm = GetExistingListenerManager()) {
|
||||
aWindowSizes.mDOMEventListenersCount += elm->ListenerCount();
|
||||
aSizes.mDOMEventListenersCount += elm->ListenerCount();
|
||||
}
|
||||
|
||||
// Measurement of the following members may be added later if DMD finds it
|
||||
|
@ -12440,10 +12439,12 @@ SizeOfOwnedSheetArrayExcludingThis(const nsTArray<RefPtr<StyleSheet>>& aSheets,
|
|||
return n;
|
||||
}
|
||||
|
||||
size_t
|
||||
nsDocument::SizeOfExcludingThis(SizeOfState& aState) const
|
||||
void
|
||||
nsDocument::AddSizeOfExcludingThis(SizeOfState& aState,
|
||||
nsStyleSizes& aSizes,
|
||||
size_t* aNodeSize) const
|
||||
{
|
||||
// This SizeOfExcludingThis() overrides the one from nsINode. But
|
||||
// This AddSizeOfExcludingThis() overrides the one from nsINode. But
|
||||
// nsDocuments can only appear at the top of the DOM tree, and we use the
|
||||
// specialized DocAddSizeOfExcludingThis() in that case. So this should never
|
||||
// be called.
|
||||
|
@ -12453,40 +12454,48 @@ nsDocument::SizeOfExcludingThis(SizeOfState& aState) const
|
|||
void
|
||||
nsDocument::DocAddSizeOfExcludingThis(nsWindowSizes& aWindowSizes) const
|
||||
{
|
||||
nsIDocument::DocAddSizeOfExcludingThis(aWindowSizes);
|
||||
|
||||
for (nsIContent* node = nsINode::GetFirstChild();
|
||||
node;
|
||||
node = node->GetNextNode(this))
|
||||
{
|
||||
size_t nodeSize = node->SizeOfIncludingThis(aWindowSizes.mState);
|
||||
size_t* p;
|
||||
size_t nodeSize = 0;
|
||||
node->AddSizeOfIncludingThis(aWindowSizes.mState, aWindowSizes.mStyleSizes,
|
||||
&nodeSize);
|
||||
|
||||
// This is where we transfer the nodeSize obtained from
|
||||
// nsINode::AddSizeOfIncludingThis() to a value in nsWindowSizes.
|
||||
switch (node->NodeType()) {
|
||||
case nsIDOMNode::ELEMENT_NODE:
|
||||
p = &aWindowSizes.mDOMElementNodesSize;
|
||||
aWindowSizes.mDOMElementNodesSize += nodeSize;
|
||||
break;
|
||||
case nsIDOMNode::TEXT_NODE:
|
||||
p = &aWindowSizes.mDOMTextNodesSize;
|
||||
aWindowSizes.mDOMTextNodesSize += nodeSize;
|
||||
break;
|
||||
case nsIDOMNode::CDATA_SECTION_NODE:
|
||||
p = &aWindowSizes.mDOMCDATANodesSize;
|
||||
aWindowSizes.mDOMCDATANodesSize += nodeSize;
|
||||
break;
|
||||
case nsIDOMNode::COMMENT_NODE:
|
||||
p = &aWindowSizes.mDOMCommentNodesSize;
|
||||
aWindowSizes.mDOMCommentNodesSize += nodeSize;
|
||||
break;
|
||||
default:
|
||||
p = &aWindowSizes.mDOMOtherSize;
|
||||
aWindowSizes.mDOMOtherSize += nodeSize;
|
||||
break;
|
||||
}
|
||||
|
||||
*p += nodeSize;
|
||||
|
||||
if (EventListenerManager* elm = node->GetExistingListenerManager()) {
|
||||
aWindowSizes.mDOMEventListenersCount += elm->ListenerCount();
|
||||
}
|
||||
}
|
||||
|
||||
// IMPORTANT: for our ComputedValues measurements, we want to measure
|
||||
// ComputedValues accessible from DOM elements before ComputedValues not
|
||||
// accessible from DOM elements (i.e. accessible only from the frame tree).
|
||||
//
|
||||
// Therefore, the measurement of the nsIDocument superclass must happen after
|
||||
// the measurement of DOM nodes (above), because nsIDocument contains the
|
||||
// PresShell, which contains the frame tree.
|
||||
nsIDocument::DocAddSizeOfExcludingThis(aWindowSizes);
|
||||
|
||||
aWindowSizes.mStyleSheetsSize +=
|
||||
SizeOfOwnedSheetArrayExcludingThis(mStyleSheets,
|
||||
aWindowSizes.mState.mMallocSizeOf);
|
||||
|
|
|
@ -367,7 +367,7 @@ public:
|
|||
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
|
||||
NS_DECL_SIZEOF_EXCLUDING_THIS
|
||||
NS_DECL_ADDSIZEOFEXCLUDINGTHIS
|
||||
|
||||
virtual void Reset(nsIChannel *aChannel, nsILoadGroup *aLoadGroup) override;
|
||||
virtual void ResetToURI(nsIURI *aURI, nsILoadGroup *aLoadGroup,
|
||||
|
|
|
@ -1109,11 +1109,12 @@ nsGenericDOMDataNode::GetAttributeChangeHint(const nsIAtom* aAttribute,
|
|||
return nsChangeHint(0);
|
||||
}
|
||||
|
||||
size_t
|
||||
nsGenericDOMDataNode::SizeOfExcludingThis(SizeOfState& aState) const
|
||||
void
|
||||
nsGenericDOMDataNode::AddSizeOfExcludingThis(SizeOfState& aState,
|
||||
nsStyleSizes& aSizes,
|
||||
size_t* aNodeSize) const
|
||||
{
|
||||
size_t n = nsIContent::SizeOfExcludingThis(aState);
|
||||
n += mText.SizeOfExcludingThis(aState.mMallocSizeOf);
|
||||
return n;
|
||||
nsIContent::AddSizeOfExcludingThis(aState, aSizes, aNodeSize);
|
||||
*aNodeSize += mText.SizeOfExcludingThis(aState.mMallocSizeOf);
|
||||
}
|
||||
|
||||
|
|
|
@ -67,7 +67,7 @@ class nsGenericDOMDataNode : public nsIContent
|
|||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
|
||||
NS_DECL_SIZEOF_EXCLUDING_THIS
|
||||
NS_DECL_ADDSIZEOFEXCLUDINGTHIS
|
||||
|
||||
explicit nsGenericDOMDataNode(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
|
||||
explicit nsGenericDOMDataNode(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo);
|
||||
|
|
|
@ -2569,13 +2569,13 @@ nsINode::GetAccessibleNode()
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
size_t
|
||||
nsINode::SizeOfExcludingThis(SizeOfState& aState) const
|
||||
void
|
||||
nsINode::AddSizeOfExcludingThis(SizeOfState& aState, nsStyleSizes& aSizes,
|
||||
size_t* aNodeSize) const
|
||||
{
|
||||
size_t n = 0;
|
||||
EventListenerManager* elm = GetExistingListenerManager();
|
||||
if (elm) {
|
||||
n += elm->SizeOfIncludingThis(aState.mMallocSizeOf);
|
||||
*aNodeSize += elm->SizeOfIncludingThis(aState.mMallocSizeOf);
|
||||
}
|
||||
|
||||
// Measurement of the following members may be added later if DMD finds it is
|
||||
|
@ -2586,7 +2586,6 @@ nsINode::SizeOfExcludingThis(SizeOfState& aState) const
|
|||
// The following members are not measured:
|
||||
// - mParent, mNextSibling, mPreviousSibling, mFirstChild: because they're
|
||||
// non-owning
|
||||
return n;
|
||||
}
|
||||
|
||||
#define EVENT(name_, id_, type_, struct_) \
|
||||
|
|
|
@ -17,9 +17,9 @@
|
|||
#include "nsNodeInfoManager.h" // for use in NodePrincipal()
|
||||
#include "nsPropertyTable.h" // for typedefs
|
||||
#include "nsTObserverArray.h" // for member
|
||||
#include "nsWindowSizes.h" // for nsStyleSizes
|
||||
#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"
|
||||
|
@ -264,13 +264,13 @@ private:
|
|||
};
|
||||
|
||||
// This should be used for any nsINode sub-class that has fields of its own
|
||||
// that it needs to measure; any sub-class that doesn't use it will inherit
|
||||
// SizeOfExcludingThis from its super-class. SizeOfIncludingThis() need not be
|
||||
// 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::SizeOfState& aState) \
|
||||
const override;
|
||||
// that it needs to measure; any sub-class that doesn't use it will inherit
|
||||
// AddSizeOfExcludingThis from its super-class. AddSizeOfIncludingThis() need
|
||||
// not be defined, it is inherited from nsINode.
|
||||
#define NS_DECL_ADDSIZEOFEXCLUDINGTHIS \
|
||||
virtual void AddSizeOfExcludingThis(mozilla::SizeOfState& aState, \
|
||||
nsStyleSizes& aSizes, \
|
||||
size_t* aNodeSize) const override;
|
||||
|
||||
// Categories of node properties
|
||||
// 0 is global.
|
||||
|
@ -305,6 +305,10 @@ public:
|
|||
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_INODE_IID)
|
||||
|
||||
// The |aNodeSize| outparam on this function is where the actual node size
|
||||
// value is put. It gets added to the appropriate value within |aSizes| by
|
||||
// nsDocument::DocAddSizeOfExcludingThis().
|
||||
//
|
||||
// Among the sub-classes that inherit (directly or indirectly) from nsINode,
|
||||
// measurement of the following members may be added later if DMD finds it is
|
||||
// worthwhile:
|
||||
|
@ -328,15 +332,20 @@ 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::SizeOfState& aState) const;
|
||||
virtual void AddSizeOfExcludingThis(mozilla::SizeOfState& aState,
|
||||
nsStyleSizes& aSizes,
|
||||
size_t* aNodeSize) 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, so aState.mMallocSizeOf(this) is always
|
||||
// safe to call no matter which object it was invoked on.
|
||||
virtual size_t SizeOfIncludingThis(mozilla::SizeOfState& aState) const {
|
||||
return aState.mMallocSizeOf(this) + SizeOfExcludingThis(aState);
|
||||
virtual void AddSizeOfIncludingThis(mozilla::SizeOfState& aState,
|
||||
nsStyleSizes& aSizes,
|
||||
size_t* aNodeSize) const {
|
||||
*aNodeSize += aState.mMallocSizeOf(this);
|
||||
AddSizeOfExcludingThis(aState, aSizes, aNodeSize);
|
||||
}
|
||||
|
||||
friend class nsNodeUtils;
|
||||
|
|
|
@ -384,7 +384,7 @@ CollectWindowReports(nsGlobalWindow *aWindow,
|
|||
aWindowTotalSizes->mArenaSizes.mStyleContexts
|
||||
+= windowSizes.mArenaSizes.mStyleContexts;
|
||||
|
||||
REPORT_SIZE("/layout/style-structs", windowSizes.mArenaSizes.mStyleStructs,
|
||||
REPORT_SIZE("/layout/gecko-style-structs", windowSizes.mArenaSizes.mStyleStructs,
|
||||
"Memory used by style structs within a window.");
|
||||
aWindowTotalSizes->mArenaSizes.mStyleStructs
|
||||
+= windowSizes.mArenaSizes.mStyleStructs;
|
||||
|
@ -429,19 +429,17 @@ CollectWindowReports(nsGlobalWindow *aWindow,
|
|||
js::MemoryReportingSundriesThreshold();
|
||||
|
||||
size_t frameSundriesSize = 0;
|
||||
#define FRAME_ID(classname, ...) \
|
||||
{ \
|
||||
size_t frameSize \
|
||||
= windowSizes.mArenaSizes.NS_ARENA_SIZES_FIELD(classname); \
|
||||
if (frameSize < FRAME_SUNDRIES_THRESHOLD) { \
|
||||
frameSundriesSize += frameSize; \
|
||||
} else { \
|
||||
REPORT_SIZE("/layout/frames/" # classname, frameSize, \
|
||||
"Memory used by frames of " \
|
||||
"type " #classname " within a window."); \
|
||||
} \
|
||||
aWindowTotalSizes->mArenaSizes.NS_ARENA_SIZES_FIELD(classname) \
|
||||
+= frameSize; \
|
||||
#define FRAME_ID(classname, ...) \
|
||||
{ \
|
||||
size_t size = windowSizes.mArenaSizes.NS_ARENA_SIZES_FIELD(classname); \
|
||||
if (size < FRAME_SUNDRIES_THRESHOLD) { \
|
||||
frameSundriesSize += size; \
|
||||
} else { \
|
||||
REPORT_SIZE("/layout/frames/" # classname, size, \
|
||||
"Memory used by frames of " \
|
||||
"type " #classname " within a window."); \
|
||||
} \
|
||||
aWindowTotalSizes->mArenaSizes.NS_ARENA_SIZES_FIELD(classname) += size; \
|
||||
}
|
||||
#define ABSTRACT_FRAME_ID(...)
|
||||
#include "nsFrameIdList.h"
|
||||
|
@ -454,6 +452,50 @@ CollectWindowReports(nsGlobalWindow *aWindow,
|
|||
"to be shown individually.");
|
||||
}
|
||||
|
||||
// There are many different kinds of style structs, but it is likely that
|
||||
// only a few matter. Implement a cutoff so we don't bloat about:memory with
|
||||
// many uninteresting entries.
|
||||
const size_t STYLE_SUNDRIES_THRESHOLD =
|
||||
js::MemoryReportingSundriesThreshold();
|
||||
|
||||
size_t styleSundriesSize = 0;
|
||||
#define STYLE_STRUCT(name_, cb_) \
|
||||
{ \
|
||||
size_t size = windowSizes.mStyleSizes.NS_STYLE_SIZES_FIELD(name_); \
|
||||
if (size < STYLE_SUNDRIES_THRESHOLD) { \
|
||||
styleSundriesSize += size; \
|
||||
} else { \
|
||||
REPORT_SIZE("/layout/servo-style-structs/" # name_, size, \
|
||||
"Memory used by the " #name_ " Servo style structs " \
|
||||
"within a window."); \
|
||||
} \
|
||||
aWindowTotalSizes->mStyleSizes.NS_STYLE_SIZES_FIELD(name_) += size; \
|
||||
}
|
||||
#define STYLE_STRUCT_LIST_IGNORE_VARIABLES
|
||||
#include "nsStyleStructList.h"
|
||||
#undef STYLE_STRUCT
|
||||
#undef STYLE_STRUCT_LIST_IGNORE_VARIABLES
|
||||
|
||||
if (styleSundriesSize > 0) {
|
||||
REPORT_SIZE("/layout/servo-style-structs/sundries", styleSundriesSize,
|
||||
"The sum of all memory used by Servo style structs which were "
|
||||
"too small to be shown individually.");
|
||||
}
|
||||
|
||||
REPORT_SIZE("/layout/computed-values/dom",
|
||||
windowSizes.mStyleSizes.mComputedValuesDom,
|
||||
"Memory used by ComputedValues objects accessible from DOM "
|
||||
"elements.");
|
||||
aWindowTotalSizes->mStyleSizes.mComputedValuesDom +=
|
||||
windowSizes.mStyleSizes.mComputedValuesDom;
|
||||
|
||||
REPORT_SIZE("/layout/computed-values/non-dom",
|
||||
windowSizes.mStyleSizes.mComputedValuesNonDom,
|
||||
"Memory used by ComputedValues objects not accessible from DOM "
|
||||
"elements.");
|
||||
aWindowTotalSizes->mStyleSizes.mComputedValuesNonDom +=
|
||||
windowSizes.mStyleSizes.mComputedValuesNonDom;
|
||||
|
||||
#undef REPORT_SIZE
|
||||
#undef REPORT_COUNT
|
||||
}
|
||||
|
@ -575,9 +617,9 @@ nsWindowMemoryReporter::CollectReports(nsIHandleReportCallback* aHandleReport,
|
|||
windowTotalSizes.mArenaSizes.mStyleContexts,
|
||||
"This is the sum of all windows' 'layout/style-contexts' numbers.");
|
||||
|
||||
REPORT("window-objects/layout/style-structs",
|
||||
REPORT("window-objects/layout/gecko-style-structs",
|
||||
windowTotalSizes.mArenaSizes.mStyleStructs,
|
||||
"This is the sum of all windows' 'layout/style-structs' numbers.");
|
||||
"This is the sum of all windows' 'layout/gecko-style-structs' numbers.");
|
||||
|
||||
REPORT("window-objects/layout/style-sets", windowTotalSizes.mLayoutStyleSetsSize,
|
||||
"This is the sum of all windows' 'layout/style-sets' numbers.");
|
||||
|
@ -603,6 +645,24 @@ nsWindowMemoryReporter::CollectReports(nsIHandleReportCallback* aHandleReport,
|
|||
"Memory used for layout frames within windows. "
|
||||
"This is the sum of all windows' 'layout/frames/' numbers.");
|
||||
|
||||
size_t styleTotal = 0;
|
||||
#define STYLE_STRUCT(name_, cb_) \
|
||||
styleTotal += windowTotalSizes.mStyleSizes.NS_STYLE_SIZES_FIELD(name_);
|
||||
#define STYLE_STRUCT_LIST_IGNORE_VARIABLES
|
||||
#include "nsStyleStructList.h"
|
||||
#undef STYLE_STRUCT
|
||||
#undef STYLE_STRUCT_LIST_IGNORE_VARIABLES
|
||||
|
||||
REPORT("window-objects/layout/servo-style-structs", styleTotal,
|
||||
"Memory used for style structs within windows. This is the sum of "
|
||||
"all windows' 'layout/servo-style-structs/' numbers.");
|
||||
|
||||
REPORT("window-objects/layout/computed-values",
|
||||
windowTotalSizes.mStyleSizes.mComputedValuesDom +
|
||||
windowTotalSizes.mStyleSizes.mComputedValuesNonDom,
|
||||
"This is the sum of all windows' 'layout/computed-values/' "
|
||||
"numbers.");
|
||||
|
||||
#undef REPORT
|
||||
|
||||
return NS_OK;
|
||||
|
|
|
@ -36,6 +36,11 @@ public:
|
|||
size_t mOther;
|
||||
};
|
||||
|
||||
#define ZERO_SIZE(kind, mSize) mSize(0),
|
||||
#define ADD_TO_TAB_SIZES(kind, mSize) aSizes->add(nsTabSizes::kind, mSize);
|
||||
#define ADD_TO_TOTAL_SIZE(kind, mSize) total += mSize;
|
||||
#define DECL_SIZE(kind, mSize) size_t mSize;
|
||||
|
||||
#define NS_ARENA_SIZES_FIELD(classname) mArena##classname
|
||||
|
||||
struct nsArenaSizes {
|
||||
|
@ -47,24 +52,24 @@ struct nsArenaSizes {
|
|||
|
||||
nsArenaSizes()
|
||||
:
|
||||
#define ZERO_SIZE(kind, mSize) mSize(0),
|
||||
FOR_EACH_SIZE(ZERO_SIZE)
|
||||
#undef ZERO_SIZE
|
||||
#define FRAME_ID(classname, ...) NS_ARENA_SIZES_FIELD(classname)(),
|
||||
|
||||
#define FRAME_ID(classname, ...) \
|
||||
NS_ARENA_SIZES_FIELD(classname)(0),
|
||||
#define ABSTRACT_FRAME_ID(...)
|
||||
#include "nsFrameIdList.h"
|
||||
#undef FRAME_ID
|
||||
#undef ABSTRACT_FRAME_ID
|
||||
|
||||
dummy()
|
||||
{}
|
||||
|
||||
void addToTabSizes(nsTabSizes *sizes) const
|
||||
void addToTabSizes(nsTabSizes* aSizes) const
|
||||
{
|
||||
#define ADD_TO_TAB_SIZES(kind, mSize) sizes->add(nsTabSizes::kind, mSize);
|
||||
FOR_EACH_SIZE(ADD_TO_TAB_SIZES)
|
||||
#undef ADD_TO_TAB_SIZES
|
||||
|
||||
#define FRAME_ID(classname, ...) \
|
||||
sizes->add(nsTabSizes::Other, NS_ARENA_SIZES_FIELD(classname));
|
||||
aSizes->add(nsTabSizes::Other, NS_ARENA_SIZES_FIELD(classname));
|
||||
#define ABSTRACT_FRAME_ID(...)
|
||||
#include "nsFrameIdList.h"
|
||||
#undef FRAME_ID
|
||||
|
@ -74,28 +79,95 @@ struct nsArenaSizes {
|
|||
size_t getTotalSize() const
|
||||
{
|
||||
size_t total = 0;
|
||||
#define ADD_TO_TOTAL_SIZE(kind, mSize) total += mSize;
|
||||
|
||||
FOR_EACH_SIZE(ADD_TO_TOTAL_SIZE)
|
||||
#undef ADD_TO_TOTAL_SIZE
|
||||
|
||||
#define FRAME_ID(classname, ...) \
|
||||
total += NS_ARENA_SIZES_FIELD(classname);
|
||||
#define ABSTRACT_FRAME_ID(...)
|
||||
#include "nsFrameIdList.h"
|
||||
#undef FRAME_ID
|
||||
#undef ABSTRACT_FRAME_ID
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
#define DECL_SIZE(kind, mSize) size_t mSize;
|
||||
FOR_EACH_SIZE(DECL_SIZE)
|
||||
#undef DECL_SIZE
|
||||
#define FRAME_ID(classname, ...) size_t NS_ARENA_SIZES_FIELD(classname);
|
||||
|
||||
#define FRAME_ID(classname, ...) \
|
||||
size_t NS_ARENA_SIZES_FIELD(classname);
|
||||
#define ABSTRACT_FRAME_ID(...)
|
||||
#include "nsFrameIdList.h"
|
||||
#undef FRAME_ID
|
||||
#undef ABSTRACT_FRAME_ID
|
||||
int dummy; // present just to absorb the trailing comma from FRAME_ID in the
|
||||
// constructor
|
||||
|
||||
// Present just to absorb the trailing comma in the constructor.
|
||||
int dummy;
|
||||
|
||||
#undef FOR_EACH_SIZE
|
||||
};
|
||||
|
||||
#define NS_STYLE_SIZES_FIELD(name_) mStyle##name_
|
||||
|
||||
struct nsStyleSizes
|
||||
{
|
||||
#define FOR_EACH_SIZE(macro) \
|
||||
macro(Style, mComputedValuesDom) \
|
||||
macro(Style, mComputedValuesNonDom)
|
||||
|
||||
nsStyleSizes()
|
||||
:
|
||||
FOR_EACH_SIZE(ZERO_SIZE)
|
||||
|
||||
#define STYLE_STRUCT(name_, cb_) \
|
||||
NS_STYLE_SIZES_FIELD(name_)(0),
|
||||
#define STYLE_STRUCT_LIST_IGNORE_VARIABLES
|
||||
#include "nsStyleStructList.h"
|
||||
#undef STYLE_STRUCT
|
||||
#undef STYLE_STRUCT_LIST_IGNORE_VARIABLES
|
||||
|
||||
dummy()
|
||||
{}
|
||||
|
||||
void addToTabSizes(nsTabSizes* aSizes) const
|
||||
{
|
||||
FOR_EACH_SIZE(ADD_TO_TAB_SIZES)
|
||||
|
||||
#define STYLE_STRUCT(name_, cb_) \
|
||||
aSizes->add(nsTabSizes::Style, NS_STYLE_SIZES_FIELD(name_));
|
||||
#define STYLE_STRUCT_LIST_IGNORE_VARIABLES
|
||||
#include "nsStyleStructList.h"
|
||||
#undef STYLE_STRUCT
|
||||
#undef STYLE_STRUCT_LIST_IGNORE_VARIABLES
|
||||
}
|
||||
|
||||
size_t getTotalSize() const
|
||||
{
|
||||
size_t total = 0;
|
||||
|
||||
FOR_EACH_SIZE(ADD_TO_TOTAL_SIZE)
|
||||
|
||||
#define STYLE_STRUCT(name_, cb_) \
|
||||
total += NS_STYLE_SIZES_FIELD(name_);
|
||||
#define STYLE_STRUCT_LIST_IGNORE_VARIABLES
|
||||
#include "nsStyleStructList.h"
|
||||
#undef STYLE_STRUCT
|
||||
#undef STYLE_STRUCT_LIST_IGNORE_VARIABLES
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
FOR_EACH_SIZE(DECL_SIZE)
|
||||
|
||||
#define STYLE_STRUCT(name_, cb_) \
|
||||
size_t NS_STYLE_SIZES_FIELD(name_);
|
||||
#define STYLE_STRUCT_LIST_IGNORE_VARIABLES
|
||||
#include "nsStyleStructList.h"
|
||||
#undef STYLE_STRUCT
|
||||
#undef STYLE_STRUCT_LIST_IGNORE_VARIABLES
|
||||
|
||||
// Present just to absorb the trailing comma in the constructor.
|
||||
int dummy;
|
||||
|
||||
#undef FOR_EACH_SIZE
|
||||
};
|
||||
|
@ -122,43 +194,50 @@ class nsWindowSizes
|
|||
public:
|
||||
explicit nsWindowSizes(mozilla::SizeOfState& aState)
|
||||
:
|
||||
#define ZERO_SIZE(kind, mSize) mSize(0),
|
||||
FOR_EACH_SIZE(ZERO_SIZE)
|
||||
#undef ZERO_SIZE
|
||||
mDOMEventTargetsCount(0),
|
||||
mDOMEventListenersCount(0),
|
||||
mArenaSizes(),
|
||||
mStyleSizes(),
|
||||
mState(aState)
|
||||
{}
|
||||
|
||||
void addToTabSizes(nsTabSizes *sizes) const {
|
||||
#define ADD_TO_TAB_SIZES(kind, mSize) sizes->add(nsTabSizes::kind, mSize);
|
||||
void addToTabSizes(nsTabSizes* aSizes) const {
|
||||
FOR_EACH_SIZE(ADD_TO_TAB_SIZES)
|
||||
#undef ADD_TO_TAB_SIZES
|
||||
mArenaSizes.addToTabSizes(sizes);
|
||||
mArenaSizes.addToTabSizes(aSizes);
|
||||
mStyleSizes.addToTabSizes(aSizes);
|
||||
}
|
||||
|
||||
size_t getTotalSize() const
|
||||
{
|
||||
size_t total = 0;
|
||||
#define ADD_TO_TOTAL_SIZE(kind, mSize) total += mSize;
|
||||
|
||||
FOR_EACH_SIZE(ADD_TO_TOTAL_SIZE)
|
||||
#undef ADD_TO_TOTAL_SIZE
|
||||
total += mArenaSizes.getTotalSize();
|
||||
total += mStyleSizes.getTotalSize();
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
#define DECL_SIZE(kind, mSize) size_t mSize;
|
||||
FOR_EACH_SIZE(DECL_SIZE);
|
||||
#undef DECL_SIZE
|
||||
|
||||
uint32_t mDOMEventTargetsCount;
|
||||
uint32_t mDOMEventListenersCount;
|
||||
|
||||
nsArenaSizes mArenaSizes;
|
||||
|
||||
// This is Stylo-only because in Gecko these style structs are stored in the
|
||||
// nsPresArena, and so are measured as part of that.
|
||||
nsStyleSizes mStyleSizes;
|
||||
|
||||
mozilla::SizeOfState& mState;
|
||||
|
||||
#undef FOR_EACH_SIZE
|
||||
};
|
||||
|
||||
#undef ZERO_SIZE
|
||||
#undef ADD_TO_TAB_SIZES
|
||||
#undef ADD_TO_TOTAL_SIZE
|
||||
#undef DECL_SIZE
|
||||
|
||||
#endif // nsWindowSizes_h
|
||||
|
|
|
@ -405,11 +405,13 @@ HTMLAnchorElement::IntrinsicState() const
|
|||
return Link::LinkState() | nsGenericHTMLElement::IntrinsicState();
|
||||
}
|
||||
|
||||
size_t
|
||||
HTMLAnchorElement::SizeOfExcludingThis(mozilla::SizeOfState& aState) const
|
||||
void
|
||||
HTMLAnchorElement::AddSizeOfExcludingThis(SizeOfState& aState,
|
||||
nsStyleSizes& aSizes,
|
||||
size_t* aNodeSize) const
|
||||
{
|
||||
return nsGenericHTMLElement::SizeOfExcludingThis(aState) +
|
||||
Link::SizeOfExcludingThis(aState);
|
||||
nsGenericHTMLElement::AddSizeOfExcludingThis(aState, aSizes, aNodeSize);
|
||||
*aNodeSize += Link::SizeOfExcludingThis(aState);
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -48,8 +48,7 @@ public:
|
|||
// nsIDOMHTMLAnchorElement
|
||||
NS_DECL_NSIDOMHTMLANCHORELEMENT
|
||||
|
||||
// DOM memory reporter participant
|
||||
NS_DECL_SIZEOF_EXCLUDING_THIS
|
||||
NS_DECL_ADDSIZEOFEXCLUDINGTHIS
|
||||
|
||||
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
nsIContent* aBindingParent,
|
||||
|
|
|
@ -219,11 +219,13 @@ HTMLAreaElement::IntrinsicState() const
|
|||
return Link::LinkState() | nsGenericHTMLElement::IntrinsicState();
|
||||
}
|
||||
|
||||
size_t
|
||||
HTMLAreaElement::SizeOfExcludingThis(mozilla::SizeOfState& aState) const
|
||||
void
|
||||
HTMLAreaElement::AddSizeOfExcludingThis(SizeOfState& aState,
|
||||
nsStyleSizes& aSizes,
|
||||
size_t* aNodeSize) const
|
||||
{
|
||||
return nsGenericHTMLElement::SizeOfExcludingThis(aState) +
|
||||
Link::SizeOfExcludingThis(aState);
|
||||
nsGenericHTMLElement::AddSizeOfExcludingThis(aState, aSizes, aNodeSize);
|
||||
*aNodeSize += Link::SizeOfExcludingThis(aState);
|
||||
}
|
||||
|
||||
JSObject*
|
||||
|
|
|
@ -36,8 +36,7 @@ public:
|
|||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLAreaElement,
|
||||
nsGenericHTMLElement)
|
||||
|
||||
// DOM memory reporter participant
|
||||
NS_DECL_SIZEOF_EXCLUDING_THIS
|
||||
NS_DECL_ADDSIZEOFEXCLUDINGTHIS
|
||||
|
||||
virtual int32_t TabIndexDefault() override;
|
||||
|
||||
|
|
|
@ -508,11 +508,13 @@ HTMLLinkElement::IntrinsicState() const
|
|||
return Link::LinkState() | nsGenericHTMLElement::IntrinsicState();
|
||||
}
|
||||
|
||||
size_t
|
||||
HTMLLinkElement::SizeOfExcludingThis(mozilla::SizeOfState& aState) const
|
||||
void
|
||||
HTMLLinkElement::AddSizeOfExcludingThis(SizeOfState& aState,
|
||||
nsStyleSizes& aSizes,
|
||||
size_t* aNodeSize) const
|
||||
{
|
||||
return nsGenericHTMLElement::SizeOfExcludingThis(aState) +
|
||||
Link::SizeOfExcludingThis(aState);
|
||||
nsGenericHTMLElement::AddSizeOfExcludingThis(aState, aSizes, aNodeSize);
|
||||
*aNodeSize += Link::SizeOfExcludingThis(aState);
|
||||
}
|
||||
|
||||
JSObject*
|
||||
|
|
|
@ -36,8 +36,7 @@ public:
|
|||
// nsIDOMHTMLLinkElement
|
||||
NS_DECL_NSIDOMHTMLLINKELEMENT
|
||||
|
||||
// DOM memory reporter participant
|
||||
NS_DECL_SIZEOF_EXCLUDING_THIS
|
||||
NS_DECL_ADDSIZEOFEXCLUDINGTHIS
|
||||
|
||||
void LinkAdded();
|
||||
void LinkRemoved();
|
||||
|
|
|
@ -45,11 +45,13 @@ SVGPathElement::SVGPathElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeIn
|
|||
//----------------------------------------------------------------------
|
||||
// memory reporting methods
|
||||
|
||||
size_t
|
||||
SVGPathElement::SizeOfExcludingThis(mozilla::SizeOfState& aState) const
|
||||
void
|
||||
SVGPathElement::AddSizeOfExcludingThis(SizeOfState& aState,
|
||||
nsStyleSizes& aSizes,
|
||||
size_t* aNodeSize) const
|
||||
{
|
||||
return SVGPathElementBase::SizeOfExcludingThis(aState) +
|
||||
mD.SizeOfExcludingThis(aState.mMallocSizeOf);
|
||||
SVGPathElementBase::AddSizeOfExcludingThis(aState, aSizes, aNodeSize);
|
||||
*aNodeSize += mD.SizeOfExcludingThis(aState.mMallocSizeOf);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
|
|
@ -35,8 +35,7 @@ protected:
|
|||
explicit SVGPathElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
|
||||
|
||||
public:
|
||||
// DOM memory reporter participant
|
||||
NS_DECL_SIZEOF_EXCLUDING_THIS
|
||||
NS_DECL_ADDSIZEOFEXCLUDINGTHIS
|
||||
|
||||
// nsIContent interface
|
||||
NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* name) const override;
|
||||
|
|
|
@ -2121,16 +2121,6 @@ MOZ_DEFINE_MALLOC_SIZE_OF(OrphanMallocSizeOf)
|
|||
|
||||
namespace xpc {
|
||||
|
||||
static size_t
|
||||
SizeOfTreeIncludingThis(nsINode* tree, SizeOfState& aState)
|
||||
{
|
||||
size_t n = tree->SizeOfIncludingThis(aState);
|
||||
for (nsIContent* child = tree->GetFirstChild(); child; child = child->GetNextNode(tree))
|
||||
n += child->SizeOfIncludingThis(aState);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
class OrphanReporter : public JS::ObjectPrivateVisitor
|
||||
{
|
||||
public:
|
||||
|
@ -2154,12 +2144,28 @@ class OrphanReporter : public JS::ObjectPrivateVisitor
|
|||
// and then record its root so we don't measure it again.
|
||||
nsCOMPtr<nsINode> orphanTree = node->SubtreeRoot();
|
||||
if (orphanTree && !mState.HaveSeenPtr(orphanTree.get())) {
|
||||
n += SizeOfTreeIncludingThis(orphanTree, mState);
|
||||
n += SizeOfTreeIncludingThis(orphanTree);
|
||||
}
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t SizeOfTreeIncludingThis(nsINode* tree)
|
||||
{
|
||||
size_t nodeSize = 0;
|
||||
nsStyleSizes sizes;
|
||||
tree->AddSizeOfIncludingThis(mState, sizes, &nodeSize);
|
||||
for (nsIContent* child = tree->GetFirstChild(); child; child = child->GetNextNode(tree))
|
||||
child->AddSizeOfIncludingThis(mState, sizes, &nodeSize);
|
||||
|
||||
// We combine the node size with nsStyleSizes here. It's not ideal, but
|
||||
// it's hard to get the style structs measurements out to
|
||||
// nsWindowMemoryReporter. Also, we drop mServoData in
|
||||
// UnbindFromTree(), so in theory any non-in-tree element won't have
|
||||
// any style data to measure.
|
||||
return nodeSize + sizes.getTotalSize();
|
||||
}
|
||||
|
||||
private:
|
||||
SizeOfState mState;
|
||||
};
|
||||
|
|
|
@ -11045,8 +11045,7 @@ PresShell::AddSizeOfIncludingThis(nsWindowSizes& aSizes) const
|
|||
|
||||
nsIFrame* rootFrame = mFrameConstructor->GetRootFrame();
|
||||
if (rootFrame) {
|
||||
aSizes.mLayoutFramePropertiesSize +=
|
||||
rootFrame->SizeOfFramePropertiesForTree(mallocSizeOf);
|
||||
rootFrame->AddSizeOfExcludingThisForTree(aSizes);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10701,22 +10701,29 @@ nsFrame::HasCSSTransitions()
|
|||
return collection && collection->mAnimations.Length() > 0;
|
||||
}
|
||||
|
||||
size_t
|
||||
nsIFrame::SizeOfFramePropertiesForTree(MallocSizeOf aMallocSizeOf) const
|
||||
void
|
||||
nsIFrame::AddSizeOfExcludingThisForTree(nsWindowSizes& aSizes) const
|
||||
{
|
||||
size_t result = 0;
|
||||
aSizes.mLayoutFramePropertiesSize +=
|
||||
mProperties.SizeOfExcludingThis(aSizes.mState.mMallocSizeOf);
|
||||
|
||||
result += mProperties.SizeOfExcludingThis(aMallocSizeOf);
|
||||
// We don't do this for Gecko because this stuff is stored in the nsPresArena
|
||||
// and so measured elsewhere.
|
||||
if (mStyleContext->IsServo()) {
|
||||
ServoStyleContext* sc = mStyleContext->AsServo();
|
||||
if (!aSizes.mState.HaveSeenPtr(sc)) {
|
||||
sc->AddSizeOfIncludingThis(aSizes.mState, aSizes.mStyleSizes,
|
||||
/* isDOM = */ false);
|
||||
}
|
||||
}
|
||||
|
||||
FrameChildListIterator iter(this);
|
||||
while (!iter.IsDone()) {
|
||||
for (const nsIFrame* f : iter.CurrentList()) {
|
||||
result += f->SizeOfFramePropertiesForTree(aMallocSizeOf);
|
||||
f->AddSizeOfExcludingThisForTree(aSizes);
|
||||
}
|
||||
iter.Next();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Box layout debugging
|
||||
|
|
|
@ -88,6 +88,7 @@ class nsIContent;
|
|||
class nsContainerFrame;
|
||||
class nsPlaceholderFrame;
|
||||
class nsStyleChangeList;
|
||||
class nsWindowSizes;
|
||||
|
||||
struct nsPeekOffsetStruct;
|
||||
struct nsPoint;
|
||||
|
@ -3541,8 +3542,10 @@ public:
|
|||
mProperties.DeleteAll(this);
|
||||
}
|
||||
|
||||
// Reports size of the FrameProperties for this frame and its descendants
|
||||
size_t SizeOfFramePropertiesForTree(mozilla::MallocSizeOf aMallocSizeOf) const;
|
||||
// nsIFrames themselves are in the nsPresArena, and so are not measured here.
|
||||
// Instead, this measures heap-allocated things hanging off the nsIFrame, and
|
||||
// likewise for its descendants.
|
||||
void AddSizeOfExcludingThisForTree(nsWindowSizes& aWindowSizes) const;
|
||||
|
||||
/**
|
||||
* Return true if and only if this frame obeys visibility:hidden.
|
||||
|
|
|
@ -20,8 +20,19 @@
|
|||
|
||||
// Element data
|
||||
SERVO_BINDING_FUNC(Servo_Element_ClearData, void, RawGeckoElementBorrowed node)
|
||||
SERVO_BINDING_FUNC(Servo_Element_SizeOfExcludingThis, size_t, mozilla::MallocSizeOf,
|
||||
mozilla::SeenPtrs* seen_ptrs, RawGeckoElementBorrowed node)
|
||||
SERVO_BINDING_FUNC(Servo_Element_SizeOfExcludingThisAndCVs, size_t,
|
||||
mozilla::MallocSizeOf, mozilla::SeenPtrs* seen_ptrs,
|
||||
RawGeckoElementBorrowed node)
|
||||
SERVO_BINDING_FUNC(Servo_Element_HasPrimaryComputedValues, bool,
|
||||
RawGeckoElementBorrowed node)
|
||||
SERVO_BINDING_FUNC(Servo_Element_GetPrimaryComputedValues,
|
||||
ServoStyleContextStrong,
|
||||
RawGeckoElementBorrowed node)
|
||||
SERVO_BINDING_FUNC(Servo_Element_HasPseudoComputedValues, bool,
|
||||
RawGeckoElementBorrowed node, size_t index)
|
||||
SERVO_BINDING_FUNC(Servo_Element_GetPseudoComputedValues,
|
||||
ServoStyleContextStrong,
|
||||
RawGeckoElementBorrowed node, size_t index)
|
||||
|
||||
// Styleset and Stylesheet management
|
||||
SERVO_BINDING_FUNC(Servo_StyleSheet_FromUTF8Bytes, RawServoStyleSheetContentsStrong,
|
||||
|
|
|
@ -235,6 +235,46 @@ ServoComputedData::GetStyleVariables() const
|
|||
"called");
|
||||
}
|
||||
|
||||
MOZ_DEFINE_MALLOC_SIZE_OF(ServoStyleStructsMallocSizeOf)
|
||||
|
||||
void
|
||||
ServoComputedData::AddSizeOfExcludingThis(SizeOfState& aState,
|
||||
nsStyleSizes& aSizes) const
|
||||
{
|
||||
// XXX WARNING: GetStyleFoo() returns an nsStyleFoo pointer. This nsStyleFoo
|
||||
// sits within a servo_arc::Arc, i.e. it is preceded by a word-sized
|
||||
// refcount. So this pointer is an interior pointer. To get the start address
|
||||
// of the heap block we move the pointer back by one word. For this to work,
|
||||
// two things must be true.
|
||||
//
|
||||
// - The layout of servo_arc::Arc must stay the same.
|
||||
//
|
||||
// - The alignment of each nsStyleFoo must not be greater than the size of a
|
||||
// word (otherwise padding might be inserted between the refcount and the
|
||||
// struct in the servo_arc::Arc).
|
||||
//
|
||||
// In the long run a better solution here is for mozjemalloc to provide a
|
||||
// function that converts an interior pointer to a start pointer (bug
|
||||
// 1389305), but that's not available right now.
|
||||
//
|
||||
// Also, we use ServoStyleStructsMallocSizeOf rather than
|
||||
// |aState.mMallocSizeOf| to better distinguish in DMD's output the memory
|
||||
// measured here.
|
||||
#define STYLE_STRUCT(name_, cb_) \
|
||||
static_assert(alignof(nsStyle##name_) <= sizeof(size_t), \
|
||||
"alignment will break AddSizeOfExcludingThis()"); \
|
||||
const char* p##name_ = reinterpret_cast<const char*>(GetStyle##name_()); \
|
||||
p##name_ -= sizeof(size_t); \
|
||||
if (!aState.HaveSeenPtr(p##name_)) { \
|
||||
aSizes.NS_STYLE_SIZES_FIELD(name_) += \
|
||||
ServoStyleStructsMallocSizeOf(p##name_); \
|
||||
}
|
||||
#define STYLE_STRUCT_LIST_IGNORE_VARIABLES
|
||||
#include "nsStyleStructList.h"
|
||||
#undef STYLE_STRUCT
|
||||
#undef STYLE_STRUCT_LIST_IGNORE_VARIABLES
|
||||
}
|
||||
|
||||
void
|
||||
Gecko_ServoStyleContext_Destroy(ServoStyleContext* aContext)
|
||||
{
|
||||
|
|
|
@ -7,7 +7,10 @@
|
|||
#ifndef mozilla_ServoStyleContext_h
|
||||
#define mozilla_ServoStyleContext_h
|
||||
|
||||
#include "nsIMemoryReporter.h"
|
||||
#include "nsStyleContext.h"
|
||||
#include "nsWindowSizes.h"
|
||||
#include <algorithm>
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
@ -15,6 +18,8 @@ namespace dom {
|
|||
class Element;
|
||||
} // namespace dom
|
||||
|
||||
MOZ_DEFINE_MALLOC_SIZE_OF(ServoComputedValuesMallocSizeOf)
|
||||
|
||||
class ServoStyleContext final : public nsStyleContext
|
||||
{
|
||||
public:
|
||||
|
@ -95,6 +100,29 @@ public:
|
|||
*/
|
||||
inline void ResolveSameStructsAs(const ServoStyleContext* aOther);
|
||||
|
||||
void AddSizeOfIncludingThis(SizeOfState& aState, nsStyleSizes& aSizes,
|
||||
bool aIsDOM) const
|
||||
{
|
||||
// XXX WARNING: similar to ServoComputedData::AddSizeOfExcludingThis(),
|
||||
// but here we need to step back 4 or 8 bytes to get past the servo_arc::Arc
|
||||
// refcount to the base pointer.
|
||||
static_assert(alignof(ServoStyleContext) == 4 ||
|
||||
alignof(ServoStyleContext) == 8,
|
||||
"alignment will break AddSizeOfExcludingThis()");
|
||||
const char* p = reinterpret_cast<const char*>(this);
|
||||
p -= std::max(sizeof(size_t), alignof(ServoStyleContext));
|
||||
|
||||
// We use ServoComputedValuesMallocSizeOf rather than
|
||||
// |aState.mMallocSizeOf| to better distinguish in DMD's output the memory
|
||||
// measured here.
|
||||
if (aIsDOM) {
|
||||
aSizes.mComputedValuesDom += ServoComputedValuesMallocSizeOf(p);
|
||||
} else {
|
||||
aSizes.mComputedValuesNonDom += ServoComputedValuesMallocSizeOf(p);
|
||||
}
|
||||
mSource.AddSizeOfExcludingThis(aState, aSizes);
|
||||
}
|
||||
|
||||
private:
|
||||
nsPresContext* mPresContext;
|
||||
ServoComputedData mSource;
|
||||
|
|
|
@ -18,9 +18,12 @@
|
|||
* so don't add significant include dependencies to this file.
|
||||
*/
|
||||
|
||||
struct nsStyleSizes;
|
||||
struct ServoNodeData;
|
||||
namespace mozilla {
|
||||
|
||||
class SizeOfState;
|
||||
|
||||
/*
|
||||
* Replaced types. These get mapped to associated Servo types in bindgen.
|
||||
*/
|
||||
|
@ -230,6 +233,9 @@ public:
|
|||
#undef STYLE_STRUCT_LIST_IGNORE_VARIABLES
|
||||
const nsStyleVariables* GetStyleVariables() const;
|
||||
|
||||
void AddSizeOfExcludingThis(mozilla::SizeOfState& aState,
|
||||
nsStyleSizes& aSizes) const;
|
||||
|
||||
private:
|
||||
mozilla::ServoCustomPropertiesMap custom_properties;
|
||||
mozilla::ServoWritingMode writing_mode;
|
||||
|
|
|
@ -87,6 +87,9 @@ public:
|
|||
|
||||
static bool IsCSS2PseudoElement(nsIAtom *aAtom);
|
||||
|
||||
// This must match EAGER_PSEUDO_COUNT in Rust code.
|
||||
static const size_t kEagerPseudoCount = 4;
|
||||
|
||||
static bool IsEagerlyCascadedInServo(const Type aType)
|
||||
{
|
||||
return PseudoElementHasFlags(aType, CSS_PSEUDO_ELEMENT_IS_CSS2);
|
||||
|
|
|
@ -1677,7 +1677,9 @@ ReportHelper(const void* aPtr, bool aReportedOnAlloc)
|
|||
} else {
|
||||
// We have no record of the block. It must be a bogus pointer. This should
|
||||
// be extremely rare because Report() is almost always called in
|
||||
// conjunction with a malloc_size_of-style function.
|
||||
// conjunction with a malloc_size_of-style function. Print a message so
|
||||
// that we get some feedback.
|
||||
StatusMsg("Unknown pointer %p\n", aPtr);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче