-
-
Save ry/d5fcb57e00e1a32475b4 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/deps/v8/src/arm/code-stubs-arm.cc b/deps/v8/src/arm/code-stubs-arm.cc | |
index e65f6d9..121a4e8 100644 | |
--- a/deps/v8/src/arm/code-stubs-arm.cc | |
+++ b/deps/v8/src/arm/code-stubs-arm.cc | |
@@ -5428,7 +5428,11 @@ void StringHelper::GenerateHashInit(MacroAssembler* masm, | |
Register hash, | |
Register character) { | |
// hash = character + (character << 10); | |
- __ add(hash, character, Operand(character, LSL, 10)); | |
+ __ LoadRoot(hash, Heap::kStringHashSeedRootIndex); | |
+ // Untag smi seed and add the character. | |
+ __ add(hash, character, Operand(hash, LSR, kSmiTagSize)); | |
+ // hash += hash << 10; | |
+ __ add(hash, hash, Operand(hash, LSL, 10)); | |
// hash ^= hash >> 6; | |
__ eor(hash, hash, Operand(hash, ASR, 6)); | |
} | |
diff --git a/deps/v8/src/flag-definitions.h b/deps/v8/src/flag-definitions.h | |
index 7df2b0b..53cc485 100644 | |
--- a/deps/v8/src/flag-definitions.h | |
+++ b/deps/v8/src/flag-definitions.h | |
@@ -319,6 +319,14 @@ DEFINE_bool(trace_exception, false, | |
"print stack trace when throwing exceptions") | |
DEFINE_bool(preallocate_message_memory, false, | |
"preallocate some memory to build stack traces.") | |
+DEFINE_bool(randomize_string_hashes, | |
+ true, | |
+ "randomize string hashes to avoid predictable hash collisions " | |
+ "(with snapshots this option cannot override the baked-in seed)") | |
+DEFINE_int(string_hash_seed, | |
+ 0, | |
+ "Fixed seed to use to string hashing (0 means random)" | |
+ "(with snapshots this option cannot override the baked-in seed)") | |
// v8.cc | |
DEFINE_bool(preemption, false, | |
diff --git a/deps/v8/src/heap.cc b/deps/v8/src/heap.cc | |
index d018593..1fab680 100644 | |
--- a/deps/v8/src/heap.cc | |
+++ b/deps/v8/src/heap.cc | |
@@ -2081,6 +2081,10 @@ bool Heap::CreateInitialObjects() { | |
Oddball::cast(obj)->set_kind(Oddball::kUndefined); | |
ASSERT(!InNewSpace(undefined_value())); | |
+ // The hole has not been created yet, but we want to put something | |
+ // predictable in the gaps in the symbol table, so lets make that Smi zero. | |
+ set_the_hole_value(reinterpret_cast<Oddball*>(Smi::FromInt(0))); | |
+ | |
// Allocate initial symbol table. | |
{ MaybeObject* maybe_obj = SymbolTable::Allocate(kInitialSymbolTableSize); | |
if (!maybe_obj->ToObject(&obj)) return false; | |
@@ -5362,6 +5366,17 @@ bool Heap::Setup(bool create_heap_objects) { | |
if (lo_space_ == NULL) return false; | |
if (!lo_space_->Setup()) return false; | |
+ // Setup the seed that is used to randomize the string hash function. | |
+ ASSERT(string_hash_seed() == 0); | |
+ if (FLAG_randomize_string_hashes) { | |
+ if (FLAG_string_hash_seed == 0) { | |
+ set_string_hash_seed( | |
+ Smi::FromInt(V8::RandomPrivate(isolate()) & 0x3fffffff)); | |
+ } else { | |
+ set_string_hash_seed(Smi::FromInt(FLAG_string_hash_seed)); | |
+ } | |
+ } | |
+ | |
if (create_heap_objects) { | |
// Create initial maps. | |
if (!CreateInitialMaps()) return false; | |
diff --git a/deps/v8/src/heap.h b/deps/v8/src/heap.h | |
index d81ff6c..26d8722 100644 | |
--- a/deps/v8/src/heap.h | |
+++ b/deps/v8/src/heap.h | |
@@ -79,6 +79,7 @@ inline Heap* _inline_get_heap_(); | |
V(FixedArray, single_character_string_cache, SingleCharacterStringCache) \ | |
V(FixedArray, string_split_cache, StringSplitCache) \ | |
V(Object, termination_exception, TerminationException) \ | |
+ V(Smi, string_hash_seed, StringHashSeed) \ | |
V(FixedArray, empty_fixed_array, EmptyFixedArray) \ | |
V(ByteArray, empty_byte_array, EmptyByteArray) \ | |
V(FixedDoubleArray, empty_fixed_double_array, EmptyFixedDoubleArray) \ | |
@@ -841,8 +842,7 @@ class Heap { | |
// Please note this function does not perform a garbage collection. | |
MUST_USE_RESULT MaybeObject* LookupSymbol(Vector<const char> str); | |
MUST_USE_RESULT MaybeObject* LookupAsciiSymbol(Vector<const char> str); | |
- MUST_USE_RESULT MaybeObject* LookupTwoByteSymbol( | |
- Vector<const uc16> str); | |
+ MUST_USE_RESULT MaybeObject* LookupTwoByteSymbol(Vector<const uc16> str); | |
MUST_USE_RESULT MaybeObject* LookupAsciiSymbol(const char* str) { | |
return LookupSymbol(CStrVector(str)); | |
} | |
@@ -1301,6 +1301,12 @@ class Heap { | |
if (global_gc_epilogue_callback_ != NULL) global_gc_epilogue_callback_(); | |
} | |
+ uint32_t StringHashSeed() { | |
+ uint32_t seed = static_cast<uint32_t>(string_hash_seed()->value()); | |
+ ASSERT(FLAG_randomize_string_hashes || seed == 0); | |
+ return seed; | |
+ } | |
+ | |
private: | |
Heap(); | |
diff --git a/deps/v8/src/ia32/code-stubs-ia32.cc b/deps/v8/src/ia32/code-stubs-ia32.cc | |
index 1009aaf..1f9fd52 100644 | |
--- a/deps/v8/src/ia32/code-stubs-ia32.cc | |
+++ b/deps/v8/src/ia32/code-stubs-ia32.cc | |
@@ -5606,10 +5606,24 @@ void StringHelper::GenerateHashInit(MacroAssembler* masm, | |
Register hash, | |
Register character, | |
Register scratch) { | |
- // hash = character + (character << 10); | |
- __ mov(hash, character); | |
- __ shl(hash, 10); | |
- __ add(hash, Operand(character)); | |
+ // hash = (seed + character) + ((seed + character) << 10); | |
+ if (Serializer::enabled()) { | |
+ ExternalReference roots_array_start = | |
+ ExternalReference::roots_array_start(masm->isolate()); | |
+ __ mov(scratch, Immediate(Heap::kStringHashSeedRootIndex)); | |
+ __ mov(scratch, Operand::StaticArray(scratch, | |
+ times_pointer_size, | |
+ roots_array_start)); | |
+ __ add(scratch, character); | |
+ __ mov(hash, scratch); | |
+ __ shl(scratch, 10); | |
+ __ add(hash, scratch); | |
+ } else { | |
+ int32_t seed = masm->isolate()->heap()->StringHashSeed(); | |
+ __ lea(scratch, Operand(character, seed)); | |
+ __ shl(scratch, 10); | |
+ __ lea(hash, Operand(scratch, character, times_1, seed)); | |
+ } | |
// hash ^= hash >> 6; | |
__ mov(scratch, hash); | |
__ sar(scratch, 6); | |
diff --git a/deps/v8/src/mips/code-stubs-mips.cc b/deps/v8/src/mips/code-stubs-mips.cc | |
index 521b8e5..3500ba7 100644 | |
--- a/deps/v8/src/mips/code-stubs-mips.cc | |
+++ b/deps/v8/src/mips/code-stubs-mips.cc | |
@@ -5577,11 +5577,15 @@ void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm, | |
void StringHelper::GenerateHashInit(MacroAssembler* masm, | |
- Register hash, | |
- Register character) { | |
- // hash = character + (character << 10); | |
- __ sll(hash, character, 10); | |
+ Register hash, | |
+ Register character) { | |
+ // hash = seed + character + ((seed + character) << 10); | |
+ __ LoadRoot(hash, Heap::kStringHashSeedRootIndex); | |
+ // Untag smi seed and add the character. | |
+ __ SmiUntag(hash); | |
__ addu(hash, hash, character); | |
+ __ sll(at, hash, 10); | |
+ __ addu(hash, hash, at); | |
// hash ^= hash >> 6; | |
__ sra(at, hash, 6); | |
__ xor_(hash, hash, at); | |
@@ -5589,8 +5593,8 @@ void StringHelper::GenerateHashInit(MacroAssembler* masm, | |
void StringHelper::GenerateHashAddCharacter(MacroAssembler* masm, | |
- Register hash, | |
- Register character) { | |
+ Register hash, | |
+ Register character) { | |
// hash += character; | |
__ addu(hash, hash, character); | |
// hash += hash << 10; | |
diff --git a/deps/v8/src/objects-inl.h b/deps/v8/src/objects-inl.h | |
index 8796865..625f235 100644 | |
--- a/deps/v8/src/objects-inl.h | |
+++ b/deps/v8/src/objects-inl.h | |
@@ -2082,8 +2082,9 @@ int HashTable<Shape, Key>::FindEntry(Isolate* isolate, Key key) { | |
// EnsureCapacity will guarantee the hash table is never full. | |
while (true) { | |
Object* element = KeyAt(entry); | |
- if (element == isolate->heap()->undefined_value()) break; // Empty entry. | |
- if (element != isolate->heap()->null_value() && | |
+ // Empty entry. | |
+ if (element == isolate->heap()->raw_unchecked_undefined_value()) break; | |
+ if (element != isolate->heap()->raw_unchecked_the_hole_value() && | |
Shape::IsMatch(key, element)) return entry; | |
entry = NextProbe(entry, count++, capacity); | |
} | |
@@ -4235,13 +4236,15 @@ uint32_t String::Hash() { | |
} | |
-StringHasher::StringHasher(int length) | |
+StringHasher::StringHasher(int length, uint32_t seed) | |
: length_(length), | |
- raw_running_hash_(0), | |
+ raw_running_hash_(seed), | |
array_index_(0), | |
is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize), | |
is_first_char_(true), | |
- is_valid_(true) { } | |
+ is_valid_(true) { | |
+ ASSERT(FLAG_randomize_string_hashes || raw_running_hash_ == 0); | |
+} | |
bool StringHasher::has_trivial_hash() { | |
@@ -4301,8 +4304,8 @@ uint32_t StringHasher::GetHash() { | |
template <typename schar> | |
-uint32_t HashSequentialString(const schar* chars, int length) { | |
- StringHasher hasher(length); | |
+uint32_t HashSequentialString(const schar* chars, int length, uint32_t seed) { | |
+ StringHasher hasher(length, seed); | |
if (!hasher.has_trivial_hash()) { | |
int i; | |
for (i = 0; hasher.is_array_index() && (i < length); i++) { | |
diff --git a/deps/v8/src/objects.cc b/deps/v8/src/objects.cc | |
index 6085b4e..e35c4ac 100644 | |
--- a/deps/v8/src/objects.cc | |
+++ b/deps/v8/src/objects.cc | |
@@ -5926,6 +5926,20 @@ bool String::SlowEquals(String* other) { | |
// 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 @@ uint32_t String::ComputeAndSetHash() { | |
// 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 StringHasher::GetHashField() { | |
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 @@ class RegExpKey : public HashTableKey { | |
// 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 @@ class Utf8SymbolKey : public HashTableKey { | |
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 @@ class Utf8SymbolKey : public HashTableKey { | |
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 @@ class SequentialSymbolKey : public HashTableKey { | |
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 @@ class SubStringAsciiSymbolKey : public HashTableKey { | |
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 @@ class SubStringAsciiSymbolKey : public HashTableKey { | |
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 @@ MaybeObject* SymbolTable::LookupString(String* string, Object** s) { | |
// 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; | |
@@ -10494,7 +10519,7 @@ class TwoCharHashTableKey : public HashTableKey { | |
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 | |
@@ -10551,7 +10576,7 @@ bool SymbolTable::LookupSymbolIfExists(String* string, String** symbol) { | |
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 @@ bool SymbolTable::LookupTwoCharsSymbolIfExists(uint32_t c1, | |
} | |
-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 @@ MaybeObject* SymbolTable::LookupSubStringAsciiSymbol(Handle<SeqAsciiString> str, | |
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); | |
} | |
diff --git a/deps/v8/src/objects.h b/deps/v8/src/objects.h | |
index 48a76d3..2049160 100644 | |
--- a/deps/v8/src/objects.h | |
+++ b/deps/v8/src/objects.h | |
@@ -5734,7 +5734,7 @@ enum RobustnessFlag {ROBUST_STRING_TRAVERSAL, FAST_STRING_TRAVERSAL}; | |
class StringHasher { | |
public: | |
- explicit inline StringHasher(int length); | |
+ explicit inline StringHasher(int length, uint32_t seed); | |
// Returns true if the hash of this string can be computed without | |
// looking at the contents. | |
@@ -5785,7 +5785,9 @@ class StringHasher { | |
// Calculates string hash. | |
template <typename schar> | |
-inline uint32_t HashSequentialString(const schar* chars, int length); | |
+inline uint32_t HashSequentialString(const schar* chars, | |
+ int length, | |
+ uint32_t seed); | |
// The characteristics of a string are stored in its map. Retrieving these | |
@@ -6007,7 +6009,8 @@ class String: public HeapObject { | |
inline uint32_t Hash(); | |
static uint32_t ComputeHashField(unibrow::CharacterStream* buffer, | |
- int length); | |
+ int length, | |
+ uint32_t seed); | |
static bool ComputeArrayIndex(unibrow::CharacterStream* buffer, | |
uint32_t* index, | |
diff --git a/deps/v8/src/profile-generator.cc b/deps/v8/src/profile-generator.cc | |
index adf55ad..93a7b80 100644 | |
--- a/deps/v8/src/profile-generator.cc | |
+++ b/deps/v8/src/profile-generator.cc | |
@@ -110,7 +110,8 @@ const char* StringsStorage::GetCopy(const char* src) { | |
Vector<char> dst = Vector<char>::New(len + 1); | |
OS::StrNCpy(dst, src, len); | |
dst[len] = '\0'; | |
- uint32_t hash = HashSequentialString(dst.start(), len); | |
+ uint32_t hash = | |
+ HashSequentialString(dst.start(), len, HEAP->StringHashSeed()); | |
return AddOrDisposeString(dst.start(), hash); | |
} | |
@@ -143,16 +144,20 @@ const char* StringsStorage::GetVFormatted(const char* format, va_list args) { | |
DeleteArray(str.start()); | |
return format; | |
} | |
- uint32_t hash = HashSequentialString(str.start(), len); | |
+ uint32_t hash = HashSequentialString( | |
+ str.start(), len, HEAP->StringHashSeed()); | |
return AddOrDisposeString(str.start(), hash); | |
} | |
const char* StringsStorage::GetName(String* name) { | |
if (name->IsString()) { | |
- return AddOrDisposeString( | |
- name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL).Detach(), | |
- name->Hash()); | |
+ int length = name->length(); | |
+ SmartArrayPointer<char> data = | |
+ name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL); | |
+ uint32_t hash = | |
+ HashSequentialString(*data, length, name->GetHeap()->StringHashSeed()); | |
+ return AddOrDisposeString(data.Detach(), hash); | |
} | |
return ""; | |
} | |
@@ -1462,7 +1467,9 @@ void HeapObjectsMap::RemoveDeadEntries() { | |
uint64_t HeapObjectsMap::GenerateId(v8::RetainedObjectInfo* info) { | |
uint64_t id = static_cast<uint64_t>(info->GetHash()); | |
const char* label = info->GetLabel(); | |
- id ^= HashSequentialString(label, static_cast<int>(strlen(label))); | |
+ id ^= HashSequentialString(label, | |
+ static_cast<int>(strlen(label)), | |
+ HEAP->StringHashSeed()); | |
intptr_t element_count = info->GetElementCount(); | |
if (element_count != -1) | |
id ^= ComputeIntegerHash(static_cast<uint32_t>(element_count)); | |
diff --git a/deps/v8/src/x64/code-stubs-x64.cc b/deps/v8/src/x64/code-stubs-x64.cc | |
index df4438b..8f8acbc 100644 | |
--- a/deps/v8/src/x64/code-stubs-x64.cc | |
+++ b/deps/v8/src/x64/code-stubs-x64.cc | |
@@ -4609,10 +4609,13 @@ void StringHelper::GenerateHashInit(MacroAssembler* masm, | |
Register hash, | |
Register character, | |
Register scratch) { | |
- // hash = character + (character << 10); | |
- __ movl(hash, character); | |
- __ shll(hash, Immediate(10)); | |
- __ addl(hash, character); | |
+ // hash = (seed + character) + ((seed + character) << 10); | |
+ __ LoadRoot(scratch, Heap::kStringHashSeedRootIndex); | |
+ __ SmiToInteger32(scratch, scratch); | |
+ __ addl(scratch, character); | |
+ __ movl(hash, scratch); | |
+ __ shll(scratch, Immediate(10)); | |
+ __ addl(hash, scratch); | |
// hash ^= hash >> 6; | |
__ movl(scratch, hash); | |
__ sarl(scratch, Immediate(6)); | |
diff --git a/deps/v8/test/mjsunit/debug-evaluate-locals-optimized-double.js b/deps/v8/test/mjsunit/debug-evaluate-locals-optimized-double.js | |
index 9ed1dbb..8447df5 100644 | |
--- a/deps/v8/test/mjsunit/debug-evaluate-locals-optimized-double.js | |
+++ b/deps/v8/test/mjsunit/debug-evaluate-locals-optimized-double.js | |
@@ -50,10 +50,12 @@ function listener(event, exec_state, event_data, data) { | |
var expected_y = (i + 1) * 2 + 2 + ((i + 1) * 2 + 2) / 100; | |
// All frames except the bottom one has normal variables a and b. | |
- assertEquals('a', frame.localName(0)); | |
- assertEquals('b', frame.localName(1)); | |
- assertEquals(expected_a, frame.localValue(0).value()); | |
- assertEquals(expected_b, frame.localValue(1).value()); | |
+ var a = ('a' === frame.localName(0)) ? 0 : 1; | |
+ var b = 1 - a; | |
+ assertEquals('a', frame.localName(a)); | |
+ assertEquals('b', frame.localName(b)); | |
+ assertEquals(expected_a, frame.localValue(a).value()); | |
+ assertEquals(expected_b, frame.localValue(b).value()); | |
// All frames except the bottom one has arguments variables x and y. | |
assertEquals('x', frame.argumentName(0)); | |
diff --git a/deps/v8/test/mjsunit/debug-evaluate-locals-optimized.js b/deps/v8/test/mjsunit/debug-evaluate-locals-optimized.js | |
index 683c139..c3cd5eb 100644 | |
--- a/deps/v8/test/mjsunit/debug-evaluate-locals-optimized.js | |
+++ b/deps/v8/test/mjsunit/debug-evaluate-locals-optimized.js | |
@@ -50,10 +50,12 @@ function listener(event, exec_state, event_data, data) { | |
var expected_y = (i + 1) * 2 + 2; | |
// All frames except the bottom one has normal variables a and b. | |
- assertEquals('a', frame.localName(0)); | |
- assertEquals('b', frame.localName(1)); | |
- assertEquals(expected_a, frame.localValue(0).value()); | |
- assertEquals(expected_b, frame.localValue(1).value()); | |
+ var a = ('a' === frame.localName(0)) ? 0 : 1; | |
+ var b = 1 - a; | |
+ assertEquals('a', frame.localName(a)); | |
+ assertEquals('b', frame.localName(b)); | |
+ assertEquals(expected_a, frame.localValue(a).value()); | |
+ assertEquals(expected_b, frame.localValue(b).value()); | |
// All frames except the bottom one has arguments variables x and y. | |
assertEquals('x', frame.argumentName(0)); | |
@@ -119,7 +121,7 @@ function listener(event, exec_state, event_data, data) { | |
listenerComplete = true; | |
} | |
} catch (e) { | |
- exception = e | |
+ exception = e.stack; | |
}; | |
}; | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment