blob: 154761313935d7fce15d4decdcb64e3dbdef01a7 [file] [log] [blame]
danno@chromium.org2c456792011-11-11 12:00:53 +00001// Copyright 2011 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include <stdlib.h>
29
ulan@chromium.org57ff8812013-05-10 08:16:55 +000030// TODO(dcarney): remove
31#define V8_ALLOW_ACCESS_TO_PERSISTENT_IMPLICIT
32
danno@chromium.org2c456792011-11-11 12:00:53 +000033#include "v8.h"
34
35#include "factory.h"
36#include "macro-assembler.h"
37#include "cctest.h"
38#include "code-stubs.h"
39#include "objects.h"
40
41#ifdef USE_SIMULATOR
42#include "simulator.h"
43#endif
44
45using namespace v8::internal;
46
47
48typedef uint32_t (*HASH_FUNCTION)();
49
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000050#define __ masm->
danno@chromium.org2c456792011-11-11 12:00:53 +000051
52
jkummerow@chromium.org59297c72013-01-09 16:32:23 +000053void generate(MacroAssembler* masm, i::Vector<const uint8_t> string) {
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000054 // GenerateHashInit takes the first character as an argument so it can't
55 // handle the zero length string.
56 ASSERT(string.length() > 0);
danno@chromium.org2c456792011-11-11 12:00:53 +000057#ifdef V8_TARGET_ARCH_IA32
58 __ push(ebx);
59 __ push(ecx);
60 __ mov(eax, Immediate(0));
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000061 __ mov(ebx, Immediate(string.at(0)));
62 StringHelper::GenerateHashInit(masm, eax, ebx, ecx);
danno@chromium.org2c456792011-11-11 12:00:53 +000063 for (int i = 1; i < string.length(); i++) {
64 __ mov(ebx, Immediate(string.at(i)));
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000065 StringHelper::GenerateHashAddCharacter(masm, eax, ebx, ecx);
danno@chromium.org2c456792011-11-11 12:00:53 +000066 }
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000067 StringHelper::GenerateHashGetHash(masm, eax, ecx);
danno@chromium.org2c456792011-11-11 12:00:53 +000068 __ pop(ecx);
69 __ pop(ebx);
70 __ Ret();
71#elif V8_TARGET_ARCH_X64
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000072 __ push(kRootRegister);
73 __ InitializeRootRegister();
danno@chromium.org2c456792011-11-11 12:00:53 +000074 __ push(rbx);
75 __ push(rcx);
76 __ movq(rax, Immediate(0));
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000077 __ movq(rbx, Immediate(string.at(0)));
78 StringHelper::GenerateHashInit(masm, rax, rbx, rcx);
danno@chromium.org2c456792011-11-11 12:00:53 +000079 for (int i = 1; i < string.length(); i++) {
80 __ movq(rbx, Immediate(string.at(i)));
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000081 StringHelper::GenerateHashAddCharacter(masm, rax, rbx, rcx);
danno@chromium.org2c456792011-11-11 12:00:53 +000082 }
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000083 StringHelper::GenerateHashGetHash(masm, rax, rcx);
danno@chromium.org2c456792011-11-11 12:00:53 +000084 __ pop(rcx);
85 __ pop(rbx);
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000086 __ pop(kRootRegister);
danno@chromium.org2c456792011-11-11 12:00:53 +000087 __ Ret();
88#elif V8_TARGET_ARCH_ARM
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000089 __ push(kRootRegister);
90 __ InitializeRootRegister();
91
danno@chromium.org2c456792011-11-11 12:00:53 +000092 __ mov(r0, Operand(0));
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000093 __ mov(ip, Operand(string.at(0)));
94 StringHelper::GenerateHashInit(masm, r0, ip);
danno@chromium.org2c456792011-11-11 12:00:53 +000095 for (int i = 1; i < string.length(); i++) {
96 __ mov(ip, Operand(string.at(i)));
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000097 StringHelper::GenerateHashAddCharacter(masm, r0, ip);
danno@chromium.org2c456792011-11-11 12:00:53 +000098 }
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000099 StringHelper::GenerateHashGetHash(masm, r0);
100 __ pop(kRootRegister);
danno@chromium.org2c456792011-11-11 12:00:53 +0000101 __ mov(pc, Operand(lr));
102#elif V8_TARGET_ARCH_MIPS
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000103 __ push(kRootRegister);
104 __ InitializeRootRegister();
105
danno@chromium.org2c456792011-11-11 12:00:53 +0000106 __ li(v0, Operand(0));
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000107 __ li(t1, Operand(string.at(0)));
108 StringHelper::GenerateHashInit(masm, v0, t1);
danno@chromium.org2c456792011-11-11 12:00:53 +0000109 for (int i = 1; i < string.length(); i++) {
110 __ li(t1, Operand(string.at(i)));
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000111 StringHelper::GenerateHashAddCharacter(masm, v0, t1);
danno@chromium.org2c456792011-11-11 12:00:53 +0000112 }
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000113 StringHelper::GenerateHashGetHash(masm, v0);
114 __ pop(kRootRegister);
115 __ jr(ra);
116 __ nop();
117#endif
118}
119
120
121void generate(MacroAssembler* masm, uint32_t key) {
122#ifdef V8_TARGET_ARCH_IA32
123 __ push(ebx);
124 __ mov(eax, Immediate(key));
125 __ GetNumberHash(eax, ebx);
126 __ pop(ebx);
127 __ Ret();
128#elif V8_TARGET_ARCH_X64
129 __ push(kRootRegister);
130 __ InitializeRootRegister();
131 __ push(rbx);
132 __ movq(rax, Immediate(key));
133 __ GetNumberHash(rax, rbx);
134 __ pop(rbx);
135 __ pop(kRootRegister);
136 __ Ret();
137#elif V8_TARGET_ARCH_ARM
138 __ push(kRootRegister);
139 __ InitializeRootRegister();
140 __ mov(r0, Operand(key));
141 __ GetNumberHash(r0, ip);
142 __ pop(kRootRegister);
143 __ mov(pc, Operand(lr));
144#elif V8_TARGET_ARCH_MIPS
145 __ push(kRootRegister);
146 __ InitializeRootRegister();
147 __ li(v0, Operand(key));
148 __ GetNumberHash(v0, t1);
149 __ pop(kRootRegister);
danno@chromium.org2c456792011-11-11 12:00:53 +0000150 __ jr(ra);
ricow@chromium.org7ad65222011-12-19 12:13:11 +0000151 __ nop();
danno@chromium.org2c456792011-11-11 12:00:53 +0000152#endif
153}
154
155
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000156void check(i::Vector<const uint8_t> string) {
157 Isolate* isolate = Isolate::Current();
158 Factory* factory = isolate->factory();
159 HandleScope scope(isolate);
160
danno@chromium.org2c456792011-11-11 12:00:53 +0000161 v8::internal::byte buffer[2048];
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000162 MacroAssembler masm(isolate, buffer, sizeof buffer);
danno@chromium.org2c456792011-11-11 12:00:53 +0000163
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000164 generate(&masm, string);
danno@chromium.org2c456792011-11-11 12:00:53 +0000165
166 CodeDesc desc;
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000167 masm.GetCode(&desc);
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000168 Handle<Object> undefined(isolate->heap()->undefined_value(), isolate);
169 Handle<Code> code = factory->NewCode(desc,
170 Code::ComputeFlags(Code::STUB),
171 undefined);
danno@chromium.org2c456792011-11-11 12:00:53 +0000172 CHECK(code->IsCode());
173
ricow@chromium.org7ad65222011-12-19 12:13:11 +0000174 HASH_FUNCTION hash = FUNCTION_CAST<HASH_FUNCTION>(code->entry());
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000175 Handle<String> v8_string = factory->NewStringFromOneByte(string);
danno@chromium.org2c456792011-11-11 12:00:53 +0000176 v8_string->set_hash_field(String::kEmptyHashField);
177#ifdef USE_SIMULATOR
178 uint32_t codegen_hash =
179 reinterpret_cast<uint32_t>(CALL_GENERATED_CODE(hash, 0, 0, 0, 0, 0));
180#else
181 uint32_t codegen_hash = hash();
182#endif
183 uint32_t runtime_hash = v8_string->Hash();
184 CHECK(runtime_hash == codegen_hash);
185}
186
187
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000188void check(i::Vector<const char> s) {
189 check(i::Vector<const uint8_t>::cast(s));
190}
191
192
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000193void check(uint32_t key) {
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000194 Isolate* isolate = Isolate::Current();
195 Factory* factory = isolate->factory();
196 HandleScope scope(isolate);
197
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000198 v8::internal::byte buffer[2048];
199 MacroAssembler masm(Isolate::Current(), buffer, sizeof buffer);
200
201 generate(&masm, key);
202
203 CodeDesc desc;
204 masm.GetCode(&desc);
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000205 Handle<Object> undefined(isolate->heap()->undefined_value(), isolate);
206 Handle<Code> code = factory->NewCode(desc,
207 Code::ComputeFlags(Code::STUB),
208 undefined);
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000209 CHECK(code->IsCode());
210
211 HASH_FUNCTION hash = FUNCTION_CAST<HASH_FUNCTION>(code->entry());
212#ifdef USE_SIMULATOR
213 uint32_t codegen_hash =
214 reinterpret_cast<uint32_t>(CALL_GENERATED_CODE(hash, 0, 0, 0, 0, 0));
215#else
216 uint32_t codegen_hash = hash();
217#endif
218
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000219 uint32_t runtime_hash = ComputeIntegerHash(key, isolate->heap()->HashSeed());
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000220 CHECK(runtime_hash == codegen_hash);
221}
222
223
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000224void check_twochars(uint8_t a, uint8_t b) {
225 uint8_t ab[2] = {a, b};
226 check(i::Vector<const uint8_t>(ab, 2));
danno@chromium.org2c456792011-11-11 12:00:53 +0000227}
228
229
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000230static uint32_t PseudoRandom(uint32_t i, uint32_t j) {
231 return ~(~((i * 781) ^ (j * 329)));
232}
233
234
danno@chromium.org2c456792011-11-11 12:00:53 +0000235TEST(StringHash) {
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000236 v8::Isolate* isolate = v8::Isolate::GetCurrent();
237 v8::HandleScope handle_scope(isolate);
238 v8::Context::Scope context_scope(v8::Context::New(isolate));
239
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000240 for (uint8_t a = 0; a < String::kMaxOneByteCharCode; a++) {
danno@chromium.org2c456792011-11-11 12:00:53 +0000241 // Numbers are hashed differently.
242 if (a >= '0' && a <= '9') continue;
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000243 for (uint8_t b = 0; b < String::kMaxOneByteCharCode; b++) {
danno@chromium.org2c456792011-11-11 12:00:53 +0000244 if (b >= '0' && b <= '9') continue;
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000245 check_twochars(a, b);
danno@chromium.org2c456792011-11-11 12:00:53 +0000246 }
247 }
danno@chromium.org2c456792011-11-11 12:00:53 +0000248 check(i::Vector<const char>("*", 1));
249 check(i::Vector<const char>(".zZ", 3));
250 check(i::Vector<const char>("muc", 3));
251 check(i::Vector<const char>("(>'_')>", 7));
252 check(i::Vector<const char>("-=[ vee eight ftw ]=-", 21));
253}
254
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000255
256TEST(NumberHash) {
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000257 v8::Isolate* isolate = v8::Isolate::GetCurrent();
258 v8::HandleScope handle_scope(isolate);
259 v8::Context::Scope context_scope(v8::Context::New(isolate));
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000260
261 // Some specific numbers
262 for (uint32_t key = 0; key < 42; key += 7) {
263 check(key);
264 }
265
266 // Some pseudo-random numbers
267 static const uint32_t kLimit = 1000;
268 for (uint32_t i = 0; i < 5; i++) {
269 for (uint32_t j = 0; j < 5; j++) {
270 check(PseudoRandom(i, j) % kLimit);
271 }
272 }
273}
274
danno@chromium.org2c456792011-11-11 12:00:53 +0000275#undef __