author | Nicholas Nethercote <nnethercote@mozilla.com> |
Tue, 12 May 2015 17:33:22 -0700 | |
changeset 243622 | 6f6fd4dfe3a35c8a06548fa0e0d78d8eba08da46 |
parent 243621 | 8d4411ad492bff3a79fe372b35257eea52fb57ce |
child 243623 | a0587959d25ed24d9f87d9968814e72cbaf48f5e |
push id | 28744 |
push user | kwierso@gmail.com |
push date | Wed, 13 May 2015 18:12:16 +0000 |
treeherder | mozilla-central@324c3423deaf [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | froydnj |
bugs | 1161377 |
milestone | 41.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
|
--- a/dom/base/nsContentList.cpp +++ b/dom/base/nsContentList.cpp @@ -148,17 +148,17 @@ NS_IMPL_RELEASE_INHERITED(nsSimpleConten JSObject* nsSimpleContentList::WrapObject(JSContext *cx, JS::Handle<JSObject*> aGivenProto) { return NodeListBinding::Wrap(cx, this, aGivenProto); } // Hashtable for storing nsContentLists -static PLDHashTable gContentListHashTable; +static PLDHashTable* gContentListHashTable; #define RECENTLY_USED_CONTENT_LIST_CACHE_SIZE 31 static nsContentList* sRecentlyUsedContentLists[RECENTLY_USED_CONTENT_LIST_CACHE_SIZE] = {}; static MOZ_ALWAYS_INLINE uint32_t RecentlyUsedCacheIndex(const nsContentListKey& aKey) { @@ -210,29 +210,27 @@ NS_GetContentList(nsINode* aRootNode, { ContentListHashtableHashKey, ContentListHashtableMatchEntry, PL_DHashMoveEntryStub, PL_DHashClearEntryStub }; // Initialize the hashtable if needed. - if (!gContentListHashTable.IsInitialized()) { - PL_DHashTableInit(&gContentListHashTable, &hash_table_ops, - sizeof(ContentListHashEntry)); + if (!gContentListHashTable) { + gContentListHashTable = + new PLDHashTable(&hash_table_ops, sizeof(ContentListHashEntry)); } ContentListHashEntry *entry = nullptr; // First we look in our hashtable. Then we create a content list if needed - if (gContentListHashTable.IsInitialized()) { - entry = static_cast<ContentListHashEntry *> - (PL_DHashTableAdd(&gContentListHashTable, &hashKey, fallible)); - if (entry) - list = entry->mContentList; - } + entry = static_cast<ContentListHashEntry *> + (PL_DHashTableAdd(gContentListHashTable, &hashKey, fallible)); + if (entry) + list = entry->mContentList; if (!list) { // We need to create a ContentList and add it to our new entry, if // we have an entry nsCOMPtr<nsIAtom> xmlAtom = do_GetAtom(aTagname); nsCOMPtr<nsIAtom> htmlAtom; if (aMatchNameSpaceId == kNameSpaceID_Unknown) { nsAutoString lowercaseName; @@ -267,17 +265,17 @@ nsCacheableFuncStringNodeList::WrapObjec JSObject* nsCacheableFuncStringHTMLCollection::WrapObject(JSContext *cx, JS::Handle<JSObject*> aGivenProto) { return HTMLCollectionBinding::Wrap(cx, this, aGivenProto); } // Hashtable for storing nsCacheableFuncStringContentList -static PLDHashTable gFuncStringContentListHashTable; +static PLDHashTable* gFuncStringContentListHashTable; struct FuncStringContentListHashEntry : public PLDHashEntryHdr { nsCacheableFuncStringContentList* mContentList; }; static PLDHashNumber FuncStringContentListHashtableHashKey(PLDHashTable *table, const void *key) @@ -316,28 +314,28 @@ GetFuncStringContentList(nsINode* aRootN { FuncStringContentListHashtableHashKey, FuncStringContentListHashtableMatchEntry, PL_DHashMoveEntryStub, PL_DHashClearEntryStub }; // Initialize the hashtable if needed. - if (!gFuncStringContentListHashTable.IsInitialized()) { - PL_DHashTableInit(&gFuncStringContentListHashTable, &hash_table_ops, - sizeof(FuncStringContentListHashEntry)); + if (!gFuncStringContentListHashTable) { + gFuncStringContentListHashTable = + new PLDHashTable(&hash_table_ops, sizeof(FuncStringContentListHashEntry)); } FuncStringContentListHashEntry *entry = nullptr; // First we look in our hashtable. Then we create a content list if needed - if (gFuncStringContentListHashTable.IsInitialized()) { + if (gFuncStringContentListHashTable) { nsFuncStringCacheKey hashKey(aRootNode, aFunc, aString); entry = static_cast<FuncStringContentListHashEntry *> - (PL_DHashTableAdd(&gFuncStringContentListHashTable, &hashKey, fallible)); + (PL_DHashTableAdd(gFuncStringContentListHashTable, &hashKey, fallible)); if (entry) { list = entry->mContentList; #ifdef DEBUG MOZ_ASSERT_IF(list, list->mType == ListType::sType); #endif } } @@ -965,23 +963,24 @@ nsContentList::RemoveFromHashtable() nsDependentAtomString str(mXMLMatchAtom); nsContentListKey key(mRootNode, mMatchNameSpaceId, str); uint32_t recentlyUsedCacheIndex = RecentlyUsedCacheIndex(key); if (sRecentlyUsedContentLists[recentlyUsedCacheIndex] == this) { sRecentlyUsedContentLists[recentlyUsedCacheIndex] = nullptr; } - if (!gContentListHashTable.IsInitialized()) + if (!gContentListHashTable) return; - PL_DHashTableRemove(&gContentListHashTable, &key); + PL_DHashTableRemove(gContentListHashTable, &key); - if (gContentListHashTable.EntryCount() == 0) { - PL_DHashTableFinish(&gContentListHashTable); + if (gContentListHashTable->EntryCount() == 0) { + delete gContentListHashTable; + gContentListHashTable = nullptr; } } void nsContentList::BringSelfUpToDate(bool aDoFlush) { if (mRootNode && aDoFlush && mFlushesNeeded) { // XXX sXBL/XBL2 issue @@ -1003,25 +1002,26 @@ nsContentList::BringSelfUpToDate(bool aD nsCacheableFuncStringContentList::~nsCacheableFuncStringContentList() { RemoveFromFuncStringHashtable(); } void nsCacheableFuncStringContentList::RemoveFromFuncStringHashtable() { - if (!gFuncStringContentListHashTable.IsInitialized()) { + if (!gFuncStringContentListHashTable) { return; } nsFuncStringCacheKey key(mRootNode, mFunc, mString); - PL_DHashTableRemove(&gFuncStringContentListHashTable, &key); + PL_DHashTableRemove(gFuncStringContentListHashTable, &key); - if (gFuncStringContentListHashTable.EntryCount() == 0) { - PL_DHashTableFinish(&gFuncStringContentListHashTable); + if (gFuncStringContentListHashTable->EntryCount() == 0) { + delete gFuncStringContentListHashTable; + gFuncStringContentListHashTable = nullptr; } } #ifdef DEBUG_CONTENT_LIST void nsContentList::AssertInSync() { if (mState == LIST_DIRTY) {
--- a/dom/base/nsContentUtils.cpp +++ b/dom/base/nsContentUtils.cpp @@ -332,35 +332,35 @@ static const nsAttrValue::EnumTable kAut { 0 } }; namespace { static NS_DEFINE_CID(kParserServiceCID, NS_PARSERSERVICE_CID); static NS_DEFINE_CID(kCParserCID, NS_PARSER_CID); -static PLDHashTable sEventListenerManagersHash; +static PLDHashTable* sEventListenerManagersHash; class DOMEventListenerManagersHashReporter final : public nsIMemoryReporter { MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf) ~DOMEventListenerManagersHashReporter() {} public: NS_DECL_ISUPPORTS NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport, nsISupports* aData, bool aAnonymize) override { // We don't measure the |EventListenerManager| objects pointed to by the // entries because those references are non-owning. - int64_t amount = sEventListenerManagersHash.IsInitialized() + int64_t amount = sEventListenerManagersHash ? PL_DHashTableSizeOfExcludingThis( - &sEventListenerManagersHash, nullptr, MallocSizeOf) + sEventListenerManagersHash, nullptr, MallocSizeOf) : 0; return MOZ_COLLECT_REPORT( "explicit/dom/event-listener-managers-hash", KIND_HEAP, UNITS_BYTES, amount, "Memory used by the event listener manager's hash table."); } }; @@ -483,28 +483,28 @@ nsContentUtils::Init() NS_ENSURE_SUCCESS(rv, rv); rv = CallGetService(NS_WBRK_CONTRACTID, &sWordBreaker); NS_ENSURE_SUCCESS(rv, rv); if (!InitializeEventTable()) return NS_ERROR_FAILURE; - if (!sEventListenerManagersHash.IsInitialized()) { + if (!sEventListenerManagersHash) { static const PLDHashTableOps hash_table_ops = { PL_DHashVoidPtrKeyStub, PL_DHashMatchEntryStub, PL_DHashMoveEntryStub, EventListenerManagerHashClearEntry, EventListenerManagerHashInitEntry }; - PL_DHashTableInit(&sEventListenerManagersHash, &hash_table_ops, - sizeof(EventListenerManagerMapEntry)); + sEventListenerManagersHash = + new PLDHashTable(&hash_table_ops, sizeof(EventListenerManagerMapEntry)); RegisterStrongMemoryReporter(new DOMEventListenerManagersHashReporter()); } sBlockedScriptRunners = new nsTArray< nsCOMPtr<nsIRunnable> >; Preferences::AddBoolVarCache(&sAllowXULXBL_for_file, "dom.allow_XUL_XBL_for_file"); @@ -1805,31 +1805,32 @@ nsContentUtils::Shutdown() delete sAtomEventTable; sAtomEventTable = nullptr; delete sStringEventTable; sStringEventTable = nullptr; delete sUserDefinedEvents; sUserDefinedEvents = nullptr; - if (sEventListenerManagersHash.IsInitialized()) { - NS_ASSERTION(sEventListenerManagersHash.EntryCount() == 0, + if (sEventListenerManagersHash) { + NS_ASSERTION(sEventListenerManagersHash->EntryCount() == 0, "Event listener manager hash not empty at shutdown!"); // See comment above. // However, we have to handle this table differently. If it still // has entries, we want to leak it too, so that we can keep it alive // in case any elements are destroyed. Because if they are, we need // their event listener managers to be destroyed too, or otherwise // it could leave dangling references in DOMClassInfo's preserved // wrapper table. - if (sEventListenerManagersHash.EntryCount() == 0) { - PL_DHashTableFinish(&sEventListenerManagersHash); + if (sEventListenerManagersHash->EntryCount() == 0) { + delete sEventListenerManagersHash; + sEventListenerManagersHash = nullptr; } } NS_ASSERTION(!sBlockedScriptRunners || sBlockedScriptRunners->Length() == 0, "How'd this happen?"); delete sBlockedScriptRunners; sBlockedScriptRunners = nullptr; @@ -3984,54 +3985,54 @@ ListenerEnumerator(PLDHashTable* aTable, } } return PL_DHASH_NEXT; } void nsContentUtils::UnmarkGrayJSListenersInCCGenerationDocuments(uint32_t aGeneration) { - if (sEventListenerManagersHash.IsInitialized()) { - PL_DHashTableEnumerate(&sEventListenerManagersHash, ListenerEnumerator, + if (sEventListenerManagersHash) { + PL_DHashTableEnumerate(sEventListenerManagersHash, ListenerEnumerator, &aGeneration); } } /* static */ void nsContentUtils::TraverseListenerManager(nsINode *aNode, nsCycleCollectionTraversalCallback &cb) { - if (!sEventListenerManagersHash.IsInitialized()) { + if (!sEventListenerManagersHash) { // We're already shut down, just return. return; } EventListenerManagerMapEntry *entry = static_cast<EventListenerManagerMapEntry *> - (PL_DHashTableSearch(&sEventListenerManagersHash, aNode)); + (PL_DHashTableSearch(sEventListenerManagersHash, aNode)); if (entry) { CycleCollectionNoteChild(cb, entry->mListenerManager.get(), "[via hash] mListenerManager"); } } EventListenerManager* nsContentUtils::GetListenerManagerForNode(nsINode *aNode) { - if (!sEventListenerManagersHash.IsInitialized()) { + if (!sEventListenerManagersHash) { // We're already shut down, don't bother creating an event listener // manager. return nullptr; } EventListenerManagerMapEntry *entry = static_cast<EventListenerManagerMapEntry *> - (PL_DHashTableAdd(&sEventListenerManagersHash, aNode, fallible)); + (PL_DHashTableAdd(sEventListenerManagersHash, aNode, fallible)); if (!entry) { return nullptr; } if (!entry->mListenerManager) { entry->mListenerManager = new EventListenerManager(aNode); @@ -4043,47 +4044,47 @@ nsContentUtils::GetListenerManagerForNod EventListenerManager* nsContentUtils::GetExistingListenerManagerForNode(const nsINode *aNode) { if (!aNode->HasFlag(NODE_HAS_LISTENERMANAGER)) { return nullptr; } - if (!sEventListenerManagersHash.IsInitialized()) { + if (!sEventListenerManagersHash) { // We're already shut down, don't bother creating an event listener // manager. return nullptr; } EventListenerManagerMapEntry *entry = static_cast<EventListenerManagerMapEntry *> - (PL_DHashTableSearch(&sEventListenerManagersHash, aNode)); + (PL_DHashTableSearch(sEventListenerManagersHash, aNode)); if (entry) { return entry->mListenerManager; } return nullptr; } /* static */ void nsContentUtils::RemoveListenerManager(nsINode *aNode) { - if (sEventListenerManagersHash.IsInitialized()) { + if (sEventListenerManagersHash) { EventListenerManagerMapEntry *entry = static_cast<EventListenerManagerMapEntry *> - (PL_DHashTableSearch(&sEventListenerManagersHash, aNode)); + (PL_DHashTableSearch(sEventListenerManagersHash, aNode)); if (entry) { nsRefPtr<EventListenerManager> listenerManager; listenerManager.swap(entry->mListenerManager); // Remove the entry and *then* do operations that could cause further // modification of sEventListenerManagersHash. See bug 334177. - PL_DHashTableRawRemove(&sEventListenerManagersHash, entry); + PL_DHashTableRawRemove(sEventListenerManagersHash, entry); if (listenerManager) { listenerManager->Disconnect(); } } } } /* static */ @@ -7758,9 +7759,9 @@ nsContentUtils::FirePageShowEvent(nsIDoc } } nsCOMPtr<nsIDocument> doc = aItem->GetDocument(); NS_ASSERTION(doc, "What happened here?"); if (doc->IsShowing() == aFireIfShowing) { doc->OnPageShow(true, aChromeEventHandler); } -} \ No newline at end of file +}
--- a/dom/plugins/base/nsJSNPRuntime.cpp +++ b/dom/plugins/base/nsJSNPRuntime.cpp @@ -78,17 +78,17 @@ typedef js::HashMap<nsJSObjWrapperKey, js::SystemAllocPolicy> JSObjWrapperTable; static JSObjWrapperTable sJSObjWrappers; // Whether it's safe to iterate sJSObjWrappers. Set to true when sJSObjWrappers // has been initialized and is not currently being enumerated. static bool sJSObjWrappersAccessible = false; // Hash of NPObject wrappers that wrap NPObjects as JSObjects. -static PLDHashTable sNPObjWrappers; +static PLDHashTable* sNPObjWrappers; // Global wrapper count. This includes JSObject wrappers *and* // NPObject wrappers. When this count goes to zero, there are no more // wrappers and we can kill off hash tables etc. static int32_t sWrapperCount; // The runtime service used to register/unregister GC callbacks. nsCOMPtr<nsIJSRuntimeService> sCallbackRuntime; @@ -396,33 +396,34 @@ DestroyJSObjWrapperTable() // hash to prevent leaking it. sJSObjWrappers.finish(); sJSObjWrappersAccessible = false; } static bool CreateNPObjWrapperTable() { - MOZ_ASSERT(!sNPObjWrappers.IsInitialized()); + MOZ_ASSERT(!sNPObjWrappers); if (!RegisterGCCallbacks()) { return false; } - PL_DHashTableInit(&sNPObjWrappers, PL_DHashGetStubOps(), - sizeof(NPObjWrapperHashEntry)); + sNPObjWrappers = + new PLDHashTable(PL_DHashGetStubOps(), sizeof(NPObjWrapperHashEntry)); return true; } static void DestroyNPObjWrapperTable() { - MOZ_ASSERT(sNPObjWrappers.EntryCount() == 0); - - PL_DHashTableFinish(&sNPObjWrappers); + MOZ_ASSERT(sNPObjWrappers->EntryCount() == 0); + + delete sNPObjWrappers; + sNPObjWrappers = nullptr; } static void OnWrapperCreated() { ++sWrapperCount; } @@ -431,17 +432,17 @@ OnWrapperDestroyed() { NS_ASSERTION(sWrapperCount, "Whaaa, unbalanced created/destroyed calls!"); if (--sWrapperCount == 0) { if (sJSObjWrappersAccessible) { DestroyJSObjWrapperTable(); } - if (sNPObjWrappers.IsInitialized()) { + if (sNPObjWrappers) { // No more wrappers, and our hash was initialized. Finish the // hash to prevent leaking it. DestroyNPObjWrapperTable(); } UnregisterGCCallbacks(); } } @@ -1756,46 +1757,46 @@ NPObjWrapper_Convert(JSContext *cx, JS:: return false; } static void NPObjWrapper_Finalize(js::FreeOp *fop, JSObject *obj) { NPObject *npobj = (NPObject *)::JS_GetPrivate(obj); if (npobj) { - if (sNPObjWrappers.IsInitialized()) { - PL_DHashTableRemove(&sNPObjWrappers, npobj); + if (sNPObjWrappers) { + PL_DHashTableRemove(sNPObjWrappers, npobj); } } if (!sDelayedReleases) sDelayedReleases = new nsTArray<NPObject*>; sDelayedReleases->AppendElement(npobj); } static void NPObjWrapper_ObjectMoved(JSObject *obj, const JSObject *old) { // The wrapper JSObject has been moved, so we need to update the entry in the // sNPObjWrappers hash table, if present. - if (!sNPObjWrappers.IsInitialized()) { + if (!sNPObjWrappers) { return; } NPObject *npobj = (NPObject *)::JS_GetPrivate(obj); if (!npobj) { return; } // Calling PL_DHashTableSearch() will not result in GC. JS::AutoSuppressGCAnalysis nogc; NPObjWrapperHashEntry *entry = static_cast<NPObjWrapperHashEntry *> - (PL_DHashTableSearch(&sNPObjWrappers, npobj)); + (PL_DHashTableSearch(sNPObjWrappers, npobj)); MOZ_ASSERT(entry && entry->mJSObj); MOZ_ASSERT(entry->mJSObj == old); entry->mJSObj = obj; } static bool NPObjWrapper_Call(JSContext *cx, unsigned argc, JS::Value *vp) { @@ -1831,33 +1832,33 @@ nsNPObjWrapper::OnDestroy(NPObject *npob } if (npobj->_class == &nsJSObjWrapper::sJSObjWrapperNPClass) { // npobj is one of our own, no private data to clean up here. return; } - if (!sNPObjWrappers.IsInitialized()) { + if (!sNPObjWrappers) { // No hash yet (or any more), no used wrappers available. return; } NPObjWrapperHashEntry *entry = static_cast<NPObjWrapperHashEntry *> - (PL_DHashTableSearch(&sNPObjWrappers, npobj)); + (PL_DHashTableSearch(sNPObjWrappers, npobj)); if (entry && entry->mJSObj) { // Found a live NPObject wrapper, null out its JSObjects' private // data. ::JS_SetPrivate(entry->mJSObj, nullptr); // Remove the npobj from the hash now that it went away. - PL_DHashTableRawRemove(&sNPObjWrappers, entry); + PL_DHashTableRawRemove(sNPObjWrappers, entry); // The finalize hook will call OnWrapperDestroyed(). } } // Look up or create a JSObject that wraps the NPObject npobj. // static @@ -1881,25 +1882,25 @@ nsNPObjWrapper::GetNewOrUsed(NPP npp, JS } if (!npp) { NS_ERROR("No npp passed to nsNPObjWrapper::GetNewOrUsed()!"); return nullptr; } - if (!sNPObjWrappers.IsInitialized()) { + if (!sNPObjWrappers) { // No hash yet (or any more), initialize it. if (!CreateNPObjWrapperTable()) { return nullptr; } } NPObjWrapperHashEntry *entry = static_cast<NPObjWrapperHashEntry *> - (PL_DHashTableAdd(&sNPObjWrappers, npobj, fallible)); + (PL_DHashTableAdd(sNPObjWrappers, npobj, fallible)); if (!entry) { // Out of memory JS_ReportOutOfMemory(cx); return nullptr; } @@ -1911,34 +1912,34 @@ nsNPObjWrapper::GetNewOrUsed(NPP npp, JS return nullptr; } return obj; } entry->mNPObj = npobj; entry->mNpp = npp; - uint32_t generation = sNPObjWrappers.Generation(); + uint32_t generation = sNPObjWrappers->Generation(); // No existing JSObject, create one. JS::Rooted<JSObject*> obj(cx, ::JS_NewObject(cx, js::Jsvalify(&sNPObjectJSWrapperClass))); - if (generation != sNPObjWrappers.Generation()) { + if (generation != sNPObjWrappers->Generation()) { // Reload entry if the JS_NewObject call caused a GC and reallocated // the table (see bug 445229). This is guaranteed to succeed. - NS_ASSERTION(PL_DHashTableSearch(&sNPObjWrappers, npobj), + NS_ASSERTION(PL_DHashTableSearch(sNPObjWrappers, npobj), "Hashtable didn't find what we just added?"); } if (!obj) { // OOM? Remove the stale entry from the hash. - PL_DHashTableRawRemove(&sNPObjWrappers, entry); + PL_DHashTableRawRemove(sNPObjWrappers, entry); return nullptr; } OnWrapperCreated(); entry->mJSObj = obj; @@ -2034,19 +2035,19 @@ nsJSNPRuntime::OnPluginDestroy(NPP npp) } sJSObjWrappersAccessible = true; } // Use the safe JSContext here as we're not always able to find the // JSContext associated with the NPP any more. AutoSafeJSContext cx; - if (sNPObjWrappers.IsInitialized()) { + if (sNPObjWrappers) { NppAndCx nppcx = { npp, cx }; - PL_DHashTableEnumerate(&sNPObjWrappers, + PL_DHashTableEnumerate(sNPObjWrappers, NPObjWrapperPluginDestroyedCallback, &nppcx); } } // static void nsJSNPRuntime::OnPluginDestroyPending(NPP npp) { @@ -2069,17 +2070,17 @@ static NPP LookupNPP(NPObject *npobj) { if (npobj->_class == &nsJSObjWrapper::sJSObjWrapperNPClass) { nsJSObjWrapper* o = static_cast<nsJSObjWrapper*>(npobj); return o->mNpp; } NPObjWrapperHashEntry *entry = static_cast<NPObjWrapperHashEntry *> - (PL_DHashTableAdd(&sNPObjWrappers, npobj, fallible)); + (PL_DHashTableAdd(sNPObjWrappers, npobj, fallible)); if (!entry) { return nullptr; } NS_ASSERTION(entry->mNpp, "Live NPObject entry w/o an NPP!"); return entry->mNpp;
--- a/modules/libpref/Preferences.cpp +++ b/modules/libpref/Preferences.cpp @@ -230,20 +230,20 @@ SizeOfObserverEntryExcludingThis(ValueOb // Although this is a member of Preferences, it measures sPreferences and // several other global structures. /* static */ int64_t Preferences::SizeOfIncludingThisAndOtherStuff(mozilla::MallocSizeOf aMallocSizeOf) { NS_ENSURE_TRUE(InitStaticMembers(), 0); size_t n = aMallocSizeOf(sPreferences); - if (gHashTable.IsInitialized()) { + if (gHashTable) { // pref keys are allocated in a private arena, which we count elsewhere. // pref stringvals are allocated out of the same private arena. - n += PL_DHashTableSizeOfExcludingThis(&gHashTable, nullptr, aMallocSizeOf); + n += PL_DHashTableSizeOfExcludingThis(gHashTable, nullptr, aMallocSizeOf); } if (gCacheData) { n += gCacheData->SizeOfIncludingThis(aMallocSizeOf); for (uint32_t i = 0, count = gCacheData->Length(); i < count; ++i) { n += aMallocSizeOf((*gCacheData)[i]); } } if (gObserverTable) { @@ -733,18 +733,18 @@ Preferences::GetPreference(PrefSetting* return; pref_GetPrefFromEntry(entry, aPref); } void Preferences::GetPreferences(InfallibleTArray<PrefSetting>* aPrefs) { - aPrefs->SetCapacity(gHashTable.Capacity()); - PL_DHashTableEnumerate(&gHashTable, pref_GetPrefs, aPrefs); + aPrefs->SetCapacity(gHashTable->Capacity()); + PL_DHashTableEnumerate(gHashTable, pref_GetPrefs, aPrefs); } NS_IMETHODIMP Preferences::GetBranch(const char *aPrefRoot, nsIPrefBranch **_retval) { nsresult rv; if ((nullptr != aPrefRoot) && (*aPrefRoot != '\0')) { @@ -939,47 +939,48 @@ Preferences::WritePrefFile(nsIFile* aFil NS_LINEBREAK NS_LINEBREAK; nsCOMPtr<nsIOutputStream> outStreamSink; nsCOMPtr<nsIOutputStream> outStream; uint32_t writeAmount; nsresult rv; - if (!gHashTable.IsInitialized()) + if (!gHashTable) return NS_ERROR_NOT_INITIALIZED; // execute a "safe" save by saving through a tempfile rv = NS_NewSafeLocalFileOutputStream(getter_AddRefs(outStreamSink), aFile, -1, 0600); if (NS_FAILED(rv)) return rv; rv = NS_NewBufferedOutputStream(getter_AddRefs(outStream), outStreamSink, 4096); if (NS_FAILED(rv)) return rv; - nsAutoArrayPtr<char*> valueArray(new char*[gHashTable.EntryCount()]); - memset(valueArray, 0, gHashTable.EntryCount() * sizeof(char*)); + nsAutoArrayPtr<char*> valueArray(new char*[gHashTable->EntryCount()]); + memset(valueArray, 0, gHashTable->EntryCount() * sizeof(char*)); pref_saveArgs saveArgs; saveArgs.prefArray = valueArray; saveArgs.saveTypes = SAVE_ALL; - + // get the lines that we're supposed to be writing to the file - PL_DHashTableEnumerate(&gHashTable, pref_savePref, &saveArgs); - + PL_DHashTableEnumerate(gHashTable, pref_savePref, &saveArgs); + /* Sort the preferences to make a readable file on disk */ - NS_QuickSort(valueArray, gHashTable.EntryCount(), sizeof(char *), pref_CompareStrings, nullptr); - + NS_QuickSort(valueArray, gHashTable->EntryCount(), sizeof(char *), + pref_CompareStrings, nullptr); + // write out the file header outStream->Write(outHeader, sizeof(outHeader) - 1, &writeAmount); char** walker = valueArray; - for (uint32_t valueIdx = 0; valueIdx < gHashTable.EntryCount(); valueIdx++, walker++) { + for (uint32_t valueIdx = 0; valueIdx < gHashTable->EntryCount(); valueIdx++, walker++) { if (*walker) { outStream->Write(*walker, strlen(*walker), &writeAmount); outStream->Write(NS_LINEBREAK, NS_LINEBREAK_LEN, &writeAmount); free(*walker); } } // tell the safe output stream to overwrite the real prefs file
--- a/modules/libpref/nsPrefBranch.cpp +++ b/modules/libpref/nsPrefBranch.cpp @@ -550,25 +550,25 @@ NS_IMETHODIMP nsPrefBranch::GetChildList NS_ENSURE_ARG(aStartingAt); NS_ENSURE_ARG_POINTER(aCount); NS_ENSURE_ARG_POINTER(aChildArray); *aChildArray = nullptr; *aCount = 0; - if (!gHashTable.IsInitialized()) + if (!gHashTable->IsInitialized()) return NS_ERROR_NOT_INITIALIZED; // this will contain a list of all the pref name strings // allocate on the stack for speed - + ed.parent = getPrefName(aStartingAt); ed.pref_list = &prefArray; - PL_DHashTableEnumerate(&gHashTable, pref_enumChild, &ed); + PL_DHashTableEnumerate(gHashTable, pref_enumChild, &ed); // now that we've built up the list, run the callback on // all the matching elements numPrefs = prefArray.Length(); if (numPrefs) { outArray = (char **)moz_xmalloc(numPrefs * sizeof(char *)); if (!outArray)
--- a/modules/libpref/prefapi.cpp +++ b/modules/libpref/prefapi.cpp @@ -63,17 +63,17 @@ matchPrefEntry(PLDHashTable*, const PLDH if (prefEntry->key == key) return true; if (!prefEntry->key || !key) return false; const char *otherKey = reinterpret_cast<const char*>(key); return (strcmp(prefEntry->key, otherKey) == 0); } -PLDHashTable gHashTable; +PLDHashTable* gHashTable; static PLArenaPool gPrefNameArena; bool gDirty = false; static struct CallbackNode* gCallbacks = nullptr; static bool gIsAnyPrefLocked = false; // These are only used during the call to pref_DoCallback static bool gCallbacksInProgress = false; static bool gShouldCleanupDeadNodes = false; @@ -144,19 +144,20 @@ enum { kPrefStickyDefault = 4, }; static nsresult pref_HashPref(const char *key, PrefValue value, PrefType type, uint32_t flags); #define PREF_HASHTABLE_INITIAL_LENGTH 1024 nsresult PREF_Init() { - if (!gHashTable.IsInitialized()) { - PL_DHashTableInit(&gHashTable, &pref_HashTableOps, - sizeof(PrefHashEntry), PREF_HASHTABLE_INITIAL_LENGTH); + if (!gHashTable) { + gHashTable = new PLDHashTable(&pref_HashTableOps, + sizeof(PrefHashEntry), + PREF_HASHTABLE_INITIAL_LENGTH); PL_INIT_ARENA_POOL(&gPrefNameArena, "PrefNameArena", PREFNAME_ARENA_SIZE); } return NS_OK; } /* Frees the callback list. */ @@ -177,18 +178,19 @@ void PREF_Cleanup() gCallbacks = nullptr; PREF_CleanupPrefs(); } /* Frees up all the objects except the callback list. */ void PREF_CleanupPrefs() { - if (gHashTable.IsInitialized()) { - PL_DHashTableFinish(&gHashTable); + if (gHashTable) { + delete gHashTable; + gHashTable = nullptr; PL_FinishArenaPool(&gPrefNameArena); } } // note that this appends to aResult, and does not assign! static void str_escape(const char * original, nsAFlatCString& aResult) { /* JavaScript does not allow quotes, slashes, or line terminators inside @@ -461,31 +463,31 @@ pref_CompareStrings(const void *v1, cons else if (!s2) return 1; else return strcmp(s1, s2); } bool PREF_HasUserPref(const char *pref_name) { - if (!gHashTable.IsInitialized()) + if (!gHashTable) return false; PrefHashEntry *pref = pref_HashTableLookup(pref_name); if (!pref) return false; /* convert PREF_HAS_USER_VALUE to bool */ return (PREF_HAS_USER_VALUE(pref) != 0); } nsresult PREF_CopyCharPref(const char *pref_name, char ** return_buffer, bool get_default) { - if (!gHashTable.IsInitialized()) + if (!gHashTable) return NS_ERROR_NOT_INITIALIZED; nsresult rv = NS_ERROR_UNEXPECTED; char* stringVal; PrefHashEntry* pref = pref_HashTableLookup(pref_name); if (pref && (pref->flags & PREF_STRING)) { @@ -499,17 +501,17 @@ PREF_CopyCharPref(const char *pref_name, rv = NS_OK; } } return rv; } nsresult PREF_GetIntPref(const char *pref_name,int32_t * return_int, bool get_default) { - if (!gHashTable.IsInitialized()) + if (!gHashTable) return NS_ERROR_NOT_INITIALIZED; nsresult rv = NS_ERROR_UNEXPECTED; PrefHashEntry* pref = pref_HashTableLookup(pref_name); if (pref && (pref->flags & PREF_INT)) { if (get_default || PREF_IS_LOCKED(pref) || !PREF_HAS_USER_VALUE(pref)) { @@ -523,17 +525,17 @@ nsresult PREF_GetIntPref(const char *pre *return_int = pref->userPref.intVal; rv = NS_OK; } return rv; } nsresult PREF_GetBoolPref(const char *pref_name, bool * return_value, bool get_default) { - if (!gHashTable.IsInitialized()) + if (!gHashTable) return NS_ERROR_NOT_INITIALIZED; nsresult rv = NS_ERROR_UNEXPECTED; PrefHashEntry* pref = pref_HashTableLookup(pref_name); //NS_ASSERTION(pref, pref_name); if (pref && (pref->flags & PREF_BOOL)) { if (get_default || PREF_IS_LOCKED(pref) || !PREF_HAS_USER_VALUE(pref)) @@ -574,49 +576,49 @@ nsresult PREF_DeleteBranch(const char *branch_name) { #ifndef MOZ_B2G MOZ_ASSERT(NS_IsMainThread()); #endif int len = (int)strlen(branch_name); - if (!gHashTable.IsInitialized()) + if (!gHashTable) return NS_ERROR_NOT_INITIALIZED; /* The following check insures that if the branch name already has a "." * at the end, we don't end up with a "..". This fixes an incompatibility * between nsIPref, which needs the period added, and nsIPrefBranch which * does not. When nsIPref goes away this function should be fixed to * never add the period at all. */ nsAutoCString branch_dot(branch_name); if ((len > 1) && branch_name[len - 1] != '.') branch_dot += '.'; - PL_DHashTableEnumerate(&gHashTable, pref_DeleteItem, + PL_DHashTableEnumerate(gHashTable, pref_DeleteItem, (void*) branch_dot.get()); gDirty = true; return NS_OK; } nsresult PREF_ClearUserPref(const char *pref_name) { - if (!gHashTable.IsInitialized()) + if (!gHashTable) return NS_ERROR_NOT_INITIALIZED; PrefHashEntry* pref = pref_HashTableLookup(pref_name); if (pref && PREF_HAS_USER_VALUE(pref)) { pref->flags &= ~PREF_USERSET; if (!(pref->flags & PREF_HAS_DEFAULT)) { - PL_DHashTableRemove(&gHashTable, pref_name); + PL_DHashTableRemove(gHashTable, pref_name); } pref_DoCallback(pref_name); gDirty = true; } return NS_OK; } @@ -642,33 +644,33 @@ pref_ClearUserPref(PLDHashTable *table, nsresult PREF_ClearAllUserPrefs() { #ifndef MOZ_B2G MOZ_ASSERT(NS_IsMainThread()); #endif - if (!gHashTable.IsInitialized()) + if (!gHashTable) return NS_ERROR_NOT_INITIALIZED; std::vector<std::string> prefStrings; - PL_DHashTableEnumerate(&gHashTable, pref_ClearUserPref, static_cast<void*>(&prefStrings)); + PL_DHashTableEnumerate(gHashTable, pref_ClearUserPref, static_cast<void*>(&prefStrings)); for (std::string& prefString : prefStrings) { pref_DoCallback(prefString.c_str()); } gDirty = true; return NS_OK; } nsresult PREF_LockPref(const char *key, bool lockit) { - if (!gHashTable.IsInitialized()) + if (!gHashTable) return NS_ERROR_NOT_INITIALIZED; PrefHashEntry* pref = pref_HashTableLookup(key); if (!pref) return NS_ERROR_UNEXPECTED; if (lockit) { if (!PREF_IS_LOCKED(pref)) @@ -729,30 +731,30 @@ static void pref_SetValue(PrefValue* exi } PrefHashEntry* pref_HashTableLookup(const void *key) { #ifndef MOZ_B2G MOZ_ASSERT(NS_IsMainThread()); #endif - return static_cast<PrefHashEntry*>(PL_DHashTableSearch(&gHashTable, key)); + return static_cast<PrefHashEntry*>(PL_DHashTableSearch(gHashTable, key)); } nsresult pref_HashPref(const char *key, PrefValue value, PrefType type, uint32_t flags) { #ifndef MOZ_B2G MOZ_ASSERT(NS_IsMainThread()); #endif - if (!gHashTable.IsInitialized()) + if (!gHashTable) return NS_ERROR_OUT_OF_MEMORY; PrefHashEntry* pref = static_cast<PrefHashEntry*> - (PL_DHashTableAdd(&gHashTable, key, fallible)); + (PL_DHashTableAdd(gHashTable, key, fallible)); if (!pref) return NS_ERROR_OUT_OF_MEMORY; // new entry, better initialize if (!pref->key) { // initialize the pref entry @@ -834,18 +836,17 @@ pref_SizeOfPrivateData(MallocSizeOf aMal n += aMallocSizeOf(node->domain); } return n; } PrefType PREF_GetPrefType(const char *pref_name) { - if (gHashTable.IsInitialized()) - { + if (gHashTable) { PrefHashEntry* pref = pref_HashTableLookup(pref_name); if (pref) { if (pref->flags & PREF_STRING) return PREF_STRING; else if (pref->flags & PREF_INT) return PREF_INT; else if (pref->flags & PREF_BOOL) @@ -856,17 +857,17 @@ PREF_GetPrefType(const char *pref_name) } /* -- */ bool PREF_PrefIsLocked(const char *pref_name) { bool result = false; - if (gIsAnyPrefLocked && gHashTable.IsInitialized()) { + if (gIsAnyPrefLocked && gHashTable) { PrefHashEntry* pref = pref_HashTableLookup(pref_name); if (pref && PREF_IS_LOCKED(pref)) result = true; } return result; }
--- a/modules/libpref/prefapi_private_data.h +++ b/modules/libpref/prefapi_private_data.h @@ -5,18 +5,18 @@ /* Data shared between prefapi.c and nsPref.cpp */ #ifndef prefapi_private_data_h #define prefapi_private_data_h #include "mozilla/MemoryReporting.h" -extern PLDHashTable gHashTable; -extern bool gDirty; +extern PLDHashTable* gHashTable; +extern bool gDirty; namespace mozilla { namespace dom { class PrefSetting; } } enum pref_SaveTypes { SAVE_NONSHARED, SAVE_SHARED, SAVE_ALL, SAVE_ALL_AND_DEFAULTS };
--- a/netwerk/protocol/http/nsHttp.cpp +++ b/netwerk/protocol/http/nsHttp.cpp @@ -35,17 +35,17 @@ enum { // the atom table is destroyed. The structure and value string are allocated // as one contiguous block. struct HttpHeapAtom { struct HttpHeapAtom *next; char value[1]; }; -static PLDHashTable sAtomTable; +static PLDHashTable *sAtomTable; static struct HttpHeapAtom *sHeapAtoms = nullptr; static Mutex *sLock = nullptr; HttpHeapAtom * NewHeapAtom(const char *value) { int len = strlen(value); HttpHeapAtom *a = @@ -89,87 +89,84 @@ static const PLDHashTableOps ops = { PL_DHashClearEntryStub, nullptr }; // We put the atoms in a hash table for speedy lookup.. see ResolveAtom. nsresult nsHttp::CreateAtomTable() { - MOZ_ASSERT(!sAtomTable.IsInitialized(), "atom table already initialized"); + MOZ_ASSERT(!sAtomTable, "atom table already initialized"); if (!sLock) { sLock = new Mutex("nsHttp.sLock"); } // The initial length for this table is a value greater than the number of // known atoms (NUM_HTTP_ATOMS) because we expect to encounter a few random // headers right off the bat. - PL_DHashTableInit(&sAtomTable, &ops, sizeof(PLDHashEntryStub), - NUM_HTTP_ATOMS + 10); + sAtomTable = new PLDHashTable(&ops, sizeof(PLDHashEntryStub), + NUM_HTTP_ATOMS + 10); // fill the table with our known atoms const char *const atoms[] = { #define HTTP_ATOM(_name, _value) nsHttp::_name._val, #include "nsHttpAtomList.h" #undef HTTP_ATOM nullptr }; for (int i = 0; atoms[i]; ++i) { PLDHashEntryStub *stub = reinterpret_cast<PLDHashEntryStub *> - (PL_DHashTableAdd(&sAtomTable, atoms[i], fallible)); + (PL_DHashTableAdd(sAtomTable, atoms[i], fallible)); if (!stub) return NS_ERROR_OUT_OF_MEMORY; MOZ_ASSERT(!stub->key, "duplicate static atom"); stub->key = atoms[i]; } return NS_OK; } void nsHttp::DestroyAtomTable() { - if (sAtomTable.IsInitialized()) { - PL_DHashTableFinish(&sAtomTable); - } + delete sAtomTable; + sAtomTable = nullptr; while (sHeapAtoms) { HttpHeapAtom *next = sHeapAtoms->next; free(sHeapAtoms); sHeapAtoms = next; } - if (sLock) { - delete sLock; - sLock = nullptr; - } + delete sLock; + sLock = nullptr; } Mutex * nsHttp::GetLock() { return sLock; } // this function may be called from multiple threads nsHttpAtom nsHttp::ResolveAtom(const char *str) { nsHttpAtom atom = { nullptr }; - if (!str || !sAtomTable.IsInitialized()) + if (!str || !sAtomTable) return atom; MutexAutoLock lock(*sLock); PLDHashEntryStub *stub = reinterpret_cast<PLDHashEntryStub *> - (PL_DHashTableAdd(&sAtomTable, str, fallible)); + (PL_DHashTableAdd(sAtomTable, str, fallible)); if (!stub) return atom; // out of memory if (stub->key) { atom._val = reinterpret_cast<const char *>(stub->key); return atom; }
--- a/parser/htmlparser/nsHTMLEntities.cpp +++ b/parser/htmlparser/nsHTMLEntities.cpp @@ -2,18 +2,16 @@ /* 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 "mozilla/ArrayUtils.h" #include "nsHTMLEntities.h" - - #include "nsString.h" #include "nsCRT.h" #include "pldhash.h" using namespace mozilla; struct EntityNode { const char* mStr; // never owns buffer @@ -62,102 +60,101 @@ static const PLDHashTableOps EntityToUni static const PLDHashTableOps UnicodeToEntityOps = { hashUnicodeValue, matchNodeUnicode, PL_DHashMoveEntryStub, PL_DHashClearEntryStub, nullptr, }; -static PLDHashTable gEntityToUnicode; -static PLDHashTable gUnicodeToEntity; +static PLDHashTable* gEntityToUnicode; +static PLDHashTable* gUnicodeToEntity; static nsrefcnt gTableRefCnt = 0; #define HTML_ENTITY(_name, _value) { #_name, _value }, static const EntityNode gEntityArray[] = { #include "nsHTMLEntityList.h" }; #undef HTML_ENTITY #define NS_HTML_ENTITY_COUNT ((int32_t)ArrayLength(gEntityArray)) nsresult nsHTMLEntities::AddRefTable(void) { if (!gTableRefCnt) { - PL_DHashTableInit(&gEntityToUnicode, &EntityToUnicodeOps, - sizeof(EntityNodeEntry), NS_HTML_ENTITY_COUNT); - PL_DHashTableInit(&gUnicodeToEntity, &UnicodeToEntityOps, - sizeof(EntityNodeEntry), NS_HTML_ENTITY_COUNT); + gEntityToUnicode = new PLDHashTable(&EntityToUnicodeOps, + sizeof(EntityNodeEntry), + NS_HTML_ENTITY_COUNT); + gUnicodeToEntity = new PLDHashTable(&UnicodeToEntityOps, + sizeof(EntityNodeEntry), + NS_HTML_ENTITY_COUNT); for (const EntityNode *node = gEntityArray, *node_end = ArrayEnd(gEntityArray); node < node_end; ++node) { // add to Entity->Unicode table EntityNodeEntry* entry = static_cast<EntityNodeEntry*> - (PL_DHashTableAdd(&gEntityToUnicode, node->mStr, fallible)); + (PL_DHashTableAdd(gEntityToUnicode, node->mStr, fallible)); NS_ASSERTION(entry, "Error adding an entry"); // Prefer earlier entries when we have duplication. if (!entry->node) entry->node = node; // add to Unicode->Entity table entry = static_cast<EntityNodeEntry*> - (PL_DHashTableAdd(&gUnicodeToEntity, + (PL_DHashTableAdd(gUnicodeToEntity, NS_INT32_TO_PTR(node->mUnicode), fallible)); NS_ASSERTION(entry, "Error adding an entry"); // Prefer earlier entries when we have duplication. if (!entry->node) entry->node = node; } #ifdef DEBUG - PL_DHashMarkTableImmutable(&gUnicodeToEntity); - PL_DHashMarkTableImmutable(&gEntityToUnicode); + PL_DHashMarkTableImmutable(gUnicodeToEntity); + PL_DHashMarkTableImmutable(gEntityToUnicode); #endif } ++gTableRefCnt; return NS_OK; } void nsHTMLEntities::ReleaseTable(void) { if (--gTableRefCnt != 0) return; - if (gEntityToUnicode.IsInitialized()) { - PL_DHashTableFinish(&gEntityToUnicode); - } - if (gUnicodeToEntity.IsInitialized()) { - PL_DHashTableFinish(&gUnicodeToEntity); - } + delete gEntityToUnicode; + delete gUnicodeToEntity; + gEntityToUnicode = nullptr; + gUnicodeToEntity = nullptr; } int32_t nsHTMLEntities::EntityToUnicode(const nsCString& aEntity) { - NS_ASSERTION(gEntityToUnicode.IsInitialized(), - "no lookup table, needs addref"); - if (!gEntityToUnicode.IsInitialized()) + NS_ASSERTION(gEntityToUnicode, "no lookup table, needs addref"); + if (!gEntityToUnicode) return -1; //this little piece of code exists because entities may or may not have the terminating ';'. //if we see it, strip if off for this test... if(';'==aEntity.Last()) { nsAutoCString temp(aEntity); temp.Truncate(aEntity.Length()-1); return EntityToUnicode(temp); } EntityNodeEntry* entry = static_cast<EntityNodeEntry*> - (PL_DHashTableSearch(&gEntityToUnicode, aEntity.get())); + (PL_DHashTableSearch(gEntityToUnicode, aEntity.get())); return entry ? entry->node->mUnicode : -1; } int32_t nsHTMLEntities::EntityToUnicode(const nsAString& aEntity) { nsAutoCString theEntity; theEntity.AssignWithConversion(aEntity); @@ -167,21 +164,20 @@ nsHTMLEntities::EntityToUnicode(const ns return EntityToUnicode(theEntity); } const char* nsHTMLEntities::UnicodeToEntity(int32_t aUnicode) { - NS_ASSERTION(gUnicodeToEntity.IsInitialized(), - "no lookup table, needs addref"); + NS_ASSERTION(gUnicodeToEntity, "no lookup table, needs addref"); EntityNodeEntry* entry = static_cast<EntityNodeEntry*> - (PL_DHashTableSearch(&gUnicodeToEntity, NS_INT32_TO_PTR(aUnicode))); + (PL_DHashTableSearch(gUnicodeToEntity, NS_INT32_TO_PTR(aUnicode))); return entry ? entry->node->mStr : nullptr; } #ifdef DEBUG #include <stdio.h> class nsTestEntityTable {
--- a/xpcom/ds/nsAtomTable.cpp +++ b/xpcom/ds/nsAtomTable.cpp @@ -36,17 +36,17 @@ using namespace mozilla; /** * The shared hash table for atom lookups. * * XXX This should be manipulated in a threadsafe way or we should make * sure it's only manipulated from the main thread. Probably the latter * is better, since the former would hurt performance. */ -static PLDHashTable gAtomTable; +static PLDHashTable* gAtomTable; class StaticAtomEntry : public PLDHashEntryHdr { public: typedef const nsAString& KeyType; typedef const nsAString* KeyTypePointer; explicit StaticAtomEntry(KeyTypePointer aKey) {} @@ -331,29 +331,31 @@ PromoteToPermanent(AtomImpl* aAtom) #endif aAtom = new (aAtom) PermanentAtomImpl(); } void NS_PurgeAtomTable() { delete gStaticAtomTable; + gStaticAtomTable = nullptr; - if (gAtomTable.IsInitialized()) { + if (gAtomTable) { #ifdef DEBUG const char* dumpAtomLeaks = PR_GetEnv("MOZ_DUMP_ATOM_LEAKS"); if (dumpAtomLeaks && *dumpAtomLeaks) { uint32_t leaked = 0; printf("*** %d atoms still exist (including permanent):\n", - gAtomTable.EntryCount()); - PL_DHashTableEnumerate(&gAtomTable, DumpAtomLeaks, &leaked); + gAtomTable->EntryCount()); + PL_DHashTableEnumerate(gAtomTable, DumpAtomLeaks, &leaked); printf("*** %u non-permanent atoms leaked\n", leaked); } #endif - PL_DHashTableFinish(&gAtomTable); + delete gAtomTable; + gAtomTable = nullptr; } } AtomImpl::AtomImpl(const nsAString& aString, uint32_t aHash) { mLength = aString.Length(); nsRefPtr<nsStringBuffer> buf = nsStringBuffer::FromString(aString); if (buf) { @@ -392,27 +394,26 @@ AtomImpl::AtomImpl(nsStringBuffer* aStri NS_ASSERTION(mString[mLength] == char16_t(0), "null terminated"); NS_ASSERTION(aStringBuffer && aStringBuffer->StorageSize() == (mLength + 1) * sizeof(char16_t), "correct storage"); } AtomImpl::~AtomImpl() { - NS_PRECONDITION(gAtomTable.IsInitialized(), "uninitialized atom hashtable"); + MOZ_ASSERT(gAtomTable, "uninitialized atom hashtable"); // Permanent atoms are removed from the hashtable at shutdown, and we // don't want to remove them twice. See comment above in // |AtomTableClearEntry|. if (!IsPermanentInDestructor()) { AtomTableKey key(mString, mLength, mHash); - PL_DHashTableRemove(&gAtomTable, &key); - if (gAtomTable.IsInitialized() && gAtomTable.EntryCount() == 0) { - PL_DHashTableFinish(&gAtomTable); - NS_ASSERTION(gAtomTable.EntryCount() == 0, - "PL_DHashTableFinish changed the entry count"); + PL_DHashTableRemove(gAtomTable, &key); + if (gAtomTable->EntryCount() == 0) { + delete gAtomTable; + gAtomTable = nullptr; } } nsStringBuffer::FromData(mString)->Release(); } NS_IMPL_ISUPPORTS(AtomImpl, nsIAtom) @@ -518,58 +519,58 @@ SizeOfAtomTableEntryExcludingThis(PLDHas AtomTableEntry* entry = static_cast<AtomTableEntry*>(aHdr); return entry->mAtom->SizeOfIncludingThis(aMallocSizeOf); } void NS_SizeOfAtomTablesIncludingThis(MallocSizeOf aMallocSizeOf, size_t* aMain, size_t* aStatic) { - *aMain = gAtomTable.IsInitialized() - ? PL_DHashTableSizeOfExcludingThis(&gAtomTable, + *aMain = gAtomTable + ? PL_DHashTableSizeOfExcludingThis(gAtomTable, SizeOfAtomTableEntryExcludingThis, aMallocSizeOf) : 0; // The atoms in the this table are almost certainly stored in static data, so // we don't need a SizeOfEntry function. *aStatic = gStaticAtomTable ? gStaticAtomTable->SizeOfIncludingThis(nullptr, aMallocSizeOf) : 0; } #define ATOM_HASHTABLE_INITIAL_LENGTH 2048 static inline void EnsureTableExists() { - if (!gAtomTable.IsInitialized()) { - PL_DHashTableInit(&gAtomTable, &AtomTableOps, - sizeof(AtomTableEntry), ATOM_HASHTABLE_INITIAL_LENGTH); + if (!gAtomTable) { + gAtomTable = new PLDHashTable(&AtomTableOps, sizeof(AtomTableEntry), + ATOM_HASHTABLE_INITIAL_LENGTH); } } static inline AtomTableEntry* GetAtomHashEntry(const char* aString, uint32_t aLength, uint32_t* aHashOut) { MOZ_ASSERT(NS_IsMainThread(), "wrong thread"); EnsureTableExists(); AtomTableKey key(aString, aLength, aHashOut); // This is an infallible add. - return static_cast<AtomTableEntry*>(PL_DHashTableAdd(&gAtomTable, &key)); + return static_cast<AtomTableEntry*>(PL_DHashTableAdd(gAtomTable, &key)); } static inline AtomTableEntry* GetAtomHashEntry(const char16_t* aString, uint32_t aLength, uint32_t* aHashOut) { MOZ_ASSERT(NS_IsMainThread(), "wrong thread"); EnsureTableExists(); AtomTableKey key(aString, aLength, aHashOut); // This is an infallible add. - return static_cast<AtomTableEntry*>(PL_DHashTableAdd(&gAtomTable, &key)); + return static_cast<AtomTableEntry*>(PL_DHashTableAdd(gAtomTable, &key)); } class CheckStaticAtomSizes { CheckStaticAtomSizes() { static_assert((sizeof(nsFakeStringBuffer<1>().mRefCnt) == sizeof(nsStringBuffer().mRefCount)) && @@ -704,17 +705,18 @@ NS_NewPermanentAtom(const nsAString& aUT // No need to addref since permanent atoms aren't refcounted anyway return atom; } nsrefcnt NS_GetNumberOfAtoms(void) { - return gAtomTable.EntryCount(); + MOZ_ASSERT(gAtomTable); + return gAtomTable->EntryCount(); } nsIAtom* NS_GetStaticAtom(const nsAString& aUTF16String) { NS_PRECONDITION(gStaticAtomTable, "Static atom table not created yet."); NS_PRECONDITION(gStaticAtomTableSealed, "Static atom table not sealed yet."); StaticAtomEntry* entry = gStaticAtomTable->GetEntry(aUTF16String);