Revision: 9956
Author:   [email protected]
Date:     Thu Nov 10 06:26:57 2011
Log:      Fixing generated hash function on all platforms.

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

Review URL: http://codereview.chromium.org/8512004
http://code.google.com/p/v8/source/detail?r=9956

Added:
 /branches/bleeding_edge/test/cctest/test-hashing.cc
Modified:
 /branches/bleeding_edge/src/arm/code-stubs-arm.cc
 /branches/bleeding_edge/src/arm/code-stubs-arm.h
 /branches/bleeding_edge/src/ia32/code-stubs-ia32.cc
 /branches/bleeding_edge/src/ia32/macro-assembler-ia32.cc
 /branches/bleeding_edge/src/mips/code-stubs-mips.cc
 /branches/bleeding_edge/src/mips/code-stubs-mips.h
 /branches/bleeding_edge/src/x64/code-stubs-x64.cc
 /branches/bleeding_edge/test/cctest/cctest.gyp

=======================================
--- /dev/null
+++ /branches/bleeding_edge/test/cctest/test-hashing.cc Thu Nov 10 06:26:57 2011
@@ -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 __
=======================================
--- /branches/bleeding_edge/src/arm/code-stubs-arm.cc Thu Nov 10 00:07:39 2011 +++ /branches/bleeding_edge/src/arm/code-stubs-arm.cc Thu Nov 10 06:26:57 2011
@@ -5246,70 +5246,6 @@
 }


-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 @@
   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 @@

     __ 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 @@
   __ 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 @@
   // 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 @@
   // 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 @@
   // 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);
 }


=======================================
--- /branches/bleeding_edge/src/arm/code-stubs-arm.h Wed Nov 9 07:44:13 2011 +++ /branches/bleeding_edge/src/arm/code-stubs-arm.h Thu Nov 10 06:26:57 2011
@@ -244,6 +244,70 @@
 };


+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,
=======================================
--- /branches/bleeding_edge/src/ia32/code-stubs-ia32.cc Thu Nov 10 00:07:39 2011 +++ /branches/bleeding_edge/src/ia32/code-stubs-ia32.cc Thu Nov 10 06:26:57 2011
@@ -5772,6 +5772,7 @@
   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 @@
     __ 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 @@
     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 @@
   __ 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 @@
   __ add(hash, character);
   // hash ^= hash >> 6;
   __ mov(scratch, hash);
-  __ sar(scratch, 6);
+  __ shr(scratch, 6);
   __ xor_(hash, scratch);
 }

@@ -5862,7 +5862,7 @@
   __ add(hash, scratch);
   // hash ^= hash >> 6;
   __ mov(scratch, hash);
-  __ sar(scratch, 6);
+  __ shr(scratch, 6);
   __ xor_(hash, scratch);
 }

@@ -5876,13 +5876,16 @@
   __ 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);
=======================================
--- /branches/bleeding_edge/src/ia32/macro-assembler-ia32.cc Tue Nov 8 03:09:00 2011 +++ /branches/bleeding_edge/src/ia32/macro-assembler-ia32.cc Thu Nov 10 06:26:57 2011
@@ -2143,8 +2143,6 @@
     ret(0);
   }
 }
-
-


 void MacroAssembler::Drop(int stack_elements) {
=======================================
--- /branches/bleeding_edge/src/mips/code-stubs-mips.cc Thu Nov 10 06:13:32 2011 +++ /branches/bleeding_edge/src/mips/code-stubs-mips.cc Thu Nov 10 06:26:57 2011
@@ -5462,70 +5462,6 @@
 }


-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 @@
   __ 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 @@
   __ 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 @@
   __ 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);
=======================================
--- /branches/bleeding_edge/src/mips/code-stubs-mips.h Wed Nov 9 07:44:13 2011 +++ /branches/bleeding_edge/src/mips/code-stubs-mips.h Thu Nov 10 06:26:57 2011
@@ -245,6 +245,70 @@
 };


+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,
=======================================
--- /branches/bleeding_edge/src/x64/code-stubs-x64.cc Thu Nov 10 00:07:39 2011 +++ /branches/bleeding_edge/src/x64/code-stubs-x64.cc Thu Nov 10 06:26:57 2011
@@ -4705,6 +4705,7 @@
   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 @@
     __ 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 @@

     __ 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 @@
   __ 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 @@
   __ addl(hash, character);
   // hash ^= hash >> 6;
   __ movl(scratch, hash);
-  __ sarl(scratch, Immediate(6));
+  __ shrl(scratch, Immediate(6));
   __ xorl(hash, scratch);
 }

@@ -4795,7 +4800,7 @@
   __ addl(hash, scratch);
   // hash ^= hash >> 6;
   __ movl(scratch, hash);
-  __ sarl(scratch, Immediate(6));
+  __ shrl(scratch, Immediate(6));
   __ xorl(hash, scratch);
 }

@@ -4807,13 +4812,16 @@
   __ 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);
=======================================
--- /branches/bleeding_edge/test/cctest/cctest.gyp      Tue Oct  4 09:32:34 2011
+++ /branches/bleeding_edge/test/cctest/cctest.gyp      Thu Nov 10 06:26:57 2011
@@ -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',

--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to