Bug 729940 - Part 3: Stop using crappy hash functions in Gecko. r=bz
authorJustin Lebar <justin.lebar@gmail.com>
Sun, 04 Mar 2012 13:49:42 -0500
changeset 88235 d75775dfc565a340e2ab4ece2d3e89d17729552a
parent 88234 bfbe72a6251d86339b9301e529d4bc00fe1905cb
child 88236 158587a6b17e84403075f55e06aaf626372aac21
push id22184
push usermbrubeck@mozilla.com
push dateMon, 05 Mar 2012 20:58:48 +0000
treeherdermozilla-central@4b728a090880 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs729940
milestone13.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 729940 - Part 3: 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/nsDoubleHashtable.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)
 {
@@ -801,17 +802,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
@@ -167,20 +170,19 @@ txKeyValueHashEntry::MatchEntry(const vo
 }
 
 PLDHashNumber
 txKeyValueHashEntry::HashKey(const void* aKey)
 {
     const txKeyValueHashKey* key =
         static_cast<const txKeyValueHashKey*>(aKey);
 
-    return key->mKeyName.mNamespaceID ^
-           NS_PTR_TO_INT32(key->mKeyName.mLocalName.get()) ^
-           key->mRootIdentifier ^
-           HashString(key->mKeyValue);
+    PLDHashNumber hash = HashString(key->mKeyValue);
+    return AddToHash(hash, key->mKeyName.mNamespaceID, key->mRootIdentifier,
+                     key->mKeyName.mLocalName.get());
 }
 
 bool
 txIndexedKeyHashEntry::MatchEntry(const void* aKey) const
 {
     const txIndexedKeyHashKey* key =
         static_cast<const txIndexedKeyHashKey*>(aKey);
 
@@ -188,20 +190,19 @@ txIndexedKeyHashEntry::MatchEntry(const 
            mKey.mRootIdentifier == key->mRootIdentifier;
 }
 
 PLDHashNumber
 txIndexedKeyHashEntry::HashKey(const void* aKey)
 {
     const txIndexedKeyHashKey* key =
         static_cast<const txIndexedKeyHashKey*>(aKey);
-
-    return key->mKeyName.mNamespaceID ^
-           NS_PTR_TO_INT32(key->mKeyName.mLocalName.get()) ^
-           key->mRootIdentifier;
+    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;
@@ -790,17 +791,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
@@ -37,16 +37,17 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "mozilla/Util.h"
 
 #include "ManifestParser.h"
 
 #include <string.h>
 
+#include "nsCRT.h"
 #include "prio.h"
 #include "prprf.h"
 #if defined(XP_WIN)
 #include <windows.h>
 #elif defined(MOZ_WIDGET_COCOA)
 #include <CoreServices/CoreServices.h>
 #elif defined(MOZ_WIDGET_GTK2)
 #include <gtk/gtk.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/nsDoubleHashtable.h
+++ b/xpcom/ds/nsDoubleHashtable.h
@@ -401,17 +401,17 @@ void CLASSNAME::Remove(const KEY_TYPE aK
 class PLDHashStringEntry : public PLDHashEntryHdr
 {
 public:
   PLDHashStringEntry(const void* aKey) :
     mKey(*static_cast<const nsAString*>(aKey)) { }
   ~PLDHashStringEntry() { }
 
   static PLDHashNumber HashKey(const void* key) {
-    return HashString(*static_cast<const nsAString*>(key));
+    return mozilla::HashString(*static_cast<const nsAString*>(key));
   }
   bool MatchEntry(const void* key) const {
     return static_cast<const nsAString*>(key)->Equals(mKey);
   }
 
   const nsString mKey;
 };
 
@@ -421,17 +421,17 @@ public:
 class PLDHashCStringEntry : public PLDHashEntryHdr
 {
 public:
   PLDHashCStringEntry(const void* aKey) :
     mKey(*static_cast<const nsACString*>(aKey)) { }
   ~PLDHashCStringEntry() { }
 
   static PLDHashNumber HashKey(const void* key) {
-    return HashString(*static_cast<const nsACString*>(key));
+    return mozilla::HashString(*static_cast<const nsACString*>(key));
   }
   bool MatchEntry(const void* key) const {
     return static_cast<const nsACString*>(key)->Equals(mKey);
   }
 
   const nsCString mKey;
 };
 
--- 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,110 +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;
-  const char *origStr = str;
-
-  while (*str) {
-    code = AddToHash(code, *str);
-    ++str;
-  }
-
-  return code;
-}
-
-PRUint32
-HashString(const PRUnichar *str)
-{
-  PRUint32 code = 0;
-  const PRUnichar *origStr = str;
-
-  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;
 }