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 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
63 return true; | 63 return true; |
64 case CompareOperationHint::kNumber: | 64 case CompareOperationHint::kNumber: |
65 *hint = NumberOperationHint::kNumber; | 65 *hint = NumberOperationHint::kNumber; |
66 return true; | 66 return true; |
67 case CompareOperationHint::kNumberOrOddball: | 67 case CompareOperationHint::kNumberOrOddball: |
68 *hint = NumberOperationHint::kNumberOrOddball; | 68 *hint = NumberOperationHint::kNumberOrOddball; |
69 return true; | 69 return true; |
70 case CompareOperationHint::kAny: | 70 case CompareOperationHint::kAny: |
71 case CompareOperationHint::kNone: | 71 case CompareOperationHint::kNone: |
72 case CompareOperationHint::kString: | 72 case CompareOperationHint::kString: |
| 73 case CompareOperationHint::kReceiver: |
73 case CompareOperationHint::kInternalizedString: | 74 case CompareOperationHint::kInternalizedString: |
74 break; | 75 break; |
75 } | 76 } |
76 } | 77 } |
77 return false; | 78 return false; |
78 } | 79 } |
79 | 80 |
80 bool IsInternalizedStringCompareOperation() { | 81 bool IsInternalizedStringCompareOperation() { |
81 if (lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) { | 82 if (lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) { |
82 DCHECK_EQ(1, node_->op()->EffectOutputCount()); | 83 DCHECK_EQ(1, node_->op()->EffectOutputCount()); |
83 return (CompareOperationHintOf(node_->op()) == | 84 return (CompareOperationHintOf(node_->op()) == |
84 CompareOperationHint::kInternalizedString) && | 85 CompareOperationHint::kInternalizedString) && |
85 BothInputsMaybe(Type::InternalizedString()); | 86 BothInputsMaybe(Type::InternalizedString()); |
86 } | 87 } |
87 return false; | 88 return false; |
88 } | 89 } |
89 | 90 |
| 91 bool IsReceiverCompareOperation() { |
| 92 if (lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) { |
| 93 DCHECK_EQ(1, node_->op()->EffectOutputCount()); |
| 94 return (CompareOperationHintOf(node_->op()) == |
| 95 CompareOperationHint::kReceiver) && |
| 96 BothInputsMaybe(Type::Receiver()); |
| 97 } |
| 98 return false; |
| 99 } |
| 100 |
90 // Check if a string addition will definitely result in creating a ConsString, | 101 // Check if a string addition will definitely result in creating a ConsString, |
91 // i.e. if the combined length of the resulting string exceeds the ConsString | 102 // i.e. if the combined length of the resulting string exceeds the ConsString |
92 // minimum length. | 103 // minimum length. |
93 bool ShouldCreateConsString() { | 104 bool ShouldCreateConsString() { |
94 DCHECK_EQ(IrOpcode::kJSAdd, node_->opcode()); | 105 DCHECK_EQ(IrOpcode::kJSAdd, node_->opcode()); |
95 if (BothInputsAre(Type::String()) || | 106 if (BothInputsAre(Type::String()) || |
96 ((lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) && | 107 ((lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) && |
97 BinaryOperationHintOf(node_->op()) == BinaryOperationHint::kString)) { | 108 BinaryOperationHintOf(node_->op()) == BinaryOperationHint::kString)) { |
98 HeapObjectBinopMatcher m(node_); | 109 HeapObjectBinopMatcher m(node_); |
99 if (m.right().HasValue() && m.right().Value()->IsString()) { | 110 if (m.right().HasValue() && m.right().Value()->IsString()) { |
100 Handle<String> right_string = Handle<String>::cast(m.right().Value()); | 111 Handle<String> right_string = Handle<String>::cast(m.right().Value()); |
101 if (right_string->length() >= ConsString::kMinLength) return true; | 112 if (right_string->length() >= ConsString::kMinLength) return true; |
102 } | 113 } |
103 if (m.left().HasValue() && m.left().Value()->IsString()) { | 114 if (m.left().HasValue() && m.left().Value()->IsString()) { |
104 Handle<String> left_string = Handle<String>::cast(m.left().Value()); | 115 Handle<String> left_string = Handle<String>::cast(m.left().Value()); |
105 if (left_string->length() >= ConsString::kMinLength) { | 116 if (left_string->length() >= ConsString::kMinLength) { |
106 // The invariant for ConsString requires the left hand side to be | 117 // The invariant for ConsString requires the left hand side to be |
107 // a sequential or external string if the right hand side is the | 118 // a sequential or external string if the right hand side is the |
108 // empty string. Since we don't know anything about the right hand | 119 // empty string. Since we don't know anything about the right hand |
109 // side here, we must ensure that the left hand side satisfy the | 120 // side here, we must ensure that the left hand side satisfy the |
110 // constraints independent of the right hand side. | 121 // constraints independent of the right hand side. |
111 return left_string->IsSeqString() || left_string->IsExternalString(); | 122 return left_string->IsSeqString() || left_string->IsExternalString(); |
112 } | 123 } |
113 } | 124 } |
114 } | 125 } |
115 return false; | 126 return false; |
116 } | 127 } |
117 | 128 |
| 129 // Inserts a CheckReceiver for the left input. |
| 130 void CheckLeftInputToReceiver() { |
| 131 Node* left_input = graph()->NewNode(simplified()->CheckReceiver(), left(), |
| 132 effect(), control()); |
| 133 node_->ReplaceInput(0, left_input); |
| 134 update_effect(left_input); |
| 135 } |
| 136 |
| 137 // Checks that both inputs are Receiver, and if we don't know |
| 138 // statically that one side is already a Receiver, insert a |
| 139 // CheckReceiver node. |
| 140 void CheckInputsToReceiver() { |
| 141 if (!left_type()->Is(Type::Receiver())) { |
| 142 CheckLeftInputToReceiver(); |
| 143 } |
| 144 if (!right_type()->Is(Type::Receiver())) { |
| 145 Node* right_input = graph()->NewNode(simplified()->CheckReceiver(), |
| 146 right(), effect(), control()); |
| 147 node_->ReplaceInput(1, right_input); |
| 148 update_effect(right_input); |
| 149 } |
| 150 } |
| 151 |
118 // Checks that both inputs are InternalizedString, and if we don't know | 152 // Checks that both inputs are InternalizedString, and if we don't know |
119 // statically that one side is already an InternalizedString, insert a | 153 // statically that one side is already an InternalizedString, insert a |
120 // CheckInternalizedString node. | 154 // CheckInternalizedString node. |
121 void CheckInputsToInternalizedString() { | 155 void CheckInputsToInternalizedString() { |
122 if (!left_type()->Is(Type::UniqueName())) { | 156 if (!left_type()->Is(Type::UniqueName())) { |
123 Node* left_input = graph()->NewNode( | 157 Node* left_input = graph()->NewNode( |
124 simplified()->CheckInternalizedString(), left(), effect(), control()); | 158 simplified()->CheckInternalizedString(), left(), effect(), control()); |
125 node_->ReplaceInput(0, left_input); | 159 node_->ReplaceInput(0, left_input); |
126 update_effect(left_input); | 160 update_effect(left_input); |
127 } | 161 } |
(...skipping 789 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
917 | 951 |
918 NumberOperationHint hint; | 952 NumberOperationHint hint; |
919 if (r.BothInputsAre(Type::Signed32()) || | 953 if (r.BothInputsAre(Type::Signed32()) || |
920 r.BothInputsAre(Type::Unsigned32())) { | 954 r.BothInputsAre(Type::Unsigned32())) { |
921 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert); | 955 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert); |
922 } else if (r.GetCompareNumberOperationHint(&hint)) { | 956 } else if (r.GetCompareNumberOperationHint(&hint)) { |
923 return r.ChangeToSpeculativeOperator( | 957 return r.ChangeToSpeculativeOperator( |
924 simplified()->SpeculativeNumberEqual(hint), invert, Type::Boolean()); | 958 simplified()->SpeculativeNumberEqual(hint), invert, Type::Boolean()); |
925 } else if (r.BothInputsAre(Type::Number())) { | 959 } else if (r.BothInputsAre(Type::Number())) { |
926 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert); | 960 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert); |
| 961 } else if (r.IsReceiverCompareOperation()) { |
| 962 r.CheckInputsToReceiver(); |
| 963 return r.ChangeToPureOperator(simplified()->ReferenceEqual(), invert); |
927 } | 964 } |
928 return NoChange(); | 965 return NoChange(); |
929 } | 966 } |
930 | 967 |
931 Reduction JSTypedLowering::ReduceJSStrictEqual(Node* node, bool invert) { | 968 Reduction JSTypedLowering::ReduceJSStrictEqual(Node* node, bool invert) { |
932 JSBinopReduction r(this, node); | 969 JSBinopReduction r(this, node); |
933 if (r.left() == r.right()) { | 970 if (r.left() == r.right()) { |
934 // x === x is always true if x != NaN | 971 // x === x is always true if x != NaN |
935 if (!r.left_type()->Maybe(Type::NaN())) { | 972 if (!r.left_type()->Maybe(Type::NaN())) { |
936 Node* replacement = jsgraph()->BooleanConstant(!invert); | 973 Node* replacement = jsgraph()->BooleanConstant(!invert); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
968 | 1005 |
969 NumberOperationHint hint; | 1006 NumberOperationHint hint; |
970 if (r.BothInputsAre(Type::Signed32()) || | 1007 if (r.BothInputsAre(Type::Signed32()) || |
971 r.BothInputsAre(Type::Unsigned32())) { | 1008 r.BothInputsAre(Type::Unsigned32())) { |
972 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert); | 1009 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert); |
973 } else if (r.GetCompareNumberOperationHint(&hint)) { | 1010 } else if (r.GetCompareNumberOperationHint(&hint)) { |
974 return r.ChangeToSpeculativeOperator( | 1011 return r.ChangeToSpeculativeOperator( |
975 simplified()->SpeculativeNumberEqual(hint), invert, Type::Boolean()); | 1012 simplified()->SpeculativeNumberEqual(hint), invert, Type::Boolean()); |
976 } else if (r.BothInputsAre(Type::Number())) { | 1013 } else if (r.BothInputsAre(Type::Number())) { |
977 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert); | 1014 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert); |
| 1015 } else if (r.IsReceiverCompareOperation()) { |
| 1016 // For strict equality, it's enough to know that one input is a Receiver, |
| 1017 // as a strict equality comparison with a Receiver can only yield true if |
| 1018 // both sides refer to the same Receiver than. |
| 1019 r.CheckLeftInputToReceiver(); |
| 1020 return r.ChangeToPureOperator(simplified()->ReferenceEqual(), invert); |
978 } | 1021 } |
979 return NoChange(); | 1022 return NoChange(); |
980 } | 1023 } |
981 | 1024 |
982 Reduction JSTypedLowering::ReduceJSToBoolean(Node* node) { | 1025 Reduction JSTypedLowering::ReduceJSToBoolean(Node* node) { |
983 Node* const input = node->InputAt(0); | 1026 Node* const input = node->InputAt(0); |
984 Type* const input_type = NodeProperties::GetType(input); | 1027 Type* const input_type = NodeProperties::GetType(input); |
985 if (input_type->Is(Type::Boolean())) { | 1028 if (input_type->Is(Type::Boolean())) { |
986 // JSToBoolean(x:boolean) => x | 1029 // JSToBoolean(x:boolean) => x |
987 return Replace(input); | 1030 return Replace(input); |
(...skipping 1355 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2343 } | 2386 } |
2344 | 2387 |
2345 | 2388 |
2346 CompilationDependencies* JSTypedLowering::dependencies() const { | 2389 CompilationDependencies* JSTypedLowering::dependencies() const { |
2347 return dependencies_; | 2390 return dependencies_; |
2348 } | 2391 } |
2349 | 2392 |
2350 } // namespace compiler | 2393 } // namespace compiler |
2351 } // namespace internal | 2394 } // namespace internal |
2352 } // namespace v8 | 2395 } // namespace v8 |
OLD | NEW |