Bug 1186786 - Replace nsBaseHashtable::EnumerateRead() calls in accessible/ with iterators. r=tbsaunde.
authorNicholas Nethercote <nnethercote@mozilla.com>
Mon, 19 Oct 2015 17:52:43 -0700
changeset 304309 9a1e89df904b953006be78880dbe99ad262c5d6a
parent 304308 4d1821f242547fc64ff9417de0406bd1f36c0734
child 304310 8009ed0eb3a6ddd265fc236c0478f73130a9f07f
push id1001
push userraliiev@mozilla.com
push dateMon, 18 Jan 2016 19:06:03 +0000
treeherdermozilla-release@8b89261f3ac4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstbsaunde
bugs1186786
milestone44.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 1186786 - Replace nsBaseHashtable::EnumerateRead() calls in accessible/ with iterators. r=tbsaunde.
accessible/base/DocManager.cpp
accessible/base/DocManager.h
accessible/generic/DocAccessible.cpp
accessible/generic/DocAccessible.h
--- a/accessible/base/DocManager.cpp
+++ b/accessible/base/DocManager.cpp
@@ -1,9 +1,10 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "DocManager.h"
 
 #include "ApplicationAccessible.h"
 #include "ARIAMap.h"
@@ -66,23 +67,29 @@ DocManager::GetDocAccessible(nsIDocument
     return docAcc;
 
   return CreateDocOrRootAccessible(aDocument);
 }
 
 Accessible*
 DocManager::FindAccessibleInCache(nsINode* aNode) const
 {
-  nsSearchAccessibleInCacheArg arg;
-  arg.mNode = aNode;
+  for (auto iter = mDocAccessibleCache.ConstIter(); !iter.Done(); iter.Next()) {
+    DocAccessible* docAccessible = iter.UserData();
+    NS_ASSERTION(docAccessible,
+                 "No doc accessible for the object in doc accessible cache!");
 
-  mDocAccessibleCache.EnumerateRead(SearchAccessibleInDocCache,
-                                    static_cast<void*>(&arg));
-
-  return arg.mAccessible;
+    if (docAccessible) {
+      Accessible* accessible = docAccessible->GetAccessible(aNode);
+      if (accessible) {
+        return accessible;
+      }
+    }
+  }
+  return nullptr;
 }
 
 void
 DocManager::NotifyOfDocumentShutdown(DocAccessible* aDocument,
                                      nsIDocument* aDOMDocument)
 {
   xpcAccessibleDocument* xpcDoc = mXPCDocumentCache.GetWeak(aDocument);
   if (xpcDoc) {
@@ -107,21 +114,27 @@ DocManager::GetXPCDocument(DocAccessible
   }
   return xpcDoc;
 }
 
 #ifdef DEBUG
 bool
 DocManager::IsProcessingRefreshDriverNotification() const
 {
-  bool isDocRefreshing = false;
-  mDocAccessibleCache.EnumerateRead(SearchIfDocIsRefreshing,
-                                    static_cast<void*>(&isDocRefreshing));
+  for (auto iter = mDocAccessibleCache.ConstIter(); !iter.Done(); iter.Next()) {
+    DocAccessible* docAccessible = iter.UserData();
+    NS_ASSERTION(docAccessible,
+                 "No doc accessible for the object in doc accessible cache!");
 
-  return isDocRefreshing;
+    if (docAccessible && docAccessible->mNotificationController &&
+        docAccessible->mNotificationController->IsUpdating()) {
+      return true;
+    }
+  }
+  return false;
 }
 #endif
 
 
 ////////////////////////////////////////////////////////////////////////////////
 // DocManager protected
 
 bool
@@ -483,76 +496,34 @@ DocManager::CreateDocOrRootAccessible(ns
 
   AddListeners(aDocument, isRootDoc);
   return docAcc;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // DocManager static
 
-PLDHashOperator
-DocManager::GetFirstEntryInDocCache(const nsIDocument* aKey,
-                                    DocAccessible* aDocAccessible,
-                                    void* aUserArg)
-{
-  NS_ASSERTION(aDocAccessible,
-               "No doc accessible for the object in doc accessible cache!");
-  *reinterpret_cast<DocAccessible**>(aUserArg) = aDocAccessible;
-
-  return PL_DHASH_STOP;
-}
-
 void
 DocManager::ClearDocCache()
 {
-  DocAccessible* docAcc = nullptr;
-  while (mDocAccessibleCache.EnumerateRead(GetFirstEntryInDocCache, static_cast<void*>(&docAcc))) {
-    if (docAcc)
+  // This unusual do-one-element-per-iterator approach is required because each
+  // DocAccessible is removed elsewhere upon its Shutdown() method being
+  // called, which invalidates the existing iterator.
+  while (mDocAccessibleCache.Count() > 0) {
+    auto iter = mDocAccessibleCache.Iter();
+    MOZ_ASSERT(!iter.Done());
+    DocAccessible* docAcc = iter.UserData();
+    NS_ASSERTION(docAcc,
+                 "No doc accessible for the object in doc accessible cache!");
+    if (docAcc) {
       docAcc->Shutdown();
+    }
   }
 }
 
-PLDHashOperator
-DocManager::SearchAccessibleInDocCache(const nsIDocument* aKey,
-                                       DocAccessible* aDocAccessible,
-                                       void* aUserArg)
-{
-  NS_ASSERTION(aDocAccessible,
-               "No doc accessible for the object in doc accessible cache!");
-
-  if (aDocAccessible) {
-    nsSearchAccessibleInCacheArg* arg =
-      static_cast<nsSearchAccessibleInCacheArg*>(aUserArg);
-    arg->mAccessible = aDocAccessible->GetAccessible(arg->mNode);
-    if (arg->mAccessible)
-      return PL_DHASH_STOP;
-  }
-
-  return PL_DHASH_NEXT;
-}
-
-#ifdef DEBUG
-PLDHashOperator
-DocManager::SearchIfDocIsRefreshing(const nsIDocument* aKey,
-                                    DocAccessible* aDocAccessible,
-                                    void* aUserArg)
-{
-  NS_ASSERTION(aDocAccessible,
-               "No doc accessible for the object in doc accessible cache!");
-
-  if (aDocAccessible && aDocAccessible->mNotificationController &&
-      aDocAccessible->mNotificationController->IsUpdating()) {
-    *(static_cast<bool*>(aUserArg)) = true;
-    return PL_DHASH_STOP;
-  }
-
-  return PL_DHASH_NEXT;
-}
-#endif
-
 void
 DocManager::RemoteDocAdded(DocAccessibleParent* aDoc)
 {
   if (!sRemoteDocuments) {
     sRemoteDocuments = new nsTArray<DocAccessibleParent*>;
     ClearOnShutdown(&sRemoteDocuments);
   }
 
--- a/accessible/base/DocManager.h
+++ b/accessible/base/DocManager.h
@@ -131,45 +131,20 @@ private:
   void RemoveListeners(nsIDocument* aDocument);
 
   /**
    * Create document or root accessible.
    */
   DocAccessible* CreateDocOrRootAccessible(nsIDocument* aDocument);
 
   /**
-   * Get first entry of the document accessible from cache.
-   */
-  static PLDHashOperator
-    GetFirstEntryInDocCache(const nsIDocument* aKey,
-                            DocAccessible* aDocAccessible,
-                            void* aUserArg);
-
-  /**
    * Clear the cache and shutdown the document accessibles.
    */
   void ClearDocCache();
 
-  struct nsSearchAccessibleInCacheArg
-  {
-    Accessible* mAccessible;
-    nsINode* mNode;
-  };
-
-  static PLDHashOperator
-    SearchAccessibleInDocCache(const nsIDocument* aKey,
-                               DocAccessible* aDocAccessible,
-                               void* aUserArg);
-
-#ifdef DEBUG
-  static PLDHashOperator
-    SearchIfDocIsRefreshing(const nsIDocument* aKey,
-                            DocAccessible* aDocAccessible, void* aUserArg);
-#endif
-
   typedef nsRefPtrHashtable<nsPtrHashKey<const nsIDocument>, DocAccessible>
     DocAccessibleHashtable;
   DocAccessibleHashtable mDocAccessibleCache;
 
   typedef nsRefPtrHashtable<nsPtrHashKey<const DocAccessible>, xpcAccessibleDocument>
     XPCDocumentHashtable;
   XPCDocumentHashtable mXPCDocumentCache;
 
--- a/accessible/generic/DocAccessible.cpp
+++ b/accessible/generic/DocAccessible.cpp
@@ -1,9 +1,10 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "Accessible-inl.h"
 #include "AccIterator.h"
 #include "DocAccessible-inl.h"
 #include "DocAccessibleChild.h"
@@ -108,17 +109,30 @@ DocAccessible::~DocAccessible()
 // nsISupports
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(DocAccessible)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(DocAccessible, Accessible)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNotificationController)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVirtualCursor)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChildDocuments)
-  tmp->mDependentIDsHash.EnumerateRead(CycleCollectorTraverseDepIDsEntry, &cb);
+  for (auto iter = tmp->mDependentIDsHash.Iter(); !iter.Done(); iter.Next()) {
+    AttrRelProviderArray* providers = iter.UserData();
+
+    for (int32_t jdx = providers->Length() - 1; jdx >= 0; jdx--) {
+      NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(
+        cb, "content of dependent ids hash entry of document accessible");
+
+      AttrRelProvider* provider = (*providers)[jdx];
+      cb.NoteXPCOMChild(provider->mContent);
+
+      NS_ASSERTION(provider->mContent->IsInDoc(),
+                   "Referred content is not in document!");
+    }
+  }
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAccessibleCache)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAnchorJumpElm)
   for (uint32_t i = 0; i < tmp->mARIAOwnsInvalidationList.Length(); ++i) {
     NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mARIAOwnsInvalidationList[i].mOwner)
     NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mARIAOwnsInvalidationList[i].mChild)
   }
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
@@ -2212,30 +2226,8 @@ DocAccessible::IsLoadEventTarget() const
     DocAccessible* parentDoc = ParentDocument();
     return parentDoc && parentDoc->HasLoadState(eCompletelyLoaded);
   }
 
   // It's content (not chrome) root document.
   return (treeItem->ItemType() == nsIDocShellTreeItem::typeContent);
 }
 
-PLDHashOperator
-DocAccessible::CycleCollectorTraverseDepIDsEntry(const nsAString& aKey,
-                                                 AttrRelProviderArray* aProviders,
-                                                 void* aUserArg)
-{
-  nsCycleCollectionTraversalCallback* cb =
-    static_cast<nsCycleCollectionTraversalCallback*>(aUserArg);
-
-  for (int32_t jdx = aProviders->Length() - 1; jdx >= 0; jdx--) {
-    NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb,
-                                       "content of dependent ids hash entry of document accessible");
-
-    AttrRelProvider* provider = (*aProviders)[jdx];
-    cb->NoteXPCOMChild(provider->mContent);
-
-    NS_ASSERTION(provider->mContent->IsInDoc(),
-                 "Referred content is not in document!");
-  }
-
-  return PL_DHASH_NEXT;
-}
-
--- a/accessible/generic/DocAccessible.h
+++ b/accessible/generic/DocAccessible.h
@@ -653,21 +653,16 @@ protected:
   typedef nsClassHashtable<nsStringHashKey, AttrRelProviderArray>
     DependentIDsHashtable;
 
   /**
    * The cache of IDs pointed by relation attributes.
    */
   DependentIDsHashtable mDependentIDsHash;
 
-  static PLDHashOperator
-    CycleCollectorTraverseDepIDsEntry(const nsAString& aKey,
-                                      AttrRelProviderArray* aProviders,
-                                      void* aUserArg);
-
   friend class RelatedAccIterator;
 
   /**
    * Used for our caching algorithm. We store the list of nodes that should be
    * invalidated.
    *
    * @see ProcessInvalidationList
    */