Backout c375efe78e07 (bug 1161377 part 3) for (probably) increasing the static constructor count and regressing Fennec start-up time. r=me.
authorNicholas Nethercote <nnethercote@mozilla.com>
Sun, 10 May 2015 22:16:18 -0700
changeset 243331 3cd634573d29d195bae4718bc4c6aba1032a1f7b
parent 243330 5ec60cbf124c89669f4b3bbe6c84bd6bc1e8150a
child 243332 e2aabff6bd77fb01564d47d139010e56bb0ae326
push id28738
push usercbook@mozilla.com
push dateTue, 12 May 2015 14:11:31 +0000
treeherdermozilla-central@bedce1b405a3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersme
bugs1161377
milestone40.0a1
backs outc375efe78e070322db1cbfcf7b373ab1c6830e17
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
Backout c375efe78e07 (bug 1161377 part 3) for (probably) increasing the static constructor count and regressing Fennec start-up time. r=me.
dom/base/nsPropertyTable.cpp
gfx/thebes/gfxFT2FontList.cpp
layout/style/nsCSSRuleProcessor.cpp
security/manager/ssl/src/nsNSSShutDown.cpp
security/manager/ssl/src/nsNSSShutDown.h
uriloader/base/nsDocLoader.cpp
uriloader/base/nsDocLoader.h
xpcom/ds/nsPersistentProperties.cpp
xpcom/tests/TestPLDHash.cpp
--- a/dom/base/nsPropertyTable.cpp
+++ b/dom/base/nsPropertyTable.cpp
@@ -282,28 +282,31 @@ nsPropertyTable::GetPropertyListFor(nsIA
 
 //----------------------------------------------------------------------
 
 nsPropertyTable::PropertyList::PropertyList(nsIAtom            *aName,
                                             NSPropertyDtorFunc  aDtorFunc,
                                             void               *aDtorData,
                                             bool                aTransfer)
   : mName(aName),
-    mObjectValueMap(PL_DHashGetStubOps(), sizeof(PropertyListMapEntry)),
     mDtorFunc(aDtorFunc),
     mDtorData(aDtorData),
     mTransfer(aTransfer),
     mNext(nullptr)
 {
+  PL_DHashTableInit(&mObjectValueMap, PL_DHashGetStubOps(),
+                    sizeof(PropertyListMapEntry));
 }
 
 nsPropertyTable::PropertyList::~PropertyList()
 {
+  PL_DHashTableFinish(&mObjectValueMap);
 }
 
+
 static PLDHashOperator
 DestroyPropertyEnumerator(PLDHashTable *table, PLDHashEntryHdr *hdr,
                           uint32_t number, void *arg)
 {
   nsPropertyTable::PropertyList *propList =
       static_cast<nsPropertyTable::PropertyList*>(arg);
   PropertyListMapEntry* entry = static_cast<PropertyListMapEntry*>(hdr);
 
--- a/gfx/thebes/gfxFT2FontList.cpp
+++ b/gfx/thebes/gfxFT2FontList.cpp
@@ -612,35 +612,49 @@ FT2FontFamily::AddFacesToFontList(Infall
  * find their attributes), leading to significantly quicker startup.
  */
 
 #define CACHE_KEY "font.cached-list"
 
 class FontNameCache {
 public:
     FontNameCache()
-        : mMap(&sMapOps, sizeof(FNCMapEntry), 0)
-        , mWriteNeeded(false)
+        : mWriteNeeded(false)
     {
+        mOps = (PLDHashTableOps) {
+            StringHash,
+            HashMatchEntry,
+            MoveEntry,
+            PL_DHashClearEntryStub,
+            nullptr
+        };
+
+        PL_DHashTableInit(&mMap, &mOps, sizeof(FNCMapEntry), 0);
+
         MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default,
                    "StartupCacheFontNameCache should only be used in chrome "
                    "process");
         mCache = mozilla::scache::StartupCache::GetSingleton();
 
         Init();
     }
 
     ~FontNameCache()
     {
+        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.IsInitialized() || !mCache) {
             return;
         }
@@ -732,17 +746,17 @@ public:
         mWriteNeeded = true;
     }
 
 private:
     mozilla::scache::StartupCache* mCache;
     PLDHashTable mMap;
     bool mWriteNeeded;
 
-    static const PLDHashTableOps sMapOps;
+    PLDHashTableOps mOps;
 
     static PLDHashOperator WriteOutMap(PLDHashTable *aTable,
                                        PLDHashEntryHdr *aHdr,
                                        uint32_t aNumber, void *aData)
     {
         FNCMapEntry* entry = static_cast<FNCMapEntry*>(aHdr);
         if (!entry->mFileExists) {
             // skip writing entries for files that are no longer present
@@ -791,25 +805,16 @@ private:
         to->mFilename.Assign(from->mFilename);
         to->mTimestamp = from->mTimestamp;
         to->mFilesize = from->mFilesize;
         to->mFaces.Assign(from->mFaces);
         to->mFileExists = from->mFileExists;
     }
 };
 
-/* static */ const PLDHashTableOps FontNameCache::sMapOps =
-{
-    FontNameCache::StringHash,
-    FontNameCache::HashMatchEntry,
-    FontNameCache::MoveEntry,
-    PL_DHashClearEntryStub,
-    nullptr
-};
-
 /***************************************************************
  *
  * gfxFT2FontList
  *
  */
 
 // For Mobile, we use gfxFT2Fonts, and we build the font list by directly
 // scanning the system's Fonts directory for OpenType and TrueType files.
--- a/layout/style/nsCSSRuleProcessor.cpp
+++ b/layout/style/nsCSSRuleProcessor.cpp
@@ -484,24 +484,16 @@ protected:
   uint32_t    mElementTagCalls;
   uint32_t    mElementClassCalls;
   uint32_t    mElementIdCalls;
 #endif // RULE_HASH_STATS
 };
 
 RuleHash::RuleHash(bool aQuirksMode)
   : mRuleCount(0),
-    mIdTable(aQuirksMode ? &RuleHash_IdTable_CIOps.ops
-                         : &RuleHash_IdTable_CSOps.ops,
-             sizeof(RuleHashTableEntry)),
-    mClassTable(aQuirksMode ? &RuleHash_ClassTable_CIOps.ops
-                            : &RuleHash_ClassTable_CSOps.ops,
-                sizeof(RuleHashTableEntry)),
-    mTagTable(&RuleHash_TagTable_Ops, sizeof(RuleHashTagTableEntry)),
-    mNameSpaceTable(&RuleHash_NameSpaceTable_Ops, sizeof(RuleHashTableEntry)),
     mUniversalRules(0),
     mEnumList(nullptr), mEnumListSize(0),
     mQuirksMode(aQuirksMode)
 #ifdef RULE_HASH_STATS
     ,
     mUniversalSelectors(0),
     mNameSpaceSelectors(0),
     mTagSelectors(0),
@@ -511,16 +503,30 @@ RuleHash::RuleHash(bool aQuirksMode)
     mElementUniversalCalls(0),
     mElementNameSpaceCalls(0),
     mElementTagCalls(0),
     mElementClassCalls(0),
     mElementIdCalls(0)
 #endif
 {
   MOZ_COUNT_CTOR(RuleHash);
+
+  PL_DHashTableInit(&mIdTable, aQuirksMode ? &RuleHash_IdTable_CIOps.ops
+                                           : &RuleHash_IdTable_CSOps.ops,
+                    sizeof(RuleHashTableEntry));
+
+  PL_DHashTableInit(&mClassTable, aQuirksMode ? &RuleHash_ClassTable_CIOps.ops
+                                              : &RuleHash_ClassTable_CSOps.ops,
+                    sizeof(RuleHashTableEntry));
+
+  PL_DHashTableInit(&mTagTable, &RuleHash_TagTable_Ops,
+                    sizeof(RuleHashTagTableEntry));
+
+  PL_DHashTableInit(&mNameSpaceTable, &RuleHash_NameSpaceTable_Ops,
+                    sizeof(RuleHashTableEntry));
 }
 
 RuleHash::~RuleHash()
 {
   MOZ_COUNT_DTOR(RuleHash);
 #ifdef RULE_HASH_STATS
   printf(
 "RuleHash(%p):\n"
@@ -552,16 +558,21 @@ RuleHash::~RuleHash()
 #endif // PRINT_UNIVERSAL_RULES
 #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
+  PL_DHashTableFinish(&mIdTable);
+  PL_DHashTableFinish(&mClassTable);
+  PL_DHashTableFinish(&mTagTable);
+  PL_DHashTableFinish(&mNameSpaceTable);
 }
 
 void RuleHash::AppendRuleToTable(PLDHashTable* aTable, const void* aKey,
                                  const RuleSelectorPair& aRuleInfo)
 {
   // Get a new or existing entry.
   RuleHashTableEntry *entry = static_cast<RuleHashTableEntry*>
     (PL_DHashTableAdd(aTable, aKey, fallible));
@@ -850,41 +861,52 @@ static const RuleHashTableOps AtomSelect
 
 //--------------------------------
 
 struct RuleCascadeData {
   RuleCascadeData(nsIAtom *aMedium, bool aQuirksMode)
     : mRuleHash(aQuirksMode),
       mStateSelectors(),
       mSelectorDocumentStates(0),
-      mClassSelectors(aQuirksMode ? &AtomSelector_CIOps.ops
-                                  : &AtomSelector_CSOps,
-                      sizeof(AtomSelectorEntry)),
-      mIdSelectors(aQuirksMode ? &AtomSelector_CIOps.ops
-                               : &AtomSelector_CSOps,
-                   sizeof(AtomSelectorEntry)),
-      // mAttributeSelectors is matching on the attribute _name_, not the
-      // value, and we case-fold names at parse-time, so this is a
-      // case-sensitive match.
-      mAttributeSelectors(&AtomSelector_CSOps, sizeof(AtomSelectorEntry)),
-      mAnonBoxRules(&RuleHash_TagTable_Ops, sizeof(RuleHashTagTableEntry)),
-#ifdef MOZ_XUL
-      mXULTreeRules(&RuleHash_TagTable_Ops, sizeof(RuleHashTagTableEntry)),
-#endif
       mKeyframesRuleTable(),
       mCounterStyleRuleTable(),
       mCacheKey(aMedium),
       mNext(nullptr),
       mQuirksMode(aQuirksMode)
   {
+    // mAttributeSelectors is matching on the attribute _name_, not the value,
+    // and we case-fold names at parse-time, so this is a case-sensitive match.
+    PL_DHashTableInit(&mAttributeSelectors, &AtomSelector_CSOps,
+                      sizeof(AtomSelectorEntry));
+    PL_DHashTableInit(&mAnonBoxRules, &RuleHash_TagTable_Ops,
+                      sizeof(RuleHashTagTableEntry));
+    PL_DHashTableInit(&mIdSelectors,
+                      aQuirksMode ? &AtomSelector_CIOps.ops :
+                                    &AtomSelector_CSOps,
+                      sizeof(AtomSelectorEntry));
+    PL_DHashTableInit(&mClassSelectors,
+                      aQuirksMode ? &AtomSelector_CIOps.ops :
+                                    &AtomSelector_CSOps,
+                      sizeof(AtomSelectorEntry));
     memset(mPseudoElementRuleHashes, 0, sizeof(mPseudoElementRuleHashes));
+#ifdef MOZ_XUL
+    PL_DHashTableInit(&mXULTreeRules, &RuleHash_TagTable_Ops,
+                      sizeof(RuleHashTagTableEntry));
+#endif
   }
 
   ~RuleCascadeData()
   {
+    PL_DHashTableFinish(&mAttributeSelectors);
+    PL_DHashTableFinish(&mAnonBoxRules);
+    PL_DHashTableFinish(&mIdSelectors);
+    PL_DHashTableFinish(&mClassSelectors);
+#ifdef MOZ_XUL
+    PL_DHashTableFinish(&mXULTreeRules);
+#endif
     for (uint32_t i = 0; i < ArrayLength(mPseudoElementRuleHashes); ++i) {
       delete mPseudoElementRuleHashes[i];
     }
   }
 
   size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const;
 
   RuleHash                 mRuleHash;
@@ -3293,26 +3315,30 @@ struct CascadeEnumData {
                   uint8_t aSheetType)
     : mPresContext(aPresContext),
       mFontFaceRules(aFontFaceRules),
       mKeyframesRules(aKeyframesRules),
       mFontFeatureValuesRules(aFontFeatureValuesRules),
       mPageRules(aPageRules),
       mCounterStyleRules(aCounterStyleRules),
       mCacheKey(aKey),
-      mRulesByWeight(&gRulesByWeightOps, sizeof(RuleByWeightEntry), 32),
       mSheetType(aSheetType)
   {
+    PL_DHashTableInit(&mRulesByWeight, &gRulesByWeightOps,
+                      sizeof(RuleByWeightEntry), 32);
+
     // Initialize our arena
     PL_INIT_ARENA_POOL(&mArena, "CascadeEnumDataArena",
                        NS_CASCADEENUMDATA_ARENA_BLOCK_SIZE);
   }
 
   ~CascadeEnumData()
   {
+    if (mRulesByWeight.IsInitialized())
+      PL_DHashTableFinish(&mRulesByWeight);
     PL_FinishArenaPool(&mArena);
   }
 
   nsPresContext* mPresContext;
   nsTArray<nsFontFaceRuleContainer>& mFontFaceRules;
   nsTArray<nsCSSKeyframesRule*>& mKeyframesRules;
   nsTArray<nsCSSFontFeatureValuesRule*>& mFontFeatureValuesRules;
   nsTArray<nsCSSPageRule*>& mPageRules;
--- a/security/manager/ssl/src/nsNSSShutDown.cpp
+++ b/security/manager/ssl/src/nsNSSShutDown.cpp
@@ -34,25 +34,32 @@ static const PLDHashTableOps gSetOps = {
   PL_DHashMoveEntryStub,
   PL_DHashClearEntryStub,
   ObjectSetInitEntry
 };
 
 nsNSSShutDownList *nsNSSShutDownList::singleton = nullptr;
 
 nsNSSShutDownList::nsNSSShutDownList()
-  : mListLock("nsNSSShutDownList.mListLock")
-  , mActiveSSLSockets(0)
-  , mObjects(&gSetOps, sizeof(ObjectHashEntry))
-  , mPK11LogoutCancelObjects(&gSetOps, sizeof(ObjectHashEntry))
+:mListLock("nsNSSShutDownList.mListLock")
 {
+  mActiveSSLSockets = 0;
+  PL_DHashTableInit(&mObjects, &gSetOps, sizeof(ObjectHashEntry));
+  PL_DHashTableInit(&mPK11LogoutCancelObjects, &gSetOps,
+                    sizeof(ObjectHashEntry));
 }
 
 nsNSSShutDownList::~nsNSSShutDownList()
 {
+  if (mObjects.IsInitialized()) {
+    PL_DHashTableFinish(&mObjects);
+  }
+  if (mPK11LogoutCancelObjects.IsInitialized()) {
+    PL_DHashTableFinish(&mPK11LogoutCancelObjects);
+  }
   PR_ASSERT(this == singleton);
   singleton = nullptr;
 }
 
 void nsNSSShutDownList::remember(nsNSSShutDownObject *o)
 {
   if (!singleton)
     return;
--- a/security/manager/ssl/src/nsNSSShutDown.h
+++ b/security/manager/ssl/src/nsNSSShutDown.h
@@ -152,18 +152,18 @@ private:
                                                         uint32_t number, void *arg);
 
   static PLDHashOperator
   doPK11LogoutHelper(PLDHashTable *table, PLDHashEntryHdr *hdr,
                                                     uint32_t number, void *arg);
 protected:
   mozilla::Mutex mListLock;
   static nsNSSShutDownList *singleton;
+  PLDHashTable mObjects;
   uint32_t mActiveSSLSockets;
-  PLDHashTable mObjects;
   PLDHashTable mPK11LogoutCancelObjects;
   nsNSSActivityState mActivityState;
 };
 
 /*
   A class deriving from nsNSSShutDownObject will have its instances
   automatically tracked in a list. However, it must follow some rules
   to assure correct behaviour.
--- a/uriloader/base/nsDocLoader.cpp
+++ b/uriloader/base/nsDocLoader.cpp
@@ -86,58 +86,63 @@ class nsDefaultComparator <nsDocLoader::
     bool Equals(const nsDocLoader::nsListenerInfo& aInfo,
                 nsIWebProgressListener* const& aListener) const {
       nsCOMPtr<nsIWebProgressListener> listener =
                                        do_QueryReferent(aInfo.mWeakListener);
       return aListener == listener;
     }
 };
 
-/* static */ const PLDHashTableOps nsDocLoader::sRequestInfoHashOps =
-{
-  PL_DHashVoidPtrKeyStub,
-  PL_DHashMatchEntryStub,
-  PL_DHashMoveEntryStub,
-  nsDocLoader::RequestInfoHashClearEntry,
-  nsDocLoader::RequestInfoHashInitEntry
-};
-
 nsDocLoader::nsDocLoader()
   : mParent(nullptr),
     mCurrentSelfProgress(0),
     mMaxSelfProgress(0),
     mCurrentTotalProgress(0),
     mMaxTotalProgress(0),
-    mRequestInfoHash(&sRequestInfoHashOps, sizeof(nsRequestInfo)),
     mCompletedTotalProgress(0),
     mIsLoadingDocument(false),
     mIsRestoringDocument(false),
     mDontFlushLayout(false),
     mIsFlushingLayout(false)
 {
   if (nullptr == gDocLoaderLog) {
       gDocLoaderLog = PR_NewLogModule("DocLoader");
   }
 
+  static const PLDHashTableOps hash_table_ops =
+  {
+    PL_DHashVoidPtrKeyStub,
+    PL_DHashMatchEntryStub,
+    PL_DHashMoveEntryStub,
+    RequestInfoHashClearEntry,
+    RequestInfoHashInitEntry
+  };
+
+  PL_DHashTableInit(&mRequestInfoHash, &hash_table_ops, sizeof(nsRequestInfo));
+
   ClearInternalProgress();
 
   PR_LOG(gDocLoaderLog, PR_LOG_DEBUG,
          ("DocLoader:%p: created.\n", this));
 }
 
 nsresult
 nsDocLoader::SetDocLoaderParent(nsDocLoader *aParent)
 {
   mParent = aParent;
   return NS_OK;
 }
 
 nsresult
 nsDocLoader::Init()
 {
+  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()));
 
   return NS_OK;
 }
@@ -156,16 +161,20 @@ nsDocLoader::~nsDocLoader()
   // XXXbz now that NS_IMPL_RELEASE stabilizes by setting refcount to 1, is
   // this needed?
   ClearWeakReferences();
 
   Destroy();
 
   PR_LOG(gDocLoaderLog, PR_LOG_DEBUG,
          ("DocLoader:%p: deleted.\n", this));
+
+  if (mRequestInfoHash.IsInitialized()) {
+    PL_DHashTableFinish(&mRequestInfoHash);
+  }
 }
 
 
 /*
  * Implementation of ISupports methods...
  */
 NS_IMPL_ADDREF(nsDocLoader)
 NS_IMPL_RELEASE(nsDocLoader)
@@ -1347,16 +1356,22 @@ static PLDHashOperator
 RemoveInfoCallback(PLDHashTable *table, PLDHashEntryHdr *hdr, uint32_t number,
                    void *arg)
 {
   return PL_DHASH_REMOVE;
 }
 
 void nsDocLoader::ClearRequestInfoHash(void)
 {
+  if (!mRequestInfoHash.IsInitialized() || !mRequestInfoHash.EntryCount()) {
+    // No hash, or the hash is empty, nothing to do here then...
+
+    return;
+  }
+
   PL_DHashTableEnumerate(&mRequestInfoHash, RemoveInfoCallback, nullptr);
 }
 
 // PLDHashTable enumeration callback that calculates the max progress.
 PLDHashOperator
 nsDocLoader::CalcMaxProgressCallback(PLDHashTable* table, PLDHashEntryHdr* hdr,
                                      uint32_t number, void* arg)
 {
--- a/uriloader/base/nsDocLoader.h
+++ b/uriloader/base/nsDocLoader.h
@@ -297,18 +297,16 @@ protected:
 
     /* Flag to indicate whether we should consider ourselves as currently
        flushing layout for the purposes of IsBusy. For example, if Stop has
        been called then IsBusy should return false even if we are still
        flushing. */
     bool mIsFlushingLayout;
 
 private:
-    static const PLDHashTableOps sRequestInfoHashOps;
-
     // A list of kids that are in the middle of their onload calls and will let
     // us know once they're done.  We don't want to fire onload for "normal"
     // DocLoaderIsEmpty calls (those coming from requests finishing in our
     // loadgroup) unless this is empty.
     nsCOMArray<nsIDocumentLoader> mChildrenInOnload;
 
     // DocLoaderIsEmpty should be called whenever the docloader may be empty.
     // This method is idempotent and does nothing if the docloader is not in
--- a/xpcom/ds/nsPersistentProperties.cpp
+++ b/xpcom/ds/nsPersistentProperties.cpp
@@ -455,24 +455,29 @@ nsPropertiesParser::ParseBuffer(const ch
     mKey += Substring(tokenStart, cur);
   }
 
   return NS_OK;
 }
 
 nsPersistentProperties::nsPersistentProperties()
   : mIn(nullptr)
-  , mTable(&property_HashTableOps, sizeof(PropertyTableEntry), 16)
 {
+  PL_DHashTableInit(&mTable, &property_HashTableOps,
+                    sizeof(PropertyTableEntry), 16);
+
   PL_INIT_ARENA_POOL(&mArena, "PersistentPropertyArena", 2048);
 }
 
 nsPersistentProperties::~nsPersistentProperties()
 {
   PL_FinishArenaPool(&mArena);
+  if (mTable.IsInitialized()) {
+    PL_DHashTableFinish(&mTable);
+  }
 }
 
 nsresult
 nsPersistentProperties::Create(nsISupports* aOuter, REFNSIID aIID,
                                void** aResult)
 {
   if (aOuter) {
     return NS_ERROR_NO_AGGREGATION;
--- a/xpcom/tests/TestPLDHash.cpp
+++ b/xpcom/tests/TestPLDHash.cpp
@@ -48,17 +48,18 @@ static bool test_pldhash_Init_capacity_o
     return false;
   }
 
   return true;
 }
 
 static bool test_pldhash_lazy_storage()
 {
-  PLDHashTable t(PL_DHashGetStubOps(), sizeof(PLDHashEntryStub));
+  PLDHashTable t;
+  PL_DHashTableInit(&t, PL_DHashGetStubOps(), sizeof(PLDHashEntryStub));
 
   // PLDHashTable allocates entry storage lazily. Check that all the non-add
   // operations work appropriately when the table is empty and the storage
   // hasn't yet been allocated.
 
   if (!t.IsInitialized()) {
     return false;
   }
@@ -101,16 +102,18 @@ static bool test_pldhash_lazy_storage()
 
   // Using a null |mallocSizeOf| should be fine because it shouldn't be called
   // for an empty table.
   mozilla::MallocSizeOf mallocSizeOf = nullptr;
   if (PL_DHashTableSizeOfExcludingThis(&t, nullptr, mallocSizeOf) != 0) {
     return false;   // size is non-zero?
   }
 
+  PL_DHashTableFinish(&t);
+
   return true;
 }
 
 // We insert the integers 0.., so this hash function is (a) as simple as
 // possible, and (b) collision-free.  Both of which are good, because we want
 // this test to be as fast as possible.
 static PLDHashNumber
 trivial_hash(PLDHashTable *table, const void *key)
@@ -123,25 +126,29 @@ static bool test_pldhash_move_semantics(
   static const PLDHashTableOps ops = {
     trivial_hash,
     PL_DHashMatchEntryStub,
     PL_DHashMoveEntryStub,
     PL_DHashClearEntryStub,
     nullptr
   };
 
-  PLDHashTable t1(&ops, sizeof(PLDHashEntryStub));
+  PLDHashTable t1, t2;
+  PL_DHashTableInit(&t1, &ops, sizeof(PLDHashEntryStub));
   PL_DHashTableAdd(&t1, (const void*)88);
-  PLDHashTable t2(&ops, sizeof(PLDHashEntryStub));
+  PL_DHashTableInit(&t2, &ops, sizeof(PLDHashEntryStub));
   PL_DHashTableAdd(&t2, (const void*)99);
 
   t1 = mozilla::Move(t1);   // self-move
 
   t1 = mozilla::Move(t2);   // inited overwritten with inited
 
+  PL_DHashTableFinish(&t1);
+  PL_DHashTableFinish(&t2);
+
   PLDHashTable t3, t4;
   PL_DHashTableInit(&t3, &ops, sizeof(PLDHashEntryStub));
   PL_DHashTableAdd(&t3, (const void*)88);
 
   t3 = mozilla::Move(t4);   // inited overwritten with uninited
 
   PL_DHashTableFinish(&t3);
   PL_DHashTableFinish(&t4);
@@ -153,17 +160,18 @@ static bool test_pldhash_move_semantics(
   t5 = mozilla::Move(t6);   // uninited overwritten with inited
 
   PL_DHashTableFinish(&t5);
   PL_DHashTableFinish(&t6);
 
   PLDHashTable t7;
   PLDHashTable t8(mozilla::Move(t7));   // new table constructed with uninited
 
-  PLDHashTable t9(&ops, sizeof(PLDHashEntryStub));
+  PLDHashTable t9;
+  PL_DHashTableInit(&t9, &ops, sizeof(PLDHashEntryStub));
   PL_DHashTableAdd(&t9, (const void*)88);
   PLDHashTable t10(mozilla::Move(t9));  // new table constructed with inited
 
   return true;
 }
 
 // See bug 931062, we skip this test on Android due to OOM.
 #ifndef MOZ_WIDGET_ANDROID