Skip to content

Commit 0f205a7

Browse files
committed
Bug 1477626 - Move ScrambleHashCode() from js/src/Utility.h to mfbt/HashFunctions.h. r=Waldo
And use it in PLDHashTable.cpp. MozReview-Commit-ID: BqwEkE0p5AG --HG-- extra : rebase_source : bd9118e24b82add6ad1fdcb067a5f25b25e90201
1 parent 25a1140 commit 0f205a7

File tree

6 files changed

+41
-56
lines changed

6 files changed

+41
-56
lines changed

js/public/HashTable.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1282,7 +1282,7 @@ class HashTable : private AllocPolicy
12821282

12831283
static HashNumber prepareHash(const Lookup& l)
12841284
{
1285-
HashNumber keyHash = ScrambleHashCode(HashPolicy::hash(l));
1285+
HashNumber keyHash = mozilla::ScrambleHashCode(HashPolicy::hash(l));
12861286

12871287
// Avoid reserved hash codes.
12881288
if (!isLiveHash(keyHash))

js/public/Utility.h

Lines changed: 0 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
#include "mozilla/Move.h"
1515
#include "mozilla/TemplateLib.h"
1616
#include "mozilla/UniquePtr.h"
17-
#include "mozilla/WrappingOperations.h"
1817

1918
#include <stdlib.h>
2019
#include <string.h>
@@ -664,51 +663,6 @@ typedef mozilla::UniquePtr<char16_t[], JS::FreePolicy> UniqueTwoByteChars;
664663

665664
} // namespace JS
666665

667-
namespace js {
668-
669-
namespace detail {
670-
671-
/*
672-
* Given a raw hash code, h, return a number that can be used to select a hash
673-
* bucket.
674-
*
675-
* This function aims to produce as uniform an output distribution as possible,
676-
* especially in the most significant (leftmost) bits, even though the input
677-
* distribution may be highly nonrandom, given the constraints that this must
678-
* be deterministic and quick to compute.
679-
*
680-
* Since the leftmost bits of the result are best, the hash bucket index is
681-
* computed by doing ScrambleHashCode(h) / (2^32/N) or the equivalent
682-
* right-shift, not ScrambleHashCode(h) % N or the equivalent bit-mask.
683-
*
684-
* FIXME: OrderedHashTable uses a bit-mask; see bug 775896.
685-
*/
686-
inline uint32_t
687-
ScrambleHashCode(uint32_t h)
688-
{
689-
/*
690-
* Simply returning h would not cause any hash tables to produce wrong
691-
* answers. But it can produce pathologically bad performance: The caller
692-
* right-shifts the result, keeping only the highest bits. The high bits of
693-
* hash codes are very often completely entropy-free. (So are the lowest
694-
* bits.)
695-
*
696-
* So we use Fibonacci hashing, as described in Knuth, The Art of Computer
697-
* Programming, 6.4. This mixes all the bits of the input hash code h.
698-
*
699-
* The value of goldenRatio is taken from the hex
700-
* expansion of the golden ratio, which starts 1.9E3779B9....
701-
* This value is especially good if values with consecutive hash codes
702-
* are stored in a hash table; see Knuth for details.
703-
*/
704-
static const uint32_t goldenRatio = 0x9E3779B9U;
705-
return mozilla::WrappingMultiply(h, goldenRatio);
706-
}
707-
708-
} /* namespace detail */
709-
710-
} /* namespace js */
711-
712666
/* sixgill annotation defines */
713667
#ifndef HAVE_STATIC_ANNOTATIONS
714668
# define HAVE_STATIC_ANNOTATIONS

js/src/ds/OrderedHashTable.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -618,7 +618,7 @@ class OrderedHashTable
618618

619619
public:
620620
HashNumber prepareHash(const Lookup& l) const {
621-
return ScrambleHashCode(Ops::hash(l, hcs));
621+
return mozilla::ScrambleHashCode(Ops::hash(l, hcs));
622622
}
623623

624624
private:

mfbt/HashFunctions.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,42 @@ static const uint32_t kHashNumberBits = 32;
6666
*/
6767
static const HashNumber kGoldenRatioU32 = 0x9E3779B9U;
6868

69+
/*
70+
* Given a raw hash code, h, return a number that can be used to select a hash
71+
* bucket.
72+
*
73+
* This function aims to produce as uniform an output distribution as possible,
74+
* especially in the most significant (leftmost) bits, even though the input
75+
* distribution may be highly nonrandom, given the constraints that this must
76+
* be deterministic and quick to compute.
77+
*
78+
* Since the leftmost bits of the result are best, the hash bucket index is
79+
* computed by doing ScrambleHashCode(h) / (2^32/N) or the equivalent
80+
* right-shift, not ScrambleHashCode(h) % N or the equivalent bit-mask.
81+
*
82+
* FIXME: OrderedHashTable uses a bit-mask; see bug 775896.
83+
*/
84+
constexpr HashNumber
85+
ScrambleHashCode(HashNumber h)
86+
{
87+
/*
88+
* Simply returning h would not cause any hash tables to produce wrong
89+
* answers. But it can produce pathologically bad performance: The caller
90+
* right-shifts the result, keeping only the highest bits. The high bits of
91+
* hash codes are very often completely entropy-free. (So are the lowest
92+
* bits.)
93+
*
94+
* So we use Fibonacci hashing, as described in Knuth, The Art of Computer
95+
* Programming, 6.4. This mixes all the bits of the input hash code h.
96+
*
97+
* The value of goldenRatio is taken from the hex expansion of the golden
98+
* ratio, which starts 1.9E3779B9.... This value is especially good if
99+
* values with consecutive hash codes are stored in a hash table; see Knuth
100+
* for details.
101+
*/
102+
return mozilla::WrappingMultiply(h, kGoldenRatioU32);
103+
}
104+
69105
namespace detail {
70106

71107
MOZ_NO_SANITIZE_UNSIGNED_OVERFLOW

xpcom/ds/PLDHashTable.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -528,8 +528,7 @@ PLDHashTable::ComputeKeyHash(const void* aKey) const
528528
{
529529
MOZ_ASSERT(mEntryStore.Get());
530530

531-
PLDHashNumber keyHash = mOps->hashKey(aKey);
532-
keyHash *= kGoldenRatio;
531+
PLDHashNumber keyHash = mozilla::ScrambleHashCode(mOps->hashKey(aKey));
533532

534533
// Avoid 0 and 1 hash codes, they indicate free and removed entries.
535534
if (keyHash < 2) {

xpcom/ds/PLDHashTable.h

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ struct PLDHashTableOps;
3333
// structure, for single static initialization per hash table sub-type.
3434
//
3535
// Each hash table sub-type should make its entry type a subclass of
36-
// PLDHashEntryHdr. The mKeyHash member contains the result of multiplying the
37-
// hash code returned from the hashKey callback (see below) by kGoldenRatio,
36+
// PLDHashEntryHdr. The mKeyHash member contains the result of suitably
37+
// scrambling the hash code returned from the hashKey callback (see below),
3838
// then constraining the result to avoid the magic 0 and 1 values. The stored
3939
// mKeyHash value is table size invariant, and it is maintained automatically
4040
// -- users need never access it.
@@ -503,10 +503,6 @@ class PLDHashTable
503503
}
504504

505505
private:
506-
// Multiplicative hash uses an unsigned 32 bit integer and the golden ratio,
507-
// expressed as a fixed-point 32-bit fraction.
508-
static const uint32_t kGoldenRatio = 0x9E3779B9U;
509-
510506
static uint32_t HashShift(uint32_t aEntrySize, uint32_t aLength);
511507

512508
static const PLDHashNumber kCollisionFlag = 1;

0 commit comments

Comments
 (0)