1// Copyright 2014 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "src/v8.h"
6
7#include "src/compiler/js-graph.h"
8#include "src/compiler/node-properties-inl.h"
9#include "src/compiler/typer.h"
10#include "src/types.h"
11#include "test/cctest/cctest.h"
12#include "test/cctest/compiler/value-helper.h"
13
14using namespace v8::internal;
15using namespace v8::internal::compiler;
16
17class JSCacheTesterHelper {
18 protected:
19  explicit JSCacheTesterHelper(Zone* zone)
20      : main_graph_(zone),
21        main_common_(zone),
22        main_javascript_(zone),
23        main_typer_(zone),
24        main_machine_() {}
25  Graph main_graph_;
26  CommonOperatorBuilder main_common_;
27  JSOperatorBuilder main_javascript_;
28  Typer main_typer_;
29  MachineOperatorBuilder main_machine_;
30};
31
32
33class JSConstantCacheTester : public HandleAndZoneScope,
34                              public JSCacheTesterHelper,
35                              public JSGraph {
36 public:
37  JSConstantCacheTester()
38      : JSCacheTesterHelper(main_zone()),
39        JSGraph(&main_graph_, &main_common_, &main_javascript_, &main_typer_,
40                &main_machine_) {}
41
42  Type* upper(Node* node) { return NodeProperties::GetBounds(node).upper; }
43
44  Handle<Object> handle(Node* node) {
45    CHECK_EQ(IrOpcode::kHeapConstant, node->opcode());
46    return OpParameter<Unique<Object> >(node).handle();
47  }
48
49  Factory* factory() { return main_isolate()->factory(); }
50};
51
52
53TEST(ZeroConstant1) {
54  JSConstantCacheTester T;
55
56  Node* zero = T.ZeroConstant();
57
58  CHECK_EQ(IrOpcode::kNumberConstant, zero->opcode());
59  CHECK_EQ(zero, T.Constant(0));
60  CHECK_NE(zero, T.Constant(-0.0));
61  CHECK_NE(zero, T.Constant(1.0));
62  CHECK_NE(zero, T.Constant(v8::base::OS::nan_value()));
63  CHECK_NE(zero, T.Float64Constant(0));
64  CHECK_NE(zero, T.Int32Constant(0));
65
66  Type* t = T.upper(zero);
67
68  CHECK(t->Is(Type::Number()));
69  CHECK(t->Is(Type::Integral32()));
70  CHECK(t->Is(Type::Signed32()));
71  CHECK(t->Is(Type::Unsigned32()));
72  CHECK(t->Is(Type::SignedSmall()));
73  CHECK(t->Is(Type::UnsignedSmall()));
74}
75
76
77TEST(MinusZeroConstant) {
78  JSConstantCacheTester T;
79
80  Node* minus_zero = T.Constant(-0.0);
81  Node* zero = T.ZeroConstant();
82
83  CHECK_EQ(IrOpcode::kNumberConstant, minus_zero->opcode());
84  CHECK_EQ(minus_zero, T.Constant(-0.0));
85  CHECK_NE(zero, minus_zero);
86
87  Type* t = T.upper(minus_zero);
88
89  CHECK(t->Is(Type::Number()));
90  CHECK(t->Is(Type::MinusZero()));
91  CHECK(!t->Is(Type::Integral32()));
92  CHECK(!t->Is(Type::Signed32()));
93  CHECK(!t->Is(Type::Unsigned32()));
94  CHECK(!t->Is(Type::SignedSmall()));
95  CHECK(!t->Is(Type::UnsignedSmall()));
96
97  double zero_value = OpParameter<double>(zero);
98  double minus_zero_value = OpParameter<double>(minus_zero);
99
100  CHECK_EQ(0.0, zero_value);
101  CHECK_NE(-0.0, zero_value);
102  CHECK_EQ(-0.0, minus_zero_value);
103  CHECK_NE(0.0, minus_zero_value);
104}
105
106
107TEST(ZeroConstant2) {
108  JSConstantCacheTester T;
109
110  Node* zero = T.Constant(0);
111
112  CHECK_EQ(IrOpcode::kNumberConstant, zero->opcode());
113  CHECK_EQ(zero, T.ZeroConstant());
114  CHECK_NE(zero, T.Constant(-0.0));
115  CHECK_NE(zero, T.Constant(1.0));
116  CHECK_NE(zero, T.Constant(v8::base::OS::nan_value()));
117  CHECK_NE(zero, T.Float64Constant(0));
118  CHECK_NE(zero, T.Int32Constant(0));
119
120  Type* t = T.upper(zero);
121
122  CHECK(t->Is(Type::Number()));
123  CHECK(t->Is(Type::Integral32()));
124  CHECK(t->Is(Type::Signed32()));
125  CHECK(t->Is(Type::Unsigned32()));
126  CHECK(t->Is(Type::SignedSmall()));
127  CHECK(t->Is(Type::UnsignedSmall()));
128}
129
130
131TEST(OneConstant1) {
132  JSConstantCacheTester T;
133
134  Node* one = T.OneConstant();
135
136  CHECK_EQ(IrOpcode::kNumberConstant, one->opcode());
137  CHECK_EQ(one, T.Constant(1));
138  CHECK_EQ(one, T.Constant(1.0));
139  CHECK_NE(one, T.Constant(1.01));
140  CHECK_NE(one, T.Constant(-1.01));
141  CHECK_NE(one, T.Constant(v8::base::OS::nan_value()));
142  CHECK_NE(one, T.Float64Constant(1.0));
143  CHECK_NE(one, T.Int32Constant(1));
144
145  Type* t = T.upper(one);
146
147  CHECK(t->Is(Type::Number()));
148  CHECK(t->Is(Type::Integral32()));
149  CHECK(t->Is(Type::Signed32()));
150  CHECK(t->Is(Type::Unsigned32()));
151  CHECK(t->Is(Type::SignedSmall()));
152  CHECK(t->Is(Type::UnsignedSmall()));
153}
154
155
156TEST(OneConstant2) {
157  JSConstantCacheTester T;
158
159  Node* one = T.Constant(1);
160
161  CHECK_EQ(IrOpcode::kNumberConstant, one->opcode());
162  CHECK_EQ(one, T.OneConstant());
163  CHECK_EQ(one, T.Constant(1.0));
164  CHECK_NE(one, T.Constant(1.01));
165  CHECK_NE(one, T.Constant(-1.01));
166  CHECK_NE(one, T.Constant(v8::base::OS::nan_value()));
167  CHECK_NE(one, T.Float64Constant(1.0));
168  CHECK_NE(one, T.Int32Constant(1));
169
170  Type* t = T.upper(one);
171
172  CHECK(t->Is(Type::Number()));
173  CHECK(t->Is(Type::Integral32()));
174  CHECK(t->Is(Type::Signed32()));
175  CHECK(t->Is(Type::Unsigned32()));
176  CHECK(t->Is(Type::SignedSmall()));
177  CHECK(t->Is(Type::UnsignedSmall()));
178}
179
180
181TEST(Canonicalizations) {
182  JSConstantCacheTester T;
183
184  CHECK_EQ(T.ZeroConstant(), T.ZeroConstant());
185  CHECK_EQ(T.UndefinedConstant(), T.UndefinedConstant());
186  CHECK_EQ(T.TheHoleConstant(), T.TheHoleConstant());
187  CHECK_EQ(T.TrueConstant(), T.TrueConstant());
188  CHECK_EQ(T.FalseConstant(), T.FalseConstant());
189  CHECK_EQ(T.NullConstant(), T.NullConstant());
190  CHECK_EQ(T.ZeroConstant(), T.ZeroConstant());
191  CHECK_EQ(T.OneConstant(), T.OneConstant());
192  CHECK_EQ(T.NaNConstant(), T.NaNConstant());
193}
194
195
196TEST(NoAliasing) {
197  JSConstantCacheTester T;
198
199  Node* nodes[] = {T.UndefinedConstant(), T.TheHoleConstant(), T.TrueConstant(),
200                   T.FalseConstant(),     T.NullConstant(),    T.ZeroConstant(),
201                   T.OneConstant(),       T.NaNConstant(),     T.Constant(21),
202                   T.Constant(22.2)};
203
204  for (size_t i = 0; i < arraysize(nodes); i++) {
205    for (size_t j = 0; j < arraysize(nodes); j++) {
206      if (i != j) CHECK_NE(nodes[i], nodes[j]);
207    }
208  }
209}
210
211
212TEST(CanonicalizingNumbers) {
213  JSConstantCacheTester T;
214
215  FOR_FLOAT64_INPUTS(i) {
216    Node* node = T.Constant(*i);
217    for (int j = 0; j < 5; j++) {
218      CHECK_EQ(node, T.Constant(*i));
219    }
220  }
221}
222
223
224TEST(NumberTypes) {
225  JSConstantCacheTester T;
226
227  FOR_FLOAT64_INPUTS(i) {
228    double value = *i;
229    Node* node = T.Constant(value);
230    CHECK(T.upper(node)->Equals(Type::Of(value, T.main_zone())));
231  }
232}
233
234
235TEST(HeapNumbers) {
236  JSConstantCacheTester T;
237
238  FOR_FLOAT64_INPUTS(i) {
239    double value = *i;
240    Handle<Object> num = T.factory()->NewNumber(value);
241    Handle<HeapNumber> heap = T.factory()->NewHeapNumber(value);
242    Node* node1 = T.Constant(value);
243    Node* node2 = T.Constant(num);
244    Node* node3 = T.Constant(heap);
245    CHECK_EQ(node1, node2);
246    CHECK_EQ(node1, node3);
247  }
248}
249
250
251TEST(OddballHandle) {
252  JSConstantCacheTester T;
253
254  CHECK_EQ(T.UndefinedConstant(), T.Constant(T.factory()->undefined_value()));
255  CHECK_EQ(T.TheHoleConstant(), T.Constant(T.factory()->the_hole_value()));
256  CHECK_EQ(T.TrueConstant(), T.Constant(T.factory()->true_value()));
257  CHECK_EQ(T.FalseConstant(), T.Constant(T.factory()->false_value()));
258  CHECK_EQ(T.NullConstant(), T.Constant(T.factory()->null_value()));
259  CHECK_EQ(T.NaNConstant(), T.Constant(T.factory()->nan_value()));
260}
261
262
263TEST(OddballValues) {
264  JSConstantCacheTester T;
265
266  CHECK_EQ(*T.factory()->undefined_value(), *T.handle(T.UndefinedConstant()));
267  CHECK_EQ(*T.factory()->the_hole_value(), *T.handle(T.TheHoleConstant()));
268  CHECK_EQ(*T.factory()->true_value(), *T.handle(T.TrueConstant()));
269  CHECK_EQ(*T.factory()->false_value(), *T.handle(T.FalseConstant()));
270  CHECK_EQ(*T.factory()->null_value(), *T.handle(T.NullConstant()));
271}
272
273
274TEST(OddballTypes) {
275  JSConstantCacheTester T;
276
277  CHECK(T.upper(T.UndefinedConstant())->Is(Type::Undefined()));
278  // TODO(dcarney): figure this out.
279  // CHECK(T.upper(T.TheHoleConstant())->Is(Type::Internal()));
280  CHECK(T.upper(T.TrueConstant())->Is(Type::Boolean()));
281  CHECK(T.upper(T.FalseConstant())->Is(Type::Boolean()));
282  CHECK(T.upper(T.NullConstant())->Is(Type::Null()));
283  CHECK(T.upper(T.ZeroConstant())->Is(Type::Number()));
284  CHECK(T.upper(T.OneConstant())->Is(Type::Number()));
285  CHECK(T.upper(T.NaNConstant())->Is(Type::NaN()));
286}
287
288
289TEST(ExternalReferences) {
290  // TODO(titzer): test canonicalization of external references.
291}
292