Bug 1123151 (part 2) - Add PLDHashTable::IsInitialized(). r=froydnj.
authorNicholas Nethercote <nnethercote@mozilla.com>
Mon, 19 Jan 2015 16:11:34 -0800
changeset 251713 694f5026338d983cad594d6a841fa3df13a0da09
parent 251712 7ad73fa3f416d8d0925aac2f0d3e029c1321a4b3
child 251714 35d043b3e8894763cf99b53bed48e1314c003614
push id4610
push userjlund@mozilla.com
push dateMon, 30 Mar 2015 18:32:55 +0000
treeherdermozilla-beta@4df54044d9ef [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj
bugs1123151
milestone38.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 1123151 (part 2) - Add PLDHashTable::IsInitialized(). r=froydnj. This encapsulates most of the uses of PLDHashTable::ops.
dom/base/nsContentList.cpp
dom/base/nsContentUtils.cpp
dom/base/nsDocument.cpp
dom/base/nsPropertyTable.cpp
dom/plugins/base/nsJSNPRuntime.cpp
dom/xul/templates/nsContentSupportMap.cpp
dom/xul/templates/nsContentSupportMap.h
gfx/thebes/gfxFT2FontList.cpp
layout/base/nsFrameManager.cpp
layout/style/nsCSSRuleProcessor.cpp
layout/style/nsHTMLStyleSheet.cpp
layout/tables/SpanningCellSorter.cpp
modules/libpref/Preferences.cpp
modules/libpref/nsPrefBranch.cpp
modules/libpref/prefapi.cpp
netwerk/base/src/nsLoadGroup.cpp
netwerk/protocol/http/nsHttp.cpp
parser/htmlparser/nsHTMLEntities.cpp
rdf/base/nsInMemoryDataSource.cpp
rdf/base/nsRDFService.cpp
security/manager/boot/src/nsSecureBrowserUIImpl.cpp
security/manager/ssl/src/nsCertTree.cpp
security/manager/ssl/src/nsNSSShutDown.cpp
uriloader/base/nsDocLoader.cpp
xpcom/base/nsCycleCollector.cpp
xpcom/ds/nsAtomTable.cpp
xpcom/ds/nsPersistentProperties.cpp
xpcom/ds/nsStaticNameTable.cpp
xpcom/glue/nsBaseHashtable.h
xpcom/glue/nsTHashtable.h
xpcom/glue/pldhash.h
xpcom/tests/TestPLDHash.cpp
--- a/dom/base/nsContentList.cpp
+++ b/dom/base/nsContentList.cpp
@@ -210,24 +210,24 @@ NS_GetContentList(nsINode* aRootNode,
   {
     ContentListHashtableHashKey,
     ContentListHashtableMatchEntry,
     PL_DHashMoveEntryStub,
     PL_DHashClearEntryStub
   };
 
   // Initialize the hashtable if needed.
-  if (!gContentListHashTable.ops) {
+  if (!gContentListHashTable.IsInitialized()) {
     PL_DHashTableInit(&gContentListHashTable, &hash_table_ops,
                       sizeof(ContentListHashEntry));
   }
 
   ContentListHashEntry *entry = nullptr;
   // First we look in our hashtable.  Then we create a content list if needed
-  if (gContentListHashTable.ops) {
+  if (gContentListHashTable.IsInitialized()) {
 
     // A PL_DHASH_ADD is equivalent to a PL_DHASH_LOOKUP for cases
     // when the entry is already in the hashtable.
     entry = static_cast<ContentListHashEntry *>
                        (PL_DHashTableAdd(&gContentListHashTable, &hashKey));
     if (entry)
       list = entry->mContentList;
   }
@@ -320,24 +320,24 @@ GetFuncStringContentList(nsINode* aRootN
   {
     FuncStringContentListHashtableHashKey,
     FuncStringContentListHashtableMatchEntry,
     PL_DHashMoveEntryStub,
     PL_DHashClearEntryStub
   };
 
   // Initialize the hashtable if needed.
-  if (!gFuncStringContentListHashTable.ops) {
+  if (!gFuncStringContentListHashTable.IsInitialized()) {
     PL_DHashTableInit(&gFuncStringContentListHashTable, &hash_table_ops,
                       sizeof(FuncStringContentListHashEntry));
   }
 
   FuncStringContentListHashEntry *entry = nullptr;
   // First we look in our hashtable.  Then we create a content list if needed
-  if (gFuncStringContentListHashTable.ops) {
+  if (gFuncStringContentListHashTable.IsInitialized()) {
     nsFuncStringCacheKey hashKey(aRootNode, aFunc, aString);
 
     // A PL_DHASH_ADD is equivalent to a PL_DHASH_LOOKUP for cases
     // when the entry is already in the hashtable.
     entry = static_cast<FuncStringContentListHashEntry *>
                        (PL_DHashTableAdd(&gFuncStringContentListHashTable,
                                          &hashKey));
     if (entry) {
@@ -972,17 +972,17 @@ nsContentList::RemoveFromHashtable()
   
   nsDependentAtomString str(mXMLMatchAtom);
   nsContentListKey key(mRootNode, mMatchNameSpaceId, str);
   uint32_t recentlyUsedCacheIndex = RecentlyUsedCacheIndex(key);
   if (sRecentlyUsedContentLists[recentlyUsedCacheIndex] == this) {
     sRecentlyUsedContentLists[recentlyUsedCacheIndex] = nullptr;
   }
 
-  if (!gContentListHashTable.ops)
+  if (!gContentListHashTable.IsInitialized())
     return;
 
   PL_DHashTableRemove(&gContentListHashTable, &key);
 
   if (gContentListHashTable.EntryCount() == 0) {
     PL_DHashTableFinish(&gContentListHashTable);
   }
 }
@@ -1010,17 +1010,17 @@ nsContentList::BringSelfUpToDate(bool aD
 nsCacheableFuncStringContentList::~nsCacheableFuncStringContentList()
 {
   RemoveFromFuncStringHashtable();
 }
 
 void
 nsCacheableFuncStringContentList::RemoveFromFuncStringHashtable()
 {
-  if (!gFuncStringContentListHashTable.ops) {
+  if (!gFuncStringContentListHashTable.IsInitialized()) {
     return;
   }
 
   nsFuncStringCacheKey key(mRootNode, mFunc, mString);
   PL_DHashTableRemove(&gFuncStringContentListHashTable, &key);
 
   if (gFuncStringContentListHashTable.EntryCount() == 0) {
     PL_DHashTableFinish(&gFuncStringContentListHashTable);
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -339,17 +339,17 @@ class DOMEventListenerManagersHashReport
 public:
   NS_DECL_ISUPPORTS
 
   NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
                             nsISupports* aData, bool aAnonymize) MOZ_OVERRIDE
   {
     // We don't measure the |EventListenerManager| objects pointed to by the
     // entries because those references are non-owning.
-    int64_t amount = sEventListenerManagersHash.ops
+    int64_t amount = sEventListenerManagersHash.IsInitialized()
                    ? PL_DHashTableSizeOfExcludingThis(
                        &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.");
@@ -471,17 +471,17 @@ 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.ops) {
+  if (!sEventListenerManagersHash.IsInitialized()) {
     static const PLDHashTableOps hash_table_ops =
     {
       PL_DHashVoidPtrKeyStub,
       PL_DHashMatchEntryStub,
       PL_DHashMoveEntryStub,
       EventListenerManagerHashClearEntry,
       EventListenerManagerHashInitEntry
     };
@@ -1756,17 +1756,17 @@ nsContentUtils::Shutdown()
 
   delete sAtomEventTable;
   sAtomEventTable = nullptr;
   delete sStringEventTable;
   sStringEventTable = nullptr;
   delete sUserDefinedEvents;
   sUserDefinedEvents = nullptr;
 
-  if (sEventListenerManagersHash.ops) {
+  if (sEventListenerManagersHash.IsInitialized()) {
     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
@@ -3905,45 +3905,45 @@ ListenerEnumerator(PLDHashTable* aTable,
     }
   }
   return PL_DHASH_NEXT;
 }
 
 void
 nsContentUtils::UnmarkGrayJSListenersInCCGenerationDocuments(uint32_t aGeneration)
 {
-  if (sEventListenerManagersHash.ops) {
+  if (sEventListenerManagersHash.IsInitialized()) {
     PL_DHashTableEnumerate(&sEventListenerManagersHash, ListenerEnumerator,
                            &aGeneration);
   }
 }
 
 /* static */
 void
 nsContentUtils::TraverseListenerManager(nsINode *aNode,
                                         nsCycleCollectionTraversalCallback &cb)
 {
-  if (!sEventListenerManagersHash.ops) {
+  if (!sEventListenerManagersHash.IsInitialized()) {
     // We're already shut down, just return.
     return;
   }
 
   EventListenerManagerMapEntry *entry =
     static_cast<EventListenerManagerMapEntry *>
                (PL_DHashTableLookup(&sEventListenerManagersHash, aNode));
   if (PL_DHASH_ENTRY_IS_BUSY(entry)) {
     CycleCollectionNoteChild(cb, entry->mListenerManager.get(),
                              "[via hash] mListenerManager");
   }
 }
 
 EventListenerManager*
 nsContentUtils::GetListenerManagerForNode(nsINode *aNode)
 {
-  if (!sEventListenerManagersHash.ops) {
+  if (!sEventListenerManagersHash.IsInitialized()) {
     // We're already shut down, don't bother creating an event listener
     // manager.
 
     return nullptr;
   }
 
   EventListenerManagerMapEntry *entry =
     static_cast<EventListenerManagerMapEntry *>
@@ -3964,17 +3964,17 @@ nsContentUtils::GetListenerManagerForNod
 
 EventListenerManager*
 nsContentUtils::GetExistingListenerManagerForNode(const nsINode *aNode)
 {
   if (!aNode->HasFlag(NODE_HAS_LISTENERMANAGER)) {
     return nullptr;
   }
   
-  if (!sEventListenerManagersHash.ops) {
+  if (!sEventListenerManagersHash.IsInitialized()) {
     // We're already shut down, don't bother creating an event listener
     // manager.
 
     return nullptr;
   }
 
   EventListenerManagerMapEntry *entry =
     static_cast<EventListenerManagerMapEntry *>
@@ -3985,17 +3985,17 @@ nsContentUtils::GetExistingListenerManag
 
   return nullptr;
 }
 
 /* static */
 void
 nsContentUtils::RemoveListenerManager(nsINode *aNode)
 {
-  if (sEventListenerManagersHash.ops) {
+  if (sEventListenerManagersHash.IsInitialized()) {
     EventListenerManagerMapEntry *entry =
       static_cast<EventListenerManagerMapEntry *>
                  (PL_DHashTableLookup(&sEventListenerManagersHash, aNode));
     if (PL_DHASH_ENTRY_IS_BUSY(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.
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -2027,17 +2027,17 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
     cb.NoteXPCOMChild(tmp->mFrameRequestCallbacks[i].mCallback.GetISupports());
   }
 
   // Traverse animation components
   if (tmp->mAnimationController) {
     tmp->mAnimationController->Traverse(&cb);
   }
 
-  if (tmp->mSubDocuments && tmp->mSubDocuments->ops) {
+  if (tmp->mSubDocuments && tmp->mSubDocuments->IsInitialized()) {
     PL_DHashTableEnumerate(tmp->mSubDocuments, SubDocTraverser, &cb);
   }
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCSSLoader)
 
   for (uint32_t i = 0; i < tmp->mHostObjectURIs.Length(); ++i) {
     nsHostObjectProtocolHandler::Traverse(tmp->mHostObjectURIs[i], cb);
   }
--- a/dom/base/nsPropertyTable.cpp
+++ b/dom/base/nsPropertyTable.cpp
@@ -210,17 +210,17 @@ nsPropertyTable::SetPropertyInternal(nsP
         aTransfer != propertyList->mTransfer) {
       NS_WARNING("Destructor/data mismatch while setting property");
       return NS_ERROR_INVALID_ARG;
     }
 
   } else {
     propertyList = new PropertyList(aPropertyName, aPropDtorFunc,
                                     aPropDtorData, aTransfer);
-    if (!propertyList || !propertyList->mObjectValueMap.ops) {
+    if (!propertyList || !propertyList->mObjectValueMap.IsInitialized()) {
       delete propertyList;
       return NS_ERROR_OUT_OF_MEMORY;
     }
 
     propertyList->mNext = mPropertyList;
     mPropertyList = propertyList;
   }
 
--- a/dom/plugins/base/nsJSNPRuntime.cpp
+++ b/dom/plugins/base/nsJSNPRuntime.cpp
@@ -397,17 +397,17 @@ DestroyJSObjWrapperTable()
   // hash to prevent leaking it.
   sJSObjWrappers.finish();
   sJSObjWrappersAccessible = false;
 }
 
 static bool
 CreateNPObjWrapperTable()
 {
-  MOZ_ASSERT(!sNPObjWrappers.ops);
+  MOZ_ASSERT(!sNPObjWrappers.IsInitialized());
 
   if (!RegisterGCCallbacks()) {
     return false;
   }
 
   PL_DHashTableInit(&sNPObjWrappers, PL_DHashGetStubOps(),
                     sizeof(NPObjWrapperHashEntry));
   return true;
@@ -432,17 +432,17 @@ OnWrapperDestroyed()
 {
   NS_ASSERTION(sWrapperCount, "Whaaa, unbalanced created/destroyed calls!");
 
   if (--sWrapperCount == 0) {
     if (sJSObjWrappersAccessible) {
       DestroyJSObjWrapperTable();
     }
 
-    if (sNPObjWrappers.ops) {
+    if (sNPObjWrappers.IsInitialized()) {
       // No more wrappers, and our hash was initialized. Finish the
       // hash to prevent leaking it.
       DestroyNPObjWrapperTable();
     }
 
     UnregisterGCCallbacks();
   }
 }
@@ -1742,33 +1742,33 @@ 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.ops) {
+    if (sNPObjWrappers.IsInitialized()) {
       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.ops) {
+  if (!sNPObjWrappers.IsInitialized()) {
     return;
   }
 
   NPObject *npobj = (NPObject *)::JS_GetPrivate(obj);
   if (!npobj) {
     return;
   }
 
@@ -1817,17 +1817,17 @@ 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.ops) {
+  if (!sNPObjWrappers.IsInitialized()) {
     // No hash yet (or any more), no used wrappers available.
 
     return;
   }
 
   NPObjWrapperHashEntry *entry = static_cast<NPObjWrapperHashEntry *>
     (PL_DHashTableLookup(&sNPObjWrappers, npobj));
 
@@ -1867,17 +1867,17 @@ nsNPObjWrapper::GetNewOrUsed(NPP npp, JS
   }
 
   if (!npp) {
     NS_ERROR("No npp passed to nsNPObjWrapper::GetNewOrUsed()!");
 
     return nullptr;
   }
 
-  if (!sNPObjWrappers.ops) {
+  if (!sNPObjWrappers.IsInitialized()) {
     // No hash yet (or any more), initialize it.
     if (!CreateNPObjWrapperTable()) {
       return nullptr;
     }
   }
 
   NPObjWrapperHashEntry *entry = static_cast<NPObjWrapperHashEntry *>
     (PL_DHashTableAdd(&sNPObjWrappers, npobj));
@@ -2023,17 +2023,17 @@ 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.ops) {
+  if (sNPObjWrappers.IsInitialized()) {
     NppAndCx nppcx = { npp, cx };
     PL_DHashTableEnumerate(&sNPObjWrappers,
                            NPObjWrapperPluginDestroyedCallback, &nppcx);
   }
 }
 
 
 // Find the NPP for a NPObject.
--- a/dom/xul/templates/nsContentSupportMap.cpp
+++ b/dom/xul/templates/nsContentSupportMap.cpp
@@ -10,24 +10,24 @@ void
 nsContentSupportMap::Init()
 {
     PL_DHashTableInit(&mMap, PL_DHashGetStubOps(), sizeof(Entry));
 }
 
 void
 nsContentSupportMap::Finish()
 {
-    if (mMap.ops)
+    if (mMap.IsInitialized())
         PL_DHashTableFinish(&mMap);
 }
 
 nsresult
 nsContentSupportMap::Remove(nsIContent* aElement)
 {
-    if (!mMap.ops)
+    if (!mMap.IsInitialized())
         return NS_ERROR_NOT_INITIALIZED;
 
     nsIContent* child = aElement;
     do {
         PL_DHashTableRemove(&mMap, child);
         child = child->GetNextNode(aElement);
     } while(child);
 
--- a/dom/xul/templates/nsContentSupportMap.h
+++ b/dom/xul/templates/nsContentSupportMap.h
@@ -20,31 +20,31 @@
  * and rule information).
  */
 class nsContentSupportMap {
 public:
     nsContentSupportMap() { Init(); }
     ~nsContentSupportMap() { Finish(); }
 
     nsresult Put(nsIContent* aElement, nsTemplateMatch* aMatch) {
-        if (!mMap.ops)
+        if (!mMap.IsInitialized())
             return NS_ERROR_NOT_INITIALIZED;
 
         PLDHashEntryHdr* hdr = PL_DHashTableAdd(&mMap, aElement);
         if (!hdr)
             return NS_ERROR_OUT_OF_MEMORY;
 
         Entry* entry = reinterpret_cast<Entry*>(hdr);
         NS_ASSERTION(entry->mMatch == nullptr, "over-writing entry");
         entry->mContent = aElement;
         entry->mMatch   = aMatch;
         return NS_OK; }
 
     bool Get(nsIContent* aElement, nsTemplateMatch** aMatch) {
-        if (!mMap.ops)
+        if (!mMap.IsInitialized())
             return false;
 
         PLDHashEntryHdr* hdr = PL_DHashTableLookup(&mMap, aElement);
         if (PL_DHASH_ENTRY_IS_FREE(hdr))
             return false;
 
         Entry* entry = reinterpret_cast<Entry*>(hdr);
         *aMatch = entry->mMatch;
--- a/gfx/thebes/gfxFT2FontList.cpp
+++ b/gfx/thebes/gfxFT2FontList.cpp
@@ -635,33 +635,33 @@ public:
                           "StartupCacheFontNameCache should only be used in chrome process");
         mCache = mozilla::scache::StartupCache::GetSingleton();
 
         Init();
     }
 
     ~FontNameCache()
     {
-        if (!mMap.ops) {
+        if (!mMap.IsInitialized()) {
             return;
         }
         if (!mWriteNeeded || !mCache) {
             PL_DHashTableFinish(&mMap);
             return;
         }
 
         nsAutoCString buf;
         PL_DHashTableEnumerate(&mMap, WriteOutMap, &buf);
         PL_DHashTableFinish(&mMap);
         mCache->PutBuffer(CACHE_KEY, buf.get(), buf.Length() + 1);
     }
 
     void Init()
     {
-        if (!mMap.ops || !mCache) {
+        if (!mMap.IsInitialized() || !mCache) {
             return;
         }
         uint32_t size;
         char* buf;
         if (NS_FAILED(mCache->GetBuffer(CACHE_KEY, &buf, &size))) {
             return;
         }
 
@@ -707,17 +707,17 @@ public:
         // Should we use free() or delete[] here? See bug 684700.
         free(buf);
     }
 
     virtual void
     GetInfoForFile(const nsCString& aFileName, nsCString& aFaceList,
                    uint32_t *aTimestamp, uint32_t *aFilesize)
     {
-        if (!mMap.ops) {
+        if (!mMap.IsInitialized()) {
             return;
         }
         PLDHashEntryHdr *hdr =
             PL_DHashTableLookup(&mMap, aFileName.get());
         if (!hdr) {
             return;
         }
         FNCMapEntry* entry = static_cast<FNCMapEntry*>(hdr);
@@ -731,17 +731,17 @@ public:
             entry->mFileExists = true;
         }
     }
 
     virtual void
     CacheFileInfo(const nsCString& aFileName, const nsCString& aFaceList,
                   uint32_t aTimestamp, uint32_t aFilesize)
     {
-        if (!mMap.ops) {
+        if (!mMap.IsInitialized()) {
             return;
         }
         FNCMapEntry* entry =
             static_cast<FNCMapEntry*>
             (PL_DHashTableAdd(&mMap, aFileName.get()));
         if (entry) {
             entry->mFilename.Assign(aFileName);
             entry->mTimestamp = aTimestamp;
--- a/layout/base/nsFrameManager.cpp
+++ b/layout/base/nsFrameManager.cpp
@@ -148,17 +148,17 @@ nsFrameManager::Destroy()
 //----------------------------------------------------------------------
 
 // Placeholder frame functions
 nsPlaceholderFrame*
 nsFrameManager::GetPlaceholderFrameFor(const nsIFrame* aFrame)
 {
   NS_PRECONDITION(aFrame, "null param unexpected");
 
-  if (mPlaceholderMap.ops) {
+  if (mPlaceholderMap.IsInitialized()) {
     PlaceholderMapEntry *entry = static_cast<PlaceholderMapEntry*>
                                             (PL_DHashTableLookup(const_cast<PLDHashTable*>(&mPlaceholderMap),
                                 aFrame));
     if (PL_DHASH_ENTRY_IS_BUSY(entry)) {
       return entry->placeholderFrame;
     }
   }
 
@@ -166,17 +166,17 @@ nsFrameManager::GetPlaceholderFrameFor(c
 }
 
 nsresult
 nsFrameManager::RegisterPlaceholderFrame(nsPlaceholderFrame* aPlaceholderFrame)
 {
   NS_PRECONDITION(aPlaceholderFrame, "null param unexpected");
   NS_PRECONDITION(nsGkAtoms::placeholderFrame == aPlaceholderFrame->GetType(),
                   "unexpected frame type");
-  if (!mPlaceholderMap.ops) {
+  if (!mPlaceholderMap.IsInitialized()) {
     PL_DHashTableInit(&mPlaceholderMap, &PlaceholderMapOps,
                       sizeof(PlaceholderMapEntry));
   }
   PlaceholderMapEntry *entry = static_cast<PlaceholderMapEntry*>(PL_DHashTableAdd(&mPlaceholderMap,
                               aPlaceholderFrame->GetOutOfFlowFrame()));
   if (!entry)
     return NS_ERROR_OUT_OF_MEMORY;
 
@@ -188,17 +188,17 @@ nsFrameManager::RegisterPlaceholderFrame
 
 void
 nsFrameManager::UnregisterPlaceholderFrame(nsPlaceholderFrame* aPlaceholderFrame)
 {
   NS_PRECONDITION(aPlaceholderFrame, "null param unexpected");
   NS_PRECONDITION(nsGkAtoms::placeholderFrame == aPlaceholderFrame->GetType(),
                   "unexpected frame type");
 
-  if (mPlaceholderMap.ops) {
+  if (mPlaceholderMap.IsInitialized()) {
     PL_DHashTableRemove(&mPlaceholderMap,
                         aPlaceholderFrame->GetOutOfFlowFrame());
   }
 }
 
 static PLDHashOperator
 UnregisterPlaceholders(PLDHashTable* table, PLDHashEntryHdr* hdr,
                        uint32_t number, void* arg)
@@ -206,17 +206,17 @@ UnregisterPlaceholders(PLDHashTable* tab
   PlaceholderMapEntry* entry = static_cast<PlaceholderMapEntry*>(hdr);
   entry->placeholderFrame->SetOutOfFlowFrame(nullptr);
   return PL_DHASH_NEXT;
 }
 
 void
 nsFrameManager::ClearPlaceholderFrameMap()
 {
-  if (mPlaceholderMap.ops) {
+  if (mPlaceholderMap.IsInitialized()) {
     PL_DHashTableEnumerate(&mPlaceholderMap, UnregisterPlaceholders, nullptr);
     PL_DHashTableFinish(&mPlaceholderMap);
   }
 }
 
 //----------------------------------------------------------------------
 
 /* static */ nsStyleContext*
--- a/layout/style/nsCSSRuleProcessor.cpp
+++ b/layout/style/nsCSSRuleProcessor.cpp
@@ -550,26 +550,26 @@ RuleHash::~RuleHash()
 #endif // RULE_HASH_STATS
   // Rule Values are arena allocated no need to delete them. Their destructor
   // isn't doing any cleanup. So we dont even bother to enumerate through
   // the hash tables and call their destructors.
   if (nullptr != mEnumList) {
     delete [] mEnumList;
   }
   // delete arena for strings and small objects
-  if (mIdTable.ops) {
+  if (mIdTable.IsInitialized()) {
     PL_DHashTableFinish(&mIdTable);
   }
-  if (mClassTable.ops) {
+  if (mClassTable.IsInitialized()) {
     PL_DHashTableFinish(&mClassTable);
   }
-  if (mTagTable.ops) {
+  if (mTagTable.IsInitialized()) {
     PL_DHashTableFinish(&mTagTable);
   }
-  if (mNameSpaceTable.ops) {
+  if (mNameSpaceTable.IsInitialized()) {
     PL_DHashTableFinish(&mNameSpaceTable);
   }
 }
 
 void RuleHash::AppendRuleToTable(PLDHashTable* aTable, const void* aKey,
                                  const RuleSelectorPair& aRuleInfo)
 {
   // Get a new or existing entry.
@@ -600,51 +600,51 @@ void RuleHash::AppendUniversalRule(const
 
 void RuleHash::AppendRule(const RuleSelectorPair& aRuleInfo)
 {
   nsCSSSelector *selector = aRuleInfo.mSelector;
   if (selector->IsPseudoElement()) {
     selector = selector->mNext;
   }
   if (nullptr != selector->mIDList) {
-    if (!mIdTable.ops) {
+    if (!mIdTable.IsInitialized()) {
       PL_DHashTableInit(&mIdTable,
                         mQuirksMode ? &RuleHash_IdTable_CIOps.ops
                                     : &RuleHash_IdTable_CSOps.ops,
                         sizeof(RuleHashTableEntry));
     }
     AppendRuleToTable(&mIdTable, selector->mIDList->mAtom, aRuleInfo);
     RULE_HASH_STAT_INCREMENT(mIdSelectors);
   }
   else if (nullptr != selector->mClassList) {
-    if (!mClassTable.ops) {
+    if (!mClassTable.IsInitialized()) {
       PL_DHashTableInit(&mClassTable,
                         mQuirksMode ? &RuleHash_ClassTable_CIOps.ops
                                     : &RuleHash_ClassTable_CSOps.ops,
                         sizeof(RuleHashTableEntry));
     }
     AppendRuleToTable(&mClassTable, selector->mClassList->mAtom, aRuleInfo);
     RULE_HASH_STAT_INCREMENT(mClassSelectors);
   }
   else if (selector->mLowercaseTag) {
     RuleValue ruleValue(aRuleInfo, mRuleCount++, mQuirksMode);
-    if (!mTagTable.ops) {
+    if (!mTagTable.IsInitialized()) {
       PL_DHashTableInit(&mTagTable, &RuleHash_TagTable_Ops,
                         sizeof(RuleHashTagTableEntry));
     }
     AppendRuleToTagTable(&mTagTable, selector->mLowercaseTag, ruleValue);
     RULE_HASH_STAT_INCREMENT(mTagSelectors);
     if (selector->mCasedTag &&
         selector->mCasedTag != selector->mLowercaseTag) {
       AppendRuleToTagTable(&mTagTable, selector->mCasedTag, ruleValue);
       RULE_HASH_STAT_INCREMENT(mTagSelectors);
     }
   }
   else if (kNameSpaceID_Unknown != selector->mNameSpace) {
-    if (!mNameSpaceTable.ops) {
+    if (!mNameSpaceTable.IsInitialized()) {
       PL_DHashTableInit(&mNameSpaceTable, &RuleHash_NameSpaceTable_Ops,
                         sizeof(RuleHashTableEntry));
     }
     AppendRuleToTable(&mNameSpaceTable,
                       NS_INT32_TO_PTR(selector->mNameSpace), aRuleInfo);
     RULE_HASH_STAT_INCREMENT(mNameSpaceSelectors);
   }
   else {  // universal tag selector
@@ -694,41 +694,41 @@ void RuleHash::EnumerateAllRules(Element
   int32_t valueCount = 0;
   RULE_HASH_STAT_INCREMENT(mElementsMatched);
 
   if (mUniversalRules.Length() != 0) { // universal rules
     mEnumList[valueCount++] = ToEnumData(mUniversalRules);
     RULE_HASH_STAT_INCREMENT_LIST_COUNT(mUniversalRules, mElementUniversalCalls);
   }
   // universal rules within the namespace
-  if (kNameSpaceID_Unknown != nameSpace && mNameSpaceTable.ops) {
+  if (kNameSpaceID_Unknown != nameSpace && mNameSpaceTable.IsInitialized()) {
     RuleHashTableEntry *entry = static_cast<RuleHashTableEntry*>
                                            (PL_DHashTableLookup(&mNameSpaceTable, NS_INT32_TO_PTR(nameSpace)));
     if (PL_DHASH_ENTRY_IS_BUSY(entry)) {
       mEnumList[valueCount++] = ToEnumData(entry->mRules);
       RULE_HASH_STAT_INCREMENT_LIST_COUNT(entry->mRules, mElementNameSpaceCalls);
     }
   }
-  if (mTagTable.ops) {
+  if (mTagTable.IsInitialized()) {
     RuleHashTableEntry *entry = static_cast<RuleHashTableEntry*>
                                            (PL_DHashTableLookup(&mTagTable, tag));
     if (PL_DHASH_ENTRY_IS_BUSY(entry)) {
       mEnumList[valueCount++] = ToEnumData(entry->mRules);
       RULE_HASH_STAT_INCREMENT_LIST_COUNT(entry->mRules, mElementTagCalls);
     }
   }
-  if (id && mIdTable.ops) {
+  if (id && mIdTable.IsInitialized()) {
     RuleHashTableEntry *entry = static_cast<RuleHashTableEntry*>
                                            (PL_DHashTableLookup(&mIdTable, id));
     if (PL_DHASH_ENTRY_IS_BUSY(entry)) {
       mEnumList[valueCount++] = ToEnumData(entry->mRules);
       RULE_HASH_STAT_INCREMENT_LIST_COUNT(entry->mRules, mElementIdCalls);
     }
   }
-  if (mClassTable.ops) {
+  if (mClassTable.IsInitialized()) {
     for (int32_t index = 0; index < classCount; ++index) {
       RuleHashTableEntry *entry = static_cast<RuleHashTableEntry*>
                                              (PL_DHashTableLookup(&mClassTable, classList->AtomAt(index)));
       if (PL_DHASH_ENTRY_IS_BUSY(entry)) {
         mEnumList[valueCount++] = ToEnumData(entry->mRules);
         RULE_HASH_STAT_INCREMENT_LIST_COUNT(entry->mRules, mElementClassCalls);
       }
     }
@@ -781,35 +781,35 @@ SizeOfRuleHashTableEntry(PLDHashEntryHdr
   return entry->mRules.SizeOfExcludingThis(aMallocSizeOf);
 }
 
 size_t
 RuleHash::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
 {
   size_t n = 0;
 
-  if (mIdTable.ops) {
+  if (mIdTable.IsInitialized()) {
     n += PL_DHashTableSizeOfExcludingThis(&mIdTable,
                                           SizeOfRuleHashTableEntry,
                                           aMallocSizeOf);
   }
 
-  if (mClassTable.ops) {
+  if (mClassTable.IsInitialized()) {
     n += PL_DHashTableSizeOfExcludingThis(&mClassTable,
                                           SizeOfRuleHashTableEntry,
                                           aMallocSizeOf);
   }
 
-  if (mTagTable.ops) {
+  if (mTagTable.IsInitialized()) {
     n += PL_DHashTableSizeOfExcludingThis(&mTagTable,
                                           SizeOfRuleHashTableEntry,
                                           aMallocSizeOf);
   }
 
-  if (mNameSpaceTable.ops) {
+  if (mNameSpaceTable.IsInitialized()) {
     n += PL_DHashTableSizeOfExcludingThis(&mNameSpaceTable,
                                           SizeOfRuleHashTableEntry,
                                           aMallocSizeOf);
   }
 
   n += mUniversalRules.SizeOfExcludingThis(aMallocSizeOf);
 
   return n;
@@ -3361,17 +3361,17 @@ struct CascadeEnumData {
 
     // Initialize our arena
     PL_INIT_ARENA_POOL(&mArena, "CascadeEnumDataArena",
                        NS_CASCADEENUMDATA_ARENA_BLOCK_SIZE);
   }
 
   ~CascadeEnumData()
   {
-    if (mRulesByWeight.ops)
+    if (mRulesByWeight.IsInitialized())
       PL_DHashTableFinish(&mRulesByWeight);
     PL_FinishArenaPool(&mArena);
   }
 
   nsPresContext* mPresContext;
   nsTArray<nsFontFaceRuleContainer>& mFontFaceRules;
   nsTArray<nsCSSKeyframesRule*>& mKeyframesRules;
   nsTArray<nsCSSFontFeatureValuesRule*>& mFontFeatureValuesRules;
@@ -3575,17 +3575,17 @@ nsCSSRuleProcessor::RefreshRuleCascade(n
     if (newCascade) {
       CascadeEnumData data(aPresContext, newCascade->mFontFaceRules,
                            newCascade->mKeyframesRules,
                            newCascade->mFontFeatureValuesRules,
                            newCascade->mPageRules,
                            newCascade->mCounterStyleRules,
                            newCascade->mCacheKey,
                            mSheetType);
-      if (!data.mRulesByWeight.ops)
+      if (!data.mRulesByWeight.IsInitialized())
         return; /* out of memory */
 
       for (uint32_t i = 0; i < mSheets.Length(); ++i) {
         if (!CascadeSheet(mSheets.ElementAt(i), &data))
           return; /* out of memory */
       }
 
       // Sort the hash table of per-weight linked lists by weight.
--- a/layout/style/nsHTMLStyleSheet.cpp
+++ b/layout/style/nsHTMLStyleSheet.cpp
@@ -237,20 +237,22 @@ nsHTMLStyleSheet::nsHTMLStyleSheet(nsIDo
   , mTableQuirkColorRule(new TableQuirkColorRule())
   , mTableTHRule(new TableTHRule())
 {
   MOZ_ASSERT(aDocument);
 }
 
 nsHTMLStyleSheet::~nsHTMLStyleSheet()
 {
-  if (mLangRuleTable.ops)
+  if (mLangRuleTable.IsInitialized()) {
     PL_DHashTableFinish(&mLangRuleTable);
-  if (mMappedAttrTable.ops)
+  }
+  if (mMappedAttrTable.IsInitialized()) {
     PL_DHashTableFinish(&mMappedAttrTable);
+  }
 }
 
 NS_IMPL_ISUPPORTS(nsHTMLStyleSheet, nsIStyleRuleProcessor)
 
 /* virtual */ void
 nsHTMLStyleSheet::RulesMatching(ElementRuleProcessorData* aData)
 {
   nsRuleWalker *ruleWalker = aData->mRuleWalker;
@@ -418,20 +420,20 @@ nsHTMLStyleSheet::SetOwningDocument(nsID
 
 void
 nsHTMLStyleSheet::Reset()
 {
   mLinkRule          = nullptr;
   mVisitedRule       = nullptr;
   mActiveRule        = nullptr;
 
-  if (mLangRuleTable.ops) {
+  if (mLangRuleTable.IsInitialized()) {
     PL_DHashTableFinish(&mLangRuleTable);
   }
-  if (mMappedAttrTable.ops) {
+  if (mMappedAttrTable.IsInitialized()) {
     PL_DHashTableFinish(&mMappedAttrTable);
   }
 }
 
 nsresult
 nsHTMLStyleSheet::ImplLinkColorSetter(nsRefPtr<HTMLColorRule>& aRule, nscolor aColor)
 {
   if (aRule && aRule->mColor == aColor) {
@@ -472,17 +474,17 @@ nsresult
 nsHTMLStyleSheet::SetVisitedLinkColor(nscolor aColor)
 {
   return ImplLinkColorSetter(mVisitedRule, aColor);
 }
 
 already_AddRefed<nsMappedAttributes>
 nsHTMLStyleSheet::UniqueMappedAttributes(nsMappedAttributes* aMapped)
 {
-  if (!mMappedAttrTable.ops) {
+  if (!mMappedAttrTable.IsInitialized()) {
     PL_DHashTableInit(&mMappedAttrTable, &MappedAttrTable_Ops,
                       sizeof(MappedAttrTableEntry));
   }
   MappedAttrTableEntry *entry = static_cast<MappedAttrTableEntry*>
                                            (PL_DHashTableAdd(&mMappedAttrTable, aMapped));
   if (!entry)
     return nullptr;
   if (!entry->mAttributes) {
@@ -493,30 +495,30 @@ nsHTMLStyleSheet::UniqueMappedAttributes
   return ret.forget();
 }
 
 void
 nsHTMLStyleSheet::DropMappedAttributes(nsMappedAttributes* aMapped)
 {
   NS_ENSURE_TRUE_VOID(aMapped);
 
-  NS_ASSERTION(mMappedAttrTable.ops, "table uninitialized");
+  NS_ASSERTION(mMappedAttrTable.IsInitialized(), "table uninitialized");
 #ifdef DEBUG
   uint32_t entryCount = mMappedAttrTable.EntryCount() - 1;
 #endif
 
   PL_DHashTableRemove(&mMappedAttrTable, aMapped);
 
   NS_ASSERTION(entryCount == mMappedAttrTable.EntryCount(), "not removed");
 }
 
 nsIStyleRule*
 nsHTMLStyleSheet::LangRuleFor(const nsString& aLanguage)
 {
-  if (!mLangRuleTable.ops) {
+  if (!mLangRuleTable.IsInitialized()) {
     PL_DHashTableInit(&mLangRuleTable, &LangRuleTable_Ops,
                       sizeof(LangRuleTableEntry));
   }
   LangRuleTableEntry *entry = static_cast<LangRuleTableEntry*>
     (PL_DHashTableAdd(&mLangRuleTable, &aLanguage));
   if (!entry) {
     NS_ASSERTION(false, "out of memory");
     return nullptr;
@@ -536,17 +538,17 @@ SizeOfAttributesEntryExcludingThis(PLDHa
   return entry->mAttributes->SizeOfIncludingThis(aMallocSizeOf);
 }
 
 size_t
 nsHTMLStyleSheet::DOMSizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
 {
   size_t n = aMallocSizeOf(this);
 
-  if (mMappedAttrTable.ops) {
+  if (mMappedAttrTable.IsInitialized()) {
     n += PL_DHashTableSizeOfExcludingThis(&mMappedAttrTable,
                                           SizeOfAttributesEntryExcludingThis,
                                           aMallocSizeOf);
   }
 
   // Measurement of the following members may be added later if DMD finds it is
   // worthwhile:
   // - mURL
--- a/layout/tables/SpanningCellSorter.cpp
+++ b/layout/tables/SpanningCellSorter.cpp
@@ -18,17 +18,17 @@ SpanningCellSorter::SpanningCellSorter()
   : mState(ADDING)
   , mSortedHashTable(nullptr)
 {
     memset(mArray, 0, sizeof(mArray));
 }
 
 SpanningCellSorter::~SpanningCellSorter()
 {
-    if (mHashTable.ops) {
+    if (mHashTable.IsInitialized()) {
         PL_DHashTableFinish(&mHashTable);
     }
     delete [] mSortedHashTable;
 }
 
 /* static */ const PLDHashTableOps
 SpanningCellSorter::HashTableOps = {
     HashTableHashKey,
@@ -65,17 +65,17 @@ SpanningCellSorter::AddCell(int32_t aCol
     i->row = aRow;
     i->col = aCol;
 
     if (UseArrayForSpan(aColSpan)) {
         int32_t index = SpanToIndex(aColSpan);
         i->next = mArray[index];
         mArray[index] = i;
     } else {
-        if (!mHashTable.ops) {
+        if (!mHashTable.IsInitialized()) {
             PL_DHashTableInit(&mHashTable, &HashTableOps,
                               sizeof(HashTableEntry));
         }
         HashTableEntry *entry = static_cast<HashTableEntry*>
                                            (PL_DHashTableAdd(&mHashTable, NS_INT32_TO_PTR(aColSpan)));
         NS_ENSURE_TRUE(entry, false);
 
         NS_ASSERTION(entry->mColSpan == 0 || entry->mColSpan == aColSpan,
@@ -140,32 +140,34 @@ SpanningCellSorter::GetNext(int32_t *aCo
                        static_cast<void*>(this), *aColSpan);
 #endif
                 ++mEnumerationIndex;
                 return result;
             }
             /* prepare to enumerate the hash */
             mState = ENUMERATING_HASH;
             mEnumerationIndex = 0;
-            if (mHashTable.ops) {
+            if (mHashTable.IsInitialized()) {
                 HashTableEntry **sh =
                     new HashTableEntry*[mHashTable.EntryCount()];
                 if (!sh) {
                     // give up
                     mState = DONE;
                     return nullptr;
                 }
                 PL_DHashTableEnumerate(&mHashTable, FillSortedArray, sh);
                 NS_QuickSort(sh, mHashTable.EntryCount(), sizeof(sh[0]),
                              SortArray, nullptr);
                 mSortedHashTable = sh;
             }
             /* fall through */
         case ENUMERATING_HASH:
-            if (mHashTable.ops && mEnumerationIndex < mHashTable.EntryCount()) {
+            if (mHashTable.IsInitialized() &&
+                mEnumerationIndex < mHashTable.EntryCount())
+            {
                 Item *result = mSortedHashTable[mEnumerationIndex]->mItems;
                 *aColSpan = mSortedHashTable[mEnumerationIndex]->mColSpan;
                 NS_ASSERTION(result, "holes in hash table");
 #ifdef DEBUG_SPANNING_CELL_SORTER
                 printf("SpanningCellSorter[%p]:"
                        " returning list for colspan=%d from hash\n",
                        static_cast<void*>(this), *aColSpan);
 #endif
--- a/modules/libpref/Preferences.cpp
+++ b/modules/libpref/Preferences.cpp
@@ -230,17 +230,17 @@ 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.ops) {
+  if (gHashTable.IsInitialized()) {
     // 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);
   }
   if (gCacheData) {
     n += gCacheData->SizeOfIncludingThis(aMallocSizeOf);
     for (uint32_t i = 0, count = gCacheData->Length(); i < count; ++i) {
       n += aMallocSizeOf((*gCacheData)[i]);
@@ -950,17 +950,17 @@ Preferences::WritePrefFile(nsIFile* aFil
     NS_LINEBREAK
     NS_LINEBREAK;
 
   nsCOMPtr<nsIOutputStream> outStreamSink;
   nsCOMPtr<nsIOutputStream> outStream;
   uint32_t                  writeAmount;
   nsresult                  rv;
 
-  if (!gHashTable.ops)
+  if (!gHashTable.IsInitialized())
     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)) 
--- a/modules/libpref/nsPrefBranch.cpp
+++ b/modules/libpref/nsPrefBranch.cpp
@@ -550,17 +550,17 @@ NS_IMETHODIMP nsPrefBranch::GetChildList
 
   NS_ENSURE_ARG(aStartingAt);
   NS_ENSURE_ARG_POINTER(aCount);
   NS_ENSURE_ARG_POINTER(aChildArray);
 
   *aChildArray = nullptr;
   *aCount = 0;
 
-  if (!gHashTable.ops)
+  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);
--- a/modules/libpref/prefapi.cpp
+++ b/modules/libpref/prefapi.cpp
@@ -140,17 +140,17 @@ enum {
     kPrefForceSet = 2
 };
 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.ops) {
+    if (!gHashTable.IsInitialized()) {
         if (!PL_DHashTableInit(&gHashTable, &pref_HashTableOps,
                                sizeof(PrefHashEntry), fallible_t(),
                                PREF_HASHTABLE_INITIAL_LENGTH)) {
             return NS_ERROR_OUT_OF_MEMORY;
         }
 
         PL_INIT_ARENA_POOL(&gPrefNameArena, "PrefNameArena",
                            PREFNAME_ARENA_SIZE);
@@ -176,17 +176,17 @@ void PREF_Cleanup()
     gCallbacks = nullptr;
 
     PREF_CleanupPrefs();
 }
 
 /* Frees up all the objects except the callback list. */
 void PREF_CleanupPrefs()
 {
-    if (gHashTable.ops) {
+    if (gHashTable.IsInitialized()) {
         PL_DHashTableFinish(&gHashTable);
         PL_FinishArenaPool(&gPrefNameArena);
     }
 }
 
 // note that this appends to aResult, and does not assign!
 static void str_escape(const char * original, nsAFlatCString& aResult)
 {
@@ -459,31 +459,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.ops)
+    if (!gHashTable.IsInitialized())
         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.ops)
+    if (!gHashTable.IsInitialized())
         return NS_ERROR_NOT_INITIALIZED;
 
     nsresult rv = NS_ERROR_UNEXPECTED;
     char* stringVal;
     PrefHashEntry* pref = pref_HashTableLookup(pref_name);
 
     if (pref && (pref->flags & PREF_STRING))
     {
@@ -497,17 +497,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.ops)
+    if (!gHashTable.IsInitialized())
         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))
         {
@@ -521,17 +521,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.ops)
+    if (!gHashTable.IsInitialized())
         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))
@@ -572,17 +572,17 @@ nsresult
 PREF_DeleteBranch(const char *branch_name)
 {
 #ifndef MOZ_B2G
     MOZ_ASSERT(NS_IsMainThread());
 #endif
 
     int len = (int)strlen(branch_name);
 
-    if (!gHashTable.ops)
+    if (!gHashTable.IsInitialized())
         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.
      */
@@ -595,17 +595,17 @@ PREF_DeleteBranch(const char *branch_nam
     gDirty = true;
     return NS_OK;
 }
 
 
 nsresult
 PREF_ClearUserPref(const char *pref_name)
 {
-    if (!gHashTable.ops)
+    if (!gHashTable.IsInitialized())
         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)) {
@@ -641,28 +641,28 @@ pref_ClearUserPref(PLDHashTable *table, 
 
 nsresult
 PREF_ClearAllUserPrefs()
 {
 #ifndef MOZ_B2G
     MOZ_ASSERT(NS_IsMainThread());
 #endif
 
-    if (!gHashTable.ops)
+    if (!gHashTable.IsInitialized())
         return NS_ERROR_NOT_INITIALIZED;
 
     PL_DHashTableEnumerate(&gHashTable, pref_ClearUserPref, nullptr);
 
     gDirty = true;
     return NS_OK;
 }
 
 nsresult PREF_LockPref(const char *key, bool lockit)
 {
-    if (!gHashTable.ops)
+    if (!gHashTable.IsInitialized())
         return NS_ERROR_NOT_INITIALIZED;
 
     PrefHashEntry* pref = pref_HashTableLookup(key);
     if (!pref)
         return NS_ERROR_UNEXPECTED;
 
     if (lockit) {
         if (!PREF_IS_LOCKED(pref))
@@ -738,17 +738,17 @@ PrefHashEntry* pref_HashTableLookup(cons
 }
 
 nsresult pref_HashPref(const char *key, PrefValue value, PrefType type, uint32_t flags)
 {
 #ifndef MOZ_B2G
     MOZ_ASSERT(NS_IsMainThread());
 #endif
 
-    if (!gHashTable.ops)
+    if (!gHashTable.IsInitialized())
         return NS_ERROR_OUT_OF_MEMORY;
 
     PrefHashEntry* pref = static_cast<PrefHashEntry*>(PL_DHashTableAdd(&gHashTable, key));
 
     if (!pref)
         return NS_ERROR_OUT_OF_MEMORY;
 
     // new entry, better initialize
@@ -829,17 +829,17 @@ pref_SizeOfPrivateData(MallocSizeOf aMal
         n += aMallocSizeOf(node->domain);
     }
     return n;
 }
 
 PrefType
 PREF_GetPrefType(const char *pref_name)
 {
-    if (gHashTable.ops)
+    if (gHashTable.IsInitialized())
     {
         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;
@@ -851,17 +851,17 @@ PREF_GetPrefType(const char *pref_name)
 }
 
 /* -- */
 
 bool
 PREF_PrefIsLocked(const char *pref_name)
 {
     bool result = false;
-    if (gIsAnyPrefLocked && gHashTable.ops) {
+    if (gIsAnyPrefLocked && gHashTable.IsInitialized()) {
         PrefHashEntry* pref = pref_HashTableLookup(pref_name);
         if (pref && PREF_IS_LOCKED(pref))
             result = true;
     }
 
     return result;
 }
 
--- a/netwerk/base/src/nsLoadGroup.cpp
+++ b/netwerk/base/src/nsLoadGroup.cpp
@@ -134,17 +134,17 @@ nsLoadGroup::nsLoadGroup(nsISupports* ou
     LOG(("LOADGROUP [%x]: Created.\n", this));
 }
 
 nsLoadGroup::~nsLoadGroup()
 {
     DebugOnly<nsresult> rv = Cancel(NS_BINDING_ABORTED);
     NS_ASSERTION(NS_SUCCEEDED(rv), "Cancel failed");
 
-    if (mRequests.ops) {
+    if (mRequests.IsInitialized()) {
         PL_DHashTableFinish(&mRequests);
     }
 
     mDefaultLoadRequest = 0;
 
     LOG(("LOADGROUP [%x]: Destroyed.\n", this));
 }
 
--- a/netwerk/protocol/http/nsHttp.cpp
+++ b/netwerk/protocol/http/nsHttp.cpp
@@ -91,17 +91,17 @@ 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.ops, "atom table already initialized");
+    MOZ_ASSERT(!sAtomTable.IsInitialized(), "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.
@@ -129,17 +129,17 @@ nsHttp::CreateAtomTable()
     }
 
     return NS_OK;
 }
 
 void
 nsHttp::DestroyAtomTable()
 {
-    if (sAtomTable.ops) {
+    if (sAtomTable.IsInitialized()) {
         PL_DHashTableFinish(&sAtomTable);
     }
 
     while (sHeapAtoms) {
         HttpHeapAtom *next = sHeapAtoms->next;
         free(sHeapAtoms);
         sHeapAtoms = next;
     }
@@ -157,17 +157,17 @@ nsHttp::GetLock()
 }
 
 // this function may be called from multiple threads
 nsHttpAtom
 nsHttp::ResolveAtom(const char *str)
 {
     nsHttpAtom atom = { nullptr };
 
-    if (!str || !sAtomTable.ops)
+    if (!str || !sAtomTable.IsInitialized())
         return atom;
 
     MutexAutoLock lock(*sLock);
 
     PLDHashEntryStub *stub = reinterpret_cast<PLDHashEntryStub *>
                                              (PL_DHashTableAdd(&sAtomTable, str));
     if (!stub)
         return atom;  // out of memory
--- a/parser/htmlparser/nsHTMLEntities.cpp
+++ b/parser/htmlparser/nsHTMLEntities.cpp
@@ -126,29 +126,30 @@ nsHTMLEntities::AddRefTable(void)
 }
 
 void
 nsHTMLEntities::ReleaseTable(void)
 {
   if (--gTableRefCnt != 0)
     return;
 
-  if (gEntityToUnicode.ops) {
+  if (gEntityToUnicode.IsInitialized()) {
     PL_DHashTableFinish(&gEntityToUnicode);
   }
-  if (gUnicodeToEntity.ops) {
+  if (gUnicodeToEntity.IsInitialized()) {
     PL_DHashTableFinish(&gUnicodeToEntity);
   }
 }
 
 int32_t
 nsHTMLEntities::EntityToUnicode(const nsCString& aEntity)
 {
-  NS_ASSERTION(gEntityToUnicode.ops, "no lookup table, needs addref");
-  if (!gEntityToUnicode.ops)
+  NS_ASSERTION(gEntityToUnicode.IsInitialized(),
+               "no lookup table, needs addref");
+  if (!gEntityToUnicode.IsInitialized())
     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);
@@ -175,17 +176,18 @@ nsHTMLEntities::EntityToUnicode(const ns
 
   return EntityToUnicode(theEntity);
 }
 
 
 const char*
 nsHTMLEntities::UnicodeToEntity(int32_t aUnicode)
 {
-  NS_ASSERTION(gUnicodeToEntity.ops, "no lookup table, needs addref");
+  NS_ASSERTION(gUnicodeToEntity.IsInitialized(),
+               "no lookup table, needs addref");
   EntityNodeEntry* entry =
     static_cast<EntityNodeEntry*>
                (PL_DHashTableLookup(&gUnicodeToEntity, NS_INT32_TO_PTR(aUnicode)));
                    
   if (!entry || PL_DHASH_ENTRY_IS_FREE(entry))
   return nullptr;
     
   return entry->node->mStr;
--- a/rdf/base/nsInMemoryDataSource.cpp
+++ b/rdf/base/nsInMemoryDataSource.cpp
@@ -802,25 +802,25 @@ InMemoryDataSource::Init()
 
 InMemoryDataSource::~InMemoryDataSource()
 {
 #ifdef DEBUG_REFS
     --gInstanceCount;
     fprintf(stdout, "%d - RDF: InMemoryDataSource\n", gInstanceCount);
 #endif
 
-    if (mForwardArcs.ops) {
+    if (mForwardArcs.IsInitialized()) {
         // This'll release all of the Assertion objects that are
         // associated with this data source. We only need to do this
         // for the forward arcs, because the reverse arcs table
         // indexes the exact same set of resources.
         PL_DHashTableEnumerate(&mForwardArcs, DeleteForwardArcsEntry, nullptr);
         PL_DHashTableFinish(&mForwardArcs);
     }
-    if (mReverseArcs.ops)
+    if (mReverseArcs.IsInitialized())
         PL_DHashTableFinish(&mReverseArcs);
 
     PR_LOG(gLog, PR_LOG_NOTICE,
            ("InMemoryDataSource(%p): destroyed.", this));
 
     MOZ_COUNT_DTOR(InMemoryDataSource);
 }
 
--- a/rdf/base/nsRDFService.cpp
+++ b/rdf/base/nsRDFService.cpp
@@ -765,25 +765,25 @@ RDFServiceImpl::Init()
 
 
 RDFServiceImpl::~RDFServiceImpl()
 {
     if (mNamedDataSources) {
         PL_HashTableDestroy(mNamedDataSources);
         mNamedDataSources = nullptr;
     }
-    if (mResources.ops)
+    if (mResources.IsInitialized())
         PL_DHashTableFinish(&mResources);
-    if (mLiterals.ops)
+    if (mLiterals.IsInitialized())
         PL_DHashTableFinish(&mLiterals);
-    if (mInts.ops)
+    if (mInts.IsInitialized())
         PL_DHashTableFinish(&mInts);
-    if (mDates.ops)
+    if (mDates.IsInitialized())
         PL_DHashTableFinish(&mDates);
-    if (mBlobs.ops)
+    if (mBlobs.IsInitialized())
         PL_DHashTableFinish(&mBlobs);
     gRDFService = nullptr;
 }
 
 
 // static
 nsresult
 RDFServiceImpl::CreateSingleton(nsISupports* aOuter,
--- a/security/manager/boot/src/nsSecureBrowserUIImpl.cpp
+++ b/security/manager/boot/src/nsSecureBrowserUIImpl.cpp
@@ -128,17 +128,17 @@ nsSecureBrowserUIImpl::nsSecureBrowserUI
 #if defined(PR_LOGGING)
   if (!gSecureDocLog)
     gSecureDocLog = PR_NewLogModule("nsSecureBrowserUI");
 #endif /* PR_LOGGING */
 }
 
 nsSecureBrowserUIImpl::~nsSecureBrowserUIImpl()
 {
-  if (mTransferringRequests.ops) {
+  if (mTransferringRequests.IsInitialized()) {
     PL_DHashTableFinish(&mTransferringRequests);
   }
 }
 
 NS_IMPL_ISUPPORTS(nsSecureBrowserUIImpl,
                   nsISecureBrowserUI,
                   nsIWebProgressListener,
                   nsIFormSubmitObserver,
@@ -462,17 +462,17 @@ nsSecureBrowserUIImpl::OnProgressChange(
   return NS_OK;
 }
 
 void nsSecureBrowserUIImpl::ResetStateTracking()
 {
   ReentrantMonitorAutoEnter lock(mReentrantMonitor);
 
   mDocumentRequestsInProgress = 0;
-  if (mTransferringRequests.ops) {
+  if (mTransferringRequests.IsInitialized()) {
     PL_DHashTableFinish(&mTransferringRequests);
   }
   PL_DHashTableInit(&mTransferringRequests, &gMapOps, sizeof(RequestHashEntry));
 }
 
 void
 nsSecureBrowserUIImpl::EvaluateAndUpdateSecurityState(nsIRequest* aRequest,
                                                       nsISupports *info,
--- a/security/manager/ssl/src/nsCertTree.cpp
+++ b/security/manager/ssl/src/nsCertTree.cpp
@@ -168,17 +168,17 @@ nsCertTree::nsCertTree() : mTreeArray(nu
     do_GetService(kCertOverrideCID);
   mOriginalOverrideService =
     static_cast<nsCertOverrideService*>(origCertOverride.get());
   mCellText = nullptr;
 }
 
 void nsCertTree::ClearCompareHash()
 {
-  if (mCompareCache.ops) {
+  if (mCompareCache.IsInitialized()) {
     PL_DHashTableFinish(&mCompareCache);
   }
 }
 
 nsresult nsCertTree::InitCompareHash()
 {
   ClearCompareHash();
   if (!PL_DHashTableInit(&mCompareCache, &gMapOps,
--- a/security/manager/ssl/src/nsNSSShutDown.cpp
+++ b/security/manager/ssl/src/nsNSSShutDown.cpp
@@ -48,20 +48,20 @@ nsNSSShutDownList::nsNSSShutDownList()
   mActiveSSLSockets = 0;
   PL_DHashTableInit(&mObjects, &gSetOps, sizeof(ObjectHashEntry));
   PL_DHashTableInit(&mPK11LogoutCancelObjects, &gSetOps,
                     sizeof(ObjectHashEntry));
 }
 
 nsNSSShutDownList::~nsNSSShutDownList()
 {
-  if (mObjects.ops) {
+  if (mObjects.IsInitialized()) {
     PL_DHashTableFinish(&mObjects);
   }
-  if (mPK11LogoutCancelObjects.ops) {
+  if (mPK11LogoutCancelObjects.IsInitialized()) {
     PL_DHashTableFinish(&mPK11LogoutCancelObjects);
   }
   PR_ASSERT(this == singleton);
   singleton = nullptr;
 }
 
 void nsNSSShutDownList::remember(nsNSSShutDownObject *o)
 {
--- a/uriloader/base/nsDocLoader.cpp
+++ b/uriloader/base/nsDocLoader.cpp
@@ -134,17 +134,17 @@ nsDocLoader::SetDocLoaderParent(nsDocLoa
 {
   mParent = aParent;
   return NS_OK; 
 }
 
 nsresult
 nsDocLoader::Init()
 {
-  if (!mRequestInfoHash.ops) {
+  if (!mRequestInfoHash.IsInitialized()) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   nsresult rv = NS_NewLoadGroup(getter_AddRefs(mLoadGroup), this);
   if (NS_FAILED(rv)) return rv;
 
   PR_LOG(gDocLoaderLog, PR_LOG_DEBUG, 
          ("DocLoader:%p: load group %x.\n", this, mLoadGroup.get()));
@@ -167,17 +167,17 @@ nsDocLoader::~nsDocLoader()
   // this needed?
   ClearWeakReferences();
 
   Destroy();
 
   PR_LOG(gDocLoaderLog, PR_LOG_DEBUG,
          ("DocLoader:%p: deleted.\n", this));
 
-  if (mRequestInfoHash.ops) {
+  if (mRequestInfoHash.IsInitialized()) {
     PL_DHashTableFinish(&mRequestInfoHash);
   }
 }
 
 
 /*
  * Implementation of ISupports methods...
  */
@@ -1375,17 +1375,17 @@ static PLDHashOperator
 RemoveInfoCallback(PLDHashTable *table, PLDHashEntryHdr *hdr, uint32_t number,
                    void *arg)
 {
   return PL_DHASH_REMOVE;
 }
 
 void nsDocLoader::ClearRequestInfoHash(void)
 {
-  if (!mRequestInfoHash.ops || !mRequestInfoHash.EntryCount()) {
+  if (!mRequestInfoHash.IsInitialized() || !mRequestInfoHash.EntryCount()) {
     // No hash, or the hash is empty, nothing to do here then...
 
     return;
   }
 
   PL_DHashTableEnumerate(&mRequestInfoHash, RemoveInfoCallback, nullptr);
 }
 
--- a/xpcom/base/nsCycleCollector.cpp
+++ b/xpcom/base/nsCycleCollector.cpp
@@ -831,17 +831,17 @@ struct CCGraph
 private:
   PLDHashTable mPtrToNodeMap;
 
 public:
   CCGraph() : mRootCount(0) {}
 
   ~CCGraph()
   {
-    if (mPtrToNodeMap.ops) {
+    if (mPtrToNodeMap.IsInitialized()) {
       PL_DHashTableFinish(&mPtrToNodeMap);
     }
   }
 
   void Init()
   {
     MOZ_ASSERT(IsEmpty(), "Failed to call CCGraph::Clear");
     PL_DHashTableInit(&mPtrToNodeMap, &PtrNodeOps,
@@ -857,17 +857,17 @@ public:
     PL_DHashTableFinish(&mPtrToNodeMap);
   }
 
 #ifdef DEBUG
   bool IsEmpty()
   {
     return mNodes.IsEmpty() && mEdges.IsEmpty() &&
            mWeakMaps.IsEmpty() && mRootCount == 0 &&
-           !mPtrToNodeMap.ops;
+           !mPtrToNodeMap.IsInitialized();
   }
 #endif
 
   PtrInfo* FindNode(void* aPtr);
   PtrToNodeEntry* AddNodeToMap(void* aPtr);
   void RemoveNodeFromMap(void* aPtr);
 
   uint32_t MapCount() const
--- a/xpcom/ds/nsAtomTable.cpp
+++ b/xpcom/ds/nsAtomTable.cpp
@@ -35,18 +35,16 @@ using namespace mozilla;
 #endif
 
 /**
  * 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.
- *
- * If |gAtomTable.ops| is 0, then the table is uninitialized.
  */
 static PLDHashTable gAtomTable;
 
 class StaticAtomEntry : public PLDHashEntryHdr
 {
 public:
   typedef const nsAString& KeyType;
   typedef const nsAString* KeyTypePointer;
@@ -337,17 +335,17 @@ PromoteToPermanent(AtomImpl* aAtom)
   aAtom = new (aAtom) PermanentAtomImpl();
 }
 
 void
 NS_PurgeAtomTable()
 {
   delete gStaticAtomTable;
 
-  if (gAtomTable.ops) {
+  if (gAtomTable.IsInitialized()) {
 #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);
       printf("*** %u non-permanent atoms leaked\n", leaked);
@@ -397,24 +395,24 @@ 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.ops, "uninitialized atom hashtable");
+  NS_PRECONDITION(gAtomTable.IsInitialized(), "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.ops && gAtomTable.EntryCount() == 0) {
+    if (gAtomTable.IsInitialized() && gAtomTable.EntryCount() == 0) {
       PL_DHashTableFinish(&gAtomTable);
       NS_ASSERTION(gAtomTable.EntryCount() == 0,
                    "PL_DHashTableFinish changed the entry count");
     }
   }
 
   nsStringBuffer::FromData(mString)->Release();
 }
@@ -523,17 +521,17 @@ 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.ops
+  *aMain = gAtomTable.IsInitialized()
          ? 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
@@ -541,17 +539,17 @@ NS_SizeOfAtomTablesIncludingThis(MallocS
            : 0;
 }
 
 #define ATOM_HASHTABLE_INITIAL_LENGTH  2048
 
 static inline void
 EnsureTableExists()
 {
-  if (!gAtomTable.ops) {
+  if (!gAtomTable.IsInitialized()) {
     PL_DHashTableInit(&gAtomTable, &AtomTableOps,
                       sizeof(AtomTableEntry), ATOM_HASHTABLE_INITIAL_LENGTH);
   }
 }
 
 static inline AtomTableEntry*
 GetAtomHashEntry(const char* aString, uint32_t aLength, uint32_t* aHashOut)
 {
--- a/xpcom/ds/nsPersistentProperties.cpp
+++ b/xpcom/ds/nsPersistentProperties.cpp
@@ -464,17 +464,17 @@ nsPersistentProperties::nsPersistentProp
                     sizeof(PropertyTableEntry), 16);
 
   PL_INIT_ARENA_POOL(&mArena, "PersistentPropertyArena", 2048);
 }
 
 nsPersistentProperties::~nsPersistentProperties()
 {
   PL_FinishArenaPool(&mArena);
-  if (mTable.ops) {
+  if (mTable.IsInitialized()) {
     PL_DHashTableFinish(&mTable);
   }
 }
 
 nsresult
 nsPersistentProperties::Create(nsISupports* aOuter, REFNSIID aIID,
                                void** aResult)
 {
--- a/xpcom/ds/nsStaticNameTable.cpp
+++ b/xpcom/ds/nsStaticNameTable.cpp
@@ -112,28 +112,28 @@ nsStaticCaseInsensitiveNameTable::~nsSta
 {
   if (mNameArray) {
     // manually call the destructor on placement-new'ed objects
     for (uint32_t index = 0; index < mNameTable.EntryCount(); index++) {
       mNameArray[index].~nsDependentCString();
     }
     nsMemory::Free((void*)mNameArray);
   }
-  if (mNameTable.ops) {
+  if (mNameTable.IsInitialized()) {
     PL_DHashTableFinish(&mNameTable);
   }
   MOZ_COUNT_DTOR(nsStaticCaseInsensitiveNameTable);
 }
 
 bool
 nsStaticCaseInsensitiveNameTable::Init(const char* const aNames[],
                                        int32_t aLength)
 {
   NS_ASSERTION(!mNameArray, "double Init");
-  NS_ASSERTION(!mNameTable.ops, "double Init");
+  NS_ASSERTION(!mNameTable.IsInitialized(), "double Init");
   NS_ASSERTION(aNames, "null name table");
   NS_ASSERTION(aLength, "0 length");
 
   mNameArray = (nsDependentCString*)
     nsMemory::Alloc(aLength * sizeof(nsDependentCString));
   if (!mNameArray) {
     return false;
   }
@@ -180,17 +180,17 @@ nsStaticCaseInsensitiveNameTable::Init(c
 #endif
   return true;
 }
 
 int32_t
 nsStaticCaseInsensitiveNameTable::Lookup(const nsACString& aName)
 {
   NS_ASSERTION(mNameArray, "not inited");
-  NS_ASSERTION(mNameTable.ops, "not inited");
+  NS_ASSERTION(mNameTable.IsInitialized(), "not inited");
 
   const nsAFlatCString& str = PromiseFlatCString(aName);
 
   NameTableKey key(&str);
   NameTableEntry* entry =
     static_cast<NameTableEntry*>(PL_DHashTableLookup(&mNameTable, &key));
   if (PL_DHASH_ENTRY_IS_FREE(entry)) {
     return nsStaticCaseInsensitiveNameTable::NOT_FOUND;
@@ -198,17 +198,17 @@ nsStaticCaseInsensitiveNameTable::Lookup
 
   return entry->mIndex;
 }
 
 int32_t
 nsStaticCaseInsensitiveNameTable::Lookup(const nsAString& aName)
 {
   NS_ASSERTION(mNameArray, "not inited");
-  NS_ASSERTION(mNameTable.ops, "not inited");
+  NS_ASSERTION(mNameTable.IsInitialized(), "not inited");
 
   const nsAFlatString& str = PromiseFlatString(aName);
 
   NameTableKey key(&str);
   NameTableEntry* entry =
     static_cast<NameTableEntry*>(PL_DHashTableLookup(&mNameTable, &key));
   if (PL_DHASH_ENTRY_IS_FREE(entry)) {
     return nsStaticCaseInsensitiveNameTable::NOT_FOUND;
@@ -216,15 +216,15 @@ nsStaticCaseInsensitiveNameTable::Lookup
 
   return entry->mIndex;
 }
 
 const nsAFlatCString&
 nsStaticCaseInsensitiveNameTable::GetStringValue(int32_t aIndex)
 {
   NS_ASSERTION(mNameArray, "not inited");
-  NS_ASSERTION(mNameTable.ops, "not inited");
+  NS_ASSERTION(mNameTable.IsInitialized(), "not inited");
 
   if ((NOT_FOUND < aIndex) && ((uint32_t)aIndex < mNameTable.EntryCount())) {
     return mNameArray[aIndex];
   }
   return mNullStr;
 }
--- a/xpcom/glue/nsBaseHashtable.h
+++ b/xpcom/glue/nsBaseHashtable.h
@@ -162,17 +162,17 @@ public:
 
   /**
    * enumerate entries in the hashtable, without allowing changes
    * @param aEnumFunc enumeration callback
    * @param aUserArg passed unchanged to the EnumReadFunction
    */
   uint32_t EnumerateRead(EnumReadFunction aEnumFunc, void* aUserArg) const
   {
-    NS_ASSERTION(this->mTable.ops,
+    NS_ASSERTION(this->mTable.IsInitialized(),
                  "nsBaseHashtable was not initialized properly.");
 
     s_EnumReadArgs enumData = { aEnumFunc, aUserArg };
     return PL_DHashTableEnumerate(const_cast<PLDHashTable*>(&this->mTable),
                                   s_EnumReadStub,
                                   &enumData);
   }
 
@@ -194,17 +194,17 @@ public:
   /**
    * enumerate entries in the hashtable, allowing changes. This
    * functions write-locks the hashtable.
    * @param aEnumFunc enumeration callback
    * @param aUserArg passed unchanged to the EnumFunction
    */
   uint32_t Enumerate(EnumFunction aEnumFunc, void* aUserArg)
   {
-    NS_ASSERTION(this->mTable.ops,
+    NS_ASSERTION(this->mTable.IsInitialized(),
                  "nsBaseHashtable was not initialized properly.");
 
     s_EnumArgs enumData = { aEnumFunc, aUserArg };
     return PL_DHashTableEnumerate(&this->mTable,
                                   s_EnumStub,
                                   &enumData);
   }
 
--- a/xpcom/glue/nsTHashtable.h
+++ b/xpcom/glue/nsTHashtable.h
@@ -121,17 +121,18 @@ public:
   /**
    * Get the entry associated with a key.
    * @param     aKey the key to retrieve
    * @return    pointer to the entry class, if the key exists; nullptr if the
    *            key doesn't exist
    */
   EntryType* GetEntry(KeyType aKey) const
   {
-    NS_ASSERTION(mTable.ops, "nsTHashtable was not initialized properly.");
+    NS_ASSERTION(mTable.IsInitialized(),
+                 "nsTHashtable was not initialized properly.");
 
     EntryType* entry = reinterpret_cast<EntryType*>(
       PL_DHashTableLookup(const_cast<PLDHashTable*>(&mTable),
                           EntryType::KeyToPointer(aKey)));
     return PL_DHASH_ENTRY_IS_BUSY(entry) ? entry : nullptr;
   }
 
   /**
@@ -152,29 +153,31 @@ public:
     EntryType* e = PutEntry(aKey, fallible_t());
     if (!e) {
       NS_ABORT_OOM(mTable.EntrySize() * mTable.EntryCount());
     }
     return e;
   }
 
   EntryType* PutEntry(KeyType aKey, const fallible_t&) NS_WARN_UNUSED_RESULT {
-    NS_ASSERTION(mTable.ops, "nsTHashtable was not initialized properly.");
+    NS_ASSERTION(mTable.IsInitialized(),
+                 "nsTHashtable was not initialized properly.");
 
     return static_cast<EntryType*>(PL_DHashTableAdd(
       &mTable, EntryType::KeyToPointer(aKey)));
   }
 
   /**
    * Remove the entry associated with a key.
    * @param     aKey of the entry to remove
    */
   void RemoveEntry(KeyType aKey)
   {
-    NS_ASSERTION(mTable.ops, "nsTHashtable was not initialized properly.");
+    NS_ASSERTION(mTable.IsInitialized(),
+                 "nsTHashtable was not initialized properly.");
 
     PL_DHashTableRemove(&mTable,
                         EntryType::KeyToPointer(aKey));
   }
 
   /**
    * Remove the entry associated with a key, but don't resize the hashtable.
    * This is a low-level method, and is not recommended unless you know what
@@ -204,28 +207,30 @@ public:
    * Enumerate all the entries of the function.
    * @param     enumFunc the <code>Enumerator</code> function to call
    * @param     userArg a pointer to pass to the
    *            <code>Enumerator</code> function
    * @return    the number of entries actually enumerated
    */
   uint32_t EnumerateEntries(Enumerator aEnumFunc, void* aUserArg)
   {
-    NS_ASSERTION(mTable.ops, "nsTHashtable was not initialized properly.");
+    NS_ASSERTION(mTable.IsInitialized(),
+                 "nsTHashtable was not initialized properly.");
 
     s_EnumArgs args = { aEnumFunc, aUserArg };
     return PL_DHashTableEnumerate(&mTable, s_EnumStub, &args);
   }
 
   /**
    * remove all entries, return hashtable to "pristine" state ;)
    */
   void Clear()
   {
-    NS_ASSERTION(mTable.ops, "nsTHashtable was not initialized properly.");
+    NS_ASSERTION(mTable.IsInitialized(),
+                 "nsTHashtable was not initialized properly.");
 
     PL_DHashTableEnumerate(&mTable, PL_DHashStubEnumRemove, nullptr);
   }
 
   /**
    * client must provide a <code>SizeOfEntryExcludingThisFun</code> function for
    *   SizeOfExcludingThis.
    * @param     aEntry the entry being enumerated
@@ -304,17 +309,18 @@ public:
   /**
    * Mark the table as constant after initialization.
    *
    * This will prevent assertions when a read-only hash is accessed on multiple
    * threads without synchronization.
    */
   void MarkImmutable()
   {
-    NS_ASSERTION(mTable.ops, "nsTHashtable was not initialized properly.");
+    NS_ASSERTION(mTable.IsInitialized(),
+                 "nsTHashtable was not initialized properly.");
 
     PL_DHashMarkTableImmutable(&mTable);
   }
 #endif
 
 protected:
   PLDHashTable mTable;
 
@@ -403,17 +409,17 @@ nsTHashtable<EntryType>::nsTHashtable(ns
   // Indicate that aOther is not initialized.  This will make its destructor a
   // nop, which is what we want.
   aOther.mTable.ops = nullptr;
 }
 
 template<class EntryType>
 nsTHashtable<EntryType>::~nsTHashtable()
 {
-  if (mTable.ops) {
+  if (mTable.IsInitialized()) {
     PL_DHashTableFinish(&mTable);
   }
 }
 
 template<class EntryType>
 void
 nsTHashtable<EntryType>::Init(uint32_t aInitLength)
 {
--- a/xpcom/glue/pldhash.h
+++ b/xpcom/glue/pldhash.h
@@ -217,32 +217,35 @@ private:
     uint32_t        mGrows;         /* table expansions */
     uint32_t        mShrinks;       /* table contractions */
     uint32_t        mCompresses;    /* table compressions */
     uint32_t        mEnumShrinks;   /* contractions after Enumerate */
   } mStats;
 #endif
 
 public:
-  // All the other fields are initialized in Init(), but we zero |ops| here
-  // because it's used to determine if Init() has been called.
+  // The most important thing here is that we zero |ops| because it's used to
+  // determine if Init() has been called. (The use of MOZ_CONSTEXPR means all
+  // the other members must be initialized too.)
   MOZ_CONSTEXPR PLDHashTable()
     : ops(nullptr)
     , mHashShift(0)
     , mRecursionLevel(0)
     , mEntrySize(0)
     , mEntryCount(0)
     , mRemovedCount(0)
     , mGeneration(0)
     , mEntryStore(nullptr)
 #ifdef PL_DHASHMETER
     , mStats()
 #endif
   {}
 
+  bool IsInitialized() const { return !!ops; }
+
   /*
    * Size in entries (gross, not net of free and removed sentinels) for table.
    * We store mHashShift rather than sizeLog2 to optimize the collision-free
    * case in SearchTable.
    */
   uint32_t Capacity() const
   {
     return ((uint32_t)1 << (PL_DHASH_BITS - mHashShift));
--- a/xpcom/tests/TestPLDHash.cpp
+++ b/xpcom/tests/TestPLDHash.cpp
@@ -14,74 +14,74 @@
 
 namespace TestPLDHash {
 
 static bool test_pldhash_Init_capacity_ok()
 {
   PLDHashTable t;
 
   // Check that the constructor nulls |ops|.
-  if (t.ops) {
+  if (t.IsInitialized()) {
     return false;
   }
 
   // Try the largest allowed capacity.  With PL_DHASH_MAX_CAPACITY==1<<26, this
   // will allocate 0.5GB of entry store on 32-bit platforms and 1GB on 64-bit
   // platforms.
   if (!PL_DHashTableInit(&t, PL_DHashGetStubOps(), sizeof(PLDHashEntryStub),
                          mozilla::fallible_t(), PL_DHASH_MAX_INITIAL_LENGTH)) {
     return false;
   }
 
   // Check that Init() sets |ops|.
-  if (!t.ops) {
+  if (!t.IsInitialized()) {
     return false;
   }
 
   // Check that Finish() nulls |ops|.
   PL_DHashTableFinish(&t);
-  if (t.ops) {
+  if (t.IsInitialized()) {
     return false;
   }
 
   return true;
 }
 
 static bool test_pldhash_Init_capacity_too_large()
 {
   PLDHashTable t;
 
   // Check that the constructor nulls |ops|.
-  if (t.ops) {
+  if (t.IsInitialized()) {
     return false;
   }
 
   // Try the smallest too-large capacity.
   if (PL_DHashTableInit(&t, PL_DHashGetStubOps(),
                         sizeof(PLDHashEntryStub),
                         mozilla::fallible_t(),
                         PL_DHASH_MAX_INITIAL_LENGTH + 1)) {
     return false;   // it succeeded!?
   }
   // Don't call PL_DHashTableFinish() here; it's not safe after Init() failure.
 
   // Check that |ops| is still null.
-  if (t.ops) {
+  if (t.IsInitialized()) {
     return false;
   }
 
   return true;
 }
 
 static bool test_pldhash_Init_overflow()
 {
   PLDHashTable t;
 
   // Check that the constructor nulls |ops|.
-  if (t.ops) {
+  if (t.IsInitialized()) {
     return false;
   }
 
   // Try an acceptable capacity, but one whose byte size overflows uint32_t.
   //
   // Ideally we'd also try a large-but-ok capacity that almost but doesn't
   // quite overflow, but that would result in allocating just under 4GB of
   // entry storage.  That's very likely to fail on 32-bit platforms, so such a
@@ -94,17 +94,17 @@ static bool test_pldhash_Init_overflow()
 
   if (PL_DHashTableInit(&t, PL_DHashGetStubOps(), sizeof(OneKBEntry),
                         mozilla::fallible_t(), PL_DHASH_MAX_INITIAL_LENGTH)) {
     return false;   // it succeeded!?
   }
   // Don't call PL_DHashTableFinish() here; it's not safe after Init() failure.
 
   // Check that |ops| is still null.
-  if (t.ops) {
+  if (t.IsInitialized()) {
     return false;
   }
 
   return true;
 }
 
 // See bug 931062, we skip this test on Android due to OOM.
 #ifndef MOZ_WIDGET_ANDROID
@@ -125,18 +125,18 @@ static bool test_pldhash_grow_to_max_cap
     PL_DHashMoveEntryStub,
     PL_DHashClearEntryStub,
     nullptr
   };
 
   // This is infallible.
   PLDHashTable* t = PL_NewDHashTable(&ops, sizeof(PLDHashEntryStub), 128);
 
-  // Check that New() sets |ops|.
-  if (!t->ops) {
+  // Check that New() sets |t->ops|.
+  if (!t->IsInitialized()) {
     return false;
   }
 
   // Keep inserting elements until failure occurs because the table is full.
   size_t numInserted = 0;
   while (true) {
     if (!PL_DHashTableAdd(t, (const void*)numInserted)) {
       break;