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/compiler/access-builder.h" | 5 #include "src/compiler/access-builder.h" |
6 #include "src/compiler/graph-inl.h" | 6 #include "src/compiler/graph-inl.h" |
7 #include "src/compiler/js-builtin-reducer.h" | 7 #include "src/compiler/js-builtin-reducer.h" |
8 #include "src/compiler/js-typed-lowering.h" | 8 #include "src/compiler/js-typed-lowering.h" |
9 #include "src/compiler/node-aux-data-inl.h" | 9 #include "src/compiler/node-aux-data-inl.h" |
10 #include "src/compiler/node-properties-inl.h" | 10 #include "src/compiler/node-properties-inl.h" |
(...skipping 448 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
459 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert); | 459 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert); |
460 } | 460 } |
461 // TODO(turbofan): js-typed-lowering of StrictEqual(mixed types) | 461 // TODO(turbofan): js-typed-lowering of StrictEqual(mixed types) |
462 return NoChange(); | 462 return NoChange(); |
463 } | 463 } |
464 | 464 |
465 | 465 |
466 Reduction JSTypedLowering::ReduceJSToNumberInput(Node* input) { | 466 Reduction JSTypedLowering::ReduceJSToNumberInput(Node* input) { |
467 if (input->opcode() == IrOpcode::kJSToNumber) { | 467 if (input->opcode() == IrOpcode::kJSToNumber) { |
468 // Recursively try to reduce the input first. | 468 // Recursively try to reduce the input first. |
469 Reduction result = ReduceJSToNumberInput(input->InputAt(0)); | 469 Reduction result = ReduceJSToNumber(input); |
470 if (result.Changed()) { | 470 if (result.Changed()) return result; |
471 RelaxEffects(input); | |
472 return result; | |
473 } | |
474 return Changed(input); // JSToNumber(JSToNumber(x)) => JSToNumber(x) | 471 return Changed(input); // JSToNumber(JSToNumber(x)) => JSToNumber(x) |
475 } | 472 } |
476 Type* input_type = NodeProperties::GetBounds(input).upper; | 473 Type* input_type = NodeProperties::GetBounds(input).upper; |
477 if (input_type->Is(Type::Number())) { | 474 if (input_type->Is(Type::Number())) { |
478 // JSToNumber(x:number) => x | 475 // JSToNumber(x:number) => x |
479 return Changed(input); | 476 return Changed(input); |
480 } | 477 } |
481 if (input_type->Is(Type::Undefined())) { | 478 if (input_type->Is(Type::Undefined())) { |
482 // JSToNumber(undefined) => #NaN | 479 // JSToNumber(undefined) => #NaN |
483 return ReplaceWith(jsgraph()->NaNConstant()); | 480 return ReplaceWith(jsgraph()->NaNConstant()); |
484 } | 481 } |
485 if (input_type->Is(Type::Null())) { | 482 if (input_type->Is(Type::Null())) { |
486 // JSToNumber(null) => #0 | 483 // JSToNumber(null) => #0 |
487 return ReplaceWith(jsgraph()->ZeroConstant()); | 484 return ReplaceWith(jsgraph()->ZeroConstant()); |
488 } | 485 } |
489 if (input_type->Is(Type::Boolean())) { | 486 if (input_type->Is(Type::Boolean())) { |
490 // JSToNumber(x:boolean) => BooleanToNumber(x) | 487 // JSToNumber(x:boolean) => BooleanToNumber(x) |
491 return ReplaceWith( | 488 return ReplaceWith( |
492 graph()->NewNode(simplified()->BooleanToNumber(), input)); | 489 graph()->NewNode(simplified()->BooleanToNumber(), input)); |
493 } | 490 } |
494 // TODO(turbofan): js-typed-lowering of ToNumber(x:string) | 491 // TODO(turbofan): js-typed-lowering of ToNumber(x:string) |
495 return NoChange(); | 492 return NoChange(); |
496 } | 493 } |
497 | 494 |
498 | 495 |
| 496 Reduction JSTypedLowering::ReduceJSToNumber(Node* node) { |
| 497 // Try to reduce the input first. |
| 498 Node* const input = node->InputAt(0); |
| 499 Reduction reduction = ReduceJSToNumberInput(input); |
| 500 if (reduction.Changed()) { |
| 501 NodeProperties::ReplaceWithValue(node, reduction.replacement()); |
| 502 return reduction; |
| 503 } |
| 504 Type* const input_type = NodeProperties::GetBounds(input).upper; |
| 505 if (input->opcode() == IrOpcode::kPhi && input_type->Is(Type::Primitive())) { |
| 506 Node* const context = node->InputAt(1); |
| 507 // JSToNumber(phi(x1,...,xn,control):primitive) |
| 508 // => phi(JSToNumber(x1),...,JSToNumber(xn),control):number |
| 509 RelaxEffects(node); |
| 510 int const input_count = input->InputCount() - 1; |
| 511 Node* const control = input->InputAt(input_count); |
| 512 DCHECK_LE(0, input_count); |
| 513 DCHECK(NodeProperties::IsControl(control)); |
| 514 DCHECK(NodeProperties::GetBounds(node).upper->Is(Type::Number())); |
| 515 DCHECK(!NodeProperties::GetBounds(input).upper->Is(Type::Number())); |
| 516 node->set_op(common()->Phi(kMachAnyTagged, input_count)); |
| 517 for (int i = 0; i < input_count; ++i) { |
| 518 Node* value = input->InputAt(i); |
| 519 // Recursively try to reduce the value first. |
| 520 Reduction reduction = ReduceJSToNumberInput(value); |
| 521 if (reduction.Changed()) { |
| 522 value = reduction.replacement(); |
| 523 } else { |
| 524 value = graph()->NewNode(javascript()->ToNumber(), value, context, |
| 525 graph()->start(), graph()->start()); |
| 526 } |
| 527 if (i < node->InputCount()) { |
| 528 node->ReplaceInput(i, value); |
| 529 } else { |
| 530 node->AppendInput(graph()->zone(), value); |
| 531 } |
| 532 } |
| 533 if (input_count < node->InputCount()) { |
| 534 node->ReplaceInput(input_count, control); |
| 535 } else { |
| 536 node->AppendInput(graph()->zone(), control); |
| 537 } |
| 538 node->TrimInputCount(input_count + 1); |
| 539 return Changed(node); |
| 540 } |
| 541 return NoChange(); |
| 542 } |
| 543 |
| 544 |
499 Reduction JSTypedLowering::ReduceJSToStringInput(Node* input) { | 545 Reduction JSTypedLowering::ReduceJSToStringInput(Node* input) { |
500 if (input->opcode() == IrOpcode::kJSToString) { | 546 if (input->opcode() == IrOpcode::kJSToString) { |
501 // Recursively try to reduce the input first. | 547 // Recursively try to reduce the input first. |
502 Reduction result = ReduceJSToStringInput(input->InputAt(0)); | 548 Reduction result = ReduceJSToStringInput(input->InputAt(0)); |
503 if (result.Changed()) { | 549 if (result.Changed()) { |
504 RelaxEffects(input); | 550 RelaxEffects(input); |
505 return result; | 551 return result; |
506 } | 552 } |
507 return Changed(input); // JSToString(JSToString(x)) => JSToString(x) | 553 return Changed(input); // JSToString(JSToString(x)) => JSToString(x) |
508 } | 554 } |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
575 Reduction JSTypedLowering::ReduceJSToBoolean(Node* node) { | 621 Reduction JSTypedLowering::ReduceJSToBoolean(Node* node) { |
576 // Try to reduce the input first. | 622 // Try to reduce the input first. |
577 Node* const input = node->InputAt(0); | 623 Node* const input = node->InputAt(0); |
578 Reduction reduction = ReduceJSToBooleanInput(input); | 624 Reduction reduction = ReduceJSToBooleanInput(input); |
579 if (reduction.Changed()) { | 625 if (reduction.Changed()) { |
580 NodeProperties::ReplaceWithValue(node, reduction.replacement()); | 626 NodeProperties::ReplaceWithValue(node, reduction.replacement()); |
581 return reduction; | 627 return reduction; |
582 } | 628 } |
583 Type* const input_type = NodeProperties::GetBounds(input).upper; | 629 Type* const input_type = NodeProperties::GetBounds(input).upper; |
584 if (input->opcode() == IrOpcode::kPhi && input_type->Is(Type::Primitive())) { | 630 if (input->opcode() == IrOpcode::kPhi && input_type->Is(Type::Primitive())) { |
| 631 Node* const context = node->InputAt(1); |
585 // JSToBoolean(phi(x1,...,xn,control):primitive) | 632 // JSToBoolean(phi(x1,...,xn,control):primitive) |
586 // => phi(JSToBoolean(x1),...,JSToBoolean(xn),control):boolean | 633 // => phi(JSToBoolean(x1),...,JSToBoolean(xn),control):boolean |
587 RelaxEffects(node); | 634 RelaxEffects(node); |
588 int const input_count = input->InputCount() - 1; | 635 int const input_count = input->InputCount() - 1; |
589 Node* const control = input->InputAt(input_count); | 636 Node* const control = input->InputAt(input_count); |
590 DCHECK_LE(0, input_count); | 637 DCHECK_LE(0, input_count); |
591 DCHECK(NodeProperties::IsControl(control)); | 638 DCHECK(NodeProperties::IsControl(control)); |
592 DCHECK(NodeProperties::GetBounds(node).upper->Is(Type::Boolean())); | 639 DCHECK(NodeProperties::GetBounds(node).upper->Is(Type::Boolean())); |
593 DCHECK(!NodeProperties::GetBounds(input).upper->Is(Type::Boolean())); | 640 DCHECK(!NodeProperties::GetBounds(input).upper->Is(Type::Boolean())); |
594 node->set_op(common()->Phi(kMachAnyTagged, input_count)); | 641 node->set_op(common()->Phi(kMachAnyTagged, input_count)); |
595 for (int i = 0; i < input_count; ++i) { | 642 for (int i = 0; i < input_count; ++i) { |
596 Node* value = input->InputAt(i); | 643 Node* value = input->InputAt(i); |
597 // Recursively try to reduce the value first. | 644 // Recursively try to reduce the value first. |
598 Reduction reduction = ReduceJSToBooleanInput(value); | 645 Reduction reduction = ReduceJSToBooleanInput(value); |
599 if (reduction.Changed()) { | 646 if (reduction.Changed()) { |
600 value = reduction.replacement(); | 647 value = reduction.replacement(); |
601 } else { | 648 } else { |
602 value = graph()->NewNode(javascript()->ToBoolean(), value, | 649 value = graph()->NewNode(javascript()->ToBoolean(), value, context, |
603 jsgraph()->ZeroConstant(), graph()->start(), | 650 graph()->start(), graph()->start()); |
604 graph()->start()); | |
605 } | 651 } |
606 if (i < node->InputCount()) { | 652 if (i < node->InputCount()) { |
607 node->ReplaceInput(i, value); | 653 node->ReplaceInput(i, value); |
608 } else { | 654 } else { |
609 node->AppendInput(graph()->zone(), value); | 655 node->AppendInput(graph()->zone(), value); |
610 } | 656 } |
611 } | 657 } |
612 if (input_count < node->InputCount()) { | 658 if (input_count < node->InputCount()) { |
613 node->ReplaceInput(input_count, control); | 659 node->ReplaceInput(input_count, control); |
614 } else { | 660 } else { |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
762 node->set_op(javascript()->ToBoolean()); | 808 node->set_op(javascript()->ToBoolean()); |
763 NodeProperties::ReplaceWithValue(node, value, node); | 809 NodeProperties::ReplaceWithValue(node, value, node); |
764 // Note: ReplaceUses() smashes all uses, so smash it back here. | 810 // Note: ReplaceUses() smashes all uses, so smash it back here. |
765 value->ReplaceInput(0, node); | 811 value->ReplaceInput(0, node); |
766 return Changed(node); | 812 return Changed(node); |
767 } | 813 } |
768 } | 814 } |
769 case IrOpcode::kJSToBoolean: | 815 case IrOpcode::kJSToBoolean: |
770 return ReduceJSToBoolean(node); | 816 return ReduceJSToBoolean(node); |
771 case IrOpcode::kJSToNumber: | 817 case IrOpcode::kJSToNumber: |
772 return ReplaceWithReduction(node, | 818 return ReduceJSToNumber(node); |
773 ReduceJSToNumberInput(node->InputAt(0))); | |
774 case IrOpcode::kJSToString: | 819 case IrOpcode::kJSToString: |
775 return ReplaceWithReduction(node, | 820 return ReplaceWithReduction(node, |
776 ReduceJSToStringInput(node->InputAt(0))); | 821 ReduceJSToStringInput(node->InputAt(0))); |
777 case IrOpcode::kJSLoadProperty: | 822 case IrOpcode::kJSLoadProperty: |
778 return ReduceJSLoadProperty(node); | 823 return ReduceJSLoadProperty(node); |
779 case IrOpcode::kJSStoreProperty: | 824 case IrOpcode::kJSStoreProperty: |
780 return ReduceJSStoreProperty(node); | 825 return ReduceJSStoreProperty(node); |
781 case IrOpcode::kJSCallFunction: | 826 case IrOpcode::kJSCallFunction: |
782 return JSBuiltinReducer(jsgraph()).Reduce(node); | 827 return JSBuiltinReducer(jsgraph()).Reduce(node); |
783 default: | 828 default: |
784 break; | 829 break; |
785 } | 830 } |
786 return NoChange(); | 831 return NoChange(); |
787 } | 832 } |
788 | 833 |
789 } // namespace compiler | 834 } // namespace compiler |
790 } // namespace internal | 835 } // namespace internal |
791 } // namespace v8 | 836 } // namespace v8 |
OLD | NEW |