Bug 1077718 - Switch dynamic CounterStyle objects to use arena allocation. r=mats, a=lmandel
authorXidorn Quan <quanxunzhen@gmail.com>
Thu, 16 Oct 2014 16:10:00 -0400
changeset 225866 f681d39b83ca
parent 225865 60b312ec8c87
child 225867 acd99fc02446
push id4046
push userryanvm@gmail.com
push date2014-10-30 13:09 +0000
treeherdermozilla-beta@3554e60ef779 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmats, lmandel
bugs1077718
milestone34.0
Bug 1077718 - Switch dynamic CounterStyle objects to use arena allocation. r=mats, a=lmandel
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
@@ -962,21 +962,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();
@@ -1090,29 +1085,38 @@ nsPresContext::Init(nsDeviceContext* aDe
 void
 nsPresContext::SetShell(nsIPresShell* aShell)
 {
   if (mUserFontSet) {
     // Clear out user font set if we have one
     mUserFontSet->Destroy();
     NS_RELEASE(mUserFontSet);
   }
+  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.
@@ -1146,20 +1150,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
@@ -943,22 +943,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:
@@ -1041,19 +1061,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
@@ -1116,18 +1150,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 |
@@ -1837,23 +1877,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
@@ -129,16 +129,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