Skip to content

Instantly share code, notes, and snippets.

@ry
Created January 4, 2012 23:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ry/d5fcb57e00e1a32475b4 to your computer and use it in GitHub Desktop.
Save ry/d5fcb57e00e1a32475b4 to your computer and use it in GitHub Desktop.
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