blob: 06169f3ba6f2423639c86adfbbeb5a325e9654fd [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// 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
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005#include "src/assembler.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006#include "src/compiler/js-graph.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007#include "src/compiler/node-properties.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008#include "src/compiler/typer.h"
9#include "src/types.h"
10#include "test/cctest/cctest.h"
11#include "test/cctest/compiler/value-helper.h"
12
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013namespace v8 {
14namespace internal {
15namespace compiler {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016
17class JSCacheTesterHelper {
18 protected:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019 JSCacheTesterHelper(Isolate* isolate, Zone* zone)
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020 : main_graph_(zone),
21 main_common_(zone),
22 main_javascript_(zone),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023 main_typer_(isolate, &main_graph_),
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024 main_machine_(zone) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +000025 Graph main_graph_;
26 CommonOperatorBuilder main_common_;
27 JSOperatorBuilder main_javascript_;
28 Typer main_typer_;
29 MachineOperatorBuilder main_machine_;
30};
31
32
Emily Bernierd0a1eb72015-03-24 16:35:39 -040033// TODO(dcarney): JSConstantCacheTester inherits from JSGraph???
Ben Murdochb8a8cc12014-11-26 15:28:44 +000034class JSConstantCacheTester : public HandleAndZoneScope,
35 public JSCacheTesterHelper,
36 public JSGraph {
37 public:
38 JSConstantCacheTester()
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000039 : JSCacheTesterHelper(main_isolate(), main_zone()),
40 JSGraph(main_isolate(), &main_graph_, &main_common_, &main_javascript_,
41 nullptr, &main_machine_) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040042 main_graph_.SetStart(main_graph_.NewNode(common()->Start(0)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000043 main_graph_.SetEnd(
44 main_graph_.NewNode(common()->End(1), main_graph_.start()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -040045 main_typer_.Run();
46 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000047
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000048 Type* TypeOf(Node* node) { return NodeProperties::GetType(node); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000049
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000050 Handle<HeapObject> handle(Node* node) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000051 CHECK_EQ(IrOpcode::kHeapConstant, node->opcode());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000052 return OpParameter<Handle<HeapObject>>(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000053 }
54
55 Factory* factory() { return main_isolate()->factory(); }
56};
57
58
59TEST(ZeroConstant1) {
60 JSConstantCacheTester T;
61
62 Node* zero = T.ZeroConstant();
63
64 CHECK_EQ(IrOpcode::kNumberConstant, zero->opcode());
65 CHECK_EQ(zero, T.Constant(0));
66 CHECK_NE(zero, T.Constant(-0.0));
67 CHECK_NE(zero, T.Constant(1.0));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000068 CHECK_NE(zero, T.Constant(std::numeric_limits<double>::quiet_NaN()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000069 CHECK_NE(zero, T.Float64Constant(0));
70 CHECK_NE(zero, T.Int32Constant(0));
71
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000072 Type* t = T.TypeOf(zero);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000073
74 CHECK(t->Is(Type::Number()));
75 CHECK(t->Is(Type::Integral32()));
76 CHECK(t->Is(Type::Signed32()));
77 CHECK(t->Is(Type::Unsigned32()));
78 CHECK(t->Is(Type::SignedSmall()));
79 CHECK(t->Is(Type::UnsignedSmall()));
80}
81
82
83TEST(MinusZeroConstant) {
84 JSConstantCacheTester T;
85
86 Node* minus_zero = T.Constant(-0.0);
87 Node* zero = T.ZeroConstant();
88
89 CHECK_EQ(IrOpcode::kNumberConstant, minus_zero->opcode());
90 CHECK_EQ(minus_zero, T.Constant(-0.0));
91 CHECK_NE(zero, minus_zero);
92
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000093 Type* t = T.TypeOf(minus_zero);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000094
95 CHECK(t->Is(Type::Number()));
96 CHECK(t->Is(Type::MinusZero()));
97 CHECK(!t->Is(Type::Integral32()));
98 CHECK(!t->Is(Type::Signed32()));
99 CHECK(!t->Is(Type::Unsigned32()));
100 CHECK(!t->Is(Type::SignedSmall()));
101 CHECK(!t->Is(Type::UnsignedSmall()));
102
103 double zero_value = OpParameter<double>(zero);
104 double minus_zero_value = OpParameter<double>(minus_zero);
105
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000106 CHECK(bit_cast<uint64_t>(0.0) == bit_cast<uint64_t>(zero_value));
107 CHECK(bit_cast<uint64_t>(-0.0) != bit_cast<uint64_t>(zero_value));
108 CHECK(bit_cast<uint64_t>(0.0) != bit_cast<uint64_t>(minus_zero_value));
109 CHECK(bit_cast<uint64_t>(-0.0) == bit_cast<uint64_t>(minus_zero_value));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000110}
111
112
113TEST(ZeroConstant2) {
114 JSConstantCacheTester T;
115
116 Node* zero = T.Constant(0);
117
118 CHECK_EQ(IrOpcode::kNumberConstant, zero->opcode());
119 CHECK_EQ(zero, T.ZeroConstant());
120 CHECK_NE(zero, T.Constant(-0.0));
121 CHECK_NE(zero, T.Constant(1.0));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000122 CHECK_NE(zero, T.Constant(std::numeric_limits<double>::quiet_NaN()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000123 CHECK_NE(zero, T.Float64Constant(0));
124 CHECK_NE(zero, T.Int32Constant(0));
125
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000126 Type* t = T.TypeOf(zero);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000127
128 CHECK(t->Is(Type::Number()));
129 CHECK(t->Is(Type::Integral32()));
130 CHECK(t->Is(Type::Signed32()));
131 CHECK(t->Is(Type::Unsigned32()));
132 CHECK(t->Is(Type::SignedSmall()));
133 CHECK(t->Is(Type::UnsignedSmall()));
134}
135
136
137TEST(OneConstant1) {
138 JSConstantCacheTester T;
139
140 Node* one = T.OneConstant();
141
142 CHECK_EQ(IrOpcode::kNumberConstant, one->opcode());
143 CHECK_EQ(one, T.Constant(1));
144 CHECK_EQ(one, T.Constant(1.0));
145 CHECK_NE(one, T.Constant(1.01));
146 CHECK_NE(one, T.Constant(-1.01));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000147 CHECK_NE(one, T.Constant(std::numeric_limits<double>::quiet_NaN()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000148 CHECK_NE(one, T.Float64Constant(1.0));
149 CHECK_NE(one, T.Int32Constant(1));
150
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000151 Type* t = T.TypeOf(one);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000152
153 CHECK(t->Is(Type::Number()));
154 CHECK(t->Is(Type::Integral32()));
155 CHECK(t->Is(Type::Signed32()));
156 CHECK(t->Is(Type::Unsigned32()));
157 CHECK(t->Is(Type::SignedSmall()));
158 CHECK(t->Is(Type::UnsignedSmall()));
159}
160
161
162TEST(OneConstant2) {
163 JSConstantCacheTester T;
164
165 Node* one = T.Constant(1);
166
167 CHECK_EQ(IrOpcode::kNumberConstant, one->opcode());
168 CHECK_EQ(one, T.OneConstant());
169 CHECK_EQ(one, T.Constant(1.0));
170 CHECK_NE(one, T.Constant(1.01));
171 CHECK_NE(one, T.Constant(-1.01));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000172 CHECK_NE(one, T.Constant(std::numeric_limits<double>::quiet_NaN()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000173 CHECK_NE(one, T.Float64Constant(1.0));
174 CHECK_NE(one, T.Int32Constant(1));
175
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000176 Type* t = T.TypeOf(one);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000177
178 CHECK(t->Is(Type::Number()));
179 CHECK(t->Is(Type::Integral32()));
180 CHECK(t->Is(Type::Signed32()));
181 CHECK(t->Is(Type::Unsigned32()));
182 CHECK(t->Is(Type::SignedSmall()));
183 CHECK(t->Is(Type::UnsignedSmall()));
184}
185
186
187TEST(Canonicalizations) {
188 JSConstantCacheTester T;
189
190 CHECK_EQ(T.ZeroConstant(), T.ZeroConstant());
191 CHECK_EQ(T.UndefinedConstant(), T.UndefinedConstant());
192 CHECK_EQ(T.TheHoleConstant(), T.TheHoleConstant());
193 CHECK_EQ(T.TrueConstant(), T.TrueConstant());
194 CHECK_EQ(T.FalseConstant(), T.FalseConstant());
195 CHECK_EQ(T.NullConstant(), T.NullConstant());
196 CHECK_EQ(T.ZeroConstant(), T.ZeroConstant());
197 CHECK_EQ(T.OneConstant(), T.OneConstant());
198 CHECK_EQ(T.NaNConstant(), T.NaNConstant());
199}
200
201
202TEST(NoAliasing) {
203 JSConstantCacheTester T;
204
205 Node* nodes[] = {T.UndefinedConstant(), T.TheHoleConstant(), T.TrueConstant(),
206 T.FalseConstant(), T.NullConstant(), T.ZeroConstant(),
207 T.OneConstant(), T.NaNConstant(), T.Constant(21),
208 T.Constant(22.2)};
209
210 for (size_t i = 0; i < arraysize(nodes); i++) {
211 for (size_t j = 0; j < arraysize(nodes); j++) {
212 if (i != j) CHECK_NE(nodes[i], nodes[j]);
213 }
214 }
215}
216
217
218TEST(CanonicalizingNumbers) {
219 JSConstantCacheTester T;
220
221 FOR_FLOAT64_INPUTS(i) {
222 Node* node = T.Constant(*i);
223 for (int j = 0; j < 5; j++) {
224 CHECK_EQ(node, T.Constant(*i));
225 }
226 }
227}
228
229
230TEST(NumberTypes) {
231 JSConstantCacheTester T;
232
233 FOR_FLOAT64_INPUTS(i) {
234 double value = *i;
235 Node* node = T.Constant(value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000236 CHECK(T.TypeOf(node)->Is(Type::Of(value, T.main_zone())));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000237 }
238}
239
240
241TEST(HeapNumbers) {
242 JSConstantCacheTester T;
243
244 FOR_FLOAT64_INPUTS(i) {
245 double value = *i;
246 Handle<Object> num = T.factory()->NewNumber(value);
247 Handle<HeapNumber> heap = T.factory()->NewHeapNumber(value);
248 Node* node1 = T.Constant(value);
249 Node* node2 = T.Constant(num);
250 Node* node3 = T.Constant(heap);
251 CHECK_EQ(node1, node2);
252 CHECK_EQ(node1, node3);
253 }
254}
255
256
257TEST(OddballHandle) {
258 JSConstantCacheTester T;
259
260 CHECK_EQ(T.UndefinedConstant(), T.Constant(T.factory()->undefined_value()));
261 CHECK_EQ(T.TheHoleConstant(), T.Constant(T.factory()->the_hole_value()));
262 CHECK_EQ(T.TrueConstant(), T.Constant(T.factory()->true_value()));
263 CHECK_EQ(T.FalseConstant(), T.Constant(T.factory()->false_value()));
264 CHECK_EQ(T.NullConstant(), T.Constant(T.factory()->null_value()));
265 CHECK_EQ(T.NaNConstant(), T.Constant(T.factory()->nan_value()));
266}
267
268
269TEST(OddballValues) {
270 JSConstantCacheTester T;
271
272 CHECK_EQ(*T.factory()->undefined_value(), *T.handle(T.UndefinedConstant()));
273 CHECK_EQ(*T.factory()->the_hole_value(), *T.handle(T.TheHoleConstant()));
274 CHECK_EQ(*T.factory()->true_value(), *T.handle(T.TrueConstant()));
275 CHECK_EQ(*T.factory()->false_value(), *T.handle(T.FalseConstant()));
276 CHECK_EQ(*T.factory()->null_value(), *T.handle(T.NullConstant()));
277}
278
279
280TEST(OddballTypes) {
281 JSConstantCacheTester T;
282
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000283 CHECK(T.TypeOf(T.UndefinedConstant())->Is(Type::Undefined()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000284 // TODO(dcarney): figure this out.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000285 // CHECK(T.TypeOf(T.TheHoleConstant())->Is(Type::Internal()));
286 CHECK(T.TypeOf(T.TrueConstant())->Is(Type::Boolean()));
287 CHECK(T.TypeOf(T.FalseConstant())->Is(Type::Boolean()));
288 CHECK(T.TypeOf(T.NullConstant())->Is(Type::Null()));
289 CHECK(T.TypeOf(T.ZeroConstant())->Is(Type::Number()));
290 CHECK(T.TypeOf(T.OneConstant())->Is(Type::Number()));
291 CHECK(T.TypeOf(T.NaNConstant())->Is(Type::NaN()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000292}
293
294
295TEST(ExternalReferences) {
296 // TODO(titzer): test canonicalization of external references.
297}
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400298
299
300static bool Contains(NodeVector* nodes, Node* n) {
301 for (size_t i = 0; i < nodes->size(); i++) {
302 if (nodes->at(i) == n) return true;
303 }
304 return false;
305}
306
307
308static void CheckGetCachedNodesContains(JSConstantCacheTester* T, Node* n) {
309 NodeVector nodes(T->main_zone());
310 T->GetCachedNodes(&nodes);
311 CHECK(Contains(&nodes, n));
312}
313
314
315TEST(JSGraph_GetCachedNodes1) {
316 JSConstantCacheTester T;
317 CheckGetCachedNodesContains(&T, T.TrueConstant());
318 CheckGetCachedNodesContains(&T, T.UndefinedConstant());
319 CheckGetCachedNodesContains(&T, T.TheHoleConstant());
320 CheckGetCachedNodesContains(&T, T.TrueConstant());
321 CheckGetCachedNodesContains(&T, T.FalseConstant());
322 CheckGetCachedNodesContains(&T, T.NullConstant());
323 CheckGetCachedNodesContains(&T, T.ZeroConstant());
324 CheckGetCachedNodesContains(&T, T.OneConstant());
325 CheckGetCachedNodesContains(&T, T.NaNConstant());
326}
327
328
329TEST(JSGraph_GetCachedNodes_int32) {
330 JSConstantCacheTester T;
331
332 int32_t constants[] = {0, 1, 1, 1, 1, 2, 3, 4, 11, 12, 13,
333 14, 55, -55, -44, -33, -22, -11, 16, 16, 17, 17,
334 18, 18, 19, 19, 20, 20, 21, 21, 22, 23, 24,
335 25, 15, 30, 31, 45, 46, 47, 48};
336
337 for (size_t i = 0; i < arraysize(constants); i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000338 size_t count_before = T.graph()->NodeCount();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400339 NodeVector nodes_before(T.main_zone());
340 T.GetCachedNodes(&nodes_before);
341 Node* n = T.Int32Constant(constants[i]);
342 if (n->id() < count_before) {
343 // An old ID indicates a cached node. It should have been in the set.
344 CHECK(Contains(&nodes_before, n));
345 }
346 // Old or new, it should be in the cached set afterwards.
347 CheckGetCachedNodesContains(&T, n);
348 }
349}
350
351
352TEST(JSGraph_GetCachedNodes_float64) {
353 JSConstantCacheTester T;
354
355 double constants[] = {0, 11.1, 12.2, 13, 14, 55.5, -55.5, -44.4,
356 -33, -22, -11, 0, 11.1, 11.1, 12.3, 12.3,
357 11, 11, -33.3, -33.3, -22, -11};
358
359 for (size_t i = 0; i < arraysize(constants); i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000360 size_t count_before = T.graph()->NodeCount();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400361 NodeVector nodes_before(T.main_zone());
362 T.GetCachedNodes(&nodes_before);
363 Node* n = T.Float64Constant(constants[i]);
364 if (n->id() < count_before) {
365 // An old ID indicates a cached node. It should have been in the set.
366 CHECK(Contains(&nodes_before, n));
367 }
368 // Old or new, it should be in the cached set afterwards.
369 CheckGetCachedNodesContains(&T, n);
370 }
371}
372
373
374TEST(JSGraph_GetCachedNodes_int64) {
375 JSConstantCacheTester T;
376
377 int32_t constants[] = {0, 11, 12, 13, 14, 55, -55, -44, -33,
378 -22, -11, 16, 16, 17, 17, 18, 18, 19,
379 19, 20, 20, 21, 21, 22, 23, 24, 25};
380
381 for (size_t i = 0; i < arraysize(constants); i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000382 size_t count_before = T.graph()->NodeCount();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400383 NodeVector nodes_before(T.main_zone());
384 T.GetCachedNodes(&nodes_before);
385 Node* n = T.Int64Constant(constants[i]);
386 if (n->id() < count_before) {
387 // An old ID indicates a cached node. It should have been in the set.
388 CHECK(Contains(&nodes_before, n));
389 }
390 // Old or new, it should be in the cached set afterwards.
391 CheckGetCachedNodesContains(&T, n);
392 }
393}
394
395
396TEST(JSGraph_GetCachedNodes_number) {
397 JSConstantCacheTester T;
398
399 double constants[] = {0, 11.1, 12.2, 13, 14, 55.5, -55.5, -44.4,
400 -33, -22, -11, 0, 11.1, 11.1, 12.3, 12.3,
401 11, 11, -33.3, -33.3, -22, -11};
402
403 for (size_t i = 0; i < arraysize(constants); i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000404 size_t count_before = T.graph()->NodeCount();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400405 NodeVector nodes_before(T.main_zone());
406 T.GetCachedNodes(&nodes_before);
407 Node* n = T.Constant(constants[i]);
408 if (n->id() < count_before) {
409 // An old ID indicates a cached node. It should have been in the set.
410 CHECK(Contains(&nodes_before, n));
411 }
412 // Old or new, it should be in the cached set afterwards.
413 CheckGetCachedNodesContains(&T, n);
414 }
415}
416
417
418TEST(JSGraph_GetCachedNodes_external) {
419 JSConstantCacheTester T;
420
421 ExternalReference constants[] = {ExternalReference::address_of_min_int(),
422 ExternalReference::address_of_min_int(),
423 ExternalReference::address_of_min_int(),
424 ExternalReference::address_of_one_half(),
425 ExternalReference::address_of_one_half(),
426 ExternalReference::address_of_min_int(),
427 ExternalReference::address_of_the_hole_nan(),
428 ExternalReference::address_of_one_half()};
429
430 for (size_t i = 0; i < arraysize(constants); i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000431 size_t count_before = T.graph()->NodeCount();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400432 NodeVector nodes_before(T.main_zone());
433 T.GetCachedNodes(&nodes_before);
434 Node* n = T.ExternalConstant(constants[i]);
435 if (n->id() < count_before) {
436 // An old ID indicates a cached node. It should have been in the set.
437 CHECK(Contains(&nodes_before, n));
438 }
439 // Old or new, it should be in the cached set afterwards.
440 CheckGetCachedNodesContains(&T, n);
441 }
442}
443
444
445TEST(JSGraph_GetCachedNodes_together) {
446 JSConstantCacheTester T;
447
448 Node* constants[] = {
449 T.TrueConstant(),
450 T.UndefinedConstant(),
451 T.TheHoleConstant(),
452 T.TrueConstant(),
453 T.FalseConstant(),
454 T.NullConstant(),
455 T.ZeroConstant(),
456 T.OneConstant(),
457 T.NaNConstant(),
458 T.Int32Constant(0),
459 T.Int32Constant(1),
460 T.Int64Constant(-2),
461 T.Int64Constant(-4),
462 T.Float64Constant(0.9),
463 T.Float64Constant(V8_INFINITY),
464 T.Constant(0.99),
465 T.Constant(1.11),
466 T.ExternalConstant(ExternalReference::address_of_one_half())};
467
468 NodeVector nodes(T.main_zone());
469 T.GetCachedNodes(&nodes);
470
471 for (size_t i = 0; i < arraysize(constants); i++) {
472 CHECK(Contains(&nodes, constants[i]));
473 }
474}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000475
476} // namespace compiler
477} // namespace internal
478} // namespace v8