diff --git a/dom/xbl/nsXBLDocumentInfo.cpp b/dom/xbl/nsXBLDocumentInfo.cpp index f93791c5707..eae376863b8 100644 --- a/dom/xbl/nsXBLDocumentInfo.cpp +++ b/dom/xbl/nsXBLDocumentInfo.cpp @@ -223,20 +223,22 @@ nsXBLDocGlobalObject::GetPrincipal() /* Implementation file */ -static PLDHashOperator -TraverseProtos(const nsACString &aKey, nsXBLPrototypeBinding *aProto, void* aClosure) +static bool +TraverseProtos(nsHashKey *aKey, void *aData, void* aClosure) { - nsCycleCollectionTraversalCallback *cb = + nsCycleCollectionTraversalCallback *cb = static_cast(aClosure); - aProto->Traverse(*cb); - return PL_DHASH_NEXT; + nsXBLPrototypeBinding *proto = static_cast(aData); + proto->Traverse(*cb); + return kHashEnumerateNext; } -static PLDHashOperator -UnlinkProtoJSObjects(const nsACString &aKey, nsXBLPrototypeBinding *aProto, void* aClosure) +static bool +UnlinkProtoJSObjects(nsHashKey *aKey, void *aData, void* aClosure) { - aProto->UnlinkJSObjects(); - return PL_DHASH_NEXT; + nsXBLPrototypeBinding *proto = static_cast(aData); + proto->UnlinkJSObjects(); + return kHashEnumerateNext; } struct ProtoTracer @@ -245,19 +247,20 @@ struct ProtoTracer void *mClosure; }; -static PLDHashOperator -TraceProtos(const nsACString &aKey, nsXBLPrototypeBinding *aProto, void* aClosure) +static bool +TraceProtos(nsHashKey *aKey, void *aData, void* aClosure) { ProtoTracer* closure = static_cast(aClosure); - aProto->Trace(closure->mCallbacks, closure->mClosure); - return PL_DHASH_NEXT; + nsXBLPrototypeBinding *proto = static_cast(aData); + proto->Trace(closure->mCallbacks, closure->mClosure); + return kHashEnumerateNext; } NS_IMPL_CYCLE_COLLECTION_CLASS(nsXBLDocumentInfo) NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXBLDocumentInfo) if (tmp->mBindingTable) { - tmp->mBindingTable->EnumerateRead(UnlinkProtoJSObjects, nullptr); + tmp->mBindingTable->Enumerate(UnlinkProtoJSObjects, nullptr); } NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocument) NS_IMPL_CYCLE_COLLECTION_UNLINK(mGlobalObject) @@ -270,7 +273,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXBLDocumentInfo) } NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocument) if (tmp->mBindingTable) { - tmp->mBindingTable->EnumerateRead(TraverseProtos, &cb); + tmp->mBindingTable->Enumerate(TraverseProtos, &cb); } NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGlobalObject) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS @@ -278,7 +281,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsXBLDocumentInfo) if (tmp->mBindingTable) { ProtoTracer closure = { aCallbacks, aClosure }; - tmp->mBindingTable->EnumerateRead(TraceProtos, &closure); + tmp->mBindingTable->Enumerate(TraceProtos, &closure); } NS_IMPL_CYCLE_COLLECTION_TRACE_END @@ -288,11 +291,12 @@ UnmarkXBLJSObject(void* aP, const char* aName, void* aClosure) JS::ExposeObjectToActiveJS(static_cast(aP)); } -static PLDHashOperator -UnmarkProtos(const nsACString &aKey, nsXBLPrototypeBinding *aProto, void* aClosure) +static bool +UnmarkProtos(nsHashKey* aKey, void* aData, void* aClosure) { - aProto->Trace(TraceCallbackFunc(UnmarkXBLJSObject), nullptr); - return PL_DHASH_NEXT; + nsXBLPrototypeBinding* proto = static_cast(aData); + proto->Trace(TraceCallbackFunc(UnmarkXBLJSObject), nullptr); + return kHashEnumerateNext; } void @@ -303,7 +307,7 @@ nsXBLDocumentInfo::MarkInCCGeneration(uint32_t aGeneration) } // Unmark any JS we hold if (mBindingTable) { - mBindingTable->EnumerateRead(UnmarkProtos, nullptr); + mBindingTable->Enumerate(UnmarkProtos, nullptr); } if (mGlobalObject) { mGlobalObject->UnmarkCompilationGlobal(); @@ -322,6 +326,7 @@ nsXBLDocumentInfo::nsXBLDocumentInfo(nsIDocument* aDocument) : mDocument(aDocument), mScriptAccess(true), mIsChrome(false), + mBindingTable(nullptr), mFirstBinding(nullptr) { nsIURI* uri = aDocument->GetDocumentURI(); @@ -362,7 +367,11 @@ nsXBLDocumentInfo::~nsXBLDocumentInfo() if (mGlobalObject) { mGlobalObject->ClearGlobalObjectOwner(); // just in case } - mozilla::DropJSObjects(this); + if (mBindingTable) { + delete mBindingTable; + mBindingTable = nullptr; + mozilla::DropJSObjects(this); + } } nsXBLPrototypeBinding* @@ -376,19 +385,32 @@ nsXBLDocumentInfo::GetPrototypeBinding(const nsACString& aRef) return mFirstBinding; } - return mBindingTable->Get(aRef); + const nsPromiseFlatCString& flat = PromiseFlatCString(aRef); + nsCStringKey key(flat.get()); + return static_cast(mBindingTable->Get(&key)); +} + +static bool +DeletePrototypeBinding(nsHashKey* aKey, void* aData, void* aClosure) +{ + nsXBLPrototypeBinding* binding = static_cast(aData); + delete binding; + return true; } nsresult nsXBLDocumentInfo::SetPrototypeBinding(const nsACString& aRef, nsXBLPrototypeBinding* aBinding) { if (!mBindingTable) { - mBindingTable = new nsClassHashtable(); + mBindingTable = new nsObjectHashtable(nullptr, nullptr, DeletePrototypeBinding, nullptr); + mozilla::HoldJSObjects(this); } - NS_ENSURE_STATE(!mBindingTable->Get(aRef)); - mBindingTable->Put(aRef, aBinding); + const nsPromiseFlatCString& flat = PromiseFlatCString(aRef); + nsCStringKey key(flat.get()); + NS_ENSURE_STATE(!mBindingTable->Get(&key)); + mBindingTable->Put(&key, aBinding); return NS_OK; } @@ -397,18 +419,22 @@ void nsXBLDocumentInfo::RemovePrototypeBinding(const nsACString& aRef) { if (mBindingTable) { - mBindingTable->Remove(aRef); + // Use a flat string to avoid making a copy. + const nsPromiseFlatCString& flat = PromiseFlatCString(aRef); + nsCStringKey key(flat); + mBindingTable->Remove(&key); } } // Callback to enumerate over the bindings from this document and write them // out to the cache. -static PLDHashOperator -WriteBinding(const nsACString &aKey, nsXBLPrototypeBinding *aProto, void* aClosure) +bool +WriteBinding(nsHashKey *aKey, void *aData, void* aClosure) { - aProto->Write((nsIObjectOutputStream*)aClosure); + nsXBLPrototypeBinding* binding = static_cast(aData); + binding->Write((nsIObjectOutputStream*)aClosure); - return PL_DHASH_NEXT; + return kHashEnumerateNext; } // static @@ -504,9 +530,8 @@ nsXBLDocumentInfo::WritePrototypeBindings() rv = stream->Write32(XBLBinding_Serialize_Version); NS_ENSURE_SUCCESS(rv, rv); - if (mBindingTable) { - mBindingTable->EnumerateRead(WriteBinding, stream); - } + if (mBindingTable) + mBindingTable->Enumerate(WriteBinding, stream); // write a end marker at the end rv = stream->Write8(XBLBinding_Serialize_NoMoreBindings); @@ -529,19 +554,18 @@ nsXBLDocumentInfo::SetFirstPrototypeBinding(nsXBLPrototypeBinding* aBinding) mFirstBinding = aBinding; } -static PLDHashOperator -FlushScopedSkinSheets(const nsACString &aKey, nsXBLPrototypeBinding *aProto, void* aClosure) +bool FlushScopedSkinSheets(nsHashKey* aKey, void* aData, void* aClosure) { - aProto->FlushSkinSheets(); - return PL_DHASH_NEXT; + nsXBLPrototypeBinding* proto = (nsXBLPrototypeBinding*)aData; + proto->FlushSkinSheets(); + return true; } void nsXBLDocumentInfo::FlushSkinStylesheets() { - if (mBindingTable) { - mBindingTable->EnumerateRead(FlushScopedSkinSheets, nullptr); - } + if (mBindingTable) + mBindingTable->Enumerate(FlushScopedSkinSheets); } JSObject* diff --git a/dom/xbl/nsXBLDocumentInfo.h b/dom/xbl/nsXBLDocumentInfo.h index adbb00035c2..412738a4118 100644 --- a/dom/xbl/nsXBLDocumentInfo.h +++ b/dom/xbl/nsXBLDocumentInfo.h @@ -13,6 +13,7 @@ #include "nsCycleCollectionParticipant.h" class nsXBLPrototypeBinding; +class nsObjectHashtable; class nsXBLDocGlobalObject; class nsXBLDocumentInfo : public nsSupportsWeakReference @@ -40,7 +41,7 @@ public: nsresult WritePrototypeBindings(); void SetFirstPrototypeBinding(nsXBLPrototypeBinding* aBinding); - + void FlushSkinStylesheets(); bool IsChrome() { return mIsChrome; } @@ -59,8 +60,7 @@ private: bool mScriptAccess; bool mIsChrome; // the binding table owns each nsXBLPrototypeBinding - nsAutoPtr> mBindingTable; - + nsObjectHashtable* mBindingTable; // non-owning pointer to the first binding in the table nsXBLPrototypeBinding* mFirstBinding; diff --git a/dom/xbl/nsXBLPrototypeBinding.cpp b/dom/xbl/nsXBLPrototypeBinding.cpp index fb0530bc1c2..9953a3de3d7 100644 --- a/dom/xbl/nsXBLPrototypeBinding.cpp +++ b/dom/xbl/nsXBLPrototypeBinding.cpp @@ -100,6 +100,7 @@ nsXBLPrototypeBinding::nsXBLPrototypeBinding() mKeyHandlersRegistered(false), mChromeOnlyContent(false), mResources(nullptr), + mAttributeTable(nullptr), mBaseNameSpaceID(kNameSpaceID_None) { MOZ_COUNT_CTOR(nsXBLPrototypeBinding); @@ -180,6 +181,7 @@ nsXBLPrototypeBinding::Initialize() nsXBLPrototypeBinding::~nsXBLPrototypeBinding(void) { delete mResources; + delete mAttributeTable; delete mImplementation; MOZ_COUNT_DTOR(nsXBLPrototypeBinding); } @@ -323,12 +325,14 @@ nsXBLPrototypeBinding::AttributeChanged(nsIAtom* aAttribute, { if (!mAttributeTable) return; - - InnerAttributeTable *attributesNS = mAttributeTable->Get(aNameSpaceID); + nsPRUint32Key nskey(aNameSpaceID); + nsObjectHashtable *attributesNS = static_cast(mAttributeTable->Get(&nskey)); if (!attributesNS) return; - nsXBLAttributeEntry* xblAttr = attributesNS->Get(aAttribute); + nsISupportsKey key(aAttribute); + nsXBLAttributeEntry* xblAttr = static_cast + (attributesNS->Get(&key)); if (!xblAttr) return; @@ -496,12 +500,12 @@ struct nsXBLAttrChangeData }; // XXXbz this duplicates lots of AttributeChanged -static PLDHashOperator -SetAttrs(nsISupports* aKey, nsXBLAttributeEntry* aEntry, void* aClosure) +bool SetAttrs(nsHashKey* aKey, void* aData, void* aClosure) { + nsXBLAttributeEntry* entry = static_cast(aData); nsXBLAttrChangeData* changeData = static_cast(aClosure); - nsIAtom* src = aEntry->GetSrcAttribute(); + nsIAtom* src = entry->GetSrcAttribute(); int32_t srcNs = changeData->mSrcNamespace; nsAutoString value; bool attrPresent = true; @@ -525,7 +529,7 @@ SetAttrs(nsISupports* aKey, nsXBLAttributeEntry* aEntry, void* aClosure) nsIContent* content = changeData->mProto->GetImmediateChild(nsGkAtoms::content); - nsXBLAttributeEntry* curr = aEntry; + nsXBLAttributeEntry* curr = entry; while (curr) { nsIAtom* dst = curr->GetDstAttribute(); int32_t dstNs = curr->GetDstNameSpace(); @@ -556,20 +560,21 @@ SetAttrs(nsISupports* aKey, nsXBLAttributeEntry* aEntry, void* aClosure) } } - return PL_DHASH_NEXT; + return true; } -static PLDHashOperator -SetAttrsNS(const uint32_t &aNamespace, - nsXBLPrototypeBinding::InnerAttributeTable* aXBLAttributes, - void* aClosure) +bool SetAttrsNS(nsHashKey* aKey, void* aData, void* aClosure) { - if (aXBLAttributes && aClosure) { - nsXBLAttrChangeData* changeData = static_cast(aClosure); - changeData->mSrcNamespace = aNamespace; - aXBLAttributes->EnumerateRead(SetAttrs, aClosure); + if (aData && aClosure) { + nsPRUint32Key * key = static_cast(aKey); + nsObjectHashtable* xblAttributes = + static_cast(aData); + nsXBLAttrChangeData * changeData = static_cast + (aClosure); + changeData->mSrcNamespace = key->GetValue(); + xblAttributes->Enumerate(SetAttrs, (void*)changeData); } - return PL_DHASH_NEXT; + return true; } void @@ -577,7 +582,7 @@ nsXBLPrototypeBinding::SetInitialAttributes(nsIContent* aBoundElement, nsIConten { if (mAttributeTable) { nsXBLAttrChangeData data(this, aBoundElement, aAnonymousContent); - mAttributeTable->EnumerateRead(SetAttrsNS, &data); + mAttributeTable->Enumerate(SetAttrsNS, (void*)&data); } } @@ -611,11 +616,27 @@ nsXBLPrototypeBinding::GetStyleSheets() return nullptr; } +static bool +DeleteAttributeEntry(nsHashKey* aKey, void* aData, void* aClosure) +{ + delete static_cast(aData); + return true; +} + +static bool +DeleteAttributeTable(nsHashKey* aKey, void* aData, void* aClosure) +{ + delete static_cast(aData); + return true; +} + void nsXBLPrototypeBinding::EnsureAttributeTable() { if (!mAttributeTable) { - mAttributeTable = new nsClassHashtable(4); + mAttributeTable = new nsObjectHashtable(nullptr, nullptr, + DeleteAttributeTable, + nullptr, 4); } } @@ -624,18 +645,24 @@ nsXBLPrototypeBinding::AddToAttributeTable(int32_t aSourceNamespaceID, nsIAtom* int32_t aDestNamespaceID, nsIAtom* aDestTag, nsIContent* aContent) { - InnerAttributeTable* attributesNS = mAttributeTable->Get(aSourceNamespaceID); + nsPRUint32Key nskey(aSourceNamespaceID); + nsObjectHashtable* attributesNS = + static_cast(mAttributeTable->Get(&nskey)); if (!attributesNS) { - attributesNS = new InnerAttributeTable(4); - mAttributeTable->Put(aSourceNamespaceID, attributesNS); + attributesNS = new nsObjectHashtable(nullptr, nullptr, + DeleteAttributeEntry, + nullptr, 4); + mAttributeTable->Put(&nskey, attributesNS); } nsXBLAttributeEntry* xblAttr = new nsXBLAttributeEntry(aSourceTag, aDestTag, aDestNamespaceID, aContent); - nsXBLAttributeEntry* entry = attributesNS->Get(aSourceTag); + nsISupportsKey key(aSourceTag); + nsXBLAttributeEntry* entry = static_cast + (attributesNS->Get(&key)); if (!entry) { - attributesNS->Put(aSourceTag, xblAttr); + attributesNS->Put(&key, xblAttr); } else { while (entry->GetNext()) entry = entry->GetNext(); @@ -1394,41 +1421,44 @@ struct WriteAttributeData { } }; -static PLDHashOperator -WriteAttribute(nsISupports* aKey, nsXBLAttributeEntry* aEntry, void* aClosure) +static +bool +WriteAttribute(nsHashKey *aKey, void *aData, void* aClosure) { WriteAttributeData* data = static_cast(aClosure); nsIObjectOutputStream* stream = data->stream; const int32_t srcNamespace = data->srcNamespace; + nsXBLAttributeEntry* entry = static_cast(aData); do { - if (aEntry->GetElement() == data->content) { + if (entry->GetElement() == data->content) { data->binding->WriteNamespace(stream, srcNamespace); - stream->WriteWStringZ(nsDependentAtomString(aEntry->GetSrcAttribute()).get()); - data->binding->WriteNamespace(stream, aEntry->GetDstNameSpace()); - stream->WriteWStringZ(nsDependentAtomString(aEntry->GetDstAttribute()).get()); + stream->WriteWStringZ(nsDependentAtomString(entry->GetSrcAttribute()).get()); + data->binding->WriteNamespace(stream, entry->GetDstNameSpace()); + stream->WriteWStringZ(nsDependentAtomString(entry->GetDstAttribute()).get()); } - aEntry = aEntry->GetNext(); - } while (aEntry); + entry = entry->GetNext(); + } while (entry); - return PL_DHASH_NEXT; + return kHashEnumerateNext; } // 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 PLDHashOperator -WriteAttributeNS(const uint32_t &aNamespace, - nsXBLPrototypeBinding::InnerAttributeTable* aXBLAttributes, - void* aClosure) +static +bool +WriteAttributeNS(nsHashKey *aKey, void *aData, void* aClosure) { WriteAttributeData* data = static_cast(aClosure); - data->srcNamespace = aNamespace; - aXBLAttributes->EnumerateRead(WriteAttribute, data); + data->srcNamespace = static_cast(aKey)->GetValue(); - return PL_DHASH_NEXT; + nsObjectHashtable* attributes = static_cast(aData); + attributes->Enumerate(WriteAttribute, data); + + return kHashEnumerateNext; } nsresult @@ -1512,7 +1542,7 @@ nsXBLPrototypeBinding::WriteContentNode(nsIObjectOutputStream* aStream, // Write out the attribute fowarding information if (mAttributeTable) { WriteAttributeData data(this, aStream, aNode); - mAttributeTable->EnumerateRead(WriteAttributeNS, &data); + mAttributeTable->Enumerate(WriteAttributeNS, &data); } rv = aStream->Write8(XBLBinding_Serialize_NoMoreAttributes); NS_ENSURE_SUCCESS(rv, rv); diff --git a/dom/xbl/nsXBLPrototypeBinding.h b/dom/xbl/nsXBLPrototypeBinding.h index 31eaa72e830..aa5be7e69f4 100644 --- a/dom/xbl/nsXBLPrototypeBinding.h +++ b/dom/xbl/nsXBLPrototypeBinding.h @@ -9,6 +9,7 @@ #include "nsClassHashtable.h" #include "nsCOMArray.h" #include "nsCOMPtr.h" +#include "nsHashtable.h" #include "nsICSSLoaderObserver.h" #include "nsInterfaceHashtable.h" #include "nsWeakReference.h" @@ -21,9 +22,8 @@ class nsIAtom; class nsIContent; class nsIDocument; -class nsXBLAttributeEntry; -class nsXBLBinding; class nsXBLProtoImplField; +class nsXBLBinding; // *********************************************************************/ // The XBLPrototypeBinding class @@ -245,9 +245,6 @@ public: nsIContent* aTemplChild); bool ChromeOnlyContent() { return mChromeOnlyContent; } - - typedef nsClassHashtable InnerAttributeTable; - protected: // Ensure that mAttributeTable has been created. void EnsureAttributeTable(); @@ -281,10 +278,9 @@ protected: nsXBLDocumentInfo* mXBLDocInfoWeak; // A pointer back to our doc info. Weak, since it owns us. - // 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> mAttributeTable; + 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. class IIDHashKey : public PLDHashEntryHdr {