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/js-typed-lowering.h" | 5 #include "src/compiler/js-typed-lowering.h" |
6 | 6 |
7 #include "src/ast/modules.h" | 7 #include "src/ast/modules.h" |
8 #include "src/builtins/builtins-utils.h" | 8 #include "src/builtins/builtins-utils.h" |
9 #include "src/code-factory.h" | 9 #include "src/code-factory.h" |
10 #include "src/compilation-dependencies.h" | 10 #include "src/compilation-dependencies.h" |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
91 bool IsReceiverCompareOperation() { | 91 bool IsReceiverCompareOperation() { |
92 if (lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) { | 92 if (lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) { |
93 DCHECK_EQ(1, node_->op()->EffectOutputCount()); | 93 DCHECK_EQ(1, node_->op()->EffectOutputCount()); |
94 return (CompareOperationHintOf(node_->op()) == | 94 return (CompareOperationHintOf(node_->op()) == |
95 CompareOperationHint::kReceiver) && | 95 CompareOperationHint::kReceiver) && |
96 BothInputsMaybe(Type::Receiver()); | 96 BothInputsMaybe(Type::Receiver()); |
97 } | 97 } |
98 return false; | 98 return false; |
99 } | 99 } |
100 | 100 |
| 101 bool IsStringCompareOperation() { |
| 102 if (lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) { |
| 103 DCHECK_EQ(1, node_->op()->EffectOutputCount()); |
| 104 return (CompareOperationHintOf(node_->op()) == |
| 105 CompareOperationHint::kString) && |
| 106 BothInputsMaybe(Type::String()); |
| 107 } |
| 108 return false; |
| 109 } |
| 110 |
101 // Check if a string addition will definitely result in creating a ConsString, | 111 // Check if a string addition will definitely result in creating a ConsString, |
102 // i.e. if the combined length of the resulting string exceeds the ConsString | 112 // i.e. if the combined length of the resulting string exceeds the ConsString |
103 // minimum length. | 113 // minimum length. |
104 bool ShouldCreateConsString() { | 114 bool ShouldCreateConsString() { |
105 DCHECK_EQ(IrOpcode::kJSAdd, node_->opcode()); | 115 DCHECK_EQ(IrOpcode::kJSAdd, node_->opcode()); |
106 if (BothInputsAre(Type::String()) || | 116 if (BothInputsAre(Type::String()) || |
107 ((lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) && | 117 ((lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) && |
108 BinaryOperationHintOf(node_->op()) == BinaryOperationHint::kString)) { | 118 BinaryOperationHintOf(node_->op()) == BinaryOperationHint::kString)) { |
109 HeapObjectBinopMatcher m(node_); | 119 HeapObjectBinopMatcher m(node_); |
110 if (m.right().HasValue() && m.right().Value()->IsString()) { | 120 if (m.right().HasValue() && m.right().Value()->IsString()) { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
142 CheckLeftInputToReceiver(); | 152 CheckLeftInputToReceiver(); |
143 } | 153 } |
144 if (!right_type()->Is(Type::Receiver())) { | 154 if (!right_type()->Is(Type::Receiver())) { |
145 Node* right_input = graph()->NewNode(simplified()->CheckReceiver(), | 155 Node* right_input = graph()->NewNode(simplified()->CheckReceiver(), |
146 right(), effect(), control()); | 156 right(), effect(), control()); |
147 node_->ReplaceInput(1, right_input); | 157 node_->ReplaceInput(1, right_input); |
148 update_effect(right_input); | 158 update_effect(right_input); |
149 } | 159 } |
150 } | 160 } |
151 | 161 |
| 162 // Checks that both inputs are String, and if we don't know |
| 163 // statically that one side is already a String, insert a |
| 164 // CheckString node. |
| 165 void CheckInputsToString() { |
| 166 if (!left_type()->Is(Type::String())) { |
| 167 Node* left_input = graph()->NewNode(simplified()->CheckString(), left(), |
| 168 effect(), control()); |
| 169 node_->ReplaceInput(0, left_input); |
| 170 update_effect(left_input); |
| 171 } |
| 172 if (!right_type()->Is(Type::String())) { |
| 173 Node* right_input = graph()->NewNode(simplified()->CheckString(), right(), |
| 174 effect(), control()); |
| 175 node_->ReplaceInput(1, right_input); |
| 176 update_effect(right_input); |
| 177 } |
| 178 } |
| 179 |
152 // Checks that both inputs are InternalizedString, and if we don't know | 180 // Checks that both inputs are InternalizedString, and if we don't know |
153 // statically that one side is already an InternalizedString, insert a | 181 // statically that one side is already an InternalizedString, insert a |
154 // CheckInternalizedString node. | 182 // CheckInternalizedString node. |
155 void CheckInputsToInternalizedString() { | 183 void CheckInputsToInternalizedString() { |
156 if (!left_type()->Is(Type::UniqueName())) { | 184 if (!left_type()->Is(Type::UniqueName())) { |
157 Node* left_input = graph()->NewNode( | 185 Node* left_input = graph()->NewNode( |
158 simplified()->CheckInternalizedString(), left(), effect(), control()); | 186 simplified()->CheckInternalizedString(), left(), effect(), control()); |
159 node_->ReplaceInput(0, left_input); | 187 node_->ReplaceInput(0, left_input); |
160 update_effect(left_input); | 188 update_effect(left_input); |
161 } | 189 } |
(...skipping 658 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
820 less_than_or_equal = simplified()->NumberLessThanOrEqual(); | 848 less_than_or_equal = simplified()->NumberLessThanOrEqual(); |
821 } else if (r.GetCompareNumberOperationHint(&hint)) { | 849 } else if (r.GetCompareNumberOperationHint(&hint)) { |
822 less_than = simplified()->SpeculativeNumberLessThan(hint); | 850 less_than = simplified()->SpeculativeNumberLessThan(hint); |
823 less_than_or_equal = simplified()->SpeculativeNumberLessThanOrEqual(hint); | 851 less_than_or_equal = simplified()->SpeculativeNumberLessThanOrEqual(hint); |
824 } else if (r.OneInputCannotBe(Type::StringOrReceiver()) && | 852 } else if (r.OneInputCannotBe(Type::StringOrReceiver()) && |
825 (r.BothInputsAre(Type::PlainPrimitive()) || | 853 (r.BothInputsAre(Type::PlainPrimitive()) || |
826 !(flags() & kDeoptimizationEnabled))) { | 854 !(flags() & kDeoptimizationEnabled))) { |
827 r.ConvertInputsToNumber(); | 855 r.ConvertInputsToNumber(); |
828 less_than = simplified()->NumberLessThan(); | 856 less_than = simplified()->NumberLessThan(); |
829 less_than_or_equal = simplified()->NumberLessThanOrEqual(); | 857 less_than_or_equal = simplified()->NumberLessThanOrEqual(); |
| 858 } else if (r.IsStringCompareOperation()) { |
| 859 r.CheckInputsToString(); |
| 860 less_than = simplified()->StringLessThan(); |
| 861 less_than_or_equal = simplified()->StringLessThanOrEqual(); |
830 } else { | 862 } else { |
831 return NoChange(); | 863 return NoChange(); |
832 } | 864 } |
833 const Operator* comparison; | 865 const Operator* comparison; |
834 switch (node->opcode()) { | 866 switch (node->opcode()) { |
835 case IrOpcode::kJSLessThan: | 867 case IrOpcode::kJSLessThan: |
836 comparison = less_than; | 868 comparison = less_than; |
837 break; | 869 break; |
838 case IrOpcode::kJSGreaterThan: | 870 case IrOpcode::kJSGreaterThan: |
839 comparison = less_than; | 871 comparison = less_than; |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
979 r.BothInputsAre(Type::Unsigned32())) { | 1011 r.BothInputsAre(Type::Unsigned32())) { |
980 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert); | 1012 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert); |
981 } else if (r.GetCompareNumberOperationHint(&hint)) { | 1013 } else if (r.GetCompareNumberOperationHint(&hint)) { |
982 return r.ChangeToSpeculativeOperator( | 1014 return r.ChangeToSpeculativeOperator( |
983 simplified()->SpeculativeNumberEqual(hint), invert, Type::Boolean()); | 1015 simplified()->SpeculativeNumberEqual(hint), invert, Type::Boolean()); |
984 } else if (r.BothInputsAre(Type::Number())) { | 1016 } else if (r.BothInputsAre(Type::Number())) { |
985 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert); | 1017 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert); |
986 } else if (r.IsReceiverCompareOperation()) { | 1018 } else if (r.IsReceiverCompareOperation()) { |
987 r.CheckInputsToReceiver(); | 1019 r.CheckInputsToReceiver(); |
988 return r.ChangeToPureOperator(simplified()->ReferenceEqual(), invert); | 1020 return r.ChangeToPureOperator(simplified()->ReferenceEqual(), invert); |
| 1021 } else if (r.IsStringCompareOperation()) { |
| 1022 r.CheckInputsToString(); |
| 1023 return r.ChangeToPureOperator(simplified()->StringEqual(), invert); |
989 } | 1024 } |
990 return NoChange(); | 1025 return NoChange(); |
991 } | 1026 } |
992 | 1027 |
993 Reduction JSTypedLowering::ReduceJSStrictEqual(Node* node, bool invert) { | 1028 Reduction JSTypedLowering::ReduceJSStrictEqual(Node* node, bool invert) { |
994 JSBinopReduction r(this, node); | 1029 JSBinopReduction r(this, node); |
995 if (r.left() == r.right()) { | 1030 if (r.left() == r.right()) { |
996 // x === x is always true if x != NaN | 1031 // x === x is always true if x != NaN |
997 if (!r.left_type()->Maybe(Type::NaN())) { | 1032 if (!r.left_type()->Maybe(Type::NaN())) { |
998 Node* replacement = jsgraph()->BooleanConstant(!invert); | 1033 Node* replacement = jsgraph()->BooleanConstant(!invert); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1036 return r.ChangeToSpeculativeOperator( | 1071 return r.ChangeToSpeculativeOperator( |
1037 simplified()->SpeculativeNumberEqual(hint), invert, Type::Boolean()); | 1072 simplified()->SpeculativeNumberEqual(hint), invert, Type::Boolean()); |
1038 } else if (r.BothInputsAre(Type::Number())) { | 1073 } else if (r.BothInputsAre(Type::Number())) { |
1039 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert); | 1074 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert); |
1040 } else if (r.IsReceiverCompareOperation()) { | 1075 } else if (r.IsReceiverCompareOperation()) { |
1041 // For strict equality, it's enough to know that one input is a Receiver, | 1076 // For strict equality, it's enough to know that one input is a Receiver, |
1042 // as a strict equality comparison with a Receiver can only yield true if | 1077 // as a strict equality comparison with a Receiver can only yield true if |
1043 // both sides refer to the same Receiver than. | 1078 // both sides refer to the same Receiver than. |
1044 r.CheckLeftInputToReceiver(); | 1079 r.CheckLeftInputToReceiver(); |
1045 return r.ChangeToPureOperator(simplified()->ReferenceEqual(), invert); | 1080 return r.ChangeToPureOperator(simplified()->ReferenceEqual(), invert); |
| 1081 } else if (r.IsStringCompareOperation()) { |
| 1082 r.CheckInputsToString(); |
| 1083 return r.ChangeToPureOperator(simplified()->StringEqual(), invert); |
1046 } | 1084 } |
1047 return NoChange(); | 1085 return NoChange(); |
1048 } | 1086 } |
1049 | 1087 |
1050 Reduction JSTypedLowering::ReduceJSToBoolean(Node* node) { | 1088 Reduction JSTypedLowering::ReduceJSToBoolean(Node* node) { |
1051 Node* const input = node->InputAt(0); | 1089 Node* const input = node->InputAt(0); |
1052 Type* const input_type = NodeProperties::GetType(input); | 1090 Type* const input_type = NodeProperties::GetType(input); |
1053 if (input_type->Is(Type::Boolean())) { | 1091 if (input_type->Is(Type::Boolean())) { |
1054 // JSToBoolean(x:boolean) => x | 1092 // JSToBoolean(x:boolean) => x |
1055 return Replace(input); | 1093 return Replace(input); |
(...skipping 1420 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2476 } | 2514 } |
2477 | 2515 |
2478 | 2516 |
2479 CompilationDependencies* JSTypedLowering::dependencies() const { | 2517 CompilationDependencies* JSTypedLowering::dependencies() const { |
2480 return dependencies_; | 2518 return dependencies_; |
2481 } | 2519 } |
2482 | 2520 |
2483 } // namespace compiler | 2521 } // namespace compiler |
2484 } // namespace internal | 2522 } // namespace internal |
2485 } // namespace v8 | 2523 } // namespace v8 |
OLD | NEW |