Bug 1077718 - Switch dynamic CounterStyle objects to use arena allocation. r=mats
authorXidorn Quan <quanxunzhen@gmail.com>
Thu, 16 Oct 2014 16:10:00 -0400
changeset 211327 d986a5a0ebed4c85548a3f461a3538bb815cdac0
parent 211326 2a87759dd8c8a3eee0eaea861a6d73b1aa36307b
child 211328 9774579c63f1e292a3f9a50aa34b0a49fa623e47
push id27673
push userkwierso@gmail.com
push dateTue, 21 Oct 2014 01:57:45 +0000
treeherdermozilla-central@29fbfc1b31aa [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmats
bugs1077718
milestone36.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 1077718 - Switch dynamic CounterStyle objects to use arena allocation. r=mats
layout/base/nsPresArena.h
layout/base/nsPresContext.cpp
layout/style/CounterStyleManager.cpp
layout/style/CounterStyleManager.h
--- a/layout/base/nsPresArena.h
+++ b/layout/base/nsPresArena.h
@@ -29,16 +29,19 @@ public:
   enum ObjectID {
     nsLineBox_id = nsQueryFrame::NON_FRAME_MARKER,
     nsRuleNode_id,
     nsStyleContext_id,
     nsInheritedStyleData_id,
     nsResetStyleData_id,
     nsFrameList_id,
 
+    CustomCounterStyle_id,
+    DependentBuiltinCounterStyle_id,
+
     First_nsStyleStruct_id,
     DummyBeforeStyleStructs_id = First_nsStyleStruct_id - 1,
 
     #define STYLE_STRUCT(name_, checkdata_cb_) \
       nsStyle##name_##_id,
     #include "nsStyleStructList.h"
     #undef STYLE_STRUCT
 
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -963,21 +963,16 @@ nsPresContext::Init(nsDeviceContext* aDe
   mCurAppUnitsPerDevPixel = AppUnitsPerDevPixel();
 
   mEventManager = new mozilla::EventStateManager();
 
   mTransitionManager = new nsTransitionManager(this);
 
   mAnimationManager = new nsAnimationManager(this);
 
-  // Since CounterStyleManager is also the name of a method of
-  // nsPresContext, it is necessary to prefix the class with the mozilla
-  // namespace here.
-  mCounterStyleManager = new mozilla::CounterStyleManager(this);
-
   if (mDocument->GetDisplayDocument()) {
     NS_ASSERTION(mDocument->GetDisplayDocument()->GetShell() &&
                  mDocument->GetDisplayDocument()->GetShell()->GetPresContext(),
                  "Why are we being initialized?");
     mRefreshDriver = mDocument->GetDisplayDocument()->GetShell()->
       GetPresContext()->RefreshDriver();
   } else {
     nsIDocument* parent = mDocument->GetParentDocument();
@@ -1095,29 +1090,38 @@ nsPresContext::Init(nsDeviceContext* aDe
 void
 nsPresContext::SetShell(nsIPresShell* aShell)
 {
   if (mFontFaceSet) {
     // Clear out user font set if we have one
     mFontFaceSet->DestroyUserFontSet();
     mFontFaceSet = nullptr;
   }
+  if (mCounterStyleManager) {
+    mCounterStyleManager->Disconnect();
+    mCounterStyleManager = nullptr;
+  }
 
   if (mShell) {
     // Remove ourselves as the charset observer from the shell's doc, because
     // this shell may be going away for good.
     nsIDocument *doc = mShell->GetDocument();
     if (doc) {
       doc->RemoveCharSetObserver(this);
     }
   }
 
   mShell = aShell;
 
   if (mShell) {
+    // Since CounterStyleManager is also the name of a method of
+    // nsPresContext, it is necessary to prefix the class with the mozilla
+    // namespace here.
+    mCounterStyleManager = new mozilla::CounterStyleManager(this);
+
     nsIDocument *doc = mShell->GetDocument();
     NS_ASSERTION(doc, "expect document here");
     if (doc) {
       // Have to update PresContext's mDocument before calling any other methods.
       mDocument = doc;
     }
     // Initialize our state from the user preferences, now that we
     // have a presshell, and hence a document.
@@ -1151,20 +1155,16 @@ nsPresContext::SetShell(nsIPresShell* aS
     if (mAnimationManager) {
       mAnimationManager->Disconnect();
       mAnimationManager = nullptr;
     }
     if (mRestyleManager) {
       mRestyleManager->Disconnect();
       mRestyleManager = nullptr;
     }
-    if (mCounterStyleManager) {
-      mCounterStyleManager->Disconnect();
-      mCounterStyleManager = nullptr;
-    }
 
     if (IsRoot()) {
       // Have to cancel our plugin geometry timer, because the
       // callback for that depends on a non-null presshell.
       static_cast<nsRootPresContext*>(this)->CancelApplyPluginGeometryTimer();
     }
   }
 }
--- a/layout/style/CounterStyleManager.cpp
+++ b/layout/style/CounterStyleManager.cpp
@@ -961,22 +961,42 @@ public:
     NS_ASSERTION(IsDependentStyle(), "Not a dependent builtin style");
     NS_ABORT_IF_FALSE(!IsCustomStyle(), "Not a builtin style");
   }
 
   virtual CounterStyle* GetFallback() MOZ_OVERRIDE;
 
   // DependentBuiltinCounterStyle is managed in the same way as
   // CustomCounterStyle.
-  NS_INLINE_DECL_REFCOUNTING(DependentBuiltinCounterStyle)
+  NS_IMETHOD_(MozExternalRefCountType) AddRef() MOZ_OVERRIDE;
+  NS_IMETHOD_(MozExternalRefCountType) Release() MOZ_OVERRIDE;
+
+  void* operator new(size_t sz, nsPresContext* aPresContext) CPP_THROW_NEW
+  {
+    return aPresContext->PresShell()->AllocateByObjectID(
+        nsPresArena::DependentBuiltinCounterStyle_id, sz);
+  }
 
 private:
+  void Destroy()
+  {
+    nsIPresShell* shell = mManager->PresContext()->PresShell();
+    this->~DependentBuiltinCounterStyle();
+    shell->FreeByObjectID(nsPresArena::DependentBuiltinCounterStyle_id, this);
+  }
+
   CounterStyleManager* mManager;
+
+  nsAutoRefCnt mRefCnt;
+  NS_DECL_OWNINGTHREAD
 };
 
+NS_IMPL_ADDREF(DependentBuiltinCounterStyle)
+NS_IMPL_RELEASE_WITH_DESTROY(DependentBuiltinCounterStyle, Destroy())
+
 /* virtual */ CounterStyle*
 DependentBuiltinCounterStyle::GetFallback()
 {
   switch (GetStyle()) {
     case NS_STYLE_LIST_STYLE_JAPANESE_INFORMAL:
     case NS_STYLE_LIST_STYLE_JAPANESE_FORMAL:
     case NS_STYLE_LIST_STYLE_KOREAN_HANGUL_FORMAL:
     case NS_STYLE_LIST_STYLE_KOREAN_HANJA_INFORMAL:
@@ -1059,19 +1079,33 @@ public:
   bool IsExtendsSystem()
   {
     return mSystem == NS_STYLE_COUNTER_SYSTEM_EXTENDS;
   }
 
   // CustomCounterStyle should be reference-counted because it may be
   // dereferenced from the manager but still referenced by nodes and
   // frames before the style change is propagated.
-  NS_INLINE_DECL_REFCOUNTING(CustomCounterStyle)
+  NS_IMETHOD_(MozExternalRefCountType) AddRef() MOZ_OVERRIDE;
+  NS_IMETHOD_(MozExternalRefCountType) Release() MOZ_OVERRIDE;
+
+  void* operator new(size_t sz, nsPresContext* aPresContext) CPP_THROW_NEW
+  {
+    return aPresContext->PresShell()->AllocateByObjectID(
+        nsPresArena::CustomCounterStyle_id, sz);
+  }
 
 private:
+  void Destroy()
+  {
+    nsIPresShell* shell = mManager->PresContext()->PresShell();
+    this->~CustomCounterStyle();
+    shell->FreeByObjectID(nsPresArena::CustomCounterStyle_id, this);
+  }
+
   const nsTArray<nsString>& GetSymbols();
   const nsTArray<AdditiveSymbol>& GetAdditiveSymbols();
 
   // The speak-as values of counter styles may form a loop, and the
   // loops may have complex interaction with the loop formed by
   // extending. To solve this problem, the computation of speak-as is
   // divided into two phases:
   // 1. figure out the raw value, by ComputeRawSpeakAs, and
@@ -1134,18 +1168,24 @@ private:
   // That counter must not speak as another counter.
   CounterStyle* mSpeakAsCounter;
 
   CounterStyle* mExtends;
   // This field refers to the last counter in the extends chain. The
   // counter must be either a builtin style or a style whose system is
   // not 'extends'.
   CounterStyle* mExtendsRoot;
+
+  nsAutoRefCnt mRefCnt;
+  NS_DECL_OWNINGTHREAD
 };
 
+NS_IMPL_ADDREF(CustomCounterStyle)
+NS_IMPL_RELEASE_WITH_DESTROY(CustomCounterStyle, Destroy())
+
 void
 CustomCounterStyle::ResetCachedData()
 {
   mSymbols.Clear();
   mAdditiveSymbols.Clear();
   mFlags &= ~(FLAG_NEGATIVE_INITED |
               FLAG_PREFIX_INITED |
               FLAG_SUFFIX_INITED |
@@ -1963,23 +2003,23 @@ CounterStyleManager::BuildCounterStyle(c
     return data;
   }
 
   // It is intentional that the predefined names are case-insensitive
   // but the user-defined names case-sensitive.
   nsCSSCounterStyleRule* rule =
     mPresContext->StyleSet()->CounterStyleRuleForName(mPresContext, aName);
   if (rule) {
-    data = new CustomCounterStyle(this, rule);
+    data = new (mPresContext) CustomCounterStyle(this, rule);
   } else {
     int32_t type;
     nsCSSKeyword keyword = nsCSSKeywords::LookupKeyword(aName);
     if (nsCSSProps::FindKeyword(keyword, nsCSSProps::kListStyleKTable, type)) {
       if (gBuiltinStyleTable[type].IsDependentStyle()) {
-        data = new DependentBuiltinCounterStyle(type, this);
+        data = new (mPresContext) DependentBuiltinCounterStyle(type, this);
       } else {
         data = GetBuiltinStyle(type);
       }
     }
   }
   if (!data) {
     data = GetDecimalStyle();
   }
--- a/layout/style/CounterStyleManager.h
+++ b/layout/style/CounterStyleManager.h
@@ -171,16 +171,18 @@ public:
   }
 
   // This method will scan all existing counter styles generated by this
   // manager, and remove or mark data dirty accordingly. It returns true
   // if any counter style is changed, false elsewise. This method should
   // be called when any counter style may be affected.
   bool NotifyRuleChanged();
 
+  nsPresContext* PresContext() const { return mPresContext; }
+
   NS_INLINE_DECL_REFCOUNTING(CounterStyleManager)
 
 private:
   nsPresContext* mPresContext;
   nsRefPtrHashtable<nsStringHashKey, CounterStyle> mCacheTable;
 };
 
 } // namespace mozilla