Bug 1127198 - Part 1: Add a DEBUG-only count of frames that use a style context. r=dbaron a=abillings
authorCameron McCormack <cam@mcc.id.au>
Wed, 18 Feb 2015 09:29:05 +1100
changeset 244776 883c0f7c2a3835e2d3693643fcd3938ea5fa47a9
parent 244775 12be2975c7a49282acc43ff100aabcb74dd493fa
child 244777 f3372cc7e7678ed832be849056cf6d51c4a1af2b
push id734
push usermartin.thomson@gmail.com
push dateThu, 19 Feb 2015 22:06:18 +0000
reviewersdbaron, abillings
bugs1127198
milestone37.0a2
Bug 1127198 - Part 1: Add a DEBUG-only count of frames that use a style context. r=dbaron a=abillings
layout/forms/nsButtonFrameRenderer.cpp
layout/forms/nsRangeFrame.cpp
layout/generic/nsFrame.cpp
layout/generic/nsIFrame.h
layout/style/nsStyleContext.cpp
layout/style/nsStyleContext.h
--- 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);