Index: src/objects.cc |
=================================================================== |
--- src/objects.cc (revision 10353) |
+++ src/objects.cc (working copy) |
@@ -5926,6 +5926,20 @@ |
// Fast check: if hash code is computed for both strings |
// a fast negative check can be performed. |
if (HasHashCode() && other->HasHashCode()) { |
+#ifdef DEBUG |
+ if (FLAG_enable_slow_asserts) { |
+ if (Hash() != other->Hash()) { |
+ bool found_difference = false; |
+ for (int i = 0; i < len; i++) { |
+ if (Get(i) != other->Get(i)) { |
+ found_difference = true; |
+ break; |
+ } |
+ } |
+ ASSERT(found_difference); |
+ } |
+ } |
+#endif |
if (Hash() != other->Hash()) return false; |
} |
@@ -6061,12 +6075,16 @@ |
// Compute the hash code. |
uint32_t field = 0; |
if (StringShape(this).IsSequentialAscii()) { |
- field = HashSequentialString(SeqAsciiString::cast(this)->GetChars(), len); |
+ field = HashSequentialString(SeqAsciiString::cast(this)->GetChars(), |
+ len, |
+ GetHeap()->StringHashSeed()); |
} else if (StringShape(this).IsSequentialTwoByte()) { |
- field = HashSequentialString(SeqTwoByteString::cast(this)->GetChars(), len); |
+ field = HashSequentialString(SeqTwoByteString::cast(this)->GetChars(), |
+ len, |
+ GetHeap()->StringHashSeed()); |
} else { |
StringInputBuffer buffer(this); |
- field = ComputeHashField(&buffer, len); |
+ field = ComputeHashField(&buffer, len, GetHeap()->StringHashSeed()); |
} |
// Store the hash code in the object. |
@@ -6157,8 +6175,9 @@ |
uint32_t String::ComputeHashField(unibrow::CharacterStream* buffer, |
- int length) { |
- StringHasher hasher(length); |
+ int length, |
+ uint32_t seed) { |
+ StringHasher hasher(length, seed); |
// Very long strings have a trivial hash that doesn't inspect the |
// string contents. |
@@ -9542,8 +9561,8 @@ |
// Utf8SymbolKey carries a vector of chars as key. |
class Utf8SymbolKey : public HashTableKey { |
public: |
- explicit Utf8SymbolKey(Vector<const char> string) |
- : string_(string), hash_field_(0) { } |
+ explicit Utf8SymbolKey(Vector<const char> string, uint32_t seed) |
+ : string_(string), hash_field_(0), seed_(seed) { } |
bool IsMatch(Object* string) { |
return String::cast(string)->IsEqualTo(string_); |
@@ -9554,7 +9573,7 @@ |
unibrow::Utf8InputBuffer<> buffer(string_.start(), |
static_cast<unsigned>(string_.length())); |
chars_ = buffer.Length(); |
- hash_field_ = String::ComputeHashField(&buffer, chars_); |
+ hash_field_ = String::ComputeHashField(&buffer, chars_, seed_); |
uint32_t result = hash_field_ >> String::kHashShift; |
ASSERT(result != 0); // Ensure that the hash value of 0 is never computed. |
return result; |
@@ -9573,17 +9592,18 @@ |
Vector<const char> string_; |
uint32_t hash_field_; |
int chars_; // Caches the number of characters when computing the hash code. |
+ uint32_t seed_; |
}; |
template <typename Char> |
class SequentialSymbolKey : public HashTableKey { |
public: |
- explicit SequentialSymbolKey(Vector<const Char> string) |
- : string_(string), hash_field_(0) { } |
+ explicit SequentialSymbolKey(Vector<const Char> string, uint32_t seed) |
+ : string_(string), hash_field_(0), seed_(seed) { } |
uint32_t Hash() { |
- StringHasher hasher(string_.length()); |
+ StringHasher hasher(string_.length(), seed_); |
// Very long strings have a trivial hash that doesn't inspect the |
// string contents. |
@@ -9619,14 +9639,15 @@ |
Vector<const Char> string_; |
uint32_t hash_field_; |
+ uint32_t seed_; |
}; |
class AsciiSymbolKey : public SequentialSymbolKey<char> { |
public: |
- explicit AsciiSymbolKey(Vector<const char> str) |
- : SequentialSymbolKey<char>(str) { } |
+ AsciiSymbolKey(Vector<const char> str, uint32_t seed) |
+ : SequentialSymbolKey<char>(str, seed) { } |
bool IsMatch(Object* string) { |
return String::cast(string)->IsAsciiEqualTo(string_); |
@@ -9643,13 +9664,14 @@ |
public: |
explicit SubStringAsciiSymbolKey(Handle<SeqAsciiString> string, |
int from, |
- int length) |
- : string_(string), from_(from), length_(length) { } |
+ int length, |
+ uint32_t seed) |
+ : string_(string), from_(from), length_(length), seed_(seed) { } |
uint32_t Hash() { |
ASSERT(length_ >= 0); |
ASSERT(from_ + length_ <= string_->length()); |
- StringHasher hasher(length_); |
+ StringHasher hasher(length_, string_->GetHeap()->StringHashSeed()); |
// Very long strings have a trivial hash that doesn't inspect the |
// string contents. |
@@ -9701,13 +9723,14 @@ |
int from_; |
int length_; |
uint32_t hash_field_; |
+ uint32_t seed_; |
}; |
class TwoByteSymbolKey : public SequentialSymbolKey<uc16> { |
public: |
- explicit TwoByteSymbolKey(Vector<const uc16> str) |
- : SequentialSymbolKey<uc16>(str) { } |
+ explicit TwoByteSymbolKey(Vector<const uc16> str, uint32_t seed) |
+ : SequentialSymbolKey<uc16>(str, seed) { } |
bool IsMatch(Object* string) { |
return String::cast(string)->IsTwoByteEqualTo(string_); |
@@ -10479,10 +10502,12 @@ |
// algorithm. |
class TwoCharHashTableKey : public HashTableKey { |
public: |
- TwoCharHashTableKey(uint32_t c1, uint32_t c2) |
+ TwoCharHashTableKey(uint32_t c1, uint32_t c2, uint32_t seed) |
: c1_(c1), c2_(c2) { |
// Char 1. |
- uint32_t hash = c1 + (c1 << 10); |
+ uint32_t hash = seed; |
+ hash += c1; |
+ hash += hash << 10; |
hash ^= hash >> 6; |
// Char 2. |
hash += c2; |
@@ -10492,9 +10517,9 @@ |
hash += hash << 3; |
hash ^= hash >> 11; |
hash += hash << 15; |
- if (hash == 0) hash = 27; |
+ if ((hash & String::kHashBitMask) == 0) hash = 27; |
#ifdef DEBUG |
- StringHasher hasher(2); |
+ StringHasher hasher(2, seed); |
hasher.AddCharacter(c1); |
hasher.AddCharacter(c2); |
// If this assert fails then we failed to reproduce the two-character |
@@ -10551,7 +10576,7 @@ |
bool SymbolTable::LookupTwoCharsSymbolIfExists(uint32_t c1, |
uint32_t c2, |
String** symbol) { |
- TwoCharHashTableKey key(c1, c2); |
+ TwoCharHashTableKey key(c1, c2, GetHeap()->StringHashSeed()); |
int entry = FindEntry(&key); |
if (entry == kNotFound) { |
return false; |
@@ -10564,15 +10589,16 @@ |
} |
-MaybeObject* SymbolTable::LookupSymbol(Vector<const char> str, Object** s) { |
- Utf8SymbolKey key(str); |
+MaybeObject* SymbolTable::LookupSymbol(Vector<const char> str, |
+ Object** s) { |
+ Utf8SymbolKey key(str, GetHeap()->StringHashSeed()); |
return LookupKey(&key, s); |
} |
MaybeObject* SymbolTable::LookupAsciiSymbol(Vector<const char> str, |
Object** s) { |
- AsciiSymbolKey key(str); |
+ AsciiSymbolKey key(str, GetHeap()->StringHashSeed()); |
return LookupKey(&key, s); |
} |
@@ -10581,14 +10607,14 @@ |
int from, |
int length, |
Object** s) { |
- SubStringAsciiSymbolKey key(str, from, length); |
+ SubStringAsciiSymbolKey key(str, from, length, GetHeap()->StringHashSeed()); |
return LookupKey(&key, s); |
} |
MaybeObject* SymbolTable::LookupTwoByteSymbol(Vector<const uc16> str, |
Object** s) { |
- TwoByteSymbolKey key(str); |
+ TwoByteSymbolKey key(str, GetHeap()->StringHashSeed()); |
return LookupKey(&key, s); |
} |