v8  3.25.30(node0.11.13)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
test-hashing.cc
Go to the documentation of this file.
1 // 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 
30 #include "v8.h"
31 
32 #include "factory.h"
33 #include "macro-assembler.h"
34 #include "cctest.h"
35 #include "code-stubs.h"
36 #include "objects.h"
37 
38 #ifdef USE_SIMULATOR
39 #include "simulator.h"
40 #endif
41 
42 using namespace v8::internal;
43 
44 
45 typedef uint32_t (*HASH_FUNCTION)();
46 
47 #define __ masm->
48 
49 
51  // GenerateHashInit takes the first character as an argument so it can't
52  // handle the zero length string.
53  ASSERT(string.length() > 0);
54 #if V8_TARGET_ARCH_IA32
55  __ push(ebx);
56  __ push(ecx);
57  __ mov(eax, Immediate(0));
58  __ mov(ebx, Immediate(string.at(0)));
60  for (int i = 1; i < string.length(); i++) {
61  __ mov(ebx, Immediate(string.at(i)));
63  }
65  __ pop(ecx);
66  __ pop(ebx);
67  __ Ret();
68 #elif V8_TARGET_ARCH_X64
69  __ pushq(kRootRegister);
70  __ InitializeRootRegister();
71  __ pushq(rbx);
72  __ pushq(rcx);
73  __ movp(rax, Immediate(0));
74  __ movp(rbx, Immediate(string.at(0)));
76  for (int i = 1; i < string.length(); i++) {
77  __ movp(rbx, Immediate(string.at(i)));
79  }
81  __ popq(rcx);
82  __ popq(rbx);
83  __ popq(kRootRegister);
84  __ Ret();
85 #elif V8_TARGET_ARCH_ARM
86  __ push(kRootRegister);
87  __ InitializeRootRegister();
88 
89  __ mov(r0, Operand(0));
90  __ mov(ip, Operand(string.at(0)));
92  for (int i = 1; i < string.length(); i++) {
93  __ mov(ip, Operand(string.at(i)));
95  }
97  __ pop(kRootRegister);
98  __ mov(pc, Operand(lr));
99 #elif V8_TARGET_ARCH_ARM64
100  // The ARM64 assembler usually uses jssp (x28) as a stack pointer, but only
101  // csp is initialized by the calling (C++) code.
102  Register old_stack_pointer = __ StackPointer();
103  __ SetStackPointer(csp);
104  __ Push(root, xzr);
105  __ InitializeRootRegister();
106  __ Mov(x0, 0);
107  __ Mov(x10, Operand(string.at(0)));
108  StringHelper::GenerateHashInit(masm, x0, x10);
109  for (int i = 1; i < string.length(); i++) {
110  __ Mov(x10, Operand(string.at(i)));
112  }
113  StringHelper::GenerateHashGetHash(masm, x0, x10);
114  __ Pop(xzr, root);
115  __ Ret();
116  __ SetStackPointer(old_stack_pointer);
117 #elif V8_TARGET_ARCH_MIPS
118  __ push(kRootRegister);
119  __ InitializeRootRegister();
120 
121  __ li(v0, Operand(0));
122  __ li(t1, Operand(string.at(0)));
123  StringHelper::GenerateHashInit(masm, v0, t1);
124  for (int i = 1; i < string.length(); i++) {
125  __ li(t1, Operand(string.at(i)));
127  }
129  __ pop(kRootRegister);
130  __ jr(ra);
131  __ nop();
132 #else
133 #error Unsupported architecture.
134 #endif
135 }
136 
137 
138 void generate(MacroAssembler* masm, uint32_t key) {
139 #if V8_TARGET_ARCH_IA32
140  __ push(ebx);
141  __ mov(eax, Immediate(key));
142  __ GetNumberHash(eax, ebx);
143  __ pop(ebx);
144  __ Ret();
145 #elif V8_TARGET_ARCH_X64
146  __ pushq(kRootRegister);
147  __ InitializeRootRegister();
148  __ pushq(rbx);
149  __ movp(rax, Immediate(key));
150  __ GetNumberHash(rax, rbx);
151  __ popq(rbx);
152  __ popq(kRootRegister);
153  __ Ret();
154 #elif V8_TARGET_ARCH_ARM
155  __ push(kRootRegister);
156  __ InitializeRootRegister();
157  __ mov(r0, Operand(key));
158  __ GetNumberHash(r0, ip);
159  __ pop(kRootRegister);
160  __ mov(pc, Operand(lr));
161 #elif V8_TARGET_ARCH_ARM64
162  // The ARM64 assembler usually uses jssp (x28) as a stack pointer, but only
163  // csp is initialized by the calling (C++) code.
164  Register old_stack_pointer = __ StackPointer();
165  __ SetStackPointer(csp);
166  __ Push(root, xzr);
167  __ InitializeRootRegister();
168  __ Mov(x0, key);
169  __ GetNumberHash(x0, x10);
170  __ Pop(xzr, root);
171  __ Ret();
172  __ SetStackPointer(old_stack_pointer);
173 #elif V8_TARGET_ARCH_MIPS
174  __ push(kRootRegister);
175  __ InitializeRootRegister();
176  __ li(v0, Operand(key));
177  __ GetNumberHash(v0, t1);
178  __ pop(kRootRegister);
179  __ jr(ra);
180  __ nop();
181 #else
182 #error Unsupported architecture.
183 #endif
184 }
185 
186 
188  Isolate* isolate = CcTest::i_isolate();
189  Factory* factory = isolate->factory();
190  HandleScope scope(isolate);
191 
192  v8::internal::byte buffer[2048];
193  MacroAssembler masm(isolate, buffer, sizeof buffer);
194 
195  generate(&masm, string);
196 
197  CodeDesc desc;
198  masm.GetCode(&desc);
199  Handle<Object> undefined(isolate->heap()->undefined_value(), isolate);
200  Handle<Code> code = factory->NewCode(desc,
202  undefined);
203  CHECK(code->IsCode());
204 
205  HASH_FUNCTION hash = FUNCTION_CAST<HASH_FUNCTION>(code->entry());
206  Handle<String> v8_string = factory->NewStringFromOneByte(string);
207  v8_string->set_hash_field(String::kEmptyHashField);
208 #ifdef USE_SIMULATOR
209  uint32_t codegen_hash = static_cast<uint32_t>(
210  reinterpret_cast<uintptr_t>(CALL_GENERATED_CODE(hash, 0, 0, 0, 0, 0)));
211 #else
212  uint32_t codegen_hash = hash();
213 #endif
214  uint32_t runtime_hash = v8_string->Hash();
215  CHECK(runtime_hash == codegen_hash);
216 }
217 
218 
221 }
222 
223 
224 void check(uint32_t key) {
225  Isolate* isolate = CcTest::i_isolate();
226  Factory* factory = isolate->factory();
227  HandleScope scope(isolate);
228 
229  v8::internal::byte buffer[2048];
230  MacroAssembler masm(CcTest::i_isolate(), buffer, sizeof buffer);
231 
232  generate(&masm, key);
233 
234  CodeDesc desc;
235  masm.GetCode(&desc);
236  Handle<Object> undefined(isolate->heap()->undefined_value(), isolate);
237  Handle<Code> code = factory->NewCode(desc,
239  undefined);
240  CHECK(code->IsCode());
241 
242  HASH_FUNCTION hash = FUNCTION_CAST<HASH_FUNCTION>(code->entry());
243 #ifdef USE_SIMULATOR
244  uint32_t codegen_hash = static_cast<uint32_t>(
245  reinterpret_cast<uintptr_t>(CALL_GENERATED_CODE(hash, 0, 0, 0, 0, 0)));
246 #else
247  uint32_t codegen_hash = hash();
248 #endif
249 
250  uint32_t runtime_hash = ComputeIntegerHash(key, isolate->heap()->HashSeed());
251  CHECK(runtime_hash == codegen_hash);
252 }
253 
254 
255 void check_twochars(uint8_t a, uint8_t b) {
256  uint8_t ab[2] = {a, b};
258 }
259 
260 
261 static uint32_t PseudoRandom(uint32_t i, uint32_t j) {
262  return ~(~((i * 781) ^ (j * 329)));
263 }
264 
265 
266 TEST(StringHash) {
267  v8::Isolate* isolate = CcTest::isolate();
268  v8::HandleScope handle_scope(isolate);
269  v8::Context::Scope context_scope(v8::Context::New(isolate));
270 
271  for (uint8_t a = 0; a < String::kMaxOneByteCharCode; a++) {
272  // Numbers are hashed differently.
273  if (a >= '0' && a <= '9') continue;
274  for (uint8_t b = 0; b < String::kMaxOneByteCharCode; b++) {
275  if (b >= '0' && b <= '9') continue;
276  check_twochars(a, b);
277  }
278  }
279  check(i::Vector<const char>("*", 1));
280  check(i::Vector<const char>(".zZ", 3));
281  check(i::Vector<const char>("muc", 3));
282  check(i::Vector<const char>("(>'_')>", 7));
283  check(i::Vector<const char>("-=[ vee eight ftw ]=-", 21));
284 }
285 
286 
287 TEST(NumberHash) {
288  v8::Isolate* isolate = CcTest::isolate();
289  v8::HandleScope handle_scope(isolate);
290  v8::Context::Scope context_scope(v8::Context::New(isolate));
291 
292  // Some specific numbers
293  for (uint32_t key = 0; key < 42; key += 7) {
294  check(key);
295  }
296 
297  // Some pseudo-random numbers
298  static const uint32_t kLimit = 1000;
299  for (uint32_t i = 0; i < 5; i++) {
300  for (uint32_t j = 0; j < 5; j++) {
301  check(PseudoRandom(i, j) % kLimit);
302  }
303  }
304 }
305 
306 #undef __
uint32_t HashSeed()
Definition: heap.h:1831
Handle< String > NewStringFromOneByte(Vector< const uint8_t > str, PretenureFlag pretenure=NOT_TENURED)
Definition: factory.cc:265
static void GenerateHashGetHash(MacroAssembler *masm, Register hash)
uint32_t(* HASH_FUNCTION)()
Definition: test-hashing.cc:45
#define ASSERT(condition)
Definition: checks.h:329
#define CHECK(condition)
Definition: checks.h:75
Factory * factory()
Definition: isolate.h:995
void check_twochars(uint8_t a, uint8_t b)
const Register kRootRegister
uint8_t byte
Definition: globals.h:185
const Register eax
const Register ip
void GetCode(CodeDesc *desc)
void check(i::Vector< const uint8_t > string)
const Register ecx
const Register rbx
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra code(assertions) for debugging") DEFINE_bool(code_comments
const Register pc
static i::Isolate * i_isolate()
Definition: cctest.h:102
const Register rax
#define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4)
Definition: simulator-arm.h:48
static void GenerateHashAddCharacter(MacroAssembler *masm, Register hash, Register character)
const Register r0
void generate(MacroAssembler *masm, i::Vector< const uint8_t > string)
Definition: test-hashing.cc:50
static Local< Context > New(Isolate *isolate, ExtensionConfiguration *extensions=NULL, Handle< ObjectTemplate > global_template=Handle< ObjectTemplate >(), Handle< Value > global_object=Handle< Value >())
Definition: api.cc:5188
const Register lr
const Register ebx
uint32_t ComputeIntegerHash(uint32_t key, uint32_t seed)
Definition: utils.h:322
static Flags ComputeFlags(Kind kind, InlineCacheState ic_state=UNINITIALIZED, ExtraICState extra_ic_state=kNoExtraICState, StubType type=NORMAL, InlineCacheHolderFlag holder=OWN_MAP)
Definition: objects-inl.h:4601
Handle< Code > NewCode(const CodeDesc &desc, Code::Flags flags, Handle< Object > self_reference, bool immovable=false, bool crankshafted=false, int prologue_offset=Code::kPrologueOffsetNotSet)
Definition: factory.cc:1291
const Register rcx
#define __
Definition: test-hashing.cc:47
static const int kEmptyHashField
Definition: objects.h:8678
static const int32_t kMaxOneByteCharCode
Definition: objects.h:8914
static void GenerateHashInit(MacroAssembler *masm, Register hash, Register character)
static v8::Isolate * isolate()
Definition: cctest.h:96