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-graph.h" | 7 #include "src/compiler/js-graph.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-matchers.h" | 10 #include "src/compiler/node-matchers.h" |
11 #include "src/compiler/node-properties-inl.h" | 11 #include "src/compiler/node-properties-inl.h" |
12 #include "src/types.h" | 12 #include "src/types.h" |
13 | 13 |
14 namespace v8 { | 14 namespace v8 { |
15 namespace internal { | 15 namespace internal { |
16 namespace compiler { | 16 namespace compiler { |
17 | 17 |
18 // TODO(turbofan): js-typed-lowering improvements possible | 18 // TODO(turbofan): js-typed-lowering improvements possible |
19 // - immediately put in type bounds for all new nodes | 19 // - immediately put in type bounds for all new nodes |
20 // - relax effects from generic but not-side-effecting operations | 20 // - relax effects from generic but not-side-effecting operations |
21 // - relax effects for ToNumber(mixed) | |
22 | 21 |
23 | 22 |
24 // Relax the effects of {node} by immediately replacing effect uses of {node} | 23 // Relax the effects of {node} by immediately replacing effect uses of {node} |
25 // with the effect input to {node}. | 24 // with the effect input to {node}. |
26 // TODO(turbofan): replace the effect input to {node} with {graph->start()}. | 25 // TODO(turbofan): replace the effect input to {node} with {graph->start()}. |
27 // TODO(titzer): move into a GraphEditor? | 26 // TODO(titzer): move into a GraphEditor? |
28 static void RelaxEffects(Node* node) { | 27 static void RelaxEffects(Node* node) { |
29 NodeProperties::ReplaceWithValue(node, node, NULL); | 28 NodeProperties::ReplaceWithValue(node, node, NULL); |
30 } | 29 } |
31 | 30 |
(...skipping 619 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
651 Reduction JSTypedLowering::ReduceJSToNumber(Node* node) { | 650 Reduction JSTypedLowering::ReduceJSToNumber(Node* node) { |
652 // Try to reduce the input first. | 651 // Try to reduce the input first. |
653 Node* const input = node->InputAt(0); | 652 Node* const input = node->InputAt(0); |
654 Reduction reduction = ReduceJSToNumberInput(input); | 653 Reduction reduction = ReduceJSToNumberInput(input); |
655 if (reduction.Changed()) { | 654 if (reduction.Changed()) { |
656 NodeProperties::ReplaceWithValue(node, reduction.replacement()); | 655 NodeProperties::ReplaceWithValue(node, reduction.replacement()); |
657 return reduction; | 656 return reduction; |
658 } | 657 } |
659 Type* const input_type = NodeProperties::GetBounds(input).upper; | 658 Type* const input_type = NodeProperties::GetBounds(input).upper; |
660 if (input_type->Is(Type::PlainPrimitive())) { | 659 if (input_type->Is(Type::PlainPrimitive())) { |
661 // Converting a plain primitive to a number has no observable side effects. | |
662 RelaxEffects(node); | |
663 if (input->opcode() == IrOpcode::kPhi) { | 660 if (input->opcode() == IrOpcode::kPhi) { |
664 // JSToNumber(phi(x1,...,xn,control):plain-primitive,context) | 661 // JSToNumber(phi(x1,...,xn,control):plain-primitive,context) |
665 // => phi(JSToNumber(x1,no-context), | 662 // => phi(JSToNumber(x1,no-context), |
666 // ..., | 663 // ..., |
667 // JSToNumber(xn,no-context),control) | 664 // JSToNumber(xn,no-context),control) |
668 int const input_count = input->InputCount() - 1; | 665 int const input_count = input->InputCount() - 1; |
669 Node* const control = input->InputAt(input_count); | 666 Node* const control = input->InputAt(input_count); |
670 DCHECK_LE(0, input_count); | 667 DCHECK_LE(0, input_count); |
671 DCHECK(NodeProperties::IsControl(control)); | 668 DCHECK(NodeProperties::IsControl(control)); |
672 DCHECK(NodeProperties::GetBounds(node).upper->Is(Type::Number())); | 669 DCHECK(NodeProperties::GetBounds(node).upper->Is(Type::Number())); |
673 DCHECK(!NodeProperties::GetBounds(input).upper->Is(Type::Number())); | 670 DCHECK(!NodeProperties::GetBounds(input).upper->Is(Type::Number())); |
| 671 RelaxEffects(node); |
674 node->set_op(common()->Phi(kMachAnyTagged, input_count)); | 672 node->set_op(common()->Phi(kMachAnyTagged, input_count)); |
675 for (int i = 0; i < input_count; ++i) { | 673 for (int i = 0; i < input_count; ++i) { |
676 Node* value = input->InputAt(i); | 674 Node* value = input->InputAt(i); |
677 // Recursively try to reduce the value first. | 675 // Recursively try to reduce the value first. |
678 Reduction reduction = ReduceJSToNumberInput(value); | 676 Reduction reduction = ReduceJSToNumberInput(value); |
679 if (reduction.Changed()) { | 677 if (reduction.Changed()) { |
680 value = reduction.replacement(); | 678 value = reduction.replacement(); |
681 } else { | 679 } else { |
682 // We must be very careful not to introduce cycles when pushing | 680 // We must be very careful not to introduce cycles when pushing |
683 // operations into phis. It is safe for {value}, since it appears | 681 // operations into phis. It is safe for {value}, since it appears |
(...skipping 10 matching lines...) Expand all Loading... |
694 } else { | 692 } else { |
695 node->AppendInput(graph()->zone(), value); | 693 node->AppendInput(graph()->zone(), value); |
696 } | 694 } |
697 } | 695 } |
698 if (input_count < node->InputCount()) { | 696 if (input_count < node->InputCount()) { |
699 node->ReplaceInput(input_count, control); | 697 node->ReplaceInput(input_count, control); |
700 } else { | 698 } else { |
701 node->AppendInput(graph()->zone(), control); | 699 node->AppendInput(graph()->zone(), control); |
702 } | 700 } |
703 node->TrimInputCount(input_count + 1); | 701 node->TrimInputCount(input_count + 1); |
704 } else if (input->opcode() == IrOpcode::kSelect) { | 702 return Changed(node); |
| 703 } |
| 704 if (input->opcode() == IrOpcode::kSelect) { |
705 // JSToNumber(select(c,x1,x2):plain-primitive,context) | 705 // JSToNumber(select(c,x1,x2):plain-primitive,context) |
706 // => select(c,JSToNumber(x1,no-context),JSToNumber(x2,no-context)) | 706 // => select(c,JSToNumber(x1,no-context),JSToNumber(x2,no-context)) |
707 int const input_count = input->InputCount(); | 707 int const input_count = input->InputCount(); |
708 BranchHint const input_hint = SelectParametersOf(input->op()).hint(); | 708 BranchHint const input_hint = SelectParametersOf(input->op()).hint(); |
709 DCHECK_EQ(3, input_count); | 709 DCHECK_EQ(3, input_count); |
710 DCHECK(NodeProperties::GetBounds(node).upper->Is(Type::Number())); | 710 DCHECK(NodeProperties::GetBounds(node).upper->Is(Type::Number())); |
711 DCHECK(!NodeProperties::GetBounds(input).upper->Is(Type::Number())); | 711 DCHECK(!NodeProperties::GetBounds(input).upper->Is(Type::Number())); |
| 712 RelaxEffects(node); |
712 node->set_op(common()->Select(kMachAnyTagged, input_hint)); | 713 node->set_op(common()->Select(kMachAnyTagged, input_hint)); |
713 node->ReplaceInput(0, input->InputAt(0)); | 714 node->ReplaceInput(0, input->InputAt(0)); |
714 for (int i = 1; i < input_count; ++i) { | 715 for (int i = 1; i < input_count; ++i) { |
715 Node* value = input->InputAt(i); | 716 Node* value = input->InputAt(i); |
716 // Recursively try to reduce the value first. | 717 // Recursively try to reduce the value first. |
717 Reduction reduction = ReduceJSToNumberInput(value); | 718 Reduction reduction = ReduceJSToNumberInput(value); |
718 if (reduction.Changed()) { | 719 if (reduction.Changed()) { |
719 value = reduction.replacement(); | 720 value = reduction.replacement(); |
720 } else { | 721 } else { |
721 // We must be very careful not to introduce cycles when pushing | 722 // We must be very careful not to introduce cycles when pushing |
722 // operations into selects. It is safe for {value}, since it appears | 723 // operations into selects. It is safe for {value}, since it appears |
723 // as input to the select that we are replacing, but it's not safe | 724 // as input to the select that we are replacing, but it's not safe |
724 // to simply reuse the context of the {node}. However, ToNumber() | 725 // to simply reuse the context of the {node}. However, ToNumber() |
725 // does not require a context anyways, so it's safe to discard it | 726 // does not require a context anyways, so it's safe to discard it |
726 // here and pass the dummy context. | 727 // here and pass the dummy context. |
727 value = graph()->NewNode(javascript()->ToNumber(), value, | 728 value = graph()->NewNode(javascript()->ToNumber(), value, |
728 jsgraph()->NoContextConstant(), | 729 jsgraph()->NoContextConstant(), |
729 graph()->start(), graph()->start()); | 730 graph()->start(), graph()->start()); |
730 } | 731 } |
731 node->ReplaceInput(i, value); | 732 node->ReplaceInput(i, value); |
732 } | 733 } |
733 node->TrimInputCount(input_count); | 734 node->TrimInputCount(input_count); |
| 735 return Changed(node); |
734 } | 736 } |
735 return Changed(node); | 737 if (node->InputAt(1) != jsgraph()->NoContextConstant() || |
| 738 node->InputAt(2) != graph()->start()) { |
| 739 // JSToNumber(x:plain-primitive,context) => JSToNumber(x,no-context) |
| 740 node->ReplaceInput(1, jsgraph()->NoContextConstant()); |
| 741 RelaxEffects(node); |
| 742 return Changed(node); |
| 743 } |
736 } | 744 } |
737 return NoChange(); | 745 return NoChange(); |
738 } | 746 } |
739 | 747 |
740 | 748 |
741 Reduction JSTypedLowering::ReduceJSToStringInput(Node* input) { | 749 Reduction JSTypedLowering::ReduceJSToStringInput(Node* input) { |
742 if (input->opcode() == IrOpcode::kJSToString) { | 750 if (input->opcode() == IrOpcode::kJSToString) { |
743 // Recursively try to reduce the input first. | 751 // Recursively try to reduce the input first. |
744 Reduction result = ReduceJSToString(input); | 752 Reduction result = ReduceJSToString(input); |
745 if (result.Changed()) return result; | 753 if (result.Changed()) return result; |
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1037 } | 1045 } |
1038 | 1046 |
1039 | 1047 |
1040 MachineOperatorBuilder* JSTypedLowering::machine() const { | 1048 MachineOperatorBuilder* JSTypedLowering::machine() const { |
1041 return jsgraph()->machine(); | 1049 return jsgraph()->machine(); |
1042 } | 1050 } |
1043 | 1051 |
1044 } // namespace compiler | 1052 } // namespace compiler |
1045 } // namespace internal | 1053 } // namespace internal |
1046 } // namespace v8 | 1054 } // namespace v8 |
OLD | NEW |