OLD | NEW |
---|---|
1 // Copyright 2014 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <limits> | 5 #include <limits> |
6 | 6 |
7 #include "src/v8.h" | 7 #include "src/v8.h" |
8 #include "test/cctest/cctest.h" | 8 #include "test/cctest/cctest.h" |
9 #include "test/cctest/compiler/graph-builder-tester.h" | 9 #include "test/cctest/compiler/graph-builder-tester.h" |
10 #include "test/cctest/compiler/value-helper.h" | |
10 | 11 |
11 #include "src/compiler/node-matchers.h" | 12 #include "src/compiler/node-matchers.h" |
12 #include "src/compiler/representation-change.h" | 13 #include "src/compiler/representation-change.h" |
13 #include "src/compiler/typer.h" | 14 #include "src/compiler/typer.h" |
14 | 15 |
15 using namespace v8::internal; | 16 using namespace v8::internal; |
16 using namespace v8::internal::compiler; | 17 using namespace v8::internal::compiler; |
17 | 18 |
18 namespace v8 { // for friendiness. | 19 namespace v8 { // for friendiness. |
19 namespace internal { | 20 namespace internal { |
(...skipping 24 matching lines...) Expand all Loading... | |
44 JSGraph* jsgraph() { return &jsgraph_; } | 45 JSGraph* jsgraph() { return &jsgraph_; } |
45 RepresentationChanger* changer() { return &changer_; } | 46 RepresentationChanger* changer() { return &changer_; } |
46 | 47 |
47 // TODO(titzer): use ValueChecker / ValueUtil | 48 // TODO(titzer): use ValueChecker / ValueUtil |
48 void CheckInt32Constant(Node* n, int32_t expected) { | 49 void CheckInt32Constant(Node* n, int32_t expected) { |
49 Int32Matcher m(n); | 50 Int32Matcher m(n); |
50 CHECK(m.HasValue()); | 51 CHECK(m.HasValue()); |
51 CHECK_EQ(expected, m.Value()); | 52 CHECK_EQ(expected, m.Value()); |
52 } | 53 } |
53 | 54 |
55 void CheckUint32Constant(Node* n, uint32_t expected) { | |
56 Uint32Matcher m(n); | |
57 CHECK(m.HasValue()); | |
58 CHECK_EQ(static_cast<int>(expected), static_cast<int>(m.Value())); | |
59 } | |
60 | |
61 void CheckFloat64Constant(Node* n, double expected) { | |
62 Float64Matcher m(n); | |
63 CHECK(m.HasValue()); | |
64 CHECK_EQ(expected, m.Value()); | |
65 } | |
66 | |
67 void CheckFloat32Constant(Node* n, float expected) { | |
68 CHECK_EQ(IrOpcode::kFloat32Constant, n->opcode()); | |
69 float fval = OpParameter<float>(n->op()); | |
70 CHECK_EQ(expected, fval); | |
71 } | |
72 | |
54 void CheckHeapConstant(Node* n, HeapObject* expected) { | 73 void CheckHeapConstant(Node* n, HeapObject* expected) { |
55 HeapObjectMatcher<HeapObject> m(n); | 74 HeapObjectMatcher<HeapObject> m(n); |
56 CHECK(m.HasValue()); | 75 CHECK(m.HasValue()); |
57 CHECK_EQ(expected, *m.Value().handle()); | 76 CHECK_EQ(expected, *m.Value().handle()); |
58 } | 77 } |
59 | 78 |
60 void CheckNumberConstant(Node* n, double expected) { | 79 void CheckNumberConstant(Node* n, double expected) { |
61 NumberMatcher m(n); | 80 NumberMatcher m(n); |
62 CHECK_EQ(IrOpcode::kNumberConstant, n->opcode()); | 81 CHECK_EQ(IrOpcode::kNumberConstant, n->opcode()); |
63 CHECK(m.HasValue()); | 82 CHECK(m.HasValue()); |
(...skipping 21 matching lines...) Expand all Loading... | |
85 }; | 104 }; |
86 } | 105 } |
87 } | 106 } |
88 } // namespace v8::internal::compiler | 107 } // namespace v8::internal::compiler |
89 | 108 |
90 | 109 |
91 static const MachineType all_reps[] = {kRepBit, kRepWord32, kRepWord64, | 110 static const MachineType all_reps[] = {kRepBit, kRepWord32, kRepWord64, |
92 kRepFloat32, kRepFloat64, kRepTagged}; | 111 kRepFloat32, kRepFloat64, kRepTagged}; |
93 | 112 |
94 | 113 |
95 // TODO(titzer): lift this to ValueHelper | |
96 static const double double_inputs[] = { | |
97 0.0, -0.0, 1.0, -1.0, 0.1, 1.4, -1.7, | |
98 2, 5, 6, 982983, 888, -999.8, 3.1e7, | |
99 -2e66, 2.3e124, -12e73, V8_INFINITY, -V8_INFINITY}; | |
100 | |
101 | |
102 static const int32_t int32_inputs[] = { | |
103 0, 1, -1, | |
104 2, 5, 6, | |
105 982983, 888, -999, | |
106 65535, static_cast<int32_t>(0xFFFFFFFF), static_cast<int32_t>(0x80000000)}; | |
107 | |
108 | |
109 static const uint32_t uint32_inputs[] = { | |
110 0, 1, static_cast<uint32_t>(-1), 2, 5, 6, | |
111 982983, 888, static_cast<uint32_t>(-999), 65535, 0xFFFFFFFF, 0x80000000}; | |
112 | |
113 | |
114 TEST(BoolToBit_constant) { | 114 TEST(BoolToBit_constant) { |
115 RepresentationChangerTester r; | 115 RepresentationChangerTester r; |
116 | 116 |
117 Node* true_node = r.jsgraph()->TrueConstant(); | 117 Node* true_node = r.jsgraph()->TrueConstant(); |
118 Node* true_bit = | 118 Node* true_bit = |
119 r.changer()->GetRepresentationFor(true_node, kRepTagged, kRepBit); | 119 r.changer()->GetRepresentationFor(true_node, kRepTagged, kRepBit); |
120 r.CheckInt32Constant(true_bit, 1); | 120 r.CheckInt32Constant(true_bit, 1); |
121 | 121 |
122 Node* false_node = r.jsgraph()->FalseConstant(); | 122 Node* false_node = r.jsgraph()->FalseConstant(); |
123 Node* false_bit = | 123 Node* false_bit = |
(...skipping 10 matching lines...) Expand all Loading... | |
134 Node* val = r.changer()->GetRepresentationFor(node, kRepBit, kRepTagged); | 134 Node* val = r.changer()->GetRepresentationFor(node, kRepBit, kRepTagged); |
135 r.CheckHeapConstant(val, i == 0 ? r.isolate()->heap()->false_value() | 135 r.CheckHeapConstant(val, i == 0 ? r.isolate()->heap()->false_value() |
136 : r.isolate()->heap()->true_value()); | 136 : r.isolate()->heap()->true_value()); |
137 } | 137 } |
138 } | 138 } |
139 | 139 |
140 | 140 |
141 TEST(ToTagged_constant) { | 141 TEST(ToTagged_constant) { |
142 RepresentationChangerTester r; | 142 RepresentationChangerTester r; |
143 | 143 |
144 for (size_t i = 0; i < arraysize(double_inputs); i++) { | 144 { |
145 Node* n = r.jsgraph()->Float64Constant(double_inputs[i]); | 145 FOR_FLOAT64_INPUTS(i) { |
146 Node* c = r.changer()->GetRepresentationFor(n, kRepFloat64, kRepTagged); | 146 Node* n = r.jsgraph()->Float64Constant(*i); |
147 r.CheckNumberConstant(c, double_inputs[i]); | 147 Node* c = r.changer()->GetRepresentationFor(n, kRepFloat64, kRepTagged); |
148 } | 148 r.CheckNumberConstant(c, *i); |
149 | 149 } |
150 for (size_t i = 0; i < arraysize(double_inputs); i++) { | 150 } |
151 volatile float fval = static_cast<float>(double_inputs[i]); | 151 |
152 Node* n = r.jsgraph()->Float32Constant(fval); | 152 { |
153 Node* c = r.changer()->GetRepresentationFor(n, kRepFloat32, kRepTagged); | 153 FOR_FLOAT64_INPUTS(i) { |
154 r.CheckNumberConstant(c, fval); | 154 Node* n = r.jsgraph()->Constant(*i); |
155 } | 155 Node* c = r.changer()->GetRepresentationFor(n, kRepFloat64, kRepTagged); |
156 | 156 r.CheckNumberConstant(c, *i); |
157 for (size_t i = 0; i < arraysize(int32_inputs); i++) { | 157 } |
158 Node* n = r.jsgraph()->Int32Constant(int32_inputs[i]); | 158 } |
159 Node* c = r.changer()->GetRepresentationFor(n, kRepWord32 | kTypeInt32, | 159 |
160 kRepTagged); | 160 { |
161 r.CheckNumberConstant(c, static_cast<double>(int32_inputs[i])); | 161 FOR_FLOAT32_INPUTS(i) { |
162 } | 162 Node* n = r.jsgraph()->Float32Constant(*i); |
163 | 163 Node* c = r.changer()->GetRepresentationFor(n, kRepFloat32, kRepTagged); |
164 for (size_t i = 0; i < arraysize(uint32_inputs); i++) { | 164 r.CheckNumberConstant(c, *i); |
165 Node* n = r.jsgraph()->Int32Constant(uint32_inputs[i]); | 165 } |
166 Node* c = r.changer()->GetRepresentationFor(n, kRepWord32 | kTypeUint32, | 166 } |
167 kRepTagged); | 167 |
168 r.CheckNumberConstant(c, static_cast<double>(uint32_inputs[i])); | 168 { |
169 } | 169 FOR_INT32_INPUTS(i) { |
170 } | 170 Node* n = r.jsgraph()->Int32Constant(*i); |
171 | 171 Node* c = r.changer()->GetRepresentationFor(n, kRepWord32 | kTypeInt32, |
172 kRepTagged); | |
173 r.CheckNumberConstant(c, *i); | |
174 } | |
175 } | |
176 | |
177 { | |
178 FOR_UINT32_INPUTS(i) { | |
179 Node* n = r.jsgraph()->Int32Constant(*i); | |
180 Node* c = r.changer()->GetRepresentationFor(n, kRepWord32 | kTypeUint32, | |
181 kRepTagged); | |
182 r.CheckNumberConstant(c, *i); | |
183 } | |
184 } | |
185 } | |
186 | |
187 | |
188 TEST(ToFloat64_constant) { | |
189 RepresentationChangerTester r; | |
190 | |
191 { | |
192 FOR_FLOAT64_INPUTS(i) { | |
193 Node* n = r.jsgraph()->Float64Constant(*i); | |
194 Node* c = r.changer()->GetRepresentationFor(n, kRepFloat64, kRepFloat64); | |
195 CHECK_EQ(n, c); | |
196 } | |
197 } | |
198 | |
199 { | |
200 FOR_FLOAT64_INPUTS(i) { | |
201 Node* n = r.jsgraph()->Constant(*i); | |
202 Node* c = r.changer()->GetRepresentationFor(n, kRepTagged, kRepFloat64); | |
203 r.CheckFloat64Constant(c, *i); | |
204 } | |
205 } | |
206 | |
207 { | |
208 FOR_FLOAT32_INPUTS(i) { | |
209 Node* n = r.jsgraph()->Float32Constant(*i); | |
210 Node* c = r.changer()->GetRepresentationFor(n, kRepFloat32, kRepFloat64); | |
211 r.CheckFloat64Constant(c, *i); | |
212 } | |
213 } | |
214 | |
215 { | |
216 FOR_INT32_INPUTS(i) { | |
217 Node* n = r.jsgraph()->Int32Constant(*i); | |
218 Node* c = r.changer()->GetRepresentationFor(n, kRepWord32 | kTypeInt32, | |
219 kRepFloat64); | |
220 r.CheckFloat64Constant(c, *i); | |
221 } | |
222 } | |
223 | |
224 { | |
225 FOR_UINT32_INPUTS(i) { | |
226 Node* n = r.jsgraph()->Int32Constant(*i); | |
227 Node* c = r.changer()->GetRepresentationFor(n, kRepWord32 | kTypeUint32, | |
228 kRepFloat64); | |
229 r.CheckFloat64Constant(c, *i); | |
230 } | |
231 } | |
232 } | |
233 | |
234 | |
235 static bool IsFloat32Int32(int32_t val) { | |
236 return val >= -(1 << 23) && val <= (1 << 23); | |
237 } | |
238 | |
239 | |
240 static bool IsFloat32Uint32(uint32_t val) { return val <= (1 << 23); } | |
241 | |
242 | |
243 TEST(ToFloat32_constant) { | |
244 RepresentationChangerTester r; | |
245 | |
246 { | |
247 FOR_FLOAT32_INPUTS(i) { | |
248 Node* n = r.jsgraph()->Float32Constant(*i); | |
249 Node* c = r.changer()->GetRepresentationFor(n, kRepFloat32, kRepFloat32); | |
250 CHECK_EQ(n, c); | |
251 } | |
252 } | |
253 | |
254 { | |
255 FOR_FLOAT32_INPUTS(i) { | |
256 Node* n = r.jsgraph()->Constant(*i); | |
257 Node* c = r.changer()->GetRepresentationFor(n, kRepTagged, kRepFloat32); | |
258 r.CheckFloat32Constant(c, *i); | |
259 } | |
260 } | |
261 | |
262 { | |
263 FOR_FLOAT32_INPUTS(i) { | |
264 Node* n = r.jsgraph()->Float64Constant(*i); | |
265 Node* c = r.changer()->GetRepresentationFor(n, kRepFloat64, kRepFloat32); | |
266 r.CheckFloat32Constant(c, *i); | |
267 } | |
268 } | |
269 | |
270 { | |
271 FOR_INT32_INPUTS(i) { | |
272 if (!IsFloat32Int32(*i)) continue; | |
273 Node* n = r.jsgraph()->Int32Constant(*i); | |
274 Node* c = r.changer()->GetRepresentationFor(n, kRepWord32 | kTypeInt32, | |
275 kRepFloat32); | |
276 r.CheckFloat32Constant(c, *i); | |
277 } | |
278 } | |
279 | |
280 { | |
281 FOR_UINT32_INPUTS(i) { | |
282 if (!IsFloat32Uint32(*i)) continue; | |
283 Node* n = r.jsgraph()->Int32Constant(*i); | |
284 Node* c = r.changer()->GetRepresentationFor(n, kRepWord32 | kTypeUint32, | |
285 kRepFloat32); | |
286 r.CheckFloat32Constant(c, *i); | |
287 } | |
288 } | |
289 } | |
290 | |
291 | |
292 TEST(ToInt32_constant) { | |
293 RepresentationChangerTester r; | |
294 | |
295 { | |
296 FOR_INT32_INPUTS(i) { | |
297 Node* n = r.jsgraph()->Int32Constant(*i); | |
298 Node* c = r.changer()->GetRepresentationFor(n, kRepWord32 | kTypeInt32, | |
299 kRepWord32); | |
300 r.CheckInt32Constant(c, *i); | |
301 } | |
302 } | |
303 | |
304 { | |
305 FOR_INT32_INPUTS(i) { | |
306 if (!IsFloat32Int32(*i)) continue; | |
307 Node* n = r.jsgraph()->Float32Constant(*i); | |
308 Node* c = r.changer()->GetRepresentationFor(n, kRepFloat32 | kTypeInt32, | |
309 kRepWord32); | |
310 r.CheckInt32Constant(c, *i); | |
311 } | |
312 } | |
313 | |
314 { | |
315 FOR_INT32_INPUTS(i) { | |
316 Node* n = r.jsgraph()->Float64Constant(*i); | |
317 Node* c = r.changer()->GetRepresentationFor(n, kRepFloat64 | kTypeInt32, | |
318 kRepWord32); | |
319 r.CheckInt32Constant(c, *i); | |
320 } | |
321 } | |
322 | |
323 { | |
324 FOR_INT32_INPUTS(i) { | |
325 Node* n = r.jsgraph()->Constant(*i); | |
326 Node* c = r.changer()->GetRepresentationFor(n, kRepTagged | kTypeInt32, | |
327 kRepWord32); | |
328 r.CheckInt32Constant(c, *i); | |
329 } | |
330 } | |
331 } | |
332 | |
333 | |
334 TEST(ToUint32_constant) { | |
335 RepresentationChangerTester r; | |
336 | |
337 { | |
338 FOR_UINT32_INPUTS(i) { | |
339 Node* n = r.jsgraph()->Int32Constant(*i); | |
340 Node* c = r.changer()->GetRepresentationFor(n, kRepWord32 | kTypeUint32, | |
341 kRepWord32); | |
342 r.CheckInt32Constant(c, *i); | |
Jarin
2014/09/24 15:11:21
Should not this (+ the guys below) be CheckUint32C
titzer
2014/09/24 15:53:08
Good catch. Done.
| |
343 } | |
344 } | |
345 | |
346 { | |
347 FOR_UINT32_INPUTS(i) { | |
348 if (!IsFloat32Uint32(*i)) continue; | |
349 Node* n = r.jsgraph()->Float32Constant(*i); | |
350 Node* c = r.changer()->GetRepresentationFor(n, kRepFloat32 | kTypeUint32, | |
351 kRepWord32); | |
352 r.CheckInt32Constant(c, *i); | |
353 } | |
354 } | |
355 | |
356 { | |
357 FOR_UINT32_INPUTS(i) { | |
358 Node* n = r.jsgraph()->Float64Constant(*i); | |
359 Node* c = r.changer()->GetRepresentationFor(n, kRepFloat64 | kTypeUint32, | |
360 kRepWord32); | |
361 r.CheckInt32Constant(c, *i); | |
362 } | |
363 } | |
364 | |
365 { | |
366 FOR_UINT32_INPUTS(i) { | |
367 Node* n = r.jsgraph()->Constant(static_cast<double>(*i)); | |
368 Node* c = r.changer()->GetRepresentationFor(n, kRepTagged | kTypeUint32, | |
369 kRepWord32); | |
370 r.CheckInt32Constant(c, *i); | |
371 } | |
372 } | |
373 } | |
374 | |
172 | 375 |
173 static void CheckChange(IrOpcode::Value expected, MachineTypeUnion from, | 376 static void CheckChange(IrOpcode::Value expected, MachineTypeUnion from, |
174 MachineTypeUnion to) { | 377 MachineTypeUnion to) { |
175 RepresentationChangerTester r; | 378 RepresentationChangerTester r; |
176 | 379 |
177 Node* n = r.Parameter(); | 380 Node* n = r.Parameter(); |
178 Node* c = r.changer()->GetRepresentationFor(n, from, to); | 381 Node* c = r.changer()->GetRepresentationFor(n, from, to); |
179 | 382 |
180 CHECK_NE(c, n); | 383 CHECK_NE(c, n); |
181 CHECK_EQ(expected, c->opcode()); | 384 CHECK_EQ(expected, c->opcode()); |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
241 kRepWord32); | 444 kRepWord32); |
242 | 445 |
243 // Float32 <-> Tagged require two changes. | 446 // Float32 <-> Tagged require two changes. |
244 CheckTwoChanges(IrOpcode::kChangeFloat32ToFloat64, | 447 CheckTwoChanges(IrOpcode::kChangeFloat32ToFloat64, |
245 IrOpcode::kChangeFloat64ToTagged, kRepFloat32, kRepTagged); | 448 IrOpcode::kChangeFloat64ToTagged, kRepFloat32, kRepTagged); |
246 CheckTwoChanges(IrOpcode::kChangeTaggedToFloat64, | 449 CheckTwoChanges(IrOpcode::kChangeTaggedToFloat64, |
247 IrOpcode::kTruncateFloat64ToFloat32, kRepTagged, kRepFloat32); | 450 IrOpcode::kTruncateFloat64ToFloat32, kRepTagged, kRepFloat32); |
248 } | 451 } |
249 | 452 |
250 | 453 |
251 // TODO(titzer): test constant folding of changes between int/float | |
252 | |
253 | |
254 TEST(SignednessInWord32) { | 454 TEST(SignednessInWord32) { |
255 RepresentationChangerTester r; | 455 RepresentationChangerTester r; |
256 | 456 |
257 // TODO(titzer): assume that uses of a word32 without a sign mean kTypeInt32. | 457 // TODO(titzer): assume that uses of a word32 without a sign mean kTypeInt32. |
258 CheckChange(IrOpcode::kChangeTaggedToInt32, kRepTagged, | 458 CheckChange(IrOpcode::kChangeTaggedToInt32, kRepTagged, |
259 kRepWord32 | kTypeInt32); | 459 kRepWord32 | kTypeInt32); |
260 CheckChange(IrOpcode::kChangeTaggedToUint32, kRepTagged, | 460 CheckChange(IrOpcode::kChangeTaggedToUint32, kRepTagged, |
261 kRepWord32 | kTypeUint32); | 461 kRepWord32 | kTypeUint32); |
262 CheckChange(IrOpcode::kChangeInt32ToFloat64, kRepWord32, kRepFloat64); | 462 CheckChange(IrOpcode::kChangeInt32ToFloat64, kRepWord32, kRepFloat64); |
263 CheckChange(IrOpcode::kChangeFloat64ToInt32, kRepFloat64, kRepWord32); | 463 CheckChange(IrOpcode::kChangeFloat64ToInt32, kRepFloat64, kRepWord32); |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
340 r.CheckTypeError(kRepWord32 | kTypeUint32, kRepWord64); | 540 r.CheckTypeError(kRepWord32 | kTypeUint32, kRepWord64); |
341 | 541 |
342 for (size_t i = 0; i < arraysize(all_reps); i++) { | 542 for (size_t i = 0; i < arraysize(all_reps); i++) { |
343 for (size_t j = 0; j < arraysize(all_reps); j++) { | 543 for (size_t j = 0; j < arraysize(all_reps); j++) { |
344 if (i == j) continue; | 544 if (i == j) continue; |
345 // Only a single from representation is allowed. | 545 // Only a single from representation is allowed. |
346 r.CheckTypeError(all_reps[i] | all_reps[j], kRepTagged); | 546 r.CheckTypeError(all_reps[i] | all_reps[j], kRepTagged); |
347 } | 547 } |
348 } | 548 } |
349 } | 549 } |
OLD | NEW |