Bug 972591, part 3 - Convert nsXBLDocumentInfo::mBindingTable to nsClassHashtable. r=froydnj,bz
authorAndrew McCreight <continuation@gmail.com>
Tue, 25 Feb 2014 20:32:48 -0800
changeset 170611 9d212681ddb7f1192f2943ee8d7b99ef9c74ffab
parent 170610 4f7be2b146f51589cc6a9956cb37d6568f5149f1
child 170612 89b4178ff5e7748ef7b9e0090081a235c9dc2352
push id40262
push useramccreight@mozilla.com
push dateWed, 26 Feb 2014 04:33:09 +0000
treeherdermozilla-inbound@9d212681ddb7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj, bz
bugs972591
milestone30.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 972591, part 3 - Convert nsXBLDocumentInfo::mBindingTable to nsClassHashtable. r=froydnj,bz
dom/xbl/nsXBLDocumentInfo.cpp
dom/xbl/nsXBLDocumentInfo.h
--- a/dom/xbl/nsXBLDocumentInfo.cpp
+++ b/dom/xbl/nsXBLDocumentInfo.cpp
@@ -218,101 +218,97 @@ nsXBLDocGlobalObject::GetPrincipal()
   if (!document)
     return nullptr;
 
   return document->NodePrincipal();
 }
 
 /* Implementation file */
 
-static bool
-TraverseProtos(nsHashKey *aKey, void *aData, void* aClosure)
+static PLDHashOperator
+TraverseProtos(const nsACString &aKey, nsXBLPrototypeBinding *aProto, void* aClosure)
 {
-  nsCycleCollectionTraversalCallback *cb = 
+  nsCycleCollectionTraversalCallback *cb =
     static_cast<nsCycleCollectionTraversalCallback*>(aClosure);
-  nsXBLPrototypeBinding *proto = static_cast<nsXBLPrototypeBinding*>(aData);
-  proto->Traverse(*cb);
-  return kHashEnumerateNext;
+  aProto->Traverse(*cb);
+  return PL_DHASH_NEXT;
 }
 
-static bool
-UnlinkProtoJSObjects(nsHashKey *aKey, void *aData, void* aClosure)
+static PLDHashOperator
+UnlinkProtoJSObjects(const nsACString &aKey, nsXBLPrototypeBinding *aProto, void* aClosure)
 {
-  nsXBLPrototypeBinding *proto = static_cast<nsXBLPrototypeBinding*>(aData);
-  proto->UnlinkJSObjects();
-  return kHashEnumerateNext;
+  aProto->UnlinkJSObjects();
+  return PL_DHASH_NEXT;
 }
 
 struct ProtoTracer
 {
   const TraceCallbacks &mCallbacks;
   void *mClosure;
 };
 
-static bool
-TraceProtos(nsHashKey *aKey, void *aData, void* aClosure)
+static PLDHashOperator
+TraceProtos(const nsACString &aKey, nsXBLPrototypeBinding *aProto, void* aClosure)
 {
   ProtoTracer* closure = static_cast<ProtoTracer*>(aClosure);
-  nsXBLPrototypeBinding *proto = static_cast<nsXBLPrototypeBinding*>(aData);
-  proto->Trace(closure->mCallbacks, closure->mClosure);
-  return kHashEnumerateNext;
+  aProto->Trace(closure->mCallbacks, closure->mClosure);
+  return PL_DHASH_NEXT;
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsXBLDocumentInfo)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXBLDocumentInfo)
   if (tmp->mBindingTable) {
-    tmp->mBindingTable->Enumerate(UnlinkProtoJSObjects, nullptr);
+    tmp->mBindingTable->EnumerateRead(UnlinkProtoJSObjects, nullptr);
   }
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocument)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mGlobalObject)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXBLDocumentInfo)
   if (tmp->mDocument &&
       nsCCUncollectableMarker::InGeneration(cb, tmp->mDocument->GetMarkedCCGeneration())) {
     NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
     return NS_SUCCESS_INTERRUPTED_TRAVERSE;
   }
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocument)
   if (tmp->mBindingTable) {
-    tmp->mBindingTable->Enumerate(TraverseProtos, &cb);
+    tmp->mBindingTable->EnumerateRead(TraverseProtos, &cb);
   }
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGlobalObject)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsXBLDocumentInfo)
   if (tmp->mBindingTable) {
     ProtoTracer closure = { aCallbacks, aClosure };
-    tmp->mBindingTable->Enumerate(TraceProtos, &closure);
+    tmp->mBindingTable->EnumerateRead(TraceProtos, &closure);
   }
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 static void
 UnmarkXBLJSObject(void* aP, const char* aName, void* aClosure)
 {
   JS::ExposeObjectToActiveJS(static_cast<JSObject*>(aP));
 }
 
-static bool
-UnmarkProtos(nsHashKey* aKey, void* aData, void* aClosure)
+static PLDHashOperator
+UnmarkProtos(const nsACString &aKey, nsXBLPrototypeBinding *aProto, void* aClosure)
 {
-  nsXBLPrototypeBinding* proto = static_cast<nsXBLPrototypeBinding*>(aData);
-  proto->Trace(TraceCallbackFunc(UnmarkXBLJSObject), nullptr);
-  return kHashEnumerateNext;
+  aProto->Trace(TraceCallbackFunc(UnmarkXBLJSObject), nullptr);
+  return PL_DHASH_NEXT;
 }
 
 void
 nsXBLDocumentInfo::MarkInCCGeneration(uint32_t aGeneration)
 {
   if (mDocument) {
     mDocument->MarkUncollectableForCCGeneration(aGeneration);
   }
   // Unmark any JS we hold
   if (mBindingTable) {
-    mBindingTable->Enumerate(UnmarkProtos, nullptr);
+    mBindingTable->EnumerateRead(UnmarkProtos, nullptr);
   }
   if (mGlobalObject) {
     mGlobalObject->UnmarkCompilationGlobal();
   }
 }
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXBLDocumentInfo)
   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
@@ -321,17 +317,16 @@ NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsXBLDocumentInfo)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsXBLDocumentInfo)
 
 nsXBLDocumentInfo::nsXBLDocumentInfo(nsIDocument* aDocument)
   : mDocument(aDocument),
     mScriptAccess(true),
     mIsChrome(false),
-    mBindingTable(nullptr),
     mFirstBinding(nullptr)
 {
   nsIURI* uri = aDocument->GetDocumentURI();
   if (IsChromeURI(uri)) {
     // Cache whether or not this chrome XBL can execute scripts.
     nsCOMPtr<nsIXULChromeRegistry> reg =
       mozilla::services::GetXULChromeRegistryService();
     if (reg) {
@@ -362,84 +357,67 @@ nsXBLDocumentInfo::nsXBLDocumentInfo(nsI
 }
 
 nsXBLDocumentInfo::~nsXBLDocumentInfo()
 {
   /* destructor code */
   if (mGlobalObject) {
     mGlobalObject->ClearGlobalObjectOwner(); // just in case
   }
-  if (mBindingTable) {
-    delete mBindingTable;
-    mBindingTable = nullptr;
-    mozilla::DropJSObjects(this);
-  }
+  mozilla::DropJSObjects(this);
 }
 
 nsXBLPrototypeBinding*
 nsXBLDocumentInfo::GetPrototypeBinding(const nsACString& aRef)
 {
   if (!mBindingTable)
     return nullptr;
 
   if (aRef.IsEmpty()) {
     // Return our first binding
     return mFirstBinding;
   }
 
-  const nsPromiseFlatCString& flat = PromiseFlatCString(aRef);
-  nsCStringKey key(flat.get());
-  return static_cast<nsXBLPrototypeBinding*>(mBindingTable->Get(&key));
-}
-
-static bool
-DeletePrototypeBinding(nsHashKey* aKey, void* aData, void* aClosure)
-{
-  nsXBLPrototypeBinding* binding = static_cast<nsXBLPrototypeBinding*>(aData);
-  delete binding;
-  return true;
+  return mBindingTable->Get(aRef);
 }
 
 nsresult
 nsXBLDocumentInfo::SetPrototypeBinding(const nsACString& aRef, nsXBLPrototypeBinding* aBinding)
 {
   if (!mBindingTable) {
-    mBindingTable = new nsObjectHashtable(nullptr, nullptr, DeletePrototypeBinding, nullptr);
-
+    mBindingTable = new nsClassHashtable<nsCStringHashKey, nsXBLPrototypeBinding>();
     mozilla::HoldJSObjects(this);
   }
 
-  const nsPromiseFlatCString& flat = PromiseFlatCString(aRef);
-  nsCStringKey key(flat.get());
-  NS_ENSURE_STATE(!mBindingTable->Get(&key));
-  mBindingTable->Put(&key, aBinding);
+  NS_ENSURE_STATE(!mBindingTable->Get(aRef));
+  mBindingTable->Put(aRef, aBinding);
 
   return NS_OK;
 }
 
 void
 nsXBLDocumentInfo::RemovePrototypeBinding(const nsACString& aRef)
 {
   if (mBindingTable) {
-    // Use a flat string to avoid making a copy.
-    const nsPromiseFlatCString& flat = PromiseFlatCString(aRef);
-    nsCStringKey key(flat);
-    mBindingTable->Remove(&key);
+    nsAutoPtr<nsXBLPrototypeBinding> bindingToRemove;
+    mBindingTable->RemoveAndForget(aRef, bindingToRemove);
+
+    // We do not want to destroy the binding, so just forget it.
+    bindingToRemove.forget();
   }
 }
 
 // Callback to enumerate over the bindings from this document and write them
 // out to the cache.
-bool
-WriteBinding(nsHashKey *aKey, void *aData, void* aClosure)
+static PLDHashOperator
+WriteBinding(const nsACString &aKey, nsXBLPrototypeBinding *aProto, void* aClosure)
 {
-  nsXBLPrototypeBinding* binding = static_cast<nsXBLPrototypeBinding *>(aData);
-  binding->Write((nsIObjectOutputStream*)aClosure);
+  aProto->Write((nsIObjectOutputStream*)aClosure);
 
-  return kHashEnumerateNext;
+  return PL_DHASH_NEXT;
 }
 
 // static
 nsresult
 nsXBLDocumentInfo::ReadPrototypeBindings(nsIURI* aURI, nsXBLDocumentInfo** aDocInfo)
 {
   *aDocInfo = nullptr;
 
@@ -525,18 +503,19 @@ nsXBLDocumentInfo::WritePrototypeBinding
   rv = NewObjectOutputWrappedStorageStream(getter_AddRefs(stream),
                                            getter_AddRefs(storageStream),
                                            true);
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = stream->Write32(XBLBinding_Serialize_Version);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  if (mBindingTable)
-    mBindingTable->Enumerate(WriteBinding, stream);
+  if (mBindingTable) {
+    mBindingTable->EnumerateRead(WriteBinding, stream);
+  }
 
   // write a end marker at the end
   rv = stream->Write8(XBLBinding_Serialize_NoMoreBindings);
   NS_ENSURE_SUCCESS(rv, rv);
 
   stream->Close();
   NS_ENSURE_SUCCESS(rv, rv);
 
@@ -549,28 +528,29 @@ nsXBLDocumentInfo::WritePrototypeBinding
 }
 
 void
 nsXBLDocumentInfo::SetFirstPrototypeBinding(nsXBLPrototypeBinding* aBinding)
 {
   mFirstBinding = aBinding;
 }
 
-bool FlushScopedSkinSheets(nsHashKey* aKey, void* aData, void* aClosure)
+static PLDHashOperator
+FlushScopedSkinSheets(const nsACString &aKey, nsXBLPrototypeBinding *aProto, void* aClosure)
 {
-  nsXBLPrototypeBinding* proto = (nsXBLPrototypeBinding*)aData;
-  proto->FlushSkinSheets();
-  return true;
+  aProto->FlushSkinSheets();
+  return PL_DHASH_NEXT;
 }
 
 void
 nsXBLDocumentInfo::FlushSkinStylesheets()
 {
-  if (mBindingTable)
-    mBindingTable->Enumerate(FlushScopedSkinSheets);
+  if (mBindingTable) {
+    mBindingTable->EnumerateRead(FlushScopedSkinSheets, nullptr);
+  }
 }
 
 JSObject*
 nsXBLDocumentInfo::GetCompilationGlobal()
 {
   EnsureGlobalObject();
   return mGlobalObject->GetCompilationGlobal();
 }
--- a/dom/xbl/nsXBLDocumentInfo.h
+++ b/dom/xbl/nsXBLDocumentInfo.h
@@ -8,17 +8,16 @@
 #include "mozilla/Attributes.h"
 #include "nsCOMPtr.h"
 #include "nsAutoPtr.h"
 #include "nsWeakReference.h"
 #include "nsIDocument.h"
 #include "nsCycleCollectionParticipant.h"
 
 class nsXBLPrototypeBinding;
-class nsObjectHashtable;
 class nsXBLDocGlobalObject;
 
 class nsXBLDocumentInfo : public nsSupportsWeakReference
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
 
   nsXBLDocumentInfo(nsIDocument* aDocument);
@@ -36,17 +35,17 @@ public:
                                nsXBLPrototypeBinding* aBinding);
 
   // This removes the binding without deleting it
   void RemovePrototypeBinding(const nsACString& aRef);
 
   nsresult WritePrototypeBindings();
 
   void SetFirstPrototypeBinding(nsXBLPrototypeBinding* aBinding);
-  
+
   void FlushSkinStylesheets();
 
   bool IsChrome() { return mIsChrome; }
 
   JSObject* GetCompilationGlobal();
 
   void MarkInCCGeneration(uint32_t aGeneration);
 
@@ -55,17 +54,18 @@ public:
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsXBLDocumentInfo)
 
 private:
   void EnsureGlobalObject();
   nsCOMPtr<nsIDocument> mDocument;
   bool mScriptAccess;
   bool mIsChrome;
   // the binding table owns each nsXBLPrototypeBinding
-  nsObjectHashtable* mBindingTable;
+  nsAutoPtr<nsClassHashtable<nsCStringHashKey, nsXBLPrototypeBinding>> mBindingTable;
+
   // non-owning pointer to the first binding in the table
   nsXBLPrototypeBinding* mFirstBinding;
 
   nsRefPtr<nsXBLDocGlobalObject> mGlobalObject;
 };
 
 #ifdef DEBUG
 void AssertInCompilationScope();