| 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 |