| Index: src/objects.cc
 | 
| ===================================================================
 | 
| --- src/objects.cc	(revision 10321)
 | 
| +++ src/objects.cc	(working copy)
 | 
| @@ -6682,6 +6682,18 @@
 | 
|    // Fast check: if hash code is computed for both strings
 | 
|    // a fast negative check can be performed.
 | 
|    if (HasHashCode() && other->HasHashCode()) {
 | 
| +#ifdef DEBUG
 | 
| +    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;
 | 
|    }
 | 
|  
 | 
| @@ -6817,12 +6829,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,
 | 
| +                                 GetIsolate()->HasherSeed());
 | 
|    } else if (StringShape(this).IsSequentialTwoByte()) {
 | 
| -    field = HashSequentialString(SeqTwoByteString::cast(this)->GetChars(), len);
 | 
| +    field = HashSequentialString(SeqTwoByteString::cast(this)->GetChars(),
 | 
| +                                 len,
 | 
| +                                 GetIsolate()->HasherSeed());
 | 
|    } else {
 | 
|      StringInputBuffer buffer(this);
 | 
| -    field = ComputeHashField(&buffer, len);
 | 
| +    field = ComputeHashField(&buffer, len, GetIsolate()->HasherSeed());
 | 
|    }
 | 
|  
 | 
|    // Store the hash code in the object.
 | 
| @@ -6913,8 +6929,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.
 | 
| @@ -10456,8 +10473,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_);
 | 
| @@ -10468,7 +10485,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;
 | 
| @@ -10487,17 +10504,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.
 | 
| @@ -10533,14 +10551,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_);
 | 
| @@ -10557,13 +10576,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_->GetIsolate()->HasherSeed());
 | 
|  
 | 
|      // Very long strings have a trivial hash that doesn't inspect the
 | 
|      // string contents.
 | 
| @@ -10615,13 +10635,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_);
 | 
| @@ -11406,10 +11427,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;
 | 
| @@ -11421,7 +11444,7 @@
 | 
|      hash += hash << 15;
 | 
|      if (hash == 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
 | 
| @@ -11478,7 +11501,7 @@
 | 
|  bool SymbolTable::LookupTwoCharsSymbolIfExists(uint32_t c1,
 | 
|                                                 uint32_t c2,
 | 
|                                                 String** symbol) {
 | 
| -  TwoCharHashTableKey key(c1, c2);
 | 
| +  TwoCharHashTableKey key(c1, c2, GetIsolate()->HasherSeed());
 | 
|    int entry = FindEntry(&key);
 | 
|    if (entry == kNotFound) {
 | 
|      return false;
 | 
| @@ -11491,15 +11514,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, GetIsolate()->HasherSeed());
 | 
|    return LookupKey(&key, s);
 | 
|  }
 | 
|  
 | 
|  
 | 
|  MaybeObject* SymbolTable::LookupAsciiSymbol(Vector<const char> str,
 | 
|                                              Object** s) {
 | 
| -  AsciiSymbolKey key(str);
 | 
| +  AsciiSymbolKey key(str, GetIsolate()->HasherSeed());
 | 
|    return LookupKey(&key, s);
 | 
|  }
 | 
|  
 | 
| @@ -11508,14 +11532,14 @@
 | 
|                                                       int from,
 | 
|                                                       int length,
 | 
|                                                       Object** s) {
 | 
| -  SubStringAsciiSymbolKey key(str, from, length);
 | 
| +  SubStringAsciiSymbolKey key(str, from, length, GetIsolate()->HasherSeed());
 | 
|    return LookupKey(&key, s);
 | 
|  }
 | 
|  
 | 
|  
 | 
|  MaybeObject* SymbolTable::LookupTwoByteSymbol(Vector<const uc16> str,
 | 
|                                                Object** s) {
 | 
| -  TwoByteSymbolKey key(str);
 | 
| +  TwoByteSymbolKey key(str, GetIsolate()->HasherSeed());
 | 
|    return LookupKey(&key, s);
 | 
|  }
 | 
|  
 | 
| 
 |