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 "src/v8.h"
31
32#include "src/code-stubs.h"
33#include "src/factory.h"
34#include "src/macro-assembler.h"
35#include "src/objects.h"
36#include "test/cctest/cctest.h"
37
38#ifdef USE_SIMULATOR
39#include "src/simulator.h"
40#endif
41
42using namespace v8::internal;
43
44
45typedef uint32_t (*HASH_FUNCTION)();
46
47#define __ masm->
48
49
50void generate(MacroAssembler* masm, uint32_t key) {
51#if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X87
52  __ push(ebx);
53  __ mov(eax, Immediate(key));
54  __ GetNumberHash(eax, ebx);
55  __ pop(ebx);
56  __ Ret();
57#elif V8_TARGET_ARCH_X64
58  __ pushq(kRootRegister);
59  __ InitializeRootRegister();
60  __ pushq(rbx);
61  __ movp(rax, Immediate(key));
62  __ GetNumberHash(rax, rbx);
63  __ popq(rbx);
64  __ popq(kRootRegister);
65  __ Ret();
66#elif V8_TARGET_ARCH_ARM
67  __ push(kRootRegister);
68  __ InitializeRootRegister();
69  __ mov(r0, Operand(key));
70  __ GetNumberHash(r0, ip);
71  __ pop(kRootRegister);
72  __ mov(pc, Operand(lr));
73#elif V8_TARGET_ARCH_ARM64
74  // The ARM64 assembler usually uses jssp (x28) as a stack pointer, but only
75  // csp is initialized by the calling (C++) code.
76  Register old_stack_pointer = __ StackPointer();
77  __ SetStackPointer(csp);
78  __ Push(root, xzr);
79  __ InitializeRootRegister();
80  __ Mov(x0, key);
81  __ GetNumberHash(x0, x10);
82  __ Pop(xzr, root);
83  __ Ret();
84  __ SetStackPointer(old_stack_pointer);
85#elif V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64
86  __ push(kRootRegister);
87  __ InitializeRootRegister();
88  __ li(v0, Operand(key));
89  __ GetNumberHash(v0, t1);
90  __ pop(kRootRegister);
91  __ jr(ra);
92  __ nop();
93#else
94#error Unsupported architecture.
95#endif
96}
97
98
99void check(uint32_t key) {
100  Isolate* isolate = CcTest::i_isolate();
101  Factory* factory = isolate->factory();
102  HandleScope scope(isolate);
103
104  v8::internal::byte buffer[2048];
105  MacroAssembler masm(CcTest::i_isolate(), buffer, sizeof buffer);
106
107  generate(&masm, key);
108
109  CodeDesc desc;
110  masm.GetCode(&desc);
111  Handle<Object> undefined(isolate->heap()->undefined_value(), isolate);
112  Handle<Code> code = factory->NewCode(desc,
113                                       Code::ComputeFlags(Code::STUB),
114                                       undefined);
115  CHECK(code->IsCode());
116
117  HASH_FUNCTION hash = FUNCTION_CAST<HASH_FUNCTION>(code->entry());
118#ifdef USE_SIMULATOR
119  uint32_t codegen_hash = static_cast<uint32_t>(
120        reinterpret_cast<uintptr_t>(CALL_GENERATED_CODE(hash, 0, 0, 0, 0, 0)));
121#else
122  uint32_t codegen_hash = hash();
123#endif
124
125  uint32_t runtime_hash = ComputeIntegerHash(key, isolate->heap()->HashSeed());
126  CHECK(runtime_hash == codegen_hash);
127}
128
129
130static uint32_t PseudoRandom(uint32_t i, uint32_t j) {
131  return ~(~((i * 781) ^ (j * 329)));
132}
133
134
135TEST(NumberHash) {
136  v8::Isolate* isolate = CcTest::isolate();
137  v8::HandleScope handle_scope(isolate);
138  v8::Context::Scope context_scope(v8::Context::New(isolate));
139
140  // Some specific numbers
141  for (uint32_t key = 0; key < 42; key += 7) {
142    check(key);
143  }
144
145  // Some pseudo-random numbers
146  static const uint32_t kLimit = 1000;
147  for (uint32_t i = 0; i < 5; i++) {
148    for (uint32_t j = 0; j < 5; j++) {
149      check(PseudoRandom(i, j) % kLimit);
150    }
151  }
152}
153
154#undef __
155