Bug 1203766 - Part 3: Add ArenaRefPtr support to nsStyleContext. r=bzbarsky
authorCameron McCormack <cam@mcc.id.au>
Thu, 17 Sep 2015 12:08:20 +1000
changeset 295556 3dd4992e71be618115edc551af8c219977fbb506
parent 295555 5efb8afff6c73545df0b6f88ab3d4653518b8ae2
child 295557 aa31a6af845a9e39fa4ebae3c78b2d71d0b4fbc1
push id5245
push userraliiev@mozilla.com
push dateThu, 29 Oct 2015 11:30:51 +0000
treeherdermozilla-beta@dac831dc1bd0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbzbarsky
bugs1203766
milestone43.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1203766 - Part 3: Add ArenaRefPtr support to nsStyleContext. r=bzbarsky
layout/base/nsIPresShell.h
layout/base/nsPresArena.cpp
layout/base/nsPresArena.h
layout/base/nsPresArenaObjectList.h
layout/style/nsStyleContext.cpp
layout/style/nsStyleContext.h
layout/style/nsStyleSet.cpp
--- a/layout/base/nsIPresShell.h
+++ b/layout/base/nsIPresShell.h
@@ -299,16 +299,21 @@ public:
   }
 
   template<typename T>
   void DeregisterArenaRefPtr(mozilla::ArenaRefPtr<T>* aPtr)
   {
     mFrameArena.DeregisterArenaRefPtr(aPtr);
   }
 
+  void ClearArenaRefPtrs(mozilla::ArenaObjectID aObjectID)
+  {
+    mFrameArena.ClearArenaRefPtrs(aObjectID);
+  }
+
   nsIDocument* GetDocument() const { return mDocument; }
 
   nsPresContext* GetPresContext() const { return mPresContext; }
 
   nsViewManager* GetViewManager() const { return mViewManager; }
 
 #ifdef ACCESSIBILITY
   /**
--- a/layout/base/nsPresArena.cpp
+++ b/layout/base/nsPresArena.cpp
@@ -18,16 +18,17 @@
 // PL_ARENA_CONST_ALIGN_MASK in this file.
 
 #include "nsPresArena.h"
 
 #include "mozilla/Poison.h"
 #include "nsDebug.h"
 #include "nsArenaMemoryStats.h"
 #include "nsPrintfCString.h"
+#include "nsStyleContext.h"
 
 #include <inttypes.h>
 
 using namespace mozilla;
 
 // Size to use for PLArena block allocations.
 static const size_t ARENA_PAGE_SIZE = 8192;
 
@@ -89,16 +90,29 @@ nsPresArena::ClearArenaRefPtrs()
   for (auto iter = mArenaRefPtrs.Iter(); !iter.Done(); iter.Next()) {
     void* ptr = iter.Key();
     ArenaObjectID id = iter.UserData();
     ClearArenaRefPtrWithoutDeregistering(ptr, id);
   }
   mArenaRefPtrs.Clear();
 }
 
+void
+nsPresArena::ClearArenaRefPtrs(ArenaObjectID aObjectID)
+{
+  for (auto iter = mArenaRefPtrs.Iter(); !iter.Done(); iter.Next()) {
+    void* ptr = iter.Key();
+    ArenaObjectID id = iter.UserData();
+    if (id == aObjectID) {
+      ClearArenaRefPtrWithoutDeregistering(ptr, id);
+      iter.Remove();
+    }
+  }
+}
+
 void*
 nsPresArena::Allocate(uint32_t aCode, size_t aSize)
 {
   MOZ_ASSERT(aSize > 0, "PresArena cannot allocate zero bytes");
 
   // We only hand out aligned sizes
   aSize = PL_ARENA_ALIGN(&mPool, aSize);
 
--- a/layout/base/nsPresArena.h
+++ b/layout/base/nsPresArena.h
@@ -71,17 +71,17 @@ public:
 
   /**
    * Register an ArenaRefPtr to be cleared when this arena is about to
    * be destroyed.
    *
    * (Defined in ArenaRefPtrInlines.h.)
    *
    * @param aPtr The ArenaRefPtr to clear.
-   * @param aObjectID The nsPresArena::ObjectID value that uniquely identifies
+   * @param aObjectID The ArenaObjectID value that uniquely identifies
    *   the type of object the ArenaRefPtr holds.
    */
   template<typename T>
   void RegisterArenaRefPtr(mozilla::ArenaRefPtr<T>* aPtr);
 
   /**
    * Deregister an ArenaRefPtr that was previously registered with
    * RegisterArenaRefPtr.
@@ -96,16 +96,24 @@ public:
   /**
    * Clears all currently registered ArenaRefPtrs.  This will be called during
    * the destructor, but can be called by users of nsPresArena who want to
    * ensure arena-allocated objects are released earlier.
    */
   void ClearArenaRefPtrs();
 
   /**
+   * Clears all currently registered ArenaRefPtrs for the given ArenaObjectID.
+   * This is called when we reconstruct the rule tree so that style contexts
+   * pointing into the old rule tree aren't released afterwards, triggering an
+   * assertion in ~nsStyleContext.
+   */
+  void ClearArenaRefPtrs(mozilla::ArenaObjectID aObjectID);
+
+  /**
    * Increment aArenaStats with sizes of interesting objects allocated in this
    * arena and its mOther field with the size of everything else.
    */
   void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf,
                               nsArenaMemoryStats* aArenaStats);
 
 private:
   void* Allocate(uint32_t aCode, size_t aSize);
--- a/layout/base/nsPresArenaObjectList.h
+++ b/layout/base/nsPresArenaObjectList.h
@@ -42,17 +42,17 @@
 //
 // Files including nsPresArenaObjectList.h can either define one or both
 // of PRES_ARENA_OBJECT_{WITH,WITHOUT}_ARENAREFPTR_SUPPORT to capture those
 // classes separately, or PRES_ARENA_OBJECT to capture all nsPresArena-
 // allocated classes.
 
 PRES_ARENA_OBJECT_WITHOUT_ARENAREFPTR_SUPPORT(nsLineBox)
 PRES_ARENA_OBJECT_WITHOUT_ARENAREFPTR_SUPPORT(nsRuleNode)
-PRES_ARENA_OBJECT_WITHOUT_ARENAREFPTR_SUPPORT(nsStyleContext)
+PRES_ARENA_OBJECT_WITH_ARENAREFPTR_SUPPORT(nsStyleContext)
 PRES_ARENA_OBJECT_WITHOUT_ARENAREFPTR_SUPPORT(nsInheritedStyleData)
 PRES_ARENA_OBJECT_WITHOUT_ARENAREFPTR_SUPPORT(nsResetStyleData)
 PRES_ARENA_OBJECT_WITHOUT_ARENAREFPTR_SUPPORT(nsConditionalResetStyleData)
 PRES_ARENA_OBJECT_WITHOUT_ARENAREFPTR_SUPPORT(nsConditionalResetStyleDataEntry)
 PRES_ARENA_OBJECT_WITHOUT_ARENAREFPTR_SUPPORT(nsFrameList)
 PRES_ARENA_OBJECT_WITHOUT_ARENAREFPTR_SUPPORT(CustomCounterStyle)
 PRES_ARENA_OBJECT_WITHOUT_ARENAREFPTR_SUPPORT(DependentBuiltinCounterStyle)
 
--- a/layout/style/nsStyleContext.cpp
+++ b/layout/style/nsStyleContext.cpp
@@ -1209,16 +1209,22 @@ NS_NewStyleContext(nsStyleContext* aPare
 {
   nsRefPtr<nsStyleContext> context =
     new (aRuleNode->PresContext())
     nsStyleContext(aParentContext, aPseudoTag, aPseudoType, aRuleNode,
                    aSkipParentDisplayBasedStyleFixup);
   return context.forget();
 }
 
+nsIPresShell*
+nsStyleContext::Arena()
+{
+  return mRuleNode->PresContext()->PresShell();
+}
+
 static inline void
 ExtractAnimationValue(nsCSSProperty aProperty,
                       nsStyleContext* aStyleContext,
                       StyleAnimationValue& aResult)
 {
   DebugOnly<bool> success =
     StyleAnimationValue::ExtractComputedValue(aProperty, aStyleContext,
                                               aResult);
--- a/layout/style/nsStyleContext.h
+++ b/layout/style/nsStyleContext.h
@@ -68,16 +68,23 @@ public:
   nsStyleContext(nsStyleContext* aParent, nsIAtom* aPseudoTag,
                  nsCSSPseudoElements::Type aPseudoType,
                  nsRuleNode* aRuleNode,
                  bool aSkipParentDisplayBasedStyleFixup);
 
   void* operator new(size_t sz, nsPresContext* aPresContext) CPP_THROW_NEW;
   void Destroy();
 
+  // These two methods are for use by ArenaRefPtr.
+  static mozilla::ArenaObjectID ArenaObjectID()
+  {
+    return mozilla::eArenaObjectID_nsStyleContext;
+  }
+  nsIPresShell* Arena();
+
 #ifdef DEBUG
   /**
    * Initializes a cached pref, which is only used in DEBUG code.
    */
   static void Initialize();
 #endif
 
   nsrefcnt AddRef() {
--- a/layout/style/nsStyleSet.cpp
+++ b/layout/style/nsStyleSet.cpp
@@ -255,16 +255,20 @@ nsStyleSet::Init(nsPresContext *aPresCon
 }
 
 nsresult
 nsStyleSet::BeginReconstruct()
 {
   NS_ASSERTION(!mInReconstruct, "Unmatched begin/end?");
   NS_ASSERTION(mRuleTree, "Reconstructing before first construction?");
 
+  // Clear any ArenaRefPtr-managed style contexts, as we don't want them
+  // held on to after the rule tree has been reconstructed.
+  PresContext()->PresShell()->ClearArenaRefPtrs(eArenaObjectID_nsStyleContext);
+
   // Create a new rule tree root
   nsRuleNode* newTree = nsRuleNode::CreateRootNode(mRuleTree->PresContext());
 
   // Save the old rule tree so we can destroy it later
   if (!mOldRuleTrees.AppendElement(mRuleTree)) {
     newTree->Destroy();
     return NS_ERROR_OUT_OF_MEMORY;
   }