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 "src/v8.h" | 5 #include "src/v8.h" |
6 #include "test/cctest/cctest.h" | 6 #include "test/cctest/cctest.h" |
7 | 7 |
8 #include "src/compiler/graph-inl.h" | 8 #include "src/compiler/graph-inl.h" |
9 #include "src/compiler/js-typed-lowering.h" | 9 #include "src/compiler/js-typed-lowering.h" |
10 #include "src/compiler/node-properties-inl.h" | 10 #include "src/compiler/node-properties-inl.h" |
(...skipping 15 matching lines...) Expand all Loading... |
26 common(main_zone()), | 26 common(main_zone()), |
27 graph(main_zone()), | 27 graph(main_zone()), |
28 typer(main_zone()), | 28 typer(main_zone()), |
29 context_node(NULL) { | 29 context_node(NULL) { |
30 typer.DecorateGraph(&graph); | 30 typer.DecorateGraph(&graph); |
31 Node* s = graph.NewNode(common.Start(num_parameters)); | 31 Node* s = graph.NewNode(common.Start(num_parameters)); |
32 graph.SetStart(s); | 32 graph.SetStart(s); |
33 } | 33 } |
34 | 34 |
35 Isolate* isolate; | 35 Isolate* isolate; |
36 Operator* binop; | 36 const Operator* binop; |
37 Operator* unop; | 37 const Operator* unop; |
38 JSOperatorBuilder javascript; | 38 JSOperatorBuilder javascript; |
39 MachineOperatorBuilder machine; | 39 MachineOperatorBuilder machine; |
40 SimplifiedOperatorBuilder simplified; | 40 SimplifiedOperatorBuilder simplified; |
41 CommonOperatorBuilder common; | 41 CommonOperatorBuilder common; |
42 Graph graph; | 42 Graph graph; |
43 Typer typer; | 43 Typer typer; |
44 Node* context_node; | 44 Node* context_node; |
45 | 45 |
46 Node* Parameter(Type* t, int32_t index = 0) { | 46 Node* Parameter(Type* t, int32_t index = 0) { |
47 Node* n = graph.NewNode(common.Parameter(index), graph.start()); | 47 Node* n = graph.NewNode(common.Parameter(index), graph.start()); |
(...skipping 18 matching lines...) Expand all Loading... |
66 return context_node; | 66 return context_node; |
67 } | 67 } |
68 | 68 |
69 Node* control() { return start(); } | 69 Node* control() { return start(); } |
70 | 70 |
71 void CheckPureBinop(IrOpcode::Value expected, Node* node) { | 71 void CheckPureBinop(IrOpcode::Value expected, Node* node) { |
72 CHECK_EQ(expected, node->opcode()); | 72 CHECK_EQ(expected, node->opcode()); |
73 CHECK_EQ(2, node->InputCount()); // should not have context, effect, etc. | 73 CHECK_EQ(2, node->InputCount()); // should not have context, effect, etc. |
74 } | 74 } |
75 | 75 |
76 void CheckPureBinop(Operator* expected, Node* node) { | 76 void CheckPureBinop(const Operator* expected, Node* node) { |
77 CHECK_EQ(expected->opcode(), node->op()->opcode()); | 77 CHECK_EQ(expected->opcode(), node->op()->opcode()); |
78 CHECK_EQ(2, node->InputCount()); // should not have context, effect, etc. | 78 CHECK_EQ(2, node->InputCount()); // should not have context, effect, etc. |
79 } | 79 } |
80 | 80 |
81 Node* ReduceUnop(Operator* op, Type* input_type) { | 81 Node* ReduceUnop(const Operator* op, Type* input_type) { |
82 return reduce(Unop(op, Parameter(input_type))); | 82 return reduce(Unop(op, Parameter(input_type))); |
83 } | 83 } |
84 | 84 |
85 Node* ReduceBinop(Operator* op, Type* left_type, Type* right_type) { | 85 Node* ReduceBinop(const Operator* op, Type* left_type, Type* right_type) { |
86 return reduce(Binop(op, Parameter(left_type, 0), Parameter(right_type, 1))); | 86 return reduce(Binop(op, Parameter(left_type, 0), Parameter(right_type, 1))); |
87 } | 87 } |
88 | 88 |
89 Node* Binop(Operator* op, Node* left, Node* right) { | 89 Node* Binop(const Operator* op, Node* left, Node* right) { |
90 // JS binops also require context, effect, and control | 90 // JS binops also require context, effect, and control |
91 return graph.NewNode(op, left, right, context(), start(), control()); | 91 return graph.NewNode(op, left, right, context(), start(), control()); |
92 } | 92 } |
93 | 93 |
94 Node* Unop(Operator* op, Node* input) { | 94 Node* Unop(const Operator* op, Node* input) { |
95 // JS unops also require context, effect, and control | 95 // JS unops also require context, effect, and control |
96 return graph.NewNode(op, input, context(), start(), control()); | 96 return graph.NewNode(op, input, context(), start(), control()); |
97 } | 97 } |
98 | 98 |
99 Node* UseForEffect(Node* node) { | 99 Node* UseForEffect(Node* node) { |
100 // TODO(titzer): use EffectPhi after fixing EffectCount | 100 // TODO(titzer): use EffectPhi after fixing EffectCount |
101 return graph.NewNode(javascript.ToNumber(), node, context(), node, | 101 return graph.NewNode(javascript.ToNumber(), node, context(), node, |
102 control()); | 102 control()); |
103 } | 103 } |
104 | 104 |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
199 | 199 |
200 R.CheckPureBinop(IrOpcode::kNumberAdd, r); | 200 R.CheckPureBinop(IrOpcode::kNumberAdd, r); |
201 CHECK_EQ(p0, r->InputAt(0)); | 201 CHECK_EQ(p0, r->InputAt(0)); |
202 CHECK_EQ(p1, r->InputAt(1)); | 202 CHECK_EQ(p1, r->InputAt(1)); |
203 } | 203 } |
204 } | 204 } |
205 | 205 |
206 | 206 |
207 TEST(NumberBinops) { | 207 TEST(NumberBinops) { |
208 JSTypedLoweringTester R; | 208 JSTypedLoweringTester R; |
209 Operator* ops[] = { | 209 const Operator* ops[] = { |
210 R.javascript.Add(), R.simplified.NumberAdd(), | 210 R.javascript.Add(), R.simplified.NumberAdd(), |
211 R.javascript.Subtract(), R.simplified.NumberSubtract(), | 211 R.javascript.Subtract(), R.simplified.NumberSubtract(), |
212 R.javascript.Multiply(), R.simplified.NumberMultiply(), | 212 R.javascript.Multiply(), R.simplified.NumberMultiply(), |
213 R.javascript.Divide(), R.simplified.NumberDivide(), | 213 R.javascript.Divide(), R.simplified.NumberDivide(), |
214 R.javascript.Modulus(), R.simplified.NumberModulus(), | 214 R.javascript.Modulus(), R.simplified.NumberModulus(), |
215 }; | 215 }; |
216 | 216 |
217 for (size_t i = 0; i < arraysize(kNumberTypes); ++i) { | 217 for (size_t i = 0; i < arraysize(kNumberTypes); ++i) { |
218 Node* p0 = R.Parameter(kNumberTypes[i], 0); | 218 Node* p0 = R.Parameter(kNumberTypes[i], 0); |
219 | 219 |
(...skipping 26 matching lines...) Expand all Loading... |
246 } else { | 246 } else { |
247 CHECK_EQ(NumberToI32(is_signed), new_input->opcode()); | 247 CHECK_EQ(NumberToI32(is_signed), new_input->opcode()); |
248 } | 248 } |
249 } | 249 } |
250 | 250 |
251 | 251 |
252 // A helper class for testing lowering of bitwise shift operators. | 252 // A helper class for testing lowering of bitwise shift operators. |
253 class JSBitwiseShiftTypedLoweringTester : public JSTypedLoweringTester { | 253 class JSBitwiseShiftTypedLoweringTester : public JSTypedLoweringTester { |
254 public: | 254 public: |
255 static const int kNumberOps = 6; | 255 static const int kNumberOps = 6; |
256 Operator* ops[kNumberOps]; | 256 const Operator* ops[kNumberOps]; |
257 bool signedness[kNumberOps]; | 257 bool signedness[kNumberOps]; |
258 | 258 |
259 JSBitwiseShiftTypedLoweringTester() { | 259 JSBitwiseShiftTypedLoweringTester() { |
260 int i = 0; | 260 int i = 0; |
261 set(i++, javascript.ShiftLeft(), true); | 261 set(i++, javascript.ShiftLeft(), true); |
262 set(i++, machine.Word32Shl(), false); | 262 set(i++, machine.Word32Shl(), false); |
263 set(i++, javascript.ShiftRight(), true); | 263 set(i++, javascript.ShiftRight(), true); |
264 set(i++, machine.Word32Sar(), false); | 264 set(i++, machine.Word32Sar(), false); |
265 set(i++, javascript.ShiftRightLogical(), false); | 265 set(i++, javascript.ShiftRightLogical(), false); |
266 set(i++, machine.Word32Shr(), false); | 266 set(i++, machine.Word32Shr(), false); |
267 } | 267 } |
268 | 268 |
269 private: | 269 private: |
270 void set(int idx, Operator* op, bool s) { | 270 void set(int idx, const Operator* op, bool s) { |
271 ops[idx] = op; | 271 ops[idx] = op; |
272 signedness[idx] = s; | 272 signedness[idx] = s; |
273 } | 273 } |
274 }; | 274 }; |
275 | 275 |
276 | 276 |
277 TEST(Int32BitwiseShifts) { | 277 TEST(Int32BitwiseShifts) { |
278 JSBitwiseShiftTypedLoweringTester R; | 278 JSBitwiseShiftTypedLoweringTester R; |
279 | 279 |
280 Type* types[] = { | 280 Type* types[] = { |
(...skipping 25 matching lines...) Expand all Loading... |
306 } | 306 } |
307 } | 307 } |
308 } | 308 } |
309 } | 309 } |
310 | 310 |
311 | 311 |
312 // A helper class for testing lowering of bitwise operators. | 312 // A helper class for testing lowering of bitwise operators. |
313 class JSBitwiseTypedLoweringTester : public JSTypedLoweringTester { | 313 class JSBitwiseTypedLoweringTester : public JSTypedLoweringTester { |
314 public: | 314 public: |
315 static const int kNumberOps = 6; | 315 static const int kNumberOps = 6; |
316 Operator* ops[kNumberOps]; | 316 const Operator* ops[kNumberOps]; |
317 bool signedness[kNumberOps]; | 317 bool signedness[kNumberOps]; |
318 | 318 |
319 JSBitwiseTypedLoweringTester() { | 319 JSBitwiseTypedLoweringTester() { |
320 int i = 0; | 320 int i = 0; |
321 set(i++, javascript.BitwiseOr(), true); | 321 set(i++, javascript.BitwiseOr(), true); |
322 set(i++, machine.Word32Or(), true); | 322 set(i++, machine.Word32Or(), true); |
323 set(i++, javascript.BitwiseXor(), true); | 323 set(i++, javascript.BitwiseXor(), true); |
324 set(i++, machine.Word32Xor(), true); | 324 set(i++, machine.Word32Xor(), true); |
325 set(i++, javascript.BitwiseAnd(), true); | 325 set(i++, javascript.BitwiseAnd(), true); |
326 set(i++, machine.Word32And(), true); | 326 set(i++, machine.Word32And(), true); |
327 } | 327 } |
328 | 328 |
329 private: | 329 private: |
330 void set(int idx, Operator* op, bool s) { | 330 void set(int idx, const Operator* op, bool s) { |
331 ops[idx] = op; | 331 ops[idx] = op; |
332 signedness[idx] = s; | 332 signedness[idx] = s; |
333 } | 333 } |
334 }; | 334 }; |
335 | 335 |
336 | 336 |
337 TEST(Int32BitwiseBinops) { | 337 TEST(Int32BitwiseBinops) { |
338 JSBitwiseTypedLoweringTester R; | 338 JSBitwiseTypedLoweringTester R; |
339 | 339 |
340 Type* types[] = { | 340 Type* types[] = { |
(...skipping 18 matching lines...) Expand all Loading... |
359 CheckToI32(p0, r->InputAt(0), R.signedness[k]); | 359 CheckToI32(p0, r->InputAt(0), R.signedness[k]); |
360 CheckToI32(p1, r->InputAt(1), R.signedness[k + 1]); | 360 CheckToI32(p1, r->InputAt(1), R.signedness[k + 1]); |
361 } | 361 } |
362 } | 362 } |
363 } | 363 } |
364 } | 364 } |
365 | 365 |
366 | 366 |
367 TEST(JSToNumber1) { | 367 TEST(JSToNumber1) { |
368 JSTypedLoweringTester R; | 368 JSTypedLoweringTester R; |
369 Operator* ton = R.javascript.ToNumber(); | 369 const Operator* ton = R.javascript.ToNumber(); |
370 | 370 |
371 for (size_t i = 0; i < arraysize(kNumberTypes); i++) { // ToNumber(number) | 371 for (size_t i = 0; i < arraysize(kNumberTypes); i++) { // ToNumber(number) |
372 Node* r = R.ReduceUnop(ton, kNumberTypes[i]); | 372 Node* r = R.ReduceUnop(ton, kNumberTypes[i]); |
373 CHECK_EQ(IrOpcode::kParameter, r->opcode()); | 373 CHECK_EQ(IrOpcode::kParameter, r->opcode()); |
374 } | 374 } |
375 | 375 |
376 { // ToNumber(undefined) | 376 { // ToNumber(undefined) |
377 Node* r = R.ReduceUnop(ton, Type::Undefined()); | 377 Node* r = R.ReduceUnop(ton, Type::Undefined()); |
378 R.CheckNaN(r); | 378 R.CheckNaN(r); |
379 } | 379 } |
(...skipping 29 matching lines...) Expand all Loading... |
409 CHECK_EQ(n, add->InputAt(0)); | 409 CHECK_EQ(n, add->InputAt(0)); |
410 CHECK_EQ(r, add->InputAt(1)); | 410 CHECK_EQ(r, add->InputAt(1)); |
411 R.CheckEffectInput(R.start(), effect_use); | 411 R.CheckEffectInput(R.start(), effect_use); |
412 } | 412 } |
413 } | 413 } |
414 | 414 |
415 | 415 |
416 TEST(JSToNumberOfConstant) { | 416 TEST(JSToNumberOfConstant) { |
417 JSTypedLoweringTester R; | 417 JSTypedLoweringTester R; |
418 | 418 |
419 Operator* ops[] = {R.common.NumberConstant(0), R.common.NumberConstant(-1), | 419 const Operator* ops[] = { |
420 R.common.NumberConstant(0.1), R.common.Int32Constant(1177), | 420 R.common.NumberConstant(0), R.common.NumberConstant(-1), |
421 R.common.Float64Constant(0.99)}; | 421 R.common.NumberConstant(0.1), R.common.Int32Constant(1177), |
| 422 R.common.Float64Constant(0.99)}; |
422 | 423 |
423 for (size_t i = 0; i < arraysize(ops); i++) { | 424 for (size_t i = 0; i < arraysize(ops); i++) { |
424 Node* n = R.graph.NewNode(ops[i]); | 425 Node* n = R.graph.NewNode(ops[i]); |
425 Node* convert = R.Unop(R.javascript.ToNumber(), n); | 426 Node* convert = R.Unop(R.javascript.ToNumber(), n); |
426 Node* r = R.reduce(convert); | 427 Node* r = R.reduce(convert); |
427 // Note that either outcome below is correct. It only depends on whether | 428 // Note that either outcome below is correct. It only depends on whether |
428 // the types of constants are eagerly computed or only computed by the | 429 // the types of constants are eagerly computed or only computed by the |
429 // typing pass. | 430 // typing pass. |
430 if (NodeProperties::GetBounds(n).upper->Is(Type::Number())) { | 431 if (NodeProperties::GetBounds(n).upper->Is(Type::Number())) { |
431 // If number constants are eagerly typed, then reduction should | 432 // If number constants are eagerly typed, then reduction should |
(...skipping 16 matching lines...) Expand all Loading... |
448 for (size_t i = 0; i < arraysize(others); i++) { | 449 for (size_t i = 0; i < arraysize(others); i++) { |
449 Type* t = Type::Union(Type::Number(), others[i], R.main_zone()); | 450 Type* t = Type::Union(Type::Number(), others[i], R.main_zone()); |
450 Node* r = R.ReduceUnop(R.javascript.ToNumber(), t); | 451 Node* r = R.ReduceUnop(R.javascript.ToNumber(), t); |
451 CHECK_EQ(IrOpcode::kJSToNumber, r->opcode()); | 452 CHECK_EQ(IrOpcode::kJSToNumber, r->opcode()); |
452 } | 453 } |
453 } | 454 } |
454 | 455 |
455 | 456 |
456 TEST(JSToBoolean) { | 457 TEST(JSToBoolean) { |
457 JSTypedLoweringTester R; | 458 JSTypedLoweringTester R; |
458 Operator* op = R.javascript.ToBoolean(); | 459 const Operator* op = R.javascript.ToBoolean(); |
459 | 460 |
460 { // ToBoolean(undefined) | 461 { // ToBoolean(undefined) |
461 Node* r = R.ReduceUnop(op, Type::Undefined()); | 462 Node* r = R.ReduceUnop(op, Type::Undefined()); |
462 R.CheckFalse(r); | 463 R.CheckFalse(r); |
463 } | 464 } |
464 | 465 |
465 { // ToBoolean(null) | 466 { // ToBoolean(null) |
466 Node* r = R.ReduceUnop(op, Type::Null()); | 467 Node* r = R.ReduceUnop(op, Type::Null()); |
467 R.CheckFalse(r); | 468 R.CheckFalse(r); |
468 } | 469 } |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
536 | 537 |
537 | 538 |
538 TEST(JSToString1) { | 539 TEST(JSToString1) { |
539 JSTypedLoweringTester R; | 540 JSTypedLoweringTester R; |
540 | 541 |
541 for (size_t i = 0; i < arraysize(kStringTypes); i++) { | 542 for (size_t i = 0; i < arraysize(kStringTypes); i++) { |
542 Node* r = R.ReduceUnop(R.javascript.ToString(), kStringTypes[i]); | 543 Node* r = R.ReduceUnop(R.javascript.ToString(), kStringTypes[i]); |
543 CHECK_EQ(IrOpcode::kParameter, r->opcode()); | 544 CHECK_EQ(IrOpcode::kParameter, r->opcode()); |
544 } | 545 } |
545 | 546 |
546 Operator* op = R.javascript.ToString(); | 547 const Operator* op = R.javascript.ToString(); |
547 | 548 |
548 { // ToString(undefined) => "undefined" | 549 { // ToString(undefined) => "undefined" |
549 Node* r = R.ReduceUnop(op, Type::Undefined()); | 550 Node* r = R.ReduceUnop(op, Type::Undefined()); |
550 R.CheckHandle(R.isolate->factory()->undefined_string(), r); | 551 R.CheckHandle(R.isolate->factory()->undefined_string(), r); |
551 } | 552 } |
552 | 553 |
553 { // ToString(null) => "null" | 554 { // ToString(null) => "null" |
554 Node* r = R.ReduceUnop(op, Type::Null()); | 555 Node* r = R.ReduceUnop(op, Type::Null()); |
555 R.CheckHandle(R.isolate->factory()->null_string(), r); | 556 R.CheckHandle(R.isolate->factory()->null_string(), r); |
556 } | 557 } |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
603 CHECK_EQ(n, add->InputAt(0)); | 604 CHECK_EQ(n, add->InputAt(0)); |
604 CHECK_EQ(r, add->InputAt(1)); | 605 CHECK_EQ(r, add->InputAt(1)); |
605 R.CheckEffectInput(R.start(), effect_use); | 606 R.CheckEffectInput(R.start(), effect_use); |
606 } | 607 } |
607 } | 608 } |
608 | 609 |
609 | 610 |
610 TEST(StringComparison) { | 611 TEST(StringComparison) { |
611 JSTypedLoweringTester R; | 612 JSTypedLoweringTester R; |
612 | 613 |
613 Operator* ops[] = { | 614 const Operator* ops[] = { |
614 R.javascript.LessThan(), R.simplified.StringLessThan(), | 615 R.javascript.LessThan(), R.simplified.StringLessThan(), |
615 R.javascript.LessThanOrEqual(), R.simplified.StringLessThanOrEqual(), | 616 R.javascript.LessThanOrEqual(), R.simplified.StringLessThanOrEqual(), |
616 R.javascript.GreaterThan(), R.simplified.StringLessThan(), | 617 R.javascript.GreaterThan(), R.simplified.StringLessThan(), |
617 R.javascript.GreaterThanOrEqual(), R.simplified.StringLessThanOrEqual()}; | 618 R.javascript.GreaterThanOrEqual(), R.simplified.StringLessThanOrEqual()}; |
618 | 619 |
619 for (size_t i = 0; i < arraysize(kStringTypes); i++) { | 620 for (size_t i = 0; i < arraysize(kStringTypes); i++) { |
620 Node* p0 = R.Parameter(kStringTypes[i], 0); | 621 Node* p0 = R.Parameter(kStringTypes[i], 0); |
621 for (size_t j = 0; j < arraysize(kStringTypes); j++) { | 622 for (size_t j = 0; j < arraysize(kStringTypes); j++) { |
622 Node* p1 = R.Parameter(kStringTypes[j], 1); | 623 Node* p1 = R.Parameter(kStringTypes[j], 1); |
623 | 624 |
(...skipping 24 matching lines...) Expand all Loading... |
648 if (converted->opcode() == IrOpcode::kNumberConstant) return; | 649 if (converted->opcode() == IrOpcode::kNumberConstant) return; |
649 CHECK_EQ(IrOpcode::kJSToNumber, converted->opcode()); | 650 CHECK_EQ(IrOpcode::kJSToNumber, converted->opcode()); |
650 CHECK_EQ(val, converted->InputAt(0)); | 651 CHECK_EQ(val, converted->InputAt(0)); |
651 } | 652 } |
652 } | 653 } |
653 | 654 |
654 | 655 |
655 TEST(NumberComparison) { | 656 TEST(NumberComparison) { |
656 JSTypedLoweringTester R; | 657 JSTypedLoweringTester R; |
657 | 658 |
658 Operator* ops[] = { | 659 const Operator* ops[] = { |
659 R.javascript.LessThan(), R.simplified.NumberLessThan(), | 660 R.javascript.LessThan(), R.simplified.NumberLessThan(), |
660 R.javascript.LessThanOrEqual(), R.simplified.NumberLessThanOrEqual(), | 661 R.javascript.LessThanOrEqual(), R.simplified.NumberLessThanOrEqual(), |
661 R.javascript.GreaterThan(), R.simplified.NumberLessThan(), | 662 R.javascript.GreaterThan(), R.simplified.NumberLessThan(), |
662 R.javascript.GreaterThanOrEqual(), R.simplified.NumberLessThanOrEqual()}; | 663 R.javascript.GreaterThanOrEqual(), R.simplified.NumberLessThanOrEqual()}; |
663 | 664 |
664 for (size_t i = 0; i < arraysize(kJSTypes); i++) { | 665 for (size_t i = 0; i < arraysize(kJSTypes); i++) { |
665 Type* t0 = kJSTypes[i]; | 666 Type* t0 = kJSTypes[i]; |
666 if (t0->Is(Type::String())) continue; // skip Type::String | 667 if (t0->Is(Type::String())) continue; // skip Type::String |
667 Node* p0 = R.Parameter(t0, 0); | 668 Node* p0 = R.Parameter(t0, 0); |
668 | 669 |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
748 | 749 |
749 // Check effect chain is correct. | 750 // Check effect chain is correct. |
750 R.CheckEffectInput(R.start(), i0); | 751 R.CheckEffectInput(R.start(), i0); |
751 R.CheckEffectInput(i0, i1); | 752 R.CheckEffectInput(i0, i1); |
752 R.CheckEffectInput(i1, effect_use); | 753 R.CheckEffectInput(i1, effect_use); |
753 } | 754 } |
754 | 755 |
755 | 756 |
756 TEST(UnaryNot) { | 757 TEST(UnaryNot) { |
757 JSTypedLoweringTester R; | 758 JSTypedLoweringTester R; |
758 Operator* opnot = R.javascript.UnaryNot(); | 759 const Operator* opnot = R.javascript.UnaryNot(); |
759 | 760 |
760 for (size_t i = 0; i < arraysize(kJSTypes); i++) { | 761 for (size_t i = 0; i < arraysize(kJSTypes); i++) { |
761 Node* orig = R.Unop(opnot, R.Parameter(kJSTypes[i])); | 762 Node* orig = R.Unop(opnot, R.Parameter(kJSTypes[i])); |
762 Node* use = R.graph.NewNode(R.common.Return(), orig); | 763 Node* use = R.graph.NewNode(R.common.Return(), orig); |
763 Node* r = R.reduce(orig); | 764 Node* r = R.reduce(orig); |
764 // TODO(titzer): test will break if/when js-typed-lowering constant folds. | 765 // TODO(titzer): test will break if/when js-typed-lowering constant folds. |
765 CHECK_EQ(IrOpcode::kBooleanNot, use->InputAt(0)->opcode()); | 766 CHECK_EQ(IrOpcode::kBooleanNot, use->InputAt(0)->opcode()); |
766 | 767 |
767 if (r == orig && orig->opcode() == IrOpcode::kJSToBoolean) { | 768 if (r == orig && orig->opcode() == IrOpcode::kJSToBoolean) { |
768 // The original node was turned into a ToBoolean. | 769 // The original node was turned into a ToBoolean. |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
825 } | 826 } |
826 } | 827 } |
827 | 828 |
828 CHECK_EQ(NULL, effect_use); // should have done all cases above. | 829 CHECK_EQ(NULL, effect_use); // should have done all cases above. |
829 } | 830 } |
830 | 831 |
831 | 832 |
832 // Helper class for testing the reduction of a single binop. | 833 // Helper class for testing the reduction of a single binop. |
833 class BinopEffectsTester { | 834 class BinopEffectsTester { |
834 public: | 835 public: |
835 explicit BinopEffectsTester(Operator* op, Type* t0, Type* t1) | 836 explicit BinopEffectsTester(const Operator* op, Type* t0, Type* t1) |
836 : R(), | 837 : R(), |
837 p0(R.Parameter(t0, 0)), | 838 p0(R.Parameter(t0, 0)), |
838 p1(R.Parameter(t1, 1)), | 839 p1(R.Parameter(t1, 1)), |
839 binop(R.Binop(op, p0, p1)), | 840 binop(R.Binop(op, p0, p1)), |
840 effect_use(R.graph.NewNode(R.common.EffectPhi(1), binop, R.start())) { | 841 effect_use(R.graph.NewNode(R.common.EffectPhi(1), binop, R.start())) { |
841 // Effects should be ordered start -> binop -> effect_use | 842 // Effects should be ordered start -> binop -> effect_use |
842 R.CheckEffectInput(R.start(), binop); | 843 R.CheckEffectInput(R.start(), binop); |
843 R.CheckEffectInput(binop, effect_use); | 844 R.CheckEffectInput(binop, effect_use); |
844 result = R.reduce(binop); | 845 result = R.reduce(binop); |
845 } | 846 } |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
954 Node* p1 = R.Parameter(Type::String()); | 955 Node* p1 = R.Parameter(Type::String()); |
955 | 956 |
956 CheckEqualityReduction(&R, true, p0, p1, IrOpcode::kStringEqual); | 957 CheckEqualityReduction(&R, true, p0, p1, IrOpcode::kStringEqual); |
957 CheckEqualityReduction(&R, false, p0, p1, IrOpcode::kStringEqual); | 958 CheckEqualityReduction(&R, false, p0, p1, IrOpcode::kStringEqual); |
958 } | 959 } |
959 | 960 |
960 | 961 |
961 TEST(RemovePureNumberBinopEffects) { | 962 TEST(RemovePureNumberBinopEffects) { |
962 JSTypedLoweringTester R; | 963 JSTypedLoweringTester R; |
963 | 964 |
964 Operator* ops[] = { | 965 const Operator* ops[] = { |
965 R.javascript.Equal(), R.simplified.NumberEqual(), | 966 R.javascript.Equal(), R.simplified.NumberEqual(), |
966 R.javascript.Add(), R.simplified.NumberAdd(), | 967 R.javascript.Add(), R.simplified.NumberAdd(), |
967 R.javascript.Subtract(), R.simplified.NumberSubtract(), | 968 R.javascript.Subtract(), R.simplified.NumberSubtract(), |
968 R.javascript.Multiply(), R.simplified.NumberMultiply(), | 969 R.javascript.Multiply(), R.simplified.NumberMultiply(), |
969 R.javascript.Divide(), R.simplified.NumberDivide(), | 970 R.javascript.Divide(), R.simplified.NumberDivide(), |
970 R.javascript.Modulus(), R.simplified.NumberModulus(), | 971 R.javascript.Modulus(), R.simplified.NumberModulus(), |
971 R.javascript.LessThan(), R.simplified.NumberLessThan(), | 972 R.javascript.LessThan(), R.simplified.NumberLessThan(), |
972 R.javascript.LessThanOrEqual(), R.simplified.NumberLessThanOrEqual(), | 973 R.javascript.LessThanOrEqual(), R.simplified.NumberLessThanOrEqual(), |
973 }; | 974 }; |
974 | 975 |
975 for (size_t j = 0; j < arraysize(ops); j += 2) { | 976 for (size_t j = 0; j < arraysize(ops); j += 2) { |
976 BinopEffectsTester B(ops[j], Type::Number(), Type::Number()); | 977 BinopEffectsTester B(ops[j], Type::Number(), Type::Number()); |
977 CHECK_EQ(ops[j + 1]->opcode(), B.result->op()->opcode()); | 978 CHECK_EQ(ops[j + 1]->opcode(), B.result->op()->opcode()); |
978 | 979 |
979 B.R.CheckPureBinop(B.result->opcode(), B.result); | 980 B.R.CheckPureBinop(B.result->opcode(), B.result); |
980 | 981 |
981 B.CheckNoOp(0); | 982 B.CheckNoOp(0); |
982 B.CheckNoOp(1); | 983 B.CheckNoOp(1); |
983 | 984 |
984 B.CheckEffectsRemoved(); | 985 B.CheckEffectsRemoved(); |
985 } | 986 } |
986 } | 987 } |
987 | 988 |
988 | 989 |
989 TEST(OrderNumberBinopEffects1) { | 990 TEST(OrderNumberBinopEffects1) { |
990 JSTypedLoweringTester R; | 991 JSTypedLoweringTester R; |
991 | 992 |
992 Operator* ops[] = { | 993 const Operator* ops[] = { |
993 R.javascript.Subtract(), R.simplified.NumberSubtract(), | 994 R.javascript.Subtract(), R.simplified.NumberSubtract(), |
994 R.javascript.Multiply(), R.simplified.NumberMultiply(), | 995 R.javascript.Multiply(), R.simplified.NumberMultiply(), |
995 R.javascript.Divide(), R.simplified.NumberDivide(), | 996 R.javascript.Divide(), R.simplified.NumberDivide(), |
996 R.javascript.Modulus(), R.simplified.NumberModulus(), | 997 R.javascript.Modulus(), R.simplified.NumberModulus(), |
997 }; | 998 }; |
998 | 999 |
999 for (size_t j = 0; j < arraysize(ops); j += 2) { | 1000 for (size_t j = 0; j < arraysize(ops); j += 2) { |
1000 BinopEffectsTester B(ops[j], Type::Object(), Type::String()); | 1001 BinopEffectsTester B(ops[j], Type::Object(), Type::String()); |
1001 CHECK_EQ(ops[j + 1]->opcode(), B.result->op()->opcode()); | 1002 CHECK_EQ(ops[j + 1]->opcode(), B.result->op()->opcode()); |
1002 | 1003 |
1003 Node* i0 = B.CheckConvertedInput(IrOpcode::kJSToNumber, 0, true); | 1004 Node* i0 = B.CheckConvertedInput(IrOpcode::kJSToNumber, 0, true); |
1004 Node* i1 = B.CheckConvertedInput(IrOpcode::kJSToNumber, 1, true); | 1005 Node* i1 = B.CheckConvertedInput(IrOpcode::kJSToNumber, 1, true); |
1005 | 1006 |
1006 CHECK_EQ(B.p0, i0->InputAt(0)); | 1007 CHECK_EQ(B.p0, i0->InputAt(0)); |
1007 CHECK_EQ(B.p1, i1->InputAt(0)); | 1008 CHECK_EQ(B.p1, i1->InputAt(0)); |
1008 | 1009 |
1009 // Effects should be ordered start -> i0 -> i1 -> effect_use | 1010 // Effects should be ordered start -> i0 -> i1 -> effect_use |
1010 B.CheckEffectOrdering(i0, i1); | 1011 B.CheckEffectOrdering(i0, i1); |
1011 } | 1012 } |
1012 } | 1013 } |
1013 | 1014 |
1014 | 1015 |
1015 TEST(OrderNumberBinopEffects2) { | 1016 TEST(OrderNumberBinopEffects2) { |
1016 JSTypedLoweringTester R; | 1017 JSTypedLoweringTester R; |
1017 | 1018 |
1018 Operator* ops[] = { | 1019 const Operator* ops[] = { |
1019 R.javascript.Add(), R.simplified.NumberAdd(), | 1020 R.javascript.Add(), R.simplified.NumberAdd(), |
1020 R.javascript.Subtract(), R.simplified.NumberSubtract(), | 1021 R.javascript.Subtract(), R.simplified.NumberSubtract(), |
1021 R.javascript.Multiply(), R.simplified.NumberMultiply(), | 1022 R.javascript.Multiply(), R.simplified.NumberMultiply(), |
1022 R.javascript.Divide(), R.simplified.NumberDivide(), | 1023 R.javascript.Divide(), R.simplified.NumberDivide(), |
1023 R.javascript.Modulus(), R.simplified.NumberModulus(), | 1024 R.javascript.Modulus(), R.simplified.NumberModulus(), |
1024 }; | 1025 }; |
1025 | 1026 |
1026 for (size_t j = 0; j < arraysize(ops); j += 2) { | 1027 for (size_t j = 0; j < arraysize(ops); j += 2) { |
1027 BinopEffectsTester B(ops[j], Type::Number(), Type::Object()); | 1028 BinopEffectsTester B(ops[j], Type::Number(), Type::Object()); |
1028 | 1029 |
(...skipping 18 matching lines...) Expand all Loading... |
1047 | 1048 |
1048 // Effects should be ordered start -> i0 -> effect_use | 1049 // Effects should be ordered start -> i0 -> effect_use |
1049 B.CheckEffectOrdering(i0); | 1050 B.CheckEffectOrdering(i0); |
1050 } | 1051 } |
1051 } | 1052 } |
1052 | 1053 |
1053 | 1054 |
1054 TEST(OrderCompareEffects) { | 1055 TEST(OrderCompareEffects) { |
1055 JSTypedLoweringTester R; | 1056 JSTypedLoweringTester R; |
1056 | 1057 |
1057 Operator* ops[] = { | 1058 const Operator* ops[] = { |
1058 R.javascript.GreaterThan(), R.simplified.NumberLessThan(), | 1059 R.javascript.GreaterThan(), R.simplified.NumberLessThan(), |
1059 R.javascript.GreaterThanOrEqual(), R.simplified.NumberLessThanOrEqual(), | 1060 R.javascript.GreaterThanOrEqual(), R.simplified.NumberLessThanOrEqual(), |
1060 }; | 1061 }; |
1061 | 1062 |
1062 for (size_t j = 0; j < arraysize(ops); j += 2) { | 1063 for (size_t j = 0; j < arraysize(ops); j += 2) { |
1063 BinopEffectsTester B(ops[j], Type::Object(), Type::String()); | 1064 BinopEffectsTester B(ops[j], Type::Object(), Type::String()); |
1064 CHECK_EQ(ops[j + 1]->opcode(), B.result->op()->opcode()); | 1065 CHECK_EQ(ops[j + 1]->opcode(), B.result->op()->opcode()); |
1065 | 1066 |
1066 Node* i0 = B.CheckConvertedInput(IrOpcode::kJSToNumber, 0, true); | 1067 Node* i0 = B.CheckConvertedInput(IrOpcode::kJSToNumber, 0, true); |
1067 Node* i1 = B.CheckConvertedInput(IrOpcode::kJSToNumber, 1, true); | 1068 Node* i1 = B.CheckConvertedInput(IrOpcode::kJSToNumber, 1, true); |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1180 CHECK_EQ(B.p0, ii0->InputAt(0)); | 1181 CHECK_EQ(B.p0, ii0->InputAt(0)); |
1181 CHECK_EQ(B.p1, ii1->InputAt(0)); | 1182 CHECK_EQ(B.p1, ii1->InputAt(0)); |
1182 | 1183 |
1183 B.CheckEffectOrdering(ii0, ii1); | 1184 B.CheckEffectOrdering(ii0, ii1); |
1184 } | 1185 } |
1185 } | 1186 } |
1186 | 1187 |
1187 | 1188 |
1188 TEST(UnaryNotEffects) { | 1189 TEST(UnaryNotEffects) { |
1189 JSTypedLoweringTester R; | 1190 JSTypedLoweringTester R; |
1190 Operator* opnot = R.javascript.UnaryNot(); | 1191 const Operator* opnot = R.javascript.UnaryNot(); |
1191 | 1192 |
1192 for (size_t i = 0; i < arraysize(kJSTypes); i++) { | 1193 for (size_t i = 0; i < arraysize(kJSTypes); i++) { |
1193 Node* p0 = R.Parameter(kJSTypes[i], 0); | 1194 Node* p0 = R.Parameter(kJSTypes[i], 0); |
1194 Node* orig = R.Unop(opnot, p0); | 1195 Node* orig = R.Unop(opnot, p0); |
1195 Node* effect_use = R.UseForEffect(orig); | 1196 Node* effect_use = R.UseForEffect(orig); |
1196 Node* value_use = R.graph.NewNode(R.common.Return(), orig); | 1197 Node* value_use = R.graph.NewNode(R.common.Return(), orig); |
1197 Node* r = R.reduce(orig); | 1198 Node* r = R.reduce(orig); |
1198 // TODO(titzer): test will break if/when js-typed-lowering constant folds. | 1199 // TODO(titzer): test will break if/when js-typed-lowering constant folds. |
1199 CHECK_EQ(IrOpcode::kBooleanNot, value_use->InputAt(0)->opcode()); | 1200 CHECK_EQ(IrOpcode::kBooleanNot, value_use->InputAt(0)->opcode()); |
1200 | 1201 |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1292 CHECK_EQ(add_node, other_use->InputAt(0)); | 1293 CHECK_EQ(add_node, other_use->InputAt(0)); |
1293 CHECK_EQ(one, other_use->InputAt(1)); | 1294 CHECK_EQ(one, other_use->InputAt(1)); |
1294 } | 1295 } |
1295 } | 1296 } |
1296 | 1297 |
1297 | 1298 |
1298 TEST(Int32Comparisons) { | 1299 TEST(Int32Comparisons) { |
1299 JSTypedLoweringTester R; | 1300 JSTypedLoweringTester R; |
1300 | 1301 |
1301 struct Entry { | 1302 struct Entry { |
1302 Operator* js_op; | 1303 const Operator* js_op; |
1303 Operator* uint_op; | 1304 const Operator* uint_op; |
1304 Operator* int_op; | 1305 const Operator* int_op; |
1305 Operator* num_op; | 1306 const Operator* num_op; |
1306 bool commute; | 1307 bool commute; |
1307 }; | 1308 }; |
1308 | 1309 |
1309 Entry ops[] = { | 1310 Entry ops[] = { |
1310 {R.javascript.LessThan(), R.machine.Uint32LessThan(), | 1311 {R.javascript.LessThan(), R.machine.Uint32LessThan(), |
1311 R.machine.Int32LessThan(), R.simplified.NumberLessThan(), false}, | 1312 R.machine.Int32LessThan(), R.simplified.NumberLessThan(), false}, |
1312 {R.javascript.LessThanOrEqual(), R.machine.Uint32LessThanOrEqual(), | 1313 {R.javascript.LessThanOrEqual(), R.machine.Uint32LessThanOrEqual(), |
1313 R.machine.Int32LessThanOrEqual(), R.simplified.NumberLessThanOrEqual(), | 1314 R.machine.Int32LessThanOrEqual(), R.simplified.NumberLessThanOrEqual(), |
1314 false}, | 1315 false}, |
1315 {R.javascript.GreaterThan(), R.machine.Uint32LessThan(), | 1316 {R.javascript.GreaterThan(), R.machine.Uint32LessThan(), |
1316 R.machine.Int32LessThan(), R.simplified.NumberLessThan(), true}, | 1317 R.machine.Int32LessThan(), R.simplified.NumberLessThan(), true}, |
1317 {R.javascript.GreaterThanOrEqual(), R.machine.Uint32LessThanOrEqual(), | 1318 {R.javascript.GreaterThanOrEqual(), R.machine.Uint32LessThanOrEqual(), |
1318 R.machine.Int32LessThanOrEqual(), R.simplified.NumberLessThanOrEqual(), | 1319 R.machine.Int32LessThanOrEqual(), R.simplified.NumberLessThanOrEqual(), |
1319 true}}; | 1320 true}}; |
1320 | 1321 |
1321 for (size_t o = 0; o < arraysize(ops); o++) { | 1322 for (size_t o = 0; o < arraysize(ops); o++) { |
1322 for (size_t i = 0; i < arraysize(kNumberTypes); i++) { | 1323 for (size_t i = 0; i < arraysize(kNumberTypes); i++) { |
1323 Type* t0 = kNumberTypes[i]; | 1324 Type* t0 = kNumberTypes[i]; |
1324 Node* p0 = R.Parameter(t0, 0); | 1325 Node* p0 = R.Parameter(t0, 0); |
1325 | 1326 |
1326 for (size_t j = 0; j < arraysize(kNumberTypes); j++) { | 1327 for (size_t j = 0; j < arraysize(kNumberTypes); j++) { |
1327 Type* t1 = kNumberTypes[j]; | 1328 Type* t1 = kNumberTypes[j]; |
1328 Node* p1 = R.Parameter(t1, 1); | 1329 Node* p1 = R.Parameter(t1, 1); |
1329 | 1330 |
1330 Node* cmp = R.Binop(ops[o].js_op, p0, p1); | 1331 Node* cmp = R.Binop(ops[o].js_op, p0, p1); |
1331 Node* r = R.reduce(cmp); | 1332 Node* r = R.reduce(cmp); |
1332 | 1333 |
1333 Operator* expected; | 1334 const Operator* expected; |
1334 if (t0->Is(Type::Unsigned32()) && t1->Is(Type::Unsigned32())) { | 1335 if (t0->Is(Type::Unsigned32()) && t1->Is(Type::Unsigned32())) { |
1335 expected = ops[o].uint_op; | 1336 expected = ops[o].uint_op; |
1336 } else if (t0->Is(Type::Signed32()) && t1->Is(Type::Signed32())) { | 1337 } else if (t0->Is(Type::Signed32()) && t1->Is(Type::Signed32())) { |
1337 expected = ops[o].int_op; | 1338 expected = ops[o].int_op; |
1338 } else { | 1339 } else { |
1339 expected = ops[o].num_op; | 1340 expected = ops[o].num_op; |
1340 } | 1341 } |
1341 R.CheckPureBinop(expected, r); | 1342 R.CheckPureBinop(expected, r); |
1342 if (ops[o].commute) { | 1343 if (ops[o].commute) { |
1343 CHECK_EQ(p1, r->InputAt(0)); | 1344 CHECK_EQ(p1, r->InputAt(0)); |
1344 CHECK_EQ(p0, r->InputAt(1)); | 1345 CHECK_EQ(p0, r->InputAt(1)); |
1345 } else { | 1346 } else { |
1346 CHECK_EQ(p0, r->InputAt(0)); | 1347 CHECK_EQ(p0, r->InputAt(0)); |
1347 CHECK_EQ(p1, r->InputAt(1)); | 1348 CHECK_EQ(p1, r->InputAt(1)); |
1348 } | 1349 } |
1349 } | 1350 } |
1350 } | 1351 } |
1351 } | 1352 } |
1352 } | 1353 } |
OLD | NEW |