--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -1612,16 +1612,18 @@ public:
void SetNeedStyleFlush() {
mNeedStyleFlush = true;
if (mDisplayDocument) {
mDisplayDocument->SetNeedStyleFlush();
}
}
+ virtual size_t SizeOfStyleSheets(nsMallocSizeOfFun aMallocSizeOf) const = 0;
+
private:
PRUint64 mWarnedAbout;
protected:
~nsIDocument()
{
// XXX The cleanup of mNodeInfoManager (calling DropDocumentReference and
// releasing it) happens in the nsDocument destructor. We'd prefer to
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -9129,8 +9129,23 @@ nsDocument::GetMozVisibilityState(nsAStr
static const char states[][8] = {
"hidden",
"visible"
};
PR_STATIC_ASSERT(NS_ARRAY_LENGTH(states) == eVisibilityStateCount);
aState.AssignASCII(states[mVisibilityState]);
return NS_OK;
}
+
+static size_t
+SizeOfStyleSheetsElementIncludingThis(nsIStyleSheet* aStyleSheet,
+ nsMallocSizeOfFun aMallocSizeOf,
+ void* aData)
+{
+ return aStyleSheet->SizeOfIncludingThis(aMallocSizeOf);
+}
+
+/* virtual */ size_t
+nsDocument::SizeOfStyleSheets(nsMallocSizeOfFun aMallocSizeOf) const
+{
+ return mStyleSheets.SizeOfExcludingThis(SizeOfStyleSheetsElementIncludingThis,
+ aMallocSizeOf);
+}
--- a/content/base/src/nsDocument.h
+++ b/content/base/src/nsDocument.h
@@ -986,16 +986,18 @@ public:
Element* FullScreenStackTop();
// This method may fire a DOM event; if it does so it will happen
// synchronously.
void UpdateVisibilityState();
// Posts an event to call UpdateVisibilityState
virtual void PostVisibilityUpdateEvent();
+ virtual size_t SizeOfStyleSheets(nsMallocSizeOfFun aMallocSizeOf) const;
+
protected:
friend class nsNodeUtils;
// Returns true if a request for DOM full-screen is currently enabled in
// this document. This returns true if there are no windowed plugins in this
// doc tree, and if the document is visible, and if the api is not
// disabled by pref. aIsCallerChrome must contain the return value of
// nsContentUtils::IsCallerChrome() from the context we're checking.
--- a/dom/base/nsDOMMemoryReporter.cpp
+++ b/dom/base/nsDOMMemoryReporter.cpp
@@ -83,24 +83,32 @@ AppendWindowURI(nsGlobalWindow *aWindow,
// (such as about:memory) have to undo this change.
spec.ReplaceChar('/', '\\');
aStr += spec;
return true;
}
+struct WindowTotals
+{
+ WindowTotals() : mDom(0), mStyleSheets(0) {}
+ size_t mDom;
+ size_t mStyleSheets;
+};
+
+NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(WindowStyleSheetsMallocSizeOf,
+ "window/style-sheets")
+
static void
-CollectWindowMemoryUsage(nsGlobalWindow *aWindow,
- nsIMemoryMultiReporterCallback *aCb,
- nsISupports *aClosure)
+CollectWindowReports(nsGlobalWindow *aWindow,
+ WindowTotals *aWindowTotals,
+ nsIMemoryMultiReporterCallback *aCb,
+ nsISupports *aClosure)
{
- NS_NAMED_LITERAL_CSTRING(kWindowDesc,
- "Memory used by a window and the DOM within it.");
-
// DOM window objects fall into one of three categories:
// - "active" windows are currently either displayed in an active
// tab, or a child of such a window.
// - "cached" windows are in the fastback cache.
// - "other" windows are closed (or navigated away from w/o being
// cached) yet held alive by either a website or our code. The
// latter case may be a memory leak, but not necessarily.
//
@@ -114,17 +122,17 @@ CollectWindowMemoryUsage(nsGlobalWindow
// For outer windows we simply group them all together and just show
// the combined count and amount of memory used, which is generally
// a constant amount per window (since all the actual data lives in
// the inner window).
//
// The path we give to the reporter callback for inner windows are
// as follows:
//
- // explicit/dom/window-objects/<category>/top=<top-outer-id> (inner=<top-inner-id>)/inner-window(id=<id>, uri=<uri>)
+ // explicit/dom+style/window-objects/<category>/top=<top-outer-id> (inner=<top-inner-id>)/inner-window(id=<id>, uri=<uri>)
//
// Where:
// - <category> is active, cached, or other, as described above.
// - <top-outer-id> is the window id (nsPIDOMWindow::WindowID()) of
// the top outer window (i.e. tab, or top level chrome window).
// - <top-inner-id> is the window id of the top window's inner
// window.
// - <id> is the window id of the inner window in question.
@@ -133,72 +141,92 @@ CollectWindowMemoryUsage(nsGlobalWindow
// Exposing the window ids is done to get logical grouping in
// about:memory, and also for debuggability since one can get to the
// nsGlobalWindow for a window id by calling the static method
// nsGlobalWindow::GetInnerWindowWithId(id) (or
// GetOuterWindowWithId(id) in a debugger.
//
// For outer windows we simply use:
//
- // explicit/dom/window-objects/<category>/outer-windows
+ // explicit/dom+style/window-objects/<category>/outer-windows
//
// Which gives us simple counts of how many outer windows (and their
// combined sizes) per category.
- nsCAutoString str("explicit/dom/window-objects/");
+ nsCAutoString windowPath("explicit/dom+style/window-objects/");
nsIDocShell *docShell = aWindow->GetDocShell();
nsGlobalWindow *top = aWindow->GetTop();
- PRInt64 windowSize = aWindow->SizeOf();
+ PRInt64 windowDOMSize = aWindow->SizeOf();
+ PRInt64 styleSheetsSize = aWindow->SizeOfStyleSheets(WindowStyleSheetsMallocSizeOf);
if (docShell && aWindow->IsFrozen()) {
- str += NS_LITERAL_CSTRING("cached/");
+ windowPath += NS_LITERAL_CSTRING("cached/");
} else if (docShell) {
- str += NS_LITERAL_CSTRING("active/");
+ windowPath += NS_LITERAL_CSTRING("active/");
} else {
- str += NS_LITERAL_CSTRING("other/");
+ windowPath += NS_LITERAL_CSTRING("other/");
}
if (aWindow->IsInnerWindow()) {
- str += NS_LITERAL_CSTRING("top=");
+ windowPath += NS_LITERAL_CSTRING("top=");
if (top) {
- str.AppendInt(top->WindowID());
+ windowPath.AppendInt(top->WindowID());
nsGlobalWindow *topInner = top->GetCurrentInnerWindowInternal();
if (topInner) {
- str += NS_LITERAL_CSTRING(" (inner=");
- str.AppendInt(topInner->WindowID());
- str += NS_LITERAL_CSTRING(")");
+ windowPath += NS_LITERAL_CSTRING(" (inner=");
+ windowPath.AppendInt(topInner->WindowID());
+ windowPath += NS_LITERAL_CSTRING(")");
}
} else {
- str += NS_LITERAL_CSTRING("none");
+ windowPath += NS_LITERAL_CSTRING("none");
}
- str += NS_LITERAL_CSTRING("/inner-window(id=");
- str.AppendInt(aWindow->WindowID());
- str += NS_LITERAL_CSTRING(", uri=");
+ windowPath += NS_LITERAL_CSTRING("/inner-window(id=");
+ windowPath.AppendInt(aWindow->WindowID());
+ windowPath += NS_LITERAL_CSTRING(", uri=");
- if (!AppendWindowURI(aWindow, str)) {
- str += NS_LITERAL_CSTRING("[system]");
+ if (!AppendWindowURI(aWindow, windowPath)) {
+ windowPath += NS_LITERAL_CSTRING("[system]");
}
- str += NS_LITERAL_CSTRING(")");
+ windowPath += NS_LITERAL_CSTRING(")");
} else {
// Combine all outer windows per section (active/cached/other) as
// they basically never contain anything of interest, and are
// always pretty much the same size.
- str += NS_LITERAL_CSTRING("outer-windows");
+ windowPath += NS_LITERAL_CSTRING("outer-windows");
}
- aCb->Callback(EmptyCString(), str, nsIMemoryReporter::KIND_HEAP,
- nsIMemoryReporter::UNITS_BYTES, windowSize, kWindowDesc,
- aClosure);
+ if (windowDOMSize > 0) {
+ nsCAutoString domPath(windowPath);
+ domPath += "/dom";
+ NS_NAMED_LITERAL_CSTRING(kWindowDesc,
+ "Memory used by a window and the DOM within it.");
+ aCb->Callback(EmptyCString(), domPath, nsIMemoryReporter::KIND_HEAP,
+ nsIMemoryReporter::UNITS_BYTES, windowDOMSize, kWindowDesc,
+ aClosure);
+ aWindowTotals->mDom += windowDOMSize;
+ }
+
+ if (styleSheetsSize > 0) {
+ nsCAutoString styleSheetsPath(windowPath);
+ styleSheetsPath += "/style-sheets";
+ NS_NAMED_LITERAL_CSTRING(kStyleSheetsDesc,
+ "Memory used by style sheets within a window.");
+ aCb->Callback(EmptyCString(), styleSheetsPath,
+ nsIMemoryReporter::KIND_HEAP,
+ nsIMemoryReporter::UNITS_BYTES, styleSheetsSize,
+ kStyleSheetsDesc, aClosure);
+ aWindowTotals->mStyleSheets += styleSheetsSize;
+ }
}
typedef nsTArray< nsRefPtr<nsGlobalWindow> > WindowArray;
static
PLDHashOperator
GetWindows(const PRUint64& aId, nsGlobalWindow*& aWindow, void* aClosure)
{
@@ -218,20 +246,37 @@ nsDOMMemoryMultiReporter::CollectReports
// Hold on to every window in memory so that window objects can't be
// destroyed while we're calling the memory reporter callback.
WindowArray windows;
windowsById->Enumerate(GetWindows, &windows);
// Collect window memory usage.
nsRefPtr<nsGlobalWindow> *w = windows.Elements();
nsRefPtr<nsGlobalWindow> *end = w + windows.Length();
+ WindowTotals windowTotals;
for (; w != end; ++w) {
- CollectWindowMemoryUsage(*w, aCb, aClosure);
+ CollectWindowReports(*w, &windowTotals, aCb, aClosure);
}
+ NS_NAMED_LITERAL_CSTRING(kDomTotalWindowsDesc,
+ "Memory used for the DOM within windows. This is the sum of all windows' "
+ "'dom' numbers.");
+ aCb->Callback(EmptyCString(), NS_LITERAL_CSTRING("dom-total-window"),
+ nsIMemoryReporter::KIND_OTHER,
+ nsIMemoryReporter::UNITS_BYTES, windowTotals.mDom,
+ kDomTotalWindowsDesc, aClosure);
+
+ NS_NAMED_LITERAL_CSTRING(kLayoutTotalWindowStyleSheetsDesc,
+ "Memory used for style sheets within windows. This is the sum of all windows' "
+ "'style-sheets' numbers.");
+ aCb->Callback(EmptyCString(), NS_LITERAL_CSTRING("style-sheets-total-window"),
+ nsIMemoryReporter::KIND_OTHER,
+ nsIMemoryReporter::UNITS_BYTES, windowTotals.mStyleSheets,
+ kLayoutTotalWindowStyleSheetsDesc, aClosure);
+
return NS_OK;
}
NS_IMETHODIMP
nsDOMMemoryMultiReporter::GetExplicitNonHeap(PRInt64* aAmount)
{
// This reporter only measures heap memory.
*aAmount = 0;
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -10291,16 +10291,26 @@ nsGlobalWindow::SizeOf() const
}
}
size += mNavigator ? mNavigator->SizeOf() : 0;
return size;
}
+size_t
+nsGlobalWindow::SizeOfStyleSheets(nsMallocSizeOfFun aMallocSizeOf) const
+{
+ size_t n = 0;
+ if (IsInnerWindow() && mDoc) {
+ n += mDoc->SizeOfStyleSheets(aMallocSizeOf);
+ }
+ return n;
+}
+
// nsGlobalChromeWindow implementation
NS_IMPL_CYCLE_COLLECTION_CLASS(nsGlobalChromeWindow)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsGlobalChromeWindow,
nsGlobalWindow)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mBrowserDOMWindow)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mMessageManager)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -571,16 +571,17 @@ public:
static bool HasPerformanceSupport();
static WindowByIdTable* GetWindowsTable() {
return sWindowsById;
}
PRInt64 SizeOf() const;
+ size_t SizeOfStyleSheets(nsMallocSizeOfFun aMallocSizeOf) const;
void UnmarkGrayTimers();
private:
// Enable updates for the accelerometer.
void EnableDeviceMotionUpdates();
// Disables updates for the accelerometer.
void DisableDeviceMotionUpdates();
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -150,16 +150,18 @@ SwapToISupportsArray(SmartPtr<T>& aSrc,
T* raw = nsnull;
aSrc.swap(raw);
nsISupports* rawSupports =
static_cast<typename ISupportsBaseInfo<T>::ISupportsBase*>(raw);
dest->swap(rawSupports);
}
+NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(JsWorkerMallocSizeOf, "js-worker")
+
class WorkerMemoryReporter : public nsIMemoryMultiReporter
{
WorkerPrivate* mWorkerPrivate;
nsCString mAddressString;
nsCString mPathPrefix;
public:
NS_DECL_ISUPPORTS
@@ -227,17 +229,17 @@ public:
}
NS_IMETHOD
CollectReports(nsIMemoryMultiReporterCallback* aCallback,
nsISupports* aClosure)
{
AssertIsOnMainThread();
- JS::RuntimeStats rtStats(xpc::JsMallocSizeOf, xpc::GetCompartmentName,
+ JS::RuntimeStats rtStats(JsWorkerMallocSizeOf, xpc::GetCompartmentName,
xpc::DestroyCompartmentName);
nsresult rv = CollectForRuntime(/* isQuick = */false, &rtStats);
if (NS_FAILED(rv)) {
return rv;
}
// Always report, even if we're disabled, so that we at least get an entry
// in about::memory.
@@ -1518,17 +1520,17 @@ public:
}
bool
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
{
JSAutoSuspendRequest asr(aCx);
*mSucceeded = mIsQuick
- ? JS::GetExplicitNonHeapForRuntime(JS_GetRuntime(aCx), static_cast<int64_t*>(mData), xpc::JsMallocSizeOf)
+ ? JS::GetExplicitNonHeapForRuntime(JS_GetRuntime(aCx), static_cast<int64_t*>(mData), JsWorkerMallocSizeOf)
: JS::CollectRuntimeStats(JS_GetRuntime(aCx), static_cast<JS::RuntimeStats*>(mData));
{
MutexAutoLock lock(mMutex);
mDone = true;
mCondVar.Notify();
}
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -1270,18 +1270,16 @@ GetCompartmentName(JSContext *cx, JSComp
}
void
DestroyCompartmentName(void *string)
{
delete static_cast<nsCString*>(string);
}
-NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(JsMallocSizeOf, "js")
-
} // namespace xpc
namespace {
template <int N>
inline void
ReportMemory(const nsACString &path, PRInt32 kind, PRInt32 units,
PRInt64 amount, const char (&desc)[N],
@@ -1720,41 +1718,43 @@ ReportJSRuntimeStats(const JS::RuntimeSt
// should equal rtStats.gcHeapChunkTotal.
JS_ASSERT(gcTotal == rtStats.gcHeapChunkTotal);
}
} // namespace memory
} // namespace xpconnect
} // namespace mozilla
+NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(JsMallocSizeOf, "js")
+
class XPConnectJSCompartmentsMultiReporter : public nsIMemoryMultiReporter
{
public:
NS_DECL_ISUPPORTS
NS_IMETHOD CollectReports(nsIMemoryMultiReporterCallback *callback,
nsISupports *closure)
{
XPCJSRuntime *xpcrt = nsXPConnect::GetRuntimeInstance();
// In the first step we get all the stats and stash them in a local
// data structure. In the second step we pass all the stashed stats to
// the callback. Separating these steps is important because the
// callback may be a JS function, and executing JS while getting these
// stats seems like a bad idea.
- JS::RuntimeStats rtStats(xpc::JsMallocSizeOf, xpc::GetCompartmentName,
+ JS::RuntimeStats rtStats(JsMallocSizeOf, xpc::GetCompartmentName,
xpc::DestroyCompartmentName);
if (!JS::CollectRuntimeStats(xpcrt->GetJSRuntime(), &rtStats))
return NS_ERROR_FAILURE;
size_t xpconnect;
{
xpconnect =
- xpcrt->SizeOfIncludingThis(xpc::JsMallocSizeOf) +
- XPCWrappedNativeScope::SizeOfAllScopesIncludingThis(xpc::JsMallocSizeOf);
+ xpcrt->SizeOfIncludingThis(JsMallocSizeOf) +
+ XPCWrappedNativeScope::SizeOfAllScopesIncludingThis(JsMallocSizeOf);
}
NS_NAMED_LITERAL_CSTRING(pathPrefix, "explicit/js/");
// This is the second step (see above).
ReportJSRuntimeStats(rtStats, pathPrefix, callback, closure);
ReportMemoryBytes(pathPrefix + NS_LITERAL_CSTRING("xpconnect"),
@@ -1850,17 +1850,17 @@ public:
return NS_OK;
}
NS_IMETHOD
GetExplicitNonHeap(PRInt64 *n)
{
JSRuntime *rt = nsXPConnect::GetRuntimeInstance()->GetJSRuntime();
- if (!JS::GetExplicitNonHeapForRuntime(rt, reinterpret_cast<int64_t*>(n), xpc::JsMallocSizeOf))
+ if (!JS::GetExplicitNonHeapForRuntime(rt, reinterpret_cast<int64_t*>(n), JsMallocSizeOf))
return NS_ERROR_FAILURE;
return NS_OK;
}
};
NS_IMPL_THREADSAFE_ISUPPORTS1(XPConnectJSCompartmentsMultiReporter
, nsIMemoryMultiReporter
--- a/js/xpconnect/src/xpcpublic.h
+++ b/js/xpconnect/src/xpcpublic.h
@@ -214,17 +214,16 @@ bool Base64Decode(JSContext *cx, JS::Val
* Convert an nsString to jsval, returning true on success.
* Note, the ownership of the string buffer may be moved from str to rval.
* If that happens, str will point to an empty string after this call.
*/
bool StringToJsval(JSContext *cx, nsString &str, JS::Value *rval);
void *GetCompartmentName(JSContext *cx, JSCompartment *c);
void DestroyCompartmentName(void *string);
-size_t JsMallocSizeOf(const void *ptr);
} // namespace xpc
class nsIMemoryMultiReporterCallback;
namespace mozilla {
namespace xpconnect {
namespace memory {
--- a/layout/base/nsPresContext.h
+++ b/layout/base/nsPresContext.h
@@ -960,19 +960,20 @@ public:
mContainsUpdatePluginGeometryFrame = aValue;
}
bool MayHaveFixedBackgroundFrames() { return mMayHaveFixedBackgroundFrames; }
void SetHasFixedBackgroundFrame() { mMayHaveFixedBackgroundFrames = true; }
virtual NS_MUST_OVERRIDE size_t
SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const {
- // XXX: lots of things hang off nsPresContext and should be included in
- // this measurement. Bug 671299 may add them.
return 0;
+
+ // Measurement of other members may be added later if DMD finds it is
+ // worthwhile.
}
virtual NS_MUST_OVERRIDE size_t
SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const {
return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
}
bool IsRootContentDocument();
@@ -1313,19 +1314,27 @@ public:
/**
* Run all runnables that need to get called before the next paint.
*/
void FlushWillPaintObservers();
virtual NS_MUST_OVERRIDE size_t
SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const MOZ_OVERRIDE {
- // XXX: several things hang off an nsRootPresContext and should be included
- // in this measurement. Bug 671299 may do this.
return nsPresContext::SizeOfExcludingThis(aMallocSizeOf);
+
+ // Measurement of the following members may be added later if DMD finds it is
+ // worthwhile:
+ // - mNotifyDidPaintTimer
+ // - mRegisteredPlugins
+ // - mWillPaintObservers
+ // - mWillPaintFallbackEvent
+ //
+ // The following member are not measured:
+ // - mUpdatePluginGeometryForFrame, because it is non-owning
}
virtual NS_MUST_OVERRIDE size_t
SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const MOZ_OVERRIDE {
return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
}
protected:
class RunWillPaintObservers : public nsRunnable {
--- a/layout/style/AnimationCommon.cpp
+++ b/layout/style/AnimationCommon.cpp
@@ -124,17 +124,23 @@ CommonAnimationManager::HasAttributeDepe
CommonAnimationManager::MediumFeaturesChanged(nsPresContext* aPresContext)
{
return false;
}
/* virtual */ size_t
CommonAnimationManager::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const
{
- // XXX: could measure mProperytValuePairs here. Bug 671299 may do this.
+ // Measurement of the following members may be added later if DMD finds it is
+ // worthwhile:
+ // - mElementData
+ //
+ // The following members are not measured
+ // - mPresContext, because it's non-owning
+
return 0;
}
/* virtual */ size_t
CommonAnimationManager::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
{
return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
}
--- a/layout/style/Declaration.cpp
+++ b/layout/style/Declaration.cpp
@@ -989,10 +989,20 @@ Declaration::EnsureMutable()
NS_ABORT_IF_FALSE(mData, "should only be called when not expanded");
if (!IsMutable()) {
return new Declaration(*this);
} else {
return this;
}
}
+size_t
+Declaration::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
+{
+ size_t n = aMallocSizeOf(this);
+ n += mOrder.SizeOfExcludingThis(aMallocSizeOf);
+ n += mData ? mData ->SizeOfIncludingThis(aMallocSizeOf) : 0;
+ n += mImportantData ? mImportantData->SizeOfIncludingThis(aMallocSizeOf) : 0;
+ return n;
+}
+
} // namespace mozilla::css
} // namespace mozilla
--- a/layout/style/Declaration.h
+++ b/layout/style/Declaration.h
@@ -252,16 +252,18 @@ private:
nsAutoString& aValue,
nsAString& aResult) const;
public:
nsCSSProperty OrderValueAt(PRUint32 aValue) const {
return nsCSSProperty(mOrder.ElementAt(aValue));
}
+ size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
+
private:
nsAutoTArray<PRUint8, 8> mOrder;
// never null, except while expanded, or before the first call to
// InitializeEmpty or CompressFrom.
nsAutoPtr<nsCSSCompressedDataBlock> mData;
// may be null
--- a/layout/style/GroupRule.h
+++ b/layout/style/GroupRule.h
@@ -91,16 +91,21 @@ public:
nsresult DeleteStyleRuleAt(PRUint32 aIndex);
nsresult InsertStyleRulesAt(PRUint32 aIndex,
nsCOMArray<Rule>& aRules);
nsresult ReplaceStyleRule(Rule *aOld, Rule *aNew);
virtual bool UseForPresentation(nsPresContext* aPresContext,
nsMediaQueryResultCacheKey& aKey) = 0;
+ NS_MUST_OVERRIDE size_t // non-virtual -- it is only called by subclasses
+ SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
+ virtual size_t
+ SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const = 0;
+
protected:
// to help implement nsIDOMCSSRule
nsresult AppendRulesToCssText(nsAString& aCssText);
// to implement common methods on nsIDOMCSSMediaRule and
// nsIDOMCSSMozDocumentRule
nsresult GetCssRules(nsIDOMCSSRuleList* *aRuleList);
nsresult InsertRule(const nsAString & aRule, PRUint32 aIndex,
--- a/layout/style/ImportRule.h
+++ b/layout/style/ImportRule.h
@@ -76,16 +76,18 @@ public:
#endif
// Rule methods
virtual PRInt32 GetType() const;
virtual already_AddRefed<Rule> Clone() const;
void SetSheet(nsCSSStyleSheet*);
+ virtual size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
+
// nsIDOMCSSRule interface
NS_DECL_NSIDOMCSSRULE
// nsIDOMCSSImportRule interface
NS_DECL_NSIDOMCSSIMPORTRULE
private:
nsString mURLSpec;
--- a/layout/style/NameSpaceRule.h
+++ b/layout/style/NameSpaceRule.h
@@ -79,16 +79,19 @@ public:
// Rule methods
virtual PRInt32 GetType() const;
virtual already_AddRefed<Rule> Clone() const;
nsIAtom* GetPrefix() const { return mPrefix; }
void GetURLSpec(nsString& aURLSpec) const { aURLSpec = mURLSpec; }
+ virtual NS_MUST_OVERRIDE size_t
+ SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
+
// nsIDOMCSSRule interface
NS_DECL_NSIDOMCSSRULE
private:
nsCOMPtr<nsIAtom> mPrefix;
nsString mURLSpec;
};
--- a/layout/style/Rule.h
+++ b/layout/style/Rule.h
@@ -124,16 +124,26 @@ public:
// Note that this returns null for inline style rules since they aren't
// supposed to have a DOM rule representation (and our code wouldn't work).
virtual nsIDOMCSSRule* GetDOMRule() = 0;
// to implement methods on nsIDOMCSSRule
nsresult GetParentRule(nsIDOMCSSRule** aParentRule);
nsresult GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet);
+ // This is pure virtual because all of Rule's data members are non-owning and
+ // thus measured elsewhere.
+ virtual NS_MUST_OVERRIDE size_t
+ SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const = 0;
+
+ // This is used to measure nsCOMArray<Rule>s.
+ static size_t SizeOfCOMArrayElementIncludingThis(css::Rule* aElement,
+ nsMallocSizeOfFun aMallocSizeOf,
+ void* aData);
+
protected:
nsCSSStyleSheet* mSheet;
GroupRule* mParentRule;
};
} // namespace css
} // namespace mozilla
--- a/layout/style/StyleRule.cpp
+++ b/layout/style/StyleRule.cpp
@@ -120,16 +120,32 @@ nsAtomList::Clone(bool aDeep) const
if (!result)
return nsnull;
if (aDeep)
NS_CSS_CLONE_LIST_MEMBER(nsAtomList, this, mNext, result, (false));
return result;
}
+size_t
+nsAtomList::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
+{
+ size_t n = 0;
+ const nsAtomList* a = this;
+ while (a) {
+ n += aMallocSizeOf(a);
+
+ // The following members aren't measured:
+ // - a->mAtom, because it may be shared
+
+ a = a->mNext;
+ }
+ return n;
+}
+
nsAtomList::~nsAtomList(void)
{
MOZ_COUNT_DTOR(nsAtomList);
NS_CSS_DELETE_LIST_MEMBER(nsAtomList, this, mNext);
}
nsPseudoClassList::nsPseudoClassList(nsCSSPseudoClasses::Type aType)
: mType(aType),
@@ -199,16 +215,42 @@ nsPseudoClassList::Clone(bool aDeep) con
if (aDeep)
NS_CSS_CLONE_LIST_MEMBER(nsPseudoClassList, this, mNext, result,
(false));
return result;
}
+size_t
+nsPseudoClassList::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
+{
+ size_t n = 0;
+ const nsPseudoClassList* p = this;
+ while (p) {
+ n += aMallocSizeOf(p);
+ if (!p->u.mMemory) {
+ // do nothing
+
+ } else if (nsCSSPseudoClasses::HasStringArg(p->mType)) {
+ n += aMallocSizeOf(p->u.mString);
+
+ } else if (nsCSSPseudoClasses::HasNthPairArg(p->mType)) {
+ n += aMallocSizeOf(p->u.mNumbers);
+
+ } else {
+ NS_ASSERTION(nsCSSPseudoClasses::HasSelectorListArg(p->mType),
+ "unexpected pseudo-class");
+ n += p->u.mSelectors->SizeOfIncludingThis(aMallocSizeOf);
+ }
+ p = p->mNext;
+ }
+ return n;
+}
+
nsPseudoClassList::~nsPseudoClassList(void)
{
MOZ_COUNT_DTOR(nsPseudoClassList);
if (nsCSSPseudoClasses::HasSelectorListArg(mType)) {
delete u.mSelectors;
} else if (u.mMemory) {
NS_Free(u.mMemory);
}
@@ -805,16 +847,44 @@ nsCSSSelector::AppendToStringWithoutComb
bool
nsCSSSelector::CanBeNamespaced(bool aIsNegated) const
{
return !aIsNegated ||
(!mIDList && !mClassList && !mPseudoClassList && !mAttrList);
}
+size_t
+nsCSSSelector::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
+{
+ size_t n = 0;
+ const nsCSSSelector* s = this;
+ while (s) {
+ n += aMallocSizeOf(s);
+
+ #define MEASURE(x) n += x ? x->SizeOfIncludingThis(aMallocSizeOf) : 0;
+
+ MEASURE(s->mIDList);
+ MEASURE(s->mClassList);
+ MEASURE(s->mPseudoClassList);
+ MEASURE(s->mNegations);
+
+ // Measurement of the following members may be added later if DMD finds it is
+ // worthwhile:
+ // - s->mAttrList
+ //
+ // The following members aren't measured:
+ // - s->mLowercaseTag, because it's an atom and therefore shared
+ // - s->mCasedTag, because it's an atom and therefore shared
+
+ s = s->mNext;
+ }
+ return n;
+}
+
// -- nsCSSSelectorList -------------------------------
nsCSSSelectorList::nsCSSSelectorList(void)
: mSelectors(nsnull),
mWeight(0),
mNext(nsnull)
{
MOZ_COUNT_CTOR(nsCSSSelectorList);
@@ -867,16 +937,29 @@ nsCSSSelectorList::Clone(bool aDeep) con
if (aDeep) {
NS_CSS_CLONE_LIST_MEMBER(nsCSSSelectorList, this, mNext, result,
(false));
}
return result;
}
+size_t
+nsCSSSelectorList::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
+{
+ size_t n = 0;
+ const nsCSSSelectorList* s = this;
+ while (s) {
+ n += aMallocSizeOf(s);
+ n += s->mSelectors ? s->mSelectors->SizeOfIncludingThis(aMallocSizeOf) : 0;
+ s = s->mNext;
+ }
+ return n;
+}
+
// -- ImportantRule ----------------------------------
namespace mozilla {
namespace css {
ImportantRule::ImportantRule(Declaration* aDeclaration)
: mDeclaration(aDeclaration)
{
@@ -1417,10 +1500,26 @@ StyleRule::GetSelectorText(nsAString& aS
void
StyleRule::SetSelectorText(const nsAString& aSelectorText)
{
// XXX TBI - get a parser and re-parse the selectors,
// XXX then need to re-compute the cascade
// XXX and dirty sheet
}
+/* virtual */ size_t
+StyleRule::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
+{
+ size_t n = aMallocSizeOf(this);
+ n += mSelector ? mSelector->SizeOfIncludingThis(aMallocSizeOf) : 0;
+ n += mDeclaration ? mDeclaration->SizeOfIncludingThis(aMallocSizeOf) : 0;
+
+ // Measurement of the following members may be added later if DMD finds it is
+ // worthwhile:
+ // - mImportantRule;
+ // - mDOMRule;
+
+ return n;
+}
+
+
} // namespace css
} // namespace mozilla
--- a/layout/style/StyleRule.h
+++ b/layout/style/StyleRule.h
@@ -65,16 +65,18 @@ struct nsAtomList {
public:
nsAtomList(nsIAtom* aAtom);
nsAtomList(const nsString& aAtomValue);
~nsAtomList(void);
/** Do a deep clone. Should be used only on the first in the linked list. */
nsAtomList* Clone() const { return Clone(true); }
+ size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
+
nsCOMPtr<nsIAtom> mAtom;
nsAtomList* mNext;
private:
nsAtomList* Clone(bool aDeep) const;
nsAtomList(const nsAtomList& aCopy) MOZ_DELETE;
nsAtomList& operator=(const nsAtomList& aCopy) MOZ_DELETE;
};
@@ -86,16 +88,18 @@ public:
nsPseudoClassList(nsCSSPseudoClasses::Type aType, const PRInt32 *aIntPair);
nsPseudoClassList(nsCSSPseudoClasses::Type aType,
nsCSSSelectorList *aSelectorList /* takes ownership */);
~nsPseudoClassList(void);
/** Do a deep clone. Should be used only on the first in the linked list. */
nsPseudoClassList* Clone() const { return Clone(true); }
+ size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
+
union {
// For a given value of mType, we have either:
// a. no value, which means mMemory is always null
// (if none of the conditions for (b), (c), or (d) is true)
// b. a string value, which means mString/mMemory is non-null
// (if nsCSSPseudoClasses::HasStringArg(mType))
// c. an integer pair value, which means mNumbers/mMemory is non-null
// (if nsCSSPseudoClasses::HasNthPairArg(mType))
@@ -212,16 +216,18 @@ public:
nsCSSPseudoElements::Type PseudoType() const {
return static_cast<nsCSSPseudoElements::Type>(mPseudoType);
}
void SetPseudoType(nsCSSPseudoElements::Type aType) {
NS_ASSERTION(aType > PR_INT16_MIN && aType < PR_INT16_MAX, "Out of bounds");
mPseudoType = static_cast<PRInt16>(aType);
}
+ size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
+
// For case-sensitive documents, mLowercaseTag is the same as mCasedTag,
// but in case-insensitive documents (HTML) mLowercaseTag is lowercase.
// Also, for pseudo-elements mCasedTag will be null but mLowercaseTag
// contains their name.
nsCOMPtr<nsIAtom> mLowercaseTag;
nsCOMPtr<nsIAtom> mCasedTag;
nsAtomList* mIDList;
nsAtomList* mClassList;
@@ -266,16 +272,18 @@ struct nsCSSSelectorList {
*/
void ToString(nsAString& aResult, nsCSSStyleSheet* aSheet);
/**
* Do a deep clone. Should be used only on the first in the list.
*/
nsCSSSelectorList* Clone() const { return Clone(true); }
+ size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
+
nsCSSSelector* mSelectors;
PRInt32 mWeight;
nsCSSSelectorList* mNext;
private:
nsCSSSelectorList* Clone(bool aDeep) const;
nsCSSSelectorList(const nsCSSSelectorList& aCopy) MOZ_DELETE;
nsCSSSelectorList& operator=(const nsCSSSelectorList& aCopy) MOZ_DELETE;
@@ -375,16 +383,18 @@ public:
// The new mapping function.
virtual void MapRuleInfoInto(nsRuleData* aRuleData);
#ifdef DEBUG
virtual void List(FILE* out = stdout, PRInt32 aIndent = 0) const;
#endif
+ virtual size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
+
private:
~StyleRule();
private:
nsCSSSelectorList* mSelector; // null for style attribute
Declaration* mDeclaration;
ImportantRule* mImportantRule; // initialized by RuleMatched
DOMCSSStyleRule* mDOMRule;
--- a/layout/style/nsAnimationManager.cpp
+++ b/layout/style/nsAnimationManager.cpp
@@ -430,19 +430,22 @@ nsAnimationManager::RulesMatching(AnonBo
nsAnimationManager::RulesMatching(XULTreeRuleProcessorData* aData)
{
}
#endif
/* virtual */ size_t
nsAnimationManager::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const
{
- // XXX: various other members in nsAnimationManager could be measured here.
- // Bug 671299 may do this.
return CommonAnimationManager::SizeOfExcludingThis(aMallocSizeOf);
+
+ // Measurement of the following members may be added later if DMD finds it is
+ // worthwhile:
+ // - mKeyframesRules
+ // - mPendingEvents
}
/* virtual */ size_t
nsAnimationManager::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
{
return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
}
--- a/layout/style/nsCSSDataBlock.cpp
+++ b/layout/style/nsCSSDataBlock.cpp
@@ -302,16 +302,30 @@ nsCSSCompressedDataBlock::~nsCSSCompress
/* static */ nsCSSCompressedDataBlock*
nsCSSCompressedDataBlock::CreateEmptyBlock()
{
nsCSSCompressedDataBlock *result = new(0) nsCSSCompressedDataBlock();
result->SetBlockEnd(result->Block());
return result;
}
+size_t
+nsCSSCompressedDataBlock::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
+{
+ size_t n = aMallocSizeOf(this);
+
+ const char* cursor = Block();
+ const char* cursor_end = BlockEnd();
+ while (cursor < cursor_end) {
+ n += ValueAtCursor(cursor)->SizeOfExcludingThis(aMallocSizeOf);
+ cursor += CDBValueStorage_advance;
+ }
+ return n;
+}
+
/*****************************************************************************/
nsCSSExpandedDataBlock::nsCSSExpandedDataBlock()
{
AssertInitialState();
}
nsCSSExpandedDataBlock::~nsCSSExpandedDataBlock()
--- a/layout/style/nsCSSDataBlock.h
+++ b/layout/style/nsCSSDataBlock.h
@@ -116,16 +116,18 @@ public:
*/
nsCSSCompressedDataBlock* Clone() const;
/**
* Create a new nsCSSCompressedDataBlock holding no declarations.
*/
static nsCSSCompressedDataBlock* CreateEmptyBlock();
+ size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
+
private:
void* operator new(size_t aBaseSize, size_t aDataSize) {
NS_ABORT_IF_FALSE(aBaseSize == sizeof(nsCSSCompressedDataBlock),
"unexpected size for nsCSSCompressedDataBlock");
return ::operator new(aBaseSize + aDataSize);
}
/**
--- a/layout/style/nsCSSRules.cpp
+++ b/layout/style/nsCSSRules.cpp
@@ -112,16 +112,23 @@ nsresult
Rule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
{
NS_ENSURE_ARG_POINTER(aSheet);
NS_IF_ADDREF(*aSheet = mSheet);
return NS_OK;
}
+size_t
+Rule::SizeOfCOMArrayElementIncludingThis(css::Rule* aElement,
+ nsMallocSizeOfFun aMallocSizeOf,
+ void* aData)
+{
+ return aElement->SizeOfIncludingThis(aMallocSizeOf);
+}
// -------------------------------
// Style Rule List for group rules
//
class GroupRuleRuleList MOZ_FINAL : public nsICSSRuleList
{
public:
@@ -317,17 +324,25 @@ CharsetRule::GetParentStyleSheet(nsIDOMC
}
NS_IMETHODIMP
CharsetRule::GetParentRule(nsIDOMCSSRule** aParentRule)
{
return Rule::GetParentRule(aParentRule);
}
+/* virtual */ size_t
+CharsetRule::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
+{
+ return aMallocSizeOf(this);
+ // Measurement of the following members may be added later if DMD finds it is
+ // worthwhile:
+ // - mEncoding
+}
// -------------------------------------------
// ImportRule
//
ImportRule::ImportRule(nsMediaList* aMedia, const nsString& aURLSpec)
: Rule()
, mURLSpec(aURLSpec)
@@ -485,16 +500,30 @@ NS_IMETHODIMP
ImportRule::GetStyleSheet(nsIDOMCSSStyleSheet * *aStyleSheet)
{
NS_ENSURE_ARG_POINTER(aStyleSheet);
NS_IF_ADDREF(*aStyleSheet = mChildSheet);
return NS_OK;
}
+/* virtual */ size_t
+ImportRule::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
+{
+ return aMallocSizeOf(this);
+
+ // Measurement of the following members may be added later if DMD finds it is
+ // worthwhile:
+ // - mURLSpec
+ //
+ // The following members are not measured:
+ // - mMedia, because it is measured via nsCSSStyleSheet::mMedia
+ // - mChildSheet, because it is measured via nsCSSStyleSheetInner::mSheets
+}
+
} // namespace css
} // namespace mozilla
// must be outside the namespace
DOMCI_DATA(CSSImportRule, css::ImportRule)
static bool
CloneRuleInto(css::Rule* aRule, void* aArray)
@@ -690,16 +719,27 @@ GroupRule::DeleteRule(PRUint32 aIndex)
return NS_ERROR_DOM_INDEX_SIZE_ERR;
NS_ASSERTION(PRUint32(mRules.Count()) <= PR_INT32_MAX,
"Too many style rules!");
return mSheet->DeleteRuleFromGroup(this, aIndex);
}
+/* virtual */ size_t
+GroupRule::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const
+{
+ return mRules.SizeOfExcludingThis(Rule::SizeOfCOMArrayElementIncludingThis,
+ aMallocSizeOf);
+
+ // Measurement of the following members may be added later if DMD finds it is
+ // worthwhile:
+ // - mRuleCollection
+}
+
// -------------------------------------------
// nsICSSMediaRule
//
MediaRule::MediaRule()
{
}
@@ -861,16 +901,29 @@ MediaRule::UseForPresentation(nsPresCont
nsMediaQueryResultCacheKey& aKey)
{
if (mMedia) {
return mMedia->Matches(aPresContext, &aKey);
}
return true;
}
+/* virtual */ size_t
+MediaRule::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
+{
+ size_t n = aMallocSizeOf(this);
+ n += GroupRule::SizeOfExcludingThis(aMallocSizeOf);
+
+ // Measurement of the following members may be added later if DMD finds it is
+ // worthwhile:
+ // - mMedia
+
+ return n;
+}
+
} // namespace css
} // namespace mozilla
// Must be outside namespace
DOMCI_DATA(CSSMediaRule, css::MediaRule)
namespace mozilla {
namespace css {
@@ -1070,16 +1123,29 @@ DocumentRule::UseForPresentation(nsPresC
return false;
}
DocumentRule::URL::~URL()
{
NS_CSS_DELETE_LIST_MEMBER(DocumentRule::URL, this, next);
}
+/* virtual */ size_t
+DocumentRule::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
+{
+ size_t n = aMallocSizeOf(this);
+ n += GroupRule::SizeOfExcludingThis(aMallocSizeOf);
+
+ // Measurement of the following members may be added later if DMD finds it is
+ // worthwhile:
+ // - mURLs
+
+ return n;
+}
+
} // namespace css
} // namespace mozilla
// Must be outside namespace
DOMCI_DATA(CSSMozDocumentRule, css::DocumentRule)
// -------------------------------------------
// NameSpaceRule
@@ -1194,16 +1260,28 @@ NameSpaceRule::GetParentStyleSheet(nsIDO
}
NS_IMETHODIMP
NameSpaceRule::GetParentRule(nsIDOMCSSRule** aParentRule)
{
return Rule::GetParentRule(aParentRule);
}
+/* virtual */ size_t
+NameSpaceRule::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
+{
+ return aMallocSizeOf(this);
+
+ // Measurement of the following members may be added later if DMD finds it is
+ // worthwhile:
+ // - mPrefix
+ // - mURLSpec
+}
+
+
} // namespace css
} // namespace mozilla
// Must be outside namespace
DOMCI_DATA(CSSNameSpaceRule, css::NameSpaceRule)
// -------------------------------------------
// nsCSSFontFaceStyleDecl and related routines
@@ -1655,16 +1733,27 @@ nsCSSFontFaceRule::GetDesc(nsCSSFontDesc
{
NS_PRECONDITION(aDescID > eCSSFontDesc_UNKNOWN &&
aDescID < eCSSFontDesc_COUNT,
"aDescID out of range in nsCSSFontFaceRule::GetDesc");
aValue = mDecl.*nsCSSFontFaceStyleDecl::Fields[aDescID];
}
+/* virtual */ size_t
+nsCSSFontFaceRule::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
+{
+ return aMallocSizeOf(this);
+
+ // Measurement of the following members may be added later if DMD finds it is
+ // worthwhile:
+ // - mDecl
+}
+
+
// -------------------------------------------
// nsCSSKeyframeStyleDeclaration
//
nsCSSKeyframeStyleDeclaration::nsCSSKeyframeStyleDeclaration(nsCSSKeyframeRule *aRule)
: mRule(aRule)
{
}
@@ -1877,16 +1966,29 @@ nsCSSKeyframeRule::ChangeDeclaration(css
{
mDeclaration = aDeclaration;
if (mSheet) {
mSheet->SetModifiedByChildRule();
}
}
+/* virtual */ size_t
+nsCSSKeyframeRule::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
+{
+ return aMallocSizeOf(this);
+
+ // Measurement of the following members may be added later if DMD finds it is
+ // worthwhile:
+ // - mKeys
+ // - mDeclaration
+ // - mDOMDeclaration
+}
+
+
// -------------------------------------------
// nsCSSKeyframesRule
//
nsCSSKeyframesRule::nsCSSKeyframesRule(const nsCSSKeyframesRule& aCopy)
// copy everything except our reference count. GroupRule's copy
// constructor also doesn't copy the lazily-constructed
// mRuleCollection.
@@ -2074,8 +2176,22 @@ nsCSSKeyframesRule::FindRule(const nsASt
/* virtual */ bool
nsCSSKeyframesRule::UseForPresentation(nsPresContext* aPresContext,
nsMediaQueryResultCacheKey& aKey)
{
NS_ABORT_IF_FALSE(false, "should not be called");
return false;
}
+/* virtual */ size_t
+nsCSSKeyframesRule::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
+{
+ size_t n = aMallocSizeOf(this);
+ n += GroupRule::SizeOfExcludingThis(aMallocSizeOf);
+
+ // Measurement of the following members may be added later if DMD finds it is
+ // worthwhile:
+ // - mName
+
+ return n;
+}
+
+
--- a/layout/style/nsCSSRules.h
+++ b/layout/style/nsCSSRules.h
@@ -106,16 +106,19 @@ public:
// rest of GroupRule
virtual bool UseForPresentation(nsPresContext* aPresContext,
nsMediaQueryResultCacheKey& aKey);
// @media rule methods
nsresult SetMedia(nsMediaList* aMedia);
+ virtual NS_MUST_OVERRIDE size_t
+ SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
+
protected:
nsRefPtr<nsMediaList> mMedia;
};
class DocumentRule MOZ_FINAL : public GroupRule,
public nsIDOMCSSMozDocumentRule
{
public:
@@ -169,16 +172,19 @@ public:
, next(aOther.next ? new URL(*aOther.next) : nsnull)
{
}
~URL();
};
void SetURLs(URL *aURLs) { mURLs = aURLs; }
+ virtual NS_MUST_OVERRIDE size_t
+ SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
+
protected:
nsAutoPtr<URL> mURLs; // linked list of |struct URL| above.
};
} // namespace css
} // namespace mozilla
// A nsCSSFontFaceStyleDecl is always embedded in a nsCSSFontFaceRule.
@@ -236,16 +242,18 @@ public:
NS_DECL_NSIDOMCSSRULE
// nsIDOMCSSFontFaceRule interface
NS_DECL_NSIDOMCSSFONTFACERULE
void SetDesc(nsCSSFontDesc aDescID, nsCSSValue const & aValue);
void GetDesc(nsCSSFontDesc aDescID, nsCSSValue & aValue);
+ virtual size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
+
protected:
friend class nsCSSFontFaceStyleDecl;
nsCSSFontFaceStyleDecl mDecl;
};
// nsFontFaceRuleContainer - used for associating sheet type with
// specific @font-face rules
struct nsFontFaceRuleContainer {
@@ -296,16 +304,18 @@ public:
// nsIDOMCSSRule interface
NS_DECL_NSIDOMCSSRULE
// nsIDOMCSSCharsetRule methods
NS_IMETHOD GetEncoding(nsAString& aEncoding);
NS_IMETHOD SetEncoding(const nsAString& aEncoding);
+ virtual size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
+
private:
nsString mEncoding;
};
} // namespace css
} // namespace mozilla
class nsCSSKeyframeRule;
@@ -373,16 +383,18 @@ public:
// nsIDOMMozCSSKeyframeRule interface
NS_DECL_NSIDOMMOZCSSKEYFRAMERULE
const nsTArray<float>& GetKeys() const { return mKeys; }
mozilla::css::Declaration* Declaration() { return mDeclaration; }
void ChangeDeclaration(mozilla::css::Declaration* aDeclaration);
+ virtual size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
+
private:
nsAutoTArray<float, 1> mKeys;
nsAutoPtr<mozilla::css::Declaration> mDeclaration;
// lazily created when needed:
nsRefPtr<nsCSSKeyframeStyleDeclaration> mDOMDeclaration;
};
class nsCSSKeyframesRule MOZ_FINAL : public mozilla::css::GroupRule,
@@ -419,15 +431,17 @@ public:
NS_DECL_NSIDOMMOZCSSKEYFRAMESRULE
// rest of GroupRule
virtual bool UseForPresentation(nsPresContext* aPresContext,
nsMediaQueryResultCacheKey& aKey);
const nsString& GetName() { return mName; }
+ virtual size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
+
private:
PRUint32 FindRuleIndexForKey(const nsAString& aKey);
nsString mName;
};
#endif /* !defined(nsCSSRules_h_) */
--- a/layout/style/nsCSSStyleSheet.cpp
+++ b/layout/style/nsCSSStyleSheet.cpp
@@ -869,16 +869,40 @@ nsCSSStyleSheet::RebuildChildList(css::R
}
(*builder->sheetSlot) = cssSheet;
builder->SetParentLinks(*builder->sheetSlot);
builder->sheetSlot = &(*builder->sheetSlot)->mNext;
return true;
}
+size_t
+nsCSSStyleSheet::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
+{
+ size_t n = 0;
+ const nsCSSStyleSheet* s = this;
+ while (s) {
+ n += aMallocSizeOf(s);
+ n += s->mInner->SizeOfIncludingThis(aMallocSizeOf);
+
+ // Measurement of the following members may be added later if DMD finds it is
+ // worthwhile:
+ // - s->mTitle
+ // - s->mMedia
+ // - s->mRuleCollection
+ // - s->mRuleProcessors
+ //
+ // The following members are not measured:
+ // - s->mOwnerRule, because it's non-owning
+
+ s = s->mNext;
+ }
+ return n;
+}
+
nsCSSStyleSheetInner::nsCSSStyleSheetInner(nsCSSStyleSheetInner& aCopy,
nsCSSStyleSheet* aPrimarySheet)
: mSheets(),
mSheetURI(aCopy.mSheetURI),
mOriginalSheetURI(aCopy.mOriginalSheetURI),
mBaseURI(aCopy.mBaseURI),
mPrincipal(aCopy.mPrincipal),
mComplete(aCopy.mComplete)
@@ -978,16 +1002,38 @@ nsCSSStyleSheetInner::CreateNamespaceMap
mNameSpaceMap = nsXMLNameSpaceMap::Create(false);
NS_ENSURE_TRUE(mNameSpaceMap, NS_ERROR_OUT_OF_MEMORY);
// Override the default namespace map behavior for the null prefix to
// return the wildcard namespace instead of the null namespace.
mNameSpaceMap->AddPrefix(nsnull, kNameSpaceID_Unknown);
return NS_OK;
}
+size_t
+nsCSSStyleSheetInner::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
+{
+ size_t n = aMallocSizeOf(this);
+ n += mOrderedRules.SizeOfExcludingThis(css::Rule::SizeOfCOMArrayElementIncludingThis,
+ aMallocSizeOf);
+ n += mFirstChild ? mFirstChild->SizeOfIncludingThis(aMallocSizeOf) : 0;
+
+ // Measurement of the following members may be added later if DMD finds it is
+ // worthwhile:
+ // - mSheetURI
+ // - mOriginalSheetURI
+ // - mBaseURI
+ // - mPrincipal
+ // - mNameSpaceMap
+ //
+ // The following members are not measured:
+ // - mSheets, because it's non-owning
+
+ return n;
+}
+
// -------------------------------
// CSS Style Sheet
//
nsCSSStyleSheet::nsCSSStyleSheet()
: mTitle(),
mParent(nsnull),
mOwnerRule(nsnull),
--- a/layout/style/nsCSSStyleSheet.h
+++ b/layout/style/nsCSSStyleSheet.h
@@ -94,16 +94,18 @@ private:
void AddSheet(nsCSSStyleSheet* aSheet);
void RemoveSheet(nsCSSStyleSheet* aSheet);
void RebuildNameSpaces();
// Create a new namespace map
nsresult CreateNamespaceMap();
+ size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
+
nsAutoTArray<nsCSSStyleSheet*, 8> mSheets;
nsCOMPtr<nsIURI> mSheetURI; // for error reports, etc.
nsCOMPtr<nsIURI> mOriginalSheetURI; // for GetHref. Can be null.
nsCOMPtr<nsIURI> mBaseURI; // for resolving relative URIs
nsCOMPtr<nsIPrincipal> mPrincipal;
nsCOMArray<mozilla::css::Rule> mOrderedRules;
nsAutoPtr<nsXMLNameSpaceMap> mNameSpaceMap;
// Linked list of child sheets. This is al fundamentally broken, because
@@ -261,16 +263,18 @@ public:
// nsIDOMCSSStyleSheet interface
NS_DECL_NSIDOMCSSSTYLESHEET
// Function used as a callback to rebuild our inner's child sheet
// list after we clone a unique inner for ourselves.
static bool RebuildChildList(mozilla::css::Rule* aRule, void* aBuilder);
+ size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
+
private:
nsCSSStyleSheet(const nsCSSStyleSheet& aCopy,
nsCSSStyleSheet* aParentToUse,
mozilla::css::ImportRule* aOwnerRuleToUse,
nsIDocument* aDocumentToUse,
nsIDOMNode* aOwningNodeToUse);
nsCSSStyleSheet(const nsCSSStyleSheet& aCopy) MOZ_DELETE;
--- a/layout/style/nsCSSValue.cpp
+++ b/layout/style/nsCSSValue.cpp
@@ -1109,16 +1109,151 @@ nsCSSValue::AppendToString(nsCSSProperty
case eCSSUnit_Hertz: aResult.AppendLiteral("Hz"); break;
case eCSSUnit_Kilohertz: aResult.AppendLiteral("kHz"); break;
case eCSSUnit_Seconds: aResult.Append(PRUnichar('s')); break;
case eCSSUnit_Milliseconds: aResult.AppendLiteral("ms"); break;
}
}
+size_t
+nsCSSValue::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const
+{
+ size_t n = 0;
+
+ switch (GetUnit()) {
+ // No value: nothing extra to measure.
+ case eCSSUnit_Null:
+ case eCSSUnit_Auto:
+ case eCSSUnit_Inherit:
+ case eCSSUnit_Initial:
+ case eCSSUnit_None:
+ case eCSSUnit_Normal:
+ case eCSSUnit_System_Font:
+ case eCSSUnit_All:
+ case eCSSUnit_Dummy:
+ case eCSSUnit_DummyInherit:
+ break;
+
+ // String
+ case eCSSUnit_String:
+ case eCSSUnit_Ident:
+ case eCSSUnit_Families:
+ case eCSSUnit_Attr:
+ case eCSSUnit_Local_Font:
+ case eCSSUnit_Font_Format:
+ case eCSSUnit_Element:
+ n += mValue.mString->SizeOfIncludingThisIfUnshared(aMallocSizeOf);
+ break;
+
+ // Array
+ case eCSSUnit_Array:
+ case eCSSUnit_Counter:
+ case eCSSUnit_Counters:
+ case eCSSUnit_Cubic_Bezier:
+ case eCSSUnit_Steps:
+ case eCSSUnit_Function:
+ case eCSSUnit_Calc:
+ case eCSSUnit_Calc_Plus:
+ case eCSSUnit_Calc_Minus:
+ case eCSSUnit_Calc_Times_L:
+ case eCSSUnit_Calc_Times_R:
+ case eCSSUnit_Calc_Divided:
+ break;
+
+ // URL
+ case eCSSUnit_URL:
+ n += mValue.mURL->SizeOfIncludingThis(aMallocSizeOf);
+ break;
+
+ // Image
+ case eCSSUnit_Image:
+ // Not yet measured. Measurement may be added later if DMD finds it
+ // worthwhile.
+ break;
+
+ // Gradient
+ case eCSSUnit_Gradient:
+ n += mValue.mGradient->SizeOfIncludingThis(aMallocSizeOf);
+ break;
+
+ // Pair
+ case eCSSUnit_Pair:
+ n += mValue.mPair->SizeOfIncludingThis(aMallocSizeOf);
+ break;
+
+ // Triplet
+ case eCSSUnit_Triplet:
+ n += mValue.mTriplet->SizeOfIncludingThis(aMallocSizeOf);
+ break;
+
+ // Rect
+ case eCSSUnit_Rect:
+ n += mValue.mRect->SizeOfIncludingThis(aMallocSizeOf);
+ break;
+
+ // List
+ case eCSSUnit_List:
+ n += mValue.mList->SizeOfIncludingThis(aMallocSizeOf);
+ break;
+
+ // ListDep: not measured because it's non-owning.
+ case eCSSUnit_ListDep:
+ break;
+
+ // PairList
+ case eCSSUnit_PairList:
+ n += mValue.mPairList->SizeOfIncludingThis(aMallocSizeOf);
+ break;
+
+ // PairListDep: not measured because it's non-owning.
+ case eCSSUnit_PairListDep:
+ break;
+
+ // Int: nothing extra to measure.
+ case eCSSUnit_Integer:
+ case eCSSUnit_Enumerated:
+ case eCSSUnit_EnumColor:
+ break;
+
+ // Color: nothing extra to measure.
+ case eCSSUnit_Color:
+ break;
+
+ // Float: nothing extra to measure.
+ case eCSSUnit_Percent:
+ case eCSSUnit_Number:
+ case eCSSUnit_PhysicalMillimeter:
+ case eCSSUnit_EM:
+ case eCSSUnit_XHeight:
+ case eCSSUnit_Char:
+ case eCSSUnit_RootEM:
+ case eCSSUnit_Point:
+ case eCSSUnit_Inch:
+ case eCSSUnit_Millimeter:
+ case eCSSUnit_Centimeter:
+ case eCSSUnit_Pica:
+ case eCSSUnit_Pixel:
+ case eCSSUnit_Degree:
+ case eCSSUnit_Grad:
+ case eCSSUnit_Radian:
+ case eCSSUnit_Hertz:
+ case eCSSUnit_Kilohertz:
+ case eCSSUnit_Seconds:
+ case eCSSUnit_Milliseconds:
+ break;
+
+ default:
+ NS_ABORT_IF_FALSE(false, "bad nsCSSUnit");
+ break;
+ }
+
+ return n;
+}
+
// --- nsCSSValueList -----------------
nsCSSValueList::~nsCSSValueList()
{
MOZ_COUNT_DTOR(nsCSSValueList);
NS_CSS_DELETE_LIST_MEMBER(nsCSSValueList, this, mNext);
}
@@ -1170,16 +1305,38 @@ nsCSSValueList::operator==(const nsCSSVa
const nsCSSValueList *p1 = this, *p2 = &aOther;
for ( ; p1 && p2; p1 = p1->mNext, p2 = p2->mNext) {
if (p1->mValue != p2->mValue)
return false;
}
return !p1 && !p2; // true if same length, false otherwise
}
+size_t
+nsCSSValueList::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
+{
+ size_t n = 0;
+ const nsCSSValueList* v = this;
+ while (v) {
+ n += aMallocSizeOf(v);
+ n += v->mValue.SizeOfExcludingThis(aMallocSizeOf);
+ v = v->mNext;
+ }
+ return n;
+}
+
+size_t
+nsCSSValueList_heap::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
+{
+ size_t n = aMallocSizeOf(this);
+ n += mValue.SizeOfExcludingThis(aMallocSizeOf);
+ n += mNext ? mNext->SizeOfIncludingThis(aMallocSizeOf) : 0;
+ return n;
+}
+
// --- nsCSSRect -----------------
nsCSSRect::nsCSSRect(void)
{
MOZ_COUNT_CTOR(nsCSSRect);
}
nsCSSRect::nsCSSRect(const nsCSSRect& aCopy)
@@ -1234,16 +1391,27 @@ nsCSSRect::AppendToString(nsCSSProperty
void nsCSSRect::SetAllSidesTo(const nsCSSValue& aValue)
{
mTop = aValue;
mRight = aValue;
mBottom = aValue;
mLeft = aValue;
}
+size_t
+nsCSSRect_heap::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
+{
+ size_t n = aMallocSizeOf(this);
+ n += mTop .SizeOfExcludingThis(aMallocSizeOf);
+ n += mRight .SizeOfExcludingThis(aMallocSizeOf);
+ n += mBottom.SizeOfExcludingThis(aMallocSizeOf);
+ n += mLeft .SizeOfExcludingThis(aMallocSizeOf);
+ return n;
+}
+
PR_STATIC_ASSERT(NS_SIDE_TOP == 0 && NS_SIDE_RIGHT == 1 &&
NS_SIDE_BOTTOM == 2 && NS_SIDE_LEFT == 3);
/* static */ const nsCSSRect::side_type nsCSSRect::sides[4] = {
&nsCSSRect::mTop,
&nsCSSRect::mRight,
&nsCSSRect::mBottom,
&nsCSSRect::mLeft,
@@ -1257,33 +1425,61 @@ nsCSSValuePair::AppendToString(nsCSSProp
{
mXValue.AppendToString(aProperty, aResult);
if (mYValue.GetUnit() != eCSSUnit_Null) {
aResult.Append(PRUnichar(' '));
mYValue.AppendToString(aProperty, aResult);
}
}
-// --- nsCSSValueTriple -----------------
+size_t
+nsCSSValuePair::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const
+{
+ size_t n = 0;
+ n += mXValue.SizeOfExcludingThis(aMallocSizeOf);
+ n += mYValue.SizeOfExcludingThis(aMallocSizeOf);
+ return n;
+}
+
+size_t
+nsCSSValuePair_heap::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
+{
+ size_t n = aMallocSizeOf(this);
+ n += mXValue.SizeOfExcludingThis(aMallocSizeOf);
+ n += mYValue.SizeOfExcludingThis(aMallocSizeOf);
+ return n;
+}
+
+// --- nsCSSValueTriplet -----------------
void
nsCSSValueTriplet::AppendToString(nsCSSProperty aProperty,
nsAString& aResult) const
{
mXValue.AppendToString(aProperty, aResult);
if (mYValue.GetUnit() != eCSSUnit_Null) {
aResult.Append(PRUnichar(' '));
mYValue.AppendToString(aProperty, aResult);
if (mZValue.GetUnit() != eCSSUnit_Null) {
aResult.Append(PRUnichar(' '));
mZValue.AppendToString(aProperty, aResult);
}
}
}
+size_t
+nsCSSValueTriplet_heap::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
+{
+ size_t n = aMallocSizeOf(this);
+ n += mXValue.SizeOfExcludingThis(aMallocSizeOf);
+ n += mYValue.SizeOfExcludingThis(aMallocSizeOf);
+ n += mZValue.SizeOfExcludingThis(aMallocSizeOf);
+ return n;
+}
+
// --- nsCSSValuePairList -----------------
nsCSSValuePairList::~nsCSSValuePairList()
{
MOZ_COUNT_DTOR(nsCSSValuePairList);
NS_CSS_DELETE_LIST_MEMBER(nsCSSValuePairList, this, mNext);
}
@@ -1337,16 +1533,50 @@ nsCSSValuePairList::operator==(const nsC
for ( ; p1 && p2; p1 = p1->mNext, p2 = p2->mNext) {
if (p1->mXValue != p2->mXValue ||
p1->mYValue != p2->mYValue)
return false;
}
return !p1 && !p2; // true if same length, false otherwise
}
+size_t
+nsCSSValuePairList::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
+{
+ size_t n = 0;
+ const nsCSSValuePairList* v = this;
+ while (v) {
+ n += aMallocSizeOf(v);
+ n += v->mXValue.SizeOfExcludingThis(aMallocSizeOf);
+ n += v->mYValue.SizeOfExcludingThis(aMallocSizeOf);
+ v = v->mNext;
+ }
+ return n;
+}
+
+size_t
+nsCSSValuePairList_heap::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
+{
+ size_t n = aMallocSizeOf(this);
+ n += mXValue.SizeOfExcludingThis(aMallocSizeOf);
+ n += mYValue.SizeOfExcludingThis(aMallocSizeOf);
+ n += mNext ? mNext->SizeOfIncludingThis(aMallocSizeOf) : 0;
+ return n;
+}
+
+size_t
+nsCSSValue::Array::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
+{
+ size_t n = aMallocSizeOf(this);
+ for (size_t i = 0; i < mCount; i++) {
+ n += mArray[i].SizeOfExcludingThis(aMallocSizeOf);
+ }
+ return n;
+}
+
nsCSSValue::URL::URL(nsIURI* aURI, nsStringBuffer* aString,
nsIURI* aReferrer, nsIPrincipal* aOriginPrincipal)
: mURI(aURI),
mString(aString),
mReferrer(aReferrer),
mOriginPrincipal(aOriginPrincipal),
mURIResolved(true)
{
@@ -1413,16 +1643,34 @@ nsCSSValue::URL::GetURI() const
NS_NewURI(getter_AddRefs(newURI),
NS_ConvertUTF16toUTF8(GetBufferValue(mString)), nsnull, mURI);
newURI.swap(mURI);
}
return mURI;
}
+size_t
+nsCSSValue::URL::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
+{
+ size_t n = aMallocSizeOf(this);
+
+ // This string is unshared.
+ n += mString->SizeOfIncludingThisMustBeUnshared(aMallocSizeOf);
+
+ // Measurement of the following members may be added later if DMD finds it is
+ // worthwhile:
+ // - mURI
+ // - mReferrer
+ // - mOriginPrincipal
+
+ return n;
+}
+
+
nsCSSValue::Image::Image(nsIURI* aURI, nsStringBuffer* aString,
nsIURI* aReferrer, nsIPrincipal* aOriginPrincipal,
nsIDocument* aDocument)
: URL(aURI, aString, aReferrer, aOriginPrincipal)
{
if (aDocument->GetOriginalDocument()) {
aDocument = aDocument->GetOriginalDocument();
}
@@ -1453,28 +1701,52 @@ nsCSSValueGradientStop::nsCSSValueGradie
MOZ_COUNT_CTOR(nsCSSValueGradientStop);
}
nsCSSValueGradientStop::~nsCSSValueGradientStop()
{
MOZ_COUNT_DTOR(nsCSSValueGradientStop);
}
+size_t
+nsCSSValueGradientStop::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const
+{
+ size_t n = 0;
+ n += mLocation.SizeOfExcludingThis(aMallocSizeOf);
+ n += mColor .SizeOfExcludingThis(aMallocSizeOf);
+ return n;
+}
+
nsCSSValueGradient::nsCSSValueGradient(bool aIsRadial,
bool aIsRepeating)
: mIsRadial(aIsRadial),
mIsRepeating(aIsRepeating),
mIsToCorner(false),
mBgPos(eCSSUnit_None),
mAngle(eCSSUnit_None),
mRadialShape(eCSSUnit_None),
mRadialSize(eCSSUnit_None)
{
}
+size_t
+nsCSSValueGradient::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
+{
+ size_t n = aMallocSizeOf(this);
+ n += mBgPos .SizeOfExcludingThis(aMallocSizeOf);
+ n += mAngle .SizeOfExcludingThis(aMallocSizeOf);
+ n += mRadialShape.SizeOfExcludingThis(aMallocSizeOf);
+ n += mRadialSize .SizeOfExcludingThis(aMallocSizeOf);
+ n += mStops .SizeOfExcludingThis(aMallocSizeOf);
+ for (PRUint32 i = 0; i < mStops.Length(); i++) {
+ n += mStops[i].SizeOfExcludingThis(aMallocSizeOf);
+ }
+ return n;
+}
+
// --- nsCSSCornerSizes -----------------
nsCSSCornerSizes::nsCSSCornerSizes(void)
{
MOZ_COUNT_CTOR(nsCSSCornerSizes);
}
nsCSSCornerSizes::nsCSSCornerSizes(const nsCSSCornerSizes& aCopy)
--- a/layout/style/nsCSSValue.h
+++ b/layout/style/nsCSSValue.h
@@ -449,16 +449,18 @@ public:
// Checks if this is a function value with the specified function id.
bool EqualsFunction(nsCSSKeyword aFunctionId) const;
// Returns an already addrefed buffer. Can return null on allocation
// failure.
static already_AddRefed<nsStringBuffer>
BufferFromString(const nsString& aValue);
+ size_t SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
+
struct URL {
// Methods are not inline because using an nsIPrincipal means requiring
// caps, which leads to REQUIRES hell, since this header is included all
// over.
// For both constructors aString must not be null.
// For both constructors aOriginPrincipal must not be null.
// Construct with a base URI; this will create the actual URI lazily from
@@ -476,16 +478,18 @@ public:
// URIEquals only compares URIs and principals (unlike operator==, which
// also compares the original strings). URIEquals also assumes that the
// mURI member of both URL objects is non-null. Do NOT call this method
// unless you're sure this is the case.
bool URIEquals(const URL& aOther) const;
nsIURI* GetURI() const;
+ size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
+
private:
// If mURIResolved is false, mURI stores the base URI.
// If mURIResolved is true, mURI stores the URI we resolve to; this may be
// null if the URI is invalid.
mutable nsCOMPtr<nsIURI> mURI;
public:
nsStringBuffer* mString; // Could use nsRefPtr, but it'd add useless
// null-checks; this is never null.
@@ -539,17 +543,17 @@ protected:
nsCSSValueGradient* mGradient;
nsCSSValuePair_heap* mPair;
nsCSSRect_heap* mRect;
nsCSSValueTriplet_heap* mTriplet;
nsCSSValueList_heap* mList;
nsCSSValueList* mListDependent;
nsCSSValuePairList_heap* mPairList;
nsCSSValuePairList* mPairListDependent;
- } mValue;
+ } mValue;
};
struct nsCSSValue::Array {
// return |Array| with reference count of zero
static Array* Create(size_t aItemCount) {
return new (aItemCount) Array(aItemCount);
}
@@ -637,16 +641,18 @@ private:
~Array()
{
MOZ_COUNT_DTOR(nsCSSValue::Array);
CSSVALUE_LIST_FOR_EXTRA_VALUES(val) {
val->~nsCSSValue();
}
}
+ size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
+
#undef CSSVALUE_LIST_FOR_EXTRA_VALUES
private:
Array(const Array& aOther) MOZ_DELETE;
Array& operator=(const Array& aOther) MOZ_DELETE;
};
// Prefer nsCSSValue::Array for lists of fixed size.
@@ -657,32 +663,36 @@ struct nsCSSValueList {
nsCSSValueList* Clone() const; // makes a deep copy
void CloneInto(nsCSSValueList* aList) const; // makes a deep copy into aList
void AppendToString(nsCSSProperty aProperty, nsAString& aResult) const;
bool operator==(nsCSSValueList const& aOther) const;
bool operator!=(const nsCSSValueList& aOther) const
{ return !(*this == aOther); }
+ size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
+
nsCSSValue mValue;
nsCSSValueList* mNext;
private:
nsCSSValueList(const nsCSSValueList& aCopy) // makes a shallow copy
: mValue(aCopy.mValue), mNext(nsnull)
{
MOZ_COUNT_CTOR(nsCSSValueList);
}
};
// nsCSSValueList_heap differs from nsCSSValueList only in being
// refcounted. It should not be necessary to use this class directly;
// it's an implementation detail of nsCSSValue.
struct nsCSSValueList_heap : public nsCSSValueList {
NS_INLINE_DECL_REFCOUNTING(nsCSSValueList_heap)
+
+ size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
};
// This has to be here so that the relationship between nsCSSValueList
// and nsCSSValueList_heap is visible.
inline nsCSSValueList*
nsCSSValue::GetListValue()
{
if (mUnit == eCSSUnit_List)
@@ -751,16 +761,18 @@ struct nsCSSRect {
static const side_type sides[4];
};
// nsCSSRect_heap differs from nsCSSRect only in being
// refcounted. It should not be necessary to use this class directly;
// it's an implementation detail of nsCSSValue.
struct nsCSSRect_heap : public nsCSSRect {
NS_INLINE_DECL_REFCOUNTING(nsCSSRect_heap)
+
+ size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
};
// This has to be here so that the relationship between nsCSSRect
// and nsCSSRect_heap is visible.
inline nsCSSRect&
nsCSSValue::GetRectValue()
{
NS_ABORT_IF_FALSE(mUnit == eCSSUnit_Rect, "not a rect value");
@@ -821,30 +833,34 @@ struct nsCSSValuePair {
bool HasValue() const {
return mXValue.GetUnit() != eCSSUnit_Null ||
mYValue.GetUnit() != eCSSUnit_Null;
}
void AppendToString(nsCSSProperty aProperty, nsAString& aResult) const;
+ size_t SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
+
nsCSSValue mXValue;
nsCSSValue mYValue;
};
// nsCSSValuePair_heap differs from nsCSSValuePair only in being
// refcounted. It should not be necessary to use this class directly;
// it's an implementation detail of nsCSSValue.
struct nsCSSValuePair_heap : public nsCSSValuePair {
- // forward constructor
- nsCSSValuePair_heap(const nsCSSValue& aXValue, const nsCSSValue& aYValue)
- : nsCSSValuePair(aXValue, aYValue)
- {}
+ // forward constructor
+ nsCSSValuePair_heap(const nsCSSValue& aXValue, const nsCSSValue& aYValue)
+ : nsCSSValuePair(aXValue, aYValue)
+ {}
- NS_INLINE_DECL_REFCOUNTING(nsCSSValuePair_heap)
+ NS_INLINE_DECL_REFCOUNTING(nsCSSValuePair_heap)
+
+ size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
};
struct nsCSSValueTriplet {
nsCSSValueTriplet()
{
MOZ_COUNT_CTOR(nsCSSValueTriplet);
}
nsCSSValueTriplet(nsCSSUnit aUnit)
@@ -911,16 +927,18 @@ struct nsCSSValueTriplet {
// it's an implementation detail of nsCSSValue.
struct nsCSSValueTriplet_heap : public nsCSSValueTriplet {
// forward constructor
nsCSSValueTriplet_heap(const nsCSSValue& aXValue, const nsCSSValue& aYValue, const nsCSSValue& aZValue)
: nsCSSValueTriplet(aXValue, aYValue, aZValue)
{}
NS_INLINE_DECL_REFCOUNTING(nsCSSValueTriplet_heap)
+
+ size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
};
// This has to be here so that the relationship between nsCSSValuePair
// and nsCSSValuePair_heap is visible.
inline nsCSSValuePair&
nsCSSValue::GetPairValue()
{
NS_ABORT_IF_FALSE(mUnit == eCSSUnit_Pair, "not a pair value");
@@ -955,16 +973,18 @@ struct nsCSSValuePairList {
nsCSSValuePairList* Clone() const; // makes a deep copy
void AppendToString(nsCSSProperty aProperty, nsAString& aResult) const;
bool operator==(const nsCSSValuePairList& aOther) const;
bool operator!=(const nsCSSValuePairList& aOther) const
{ return !(*this == aOther); }
+ size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
+
nsCSSValue mXValue;
nsCSSValue mYValue;
nsCSSValuePairList* mNext;
private:
nsCSSValuePairList(const nsCSSValuePairList& aCopy) // makes a shallow copy
: mXValue(aCopy.mXValue), mYValue(aCopy.mYValue), mNext(nsnull)
{
@@ -972,16 +992,18 @@ private:
}
};
// nsCSSValuePairList_heap differs from nsCSSValuePairList only in being
// refcounted. It should not be necessary to use this class directly;
// it's an implementation detail of nsCSSValue.
struct nsCSSValuePairList_heap : public nsCSSValuePairList {
NS_INLINE_DECL_REFCOUNTING(nsCSSValuePairList_heap)
+
+ size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
};
// This has to be here so that the relationship between nsCSSValuePairList
// and nsCSSValuePairList_heap is visible.
inline nsCSSValuePairList*
nsCSSValue::GetPairListValue()
{
if (mUnit == eCSSUnit_PairList)
@@ -1019,16 +1041,18 @@ public:
return (mLocation == aOther.mLocation &&
mColor == aOther.mColor);
}
bool operator!=(const nsCSSValueGradientStop& aOther) const
{
return !(*this == aOther);
}
+
+ size_t SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
};
struct nsCSSValueGradient {
nsCSSValueGradient(bool aIsRadial, bool aIsRepeating);
// true if gradient is radial, false if it is linear
bool mIsRadial;
bool mIsRepeating;
@@ -1067,16 +1091,18 @@ struct nsCSSValueGradient {
bool operator!=(const nsCSSValueGradient& aOther) const
{
return !(*this == aOther);
}
NS_INLINE_DECL_REFCOUNTING(nsCSSValueGradient)
+ size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
+
private:
nsCSSValueGradient(const nsCSSValueGradient& aOther) MOZ_DELETE;
nsCSSValueGradient& operator=(const nsCSSValueGradient& aOther) MOZ_DELETE;
};
struct nsCSSCornerSizes {
nsCSSCornerSizes(void);
nsCSSCornerSizes(const nsCSSCornerSizes& aCopy);
--- a/layout/style/nsIStyleSheet.h
+++ b/layout/style/nsIStyleSheet.h
@@ -104,13 +104,15 @@ public:
// style sheet owner info
virtual nsIStyleSheet* GetParentSheet() const = 0; // may be null
virtual nsIDocument* GetOwningDocument() const = 0; // may be null
virtual void SetOwningDocument(nsIDocument* aDocument) = 0;
#ifdef DEBUG
virtual void List(FILE* out = stdout, PRInt32 aIndent = 0) const = 0;
#endif
+
+ virtual size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIStyleSheet, NS_ISTYLE_SHEET_IID)
#endif /* nsIStyleSheet_h___ */
--- a/layout/style/nsLayoutStylesheetCache.cpp
+++ b/layout/style/nsLayoutStylesheetCache.cpp
@@ -36,22 +36,40 @@
* ***** END LICENSE BLOCK ***** */
#include "nsLayoutStylesheetCache.h"
#include "nsAppDirectoryServiceDefs.h"
#include "mozilla/css/Loader.h"
#include "nsIFile.h"
#include "nsLayoutCID.h"
+#include "nsIMemoryReporter.h"
#include "nsNetUtil.h"
#include "nsIObserverService.h"
#include "nsServiceManagerUtils.h"
#include "nsIXULRuntime.h"
#include "nsCSSStyleSheet.h"
+NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(LayoutStyleSheetCacheMallocSizeOf,
+ "layout/style-sheet-cache")
+
+static PRInt64
+GetStylesheetCacheSize()
+{
+ return nsLayoutStylesheetCache::SizeOfIncludingThis(
+ LayoutStyleSheetCacheMallocSizeOf);
+}
+
+NS_MEMORY_REPORTER_IMPLEMENT(Sheets,
+ "explicit/layout/style-sheet-cache",
+ KIND_HEAP,
+ nsIMemoryReporter::UNITS_BYTES,
+ GetStylesheetCacheSize,
+ "Memory used for some built-in style sheets.")
+
NS_IMPL_ISUPPORTS1(nsLayoutStylesheetCache, nsIObserver)
nsresult
nsLayoutStylesheetCache::Observe(nsISupports* aSubject,
const char* aTopic,
const PRUnichar* aData)
{
if (!strcmp(aTopic, "profile-before-change")) {
@@ -167,16 +185,48 @@ nsLayoutStylesheetCache::FullScreenOverr
void
nsLayoutStylesheetCache::Shutdown()
{
NS_IF_RELEASE(gCSSLoader);
NS_IF_RELEASE(gStyleCache);
}
+size_t
+nsLayoutStylesheetCache::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf)
+{
+ if (nsLayoutStylesheetCache::gStyleCache) {
+ return nsLayoutStylesheetCache::gStyleCache->
+ SizeOfIncludingThisHelper(aMallocSizeOf);
+ }
+ return 0;
+}
+
+size_t
+nsLayoutStylesheetCache::SizeOfIncludingThisHelper(nsMallocSizeOfFun aMallocSizeOf) const
+{
+ size_t n = aMallocSizeOf(this);
+
+ #define MEASURE(s) n += s ? s->SizeOfIncludingThis(aMallocSizeOf) : 0;
+
+ MEASURE(mScrollbarsSheet);
+ MEASURE(mFormsSheet);
+ MEASURE(mUserContentSheet);
+ MEASURE(mUserChromeSheet);
+ MEASURE(mUASheet);
+ MEASURE(mQuirkSheet);
+ MEASURE(mFullScreenOverrideSheet);
+
+ // Measurement of the following members may be added later if DMD finds it is
+ // worthwhile:
+ // - gCSSLoader
+
+ return n;
+}
+
nsLayoutStylesheetCache::nsLayoutStylesheetCache()
{
nsCOMPtr<nsIObserverService> obsSvc =
mozilla::services::GetObserverService();
NS_ASSERTION(obsSvc, "No global observer service?");
if (obsSvc) {
obsSvc->AddObserver(this, "profile-before-change", false);
@@ -203,16 +253,24 @@ nsLayoutStylesheetCache::nsLayoutStylesh
NS_ASSERTION(mQuirkSheet, "Could not load quirk.css");
NS_NewURI(getter_AddRefs(uri), "resource://gre-resources/full-screen-override.css");
if (uri) {
LoadSheet(uri, mFullScreenOverrideSheet, true);
}
NS_ASSERTION(mFullScreenOverrideSheet, "Could not load full-screen-override.css");
+ mSheetsReporter = new NS_MEMORY_REPORTER_NAME(Sheets);
+ (void)::NS_RegisterMemoryReporter(mSheetsReporter);
+}
+
+nsLayoutStylesheetCache::~nsLayoutStylesheetCache()
+{
+ (void)::NS_UnregisterMemoryReporter(mSheetsReporter);
+ mSheetsReporter = nsnull;
}
void
nsLayoutStylesheetCache::EnsureGlobal()
{
if (gStyleCache) return;
gStyleCache = new nsLayoutStylesheetCache();
--- a/layout/style/nsLayoutStylesheetCache.h
+++ b/layout/style/nsLayoutStylesheetCache.h
@@ -47,46 +47,54 @@ class nsCSSStyleSheet;
class nsIURI;
namespace mozilla {
namespace css {
class Loader;
}
}
+class nsIMemoryReporter;
+
class nsLayoutStylesheetCache
: public nsIObserver
{
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
static nsCSSStyleSheet* ScrollbarsSheet();
static nsCSSStyleSheet* FormsSheet();
static nsCSSStyleSheet* UserContentSheet();
static nsCSSStyleSheet* UserChromeSheet();
static nsCSSStyleSheet* UASheet();
static nsCSSStyleSheet* QuirkSheet();
static nsCSSStyleSheet* FullScreenOverrideSheet();
static void Shutdown();
+ static size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf);
+
private:
nsLayoutStylesheetCache();
- ~nsLayoutStylesheetCache() {}
+ ~nsLayoutStylesheetCache();
static void EnsureGlobal();
void InitFromProfile();
static void LoadSheetFile(nsIFile* aFile, nsRefPtr<nsCSSStyleSheet> &aSheet);
static void LoadSheet(nsIURI* aURI, nsRefPtr<nsCSSStyleSheet> &aSheet,
bool aEnableUnsafeRules);
+ size_t SizeOfIncludingThisHelper(nsMallocSizeOfFun aMallocSizeOf) const;
+
static nsLayoutStylesheetCache* gStyleCache;
static mozilla::css::Loader* gCSSLoader;
nsRefPtr<nsCSSStyleSheet> mScrollbarsSheet;
nsRefPtr<nsCSSStyleSheet> mFormsSheet;
nsRefPtr<nsCSSStyleSheet> mUserContentSheet;
nsRefPtr<nsCSSStyleSheet> mUserChromeSheet;
nsRefPtr<nsCSSStyleSheet> mUASheet;
nsRefPtr<nsCSSStyleSheet> mQuirkSheet;
nsRefPtr<nsCSSStyleSheet> mFullScreenOverrideSheet;
+
+ nsIMemoryReporter* mSheetsReporter;
};
#endif
--- a/xpcom/base/nsIMemoryReporter.idl
+++ b/xpcom/base/nsIMemoryReporter.idl
@@ -351,29 +351,29 @@ namespace mozilla {
* You might be wondering why we have a macro that creates multiple functions
* distinguished only by |name|, instead of a single MemoryReporterMallocSizeOf
* function. It's mostly to help with DMD integration, though it sometimes
* also helps with debugging and temporary ad hoc profiling. The |name| chosen
* doesn't matter greatly, but it's best to make it similar to the path used by
* the relevant memory reporter(s).
*/
#define NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(fn, name) \
- size_t fn(const void *ptr) \
+ static size_t fn(const void *ptr) \
{ \
size_t usable = moz_malloc_size_of(ptr); \
VALGRIND_DMD_REPORT(ptr, usable, name); \
return usable; \
}
/*
* Like NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN, but the created function sends an
* "unreport" message to DMD.
*/
#define NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN_UN(fn) \
- size_t fn(const void *ptr) \
+ static size_t fn(const void *ptr) \
{ \
size_t usable = moz_malloc_size_of(ptr); \
VALGRIND_DMD_UNREPORT(ptr); \
return usable; \
}
#ifdef MOZ_DMD