Bug 729940 - Part 2: Stop using crappy hash functions in Gecko. r=bz
authorJustin Lebar <justin.lebar@gmail.com>
Mon, 12 Mar 2012 18:53:18 -0400
changeset 88873 12813323739a79d0f502336952de779806505ce1
parent 88872 f9019988b9e48295713e35b5734a95a7489bfb30
child 88874 20c9cd87856b173e822cb78332d70fa129d5921c
push idunknown
push userunknown
push dateunknown
reviewersbz
bugs729940
milestone13.0a1
Bug 729940 - Part 2: Stop using crappy hash functions in Gecko. r=bz
caps/src/nsPrincipal.cpp
content/base/src/nsAttrValue.cpp
content/base/src/nsContentList.h
content/base/src/nsDOMAttributeMap.h
content/base/src/nsDocument.h
content/base/src/nsMappedAttributes.cpp
content/base/src/nsNameSpaceManager.cpp
content/base/src/nsNodeInfoManager.cpp
content/canvas/src/CanvasImageCache.cpp
content/html/content/src/nsHTMLFormElement.h
content/xslt/src/xslt/txKeyFunctionCall.cpp
content/xul/templates/src/nsRDFConInstanceTestNode.h
content/xul/templates/src/nsRDFPropertyTestNode.h
dom/base/nsScriptNameSpaceManager.cpp
dom/indexedDB/OpenDatabaseHelper.cpp
dom/plugins/base/nsJSNPRuntime.cpp
embedding/components/commandhandler/src/nsCommandParams.cpp
gfx/thebes/gfxFont.h
intl/unicharutil/util/nsUnicharUtils.cpp
intl/unicharutil/util/nsUnicharUtils.h
modules/libpref/src/Preferences.cpp
modules/libpref/src/nsPrefBranch.h
netwerk/base/public/nsNetUtil.h
netwerk/base/public/nsURIHashKey.h
netwerk/cache/nsCacheEntry.cpp
netwerk/cookie/nsCookieService.h
netwerk/dns/nsHostResolver.cpp
netwerk/protocol/http/nsHttp.cpp
parser/htmlparser/src/nsHTMLTags.cpp
rdf/base/src/nsRDFService.cpp
security/manager/ssl/src/nsNSSCallbacks.cpp
toolkit/system/gnome/nsAlertsIconListener.cpp
xpcom/components/ManifestParser.cpp
xpcom/ds/nsAtomTable.cpp
xpcom/ds/nsCRT.cpp
xpcom/ds/nsCRT.h
xpcom/ds/nsHashtable.cpp
xpcom/ds/nsStaticNameTable.cpp
xpcom/glue/nsHashKeys.h
xpcom/glue/nsTHashtable.cpp
xpcom/glue/pldhash.cpp
xpcom/io/nsLocalFileOS2.cpp
xpcom/io/nsLocalFileUnix.cpp
xpcom/tests/TestHashtables.cpp
xpcom/tests/TestUTF.cpp
--- a/caps/src/nsPrincipal.cpp
+++ b/caps/src/nsPrincipal.cpp
@@ -55,16 +55,17 @@
 #include "nsIObjectOutputStream.h"
 #include "nsIClassInfoImpl.h"
 #include "nsDOMError.h"
 #include "nsIContentSecurityPolicy.h"
 
 #include "nsPrincipal.h"
 
 #include "mozilla/Preferences.h"
+#include "mozilla/HashFunctions.h"
 
 using namespace mozilla;
 
 static bool gCodeBasePrincipalSupport = false;
 static bool gIsObservingCodeBasePrincipalSupport = false;
 
 static bool URIIsImmutable(nsIURI* aURI)
 {
@@ -796,17 +797,17 @@ nsPrincipal::SetCsp(nsIContentSecurityPo
 
 NS_IMETHODIMP
 nsPrincipal::GetHashValue(PRUint32* aValue)
 {
   NS_PRECONDITION(mCert || mCodebase, "Need a cert or codebase");
 
   // If there is a certificate, it takes precendence over the codebase.
   if (mCert) {
-    *aValue = nsCRT::HashCode(mCert->fingerprint.get());
+    *aValue = HashString(mCert->fingerprint);
   }
   else {
     *aValue = nsScriptSecurityManager::HashPrincipalByOrigin(this);
   }
 
   return NS_OK;
 }
 
--- a/content/base/src/nsAttrValue.cpp
+++ b/content/base/src/nsAttrValue.cpp
@@ -46,20 +46,19 @@
 #include "nsUnicharUtils.h"
 #include "mozilla/css/StyleRule.h"
 #include "mozilla/css/Declaration.h"
 #include "nsIHTMLDocument.h"
 #include "nsIDocument.h"
 #include "nsContentUtils.h"
 #include "nsReadableUtils.h"
 #include "prprf.h"
+#include "mozilla/HashFunctions.h"
 
-namespace css = mozilla::css;
-
-using mozilla::SVGAttrValueWrapper;
+using namespace mozilla;
 
 #define MISC_STR_PTR(_cont) \
   reinterpret_cast<void*>((_cont)->mStringBits & NS_ATTRVALUE_POINTERVALUE_MASK)
 
 nsTArray<const nsAttrValue::EnumTable*>* nsAttrValue::sEnumTableArray = nsnull;
 
 nsAttrValue::nsAttrValue()
     : mBits(0)
@@ -387,29 +386,29 @@ nsAttrValue::SetTo(const nsSVGIntegerPai
 
 void
 nsAttrValue::SetTo(const nsSVGLength2& aValue, const nsAString* aSerialized)
 {
   SetSVGType(eSVGLength, &aValue, aSerialized);
 }
 
 void
-nsAttrValue::SetTo(const mozilla::SVGLengthList& aValue,
+nsAttrValue::SetTo(const SVGLengthList& aValue,
                    const nsAString* aSerialized)
 {
   // While an empty string will parse as a length list, there's no need to store
   // it (and SetMiscAtomOrString will assert if we try)
   if (aSerialized && aSerialized->IsEmpty()) {
     aSerialized = nsnull;
   }
   SetSVGType(eSVGLengthList, &aValue, aSerialized);
 }
 
 void
-nsAttrValue::SetTo(const mozilla::SVGNumberList& aValue,
+nsAttrValue::SetTo(const SVGNumberList& aValue,
                    const nsAString* aSerialized)
 {
   // While an empty string will parse as a number list, there's no need to store
   // it (and SetMiscAtomOrString will assert if we try)
   if (aSerialized && aSerialized->IsEmpty()) {
     aSerialized = nsnull;
   }
   SetSVGType(eSVGNumberList, &aValue, aSerialized);
@@ -417,60 +416,60 @@ nsAttrValue::SetTo(const mozilla::SVGNum
 
 void
 nsAttrValue::SetTo(const nsSVGNumberPair& aValue, const nsAString* aSerialized)
 {
   SetSVGType(eSVGNumberPair, &aValue, aSerialized);
 }
 
 void
-nsAttrValue::SetTo(const mozilla::SVGPathData& aValue,
+nsAttrValue::SetTo(const SVGPathData& aValue,
                    const nsAString* aSerialized)
 {
   // While an empty string will parse as path data, there's no need to store it
   // (and SetMiscAtomOrString will assert if we try)
   if (aSerialized && aSerialized->IsEmpty()) {
     aSerialized = nsnull;
   }
   SetSVGType(eSVGPathData, &aValue, aSerialized);
 }
 
 void
-nsAttrValue::SetTo(const mozilla::SVGPointList& aValue,
+nsAttrValue::SetTo(const SVGPointList& aValue,
                    const nsAString* aSerialized)
 {
   // While an empty string will parse as a point list, there's no need to store
   // it (and SetMiscAtomOrString will assert if we try)
   if (aSerialized && aSerialized->IsEmpty()) {
     aSerialized = nsnull;
   }
   SetSVGType(eSVGPointList, &aValue, aSerialized);
 }
 
 void
-nsAttrValue::SetTo(const mozilla::SVGAnimatedPreserveAspectRatio& aValue,
+nsAttrValue::SetTo(const SVGAnimatedPreserveAspectRatio& aValue,
                    const nsAString* aSerialized)
 {
   SetSVGType(eSVGPreserveAspectRatio, &aValue, aSerialized);
 }
 
 void
-nsAttrValue::SetTo(const mozilla::SVGStringList& aValue,
+nsAttrValue::SetTo(const SVGStringList& aValue,
                    const nsAString* aSerialized)
 {
   // While an empty string will parse as a string list, there's no need to store
   // it (and SetMiscAtomOrString will assert if we try)
   if (aSerialized && aSerialized->IsEmpty()) {
     aSerialized = nsnull;
   }
   SetSVGType(eSVGStringList, &aValue, aSerialized);
 }
 
 void
-nsAttrValue::SetTo(const mozilla::SVGTransformList& aValue,
+nsAttrValue::SetTo(const SVGTransformList& aValue,
                    const nsAString* aSerialized)
 {
   // While an empty string will parse as a transform list, there's no need to
   // store it (and SetMiscAtomOrString will assert if we try)
   if (aSerialized && aSerialized->IsEmpty()) {
     aSerialized = nsnull;
   }
   SetSVGType(eSVGTransformList, &aValue, aSerialized);
@@ -759,17 +758,17 @@ PRUint32
 nsAttrValue::HashValue() const
 {
   switch(BaseType()) {
     case eStringBase:
     {
       nsStringBuffer* str = static_cast<nsStringBuffer*>(GetPtr());
       if (str) {
         PRUint32 len = str->StorageSize()/sizeof(PRUnichar) - 1;
-        return nsCRT::HashCode(static_cast<PRUnichar*>(str->Data()), len);
+        return HashString(static_cast<PRUnichar*>(str->Data()), len);
       }
 
       return 0;
     }
     case eOtherBase:
     {
       break;
     }
@@ -807,24 +806,24 @@ nsAttrValue::HashValue() const
       return cont->mColor;
     }
     case eCSSStyleRule:
     {
       return NS_PTR_TO_INT32(cont->mCSSStyleRule);
     }
     case eAtomArray:
     {
-      PRUint32 retval = 0;
+      PRUint32 hash = 0;
       PRUint32 count = cont->mAtomArray->Length();
       for (nsCOMPtr<nsIAtom> *cur = cont->mAtomArray->Elements(),
                              *end = cur + count;
            cur != end; ++cur) {
-        retval ^= NS_PTR_TO_INT32(cur->get());
+        hash = AddToHash(hash, cur->get());
       }
-      return retval;
+      return hash;
     }
     case eDoubleValue:
     {
       // XXX this is crappy, but oh well
       return cont->mDoubleValue;
     }
     case eIntMarginValue:
     {
--- a/content/base/src/nsContentList.h
+++ b/content/base/src/nsContentList.h
@@ -50,18 +50,18 @@
 #include "nsIHTMLCollection.h"
 #include "nsIDOMNodeList.h"
 #include "nsINodeList.h"
 #include "nsStubMutationObserver.h"
 #include "nsIAtom.h"
 #include "nsINameSpaceManager.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsWrapperCache.h"
-#include "nsCRT.h"
 #include "nsHashKeys.h"
+#include "mozilla/HashFunctions.h"
 
 // Magic namespace id that means "match all namespaces".  This is
 // negative so it won't collide with actual namespace constants.
 #define kNameSpaceID_Wildcard PR_INT32_MIN
 
 // This is a callback function type that can be used to implement an
 // arbitrary matching algorithm.  aContent is the content that may
 // match the list, while aNamespaceID, aAtom, and aData are whatever
@@ -199,20 +199,18 @@ struct nsContentListKey
     : mRootNode(aContentListKey.mRootNode),
       mMatchNameSpaceId(aContentListKey.mMatchNameSpaceId),
       mTagname(aContentListKey.mTagname)
   {
   }
 
   inline PRUint32 GetHash(void) const
   {
-    return
-      HashString(mTagname) ^
-      (NS_PTR_TO_INT32(mRootNode) << 12) ^
-      (mMatchNameSpaceId << 24);
+    PRUint32 hash = mozilla::HashString(mTagname);
+    return mozilla::AddToHash(hash, mRootNode, mMatchNameSpaceId);
   }
   
   nsINode* const mRootNode; // Weak ref
   const PRInt32 mMatchNameSpaceId;
   const nsAString& mTagname;
 };
 
 /**
@@ -485,18 +483,18 @@ public:
                        const nsAString& aString) :
     mRootNode(aRootNode),
     mFunc(aFunc),
     mString(aString)
     {}
 
   PRUint32 GetHash(void) const
   {
-    return NS_PTR_TO_INT32(mRootNode) ^ (NS_PTR_TO_INT32(mFunc) << 12) ^
-      nsCRT::HashCode(mString.BeginReading(), mString.Length());
+    PRUint32 hash = mozilla::HashString(mString);
+    return mozilla::AddToHash(hash, mRootNode, mFunc);
   }
 
 private:
   friend class nsCacheableFuncStringContentList;
 
   nsINode* const mRootNode;
   const nsContentListMatchFunc mFunc;
   const nsAString& mString;
--- a/content/base/src/nsDOMAttributeMap.h
+++ b/content/base/src/nsDOMAttributeMap.h
@@ -107,18 +107,17 @@ public:
     }
 
   static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
   static PLDHashNumber HashKey(KeyTypePointer aKey)
     {
       if (!aKey)
         return 0;
 
-      return PR_ROTATE_LEFT32(static_cast<PRUint32>(aKey->mNamespaceID), 4) ^
-             NS_PTR_TO_INT32(aKey->mLocalName);
+      return mozilla::HashGeneric(aKey->mNamespaceID, aKey->mLocalName);
     }
   enum { ALLOW_MEMMOVE = true };
 
 private:
   nsAttrKey mKey;
 };
 
 // Helper class that implements the nsIDOMNamedNodeMap interface.
--- a/content/base/src/nsDocument.h
+++ b/content/base/src/nsDocument.h
@@ -233,18 +233,17 @@ public:
       return aKey->mCallback == mKey.mCallback &&
              aKey->mData == mKey.mData &&
              aKey->mForImage == mKey.mForImage;
     }
 
     static KeyTypePointer KeyToPointer(KeyType& aKey) { return &aKey; }
     static PLDHashNumber HashKey(KeyTypePointer aKey)
     {
-      return (NS_PTR_TO_INT32(aKey->mCallback) >> 2) ^
-             (NS_PTR_TO_INT32(aKey->mData));
+      return mozilla::HashGeneric(aKey->mCallback, aKey->mData);
     }
     enum { ALLOW_MEMMOVE = true };
     
     ChangeCallback mKey;
   };
 
 private:
   void FireChangeCallbacks(Element* aOldElement, Element* aNewElement,
--- a/content/base/src/nsMappedAttributes.cpp
+++ b/content/base/src/nsMappedAttributes.cpp
@@ -40,16 +40,19 @@
  * A unique per-element set of attributes that is used as an
  * nsIStyleRule; used to implement presentational attributes.
  */
 
 #include "nsMappedAttributes.h"
 #include "nsHTMLStyleSheet.h"
 #include "nsRuleWalker.h"
 #include "prmem.h"
+#include "mozilla/HashFunctions.h"
+
+using namespace mozilla;
 
 nsMappedAttributes::nsMappedAttributes(nsHTMLStyleSheet* aSheet,
                                        nsMapRuleToAttributesFunc aMapRuleFunc)
   : mAttrCount(0),
     mSheet(aSheet),
     mRuleMapper(aMapRuleFunc)
 {
 }
@@ -171,24 +174,26 @@ nsMappedAttributes::Equals(const nsMappe
   }
 
   return true;
 }
 
 PRUint32
 nsMappedAttributes::HashValue() const
 {
-  PRUint32 value = NS_PTR_TO_INT32(mRuleMapper);
+  PRUint32 hash = HashGeneric(mRuleMapper);
 
   PRUint32 i;
   for (i = 0; i < mAttrCount; ++i) {
-    value ^= Attrs()[i].mName.HashValue() ^ Attrs()[i].mValue.HashValue();
+    hash = AddToHash(hash,
+                     Attrs()[i].mName.HashValue(),
+                     Attrs()[i].mValue.HashValue());
   }
 
-  return value;
+  return hash;
 }
 
 void
 nsMappedAttributes::SetStyleSheet(nsHTMLStyleSheet* aSheet)
 {
   if (mSheet) {
     mSheet->DropMappedAttributes(this);
   }
--- a/content/base/src/nsNameSpaceManager.cpp
+++ b/content/base/src/nsNameSpaceManager.cpp
@@ -52,16 +52,17 @@
 
 #ifdef MOZ_XTF
 #include "nsIServiceManager.h"
 #include "nsIXTFService.h"
 #include "nsContentUtils.h"
 static NS_DEFINE_CID(kXTFServiceCID, NS_XTFSERVICE_CID);
 #endif
 
+using namespace mozilla;
 using namespace mozilla::dom;
 
 #define kXMLNSNameSpaceURI "http://www.w3.org/2000/xmlns/"
 #define kXMLNameSpaceURI "http://www.w3.org/XML/1998/namespace"
 #define kXHTMLNameSpaceURI "http://www.w3.org/1999/xhtml"
 #define kXLinkNameSpaceURI "http://www.w3.org/1999/xlink"
 #define kXSLTNameSpaceURI "http://www.w3.org/1999/XSL/Transform"
 #define kXBLNameSpaceURI "http://www.mozilla.org/xbl"
--- a/content/base/src/nsNodeInfoManager.cpp
+++ b/content/base/src/nsNodeInfoManager.cpp
@@ -51,16 +51,18 @@
 #include "nsReadableUtils.h"
 #include "nsGkAtoms.h"
 #include "nsComponentManagerUtils.h"
 #include "nsLayoutStatics.h"
 #include "nsBindingManager.h"
 #include "nsHashKeys.h"
 #include "nsCCUncollectableMarker.h"
 
+using namespace mozilla;
+
 #ifdef MOZ_LOGGING
 // so we can get logging even in release builds
 #define FORCE_PR_LOG 1
 #endif
 #include "prlog.h"
 
 #ifdef PR_LOGGING
 static PRLogModuleInfo* gNodeInfoManagerLeakPRLog;
@@ -70,16 +72,19 @@ PLHashNumber
 nsNodeInfoManager::GetNodeInfoInnerHashValue(const void *key)
 {
   NS_ASSERTION(key, "Null key passed to nsNodeInfo::GetHashValue!");
 
   const nsINodeInfo::nsNodeInfoInner *node =
     reinterpret_cast<const nsINodeInfo::nsNodeInfoInner *>(key);
 
   if (node->mName) {
+    // Ideally, we'd return node->mName->hash() here.  But that doesn't work at
+    // the moment because node->mName->hash() is not the same as
+    // HashString(*(node->mNameString)).  See bug 732815.
     return HashString(nsDependentAtomString(node->mName));
   }
   return HashString(*(node->mNameString));
 }
 
 
 PRIntn
 nsNodeInfoManager::NodeInfoInnerKeyCompare(const void *key1, const void *key2)
--- a/content/canvas/src/CanvasImageCache.cpp
+++ b/content/canvas/src/CanvasImageCache.cpp
@@ -97,17 +97,17 @@ public:
   bool KeyEquals(KeyTypePointer key) const
   {
     return mData->mImage == key->mImage && mData->mCanvas == key->mCanvas;
   }
 
   static KeyTypePointer KeyToPointer(KeyType& key) { return &key; }
   static PLDHashNumber HashKey(KeyTypePointer key)
   {
-    return (NS_PTR_TO_INT32(key->mImage) ^ NS_PTR_TO_INT32(key->mCanvas)) >> 2;
+    return HashGeneric(key->mImage, key->mCanvas);
   }
   enum { ALLOW_MEMMOVE = true };
 
   nsAutoPtr<ImageCacheEntryData> mData;
 };
 
 class ImageCache MOZ_FINAL : public nsExpirationTracker<ImageCacheEntryData,4> {
 public:
--- a/content/html/content/src/nsHTMLFormElement.h
+++ b/content/html/content/src/nsHTMLFormElement.h
@@ -44,57 +44,23 @@
 #include "nsFormSubmission.h"
 #include "nsGenericHTMLElement.h"
 #include "nsIDOMHTMLFormElement.h"
 #include "nsIWebProgressListener.h"
 #include "nsIRadioGroupContainer.h"
 #include "nsIURI.h"
 #include "nsIWeakReferenceUtils.h"
 #include "nsPIDOMWindow.h"
-#include "nsUnicharUtils.h"
 #include "nsThreadUtils.h"
 #include "nsInterfaceHashtable.h"
 #include "nsDataHashtable.h"
 
 class nsFormControlList;
 class nsIMutableArray;
 
-/**
- * hashkey wrapper using nsAString KeyType
- *
- * @see nsTHashtable::EntryType for specification
- */
-class nsStringCaseInsensitiveHashKey : public PLDHashEntryHdr
-{
-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() { }
-
-  KeyType GetKey() const { return mStr; }
-  bool KeyEquals(const KeyTypePointer aKey) const
-  {
-    return mStr.Equals(*aKey, nsCaseInsensitiveStringComparator());
-  }
-
-  static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
-  static PLDHashNumber HashKey(const KeyTypePointer aKey)
-  {
-      nsAutoString tmKey(*aKey);
-      ToLowerCase(tmKey);
-      return HashString(tmKey);
-  }
-  enum { ALLOW_MEMMOVE = true };
-
-private:
-  const nsString mStr;
-};
-
 class nsHTMLFormElement : public nsGenericHTMLElement,
                           public nsIDOMHTMLFormElement,
                           public nsIWebProgressListener,
                           public nsIForm,
                           public nsIRadioGroupContainer
 {
 public:
   nsHTMLFormElement(already_AddRefed<nsINodeInfo> aNodeInfo);
--- a/content/xslt/src/xslt/txKeyFunctionCall.cpp
+++ b/content/xslt/src/xslt/txKeyFunctionCall.cpp
@@ -39,16 +39,19 @@
 #include "txExecutionState.h"
 #include "nsGkAtoms.h"
 #include "txSingleNodeContext.h"
 #include "txXSLTFunctions.h"
 #include "nsReadableUtils.h"
 #include "txKey.h"
 #include "txXSLTPatterns.h"
 #include "txNamespaceMap.h"
+#include "mozilla/HashFunctions.h"
+
+using namespace mozilla;
 
 /*
  * txKeyFunctionCall
  * A representation of the XSLT additional function: key()
  */
 
 /*
  * Creates a new key function call
@@ -158,35 +161,40 @@ txKeyValueHashEntry::KeyEquals(KeyTypePo
     return mKey.mKeyName == aKey->mKeyName &&
            mKey.mRootIdentifier == aKey->mRootIdentifier &&
            mKey.mKeyValue.Equals(aKey->mKeyValue);
 }
 
 PLDHashNumber
 txKeyValueHashEntry::HashKey(KeyTypePointer aKey)
 {
-    return aKey->mKeyName.mNamespaceID ^
-           NS_PTR_TO_INT32(aKey->mKeyName.mLocalName.get()) ^
-           aKey->mRootIdentifier ^
-           HashString(aKey->mKeyValue);
+    const txKeyValueHashKey* key =
+        static_cast<const txKeyValueHashKey*>(aKey);
+
+    return AddToHash(HashString(key->mKeyValue),
+                     key->mKeyName.mNamespaceID,
+                     key->mRootIdentifier,
+                     key->mKeyName.mLocalName.get());
 }
 
 bool
 txIndexedKeyHashEntry::KeyEquals(KeyTypePointer aKey) const
 {
     return mKey.mKeyName == aKey->mKeyName &&
            mKey.mRootIdentifier == aKey->mRootIdentifier;
 }
 
 PLDHashNumber
 txIndexedKeyHashEntry::HashKey(KeyTypePointer aKey)
 {
-    return aKey->mKeyName.mNamespaceID ^
-           NS_PTR_TO_INT32(aKey->mKeyName.mLocalName.get()) ^
-           aKey->mRootIdentifier;
+    const txIndexedKeyHashKey* key =
+        static_cast<const txIndexedKeyHashKey*>(aKey);
+    return HashGeneric(key->mKeyName.mNamespaceID,
+                       key->mRootIdentifier,
+                       key->mKeyName.mLocalName.get());
 }
 
 /*
  * Class managing XSLT-keys
  */
 
 nsresult
 txKeyHash::getKeyNodes(const txExpandedName& aKeyName,
--- a/content/xul/templates/src/nsRDFConInstanceTestNode.h
+++ b/content/xul/templates/src/nsRDFConInstanceTestNode.h
@@ -104,19 +104,18 @@ public:
             this->~Element();
             MemoryElement::gPool.Free(this, sizeof(Element));
         }
 
         virtual const char* Type() const {
             return "nsRDFConInstanceTestNode::Element"; }
 
         virtual PLHashNumber Hash() const {
-            return (PLHashNumber(NS_PTR_TO_INT32(mContainer.get())) >> 4) ^
-                PLHashNumber(mContainerTest) ^
-                (PLHashNumber(mEmptyTest) << 4); }
+            return mozilla::HashGeneric(mContainerTest, mEmptyTest, mContainer.get());
+        }
 
         virtual bool Equals(const MemoryElement& aElement) const {
             if (aElement.Type() == Type()) {
                 const Element& element = static_cast<const Element&>(aElement);
                 return mContainer == element.mContainer
                     && mContainerTest == element.mContainerTest
                     && mEmptyTest == element.mEmptyTest;
             }
--- a/content/xul/templates/src/nsRDFPropertyTestNode.h
+++ b/content/xul/templates/src/nsRDFPropertyTestNode.h
@@ -119,19 +119,18 @@ public:
             this->~Element();
             MemoryElement::gPool.Free(this, sizeof(Element));
         }
 
         virtual const char* Type() const {
             return "nsRDFPropertyTestNode::Element"; }
 
         virtual PLHashNumber Hash() const {
-            return PLHashNumber(NS_PTR_TO_INT32(mSource.get())) ^
-                (PLHashNumber(NS_PTR_TO_INT32(mProperty.get())) >> 4) ^
-                (PLHashNumber(NS_PTR_TO_INT32(mTarget.get())) >> 12); }
+            return mozilla::HashGeneric(mSource.get(), mProperty.get(), mTarget.get());
+        }
 
         virtual bool Equals(const MemoryElement& aElement) const {
             if (aElement.Type() == Type()) {
                 const Element& element = static_cast<const Element&>(aElement);
                 return mSource == element.mSource
                     && mProperty == element.mProperty
                     && mTarget == element.mTarget;
             }
--- a/dom/base/nsScriptNameSpaceManager.cpp
+++ b/dom/base/nsScriptNameSpaceManager.cpp
@@ -55,31 +55,32 @@
 #include "nsDOMClassInfo.h"
 #include "nsCRT.h"
 #include "nsIObserverService.h"
 #include "mozilla/Services.h"
 
 #define NS_INTERFACE_PREFIX "nsI"
 #define NS_DOM_INTERFACE_PREFIX "nsIDOM"
 
+using namespace mozilla;
+
 // Our extended PLDHashEntryHdr
 class GlobalNameMapEntry : public PLDHashEntryHdr
 {
 public:
   // Our hash table ops don't care about the order of these members
   nsString mKey;
   nsGlobalNameStruct mGlobalName;
 };
 
 
 static PLDHashNumber
 GlobalNameHashHashKey(PLDHashTable *table, const void *key)
 {
   const nsAString *str = static_cast<const nsAString *>(key);
-
   return HashString(*str);
 }
 
 static bool
 GlobalNameHashMatchEntry(PLDHashTable *table, const PLDHashEntryHdr *entry,
                          const void *key)
 {
   const GlobalNameMapEntry *e =
--- a/dom/indexedDB/OpenDatabaseHelper.cpp
+++ b/dom/indexedDB/OpenDatabaseHelper.cpp
@@ -46,16 +46,17 @@
 #include "nsThreadUtils.h"
 #include "snappy/snappy.h"
 #include "test_quota.h"
 
 #include "IDBEvents.h"
 #include "IDBFactory.h"
 #include "IndexedDatabaseManager.h"
 
+using namespace mozilla;
 USING_INDEXEDDB_NAMESPACE
 
 namespace {
 
 // If JS_STRUCTURED_CLONE_VERSION changes then we need to update our major
 // schema version.
 PR_STATIC_ASSERT(JS_STRUCTURED_CLONE_VERSION == 1);
 
--- a/dom/plugins/base/nsJSNPRuntime.cpp
+++ b/dom/plugins/base/nsJSNPRuntime.cpp
@@ -51,20 +51,22 @@
 #include "nsIDocument.h"
 #include "nsIJSRuntimeService.h"
 #include "nsIJSContextStack.h"
 #include "nsIXPConnect.h"
 #include "nsIDOMElement.h"
 #include "prmem.h"
 #include "nsIContent.h"
 #include "nsIPluginInstanceOwner.h"
+#include "mozilla/HashFunctions.h"
 
 #define NPRUNTIME_JSCLASS_NAME "NPObject JS wrapper class"
 
 using namespace mozilla::plugins::parent;
+using namespace mozilla;
 
 #include "mozilla/plugins/PluginScriptableObjectParent.h"
 using mozilla::plugins::PluginScriptableObjectParent;
 using mozilla::plugins::ParentNPObject;
 
 // Hash of JSObject wrappers that wraps JSObjects as NPObjects. There
 // will be one wrapper per JSObject per plugin instance, i.e. if two
 // plugins access the JSObject x, two wrappers for x will be
@@ -1017,18 +1019,17 @@ public:
   nsJSObjWrapper *mJSObjWrapper;
 };
 
 
 static PLDHashNumber
 JSObjWrapperHash(PLDHashTable *table, const void *key)
 {
   const nsJSObjWrapperKey *e = static_cast<const nsJSObjWrapperKey *>(key);
-
-  return (PLDHashNumber)((PRWord)e->mJSObj ^ (PRWord)e->mNpp) >> 2;
+  return HashGeneric(e->mJSObj, e->mNpp);
 }
 
 static bool
 JSObjWrapperHashMatchEntry(PLDHashTable *table, const PLDHashEntryHdr *entry,
                            const void *key)
 {
   const nsJSObjWrapperKey *objWrapperKey =
     static_cast<const nsJSObjWrapperKey *>(key);
--- a/embedding/components/commandhandler/src/nsCommandParams.cpp
+++ b/embedding/components/commandhandler/src/nsCommandParams.cpp
@@ -36,17 +36,19 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "xpcom-config.h"
 #include NEW_H    // for placement new
 #include "nscore.h"
 #include "nsCRT.h"
 
 #include "nsCommandParams.h"
+#include "mozilla/HashFunctions.h"
 
+using namespace mozilla;
 
 PLDHashTableOps nsCommandParams::sHashOps =
 {
     PL_DHashAllocTable,
     PL_DHashFreeTable,
     HashKey,
     HashMatchEntry,
     HashMoveEntry,
@@ -351,17 +353,17 @@ nsCommandParams::GetOrMakeEntry(const ch
 
 #if 0
 #pragma mark -
 #endif
 
 PLDHashNumber
 nsCommandParams::HashKey(PLDHashTable *table, const void *key)
 {
-  return nsCRT::HashCode((const char *)key);
+  return HashString((const char *)key);
 }
 
 bool
 nsCommandParams::HashMatchEntry(PLDHashTable *table,
                                 const PLDHashEntryHdr *entry, const void *key)
 {
   const char*   keyString = (const char*)key;
   const HashEntry*   thisEntry = static_cast<const HashEntry*>(entry);
--- a/gfx/thebes/gfxFont.h
+++ b/gfx/thebes/gfxFont.h
@@ -53,16 +53,17 @@
 #include "gfxSkipChars.h"
 #include "gfxRect.h"
 #include "nsExpirationTracker.h"
 #include "gfxFontConstants.h"
 #include "gfxPlatform.h"
 #include "nsIAtom.h"
 #include "nsISupportsImpl.h"
 #include "gfxPattern.h"
+#include "mozilla/HashFunctions.h"
 
 typedef struct _cairo_scaled_font cairo_scaled_font_t;
 
 #ifdef DEBUG
 #include <stdio.h>
 #endif
 
 class gfxContext;
@@ -801,17 +802,17 @@ protected:
         // blank. The caller of Put() will fill this in.
         HashEntry(KeyTypePointer aStr) : mFont(nsnull) { }
         HashEntry(const HashEntry& toCopy) : mFont(toCopy.mFont) { }
         ~HashEntry() { }
 
         bool KeyEquals(const KeyTypePointer aKey) const;
         static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
         static PLDHashNumber HashKey(const KeyTypePointer aKey) {
-            return NS_PTR_TO_INT32(aKey->mFontEntry) ^ aKey->mStyle->Hash();
+            return mozilla::HashGeneric(aKey->mStyle->Hash(), aKey->mFontEntry);
         }
         enum { ALLOW_MEMMOVE = true };
 
         gfxFont* mFont;
     };
 
     nsTHashtable<HashEntry> mFonts;
 
--- a/intl/unicharutil/util/nsUnicharUtils.cpp
+++ b/intl/unicharutil/util/nsUnicharUtils.cpp
@@ -42,16 +42,17 @@
 #include "nsUnicharUtilCIID.h"
 
 #include "nsCRT.h"
 #include "nsICaseConversion.h"
 #include "nsServiceManagerUtils.h"
 #include "nsXPCOMStrings.h"
 #include "casetable.h"
 #include "nsUTF8Utils.h"
+#include "nsHashKeys.h"
 
 #include <ctype.h>
 
 // For gUpperToTitle
 enum {
   kUpperIdx =0,
   kTitleIdx
 };
@@ -535,8 +536,38 @@ CaseInsensitiveUTF8CharsEqual(const char
   }
 
   // Can't have an error past this point.
   *aErr = false;
 
   return leftChar == rightChar;
 }
 
+namespace mozilla {
+
+PRUint32
+HashUTF8AsUTF16(const char* aUTF8, PRUint32 aLength, bool* aErr)
+{
+  PRUint32 hash = 0;
+  const char* s = aUTF8;
+  const char* end = aUTF8 + aLength;
+
+  *aErr = false;
+
+  while (s < end)
+  {
+    PRUint32 ucs4 = UTF8CharEnumerator::NextChar(&s, end, aErr);
+    if (*aErr) {
+      return 0;
+    }
+
+    if (ucs4 < PLANE1_BASE) {
+      hash = AddToHash(hash, ucs4);
+    }
+    else {
+      hash = AddToHash(hash, H_SURROGATE(ucs4), L_SURROGATE(ucs4));
+    }
+  }
+
+  return hash;
+}
+
+} // namespace mozilla
--- a/intl/unicharutil/util/nsUnicharUtils.h
+++ b/intl/unicharutil/util/nsUnicharUtils.h
@@ -158,9 +158,24 @@ CaseInsensitiveCompare(const char* aLeft
  * aRightNext are guaranteed to be initialized.
  */
 bool
 CaseInsensitiveUTF8CharsEqual(const char* aLeft, const char* aRight,
                               const char* aLeftEnd, const char* aRightEnd,
                               const char** aLeftNext, const char** aRightNext,
                               bool* aErr);
 
+namespace mozilla {
+
+/**
+ * Hash a UTF8 string as though it were a UTF16 string.
+ *
+ * The value returned is the same as if we converted the string to UTF16 and
+ * then ran HashString() on the result.
+ *
+ * The given |length| is in bytes.
+ */
+PRUint32
+HashUTF8AsUTF16(const char* aUTF8, PRUint32 aLength, bool* aErr);
+
+} // namespace mozilla
+
 #endif  /* nsUnicharUtils_h__ */
--- a/modules/libpref/src/Preferences.cpp
+++ b/modules/libpref/src/Preferences.cpp
@@ -35,16 +35,17 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "mozilla/dom/ContentChild.h"
 
 #include "mozilla/Util.h"
+#include "mozilla/HashFunctions.h"
 
 #include "nsXULAppAPI.h"
 
 #include "mozilla/Preferences.h"
 #include "nsAppDirectoryServiceDefs.h"
 #include "nsDirectoryServiceDefs.h"
 #include "nsICategoryManager.h"
 #include "nsCategoryManagerUtils.h"
@@ -101,19 +102,18 @@ public:
 
   static const ValueObserverHashKey* KeyToPointer(ValueObserverHashKey *aKey)
   {
     return aKey;
   }
 
   static PLDHashNumber HashKey(const ValueObserverHashKey *aKey)
   {
-    PRUint32 strHash = nsCRT::HashCode(aKey->mPrefName.BeginReading(),
-                                       aKey->mPrefName.Length());
-    return PR_ROTATE_LEFT32(strHash, 4) ^ NS_PTR_TO_UINT32(aKey->mCallback);
+    PLDHashNumber hash = HashString(aKey->mPrefName);
+    return AddToHash(hash, aKey->mCallback);
   }
 
   ValueObserverHashKey(const char *aPref, PrefChangedFunc aCallback) :
     mPrefName(aPref), mCallback(aCallback) { }
 
   ValueObserverHashKey(const ValueObserverHashKey *aOther) :
     mPrefName(aOther->mPrefName), mCallback(aOther->mCallback)
   { }
--- a/modules/libpref/src/nsPrefBranch.h
+++ b/modules/libpref/src/nsPrefBranch.h
@@ -50,37 +50,35 @@
 #include "nsString.h"
 #include "nsVoidArray.h"
 #include "nsTArray.h"
 #include "nsWeakReference.h"
 #include "nsClassHashtable.h"
 #include "nsCRT.h"
 #include "prbit.h"
 #include "nsTraceRefcnt.h"
+#include "mozilla/HashFunctions.h"
 
 class nsPrefBranch;
 
 class PrefCallback : public PLDHashEntryHdr {
 
   public:
     typedef PrefCallback* KeyType;
     typedef const PrefCallback* KeyTypePointer;
 
     static const PrefCallback* KeyToPointer(PrefCallback *aKey)
     {
       return aKey;
     }
 
     static PLDHashNumber HashKey(const PrefCallback *aKey)
     {
-      PRUint32 strHash = nsCRT::HashCode(aKey->mDomain.BeginReading(),
-                                         aKey->mDomain.Length());
-
-      return PR_ROTATE_LEFT32(strHash, 4) ^
-             NS_PTR_TO_UINT32(aKey->mCanonical);
+      PRUint32 hash = mozilla::HashString(aKey->mDomain);
+      return mozilla::AddToHash(hash, aKey->mCanonical);
     }
 
 
   public:
     // Create a PrefCallback with a strong reference to its observer.
     PrefCallback(const char *aDomain, nsIObserver *aObserver,
                  nsPrefBranch *aBranch)
       : mDomain(aDomain),
--- a/netwerk/base/public/nsNetUtil.h
+++ b/netwerk/base/public/nsNetUtil.h
@@ -43,18 +43,19 @@
 #define nsNetUtil_h__
 
 #include "nsNetError.h"
 #include "nsNetCID.h"
 #include "nsStringGlue.h"
 #include "nsMemory.h"
 #include "nsCOMPtr.h"
 #include "prio.h" // for read/write flags, permissions, etc.
+#include "nsHashKeys.h"
 
-#include "nsCRT.h"
+#include "plstr.h"
 #include "nsIURI.h"
 #include "nsIStandardURL.h"
 #include "nsIURLParser.h"
 #include "nsIUUIDGenerator.h"
 #include "nsIInputStream.h"
 #include "nsIOutputStream.h"
 #include "nsISafeOutputStream.h"
 #include "nsIStreamListener.h"
@@ -101,21 +102,20 @@
 #include "nsIMutable.h"
 #include "nsIPropertyBag2.h"
 #include "nsIWritablePropertyBag2.h"
 #include "nsIIDNService.h"
 #include "nsIChannelEventSink.h"
 #include "nsIChannelPolicy.h"
 #include "nsISocketProviderService.h"
 #include "nsISocketProvider.h"
+#include "nsIRedirectChannelRegistrar.h"
 #include "nsIMIMEHeaderParam.h"
 #include "mozilla/Services.h"
 
-#include "nsIRedirectChannelRegistrar.h"
-
 #ifdef MOZILLA_INTERNAL_API
 
 inline already_AddRefed<nsIIOService>
 do_GetIOService(nsresult* error = 0)
 {
     already_AddRefed<nsIIOService> ret = mozilla::services::GetIOService();
     if (error)
         *error = ret.get() ? NS_OK : NS_ERROR_FAILURE;
@@ -1613,40 +1613,39 @@ NS_GetFinalChannelURI(nsIChannel* channe
 inline PRUint32
 NS_SecurityHashURI(nsIURI* aURI)
 {
     nsCOMPtr<nsIURI> baseURI = NS_GetInnermostURI(aURI);
 
     nsCAutoString scheme;
     PRUint32 schemeHash = 0;
     if (NS_SUCCEEDED(baseURI->GetScheme(scheme)))
-        schemeHash = nsCRT::HashCode(scheme.get());
+        schemeHash = mozilla::HashString(scheme);
 
     // TODO figure out how to hash file:// URIs
     if (scheme.EqualsLiteral("file"))
         return schemeHash; // sad face
 
     if (scheme.EqualsLiteral("imap") ||
         scheme.EqualsLiteral("mailbox") ||
         scheme.EqualsLiteral("news"))
     {
         nsCAutoString spec;
         PRUint32 specHash = baseURI->GetSpec(spec);
         if (NS_SUCCEEDED(specHash))
-            specHash = nsCRT::HashCode(spec.get());
+            specHash = mozilla::HashString(spec);
         return specHash;
     }
 
     nsCAutoString host;
     PRUint32 hostHash = 0;
     if (NS_SUCCEEDED(baseURI->GetAsciiHost(host)))
-        hostHash = nsCRT::HashCode(host.get());
+        hostHash = mozilla::HashString(host);
 
-    // XOR to combine hash values
-    return schemeHash ^ hostHash ^ NS_GetRealPort(baseURI);
+    return mozilla::AddToHash(schemeHash, hostHash, NS_GetRealPort(baseURI));
 }
 
 inline bool
 NS_SecurityCompareURIs(nsIURI* aSourceURI,
                        nsIURI* aTargetURI,
                        bool aStrictFileOriginPolicy)
 {
     // Note that this is not an Equals() test on purpose -- for URIs that don't
--- a/netwerk/base/public/nsURIHashKey.h
+++ b/netwerk/base/public/nsURIHashKey.h
@@ -35,18 +35,18 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 #ifndef nsURIHashKey_h__
 #define nsURIHashKey_h__
 
 #include "pldhash.h"
 #include "nsCOMPtr.h"
-#include "nsCRT.h"
 #include "nsIURI.h"
+#include "nsHashKeys.h"
 
 /**
  * Hashtable key class to use with nsTHashtable/nsBaseHashtable
  */
 class nsURIHashKey : public PLDHashEntryHdr
 {
 public:
     typedef nsIURI* KeyType;
@@ -67,17 +67,17 @@ public:
         }
         return false;
     }
 
     static const nsIURI* KeyToPointer(nsIURI* aKey) { return aKey; }
     static PLDHashNumber HashKey(const nsIURI* aKey) {
         nsCAutoString spec;
         const_cast<nsIURI*>(aKey)->GetSpec(spec);
-        return nsCRT::HashCode(spec.get());
+        return mozilla::HashString(spec);
     }
     
     enum { ALLOW_MEMMOVE = true };
 
 protected:
     nsCOMPtr<nsIURI> mKey;
 };
 
--- a/netwerk/cache/nsCacheEntry.cpp
+++ b/netwerk/cache/nsCacheEntry.cpp
@@ -45,18 +45,19 @@
 #include "nsCacheMetaData.h"
 #include "nsCacheRequest.h"
 #include "nsThreadUtils.h"
 #include "nsError.h"
 #include "nsICacheService.h"
 #include "nsCache.h"
 #include "nsCacheService.h"
 #include "nsCacheDevice.h"
-#include "nsCRT.h"
+#include "nsHashKeys.h"
 
+using namespace mozilla;
 
 nsCacheEntry::nsCacheEntry(nsCString *          key,
                            bool                 streamBased,
                            nsCacheStoragePolicy storagePolicy)
     : mKey(key),
       mFetchCount(0),
       mLastFetched(0),
       mLastModified(0),
@@ -518,17 +519,17 @@ nsCacheEntryHashTable::VisitEntries( PLD
 
 /**
  *  hash table operation callback functions
  */
 
 PLDHashNumber
 nsCacheEntryHashTable::HashKey( PLDHashTable *table, const void *key)
 {
-    return PL_DHashStringKey(table,((nsCString *)key)->get());
+    return HashString(*static_cast<const nsCString *>(key));
 }
 
 bool
 nsCacheEntryHashTable::MatchEntry(PLDHashTable *       /* table */,
                                   const PLDHashEntryHdr * hashEntry,
                                   const void *            key)
 {
     NS_ASSERTION(key !=  nsnull, "### nsCacheEntryHashTable::MatchEntry : null key");
--- a/netwerk/cookie/nsCookieService.h
+++ b/netwerk/cookie/nsCookieService.h
@@ -122,17 +122,17 @@ class nsCookieEntry : public PLDHashEntr
 
     static KeyTypePointer KeyToPointer(KeyType aKey)
     {
       return &aKey;
     }
 
     static PLDHashNumber HashKey(KeyTypePointer aKey)
     {
-      return HashString(*aKey);
+      return mozilla::HashString(*aKey);
     }
 
     enum { ALLOW_MEMMOVE = true };
 
     inline ArrayType& GetCookies() { return mCookies; }
 
   private:
     nsCString mBaseDomain;
--- a/netwerk/dns/nsHostResolver.cpp
+++ b/netwerk/dns/nsHostResolver.cpp
@@ -59,16 +59,17 @@
 #include "prerror.h"
 #include "prtime.h"
 #include "prlong.h"
 #include "prlog.h"
 #include "pldhash.h"
 #include "plstr.h"
 #include "nsURLHelper.h"
 
+#include "mozilla/HashFunctions.h"
 #include "mozilla/FunctionTimer.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/Telemetry.h"
 
 using namespace mozilla;
 
 //----------------------------------------------------------------------------
 
@@ -273,17 +274,17 @@ struct nsHostDBEnt : PLDHashEntryHdr
 {
     nsHostRecord *rec;
 };
 
 static PLDHashNumber
 HostDB_HashKey(PLDHashTable *table, const void *key)
 {
     const nsHostKey *hk = static_cast<const nsHostKey *>(key);
-    return PL_DHashStringKey(table, hk->host) ^ RES_KEY_FLAGS(hk->flags) ^ hk->af;
+    return AddToHash(HashString(hk->host), RES_KEY_FLAGS(hk->flags), hk->af);
 }
 
 static bool
 HostDB_MatchEntry(PLDHashTable *table,
                   const PLDHashEntryHdr *entry,
                   const void *key)
 {
     const nsHostDBEnt *he = static_cast<const nsHostDBEnt *>(entry);
--- a/netwerk/protocol/http/nsHttp.cpp
+++ b/netwerk/protocol/http/nsHttp.cpp
@@ -35,19 +35,22 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsHttp.h"
 #include "pldhash.h"
 #include "mozilla/Mutex.h"
+#include "mozilla/HashFunctions.h"
 #include "nsCRT.h"
 #include "prbit.h"
 
+using namespace mozilla;
+
 #if defined(PR_LOGGING)
 PRLogModuleInfo *gHttpLog = nsnull;
 #endif
 
 // define storage for all atoms
 #define HTTP_ATOM(_name, _value) nsHttpAtom nsHttp::_name = { _value };
 #include "nsHttpAtomList.h"
 #undef HTTP_ATOM
@@ -93,17 +96,17 @@ NewHeapAtom(const char *value) {
 }
 
 // Hash string ignore case, based on PL_HashString
 static PLDHashNumber
 StringHash(PLDHashTable *table, const void *key)
 {
     PLDHashNumber h = 0;
     for (const char *s = reinterpret_cast<const char*>(key); *s; ++s)
-        h = PR_ROTATE_LEFT32(h, 4) ^ nsCRT::ToLower(*s);
+        h = AddToHash(h, nsCRT::ToLower(*s));
     return h;
 }
 
 static bool
 StringCompare(PLDHashTable *table, const PLDHashEntryHdr *entry,
               const void *testKey)
 {
     const void *entryKey =
--- a/parser/htmlparser/src/nsHTMLTags.cpp
+++ b/parser/htmlparser/src/nsHTMLTags.cpp
@@ -38,16 +38,17 @@
 #include "mozilla/Util.h"
 
 #include "nsHTMLTags.h"
 #include "nsCRT.h"
 #include "nsReadableUtils.h"
 #include "nsString.h"
 #include "nsStaticAtom.h"
 #include "nsUnicharUtils.h"
+#include "mozilla/HashFunctions.h"
 
 using namespace mozilla;
 
 // C++ sucks! There's no way to do this with a macro, at least not
 // that I know, if you know how to do this with a macro then please do
 // so...
 static const PRUnichar sHTMLTagUnicodeName_a[] =
   {'a', '\0'};
@@ -320,19 +321,17 @@ PRInt32 nsHTMLTags::gTableRefCount;
 PLHashTable* nsHTMLTags::gTagTable;
 PLHashTable* nsHTMLTags::gTagAtomTable;
 
 
 // PRUnichar* -> id hash
 static PLHashNumber
 HTMLTagsHashCodeUCPtr(const void *key)
 {
-  const PRUnichar *str = (const PRUnichar *)key;
-
-  return nsCRT::HashCode(str);
+  return HashString(static_cast<const PRUnichar*>(key));
 }
 
 static PRIntn
 HTMLTagsKeyCompareUCPtr(const void *key1, const void *key2)
 {
   const PRUnichar *str1 = (const PRUnichar *)key1;
   const PRUnichar *str2 = (const PRUnichar *)key2;
 
--- a/rdf/base/src/nsRDFService.cpp
+++ b/rdf/base/src/nsRDFService.cpp
@@ -84,16 +84,19 @@
 #include "plstr.h"
 #include "prlog.h"
 #include "prprf.h"
 #include "prmem.h"
 #include "rdf.h"
 #include "nsCRT.h"
 #include "nsCRTGlue.h"
 #include "prbit.h"
+#include "mozilla/HashFunctions.h"
+
+using namespace mozilla;
 
 ////////////////////////////////////////////////////////////////////////
 
 static NS_DEFINE_CID(kRDFXMLDataSourceCID,    NS_RDFXMLDATASOURCE_CID);
 static NS_DEFINE_CID(kRDFDefaultResourceCID,  NS_RDFDEFAULTRESOURCE_CID);
 
 static NS_DEFINE_IID(kIRDFLiteralIID,         NS_IRDFLITERAL_IID);
 static NS_DEFINE_IID(kIRDFDateIID,         NS_IRDFDATE_IID);
@@ -150,17 +153,17 @@ static PLHashAllocOps dataSourceHashAllo
 
 struct ResourceHashEntry : public PLDHashEntryHdr {
     const char *mKey;
     nsIRDFResource *mResource;
 
     static PLDHashNumber
     HashKey(PLDHashTable *table, const void *key)
     {
-        return nsCRT::HashCode(static_cast<const char *>(key));
+        return HashString(static_cast<const char *>(key));
     }
 
     static bool
     MatchEntry(PLDHashTable *table, const PLDHashEntryHdr *hdr,
                const void *key)
     {
         const ResourceHashEntry *entry =
             static_cast<const ResourceHashEntry *>(hdr);
@@ -188,17 +191,17 @@ static PLDHashTableOps gResourceTableOps
 
 struct LiteralHashEntry : public PLDHashEntryHdr {
     nsIRDFLiteral *mLiteral;
     const PRUnichar *mKey;
 
     static PLDHashNumber
     HashKey(PLDHashTable *table, const void *key)
     {
-        return nsCRT::HashCode(static_cast<const PRUnichar *>(key));
+        return HashString(static_cast<const PRUnichar *>(key));
     }
 
     static bool
     MatchEntry(PLDHashTable *table, const PLDHashEntryHdr *hdr,
                const void *key)
     {
         const LiteralHashEntry *entry =
             static_cast<const LiteralHashEntry *>(hdr);
@@ -384,22 +387,17 @@ BlobImpl::GetLength(PRInt32 *aResult)
 struct BlobHashEntry : public PLDHashEntryHdr {
     BlobImpl *mBlob;
 
     static PLDHashNumber
     HashKey(PLDHashTable *table, const void *key)
     {
         const BlobImpl::Data *data =
             static_cast<const BlobImpl::Data *>(key);
-
-        const PRUint8 *p = data->mBytes, *limit = p + data->mLength;
-        PLDHashNumber h = 0;
-        for ( ; p < limit; ++p)
-            h = PR_ROTATE_LEFT32(h, 4) ^ *p;
-        return h;
+        return HashBytes(data->mBytes, data->mLength);
     }
 
     static bool
     MatchEntry(PLDHashTable *table, const PLDHashEntryHdr *hdr,
                const void *key)
     {
         const BlobHashEntry *entry =
             static_cast<const BlobHashEntry *>(hdr);
--- a/security/manager/ssl/src/nsNSSCallbacks.cpp
+++ b/security/manager/ssl/src/nsNSSCallbacks.cpp
@@ -49,16 +49,17 @@
 #include "nsNSSShutDown.h"
 #include "nsIUploadChannel.h"
 #include "nsThreadUtils.h"
 #include "nsIPrompt.h"
 #include "nsProxyRelease.h"
 #include "PSMRunnable.h"
 #include "nsIConsoleService.h"
 #include "nsIHttpChannelInternal.h"
+#include "nsCRT.h"
 
 #include "ssl.h"
 #include "ocsp.h"
 #include "nssb64.h"
 
 using namespace mozilla;
 using namespace mozilla::psm;
 
--- a/toolkit/system/gnome/nsAlertsIconListener.cpp
+++ b/toolkit/system/gnome/nsAlertsIconListener.cpp
@@ -38,16 +38,17 @@
 #include "nsAlertsIconListener.h"
 #include "imgIContainer.h"
 #include "imgILoader.h"
 #include "imgIRequest.h"
 #include "nsNetUtil.h"
 #include "nsIImageToPixbuf.h"
 #include "nsIStringBundle.h"
 #include "nsIObserverService.h"
+#include "nsCRT.h"
 
 #include <gdk/gdk.h>
 
 // Compatibility macro for <libnotify-0.7
 #ifndef NOTIFY_CHECK_VERSION
 #define NOTIFY_CHECK_VERSION(x,y,z) 0
 #endif
 
--- a/xpcom/components/ManifestParser.cpp
+++ b/xpcom/components/ManifestParser.cpp
@@ -53,16 +53,17 @@
 #endif
 
 #ifdef MOZ_WIDGET_ANDROID
 #include "AndroidBridge.h"
 #endif
 
 #include "mozilla/Services.h"
 
+#include "nsCRT.h"
 #include "nsConsoleMessage.h"
 #include "nsTextFormatter.h"
 #include "nsVersionComparator.h"
 #include "nsXPCOMCIDInternal.h"
 
 #include "nsIConsoleService.h"
 #include "nsIScriptError.h"
 #include "nsIXULAppInfo.h"
--- a/xpcom/ds/nsAtomTable.cpp
+++ b/xpcom/ds/nsAtomTable.cpp
@@ -32,33 +32,37 @@
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "mozilla/Assertions.h"
+#include "mozilla/HashFunctions.h"
 
 #include "nsAtomTable.h"
 #include "nsStaticAtom.h"
 #include "nsString.h"
 #include "nsReadableUtils.h"
 #include "nsUTF8Utils.h"
 #include "nsCRT.h"
 #include "pldhash.h"
 #include "prenv.h"
 #include "nsThreadUtils.h"
 #include "nsDataHashtable.h"
 #include "nsHashKeys.h"
 #include "nsAutoPtr.h"
+#include "nsUnicharUtils.h"
 
 #define PL_ARENA_CONST_ALIGN_MASK 3
 #include "plarena.h"
 
+using namespace mozilla;
+
 /**
  * The shared hash table for atom lookups.
  *
  * XXX This should be manipulated in a threadsafe way or we should make
  * sure it's only manipulated from the main thread.  Probably the latter
  * is better, since the former would hurt performance.
  *
  * If |gAtomTable.ops| is 0, then the table is uninitialized.
@@ -187,27 +191,27 @@ struct AtomTableKey
 
 static PLDHashNumber
 AtomTableGetHash(PLDHashTable *table, const void *key)
 {
   const AtomTableKey *k = static_cast<const AtomTableKey*>(key);
 
   if (k->mUTF8String) {
     bool err;
-    PRUint32 hash = nsCRT::HashCodeAsUTF16(k->mUTF8String, k->mLength, &err);
+    PRUint32 hash = HashUTF8AsUTF16(k->mUTF8String, k->mLength, &err);
     if (err) {
       AtomTableKey* mutableKey = const_cast<AtomTableKey*>(k);
       mutableKey->mUTF8String = nsnull;
       mutableKey->mLength = 0;
       hash = 0;
     }
     return hash;
   }
 
-  return nsCRT::HashCode(k->mUTF16String, k->mLength);
+  return HashString(k->mUTF16String, k->mLength);
 }
 
 static bool
 AtomTableMatchKey(PLDHashTable *table, const PLDHashEntryHdr *entry,
                   const void *key)
 {
   const AtomTableEntry *he = static_cast<const AtomTableEntry*>(entry);
   const AtomTableKey *k = static_cast<const AtomTableKey*>(key);
--- a/xpcom/ds/nsCRT.cpp
+++ b/xpcom/ds/nsCRT.cpp
@@ -50,19 +50,16 @@
  * routines, we simply return 0.
  */
 
 
 #include "nsCRT.h"
 #include "nsIServiceManager.h"
 #include "nsCharTraits.h"
 #include "nsUTF8Utils.h"
-#include "mozilla/HashFunctions.h"
-
-using namespace mozilla;
 
 //----------------------------------------------------------------------
 
 
 ////////////////////////////////////////////////////////////////////////////////
 // My lovely strtok routine
 
 #define IS_DELIM(m, c)          ((m)[(c) >> 3] & (1 << ((c) & 7)))
@@ -197,118 +194,16 @@ PRUnichar* nsCRT::strndup(const PRUnicha
   // PRUnichar* rslt = new PRUnichar[len + 1];
 
   if (rslt == NULL) return NULL;
   memcpy(rslt, str, len * sizeof(PRUnichar));
   rslt[len] = 0;
   return rslt;
 }
 
-  /**
-   * |nsCRT::HashCode| is identical to |PL_HashString|, which tests
-   *  (http://bugzilla.mozilla.org/showattachment.cgi?attach_id=26596)
-   *  show to be the best hash among several other choices.
-   *
-   * We re-implement it here rather than calling it for two reasons:
-   *  (1) in this interface, we also calculate the length of the
-   *  string being hashed; and (2) the narrow and wide and `buffer' versions here
-   *  will hash equivalent strings to the same value, e.g., "Hello" and L"Hello".
-   */
-PRUint32 nsCRT::HashCode(const char* str, PRUint32* resultingStrLen)
-{
-  PRUint32 h = 0;
-  const char* s = str;
-
-  if (!str) return h;
-
-  unsigned char c;
-  while ( (c = *s++) ) {
-    h = AddToHash(h, c);
-  }
-
-  if ( resultingStrLen )
-    *resultingStrLen = (s-str)-1;
-
-  return h;
-}
-
-PRUint32 nsCRT::HashCode(const char* start, PRUint32 length)
-{
-  PRUint32 h = 0;
-  const char* s = start;
-  const char* end = start + length;
-
-  unsigned char c;
-  while ( s < end ) {
-    c = *s++;
-    h = AddToHash(h, c);
-  }
-
-  return h;
-}
-
-PRUint32 nsCRT::HashCode(const PRUnichar* str, PRUint32* resultingStrLen)
-{
-  PRUint32 h = 0;
-  const PRUnichar* s = str;
-
-  if (!str) return h;
-
-  PRUnichar c;
-  while ( (c = *s++) )
-    h = AddToHash(h, c);
-
-  if ( resultingStrLen )
-    *resultingStrLen = (s-str)-1;
-
-  return h;
-}
-
-PRUint32 nsCRT::HashCode(const PRUnichar* start, PRUint32 length)
-{
-  PRUint32 h = 0;
-  const PRUnichar* s = start;
-  const PRUnichar* end = start + length;
-
-  PRUnichar c;
-  while ( s < end ) {
-    c = *s++;
-    h = AddToHash(h, c);
-  }
-
-  return h;
-}
-
-PRUint32 nsCRT::HashCodeAsUTF16(const char* start, PRUint32 length,
-                                bool* err)
-{
-  PRUint32 h = 0;
-  const char* s = start;
-  const char* end = start + length;
-
-  *err = false;
-
-  while ( s < end )
-    {
-      PRUint32 ucs4 = UTF8CharEnumerator::NextChar(&s, end, err);
-      if (*err) {
-	return 0;
-      }
-
-      if (ucs4 < PLANE1_BASE) {
-        h = AddToHash(h, ucs4);
-      }
-      else {
-        h = AddToHash(h, H_SURROGATE(ucs4), L_SURROGATE(ucs4));
-      }
-    }
-
-  return h;
-}
-
 // This should use NSPR but NSPR isn't exporting its PR_strtoll function
 // Until then...
 PRInt64 nsCRT::atoll(const char *str)
 {
     if (!str)
         return LL_Zero();
 
     PRInt64 ll = LL_Zero(), digitll = LL_Zero();
--- a/xpcom/ds/nsCRT.h
+++ b/xpcom/ds/nsCRT.h
@@ -224,38 +224,16 @@ public:
   // by strndup(PRUnichar*, PRUint32).
   static PRUnichar* strndup(const PRUnichar* str, PRUint32 len);
 
   static void free(PRUnichar* str) {
   	nsCppSharedAllocator<PRUnichar> shared_allocator;
   	shared_allocator.deallocate(str, 0 /*we never new or kept the size*/);
   }
 
-  // Computes the hashcode for a c-string, returns the string length as
-  // an added bonus.
-  static PRUint32 HashCode(const char* str,
-                           PRUint32* resultingStrLen = nsnull);
-
-  // Computes the hashcode for a length number of bytes of c-string data.
-  static PRUint32 HashCode(const char* start, PRUint32 length);
-
-  // Computes the hashcode for a ucs2 string, returns the string length
-  // as an added bonus.
-  static PRUint32 HashCode(const PRUnichar* str,
-                           PRUint32* resultingStrLen = nsnull);
-
-  // Computes the hashcode for a buffer with a specified length.
-  static PRUint32 HashCode(const PRUnichar* str, PRUint32 strLen);
-
-  // Computes a hashcode for a length number of UTF8
-  // characters. Returns the same hash code as the HashCode method
-  // taking a |PRUnichar*| would if the string were converted to UTF16.
-  static PRUint32 HashCodeAsUTF16(const char* start, PRUint32 length,
-                                  bool* err);
-
   // String to longlong
   static PRInt64 atoll(const char *str);
   
   static char ToUpper(char aChar) { return NS_ToUpper(aChar); }
   static char ToLower(char aChar) { return NS_ToLower(aChar); }
   
   static bool IsUpper(char aChar) { return NS_IsUpper(aChar); }
   static bool IsLower(char aChar) { return NS_IsLower(aChar); }
--- a/xpcom/ds/nsHashtable.cpp
+++ b/xpcom/ds/nsHashtable.cpp
@@ -49,16 +49,19 @@
 #include <string.h>
 #include "prmem.h"
 #include "prlog.h"
 #include "nsHashtable.h"
 #include "nsReadableUtils.h"
 #include "nsIObjectInputStream.h"
 #include "nsIObjectOutputStream.h"
 #include "nsCRT.h"
+#include "mozilla/HashFunctions.h"
+
+using namespace mozilla;
 
 struct HTEntry : PLDHashEntryHdr
 {
     nsHashKey* key;
     void* value;
 };
 
 //
@@ -529,17 +532,17 @@ nsCStringKey::~nsCStringKey(void)
     if (mOwnership == OWN)
         nsMemory::Free(mStr);
     MOZ_COUNT_DTOR(nsCStringKey);
 }
 
 PRUint32
 nsCStringKey::HashCode(void) const
 {
-    return nsCRT::HashCode(mStr, (PRUint32*)&mStrLen);
+    return HashString(mStr, mStrLen);
 }
 
 bool
 nsCStringKey::Equals(const nsHashKey* aKey) const
 {
     NS_ASSERTION(aKey->GetKeyType() == CStringKey, "mismatched key types");
     nsCStringKey* other = (nsCStringKey*)aKey;
     NS_ASSERTION(mStrLen != PRUint32(-1), "never called HashCode");
@@ -656,17 +659,17 @@ nsStringKey::~nsStringKey(void)
     if (mOwnership == OWN)
         nsMemory::Free(mStr);
     MOZ_COUNT_DTOR(nsStringKey);
 }
 
 PRUint32
 nsStringKey::HashCode(void) const
 {
-    return nsCRT::HashCode(mStr, (PRUint32*)&mStrLen);
+    return HashString(mStr, mStrLen);
 }
 
 bool
 nsStringKey::Equals(const nsHashKey* aKey) const
 {
     NS_ASSERTION(aKey->GetKeyType() == StringKey, "mismatched key types");
     nsStringKey* other = (nsStringKey*)aKey;
     NS_ASSERTION(mStrLen != PRUint32(-1), "never called HashCode");
--- a/xpcom/ds/nsStaticNameTable.cpp
+++ b/xpcom/ds/nsStaticNameTable.cpp
@@ -40,20 +40,23 @@
 /* Class to manage lookup of static names in a table. */
 
 #include "nsCRT.h"
 
 #include "nscore.h"
 #include "nsString.h"
 #include "nsReadableUtils.h"
 #include "prbit.h"
+#include "mozilla/HashFunctions.h"
 
 #define PL_ARENA_CONST_ALIGN_MASK 3
 #include "nsStaticNameTable.h"
 
+using namespace mozilla;
+
 struct NameTableKey
 {
     NameTableKey(const nsAFlatCString* aKeyStr)
         : mIsUnichar(false)
     {
         mKeyStr.m1b = aKeyStr;
     }
         
@@ -108,24 +111,24 @@ static PLDHashNumber
 caseInsensitiveStringHashKey(PLDHashTable *table, const void *key)
 {
     PLDHashNumber h = 0;
     const NameTableKey* tableKey = static_cast<const NameTableKey*>(key);
     if (tableKey->mIsUnichar) {
         for (const PRUnichar* s = tableKey->mKeyStr.m2b->get();
              *s != '\0';
              s++)
-            h = PR_ROTATE_LEFT32(h, 4) ^ (*s & ~0x20);
+            h = AddToHash(h, *s & ~0x20);
     } else {
         for (const unsigned char* s =
                  reinterpret_cast<const unsigned char*>
                                  (tableKey->mKeyStr.m1b->get());
              *s != '\0';
              s++)
-            h = PR_ROTATE_LEFT32(h, 4) ^ (*s & ~0x20);
+            h = AddToHash(h, *s & ~0x20);
     }
     return h;
 }
 
 static const struct PLDHashTableOps nametable_CaseInsensitiveHashTableOps = {
     PL_DHashAllocTable,
     PL_DHashFreeTable,
     caseInsensitiveStringHashKey,
--- a/xpcom/glue/nsHashKeys.h
+++ b/xpcom/glue/nsHashKeys.h
@@ -42,20 +42,41 @@
 #include "nsISupports.h"
 #include "nsIHashable.h"
 #include "nsCOMPtr.h"
 #include "pldhash.h"
 #include NEW_H
 
 #include "nsStringGlue.h"
 #include "nsCRTGlue.h"
+#include "nsUnicharUtils.h"
 
 #include <stdlib.h>
 #include <string.h>
 
+#include "mozilla/HashFunctions.h"
+
+namespace mozilla {
+
+// These are defined analogously to the HashString overloads in mfbt.
+
+inline PRUint32
+HashString(const nsAString& aStr)
+{
+  return HashString(aStr.BeginReading(), aStr.Length());
+}
+
+inline PRUint32
+HashString(const nsACString& aStr)
+{
+  return HashString(aStr.BeginReading(), aStr.Length());
+}
+
+} // namespace mozilla
+
 /** @file nsHashKeys.h
  * standard HashKey classes for nsBaseHashtable and relatives. Each of these
  * classes follows the nsTHashtable::EntryType specification
  *
  * Lightweight keytypes provided here:
  * nsStringHashKey
  * nsCStringHashKey
  * nsUint32HashKey
@@ -67,21 +88,16 @@
  * nsISupportsHashKey
  * nsIDHashKey
  * nsDepCharHashKey
  * nsCharPtrHashKey
  * nsUnicharPtrHashKey
  * nsHashableHashKey
  */
 
-NS_COM_GLUE PRUint32 HashString(const nsAString& aStr);
-NS_COM_GLUE PRUint32 HashString(const nsACString& aStr);
-NS_COM_GLUE PRUint32 HashString(const char* aKey);
-NS_COM_GLUE PRUint32 HashString(const PRUnichar* aKey);
-
 /**
  * hashkey wrapper using nsAString KeyType
  *
  * @see nsTHashtable::EntryType for specification
  */
 class nsStringHashKey : public PLDHashEntryHdr
 {
 public:
@@ -96,24 +112,65 @@ public:
   bool KeyEquals(const KeyTypePointer aKey) const
   {
     return mStr.Equals(*aKey);
   }
 
   static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
   static PLDHashNumber HashKey(const KeyTypePointer aKey)
   {
-    return HashString(*aKey);
+    return mozilla::HashString(*aKey);
   }
   enum { ALLOW_MEMMOVE = true };
 
 private:
   const nsString mStr;
 };
 
+#ifdef MOZILLA_INTERNAL_API
+
+/**
+ * hashkey wrapper using nsAString KeyType
+ *
+ * This is internal-API only because nsCaseInsensitiveStringComparator is
+ * internal-only.
+ *
+ * @see nsTHashtable::EntryType for specification
+ */
+class nsStringCaseInsensitiveHashKey : public PLDHashEntryHdr
+{
+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() { }
+
+  KeyType GetKey() const { return mStr; }
+  bool KeyEquals(const KeyTypePointer aKey) const
+  {
+    return mStr.Equals(*aKey, nsCaseInsensitiveStringComparator());
+  }
+
+  static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
+  static PLDHashNumber HashKey(const KeyTypePointer aKey)
+  {
+      nsAutoString tmKey(*aKey);
+      ToLowerCase(tmKey);
+      return mozilla::HashString(tmKey);
+  }
+  enum { ALLOW_MEMMOVE = true };
+
+private:
+  const nsString mStr;
+};
+
+#endif
+
 /**
  * hashkey wrapper using nsACString KeyType
  *
  * @see nsTHashtable::EntryType for specification
  */
 class nsCStringHashKey : public PLDHashEntryHdr
 {
 public:
@@ -126,17 +183,17 @@ public:
 
   KeyType GetKey() const { return mStr; }
 
   bool KeyEquals(KeyTypePointer aKey) const { return mStr.Equals(*aKey); }
 
   static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
   static PLDHashNumber HashKey(KeyTypePointer aKey)
   {
-    return HashString(*aKey);
+    return mozilla::HashString(*aKey);
   }
   enum { ALLOW_MEMMOVE = true };
 
 private:
   const nsCString mStr;
 };
 
 /**
@@ -323,17 +380,22 @@ public:
   nsIDHashKey(const nsIDHashKey& toCopy) : mID(toCopy.mID) { }
   ~nsIDHashKey() { }
 
   KeyType GetKey() const { return mID; }
 
   bool KeyEquals(KeyTypePointer aKey) const { return aKey->Equals(mID); }
 
   static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
-  static PLDHashNumber HashKey(KeyTypePointer aKey);
+  static PLDHashNumber HashKey(KeyTypePointer aKey)
+  {
+    // Hash the nsID object's raw bytes.
+    return mozilla::HashBytes(aKey, sizeof(KeyType));
+  }
+
   enum { ALLOW_MEMMOVE = true };
 
 private:
   const nsID mID;
 };
 
 /**
  * hashkey wrapper for "dependent" const char*; this class does not "own"
@@ -357,17 +419,17 @@ public:
 
   const char* GetKey() const { return mKey; }
   bool KeyEquals(const char* aKey) const
   {
     return !strcmp(mKey, aKey);
   }
 
   static const char* KeyToPointer(const char* aKey) { return aKey; }
-  static PLDHashNumber HashKey(const char* aKey) { return HashString(aKey); }
+  static PLDHashNumber HashKey(const char* aKey) { return mozilla::HashString(aKey); }
   enum { ALLOW_MEMMOVE = true };
 
 private:
   const char* mKey;
 };
 
 /**
  * hashkey wrapper for const char*; at construction, this class duplicates
@@ -386,17 +448,17 @@ public:
 
   const char* GetKey() const { return mKey; }
   bool KeyEquals(KeyTypePointer aKey) const
   {
     return !strcmp(mKey, aKey);
   }
 
   static KeyTypePointer KeyToPointer(KeyType aKey) { return aKey; }
-  static PLDHashNumber HashKey(KeyTypePointer aKey) { return HashString(aKey); }
+  static PLDHashNumber HashKey(KeyTypePointer aKey) { return mozilla::HashString(aKey); }
 
   enum { ALLOW_MEMMOVE = true };
 
 private:
   const char* mKey;
 };
 
 /**
@@ -416,17 +478,17 @@ public:
 
   const PRUnichar* GetKey() const { return mKey; }
   bool KeyEquals(KeyTypePointer aKey) const
   {
     return !NS_strcmp(mKey, aKey);
   }
 
   static KeyTypePointer KeyToPointer(KeyType aKey) { return aKey; }
-  static PLDHashNumber HashKey(KeyTypePointer aKey) { return HashString(aKey); }
+  static PLDHashNumber HashKey(KeyTypePointer aKey) { return mozilla::HashString(aKey); }
 
   enum { ALLOW_MEMMOVE = true };
 
 private:
   const PRUnichar* mKey;
 };
 
 /**
--- a/xpcom/glue/nsTHashtable.cpp
+++ b/xpcom/glue/nsTHashtable.cpp
@@ -31,108 +31,17 @@
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsTHashtable.h"
-#include "nsHashKeys.h"
-#include "prbit.h"
-#include "mozilla/HashFunctions.h"
-
-using namespace mozilla;
-
-PRUint32
-HashString( const nsAString& aStr )
-{
-  PRUint32 code = 0;
-
-#ifdef MOZILLA_INTERNAL_API
-  nsAString::const_iterator begin, end;
-  aStr.BeginReading(begin);
-  aStr.EndReading(end);
-#else
-  const PRUnichar *begin, *end;
-  PRUint32 len = NS_StringGetData(aStr, &begin);
-  end = begin + len;
-#endif
-
-  while (begin != end) {
-    code = AddToHash(code, *begin);
-    ++begin;
-  }
-
-  return code;
-}
-
-PRUint32
-HashString( const nsACString& aStr )
-{
-  PRUint32 code = 0;
-
-#ifdef MOZILLA_INTERNAL_API
-  nsACString::const_iterator begin, end;
-  aStr.BeginReading(begin);
-  aStr.EndReading(end);
-#else
-  const char *begin, *end;
-  PRUint32 len = NS_CStringGetData(aStr, &begin);
-  end = begin + len;
-#endif
-
-  while (begin != end) {
-    code = AddToHash(code, *begin);
-    ++begin;
-  }
-
-  return code;
-}
-
-PRUint32
-HashString(const char *str)
-{
-  PRUint32 code = 0;
-
-  while (*str) {
-    code = AddToHash(code, *str);
-    ++str;
-  }
-
-  return code;
-}
-
-PRUint32
-HashString(const PRUnichar *str)
-{
-  PRUint32 code = 0;
-
-  while (*str) {
-    code = AddToHash(code, *str);
-    ++str;
-  }
-
-  return code;
-}
 
 PLDHashOperator
 PL_DHashStubEnumRemove(PLDHashTable    *table,
                                        PLDHashEntryHdr *entry,
                                        PRUint32         ordinal,
                                        void            *userarg)
 {
   return PL_DHASH_REMOVE;
 }
-
-PRUint32 nsIDHashKey::HashKey(const nsID* id)
-{
-  PRUint32 h = id->m0;
-  PRUint32 i;
-
-  h = PR_ROTATE_LEFT32(h, 4) ^ id->m1;
-  h = PR_ROTATE_LEFT32(h, 4) ^ id->m2;
-
-  for (i = 0; i < 8; i++)
-    h = PR_ROTATE_LEFT32(h, 4) ^ id->m3[i];
-
-  return h;
-}
--- a/xpcom/glue/pldhash.cpp
+++ b/xpcom/glue/pldhash.cpp
@@ -121,23 +121,17 @@ void
 PL_DHashFreeTable(PLDHashTable *table, void *ptr)
 {
     free(ptr);
 }
 
 PLDHashNumber
 PL_DHashStringKey(PLDHashTable *table, const void *key)
 {
-    PLDHashNumber h;
-    const unsigned char *s;
-
-    h = 0;
-    for (s = (const unsigned char *) key; *s != '\0'; s++)
-        h = AddToHash(h, *s);
-    return h;
+    return HashString(static_cast<const char*>(key));
 }
 
 PLDHashNumber
 PL_DHashVoidPtrKeyStub(PLDHashTable *table, const void *key)
 {
     return (PLDHashNumber)(PRPtrdiff)key >> 2;
 }
 
--- a/xpcom/io/nsLocalFileOS2.cpp
+++ b/xpcom/io/nsLocalFileOS2.cpp
@@ -54,16 +54,18 @@
 #include "prtypes.h"
 #include "prio.h"
 
 #include "nsReadableUtils.h"
 #include "nsISupportsPrimitives.h"
 #include "nsIMutableArray.h"
 #include "nsTraceRefcntImpl.h"
 
+using namespace mozilla;
+
 #define CHECK_mWorkingPath()                    \
     PR_BEGIN_MACRO                              \
         if (mWorkingPath.IsEmpty())             \
             return NS_ERROR_NOT_INITIALIZED;    \
     PR_END_MACRO
 
 //-----------------------------------------------------------------------------
 // static helper functions
@@ -2570,17 +2572,17 @@ nsLocalFile::Equals(nsIHashable* aOther,
     }
 
     return Equals(otherfile, aResult);
 }
 
 NS_IMETHODIMP
 nsLocalFile::GetHashCode(PRUint32 *aResult)
 {
-    *aResult = nsCRT::HashCode(mWorkingPath.get());
+    *aResult = HashString(mWorkingPath);
     return NS_OK;
 }
 
 nsresult
 NS_NewLocalFile(const nsAString &path, bool followLinks, nsILocalFile* *result)
 {
     nsCAutoString buf;
     nsresult rv = NS_CopyUnicodeToNative(path, buf);
--- a/xpcom/io/nsLocalFileUnix.cpp
+++ b/xpcom/io/nsLocalFileUnix.cpp
@@ -116,16 +116,17 @@ static nsresult MacErrorMapper(OSErr inE
 #ifdef MOZ_WIDGET_ANDROID
 #include "AndroidBridge.h"
 #include "nsIMIMEService.h"
 #include <linux/magic.h>
 #endif
 
 #include "nsNativeCharsetUtils.h"
 #include "nsTraceRefcntImpl.h"
+#include "nsHashKeys.h"
 
 using namespace mozilla;
 
 #define ENSURE_STAT_CACHE()                     \
     PR_BEGIN_MACRO                              \
         if (!FillStatCache())                   \
              return NSRESULT_FOR_ERRNO();       \
     PR_END_MACRO
@@ -2025,17 +2026,17 @@ nsLocalFile::Equals(nsIHashable* aOther,
     }
 
     return Equals(otherFile, aResult);
 }
 
 NS_IMETHODIMP
 nsLocalFile::GetHashCode(PRUint32 *aResult)
 {
-    *aResult = nsCRT::HashCode(mPath.get());
+    *aResult = HashString(mPath);
     return NS_OK;
 }
 
 nsresult 
 NS_NewLocalFile(const nsAString &path, bool followLinks, nsILocalFile* *result)
 {
     nsCAutoString buf;
     nsresult rv = NS_CopyUnicodeToNative(path, buf);
--- a/xpcom/tests/TestHashtables.cpp
+++ b/xpcom/tests/TestHashtables.cpp
@@ -102,17 +102,17 @@ public:
   typedef const char* KeyTypePointer;
 
   EntityToUnicodeEntry(const char* aKey) { mNode = nsnull; }
   EntityToUnicodeEntry(const EntityToUnicodeEntry& aEntry) { mNode = aEntry.mNode; }
   ~EntityToUnicodeEntry() { };
 
   bool KeyEquals(const char* aEntity) const { return !strcmp(mNode->mStr, aEntity); }
   static const char* KeyToPointer(const char* aEntity) { return aEntity; }
-  static PLDHashNumber HashKey(const char* aEntity) { return HashString(aEntity); }
+  static PLDHashNumber HashKey(const char* aEntity) { return mozilla::HashString(aEntity); }
   enum { ALLOW_MEMMOVE = true };
 
   const EntityNode* mNode;
 };
 
 PLDHashOperator
 nsTEnumGo(EntityToUnicodeEntry* aEntry, void* userArg) {
   printf("  enumerated \"%s\" = %u\n", 
--- a/xpcom/tests/TestUTF.cpp
+++ b/xpcom/tests/TestUTF.cpp
@@ -36,19 +36,19 @@
 
 #include "mozilla/Util.h"
 
 #include <stdio.h>
 #include <stdlib.h>
 #include "nsString.h"
 #include "nsStringBuffer.h"
 #include "nsReadableUtils.h"
-#include "nsCRTGlue.h"
 #include "UTFStrings.h"
-#include "nsCRT.h"
+#include "nsUnicharUtils.h"
+#include "mozilla/HashFunctions.h"
 
 using namespace mozilla;
 
 namespace TestUTF {
 
 bool
 test_valid()
 {
@@ -148,37 +148,37 @@ test_malformed8()
 }
 
 bool
 test_hashas16()
 {
   for (unsigned int i = 0; i < ArrayLength(ValidStrings); ++i) {
     nsDependentCString str8(ValidStrings[i].m8);
     bool err;
-    if (nsCRT::HashCode(ValidStrings[i].m16) !=
-        nsCRT::HashCodeAsUTF16(str8.get(), str8.Length(), &err) ||
+    if (HashString(ValidStrings[i].m16) !=
+        HashUTF8AsUTF16(str8.get(), str8.Length(), &err) ||
         err)
       return false;
   }
 
   for (unsigned int i = 0; i < ArrayLength(Invalid8Strings); ++i) {
     nsDependentCString str8(Invalid8Strings[i].m8);
     bool err;
-    if (nsCRT::HashCode(Invalid8Strings[i].m16) !=
-        nsCRT::HashCodeAsUTF16(str8.get(), str8.Length(), &err) ||
+    if (HashString(Invalid8Strings[i].m16) !=
+        HashUTF8AsUTF16(str8.get(), str8.Length(), &err) ||
         err)
       return false;
   }
 
 // Don't run this test in debug builds as that intentionally asserts.
 #ifndef DEBUG
   for (unsigned int i = 0; i < ArrayLength(Malformed8Strings); ++i) {
     nsDependentCString str8(Malformed8Strings[i]);
     bool err;
-    if (nsCRT::HashCodeAsUTF16(str8.get(), str8.Length(), &err) != 0 ||
+    if (HashUTF8AsUTF16(str8.get(), str8.Length(), &err) != 0 ||
         !err)
       return false;
   }
 #endif
 
   return true;
 }