Bug 972591, part 2 - Convert nsXBLPrototypeBinding::mAttributeTable to nsClassHashtable. r=froydnj,bz
authorAndrew McCreight <continuation@gmail.com>
Thu, 20 Feb 2014 12:55:39 -0800
changeset 170109 0f213da041376943d90fc69b62665535a317727e
parent 170108 ffd9d3ae66fe011bdb80aebe6db01b31ed8aef23
child 170110 df1edcb49a35e1e7b44136952a7e2635983f3cd5
push id270
push userpvanderbeken@mozilla.com
push dateThu, 06 Mar 2014 09:24:21 +0000
reviewersfroydnj, bz
bugs972591
milestone30.0a1
Bug 972591, part 2 - Convert nsXBLPrototypeBinding::mAttributeTable to nsClassHashtable. r=froydnj,bz
dom/xbl/nsXBLPrototypeBinding.cpp
dom/xbl/nsXBLPrototypeBinding.h
--- a/dom/xbl/nsXBLPrototypeBinding.cpp
+++ b/dom/xbl/nsXBLPrototypeBinding.cpp
@@ -95,17 +95,16 @@ protected:
 nsXBLPrototypeBinding::nsXBLPrototypeBinding()
 : mImplementation(nullptr),
   mBaseBinding(nullptr),
   mInheritStyle(true),
   mCheckedBaseProto(false),
   mKeyHandlersRegistered(false),
   mChromeOnlyContent(false),
   mResources(nullptr),
-  mAttributeTable(nullptr),
   mBaseNameSpaceID(kNameSpaceID_None)
 {
   MOZ_COUNT_CTOR(nsXBLPrototypeBinding);
 }
 
 nsresult
 nsXBLPrototypeBinding::Init(const nsACString& aID,
                             nsXBLDocumentInfo* aInfo,
@@ -176,17 +175,16 @@ nsXBLPrototypeBinding::Initialize()
   if (content) {
     ConstructAttributeTable(content);
   }
 }
 
 nsXBLPrototypeBinding::~nsXBLPrototypeBinding(void)
 {
   delete mResources;
-  delete mAttributeTable;
   delete mImplementation;
   MOZ_COUNT_DTOR(nsXBLPrototypeBinding);
 }
 
 void
 nsXBLPrototypeBinding::SetBasePrototype(nsXBLPrototypeBinding* aBinding)
 {
   if (mBaseBinding == aBinding)
@@ -320,24 +318,22 @@ nsXBLPrototypeBinding::AttributeChanged(
                                         int32_t aNameSpaceID,
                                         bool aRemoveFlag, 
                                         nsIContent* aChangedElement,
                                         nsIContent* aAnonymousContent,
                                         bool aNotify)
 {
   if (!mAttributeTable)
     return;
-  nsPRUint32Key nskey(aNameSpaceID);
-  nsObjectHashtable *attributesNS = static_cast<nsObjectHashtable*>(mAttributeTable->Get(&nskey));
+
+  InnerAttributeTable *attributesNS = mAttributeTable->Get(aNameSpaceID);
   if (!attributesNS)
     return;
 
-  nsISupportsKey key(aAttribute);
-  nsXBLAttributeEntry* xblAttr = static_cast<nsXBLAttributeEntry*>
-                                            (attributesNS->Get(&key));
+  nsXBLAttributeEntry* xblAttr = attributesNS->Get(aAttribute);
   if (!xblAttr)
     return;
 
   // Iterate over the elements in the array.
   nsCOMPtr<nsIContent> content = GetImmediateChild(nsGkAtoms::content);
   while (xblAttr) {
     nsIContent* element = xblAttr->GetElement();
 
@@ -495,22 +491,22 @@ struct nsXBLAttrChangeData
   int32_t mSrcNamespace;
 
   nsXBLAttrChangeData(nsXBLPrototypeBinding* aProto,
                       nsIContent* aElt, nsIContent* aContent) 
   :mProto(aProto), mBoundElement(aElt), mContent(aContent) {}
 };
 
 // XXXbz this duplicates lots of AttributeChanged
-bool SetAttrs(nsHashKey* aKey, void* aData, void* aClosure)
+static PLDHashOperator
+SetAttrs(nsISupports* aKey, nsXBLAttributeEntry* aEntry, void* aClosure)
 {
-  nsXBLAttributeEntry* entry = static_cast<nsXBLAttributeEntry*>(aData);
   nsXBLAttrChangeData* changeData = static_cast<nsXBLAttrChangeData*>(aClosure);
 
-  nsIAtom* src = entry->GetSrcAttribute();
+  nsIAtom* src = aEntry->GetSrcAttribute();
   int32_t srcNs = changeData->mSrcNamespace;
   nsAutoString value;
   bool attrPresent = true;
 
   if (src == nsGkAtoms::text && srcNs == kNameSpaceID_XBL) {
     nsContentUtils::GetNodeTextContent(changeData->mBoundElement, false,
                                        value);
     value.StripChar(char16_t('\n'));
@@ -524,17 +520,17 @@ bool SetAttrs(nsHashKey* aKey, void* aDa
   else {
     attrPresent = changeData->mBoundElement->GetAttr(srcNs, src, value);
   }
 
   if (attrPresent) {
     nsIContent* content =
       changeData->mProto->GetImmediateChild(nsGkAtoms::content);
 
-    nsXBLAttributeEntry* curr = entry;
+    nsXBLAttributeEntry* curr = aEntry;
     while (curr) {
       nsIAtom* dst = curr->GetDstAttribute();
       int32_t dstNs = curr->GetDstNameSpace();
       nsIContent* element = curr->GetElement();
 
       nsIContent *realElement =
         changeData->mProto->LocateInstance(changeData->mBoundElement, content,
                                            changeData->mContent, element);
@@ -555,39 +551,38 @@ bool SetAttrs(nsHashKey* aKey, void* aDa
           realElement->AppendChildTo(textContent, false);
         }
       }
 
       curr = curr->GetNext();
     }
   }
 
-  return true;
+  return PL_DHASH_NEXT;
 }
 
-bool SetAttrsNS(nsHashKey* aKey, void* aData, void* aClosure)
+static PLDHashOperator
+SetAttrsNS(const uint32_t &aNamespace,
+           nsXBLPrototypeBinding::InnerAttributeTable* aXBLAttributes,
+           void* aClosure)
 {
-  if (aData && aClosure) {
-    nsPRUint32Key * key = static_cast<nsPRUint32Key*>(aKey);
-    nsObjectHashtable* xblAttributes =
-      static_cast<nsObjectHashtable*>(aData);
-    nsXBLAttrChangeData * changeData = static_cast<nsXBLAttrChangeData *>
-                                                  (aClosure);
-    changeData->mSrcNamespace = key->GetValue();
-    xblAttributes->Enumerate(SetAttrs, (void*)changeData);
+  if (aXBLAttributes && aClosure) {
+    nsXBLAttrChangeData* changeData = static_cast<nsXBLAttrChangeData*>(aClosure);
+    changeData->mSrcNamespace = aNamespace;
+    aXBLAttributes->EnumerateRead(SetAttrs, aClosure);
   }
-  return true;
+  return PL_DHASH_NEXT;
 }
 
 void
 nsXBLPrototypeBinding::SetInitialAttributes(nsIContent* aBoundElement, nsIContent* aAnonymousContent)
 {
   if (mAttributeTable) {
     nsXBLAttrChangeData data(this, aBoundElement, aAnonymousContent);
-    mAttributeTable->Enumerate(SetAttrsNS, (void*)&data);
+    mAttributeTable->EnumerateRead(SetAttrsNS, &data);
   }
 }
 
 nsIStyleRuleProcessor*
 nsXBLPrototypeBinding::GetRuleProcessor()
 {
   if (mResources) {
     return mResources->mRuleProcessor;
@@ -611,63 +606,41 @@ nsXBLPrototypeBinding::GetStyleSheets()
 {
   if (mResources) {
     return &mResources->mStyleSheetList;
   }
 
   return nullptr;
 }
 
-static bool
-DeleteAttributeEntry(nsHashKey* aKey, void* aData, void* aClosure)
-{
-  delete static_cast<nsXBLAttributeEntry*>(aData);
-  return true;
-}
-
-static bool
-DeleteAttributeTable(nsHashKey* aKey, void* aData, void* aClosure)
-{
-  delete static_cast<nsObjectHashtable*>(aData);
-  return true;
-}
-
 void
 nsXBLPrototypeBinding::EnsureAttributeTable()
 {
   if (!mAttributeTable) {
-    mAttributeTable = new nsObjectHashtable(nullptr, nullptr,
-                                            DeleteAttributeTable,
-                                            nullptr, 4);
+    mAttributeTable = new nsClassHashtable<nsUint32HashKey, InnerAttributeTable>(4);
   }
 }
 
 void
 nsXBLPrototypeBinding::AddToAttributeTable(int32_t aSourceNamespaceID, nsIAtom* aSourceTag,
                                            int32_t aDestNamespaceID, nsIAtom* aDestTag,
                                            nsIContent* aContent)
 {
-    nsPRUint32Key nskey(aSourceNamespaceID);
-    nsObjectHashtable* attributesNS =
-      static_cast<nsObjectHashtable*>(mAttributeTable->Get(&nskey));
+    InnerAttributeTable* attributesNS = mAttributeTable->Get(aSourceNamespaceID);
     if (!attributesNS) {
-      attributesNS = new nsObjectHashtable(nullptr, nullptr,
-                                           DeleteAttributeEntry,
-                                           nullptr, 4);
-      mAttributeTable->Put(&nskey, attributesNS);
+      attributesNS = new InnerAttributeTable(4);
+      mAttributeTable->Put(aSourceNamespaceID, attributesNS);
     }
 
     nsXBLAttributeEntry* xblAttr =
       new nsXBLAttributeEntry(aSourceTag, aDestTag, aDestNamespaceID, aContent);
 
-    nsISupportsKey key(aSourceTag);
-    nsXBLAttributeEntry* entry = static_cast<nsXBLAttributeEntry*>
-                                            (attributesNS->Get(&key));
+    nsXBLAttributeEntry* entry = attributesNS->Get(aSourceTag);
     if (!entry) {
-      attributesNS->Put(&key, xblAttr);
+      attributesNS->Put(aSourceTag, xblAttr);
     } else {
       while (entry->GetNext())
         entry = entry->GetNext();
       entry->SetNext(xblAttr);
     }
 }
 
 void
@@ -1416,54 +1389,51 @@ struct WriteAttributeData
 
   WriteAttributeData(nsXBLPrototypeBinding* aBinding,
                      nsIObjectOutputStream* aStream,
                      nsIContent* aContent)
     : binding(aBinding), stream(aStream), content(aContent)
   { }
 };
 
-static
-bool
-WriteAttribute(nsHashKey *aKey, void *aData, void* aClosure)
+static PLDHashOperator
+WriteAttribute(nsISupports* aKey, nsXBLAttributeEntry* aEntry, void* aClosure)
 {
   WriteAttributeData* data = static_cast<WriteAttributeData *>(aClosure);
   nsIObjectOutputStream* stream = data->stream;
   const int32_t srcNamespace = data->srcNamespace;
 
-  nsXBLAttributeEntry* entry = static_cast<nsXBLAttributeEntry *>(aData);
   do {
-    if (entry->GetElement() == data->content) {
+    if (aEntry->GetElement() == data->content) {
       data->binding->WriteNamespace(stream, srcNamespace);
-      stream->WriteWStringZ(nsDependentAtomString(entry->GetSrcAttribute()).get());
-      data->binding->WriteNamespace(stream, entry->GetDstNameSpace());
-      stream->WriteWStringZ(nsDependentAtomString(entry->GetDstAttribute()).get());
+      stream->WriteWStringZ(nsDependentAtomString(aEntry->GetSrcAttribute()).get());
+      data->binding->WriteNamespace(stream, aEntry->GetDstNameSpace());
+      stream->WriteWStringZ(nsDependentAtomString(aEntry->GetDstAttribute()).get());
     }
 
-    entry = entry->GetNext();
-  } while (entry);
+    aEntry = aEntry->GetNext();
+  } while (aEntry);
 
-  return kHashEnumerateNext;
+  return PL_DHASH_NEXT;
 }
 
 // WriteAttributeNS is the callback to enumerate over the attribute
 // forwarding entries. Since these are stored in a hash of hashes,
 // we need to iterate over the inner hashes, calling WriteAttribute
 // to do the actual work.
-static
-bool
-WriteAttributeNS(nsHashKey *aKey, void *aData, void* aClosure)
+static PLDHashOperator
+WriteAttributeNS(const uint32_t &aNamespace,
+                 nsXBLPrototypeBinding::InnerAttributeTable* aXBLAttributes,
+                 void* aClosure)
 {
   WriteAttributeData* data = static_cast<WriteAttributeData *>(aClosure);
-  data->srcNamespace = static_cast<nsPRUint32Key *>(aKey)->GetValue();
+  data->srcNamespace = aNamespace;
+  aXBLAttributes->EnumerateRead(WriteAttribute, data);
 
-  nsObjectHashtable* attributes = static_cast<nsObjectHashtable*>(aData);
-  attributes->Enumerate(WriteAttribute, data);
-
-  return kHashEnumerateNext;
+  return PL_DHASH_NEXT;
 }
 
 nsresult
 nsXBLPrototypeBinding::WriteContentNode(nsIObjectOutputStream* aStream,
                                         nsIContent* aNode)
 {
   nsresult rv;
 
@@ -1537,17 +1507,17 @@ nsXBLPrototypeBinding::WriteContentNode(
     aNode->GetAttr(attr->NamespaceID(), attr->LocalName(), val);
     rv = aStream->WriteWStringZ(val.get());
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   // Write out the attribute fowarding information
   if (mAttributeTable) {
     WriteAttributeData data(this, aStream, aNode);
-    mAttributeTable->Enumerate(WriteAttributeNS, &data);
+    mAttributeTable->EnumerateRead(WriteAttributeNS, &data);
   }
   rv = aStream->Write8(XBLBinding_Serialize_NoMoreAttributes);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Finally, write out the child nodes.
   count = aNode->GetChildCount();
   rv = aStream->Write32(count);
   NS_ENSURE_SUCCESS(rv, rv);
--- a/dom/xbl/nsXBLPrototypeBinding.h
+++ b/dom/xbl/nsXBLPrototypeBinding.h
@@ -4,31 +4,31 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsXBLPrototypeBinding_h__
 #define nsXBLPrototypeBinding_h__
 
 #include "nsClassHashtable.h"
 #include "nsCOMArray.h"
 #include "nsCOMPtr.h"
-#include "nsHashtable.h"
 #include "nsICSSLoaderObserver.h"
 #include "nsInterfaceHashtable.h"
 #include "nsWeakReference.h"
 #include "nsXBLDocumentInfo.h"
 #include "nsXBLProtoImpl.h"
 #include "nsXBLProtoImplMethod.h"
 #include "nsXBLPrototypeHandler.h"
 #include "nsXBLPrototypeResources.h"
 
 class nsIAtom;
 class nsIContent;
 class nsIDocument;
+class nsXBLAttributeEntry;
+class nsXBLBinding;
 class nsXBLProtoImplField;
-class nsXBLBinding;
 
 // *********************************************************************/
 // The XBLPrototypeBinding class
 
 // Instances of this class are owned by the nsXBLDocumentInfo object returned
 // by XBLDocumentInfo().  Consumers who want to refcount things should refcount
 // that.
 class nsXBLPrototypeBinding
@@ -240,16 +240,19 @@ public:
    */
   nsIContent* GetImmediateChild(nsIAtom* aTag);
   nsIContent* LocateInstance(nsIContent* aBoundElt,
                              nsIContent* aTemplRoot,
                              nsIContent* aCopyRoot,
                              nsIContent* aTemplChild);
 
   bool ChromeOnlyContent() { return mChromeOnlyContent; }
+
+  typedef nsClassHashtable<nsISupportsHashKey, nsXBLAttributeEntry> InnerAttributeTable;
+
 protected:
   // Ensure that mAttributeTable has been created.
   void EnsureAttributeTable();
   // Ad an entry to the attribute table
   void AddToAttributeTable(int32_t aSourceNamespaceID, nsIAtom* aSourceTag,
                            int32_t aDestNamespaceID, nsIAtom* aDestTag,
                            nsIContent* aContent);
   void ConstructAttributeTable(nsIContent* aElement);
@@ -273,19 +276,20 @@ protected:
   bool mCheckedBaseProto;
   bool mKeyHandlersRegistered;
   bool mChromeOnlyContent;
 
   nsXBLPrototypeResources* mResources; // If we have any resources, this will be non-null.
 
   nsXBLDocumentInfo* mXBLDocInfoWeak; // A pointer back to our doc info.  Weak, since it owns us.
 
-  nsObjectHashtable* mAttributeTable; // A table for attribute containers. Namespace IDs are used as
-                                      // keys in the table. Containers are nsObjectHashtables.
-                                      // This table is used to efficiently handle attribute changes.
+  // A table for attribute containers. Namespace IDs are used as
+  // keys in the table. Containers are InnerAttributeTables.
+  // This table is used to efficiently handle attribute changes.
+  nsAutoPtr<nsClassHashtable<nsUint32HashKey, InnerAttributeTable>> mAttributeTable;
 
   class IIDHashKey : public PLDHashEntryHdr
   {
   public:
     typedef const nsIID& KeyType;
     typedef const nsIID* KeyTypePointer;
 
     IIDHashKey(const nsIID* aKey)