Bug 1127198 - Part 1: Add a DEBUG-only count of frames that use a style context. r=dbaron a=abillings
--- a/layout/forms/nsButtonFrameRenderer.cpp
+++ b/layout/forms/nsButtonFrameRenderer.cpp
@@ -22,16 +22,25 @@
nsButtonFrameRenderer::nsButtonFrameRenderer()
{
MOZ_COUNT_CTOR(nsButtonFrameRenderer);
}
nsButtonFrameRenderer::~nsButtonFrameRenderer()
{
MOZ_COUNT_DTOR(nsButtonFrameRenderer);
+
+#ifdef DEBUG
+ if (mInnerFocusStyle) {
+ mInnerFocusStyle->FrameRelease();
+ }
+ if (mOuterFocusStyle) {
+ mOuterFocusStyle->FrameRelease();
+ }
+#endif
}
void
nsButtonFrameRenderer::SetFrame(nsFrame* aFrame, nsPresContext* aPresContext)
{
mFrame = aFrame;
ReResolveStyles(aPresContext);
}
@@ -363,27 +372,45 @@ nsButtonFrameRenderer::GetAddedButtonBor
*/
void
nsButtonFrameRenderer::ReResolveStyles(nsPresContext* aPresContext)
{
// get all the styles
nsStyleContext* context = mFrame->StyleContext();
nsStyleSet *styleSet = aPresContext->StyleSet();
+#ifdef DEBUG
+ if (mInnerFocusStyle) {
+ mInnerFocusStyle->FrameRelease();
+ }
+ if (mOuterFocusStyle) {
+ mOuterFocusStyle->FrameRelease();
+ }
+#endif
+
// style for the inner such as a dotted line (Windows)
mInnerFocusStyle =
styleSet->ProbePseudoElementStyle(mFrame->GetContent()->AsElement(),
nsCSSPseudoElements::ePseudo_mozFocusInner,
context);
// style for outer focus like a ridged border (MAC).
mOuterFocusStyle =
styleSet->ProbePseudoElementStyle(mFrame->GetContent()->AsElement(),
nsCSSPseudoElements::ePseudo_mozFocusOuter,
context);
+
+#ifdef DEBUG
+ if (mInnerFocusStyle) {
+ mInnerFocusStyle->FrameAddRef();
+ }
+ if (mOuterFocusStyle) {
+ mOuterFocusStyle->FrameAddRef();
+ }
+#endif
}
nsStyleContext*
nsButtonFrameRenderer::GetStyleContext(int32_t aIndex) const
{
switch (aIndex) {
case NS_BUTTON_RENDERER_FOCUS_INNER_CONTEXT_INDEX:
return mInnerFocusStyle;
@@ -394,15 +421,28 @@ nsButtonFrameRenderer::GetStyleContext(i
}
}
void
nsButtonFrameRenderer::SetStyleContext(int32_t aIndex, nsStyleContext* aStyleContext)
{
switch (aIndex) {
case NS_BUTTON_RENDERER_FOCUS_INNER_CONTEXT_INDEX:
+#ifdef DEBUG
+ if (mInnerFocusStyle) {
+ mInnerFocusStyle->FrameRelease();
+ }
+#endif
mInnerFocusStyle = aStyleContext;
break;
case NS_BUTTON_RENDERER_FOCUS_OUTER_CONTEXT_INDEX:
+#ifdef DEBUG
+ if (mOuterFocusStyle) {
+ mOuterFocusStyle->FrameRelease();
+ }
+#endif
mOuterFocusStyle = aStyleContext;
break;
}
+#ifdef DEBUG
+ aStyleContext->FrameAddRef();
+#endif
}
--- a/layout/forms/nsRangeFrame.cpp
+++ b/layout/forms/nsRangeFrame.cpp
@@ -43,16 +43,21 @@ NS_NewRangeFrame(nsIPresShell* aPresShel
nsRangeFrame::nsRangeFrame(nsStyleContext* aContext)
: nsContainerFrame(aContext)
{
}
nsRangeFrame::~nsRangeFrame()
{
+#ifdef DEBUG
+ if (mOuterFocusStyle) {
+ mOuterFocusStyle->FrameRelease();
+ }
+#endif
}
NS_IMPL_FRAMEARENA_HELPERS(nsRangeFrame)
NS_QUERYFRAME_HEAD(nsRangeFrame)
NS_QUERYFRAME_ENTRY(nsRangeFrame)
NS_QUERYFRAME_ENTRY(nsIAnonymousContentCreator)
NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)
@@ -881,11 +886,23 @@ nsRangeFrame::GetAdditionalStyleContext(
void
nsRangeFrame::SetAdditionalStyleContext(int32_t aIndex,
nsStyleContext* aStyleContext)
{
MOZ_ASSERT(aIndex == 0,
"GetAdditionalStyleContext is handling other indexes?");
+#ifdef DEBUG
+ if (mOuterFocusStyle) {
+ mOuterFocusStyle->FrameRelease();
+ }
+#endif
+
// The -moz-focus-outer pseudo-element's style has changed.
mOuterFocusStyle = aStyleContext;
+
+#ifdef DEBUG
+ if (mOuterFocusStyle) {
+ mOuterFocusStyle->FrameAddRef();
+ }
+#endif
}
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -410,23 +410,29 @@ NS_NewEmptyFrame(nsIPresShell* aPresShel
nsFrame::nsFrame(nsStyleContext* aContext)
{
MOZ_COUNT_CTOR(nsFrame);
mState = NS_FRAME_FIRST_REFLOW | NS_FRAME_IS_DIRTY;
mStyleContext = aContext;
mStyleContext->AddRef();
+#ifdef DEBUG
+ mStyleContext->FrameAddRef();
+#endif
}
nsFrame::~nsFrame()
{
MOZ_COUNT_DTOR(nsFrame);
NS_IF_RELEASE(mContent);
+#ifdef DEBUG
+ mStyleContext->FrameRelease();
+#endif
mStyleContext->Release();
}
NS_IMPL_FRAMEARENA_HELPERS(nsFrame)
// Dummy operator delete. Will never be called, but must be defined
// to satisfy some C++ ABIs.
void
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -520,33 +520,45 @@ public:
*/
nsStyleContext* StyleContext() const { return mStyleContext; }
void SetStyleContext(nsStyleContext* aContext)
{
if (aContext != mStyleContext) {
nsStyleContext* oldStyleContext = mStyleContext;
mStyleContext = aContext;
aContext->AddRef();
+#ifdef DEBUG
+ aContext->FrameAddRef();
+#endif
DidSetStyleContext(oldStyleContext);
+#ifdef DEBUG
+ oldStyleContext->FrameRelease();
+#endif
oldStyleContext->Release();
}
}
/**
* SetStyleContextWithoutNotification is for changes to the style
* context that should suppress style change processing, in other
* words, those that aren't really changes. This generally means only
* changes that happen during frame construction.
*/
void SetStyleContextWithoutNotification(nsStyleContext* aContext)
{
if (aContext != mStyleContext) {
+#ifdef DEBUG
+ mStyleContext->FrameRelease();
+#endif
mStyleContext->Release();
mStyleContext = aContext;
aContext->AddRef();
+#ifdef DEBUG
+ aContext->FrameAddRef();
+#endif
}
}
// Style post processing hook
// Attention: the old style context is the one we're forgetting,
// and hence possibly completely bogus for GetStyle* purposes.
// Use PeekStyleData instead.
virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext) = 0;
--- a/layout/style/nsStyleContext.cpp
+++ b/layout/style/nsStyleContext.cpp
@@ -41,16 +41,19 @@ nsStyleContext::nsStyleContext(nsStyleCo
: mParent(aParent),
mChild(nullptr),
mEmptyChild(nullptr),
mPseudoTag(aPseudoTag),
mRuleNode(aRuleNode),
mCachedResetData(nullptr),
mBits(((uint64_t)aPseudoType) << NS_STYLE_CONTEXT_TYPE_SHIFT),
mRefCnt(0)
+#ifdef DEBUG
+ , mFrameRefCnt(0)
+#endif
{
// This check has to be done "backward", because if it were written the
// more natural way it wouldn't fail even when it needed to.
static_assert((UINT64_MAX >> NS_STYLE_CONTEXT_TYPE_SHIFT) >=
nsCSSPseudoElements::ePseudo_MAX,
"pseudo element bits no longer fit in a uint64_t");
MOZ_ASSERT(aRuleNode);
--- a/layout/style/nsStyleContext.h
+++ b/layout/style/nsStyleContext.h
@@ -91,16 +91,30 @@ public:
NS_LOG_RELEASE(this, mRefCnt, "nsStyleContext");
if (mRefCnt == 0) {
Destroy();
return 0;
}
return mRefCnt;
}
+#ifdef DEBUG
+ void FrameAddRef() {
+ ++mFrameRefCnt;
+ }
+
+ void FrameRelease() {
+ --mFrameRefCnt;
+ }
+
+ uint32_t FrameRefCnt() const {
+ return mFrameRefCnt;
+ }
+#endif
+
bool HasSingleReference() const {
NS_ASSERTION(mRefCnt != 0,
"do not call HasSingleReference on a newly created "
"nsStyleContext with no references yet");
return mRefCnt == 1;
}
nsPresContext* PresContext() const { return mRuleNode->PresContext(); }
@@ -512,16 +526,21 @@ private:
// Since style contexts typically have some inherited data but only sometimes
// have reset data, we always allocate the mCachedInheritedData, but only
// sometimes allocate the mCachedResetData.
nsResetStyleData* mCachedResetData; // Cached reset style data.
nsInheritedStyleData mCachedInheritedData; // Cached inherited style data
uint64_t mBits; // Which structs are inherited from the
// parent context or owned by mRuleNode.
uint32_t mRefCnt;
+
+#ifdef DEBUG
+ uint32_t mFrameRefCnt; // number of frames that use this
+ // as their style context
+#endif
};
already_AddRefed<nsStyleContext>
NS_NewStyleContext(nsStyleContext* aParentContext,
nsIAtom* aPseudoTag,
nsCSSPseudoElements::Type aPseudoType,
nsRuleNode* aRuleNode,
bool aSkipParentDisplayBasedStyleFixup);