gc-hashtables.patch
author Benjamin Smedberg <benjamin@smedbergs.us>
Sat, 26 Jul 2008 22:49:39 -0400
changeset 167 a4da40849f5436e629c5732f4368c6c48189637f
parent 159 969d8d4050b8b7ebfb082c860b4a16df41348d52
permissions -rw-r--r--
State as of now

Give hashtable keys knowledge about the outermost allocation they are in... kinda. In some of these cases I just added the param without actually making the key class safe.
* * *
* * *

diff --git a/caps/include/nsScriptSecurityManager.h b/caps/include/nsScriptSecurityManager.h
--- a/caps/include/nsScriptSecurityManager.h
+++ b/caps/include/nsScriptSecurityManager.h
@@ -96,7 +96,7 @@ public:
     typedef const nsIPrincipal* KeyType;
     typedef const nsIPrincipal* KeyTypePointer;
 
-    PrincipalKey(const nsIPrincipal* key)
+    PrincipalKey(const nsIPrincipal* key, const void *entryStore)
       : mKey(const_cast<nsIPrincipal*>(key))
     {
     }
diff --git a/chrome/src/nsChromeRegistry.h b/chrome/src/nsChromeRegistry.h
--- a/chrome/src/nsChromeRegistry.h
+++ b/chrome/src/nsChromeRegistry.h
@@ -217,9 +217,8 @@ public:
     typedef nsURIHashKey::KeyType        KeyType;
     typedef nsURIHashKey::KeyTypePointer KeyTypePointer;
 
-    OverlayListEntry(KeyTypePointer aKey) : nsURIHashKey(aKey) { }
-    OverlayListEntry(OverlayListEntry& toCopy) : nsURIHashKey(toCopy),
-                                                 mArray(toCopy.mArray) { }
+    OverlayListEntry(KeyTypePointer aKey, const char *entryStore)
+      : nsURIHashKey(aKey, entryStore) { }
     ~OverlayListEntry() { }
 
     void AddURI(nsIURI* aURI);
diff --git a/content/base/src/nsDOMAttributeMap.h b/content/base/src/nsDOMAttributeMap.h
--- a/content/base/src/nsDOMAttributeMap.h
+++ b/content/base/src/nsDOMAttributeMap.h
@@ -88,7 +88,7 @@ public:
   typedef const nsAttrKey& KeyType;
   typedef const nsAttrKey* KeyTypePointer;
 
-  nsAttrHashKey(KeyTypePointer aKey) : mKey(*aKey) {}
+  nsAttrHashKey(KeyTypePointer aKey, const void *entryStore) : mKey(*aKey) {}
   nsAttrHashKey(const nsAttrHashKey& aCopy) : mKey(aCopy.mKey) {}
   ~nsAttrHashKey() {}
 
diff --git a/content/base/src/nsDocument.h b/content/base/src/nsDocument.h
--- a/content/base/src/nsDocument.h
+++ b/content/base/src/nsDocument.h
@@ -145,7 +145,7 @@ class nsUint32ToContentHashEntry : publi
     typedef const PRUint32& KeyType;
     typedef const PRUint32* KeyTypePointer;
 
-    nsUint32ToContentHashEntry(const KeyTypePointer key) :
+    nsUint32ToContentHashEntry(const KeyTypePointer key, const void *entryStore) :
       mValue(*key), mValOrHash(nsnull) { }
     nsUint32ToContentHashEntry(const nsUint32ToContentHashEntry& toCopy) :
       mValue(toCopy.mValue), mValOrHash(toCopy.mValOrHash)
@@ -226,14 +226,9 @@ class nsIdentifierMapEntry : public nsIS
 class nsIdentifierMapEntry : public nsISupportsHashKey
 {
 public:
-  nsIdentifierMapEntry(const nsISupports* aKey) :
-    nsISupportsHashKey(aKey), mNameContentList(nsnull)
+  nsIdentifierMapEntry(const nsISupports* aKey, const void *entryStore) :
+    nsISupportsHashKey(aKey, entryStore), mNameContentList(nsnull)
   {
-  }
-  nsIdentifierMapEntry(const nsIdentifierMapEntry& aOther) :
-    nsISupportsHashKey(GetKey())
-  {
-    NS_ERROR("Should never be called");
   }
   ~nsIdentifierMapEntry();
 
@@ -286,10 +281,8 @@ public:
     typedef const ChangeCallback KeyType;
     typedef const ChangeCallback* KeyTypePointer;
 
-    ChangeCallbackEntry(const ChangeCallback* key) :
+    ChangeCallbackEntry(const ChangeCallback* key, const char *entryStore) :
       mKey(*key) { }
-    ChangeCallbackEntry(const ChangeCallbackEntry& toCopy) :
-      mKey(toCopy.mKey) { }
 
     KeyType GetKey() const { return mKey; }
     PRBool KeyEquals(KeyTypePointer aKey) const {
diff --git a/content/base/src/nsNameSpaceManager.cpp b/content/base/src/nsNameSpaceManager.cpp
--- a/content/base/src/nsNameSpaceManager.cpp
+++ b/content/base/src/nsNameSpaceManager.cpp
@@ -81,7 +81,8 @@ public:
   nsNameSpaceKey(KeyTypePointer aKey) : mKey(aKey)
   {
   }
-  nsNameSpaceKey(const nsNameSpaceKey& toCopy) : mKey(toCopy.mKey)
+  nsNameSpaceKey(const nsNameSpaceKey& toCopy, const void *entryStore)
+    : mKey(toCopy.mKey)
   {
   }
 
diff --git a/content/html/content/src/nsHTMLFormElement.cpp b/content/html/content/src/nsHTMLFormElement.cpp
--- a/content/html/content/src/nsHTMLFormElement.cpp
+++ b/content/html/content/src/nsHTMLFormElement.cpp
@@ -104,7 +104,9 @@ public:
   typedef const nsAString& KeyType;
   typedef const nsAString* KeyTypePointer;
   nsStringCaseInsensitiveHashKey(KeyTypePointer aStr) : mStr(*aStr) { } //take it easy just deal HashKey 
-  nsStringCaseInsensitiveHashKey(const nsStringCaseInsensitiveHashKey& toCopy) : mStr(toCopy.mStr) { }
+  nsStringCaseInsensitiveHashKey(const nsStringCaseInsensitiveHashKey& toCopy,
+                                 const void *entryStore)
+    : mStr(toCopy.mStr) { }
   ~nsStringCaseInsensitiveHashKey() { }
 
   KeyType GetKey() const { return mStr; }
diff --git a/content/xslt/src/xslt/txExecutionState.h b/content/xslt/src/xslt/txExecutionState.h
--- a/content/xslt/src/xslt/txExecutionState.h
+++ b/content/xslt/src/xslt/txExecutionState.h
@@ -60,7 +60,8 @@ class txLoadedDocumentEntry : public nsS
 class txLoadedDocumentEntry : public nsStringHashKey
 {
 public:
-    txLoadedDocumentEntry(KeyTypePointer aStr) : nsStringHashKey(aStr)
+    txLoadedDocumentEntry(KeyTypePointer aStr, const void *entryStore)
+        : nsStringHashKey(aStr, entryStore)
     {
     }
     txLoadedDocumentEntry(const txLoadedDocumentEntry& aToCopy)
diff --git a/content/xul/document/src/nsXULDocument.h b/content/xul/document/src/nsXULDocument.h
--- a/content/xul/document/src/nsXULDocument.h
+++ b/content/xul/document/src/nsXULDocument.h
@@ -80,14 +80,9 @@ class nsRefMapEntry : public nsISupports
 class nsRefMapEntry : public nsISupportsHashKey
 {
 public:
-  nsRefMapEntry(const nsISupports* aKey) :
-    nsISupportsHashKey(aKey)
+  nsRefMapEntry(const nsISupports* aKey, const void *entryStore) :
+    nsISupportsHashKey(aKey, entryStore)
   {
-  }
-  nsRefMapEntry(const nsRefMapEntry& aOther) :
-    nsISupportsHashKey(GetKey())
-  {
-    NS_ERROR("Should never be called");
   }
 
   nsIContent* GetFirstContent();
diff --git a/db/morkreader/nsMorkReader.h b/db/morkreader/nsMorkReader.h
--- a/db/morkreader/nsMorkReader.h
+++ b/db/morkreader/nsMorkReader.h
@@ -79,7 +79,7 @@ class NS_STACK_CLASS nsMorkReader
     typedef const nsCSubstring& KeyType;
     typedef const nsCSubstring* KeyTypePointer;
 
-    IDKey(KeyTypePointer aStr) : mStr(*aStr) { }
+    IDKey(KeyTypePointer aStr, const void *entryStore) : mStr(*aStr) { }
     IDKey(const IDKey& toCopy) : mStr(toCopy.mStr) { }
     ~IDKey() { }
 
diff --git a/dom/src/storage/nsDOMStorage.cpp b/dom/src/storage/nsDOMStorage.cpp
--- a/dom/src/storage/nsDOMStorage.cpp
+++ b/dom/src/storage/nsDOMStorage.cpp
@@ -155,8 +155,9 @@ GetQuota(const nsAString &aDomain, PRInt
   *aWarnQuota = -1;
 }
 
-nsSessionStorageEntry::nsSessionStorageEntry(KeyTypePointer aStr)
-  : nsStringHashKey(aStr), mItem(nsnull)
+nsSessionStorageEntry::nsSessionStorageEntry(KeyTypePointer aStr,
+                                             const void *entryStore)
+  : nsStringHashKey(aStr, entryStore), mItem(nsnull)
 {
 }
 
@@ -349,8 +350,9 @@ nsDOMStorageDB* nsDOMStorage::gStorageDB
 nsDOMStorageDB* nsDOMStorage::gStorageDB = nsnull;
 #endif
 
-nsDOMStorageEntry::nsDOMStorageEntry(KeyTypePointer aStr)
-  : nsVoidPtrHashKey(aStr), mStorage(nsnull)
+nsDOMStorageEntry::nsDOMStorageEntry(KeyTypePointer aStr,
+                                     const void *entryStore)
+  : nsVoidPtrHashKey(aStr, entryStore), mStorage(nsnull)
 {
 }
 
diff --git a/dom/src/storage/nsDOMStorage.h b/dom/src/storage/nsDOMStorage.h
--- a/dom/src/storage/nsDOMStorage.h
+++ b/dom/src/storage/nsDOMStorage.h
@@ -64,7 +64,7 @@ class nsDOMStorageEntry : public nsVoidP
 class nsDOMStorageEntry : public nsVoidPtrHashKey
 {
 public:
-  nsDOMStorageEntry(KeyTypePointer aStr);
+  nsDOMStorageEntry(KeyTypePointer aStr, const void *entryStore);
   nsDOMStorageEntry(const nsDOMStorageEntry& aToCopy);
   ~nsDOMStorageEntry();
 
@@ -75,7 +75,7 @@ class nsSessionStorageEntry : public nsS
 class nsSessionStorageEntry : public nsStringHashKey
 {
 public:
-  nsSessionStorageEntry(KeyTypePointer aStr);
+  nsSessionStorageEntry(KeyTypePointer aStr, const void *entryStore);
   nsSessionStorageEntry(const nsSessionStorageEntry& aToCopy);
   ~nsSessionStorageEntry();
 
diff --git a/extensions/cookie/nsPermissionManager.cpp b/extensions/cookie/nsPermissionManager.cpp
--- a/extensions/cookie/nsPermissionManager.cpp
+++ b/extensions/cookie/nsPermissionManager.cpp
@@ -77,7 +77,7 @@ ArenaStrDup(const char* str, PLArenaPool
   return static_cast<char*>(mem);
 }
 
-nsHostEntry::nsHostEntry(const char* aHost)
+nsHostEntry::nsHostEntry(const char* aHost, const void *entryStore)
 {
   mHost = ArenaStrDup(aHost, gHostArena);
 }
diff --git a/extensions/cookie/nsPermissionManager.h b/extensions/cookie/nsPermissionManager.h
--- a/extensions/cookie/nsPermissionManager.h
+++ b/extensions/cookie/nsPermissionManager.h
@@ -77,7 +77,7 @@ public:
   typedef const char* KeyType;
   typedef const char* KeyTypePointer;
 
-  nsHostEntry(const char* aHost);
+  nsHostEntry(const char* aHost, const void *entryStore);
   nsHostEntry(const nsHostEntry& toCopy);
 
   ~nsHostEntry()
diff --git a/extensions/spellcheck/src/mozPersonalDictionary.h b/extensions/spellcheck/src/mozPersonalDictionary.h
--- a/extensions/spellcheck/src/mozPersonalDictionary.h
+++ b/extensions/spellcheck/src/mozPersonalDictionary.h
@@ -61,11 +61,8 @@ public:
   typedef const PRUnichar* KeyType;
   typedef const PRUnichar* KeyTypePointer;
 
-  nsUniCharEntry(const PRUnichar* aKey) : mKey(nsCRT::strdup(aKey)) {}
-  nsUniCharEntry(const nsUniCharEntry& toCopy)
-  { 
-    NS_NOTREACHED("ALLOW_MEMMOVE is set, so copy ctor shouldn't be called");
-  }
+  nsUniCharEntry(const PRUnichar* aKey, const void *entryStore)
+    : mKey(nsCRT::strdup(aKey)) {}
 
   ~nsUniCharEntry()
   { 
@@ -78,8 +75,6 @@ public:
   static KeyTypePointer KeyToPointer(KeyType aKey) { return aKey; }
 
   static PLDHashNumber HashKey(KeyTypePointer aKey) { return nsCRT::HashCode(aKey); }
-
-  enum { ALLOW_MEMMOVE = PR_TRUE };
 
 private:
   PRUnichar *mKey;
diff --git a/gfx/thebes/public/gfxFont.h b/gfx/thebes/public/gfxFont.h
--- a/gfx/thebes/public/gfxFont.h
+++ b/gfx/thebes/public/gfxFont.h
@@ -218,7 +218,8 @@ protected:
 
         // When constructing a new entry in the hashtable, we'll leave this
         // blank. The caller of Put() will fill this in.
-        HashEntry(KeyTypePointer aStr) : mFont(nsnull) { }
+        HashEntry(KeyTypePointer aStr, const void *entryStore)
+            : mFont(nsnull) { }
         HashEntry(const HashEntry& toCopy) : mFont(toCopy.mFont) { }
         ~HashEntry() { }
 
@@ -294,7 +295,8 @@ private:
     public:
         // When constructing a new entry in the hashtable, we'll leave this
         // blank. The caller of Put() will fill this in.
-        HashEntry(KeyTypePointer aPtr) : nsUint32HashKey(aPtr) {}
+        HashEntry(KeyTypePointer aPtr, const void *entryStore)
+            : nsUint32HashKey(aPtr, entryStore) {}
         HashEntry(const HashEntry& toCopy) : nsUint32HashKey(toCopy) {
           x = toCopy.x; y = toCopy.y; width = toCopy.width; height = toCopy.height;
         }
diff --git a/gfx/thebes/src/gfxTextRunWordCache.cpp b/gfx/thebes/src/gfxTextRunWordCache.cpp
--- a/gfx/thebes/src/gfxTextRunWordCache.cpp
+++ b/gfx/thebes/src/gfxTextRunWordCache.cpp
@@ -139,8 +139,10 @@ protected:
 
         // When constructing a new entry in the hashtable, the caller of Put()
         // will fill us in.
-        CacheHashEntry(KeyTypePointer aKey) : mTextRun(nsnull), mWordOffset(0),
-            mHashedByFont(PR_FALSE) { }
+        CacheHashEntry(KeyTypePointer aKey, const void *entryStore)
+            : mTextRun(nsnull)
+            , mWordOffset(0)
+            , mHashedByFont(PR_FALSE) { }
         CacheHashEntry(const CacheHashEntry& toCopy) { NS_ERROR("Should not be called"); }
         ~CacheHashEntry() { }
 
diff --git a/layout/base/nsBidiPresUtils.h b/layout/base/nsBidiPresUtils.h
--- a/layout/base/nsBidiPresUtils.h
+++ b/layout/base/nsBidiPresUtils.h
@@ -58,7 +58,8 @@
  */
 struct nsFrameContinuationState : public nsVoidPtrHashKey
 {
-  nsFrameContinuationState(const void *aFrame) : nsVoidPtrHashKey(aFrame) {}
+  nsFrameContinuationState(const void *aFrame, const void *entryStore)
+    : nsVoidPtrHashKey(aFrame, entryStore) {}
 
   /**
    * The first visual frame in the continuation chain containing this frame, or
diff --git a/layout/style/nsCSSLoader.h b/layout/style/nsCSSLoader.h
--- a/layout/style/nsCSSLoader.h
+++ b/layout/style/nsCSSLoader.h
@@ -225,24 +225,26 @@ public:
   typedef nsURIAndPrincipalHashKey* KeyType;
   typedef const nsURIAndPrincipalHashKey* KeyTypePointer;
 
-  nsURIAndPrincipalHashKey(const nsURIAndPrincipalHashKey* aKey)
-    : nsURIHashKey(aKey->mKey), mPrincipal(aKey->mPrincipal)
+  nsURIAndPrincipalHashKey(const nsURIAndPrincipalHashKey* aKey,
+                           const void *entryStore)
+    : nsURIHashKey(aKey->mKey, entryStore), mPrincipal(aKey->mPrincipal)
   {
-    MOZ_COUNT_CTOR(nsURIAndPrincipalHashKey);
+    NS_GetGC()->WriteBarrierTrap(entryStore, aKey->mPrincipal);
   }
+
+  // this constructor may only be called if the hashkey is allocated
+  // on the stack!
   nsURIAndPrincipalHashKey(nsIURI* aURI, nsIPrincipal* aPrincipal)
-    : nsURIHashKey(aURI), mPrincipal(aPrincipal)
+    : nsURIHashKey(aURI, nsnull), mPrincipal(aPrincipal)
   {
-    MOZ_COUNT_CTOR(nsURIAndPrincipalHashKey);
   }
   nsURIAndPrincipalHashKey(const nsURIAndPrincipalHashKey& toCopy)
     : nsURIHashKey(toCopy), mPrincipal(toCopy.mPrincipal)
   {
-    MOZ_COUNT_CTOR(nsURIAndPrincipalHashKey);
+    NS_NOTREACHED("This code doesn't work!");
   }
   ~nsURIAndPrincipalHashKey()
   {
-    MOZ_COUNT_DTOR(nsURIAndPrincipalHashKey);
   }
  
   nsURIAndPrincipalHashKey* GetKey() const {
@@ -274,7 +276,7 @@ public:
   enum { ALLOW_MEMMOVE = PR_TRUE };
  
 protected:
-  nsCOMPtr<nsIPrincipal> mPrincipal;
+  nsIPrincipal *const mPrincipal;
 };
 
 /***********************************************************************
diff --git a/layout/svg/base/src/nsSVGFilterFrame.cpp b/layout/svg/base/src/nsSVGFilterFrame.cpp
--- a/layout/svg/base/src/nsSVGFilterFrame.cpp
+++ b/layout/svg/base/src/nsSVGFilterFrame.cpp
@@ -134,7 +134,8 @@ private:
 
   class ImageAnalysisEntry : public nsStringHashKey {
   public:
-    ImageAnalysisEntry(KeyTypePointer aStr) : nsStringHashKey(aStr) { }
+    ImageAnalysisEntry(KeyTypePointer aStr, const void *entryStore)
+      : nsStringHashKey(aStr, entryStore) { }
     ImageAnalysisEntry(const ImageAnalysisEntry& toCopy) : nsStringHashKey(toCopy),
       mInfo(toCopy.mInfo) { }
 
diff --git a/netwerk/base/public/nsURIHashKey.h b/netwerk/base/public/nsURIHashKey.h
--- a/netwerk/base/public/nsURIHashKey.h
+++ b/netwerk/base/public/nsURIHashKey.h
@@ -52,11 +52,16 @@ public:
     typedef nsIURI* KeyType;
     typedef const nsIURI* KeyTypePointer;
 
-    nsURIHashKey(const nsIURI* aKey) :
-        mKey(const_cast<nsIURI*>(aKey)) { MOZ_COUNT_CTOR(nsURIHashKey); }
+    // if entryStore is null, this class was allocated on the stack
+    // see the nsURIAndPrincipalHashKey subclass
+    nsURIHashKey(const nsIURI* aKey, const void *entryStore) :
+        mKey(const_cast<nsIURI*>(aKey)) {
+        if (entryStore)
+            NS_GetGC()->WriteBarrierTrap(entryStore, aKey);
+    }
     nsURIHashKey(const nsURIHashKey& toCopy) :
-        mKey(toCopy.mKey) { MOZ_COUNT_CTOR(nsURIHashKey); }
-    ~nsURIHashKey() { MOZ_COUNT_DTOR(nsURIHashKey); }
+        mKey(toCopy.mKey) { }
+    ~nsURIHashKey() { }
 
     nsIURI* GetKey() const { return mKey; }
 
@@ -78,7 +83,7 @@ public:
     enum { ALLOW_MEMMOVE = PR_TRUE };
 
 protected:
-    nsCOMPtr<nsIURI> mKey;
+    nsIURI *const mKey;
 };
 
 #endif // nsURIHashKey_h__
diff --git a/netwerk/cookie/src/nsCookieService.h b/netwerk/cookie/src/nsCookieService.h
--- a/netwerk/cookie/src/nsCookieService.h
+++ b/netwerk/cookie/src/nsCookieService.h
@@ -73,7 +73,7 @@ class nsCookieEntry : public PLDHashEntr
     typedef const char* KeyTypePointer;
 
     // do nothing with aHost - we require mHead to be set before we're live!
-    nsCookieEntry(KeyTypePointer aHost)
+    nsCookieEntry(KeyTypePointer aHost, const void *entryStore)
      : mHead(nsnull)
     {
     }
diff --git a/netwerk/dns/src/nsEffectiveTLDService.h b/netwerk/dns/src/nsEffectiveTLDService.h
--- a/netwerk/dns/src/nsEffectiveTLDService.h
+++ b/netwerk/dns/src/nsEffectiveTLDService.h
@@ -62,7 +62,7 @@ public:
   typedef const char* KeyType;
   typedef const char* KeyTypePointer;
 
-  nsDomainEntry(KeyTypePointer aEntry)
+  nsDomainEntry(KeyTypePointer aEntry, const void *entryStore)
   {
   }
 
diff --git a/security/manager/ssl/src/nsCertOverrideService.h b/security/manager/ssl/src/nsCertOverrideService.h
--- a/security/manager/ssl/src/nsCertOverrideService.h
+++ b/security/manager/ssl/src/nsCertOverrideService.h
@@ -102,14 +102,8 @@ class nsCertOverrideEntry : public PLDHa
     typedef const char* KeyTypePointer;
 
     // do nothing with aHost - we require mHead to be set before we're live!
-    nsCertOverrideEntry(KeyTypePointer aHostWithPortUTF8)
+    nsCertOverrideEntry(KeyTypePointer aHostWithPortUTF8, const void *entryStore)
     {
-    }
-
-    nsCertOverrideEntry(const nsCertOverrideEntry& toCopy)
-    {
-      mSettings = toCopy.mSettings;
-      mHostWithPort = toCopy.mHostWithPort;
     }
 
     ~nsCertOverrideEntry()
@@ -142,8 +136,6 @@ class nsCertOverrideEntry : public PLDHa
       // pass nsnull
       return PL_DHashStringKey(nsnull, aKey);
     }
-
-    enum { ALLOW_MEMMOVE = PR_FALSE };
 
     // get methods
     inline const nsCString &HostWithPort() const { return mHostWithPort; }
diff --git a/security/manager/ssl/src/nsClientAuthRemember.h b/security/manager/ssl/src/nsClientAuthRemember.h
--- a/security/manager/ssl/src/nsClientAuthRemember.h
+++ b/security/manager/ssl/src/nsClientAuthRemember.h
@@ -85,13 +85,9 @@ class nsClientAuthRememberEntry : public
     typedef const char* KeyTypePointer;
 
     // do nothing with aHost - we require mHead to be set before we're live!
-    nsClientAuthRememberEntry(KeyTypePointer aHostWithCertUTF8)
+    nsClientAuthRememberEntry(KeyTypePointer aHostWithCertUTF8,
+                              const char *entryStore)
     {
-    }
-
-    nsClientAuthRememberEntry(const nsClientAuthRememberEntry& toCopy)
-    {
-      mSettings = toCopy.mSettings;
     }
 
     ~nsClientAuthRememberEntry()
@@ -124,8 +120,6 @@ class nsClientAuthRememberEntry : public
       // pass nsnull
       return PL_DHashStringKey(nsnull, aKey);
     }
-
-    enum { ALLOW_MEMMOVE = PR_FALSE };
 
     // get methods
     inline const nsCString &HostWithCert() const { return mHostWithCert; }
diff --git a/toolkit/components/places/src/nsNavHistoryResult.h b/toolkit/components/places/src/nsNavHistoryResult.h
--- a/toolkit/components/places/src/nsNavHistoryResult.h
+++ b/toolkit/components/places/src/nsNavHistoryResult.h
@@ -75,8 +75,7 @@ public:
   typedef const PRInt64& KeyType;
   typedef const PRInt64* KeyTypePointer;
 
-  nsTrimInt64HashKey(KeyTypePointer aKey) : mValue(*aKey) { }
-  nsTrimInt64HashKey(const nsTrimInt64HashKey& toCopy) : mValue(toCopy.mValue) { }
+  nsTrimInt64HashKey(KeyTypePointer aKey, const void *entryStore) : mValue(*aKey) { }
   ~nsTrimInt64HashKey() { }
 
   KeyType GetKey() const { return mValue; }
@@ -85,7 +84,6 @@ public:
   static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
   static PLDHashNumber HashKey(KeyTypePointer aKey)
     { return static_cast<PRUint32>((*aKey) & PR_UINT32_MAX); }
-  enum { ALLOW_MEMMOVE = PR_TRUE };
 
 private:
   const PRInt64 mValue;
diff --git a/xpcom/components/nsCategoryManager.h b/xpcom/components/nsCategoryManager.h
--- a/xpcom/components/nsCategoryManager.h
+++ b/xpcom/components/nsCategoryManager.h
@@ -63,8 +63,8 @@ class CategoryLeaf : public nsDepCharHas
 class CategoryLeaf : public nsDepCharHashKey
 {
 public:
-  CategoryLeaf(const char* aKey)
-    : nsDepCharHashKey(aKey),
+  CategoryLeaf(const char* aKey, const void *entryStore)
+    : nsDepCharHashKey(aKey, entryStore),
       pValue(nsnull),
       nonpValue(nsnull) { }
   const char* pValue;
diff --git a/xpcom/components/nsComponentManager.cpp b/xpcom/components/nsComponentManager.cpp
--- a/xpcom/components/nsComponentManager.cpp
+++ b/xpcom/components/nsComponentManager.cpp
@@ -265,8 +265,8 @@ factory_ClearEntry(PLDHashTable *aTable,
 }
 
 static const PLDHashTableOps factory_DHashTableOps = {
-    PL_DHashAllocTable,
-    PL_DHashFreeTable,
+    GCAllocTable,
+    GCFreeTable,
     factory_HashKey,
     factory_MatchEntry,
     PL_DHashMoveEntryStub,
@@ -292,8 +292,8 @@ contractID_ClearEntry(PLDHashTable *aTab
 }
 
 static const PLDHashTableOps contractID_DHashTableOps = {
-    PL_DHashAllocTable,
-    PL_DHashFreeTable,
+    GCAllocTable,
+    GCFreeTable,
     PL_DHashStringKey,
     PL_DHashMatchStringKey,
     PL_DHashMoveEntryStub,
@@ -977,7 +977,7 @@ nsComponentManagerImpl::ReadPersistentRe
         }
 
         nsFactoryEntry *entry =
-            new (mem) nsFactoryEntry(aClass, loadertype, values[4]);
+            new nsFactoryEntry(aClass, loadertype, values[4]);
 
         if (!entry->mLocationKey) {
             rv = NS_ERROR_OUT_OF_MEMORY;
@@ -1929,7 +1929,7 @@ nsComponentManagerImpl::RegisterService(
         PL_ARENA_ALLOCATE(mem, &mArena, sizeof(nsFactoryEntry));
         if (!mem)
             return NS_ERROR_OUT_OF_MEMORY;
-        entry = new (mem) nsFactoryEntry(aClass, (nsIFactory*) nsnull);
+        entry = new nsFactoryEntry(aClass, (nsIFactory*) nsnull);
 
         nsFactoryTableEntry* factoryTableEntry =
             static_cast<nsFactoryTableEntry*>
@@ -1990,7 +1990,7 @@ nsComponentManagerImpl::RegisterService(
         PL_ARENA_ALLOCATE(mem, &mArena, sizeof(nsFactoryEntry));
         if (!mem)
             return NS_ERROR_OUT_OF_MEMORY;
-        entry = new (mem) nsFactoryEntry(kEmptyCID, (nsIFactory*) nsnull);
+        entry = new nsFactoryEntry(kEmptyCID, (nsIFactory*) nsnull);
 
         nsContractIDTableEntry* contractIDTableEntry =
             static_cast<nsContractIDTableEntry*>
@@ -2445,7 +2445,7 @@ nsComponentManagerImpl::RegisterFactory(
     if (!mem)
         return NS_ERROR_OUT_OF_MEMORY;
 
-    entry = new (mem) nsFactoryEntry(aClass, aFactory, entry);
+    entry = new nsFactoryEntry(aClass, aFactory, entry);
 
     factoryTableEntry->mFactoryEntry = entry;
 
@@ -2606,9 +2606,9 @@ nsComponentManagerImpl::RegisterComponen
             return NS_ERROR_OUT_OF_MEMORY;
 
         mRegistryDirty = PR_TRUE;
-        entry = new (mem) nsFactoryEntry(aClass,
-                                         typeIndex,
-                                         aRegistryName);
+        entry = new nsFactoryEntry(aClass,
+                                   typeIndex,
+                                   aRegistryName);
         if (!entry->mLocationKey)
             return NS_ERROR_OUT_OF_MEMORY;
 
diff --git a/xpcom/components/nsComponentManager.h b/xpcom/components/nsComponentManager.h
--- a/xpcom/components/nsComponentManager.h
+++ b/xpcom/components/nsComponentManager.h
@@ -253,7 +253,7 @@ public:
 
     nsTArray<nsLoaderdata> mLoaderData;
 
-    nsDataHashtable<nsHashableHashKey, PRInt64> mAutoRegEntries;
+    nsDataHashtable<nsHashableHashKey, PRInt64, GCAllocator> mAutoRegEntries;
 
     PRBool              mRegistryDirty;
     nsCOMPtr<nsCategoryManager>  mCategoryManager;
@@ -291,7 +291,7 @@ private:
  *		These are strictly session specific and in memory only.
  */
 
-struct nsFactoryEntry {
+struct nsFactoryEntry : public XPCOMGCObject {
     nsFactoryEntry(const nsCID    &aClass,
                    LoaderType      aLoaderType,
                    const char     *aLocationKey,
diff --git a/xpcom/components/nsNativeComponentLoader.cpp b/xpcom/components/nsNativeComponentLoader.cpp
--- a/xpcom/components/nsNativeComponentLoader.cpp
+++ b/xpcom/components/nsNativeComponentLoader.cpp
@@ -82,6 +82,8 @@
 #define IMPLEMENT_BREAK_AFTER_LOAD
 #endif
 
+using namespace MMgc;
+
 static PRLogModuleInfo *nsNativeModuleLoaderLog =
     PR_NewLogModule("nsNativeModuleLoader");
 
@@ -121,11 +123,10 @@ nsNativeModuleLoader::LoadModule(nsILoca
         return NS_NOINTERFACE;
     }
 
-    NativeLoadData data;
-
-    if (mLibraries.Get(hashedFile, &data)) {
-        NS_ASSERTION(data.module, "Corrupt mLibraries hash");
-        NS_ADDREF(*aResult = data.module);
+    NativeLoadData *data = mLibraries.GetEntry(hashedFile);
+    if (data) {
+        NS_ASSERTION(data->module, "Corrupt mLibraries hash");
+        *aResult = data->module;
 
         LOG(PR_LOG_DEBUG,
             ("nsNativeModuleLoader::LoadModule(\"%s\") - found in cache",
@@ -135,7 +136,8 @@ nsNativeModuleLoader::LoadModule(nsILoca
 
     // We haven't loaded this module before
 
-    rv = aFile->Load(&data.library);
+    PRLibrary *library;
+    rv = aFile->Load(&library);
 
     if (NS_FAILED(rv)) {
         char errorMsg[1024] = "<unknown; can't get error from NSPR>";
@@ -177,19 +179,24 @@ nsNativeModuleLoader::LoadModule(nsILoca
 #endif
 
     nsGetModuleProc proc = (nsGetModuleProc)
-        PR_FindFunctionSymbol(data.library, NS_GET_MODULE_SYMBOL);
+        PR_FindFunctionSymbol(library, NS_GET_MODULE_SYMBOL);
 
     if (proc) {
+        nsIModule* module;
         rv = proc(nsComponentManagerImpl::gComponentManager,
                   aFile,
-                  getter_AddRefs(data.module));
+                  &module);
         if (NS_SUCCEEDED(rv)) {
             LOG(PR_LOG_DEBUG,
                 ("nsNativeModuleLoader::LoadModule(\"%s\") - Success",
                  filePath.get()));
 
-            if (mLibraries.Put(hashedFile, data)) {
-                NS_ADDREF(*aResult = data.module);
+            data = mLibraries.PutEntry(hashedFile);
+            if (data) {
+                *aResult = module;
+                data->library = library;
+                WB(NS_GetGC(), mLibraries.GetEntryStore(),
+                   &data->module, module);
                 return NS_OK;
             }
         }
@@ -206,26 +213,16 @@ nsNativeModuleLoader::LoadModule(nsILoca
     }
 
     // at some point we failed, clean up
-    data.module = nsnull;
-    PR_UnloadLibrary(data.library);
+    PR_UnloadLibrary(library);
 
     return NS_ERROR_FAILURE;
 }
 
 PLDHashOperator
-nsNativeModuleLoader::ReleaserFunc(nsIHashable* aHashedFile,
-                                   NativeLoadData& aLoadData, void*)
-{
-    aLoadData.module = nsnull;
-    return PL_DHASH_NEXT;
-}
-
-PLDHashOperator
-nsNativeModuleLoader::UnloaderFunc(nsIHashable* aHashedFile,
-                                   NativeLoadData& aLoadData, void*)
+nsNativeModuleLoader::UnloaderFunc(NativeLoadData *aLoadData, void*)
 {
     if (PR_LOG_TEST(nsNativeModuleLoaderLog, PR_LOG_DEBUG)) {
-        nsCOMPtr<nsIFile> file(do_QueryInterface(aHashedFile));
+        nsIFile* file(do_QueryInterface(aLoadData->GetKey()));
 
         nsCAutoString filePath;
         file->GetNativePath(filePath);
@@ -241,7 +238,7 @@ nsNativeModuleLoader::UnloaderFunc(nsIHa
 #if 0
     // XXXbsmedberg: do this as soon as the static-destructor crash(es)
     // are fixed
-    PRStatus ret = PR_UnloadLibrary(aLoadData.library);
+    PRStatus ret = PR_UnloadLibrary(aLoadData->library);
     NS_ASSERTION(ret == PR_SUCCESS, "Failed to unload library");
 #endif
 
@@ -255,6 +252,5 @@ void
 void
 nsNativeModuleLoader::UnloadLibraries()
 {
-    mLibraries.Enumerate(ReleaserFunc, nsnull);
-    mLibraries.Enumerate(UnloaderFunc, nsnull);
+    mLibraries.EnumerateEntries(UnloaderFunc, nsnull);
 }
diff --git a/xpcom/components/nsNativeComponentLoader.h b/xpcom/components/nsNativeComponentLoader.h
--- a/xpcom/components/nsNativeComponentLoader.h
+++ b/xpcom/components/nsNativeComponentLoader.h
@@ -60,21 +60,24 @@ class nsNativeModuleLoader : public nsIM
     void UnloadLibraries();
 
  private:
-    struct NativeLoadData
+    struct NativeLoadData : public nsHashableHashKey
     {
-        NativeLoadData() : library(nsnull) { }
+        typedef nsHashableHashKey::KeyType KeyType;
+        typedef nsHashableHashKey::KeyTypePointer KeyTypePointer;
 
-        nsCOMPtr<nsIModule>  module;
+        NativeLoadData(const nsIHashable* aHashable, const void *entryStore)
+            : nsHashableHashKey(aHashable, entryStore)
+            , module(NULL)
+            , library(NULL) { }
+
+        nsIModule*           module;
         PRLibrary           *library;
     };
 
     static PLDHashOperator
-    ReleaserFunc(nsIHashable* aHashedFile, NativeLoadData &aLoadData, void*);
+    UnloaderFunc(NativeLoadData *data, void*);
 
-    static PLDHashOperator
-    UnloaderFunc(nsIHashable* aHashedFile, NativeLoadData &aLoadData, void*);
-
-    nsDataHashtable<nsHashableHashKey, NativeLoadData> mLibraries;
+    nsTHashtable<NativeLoadData, GCAllocator> mLibraries;
 };
 
 #endif /* nsNativeModuleLoader_h__ */
diff --git a/xpcom/components/nsStaticComponentLoader.cpp b/xpcom/components/nsStaticComponentLoader.cpp
--- a/xpcom/components/nsStaticComponentLoader.cpp
+++ b/xpcom/components/nsStaticComponentLoader.cpp
@@ -52,11 +52,15 @@ static PRLogModuleInfo *sLog = PR_NewLog
 #endif
 #define LOG(args) PR_LOG(sLog, PR_LOG_DEBUG, args)
 
+using namespace MMgc;
+
 extern const char staticComponentType[];
 
 struct StaticModuleInfo : public PLDHashEntryHdr {
+    StaticModuleInfo() : module(NULL), next(NULL) { }
+
     nsStaticModuleInfo  info;
-    nsCOMPtr<nsIModule> module;
+    nsIModule* module;
 
     // We want to autoregister the components in the order they come to us
     // in the static component list, so we keep a linked list.
@@ -80,8 +84,8 @@ info_InitEntry(PLDHashTable *table, PLDH
 }
 
 /* static */ PLDHashTableOps nsStaticModuleLoader::sInfoHashOps = {
-    PL_DHashAllocTable,
-    PL_DHashFreeTable,
+    GCAllocTable,
+    GCFreeTable,
     PL_DHashStringKey,
     PL_DHashMatchStringKey,
     PL_DHashMoveEntryStub,
@@ -131,9 +135,12 @@ nsStaticModuleLoader::EnumerateModules(S
 {
     for (StaticModuleInfo *c = mFirst; c; c = c->next) {
         if (!c->module) {
+            nsIModule* module;
             nsresult rv = c->info.
                 getModule(nsComponentManagerImpl::gComponentManager, nsnull,
-                          getter_AddRefs(c->module));
+                          &module);
+            WB(NS_GetGC(), mInfoHash.entryStore, &c->module, module);
+            
             LOG(("nSCL: EnumerateModules(): %lx\n", rv));
             if (NS_FAILED(rv))
                 continue;
@@ -156,9 +163,13 @@ nsStaticModuleLoader::GetModuleFor(const
         return NS_ERROR_FACTORY_NOT_REGISTERED;
 
     if (!info->module) {
+        nsIModule* module;
         rv = info->info.
             getModule(nsComponentManagerImpl::gComponentManager, nsnull,
-                      getter_AddRefs(info->module));
+                      &module);
+ 
+        WB(NS_GetGC(), mInfoHash.entryStore, &info->module, module);
+
         LOG(("nSCL: GetModuleForFor(\"%s\"): %lx\n", aLocation, rv));
         if (NS_FAILED(rv))
             return rv;
diff --git a/xpcom/ds/nsObserverList.h b/xpcom/ds/nsObserverList.h
--- a/xpcom/ds/nsObserverList.h
+++ b/xpcom/ds/nsObserverList.h
@@ -74,7 +74,8 @@ class nsObserverList : public nsCharPtrH
 class nsObserverList : public nsCharPtrHashKey
 {
 public:
-  nsObserverList(const char *key) : nsCharPtrHashKey(key)
+  nsObserverList(const char *key, const void *entryStore)
+    : nsCharPtrHashKey(key, entryStore)
   { MOZ_COUNT_CTOR(nsObserverList); }
 
   ~nsObserverList() { MOZ_COUNT_DTOR(nsObserverList); }
diff --git a/xpcom/glue/nsAllocator.cpp b/xpcom/glue/nsAllocator.cpp
--- a/xpcom/glue/nsAllocator.cpp
+++ b/xpcom/glue/nsAllocator.cpp
@@ -55,3 +55,15 @@ GCAllocator::Realloc(void *object, size_
     memcpy(newobject, object, oldsize);
     return newobject;
 }
+
+void*
+GCAllocTable(PLDHashTable *table, PRUint32 nbytes)
+{
+    return NS_GetGC()->Alloc(nbytes, MMgc::GC::kContainsPointers);
+}
+
+void
+GCFreeTable(PLDHashTable *table, void *ptr)
+{
+    NS_GetGC()->Free(ptr);
+}
diff --git a/xpcom/glue/nsAllocator.h b/xpcom/glue/nsAllocator.h
--- a/xpcom/glue/nsAllocator.h
+++ b/xpcom/glue/nsAllocator.h
@@ -47,6 +47,8 @@
 #include "nsXPCOM.h"
 #include "MMgc.h"
 
+struct PLDHashTable;
+
 /**
  * The following classes are all static and follow the same pattern:
  *
@@ -85,7 +87,7 @@ public:
 public:
     static void* Alloc(size_t size)
     {
-        return NS_GetGC()->Alloc(size);
+        return NS_GetGC()->Alloc(size, MMgc::GC::kContainsPointers);
     }
 
     NS_COM_GLUE static void* Realloc(void *object, size_t oldsize, size_t newsize);
@@ -98,4 +100,10 @@ public:
     }
 };
 
+NS_COM_GLUE void*
+GCAllocTable(PLDHashTable *table, PRUint32 nbytes);
+
+NS_COM_GLUE void
+GCFreeTable(PLDHashTable *table, void *ptr);
+
 #endif // nsAllocator_h__
diff --git a/xpcom/glue/nsBaseHashtable.h b/xpcom/glue/nsBaseHashtable.h
--- a/xpcom/glue/nsBaseHashtable.h
+++ b/xpcom/glue/nsBaseHashtable.h
@@ -42,7 +42,7 @@
 #include "prlock.h"
 #include "nsDebug.h"
 
-template<class KeyClass,class DataType,class UserDataType>
+template<class KeyClass,class DataType,class UserDataType,class Allocator>
 class nsBaseHashtable; // forward declaration
 
 /**
@@ -55,14 +55,11 @@ class nsBaseHashtableET : public KeyClas
 {
 public:
   DataType mData;
-  friend class nsTHashtable< nsBaseHashtableET<KeyClass,DataType> >;
 
-private:
   typedef typename KeyClass::KeyType KeyType;
   typedef typename KeyClass::KeyTypePointer KeyTypePointer;
   
-  nsBaseHashtableET(KeyTypePointer aKey);
-  nsBaseHashtableET(nsBaseHashtableET<KeyClass,DataType>& toCopy);
+  nsBaseHashtableET(KeyTypePointer aKey, const void *entryStore);
   ~nsBaseHashtableET();
 };
 
@@ -78,9 +75,9 @@ private:
  *   DataType must implicitly cast to UserDataType
  * @param UserDataType the user sees, for example PRUint32 or nsISupports*
  */
-template<class KeyClass,class DataType,class UserDataType>
+template<class KeyClass,class DataType,class UserDataType,class Allocator=CAllocator>
 class nsBaseHashtable :
-  protected nsTHashtable< nsBaseHashtableET<KeyClass,DataType> >
+  protected nsTHashtable< nsBaseHashtableET<KeyClass,DataType>, Allocator >
 {
 public:
   typedef typename KeyClass::KeyType KeyType;
@@ -96,7 +93,7 @@ public:
    * @return    PR_TRUE if the object was initialized properly.
    */
   PRBool Init(PRUint32 initSize = PL_DHASH_MIN_SIZE)
-  { return nsTHashtable<EntryType>::Init(initSize); }
+  { return nsTHashtable<EntryType, Allocator>::Init(initSize); }
 
   /**
    * Check whether the table has been initialized.
@@ -110,7 +107,7 @@ public:
    * @return    number of entries
    */
   PRUint32 Count() const
-  { return nsTHashtable<EntryType>::Count(); }
+  { return nsTHashtable<EntryType, Allocator>::Count(); }
 
   /**
    * retrieve the value for a key.
@@ -235,7 +232,7 @@ public:
   /**
    * reset the hashtable, removing all entries
    */
-  void Clear() { nsTHashtable<EntryType>::Clear(); }
+  void Clear() { nsTHashtable<EntryType, Allocator>::Clear(); }
 
 protected:
   /**
@@ -266,56 +263,13 @@ protected:
                                     void              *arg);
 };
 
-/**
- * This class is a thread-safe version of nsBaseHashtable.
- */
-template<class KeyClass,class DataType,class UserDataType>
-class nsBaseHashtableMT :
-  protected nsBaseHashtable<KeyClass,DataType,UserDataType>
-{
-public:
-  typedef typename
-    nsBaseHashtable<KeyClass,DataType,UserDataType>::EntryType EntryType;
-  typedef typename
-    nsBaseHashtable<KeyClass,DataType,UserDataType>::KeyType KeyType;
-  typedef typename
-    nsBaseHashtable<KeyClass,DataType,UserDataType>::EnumFunction EnumFunction;
-  typedef typename
-    nsBaseHashtable<KeyClass,DataType,UserDataType>::EnumReadFunction EnumReadFunction;
-
-  nsBaseHashtableMT() : mLock(nsnull) { }
-  ~nsBaseHashtableMT();
-
-  PRBool Init(PRUint32 initSize = PL_DHASH_MIN_SIZE);
-  PRBool IsInitialized() const { return mLock != nsnull; }
-  PRUint32 Count() const;
-  PRBool Get(KeyType aKey, UserDataType* pData) const;
-  PRBool Put(KeyType aKey, UserDataType aData);
-  void Remove(KeyType aKey);
-
-  PRUint32 EnumerateRead(EnumReadFunction enumFunc, void* userArg) const;
-  PRUint32 Enumerate(EnumFunction enumFunc, void* userArg);
-  void Clear();
-
-protected:
-  PRLock* mLock;
-};
-  
-
 //
 // nsBaseHashtableET definitions
 //
 
 template<class KeyClass,class DataType>
-nsBaseHashtableET<KeyClass,DataType>::nsBaseHashtableET(KeyTypePointer aKey) :
-  KeyClass(aKey)
-{ }
-
-template<class KeyClass,class DataType>
-nsBaseHashtableET<KeyClass,DataType>::nsBaseHashtableET
-  (nsBaseHashtableET<KeyClass,DataType>& toCopy) :
-  KeyClass(toCopy),
-  mData(toCopy.mData)
+nsBaseHashtableET<KeyClass,DataType>::nsBaseHashtableET(KeyTypePointer aKey, const void *entryStore) :
+  KeyClass(aKey, entryStore)
 { }
 
 template<class KeyClass,class DataType>
@@ -327,9 +281,9 @@ nsBaseHashtableET<KeyClass,DataType>::~n
 // nsBaseHashtable definitions
 //
 
-template<class KeyClass,class DataType,class UserDataType>
+template<class KeyClass,class DataType,class UserDataType,class Allocator>
 PLDHashOperator
-nsBaseHashtable<KeyClass,DataType,UserDataType>::s_EnumReadStub
+nsBaseHashtable<KeyClass,DataType,UserDataType,Allocator>::s_EnumReadStub
   (PLDHashTable *table, PLDHashEntryHdr *hdr, PRUint32 number, void* arg)
 {
   EntryType* ent = static_cast<EntryType*>(hdr);
@@ -346,9 +300,9 @@ nsBaseHashtable<KeyClass,DataType,UserDa
   return PL_DHASH_NEXT;
 }
 
-template<class KeyClass,class DataType,class UserDataType>
+template<class KeyClass,class DataType,class UserDataType,class Allocator>
 PLDHashOperator
-nsBaseHashtable<KeyClass,DataType,UserDataType>::s_EnumStub
+nsBaseHashtable<KeyClass,DataType,UserDataType,Allocator>::s_EnumStub
   (PLDHashTable *table, PLDHashEntryHdr *hdr, PRUint32 number, void* arg)
 {
   EntryType* ent = static_cast<EntryType*>(hdr);
@@ -357,110 +311,4 @@ nsBaseHashtable<KeyClass,DataType,UserDa
   return (eargs->func)(ent->GetKey(), ent->mData, eargs->userArg);
 }
 
-
-//
-// nsBaseHashtableMT  definitions
-//
-
-template<class KeyClass,class DataType,class UserDataType>
-nsBaseHashtableMT<KeyClass,DataType,UserDataType>::~nsBaseHashtableMT()
-{
-  if (this->mLock)
-    PR_DestroyLock(this->mLock);
-}
-
-template<class KeyClass,class DataType,class UserDataType>
-PRBool
-nsBaseHashtableMT<KeyClass,DataType,UserDataType>::Init(PRUint32 initSize)
-{
-  if (!nsTHashtable<EntryType>::IsInitialized() && !nsTHashtable<EntryType>::Init(initSize))
-    return PR_FALSE;
-
-  this->mLock = PR_NewLock();
-  NS_ASSERTION(this->mLock, "Error creating lock during nsBaseHashtableL::Init()");
-
-  return (this->mLock != nsnull);
-}
-
-template<class KeyClass,class DataType,class UserDataType>
-PRUint32
-nsBaseHashtableMT<KeyClass,DataType,UserDataType>::Count() const
-{
-  PR_Lock(this->mLock);
-  PRUint32 count = nsTHashtable<EntryType>::Count();
-  PR_Unlock(this->mLock);
-
-  return count;
-}
-
-template<class KeyClass,class DataType,class UserDataType>
-PRBool
-nsBaseHashtableMT<KeyClass,DataType,UserDataType>::Get(KeyType       aKey,
-                                                           UserDataType* pData) const
-{
-  PR_Lock(this->mLock);
-  PRBool res =
-    nsBaseHashtable<KeyClass,DataType,UserDataType>::Get(aKey, pData);
-  PR_Unlock(this->mLock);
-
-  return res;
-}
-
-template<class KeyClass,class DataType,class UserDataType>
-PRBool
-nsBaseHashtableMT<KeyClass,DataType,UserDataType>::Put(KeyType      aKey,
-                                                           UserDataType aData)
-{
-  PR_Lock(this->mLock);
-  PRBool res =
-    nsBaseHashtable<KeyClass,DataType,UserDataType>::Put(aKey, aData);
-  PR_Unlock(this->mLock);
-
-  return res;
-}
-
-template<class KeyClass,class DataType,class UserDataType>
-void
-nsBaseHashtableMT<KeyClass,DataType,UserDataType>::Remove(KeyType aKey)
-{
-  PR_Lock(this->mLock);
-  nsBaseHashtable<KeyClass,DataType,UserDataType>::Remove(aKey);
-  PR_Unlock(this->mLock);
-}
-
-template<class KeyClass,class DataType,class UserDataType>
-PRUint32
-nsBaseHashtableMT<KeyClass,DataType,UserDataType>::EnumerateRead
-  (EnumReadFunction fEnumCall, void* userArg) const
-{
-  PR_Lock(this->mLock);
-  PRUint32 count =
-    nsBaseHashtable<KeyClass,DataType,UserDataType>::EnumerateRead(fEnumCall, userArg);
-  PR_Unlock(this->mLock);
-
-  return count;
-}
-
-template<class KeyClass,class DataType,class UserDataType>
-PRUint32
-nsBaseHashtableMT<KeyClass,DataType,UserDataType>::Enumerate
-  (EnumFunction fEnumCall, void* userArg)
-{
-  PR_Lock(this->mLock);
-  PRUint32 count =
-    nsBaseHashtable<KeyClass,DataType,UserDataType>::Enumerate(fEnumCall, userArg);
-  PR_Unlock(this->mLock);
-
-  return count;
-}
-
-template<class KeyClass,class DataType,class UserDataType>
-void
-nsBaseHashtableMT<KeyClass,DataType,UserDataType>::Clear()
-{
-  PR_Lock(this->mLock);
-  nsBaseHashtable<KeyClass,DataType,UserDataType>::Clear();
-  PR_Unlock(this->mLock);
-}
-
 #endif // nsBaseHashtable_h__
diff --git a/xpcom/glue/nsClassHashtable.h b/xpcom/glue/nsClassHashtable.h
--- a/xpcom/glue/nsClassHashtable.h
+++ b/xpcom/glue/nsClassHashtable.h
@@ -50,9 +50,9 @@
  * @param Class the class-type being wrapped
  * @see nsInterfaceHashtable, nsClassHashtable
  */
-template<class KeyClass,class T>
+template<class KeyClass,class T,class Allocator=CAllocator>
 class nsClassHashtable :
-  public nsBaseHashtable< KeyClass, nsAutoPtr<T>, T* >
+  public nsBaseHashtable< KeyClass, nsAutoPtr<T>, T*, Allocator >
 {
 public:
   typedef typename KeyClass::KeyType KeyType;
@@ -65,39 +65,15 @@ public:
   PRBool Get(KeyType aKey, UserDataType* pData) const;
 };
 
-
-/**
- * Thread-safe version of nsClassHashtable
- * @param KeyClass a wrapper-class for the hashtable key, see nsHashKeys.h
- *   for a complete specification.
- * @param Class the class-type being wrapped
- * @see nsInterfaceHashtable, nsClassHashtable
- */
-template<class KeyClass,class T>
-class nsClassHashtableMT :
-  public nsBaseHashtableMT< KeyClass, nsAutoPtr<T>, T* >
-{
-public:
-  typedef typename KeyClass::KeyType KeyType;
-  typedef T* UserDataType;
-
-  /**
-   * @copydoc nsBaseHashtable::Get
-   * @param pData if the key doesn't exist, pData will be set to nsnull.
-   */
-  PRBool Get(KeyType aKey, UserDataType* pData) const;
-};
-
-
 //
 // nsClassHashtable definitions
 //
 
-template<class KeyClass,class T>
+template<class KeyClass,class T,class Allocator>
 PRBool
-nsClassHashtable<KeyClass,T>::Get(KeyType aKey, T** retVal) const
+nsClassHashtable<KeyClass,T,Allocator>::Get(KeyType aKey, T** retVal) const
 {
-  typename nsBaseHashtable<KeyClass,nsAutoPtr<T>,T*>::EntryType* ent =
+  typename nsBaseHashtable<KeyClass,nsAutoPtr<T>,T*,Allocator>::EntryType* ent =
     GetEntry(aKey);
 
   if (ent)
@@ -114,36 +90,4 @@ nsClassHashtable<KeyClass,T>::Get(KeyTyp
   return PR_FALSE;
 }
 
-
-//
-// nsClassHashtableMT definitions
-//
-
-template<class KeyClass,class T>
-PRBool
-nsClassHashtableMT<KeyClass,T>::Get(KeyType aKey, T** retVal) const
-{
-  PR_Lock(this->mLock);
-
-  typename nsBaseHashtableMT<KeyClass,nsAutoPtr<T>,T*>::EntryType* ent =
-    GetEntry(aKey);
-
-  if (ent)
-  {
-    if (retVal)
-      *retVal = ent->mData;
-
-    PR_Unlock(this->mLock);
-
-    return PR_TRUE;
-  }
-
-  if (retVal)
-    *retVal = nsnull;
-
-  PR_Unlock(this->mLock);
-
-  return PR_FALSE;
-}
-
 #endif // nsClassHashtable_h__
diff --git a/xpcom/glue/nsDataHashtable.h b/xpcom/glue/nsDataHashtable.h
--- a/xpcom/glue/nsDataHashtable.h
+++ b/xpcom/glue/nsDataHashtable.h
@@ -49,14 +49,9 @@
  * @param DataType the simple datatype being wrapped
  * @see nsInterfaceHashtable, nsClassHashtable
  */
-template<class KeyClass,class DataType>
+template<class KeyClass,class DataType,class Allocator=CAllocator>
 class nsDataHashtable :
-  public nsBaseHashtable<KeyClass,DataType,DataType>
-{ };
-
-template<class KeyClass,class DataType>
-class nsDataHashtableMT :
-  public nsBaseHashtableMT<KeyClass,DataType,DataType>
+  public nsBaseHashtable<KeyClass,DataType,DataType,Allocator>
 { };
 
 #endif // nsDataHashtable_h__
diff --git a/xpcom/glue/nsHashKeys.h b/xpcom/glue/nsHashKeys.h
--- a/xpcom/glue/nsHashKeys.h
+++ b/xpcom/glue/nsHashKeys.h
@@ -85,8 +85,7 @@ public:
   typedef const nsAString& KeyType;
   typedef const nsAString* KeyTypePointer;
 
-  nsStringHashKey(KeyTypePointer aStr) : mStr(*aStr) { }
-  nsStringHashKey(const nsStringHashKey& toCopy) : mStr(toCopy.mStr) { }
+  nsStringHashKey(KeyTypePointer aStr, const void *entryStore) : mStr(*aStr) { }
   ~nsStringHashKey() { }
 
   KeyType GetKey() const { return mStr; }
@@ -100,7 +99,6 @@ public:
   {
     return HashString(*aKey);
   }
-  enum { ALLOW_MEMMOVE = PR_TRUE };
 
 private:
   const nsString mStr;
@@ -117,8 +115,8 @@ public:
   typedef const nsACString& KeyType;
   typedef const nsACString* KeyTypePointer;
   
-  nsCStringHashKey(const nsACString* aStr) : mStr(*aStr) { }
-  nsCStringHashKey(const nsCStringHashKey& toCopy) : mStr(toCopy.mStr) { }
+  nsCStringHashKey(const nsACString* aStr, const void *entryStore)
+    : mStr(*aStr) { }
   ~nsCStringHashKey() { }
 
   KeyType GetKey() const { return mStr; }
@@ -130,7 +128,6 @@ public:
   {
     return HashString(*aKey);
   }
-  enum { ALLOW_MEMMOVE = PR_TRUE };
 
 private:
   const nsCString mStr;
@@ -147,8 +144,8 @@ public:
   typedef const PRUint32& KeyType;
   typedef const PRUint32* KeyTypePointer;
   
-  nsUint32HashKey(KeyTypePointer aKey) : mValue(*aKey) { }
-  nsUint32HashKey(const nsUint32HashKey& toCopy) : mValue(toCopy.mValue) { }
+  nsUint32HashKey(KeyTypePointer aKey, const void *entryStore)
+    : mValue(*aKey) { }
   ~nsUint32HashKey() { }
 
   KeyType GetKey() const { return mValue; }
@@ -156,7 +153,6 @@ public:
 
   static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
   static PLDHashNumber HashKey(KeyTypePointer aKey) { return *aKey; }
-  enum { ALLOW_MEMMOVE = PR_TRUE };
 
 private:
   const PRUint32 mValue;
@@ -173,10 +169,8 @@ public:
   typedef nsISupports* KeyType;
   typedef const nsISupports* KeyTypePointer;
 
-  nsISupportsHashKey(const nsISupports* key) :
+  nsISupportsHashKey(const nsISupports* key, const void *entryStore) :
     mSupports(const_cast<nsISupports*>(key)) { }
-  nsISupportsHashKey(const nsISupportsHashKey& toCopy) :
-    mSupports(toCopy.mSupports) { }
   ~nsISupportsHashKey() { }
 
   KeyType GetKey() const { return mSupports; }
@@ -188,7 +182,6 @@ public:
   {
     return NS_PTR_TO_INT32(aKey) >>2;
   }
-  enum { ALLOW_MEMMOVE = PR_TRUE };
 
 private:
   nsCOMPtr<nsISupports> mSupports;
@@ -205,10 +198,8 @@ public:
   typedef const void* KeyType;
   typedef const void* KeyTypePointer;
 
-  nsVoidPtrHashKey(const void* key) :
+  nsVoidPtrHashKey(const void* key, const void *entryStore) :
     mKey(key) { }
-  nsVoidPtrHashKey(const nsVoidPtrHashKey& toCopy) :
-    mKey(toCopy.mKey) { }
   ~nsVoidPtrHashKey() { }
 
   KeyType GetKey() const { return mKey; }
@@ -220,7 +211,6 @@ public:
   {
     return NS_PTR_TO_INT32(aKey) >>2;
   }
-  enum { ALLOW_MEMMOVE = PR_TRUE };
 
 private:
   const void* mKey;
@@ -240,10 +230,8 @@ public:
   typedef const void* KeyType;
   typedef const void* KeyTypePointer;
 
-  nsClearingVoidPtrHashKey(const void* key) :
+  nsClearingVoidPtrHashKey(const void* key, const void *entryStore) :
     mKey(key) { }
-  nsClearingVoidPtrHashKey(const nsClearingVoidPtrHashKey& toCopy) :
-    mKey(toCopy.mKey) { }
   ~nsClearingVoidPtrHashKey() { mKey = NULL; }
 
   KeyType GetKey() const { return mKey; }
@@ -255,7 +243,6 @@ public:
   {
     return NS_PTR_TO_INT32(aKey) >>2;
   }
-  enum { ALLOW_MEMMOVE = PR_TRUE };
 
 private:
   const void* mKey;
@@ -272,8 +259,7 @@ public:
   typedef const nsID& KeyType;
   typedef const nsID* KeyTypePointer;
   
-  nsIDHashKey(const nsID* inID) : mID(*inID) { }
-  nsIDHashKey(const nsIDHashKey& toCopy) : mID(toCopy.mID) { }
+  nsIDHashKey(const nsID* inID, const void *entryStore) : mID(*inID) { }
   ~nsIDHashKey() { }
 
   KeyType GetKey() const { return mID; }
@@ -282,7 +268,6 @@ public:
 
   static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
   static PLDHashNumber HashKey(KeyTypePointer aKey);
-  enum { ALLOW_MEMMOVE = PR_TRUE };
 
 private:
   const nsID mID;
@@ -304,8 +289,7 @@ public:
   typedef const char* KeyType;
   typedef const char* KeyTypePointer;
 
-  nsDepCharHashKey(const char* aKey) { mKey = aKey; }
-  nsDepCharHashKey(const nsDepCharHashKey& toCopy) { mKey = toCopy.mKey; }
+  nsDepCharHashKey(const char* aKey, const void *entryStore) { mKey = aKey; }
   ~nsDepCharHashKey() { }
 
   const char* GetKey() const { return mKey; }
@@ -316,7 +300,6 @@ public:
 
   static const char* KeyToPointer(const char* aKey) { return aKey; }
   static PLDHashNumber HashKey(const char* aKey) { return HashString(aKey); }
-  enum { ALLOW_MEMMOVE = PR_TRUE };
 
 private:
   const char* mKey;
@@ -333,8 +316,8 @@ public:
   typedef const char* KeyType;
   typedef const char* KeyTypePointer;
 
-  nsCharPtrHashKey(const char* aKey) : mKey(strdup(aKey)) { }
-  nsCharPtrHashKey(const nsCharPtrHashKey& toCopy) : mKey(strdup(toCopy.mKey)) { }
+  nsCharPtrHashKey(const char* aKey, const void *entryStore)
+    : mKey(strdup(aKey)) { }
   ~nsCharPtrHashKey() { if (mKey) free(const_cast<char *>(mKey)); }
 
   const char* GetKey() const { return mKey; }
@@ -345,8 +328,6 @@ public:
 
   static KeyTypePointer KeyToPointer(KeyType aKey) { return aKey; }
   static PLDHashNumber HashKey(KeyTypePointer aKey) { return HashString(aKey); }
-
-  enum { ALLOW_MEMMOVE = PR_TRUE };
 
 private:
   const char* mKey;
@@ -363,8 +344,8 @@ public:
   typedef const PRUnichar* KeyType;
   typedef const PRUnichar* KeyTypePointer;
 
-  nsUnicharPtrHashKey(const PRUnichar* aKey) : mKey(NS_strdup(aKey)) { }
-  nsUnicharPtrHashKey(const nsUnicharPtrHashKey& toCopy) : mKey(NS_strdup(toCopy.mKey)) { }
+  nsUnicharPtrHashKey(const PRUnichar* aKey, const void *entryStore)
+    : mKey(NS_strdup(aKey)) { }
   ~nsUnicharPtrHashKey() { if (mKey) NS_Free(const_cast<PRUnichar *>(mKey)); }
 
   const PRUnichar* GetKey() const { return mKey; }
@@ -375,8 +356,6 @@ public:
 
   static KeyTypePointer KeyToPointer(KeyType aKey) { return aKey; }
   static PLDHashNumber HashKey(KeyTypePointer aKey) { return HashString(aKey); }
-
-  enum { ALLOW_MEMMOVE = PR_TRUE };
 
 private:
   const PRUnichar* mKey;
@@ -391,11 +370,12 @@ public:
     typedef nsIHashable* KeyType;
     typedef const nsIHashable* KeyTypePointer;
 
-    nsHashableHashKey(const nsIHashable* aKey) :
-        mKey(const_cast<nsIHashable*>(aKey)) { }
-    nsHashableHashKey(const nsHashableHashKey& toCopy) :
-        mKey(toCopy.mKey) { }
-    ~nsHashableHashKey() { }
+    nsHashableHashKey(const nsIHashable* aKey, const void *entryStore) {
+        WB(NS_GetGC(), entryStore, &mKey, aKey);
+    }
+    ~nsHashableHashKey() {
+      mKey = NULL;
+    }
 
     nsIHashable* GetKey() const { return mKey; }
 
@@ -418,10 +398,8 @@ public:
         return code;
     }
     
-    enum { ALLOW_MEMMOVE = PR_TRUE };
-
 private:
-    nsCOMPtr<nsIHashable> mKey;
+    nsIHashable* mKey;
 };
 
 #endif // nsTHashKeys_h__
diff --git a/xpcom/glue/nsInterfaceHashtable.h b/xpcom/glue/nsInterfaceHashtable.h
--- a/xpcom/glue/nsInterfaceHashtable.h
+++ b/xpcom/glue/nsInterfaceHashtable.h
@@ -50,9 +50,9 @@
  * @param Interface the interface-type being wrapped
  * @see nsDataHashtable, nsClassHashtable
  */
-template<class KeyClass,class Interface>
+template<class KeyClass,class Interface,class Allocator=GCAllocator>
 class nsInterfaceHashtable :
-  public nsBaseHashtable< KeyClass, nsCOMPtr<Interface> , Interface* >
+  public nsBaseHashtable< KeyClass, nsCOMPtr<Interface> , Interface*, Allocator >
 {
 public:
   typedef typename KeyClass::KeyType KeyType;
@@ -74,43 +74,16 @@ public:
   Interface* GetWeak(KeyType aKey, PRBool* aFound = nsnull) const;
 };
 
-/**
- * Thread-safe version of nsInterfaceHashtable
- * @param KeyClass a wrapper-class for the hashtable key, see nsHashKeys.h
- *   for a complete specification.
- * @param Interface the interface-type being wrapped
- */
-template<class KeyClass,class Interface>
-class nsInterfaceHashtableMT :
-  public nsBaseHashtableMT< KeyClass, nsCOMPtr<Interface> , Interface* >
-{
-public:
-  typedef typename KeyClass::KeyType KeyType;
-  typedef Interface* UserDataType;
-
-  /**
-   * @copydoc nsBaseHashtable::Get
-   * @param pData This is an XPCOM getter, so pData is already_addrefed.
-   *   If the key doesn't exist, pData will be set to nsnull.
-   */
-  PRBool Get(KeyType aKey, UserDataType* pData NS_OUTPARAM) const;
-
-  // GetWeak does not make sense on a multi-threaded hashtable, where another
-  // thread may remove the entry (and hence release it) as soon as GetWeak
-  // returns
-};
-
-
 //
 // nsInterfaceHashtable definitions
 //
 
-template<class KeyClass,class Interface>
+template<class KeyClass,class Interface,class Allocator>
 PRBool
-nsInterfaceHashtable<KeyClass,Interface>::Get
+nsInterfaceHashtable<KeyClass,Interface,Allocator>::Get
   (KeyType aKey, UserDataType* pInterface) const
 {
-  typename nsBaseHashtable<KeyClass, nsCOMPtr<Interface>, Interface*>::EntryType* ent =
+  typename nsBaseHashtable<KeyClass, nsCOMPtr<Interface>, Interface*, Allocator>::EntryType* ent =
     GetEntry(aKey);
 
   if (ent)
@@ -133,12 +106,12 @@ nsInterfaceHashtable<KeyClass,Interface>
   return PR_FALSE;
 }
 
-template<class KeyClass,class Interface>
+template<class KeyClass,class Interface,class Allocator>
 Interface*
-nsInterfaceHashtable<KeyClass,Interface>::GetWeak
+nsInterfaceHashtable<KeyClass,Interface,Allocator>::GetWeak
   (KeyType aKey, PRBool* aFound) const
 {
-  typename nsBaseHashtable<KeyClass, nsCOMPtr<Interface>, Interface*>::EntryType* ent =
+  typename nsBaseHashtable<KeyClass, nsCOMPtr<Interface>, Interface*, Allocator>::EntryType* ent =
     GetEntry(aKey);
 
   if (ent)
@@ -155,42 +128,4 @@ nsInterfaceHashtable<KeyClass,Interface>
   return nsnull;
 }
 
-//
-// nsInterfaceHashtableMT definitions
-//
-
-template<class KeyClass,class Interface>
-PRBool
-nsInterfaceHashtableMT<KeyClass,Interface>::Get
-  (KeyType aKey, UserDataType* pInterface) const
-{
-  PR_Lock(this->mLock);
-
-  typename nsBaseHashtableMT<KeyClass, nsCOMPtr<Interface>, Interface*>::EntryType* ent =
-    GetEntry(aKey);
-
-  if (ent)
-  {
-    if (pInterface)
-    {
-      *pInterface = ent->mData;
-
-      NS_IF_ADDREF(*pInterface);
-    }
-
-    PR_Unlock(this->mLock);
-
-    return PR_TRUE;
-  }
-
-  // if the key doesn't exist, set *pInterface to null
-  // so that it is a valid XPCOM getter
-  if (pInterface)
-    *pInterface = nsnull;
-
-  PR_Unlock(this->mLock);
-
-  return PR_FALSE;
-}
-
 #endif // nsInterfaceHashtable_h__
diff --git a/xpcom/glue/nsRefPtrHashtable.h b/xpcom/glue/nsRefPtrHashtable.h
--- a/xpcom/glue/nsRefPtrHashtable.h
+++ b/xpcom/glue/nsRefPtrHashtable.h
@@ -39,159 +39,8 @@
 #ifndef nsRefPtrHashtable_h__
 #define nsRefPtrHashtable_h__
 
-#include "nsBaseHashtable.h"
-#include "nsHashKeys.h"
-#include "nsAutoPtr.h"
+#include "nsInterfaceHashtable.h"
 
-/**
- * templated hashtable class maps keys to reference pointers.
- * See nsBaseHashtable for complete declaration.
- * @param KeyClass a wrapper-class for the hashtable key, see nsHashKeys.h
- *   for a complete specification.
- * @param RefPtr the reference-type being wrapped
- * @see nsDataHashtable, nsClassHashtable
- */
-template<class KeyClass, class RefPtr>
-class nsRefPtrHashtable :
-  public nsBaseHashtable< KeyClass, nsRefPtr<RefPtr> , RefPtr* >
-{
-public:
-  typedef typename KeyClass::KeyType KeyType;
-  typedef RefPtr* UserDataType;
-
-  /**
-   * @copydoc nsBaseHashtable::Get
-   * @param pData This is an XPCOM getter, so pData is already_addrefed.
-   *   If the key doesn't exist, pData will be set to nsnull.
-   */
-  PRBool Get(KeyType aKey, UserDataType* pData) const;
-
-  /**
-   * Gets a weak reference to the hashtable entry.
-   * @param aFound If not nsnull, will be set to PR_TRUE if the entry is found,
-   *               to PR_FALSE otherwise.
-   * @return The entry, or nsnull if not found. Do not release this pointer!
-   */
-  RefPtr* GetWeak(KeyType aKey, PRBool* aFound = nsnull) const;
-};
-
-/**
- * Thread-safe version of nsRefPtrHashtable
- * @param KeyClass a wrapper-class for the hashtable key, see nsHashKeys.h
- *   for a complete specification.
- * @param RefPtr the reference-type being wrapped
- */
-template<class KeyClass, class RefPtr>
-class nsRefPtrHashtableMT :
-  public nsBaseHashtableMT< KeyClass, nsRefPtr<RefPtr> , RefPtr* >
-{
-public:
-  typedef typename KeyClass::KeyType KeyType;
-  typedef RefPtr* UserDataType;
-
-  /**
-   * @copydoc nsBaseHashtable::Get
-   * @param pData This is an XPCOM getter, so pData is already_addrefed.
-   *   If the key doesn't exist, pData will be set to nsnull.
-   */
-  PRBool Get(KeyType aKey, UserDataType* pData) const;
-
-  // GetWeak does not make sense on a multi-threaded hashtable, where another
-  // thread may remove the entry (and hence release it) as soon as GetWeak
-  // returns
-};
-
-
-//
-// nsRefPtrHashtable definitions
-//
-
-template<class KeyClass, class RefPtr>
-PRBool
-nsRefPtrHashtable<KeyClass,RefPtr>::Get
-  (KeyType aKey, UserDataType* pRefPtr) const
-{
-  typename nsBaseHashtable<KeyClass, nsRefPtr<RefPtr>, RefPtr*>::EntryType* ent =
-    GetEntry(aKey);
-
-  if (ent)
-  {
-    if (pRefPtr)
-    {
-      *pRefPtr = ent->mData;
-
-      NS_IF_ADDREF(*pRefPtr);
-    }
-
-    return PR_TRUE;
-  }
-
-  // if the key doesn't exist, set *pRefPtr to null
-  // so that it is a valid XPCOM getter
-  if (pRefPtr)
-    *pRefPtr = nsnull;
-
-  return PR_FALSE;
-}
-
-template<class KeyClass, class RefPtr>
-RefPtr*
-nsRefPtrHashtable<KeyClass,RefPtr>::GetWeak
-  (KeyType aKey, PRBool* aFound) const
-{
-  typename nsBaseHashtable<KeyClass, nsRefPtr<RefPtr>, RefPtr*>::EntryType* ent =
-    GetEntry(aKey);
-
-  if (ent)
-  {
-    if (aFound)
-      *aFound = PR_TRUE;
-
-    return ent->mData;
-  }
-
-  // Key does not exist, return nsnull and set aFound to PR_FALSE
-  if (aFound)
-    *aFound = PR_FALSE;
-  return nsnull;
-}
-
-//
-// nsRefPtrHashtableMT definitions
-//
-
-template<class KeyClass, class RefPtr>
-PRBool
-nsRefPtrHashtableMT<KeyClass,RefPtr>::Get
-  (KeyType aKey, UserDataType* pRefPtr) const
-{
-  PR_Lock(this->mLock);
-
-  typename nsBaseHashtableMT<KeyClass, nsRefPtr<RefPtr>, RefPtr*>::EntryType* ent =
-    GetEntry(aKey);
-
-  if (ent)
-  {
-    if (pRefPtr)
-    {
-      *pRefPtr = ent->mData;
-
-      NS_IF_ADDREF(*pRefPtr);
-    }
-
-    PR_Unlock(this->mLock);
-
-    return PR_TRUE;
-  }
-
-  // if the key doesn't exist, set *pRefPtr to null
-  // so that it is a valid XPCOM getter
-  if (pRefPtr)
-    *pRefPtr = nsnull;
-
-  PR_Unlock(this->mLock);
-
-  return PR_FALSE;
-}
+#define nsRefPtrHashtable nsInterfaceHashtable
 
 #endif // nsRefPtrHashtable_h__
diff --git a/xpcom/glue/nsTHashtable.h b/xpcom/glue/nsTHashtable.h
--- a/xpcom/glue/nsTHashtable.h
+++ b/xpcom/glue/nsTHashtable.h
@@ -41,6 +41,7 @@
 #include "nscore.h"
 #include "pldhash.h"
 #include "nsDebug.h"
+#include "nsAllocator.h"
 #include NEW_H
 
 // helper function for nsTHashtable::Clear()
@@ -64,7 +65,7 @@ PL_DHashStubEnumRemove(PLDHashTable    *
  *   PLDHashTable code.
  *<pre>   class EntryType : public PLDHashEntryHdr
  *   {
- *   public: or friend nsTHashtable<EntryType>;
+ *   public: or friend nsTHashtable<EntryType, Allocator>;
  *     // KeyType is what we use when Get()ing or Put()ing this entry
  *     // this should either be a simple datatype (PRUint32, nsISupports*) or
  *     // a const reference (const nsAString&)
@@ -91,9 +92,6 @@ PL_DHashStubEnumRemove(PLDHashTable    *
  *     // HashKey(): calculate the hash number
  *     static PLDHashNumber HashKey(KeyTypePointer aKey);
  *
- *     // ALLOW_MEMMOVE can we move this class with memmove(), or do we have
- *     // to use the copy constructor?
- *     enum { ALLOW_MEMMOVE = PR_(TRUE or FALSE) };
  *   }</pre>
  *
  * @see nsInterfaceHashtable
@@ -102,7 +100,7 @@ PL_DHashStubEnumRemove(PLDHashTable    *
  * @author "Benjamin Smedberg <bsmedberg@covad.net>"
  */
 
-template<class EntryType>
+template<class EntryType, class Allocator=CAllocator>
 class nsTHashtable
 {
 public:
@@ -251,8 +249,22 @@ public:
     PL_DHashTableEnumerate(&mTable, PL_DHashStubEnumRemove, nsnull);
   }
 
+  /**
+   * Get a pointer to the entry store, for passing to WB()
+   */
+  const void* GetEntryStore() const
+  {
+    return mTable.entryStore;
+  }
+
 protected:
   PLDHashTable mTable;
+
+  static void* PR_CALLBACK s_AllocTable(PLDHashTable *table,
+                                        PRUint32      nbytes);
+
+  static void PR_CALLBACK s_FreeTable(PLDHashTable *table,
+                                      void         *ptr);
 
   static const void* PR_CALLBACK s_GetKey(PLDHashTable    *table,
                                           PLDHashEntryHdr *entry);
@@ -263,10 +275,6 @@ protected:
   static PRBool PR_CALLBACK s_MatchEntry(PLDHashTable           *table,
                                          const PLDHashEntryHdr  *entry,
                                          const void             *key);
-  
-  static void PR_CALLBACK s_CopyEntry(PLDHashTable          *table,
-                                      const PLDHashEntryHdr *from,
-                                      PLDHashEntryHdr       *to);
   
   static void PR_CALLBACK s_ClearEntry(PLDHashTable *table,
                                        PLDHashEntryHdr *entry);
@@ -294,33 +302,33 @@ protected:
                                                 void            *arg);
 private:
   // copy constructor, not implemented
-  nsTHashtable(nsTHashtable<EntryType>& toCopy);
+  nsTHashtable(nsTHashtable<EntryType, Allocator>& toCopy);
 
   // assignment operator, not implemented
-  nsTHashtable<EntryType>& operator= (nsTHashtable<EntryType>& toEqual);
+  nsTHashtable<EntryType, Allocator>& operator= (nsTHashtable<EntryType, Allocator>& toEqual);
 };
 
 //
 // template definitions
 //
 
-template<class EntryType>
-nsTHashtable<EntryType>::nsTHashtable()
+template<class EntryType, class Allocator>
+nsTHashtable<EntryType, Allocator>::nsTHashtable()
 {
   // entrySize is our "I'm initialized" indicator
   mTable.entrySize = 0;
 }
 
-template<class EntryType>
-nsTHashtable<EntryType>::~nsTHashtable()
+template<class EntryType, class Allocator>
+nsTHashtable<EntryType, Allocator>::~nsTHashtable()
 {
   if (mTable.entrySize)
     PL_DHashTableFinish(&mTable);
 }
 
-template<class EntryType>
+template<class EntryType, class Allocator>
 PRBool
-nsTHashtable<EntryType>::Init(PRUint32 initSize)
+nsTHashtable<EntryType, Allocator>::Init(PRUint32 initSize)
 {
   if (mTable.entrySize)
   {
@@ -328,10 +336,10 @@ nsTHashtable<EntryType>::Init(PRUint32 i
     return PR_TRUE;
   }
 
-  static PLDHashTableOps sOps = 
+  static const PLDHashTableOps sOps = 
   {
-    ::PL_DHashAllocTable,
-    ::PL_DHashFreeTable,
+    s_AllocTable,
+    s_FreeTable,
     s_HashKey,
     s_MatchEntry,
     ::PL_DHashMoveEntryStub,
@@ -340,11 +348,6 @@ nsTHashtable<EntryType>::Init(PRUint32 i
     s_InitEntry
   };
 
-  if (!EntryType::ALLOW_MEMMOVE)
-  {
-    sOps.moveEntry = s_CopyEntry;
-  }
-  
   if (!PL_DHashTableInit(&mTable, &sOps, nsnull, sizeof(EntryType), initSize))
   {
     // if failed, reset "flag"
@@ -357,62 +360,65 @@ nsTHashtable<EntryType>::Init(PRUint32 i
 
 // static definitions
 
-template<class EntryType>
+template<class EntryType, class Allocator>
+void*
+nsTHashtable<EntryType, Allocator>::s_AllocTable(PLDHashTable *,
+                                                 PRUint32 nbytes)
+{
+  return Allocator::Alloc(nbytes);
+}
+
+template<class EntryType, class Allocator>
+void
+nsTHashtable<EntryType, Allocator>::s_FreeTable(PLDHashTable *,
+                                                void *ptr)
+{
+  return Allocator::Free(ptr);
+}
+
+template<class EntryType, class Allocator>
 PLDHashNumber
-nsTHashtable<EntryType>::s_HashKey(PLDHashTable  *table,
-                                   const void    *key)
+nsTHashtable<EntryType, Allocator>::s_HashKey(PLDHashTable  *table,
+                                              const void    *key)
 {
   return EntryType::HashKey(reinterpret_cast<const KeyTypePointer>(key));
 }
 
-template<class EntryType>
+template<class EntryType, class Allocator>
 PRBool
-nsTHashtable<EntryType>::s_MatchEntry(PLDHashTable          *table,
-                                      const PLDHashEntryHdr *entry,
-                                      const void            *key)
+nsTHashtable<EntryType, Allocator>::s_MatchEntry(PLDHashTable          *table,
+                                                 const PLDHashEntryHdr *entry,
+                                                 const void            *key)
 {
   return ((const EntryType*) entry)->KeyEquals(
     reinterpret_cast<const KeyTypePointer>(key));
 }
 
-template<class EntryType>
+template<class EntryType, class Allocator>
 void
-nsTHashtable<EntryType>::s_CopyEntry(PLDHashTable          *table,
-                                     const PLDHashEntryHdr *from,
-                                     PLDHashEntryHdr       *to)
-{
-  EntryType* fromEntry =
-    const_cast<EntryType*>(reinterpret_cast<const EntryType*>(from));
-
-  new(to) EntryType(*fromEntry);
-
-  fromEntry->~EntryType();
-}
-
-template<class EntryType>
-void
-nsTHashtable<EntryType>::s_ClearEntry(PLDHashTable    *table,
-                                      PLDHashEntryHdr *entry)
+nsTHashtable<EntryType, Allocator>::s_ClearEntry(PLDHashTable    *table,
+                                                 PLDHashEntryHdr *entry)
 {
   reinterpret_cast<EntryType*>(entry)->~EntryType();
 }
 
-template<class EntryType>
+template<class EntryType, class Allocator>
 PRBool
-nsTHashtable<EntryType>::s_InitEntry(PLDHashTable    *table,
-                                     PLDHashEntryHdr *entry,
-                                     const void      *key)
+nsTHashtable<EntryType, Allocator>::s_InitEntry(PLDHashTable    *table,
+                                                PLDHashEntryHdr *entry,
+                                                const void      *key)
 {
-  new(entry) EntryType(reinterpret_cast<KeyTypePointer>(key));
+  new(entry) EntryType(reinterpret_cast<KeyTypePointer>(key),
+                       table->entryStore);
   return PR_TRUE;
 }
 
-template<class EntryType>
+template<class EntryType, class Allocator>
 PLDHashOperator
-nsTHashtable<EntryType>::s_EnumStub(PLDHashTable    *table,
-                                    PLDHashEntryHdr *entry,
-                                    PRUint32         number,
-                                    void            *arg)
+nsTHashtable<EntryType, Allocator>::s_EnumStub(PLDHashTable    *table,
+                                               PLDHashEntryHdr *entry,
+                                               PRUint32         number,
+                                               void            *arg)
 {
   // dereferences the function-pointer to the user's enumeration function
   return (* reinterpret_cast<s_EnumArgs*>(arg)->userFunc)(
diff --git a/xpcom/tests/TestHashtables.cpp b/xpcom/tests/TestHashtables.cpp
--- a/xpcom/tests/TestHashtables.cpp
+++ b/xpcom/tests/TestHashtables.cpp
@@ -99,8 +99,7 @@ public:
   typedef const char* KeyType;
   typedef const char* KeyTypePointer;
 
-  EntityToUnicodeEntry(const char* aKey) { mNode = nsnull; }
-  EntityToUnicodeEntry(const EntityToUnicodeEntry& aEntry) { mNode = aEntry.mNode; }
+  EntityToUnicodeEntry(const char* aKey, const void *entryStore) { mNode = nsnull; }
   ~EntityToUnicodeEntry() { };
 
   PRBool KeyEquals(const char* aEntity) const { return !strcmp(mNode->mStr, aEntity); }
@@ -510,71 +509,6 @@ main(void) {
   printf("OK\n");
 
   //
-  // now check a thread-safe data-hashtable
-  //
-
-  nsDataHashtableMT<nsUint32HashKey,const char*> UniToEntityL;
-
-  printf("Initializing nsDataHashtableMT...");
-  if (!UniToEntityL.Init(ENTITY_COUNT)) {
-    printf("FAILED\n");
-    exit (10);
-  }
-  printf("OK\n");
-
-  printf("Filling hash with %d entries.\n", ENTITY_COUNT);
-
-  for (i = 0; i < ENTITY_COUNT; ++i) {
-    printf("  Putting entry %u...", gEntities[i].mUnicode);
-    if (!UniToEntityL.Put(gEntities[i].mUnicode, gEntities[i].mStr)) {
-      printf("FAILED\n");
-      exit (11);
-    }
-    printf("OK...\n");
-  }
-
-  printf("Testing Get:\n");
-
-  for (i = 0; i < ENTITY_COUNT; ++i) {
-    printf("  Getting entry %u...", gEntities[i].mUnicode);
-    if (!UniToEntityL.Get(gEntities[i].mUnicode, &str)) {
-      printf("FAILED\n");
-      exit (12);
-    }
-
-    printf("Found %s\n", str);
-  }
-
-  printf("Testing non-existent entries...");
-  if (UniToEntityL.Get(99446, &str)) {
-    printf("FOUND! BAD!\n");
-    exit (13);
-  }
-      
-  printf("not found; good.\n");
-      
-  printf("Enumerating:\n");
-  
-  count = UniToEntityL.EnumerateRead(nsDEnumRead, nsnull);
-  if (count != ENTITY_COUNT) {
-    printf("  Bad count!\n");
-    exit (14);
-  }
-  
-  printf("Clearing...");
-  UniToEntityL.Clear();
-  printf("OK\n");
-
-  printf("Checking count...");
-  count = UniToEntityL.Enumerate(nsDEnum, nsnull);
-  if (count) {
-    printf("  Clear did not remove all entries.\n");
-    exit (15);
-  }
-
-  printf("OK\n");
-
-  //
   // now check a class-hashtable
   //
 
@@ -636,74 +570,6 @@ main(void) {
 
   printf("Checking count...");
   count = EntToUniClass.Enumerate(nsCEnum, nsnull);
-  if (count) {
-    printf("  Clear did not remove all entries.\n");
-    exit (21);
-  }
-
-  printf("OK\n");
-
-  //
-  // now check a thread-safe class-hashtable
-  //
-
-  nsClassHashtableMT<nsCStringHashKey,TestUniChar> EntToUniClassL;
-
-  printf("Initializing nsClassHashtableMT...");
-  if (!EntToUniClassL.Init(ENTITY_COUNT)) {
-    printf("FAILED\n");
-    exit (16);
-  }
-  printf("OK\n");
-
-  printf("Filling hash with %d entries.\n", ENTITY_COUNT);
-
-  for (i = 0; i < ENTITY_COUNT; ++i) {
-    printf("  Putting entry %u...", gEntities[i].mUnicode);
-    TestUniChar* temp = new TestUniChar(gEntities[i].mUnicode);
-
-    if (!EntToUniClassL.Put(nsDependentCString(gEntities[i].mStr), temp)) {
-      printf("FAILED\n");
-      delete temp;
-      exit (17);
-    }
-    printf("OK...\n");
-  }
-
-  printf("Testing Get:\n");
-
-  for (i = 0; i < ENTITY_COUNT; ++i) {
-    printf("  Getting entry %s...", gEntities[i].mStr);
-    if (!EntToUniClassL.Get(nsDependentCString(gEntities[i].mStr), &myChar)) {
-      printf("FAILED\n");
-      exit (18);
-    }
-
-    printf("Found %c\n", myChar->GetChar());
-  }
-
-  printf("Testing non-existent entries...");
-  if (EntToUniClassL.Get(NS_LITERAL_CSTRING("xxxx"), &myChar)) {
-    printf("FOUND! BAD!\n");
-    exit (19);
-  }
-      
-  printf("not found; good.\n");
-      
-  printf("Enumerating:\n");
-  
-  count = EntToUniClassL.EnumerateRead(nsCEnumRead, nsnull);
-  if (count != ENTITY_COUNT) {
-    printf("  Bad count!\n");
-    exit (20);
-  }
-  
-  printf("Clearing...\n");
-  EntToUniClassL.Clear();
-  printf("  Clearing OK\n");
-
-  printf("Checking count...");
-  count = EntToUniClassL.Enumerate(nsCEnum, nsnull);
   if (count) {
     printf("  Clear did not remove all entries.\n");
     exit (21);
@@ -861,78 +727,5 @@ main(void) {
 
   printf("OK\n");
 
-  //
-  // now check a thread-safe interface hashtable
-  //
-
-  nsInterfaceHashtableMT<nsUint32HashKey,IFoo> UniToEntClass2L;
-
-  printf("Initializing nsInterfaceHashtableMT...");
-  if (!UniToEntClass2L.Init(ENTITY_COUNT)) {
-    printf("FAILED\n");
-    exit (28);
-  }
-  printf("OK\n");
-
-  printf("Filling hash with %d entries.\n", ENTITY_COUNT);
-
-  for (i = 0; i < ENTITY_COUNT; ++i) {
-    printf("  Putting entry %u...", gEntities[i].mUnicode);
-    nsCOMPtr<IFoo> foo;
-    CreateIFoo(getter_AddRefs(foo));
-    foo->SetString(nsDependentCString(gEntities[i].mStr));
-    
-    if (!UniToEntClass2L.Put(gEntities[i].mUnicode, foo)) {
-      printf("FAILED\n");
-      exit (29);
-    }
-    printf("OK...\n");
-  }
-
-  printf("Testing Get:\n");
-
-  for (i = 0; i < ENTITY_COUNT; ++i) {
-    printf("  Getting entry %s...", gEntities[i].mStr);
-    
-    nsCOMPtr<IFoo> myEnt;
-    if (!UniToEntClass2L.Get(gEntities[i].mUnicode, getter_AddRefs(myEnt))) {
-      printf("FAILED\n");
-      exit (30);
-    }
-    
-    nsCAutoString str;
-    myEnt->GetString(str);
-    printf("Found %s\n", str.get());
-  }
-
-  printf("Testing non-existent entries...");
-  if (UniToEntClass2L.Get(9462, getter_AddRefs(myEnt))) {
-    printf("FOUND! BAD!\n");
-    exit (31);
-  }
-      
-  printf("not found; good.\n");
-      
-  printf("Enumerating:\n");
-  
-  count = UniToEntClass2L.EnumerateRead(nsIEnumRead, nsnull);
-  if (count != ENTITY_COUNT) {
-    printf("  Bad count!\n");
-    exit (32);
-  }
-  
-  printf("Clearing...\n");
-  UniToEntClass2L.Clear();
-  printf("  Clearing OK\n");
-
-  printf("Checking count...");
-  count = UniToEntClass2L.Enumerate(nsIEnum, nsnull);
-  if (count) {
-    printf("  Clear did not remove all entries.\n");
-    exit (33);
-  }
-
-  printf("OK\n");
-
   return 0;
 }