Fixing generated hash function on all platforms.

BUG=v8:1808
TEST=cctest/test-hashing.cc

Review URL: http://codereview.chromium.org/8512004

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9956 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
yangguo@chromium.org 2011-11-10 14:26:57 +00:00
parent 6bd8d27a65
commit 07ee3e6e5c
9 changed files with 329 additions and 155 deletions

View File

@ -5246,70 +5246,6 @@ void StringCharAtGenerator::GenerateSlow(
}
class StringHelper : public AllStatic {
public:
// Generate code for copying characters using a simple loop. This should only
// be used in places where the number of characters is small and the
// additional setup and checking in GenerateCopyCharactersLong adds too much
// overhead. Copying of overlapping regions is not supported.
// Dest register ends at the position after the last character written.
static void GenerateCopyCharacters(MacroAssembler* masm,
Register dest,
Register src,
Register count,
Register scratch,
bool ascii);
// Generate code for copying a large number of characters. This function
// is allowed to spend extra time setting up conditions to make copying
// faster. Copying of overlapping regions is not supported.
// Dest register ends at the position after the last character written.
static void GenerateCopyCharactersLong(MacroAssembler* masm,
Register dest,
Register src,
Register count,
Register scratch1,
Register scratch2,
Register scratch3,
Register scratch4,
Register scratch5,
int flags);
// Probe the symbol table for a two character string. If the string is
// not found by probing a jump to the label not_found is performed. This jump
// does not guarantee that the string is not in the symbol table. If the
// string is found the code falls through with the string in register r0.
// Contents of both c1 and c2 registers are modified. At the exit c1 is
// guaranteed to contain halfword with low and high bytes equal to
// initial contents of c1 and c2 respectively.
static void GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
Register c1,
Register c2,
Register scratch1,
Register scratch2,
Register scratch3,
Register scratch4,
Register scratch5,
Label* not_found);
// Generate string hash.
static void GenerateHashInit(MacroAssembler* masm,
Register hash,
Register character);
static void GenerateHashAddCharacter(MacroAssembler* masm,
Register hash,
Register character);
static void GenerateHashGetHash(MacroAssembler* masm,
Register hash);
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(StringHelper);
};
void StringHelper::GenerateCopyCharacters(MacroAssembler* masm,
Register dest,
Register src,
@ -5562,9 +5498,8 @@ void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
static const int kProbes = 4;
Label found_in_symbol_table;
Label next_probe[kProbes];
Register candidate = scratch5; // Scratch register contains candidate.
for (int i = 0; i < kProbes; i++) {
Register candidate = scratch5; // Scratch register contains candidate.
// Calculate entry in symbol table.
if (i > 0) {
__ add(candidate, hash, Operand(SymbolTable::GetProbeOffset(i)));
@ -5589,11 +5524,11 @@ void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
__ cmp(undefined, candidate);
__ b(eq, not_found);
// Must be null (deleted entry).
// Must be the hole (deleted entry).
if (FLAG_debug_code) {
__ LoadRoot(ip, Heap::kNullValueRootIndex);
__ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
__ cmp(ip, candidate);
__ Assert(eq, "oddball in symbol table is not undefined or null");
__ Assert(eq, "oddball in symbol table is not undefined or the hole");
}
__ jmp(&next_probe[i]);
@ -5621,7 +5556,7 @@ void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
__ jmp(not_found);
// Scratch register contains result when we fall through to here.
Register result = scratch;
Register result = candidate;
__ bind(&found_in_symbol_table);
__ Move(r0, result);
}
@ -5633,7 +5568,7 @@ void StringHelper::GenerateHashInit(MacroAssembler* masm,
// hash = character + (character << 10);
__ add(hash, character, Operand(character, LSL, 10));
// hash ^= hash >> 6;
__ eor(hash, hash, Operand(hash, ASR, 6));
__ eor(hash, hash, Operand(hash, LSR, 6));
}
@ -5645,7 +5580,7 @@ void StringHelper::GenerateHashAddCharacter(MacroAssembler* masm,
// hash += hash << 10;
__ add(hash, hash, Operand(hash, LSL, 10));
// hash ^= hash >> 6;
__ eor(hash, hash, Operand(hash, ASR, 6));
__ eor(hash, hash, Operand(hash, LSR, 6));
}
@ -5654,12 +5589,15 @@ void StringHelper::GenerateHashGetHash(MacroAssembler* masm,
// hash += hash << 3;
__ add(hash, hash, Operand(hash, LSL, 3));
// hash ^= hash >> 11;
__ eor(hash, hash, Operand(hash, ASR, 11));
__ eor(hash, hash, Operand(hash, LSR, 11));
// hash += hash << 15;
__ add(hash, hash, Operand(hash, LSL, 15), SetCC);
uint32_t kHashShiftCutOffMask = (1 << (32 - String::kHashShift)) - 1;
__ and_(hash, hash, Operand(kHashShiftCutOffMask));
// if (hash == 0) hash = 27;
__ mov(hash, Operand(27), LeaveCC, ne);
__ mov(hash, Operand(27), LeaveCC, eq);
}

View File

@ -244,6 +244,70 @@ class BinaryOpStub: public CodeStub {
};
class StringHelper : public AllStatic {
public:
// Generate code for copying characters using a simple loop. This should only
// be used in places where the number of characters is small and the
// additional setup and checking in GenerateCopyCharactersLong adds too much
// overhead. Copying of overlapping regions is not supported.
// Dest register ends at the position after the last character written.
static void GenerateCopyCharacters(MacroAssembler* masm,
Register dest,
Register src,
Register count,
Register scratch,
bool ascii);
// Generate code for copying a large number of characters. This function
// is allowed to spend extra time setting up conditions to make copying
// faster. Copying of overlapping regions is not supported.
// Dest register ends at the position after the last character written.
static void GenerateCopyCharactersLong(MacroAssembler* masm,
Register dest,
Register src,
Register count,
Register scratch1,
Register scratch2,
Register scratch3,
Register scratch4,
Register scratch5,
int flags);
// Probe the symbol table for a two character string. If the string is
// not found by probing a jump to the label not_found is performed. This jump
// does not guarantee that the string is not in the symbol table. If the
// string is found the code falls through with the string in register r0.
// Contents of both c1 and c2 registers are modified. At the exit c1 is
// guaranteed to contain halfword with low and high bytes equal to
// initial contents of c1 and c2 respectively.
static void GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
Register c1,
Register c2,
Register scratch1,
Register scratch2,
Register scratch3,
Register scratch4,
Register scratch5,
Label* not_found);
// Generate string hash.
static void GenerateHashInit(MacroAssembler* masm,
Register hash,
Register character);
static void GenerateHashAddCharacter(MacroAssembler* masm,
Register hash,
Register character);
static void GenerateHashGetHash(MacroAssembler* masm,
Register hash);
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(StringHelper);
};
// Flag that indicates how to generate code for the stub StringAddStub.
enum StringAddFlags {
NO_STRING_ADD_FLAGS = 0,

View File

@ -5772,6 +5772,7 @@ void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
static const int kProbes = 4;
Label found_in_symbol_table;
Label next_probe[kProbes], next_probe_pop_mask[kProbes];
Register candidate = scratch; // Scratch register contains candidate.
for (int i = 0; i < kProbes; i++) {
// Calculate entry in symbol table.
__ mov(scratch, hash);
@ -5781,7 +5782,6 @@ void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
__ and_(scratch, mask);
// Load the entry from the symbol table.
Register candidate = scratch; // Scratch register contains candidate.
STATIC_ASSERT(SymbolTable::kEntrySize == 1);
__ mov(candidate,
FieldOperand(symbol_table,
@ -5793,7 +5793,7 @@ void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
Factory* factory = masm->isolate()->factory();
__ cmp(candidate, factory->undefined_value());
__ j(equal, not_found);
__ cmp(candidate, factory->null_value());
__ cmp(candidate, factory->the_hole_value());
__ j(equal, &next_probe[i]);
// If length is not 2 the string is not a candidate.
@ -5826,7 +5826,7 @@ void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
__ jmp(not_found);
// Scratch register contains result when we fall through to here.
Register result = scratch;
Register result = candidate;
__ bind(&found_in_symbol_table);
__ pop(mask); // Pop saved mask from the stack.
if (!result.is(eax)) {
@ -5845,7 +5845,7 @@ void StringHelper::GenerateHashInit(MacroAssembler* masm,
__ add(hash, character);
// hash ^= hash >> 6;
__ mov(scratch, hash);
__ sar(scratch, 6);
__ shr(scratch, 6);
__ xor_(hash, scratch);
}
@ -5862,7 +5862,7 @@ void StringHelper::GenerateHashAddCharacter(MacroAssembler* masm,
__ add(hash, scratch);
// hash ^= hash >> 6;
__ mov(scratch, hash);
__ sar(scratch, 6);
__ shr(scratch, 6);
__ xor_(hash, scratch);
}
@ -5876,13 +5876,16 @@ void StringHelper::GenerateHashGetHash(MacroAssembler* masm,
__ add(hash, scratch);
// hash ^= hash >> 11;
__ mov(scratch, hash);
__ sar(scratch, 11);
__ shr(scratch, 11);
__ xor_(hash, scratch);
// hash += hash << 15;
__ mov(scratch, hash);
__ shl(scratch, 15);
__ add(hash, scratch);
uint32_t kHashShiftCutOffMask = (1 << (32 - String::kHashShift)) - 1;
__ and_(hash, kHashShiftCutOffMask);
// if (hash == 0) hash = 27;
Label hash_not_zero;
__ test(hash, hash);

View File

@ -2145,8 +2145,6 @@ void MacroAssembler::Ret(int bytes_dropped, Register scratch) {
}
void MacroAssembler::Drop(int stack_elements) {
if (stack_elements > 0) {
add(esp, Immediate(stack_elements * kPointerSize));

View File

@ -5462,70 +5462,6 @@ void StringCharAtGenerator::GenerateSlow(
}
class StringHelper : public AllStatic {
public:
// Generate code for copying characters using a simple loop. This should only
// be used in places where the number of characters is small and the
// additional setup and checking in GenerateCopyCharactersLong adds too much
// overhead. Copying of overlapping regions is not supported.
// Dest register ends at the position after the last character written.
static void GenerateCopyCharacters(MacroAssembler* masm,
Register dest,
Register src,
Register count,
Register scratch,
bool ascii);
// Generate code for copying a large number of characters. This function
// is allowed to spend extra time setting up conditions to make copying
// faster. Copying of overlapping regions is not supported.
// Dest register ends at the position after the last character written.
static void GenerateCopyCharactersLong(MacroAssembler* masm,
Register dest,
Register src,
Register count,
Register scratch1,
Register scratch2,
Register scratch3,
Register scratch4,
Register scratch5,
int flags);
// Probe the symbol table for a two character string. If the string is
// not found by probing a jump to the label not_found is performed. This jump
// does not guarantee that the string is not in the symbol table. If the
// string is found the code falls through with the string in register r0.
// Contents of both c1 and c2 registers are modified. At the exit c1 is
// guaranteed to contain halfword with low and high bytes equal to
// initial contents of c1 and c2 respectively.
static void GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
Register c1,
Register c2,
Register scratch1,
Register scratch2,
Register scratch3,
Register scratch4,
Register scratch5,
Label* not_found);
// Generate string hash.
static void GenerateHashInit(MacroAssembler* masm,
Register hash,
Register character);
static void GenerateHashAddCharacter(MacroAssembler* masm,
Register hash,
Register character);
static void GenerateHashGetHash(MacroAssembler* masm,
Register hash);
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(StringHelper);
};
void StringHelper::GenerateCopyCharacters(MacroAssembler* masm,
Register dest,
Register src,
@ -5819,7 +5755,7 @@ void StringHelper::GenerateHashInit(MacroAssembler* masm,
__ sll(hash, character, 10);
__ addu(hash, hash, character);
// hash ^= hash >> 6;
__ sra(at, hash, 6);
__ srl(at, hash, 6);
__ xor_(hash, hash, at);
}
@ -5833,7 +5769,7 @@ void StringHelper::GenerateHashAddCharacter(MacroAssembler* masm,
__ sll(at, hash, 10);
__ addu(hash, hash, at);
// hash ^= hash >> 6;
__ sra(at, hash, 6);
__ srl(at, hash, 6);
__ xor_(hash, hash, at);
}
@ -5844,12 +5780,16 @@ void StringHelper::GenerateHashGetHash(MacroAssembler* masm,
__ sll(at, hash, 3);
__ addu(hash, hash, at);
// hash ^= hash >> 11;
__ sra(at, hash, 11);
__ srl(at, hash, 11);
__ xor_(hash, hash, at);
// hash += hash << 15;
__ sll(at, hash, 15);
__ addu(hash, hash, at);
uint32_t kHashShiftCutOffMask = (1 << (32 - String::kHashShift)) - 1;
__ li(at, Operand(kHashShiftCutOffMask));
__ and_(hash, hash, at);
// if (hash == 0) hash = 27;
__ ori(at, zero_reg, 27);
__ movz(hash, at, hash);

View File

@ -245,6 +245,70 @@ class BinaryOpStub: public CodeStub {
};
class StringHelper : public AllStatic {
public:
// Generate code for copying characters using a simple loop. This should only
// be used in places where the number of characters is small and the
// additional setup and checking in GenerateCopyCharactersLong adds too much
// overhead. Copying of overlapping regions is not supported.
// Dest register ends at the position after the last character written.
static void GenerateCopyCharacters(MacroAssembler* masm,
Register dest,
Register src,
Register count,
Register scratch,
bool ascii);
// Generate code for copying a large number of characters. This function
// is allowed to spend extra time setting up conditions to make copying
// faster. Copying of overlapping regions is not supported.
// Dest register ends at the position after the last character written.
static void GenerateCopyCharactersLong(MacroAssembler* masm,
Register dest,
Register src,
Register count,
Register scratch1,
Register scratch2,
Register scratch3,
Register scratch4,
Register scratch5,
int flags);
// Probe the symbol table for a two character string. If the string is
// not found by probing a jump to the label not_found is performed. This jump
// does not guarantee that the string is not in the symbol table. If the
// string is found the code falls through with the string in register r0.
// Contents of both c1 and c2 registers are modified. At the exit c1 is
// guaranteed to contain halfword with low and high bytes equal to
// initial contents of c1 and c2 respectively.
static void GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
Register c1,
Register c2,
Register scratch1,
Register scratch2,
Register scratch3,
Register scratch4,
Register scratch5,
Label* not_found);
// Generate string hash.
static void GenerateHashInit(MacroAssembler* masm,
Register hash,
Register character);
static void GenerateHashAddCharacter(MacroAssembler* masm,
Register hash,
Register character);
static void GenerateHashGetHash(MacroAssembler* masm,
Register hash);
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(StringHelper);
};
// Flag that indicates how to generate code for the stub StringAddStub.
enum StringAddFlags {
NO_STRING_ADD_FLAGS = 0,

View File

@ -4705,6 +4705,7 @@ void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
static const int kProbes = 4;
Label found_in_symbol_table;
Label next_probe[kProbes];
Register candidate = scratch; // Scratch register contains candidate.
for (int i = 0; i < kProbes; i++) {
// Calculate entry in symbol table.
__ movl(scratch, hash);
@ -4714,7 +4715,6 @@ void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
__ andl(scratch, mask);
// Load the entry from the symbol table.
Register candidate = scratch; // Scratch register contains candidate.
STATIC_ASSERT(SymbolTable::kEntrySize == 1);
__ movq(candidate,
FieldOperand(symbol_table,
@ -4729,7 +4729,12 @@ void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
__ CompareRoot(candidate, Heap::kUndefinedValueRootIndex);
__ j(equal, not_found);
// Must be null (deleted entry).
// Must be the hole (deleted entry).
if (FLAG_debug_code) {
__ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
__ cmpq(kScratchRegister, candidate);
__ Assert(equal, "oddball in symbol table is not undefined or the hole");
}
__ jmp(&next_probe[i]);
__ bind(&is_string);
@ -4760,7 +4765,7 @@ void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
__ jmp(not_found);
// Scratch register contains result when we fall through to here.
Register result = scratch;
Register result = candidate;
__ bind(&found_in_symbol_table);
if (!result.is(rax)) {
__ movq(rax, result);
@ -4778,7 +4783,7 @@ void StringHelper::GenerateHashInit(MacroAssembler* masm,
__ addl(hash, character);
// hash ^= hash >> 6;
__ movl(scratch, hash);
__ sarl(scratch, Immediate(6));
__ shrl(scratch, Immediate(6));
__ xorl(hash, scratch);
}
@ -4795,7 +4800,7 @@ void StringHelper::GenerateHashAddCharacter(MacroAssembler* masm,
__ addl(hash, scratch);
// hash ^= hash >> 6;
__ movl(scratch, hash);
__ sarl(scratch, Immediate(6));
__ shrl(scratch, Immediate(6));
__ xorl(hash, scratch);
}
@ -4807,13 +4812,16 @@ void StringHelper::GenerateHashGetHash(MacroAssembler* masm,
__ leal(hash, Operand(hash, hash, times_8, 0));
// hash ^= hash >> 11;
__ movl(scratch, hash);
__ sarl(scratch, Immediate(11));
__ shrl(scratch, Immediate(11));
__ xorl(hash, scratch);
// hash += hash << 15;
__ movl(scratch, hash);
__ shll(scratch, Immediate(15));
__ addl(hash, scratch);
uint32_t kHashShiftCutOffMask = (1 << (32 - String::kHashShift)) - 1;
__ andl(hash, Immediate(kHashShiftCutOffMask));
// if (hash == 0) hash = 27;
Label hash_not_zero;
__ j(not_zero, &hash_not_zero);

View File

@ -68,6 +68,7 @@
'test-fixed-dtoa.cc',
'test-flags.cc',
'test-func-name-inference.cc',
'test-hashing.cc',
'test-hashmap.cc',
'test-heap.cc',
'test-heap-profiler.cc',

158
test/cctest/test-hashing.cc Normal file
View File

@ -0,0 +1,158 @@
// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <stdlib.h>
#include "v8.h"
#include "factory.h"
#include "macro-assembler.h"
#include "cctest.h"
#include "code-stubs.h"
#include "objects.h"
#ifdef USE_SIMULATOR
#include "simulator.h"
#endif
using namespace v8::internal;
typedef uint32_t (*HASH_FUNCTION)();
static v8::Persistent<v8::Context> env;
#define __ assm->
void generate(MacroAssembler* assm, i::Vector<const char> string) {
#ifdef V8_TARGET_ARCH_IA32
__ mov(eax, Immediate(0));
if (string.length() > 0) {
__ mov(ebx, Immediate(string.at(0)));
StringHelper::GenerateHashInit(assm, eax, ebx, ecx);
}
for (int i = 1; i < string.length(); i++) {
__ mov(ebx, Immediate(string.at(i)));
StringHelper::GenerateHashAddCharacter(assm, eax, ebx, ecx);
}
StringHelper::GenerateHashGetHash(assm, eax, ecx);
__ Ret();
#elif V8_TARGET_ARCH_X64
__ movq(rax, Immediate(0));
if (string.length() > 0) {
__ movq(rbx, Immediate(string.at(0)));
StringHelper::GenerateHashInit(assm, rax, rbx, rcx);
}
for (int i = 1; i < string.length(); i++) {
__ movq(rbx, Immediate(string.at(i)));
StringHelper::GenerateHashAddCharacter(assm, rax, rbx, rcx);
}
StringHelper::GenerateHashGetHash(assm, rax, rcx);
__ Ret();
#elif V8_TARGET_ARCH_ARM
__ mov(r0, Operand(0));
if (string.length() > 0) {
__ mov(r1, Operand(string.at(0)));
StringHelper::GenerateHashInit(assm, r0, r1);
}
for (int i = 1; i < string.length(); i++) {
__ mov(r1, Operand(string.at(i)));
StringHelper::GenerateHashAddCharacter(assm, r0, r1);
}
StringHelper::GenerateHashGetHash(assm, r0);
__ mov(pc, Operand(lr));
#elif V8_TARGET_ARCH_MIPS
__ li(v0, Operand(0));
if (string.length() > 0) {
__ li(v1, Operand(string.at(0)));
StringHelper::GenerateHashInit(assm, v0, v1);
}
for (int i = 1; i < string.length(); i++) {
__ li(v1, Operand(string.at(i)));
StringHelper::GenerateHashAddCharacter(assm, v0, v1);
}
StringHelper::GenerateHashGetHash(assm, v0);
__ jr(ra);
#endif
}
void check(i::Vector<const char> string) {
v8::HandleScope scope;
v8::internal::byte buffer[2048];
MacroAssembler assm(Isolate::Current(), buffer, sizeof buffer);
generate(&assm, string);
CodeDesc desc;
assm.GetCode(&desc);
Code* code = Code::cast(HEAP->CreateCode(
desc,
Code::ComputeFlags(Code::STUB),
Handle<Object>(HEAP->undefined_value()))->ToObjectChecked());
CHECK(code->IsCode());
HASH_FUNCTION hash = FUNCTION_CAST<HASH_FUNCTION>(Code::cast(code)->entry());
Handle<String> v8_string = FACTORY->NewStringFromAscii(string);
v8_string->set_hash_field(String::kEmptyHashField);
#ifdef USE_SIMULATOR
uint32_t codegen_hash =
reinterpret_cast<uint32_t>(CALL_GENERATED_CODE(hash, 0, 0, 0, 0, 0));
#else
uint32_t codegen_hash = hash();
#endif
uint32_t runtime_hash = v8_string->Hash();
CHECK(runtime_hash == codegen_hash);
}
void check_twochars(char a, char b) {
char ab[2] = {a, b};
check(i::Vector<const char>(ab, 2));
}
TEST(StringHash) {
if (env.IsEmpty()) env = v8::Context::New();
for (int a = 0; a < String::kMaxAsciiCharCode; a++) {
// Numbers are hashed differently.
if (a >= '0' && a <= '9') continue;
for (int b = 0; b < String::kMaxAsciiCharCode; b++) {
if (b >= '0' && b <= '9') continue;
check_twochars(static_cast<char>(a), static_cast<char>(b));
}
}
check(i::Vector<const char>("", 0));
check(i::Vector<const char>("*", 1));
check(i::Vector<const char>(".zZ", 3));
check(i::Vector<const char>("muc", 3));
check(i::Vector<const char>("(>'_')>", 7));
check(i::Vector<const char>("-=[ vee eight ftw ]=-", 21));
}
#undef __