Bug 1379290 - Improve the hashing of signed 64-bit integers by piggy-backing on the same mechanism as the one we use for hashing pointers; r=glandium
authorEhsan Akhgari <ehsan@mozilla.com>
Fri, 07 Jul 2017 18:18:22 -0400
changeset 369477 8f5e29f603da08c4adee3278663461ee4155fb1e
parent 369476 9cd50771d27a16447dd12210039bc1e64aab3964
child 369478 190aa46c11c4463e5227b486ef9d66bcd9622b96
push id92704
push usereakhgari@mozilla.com
push dateWed, 19 Jul 2017 04:00:24 +0000
treeherdermozilla-inbound@8f5e29f603da [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersglandium
bugs1379290
milestone56.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 1379290 - Improve the hashing of signed 64-bit integers by piggy-backing on the same mechanism as the one we use for hashing pointers; r=glandium
mfbt/HashFunctions.h
--- a/mfbt/HashFunctions.h
+++ b/mfbt/HashFunctions.h
@@ -117,53 +117,44 @@ AddU32ToHash(uint32_t aHash, uint32_t aV
   return kGoldenRatioU32 * (RotateBitsLeft32(aHash, 5) ^ aValue);
 }
 
 /**
  * AddUintptrToHash takes sizeof(uintptr_t) as a template parameter.
  */
 template<size_t PtrSize>
 inline uint32_t
-AddUintptrToHash(uint32_t aHash, uintptr_t aValue);
-
-template<>
-inline uint32_t
-AddUintptrToHash<4>(uint32_t aHash, uintptr_t aValue)
+AddUintptrToHash(uint32_t aHash, uintptr_t aValue)
 {
   return AddU32ToHash(aHash, static_cast<uint32_t>(aValue));
 }
 
 template<>
 inline uint32_t
 AddUintptrToHash<8>(uint32_t aHash, uintptr_t aValue)
 {
-  /*
-   * The static cast to uint64_t below is necessary because this function
-   * sometimes gets compiled on 32-bit platforms (yes, even though it's a
-   * template and we never call this particular override in a 32-bit build).  If
-   * we do aValue >> 32 on a 32-bit machine, we're shifting a 32-bit uintptr_t
-   * right 32 bits, and the compiler throws an error.
-   */
   uint32_t v1 = static_cast<uint32_t>(aValue);
   uint32_t v2 = static_cast<uint32_t>(static_cast<uint64_t>(aValue) >> 32);
   return AddU32ToHash(AddU32ToHash(aHash, v1), v2);
 }
 
 } /* namespace detail */
 
 /**
  * AddToHash takes a hash and some values and returns a new hash based on the
  * inputs.
  *
  * Currently, we support hashing uint32_t's, values which we can implicitly
  * convert to uint32_t, data pointers, and function pointers.
  */
-template<typename A>
+template<typename T,
+         bool TypeIsNotIntegral = !mozilla::IsIntegral<T>::value,
+         typename U = typename mozilla::EnableIf<TypeIsNotIntegral>::Type>
 MOZ_MUST_USE inline uint32_t
-AddToHash(uint32_t aHash, A aA)
+AddToHash(uint32_t aHash, T aA)
 {
   /*
    * Try to convert |A| to uint32_t implicitly.  If this works, great.  If not,
    * we'll error out.
    */
   return detail::AddU32ToHash(aHash, aA);
 }
 
@@ -176,21 +167,25 @@ AddToHash(uint32_t aHash, A* aA)
    * catch data pointers and couldn't handle function pointers.
    */
 
   static_assert(sizeof(aA) == sizeof(uintptr_t), "Strange pointer!");
 
   return detail::AddUintptrToHash<sizeof(uintptr_t)>(aHash, uintptr_t(aA));
 }
 
-template<>
+// We use AddUintptrToHash() for hashing all integral types.  8-byte integral types
+// are treated the same as 64-bit pointers, and smaller integral types are first
+// implicitly converted to 32 bits and then passed to AddUintptrToHash() to be hased.
+template<typename T,
+         typename U = typename mozilla::EnableIf<mozilla::IsIntegral<T>::value>::Type>
 MOZ_MUST_USE inline uint32_t
-AddToHash(uint32_t aHash, uintptr_t aA)
+AddToHash(uint32_t aHash, T aA)
 {
-  return detail::AddUintptrToHash<sizeof(uintptr_t)>(aHash, aA);
+  return detail::AddUintptrToHash<sizeof(T)>(aHash, aA);
 }
 
 template<typename A, typename... Args>
 MOZ_MUST_USE uint32_t
 AddToHash(uint32_t aHash, A aArg, Args... aArgs)
 {
   return AddToHash(AddToHash(aHash, aArg), aArgs...);
 }