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:
parent
6bd8d27a65
commit
07ee3e6e5c
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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
158
test/cctest/test-hashing.cc
Normal 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 __
|
Loading…
Reference in New Issue
Block a user