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::kInternalizedString: |
73 break; | 74 break; |
74 } | 75 } |
75 } | 76 } |
76 return false; | 77 return false; |
77 } | 78 } |
78 | 79 |
| 80 bool IsInternalizedStringCompareOperation() { |
| 81 if (lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) { |
| 82 DCHECK_EQ(1, node_->op()->EffectOutputCount()); |
| 83 return (CompareOperationHintOf(node_->op()) == |
| 84 CompareOperationHint::kInternalizedString) && |
| 85 BothInputsMaybe(Type::InternalizedString()); |
| 86 } |
| 87 return false; |
| 88 } |
| 89 |
79 // Check if a string addition will definitely result in creating a ConsString, | 90 // Check if a string addition will definitely result in creating a ConsString, |
80 // i.e. if the combined length of the resulting string exceeds the ConsString | 91 // i.e. if the combined length of the resulting string exceeds the ConsString |
81 // minimum length. | 92 // minimum length. |
82 bool ShouldCreateConsString() { | 93 bool ShouldCreateConsString() { |
83 DCHECK_EQ(IrOpcode::kJSAdd, node_->opcode()); | 94 DCHECK_EQ(IrOpcode::kJSAdd, node_->opcode()); |
84 if (BothInputsAre(Type::String()) || | 95 if (BothInputsAre(Type::String()) || |
85 ((lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) && | 96 ((lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) && |
86 BinaryOperationHintOf(node_->op()) == BinaryOperationHint::kString)) { | 97 BinaryOperationHintOf(node_->op()) == BinaryOperationHint::kString)) { |
87 HeapObjectBinopMatcher m(node_); | 98 HeapObjectBinopMatcher m(node_); |
88 if (m.right().HasValue() && m.right().Value()->IsString()) { | 99 if (m.right().HasValue() && m.right().Value()->IsString()) { |
89 Handle<String> right_string = Handle<String>::cast(m.right().Value()); | 100 Handle<String> right_string = Handle<String>::cast(m.right().Value()); |
90 if (right_string->length() >= ConsString::kMinLength) return true; | 101 if (right_string->length() >= ConsString::kMinLength) return true; |
91 } | 102 } |
92 if (m.left().HasValue() && m.left().Value()->IsString()) { | 103 if (m.left().HasValue() && m.left().Value()->IsString()) { |
93 Handle<String> left_string = Handle<String>::cast(m.left().Value()); | 104 Handle<String> left_string = Handle<String>::cast(m.left().Value()); |
94 if (left_string->length() >= ConsString::kMinLength) { | 105 if (left_string->length() >= ConsString::kMinLength) { |
95 // The invariant for ConsString requires the left hand side to be | 106 // The invariant for ConsString requires the left hand side to be |
96 // a sequential or external string if the right hand side is the | 107 // a sequential or external string if the right hand side is the |
97 // empty string. Since we don't know anything about the right hand | 108 // empty string. Since we don't know anything about the right hand |
98 // side here, we must ensure that the left hand side satisfy the | 109 // side here, we must ensure that the left hand side satisfy the |
99 // constraints independent of the right hand side. | 110 // constraints independent of the right hand side. |
100 return left_string->IsSeqString() || left_string->IsExternalString(); | 111 return left_string->IsSeqString() || left_string->IsExternalString(); |
101 } | 112 } |
102 } | 113 } |
103 } | 114 } |
104 return false; | 115 return false; |
105 } | 116 } |
106 | 117 |
| 118 // Checks that both inputs are InternalizedString, and if we don't know |
| 119 // statically that one side is already an InternalizedString, insert a |
| 120 // CheckInternalizedString node. |
| 121 void CheckInputsToInternalizedString() { |
| 122 if (!left_type()->Is(Type::UniqueName())) { |
| 123 Node* left_input = graph()->NewNode( |
| 124 simplified()->CheckInternalizedString(), left(), effect(), control()); |
| 125 node_->ReplaceInput(0, left_input); |
| 126 update_effect(left_input); |
| 127 } |
| 128 if (!right_type()->Is(Type::UniqueName())) { |
| 129 Node* right_input = |
| 130 graph()->NewNode(simplified()->CheckInternalizedString(), right(), |
| 131 effect(), control()); |
| 132 node_->ReplaceInput(1, right_input); |
| 133 update_effect(right_input); |
| 134 } |
| 135 } |
| 136 |
107 void ConvertInputsToNumber() { | 137 void ConvertInputsToNumber() { |
108 // To convert the inputs to numbers, we have to provide frame states | 138 // To convert the inputs to numbers, we have to provide frame states |
109 // for lazy bailouts in the ToNumber conversions. | 139 // for lazy bailouts in the ToNumber conversions. |
110 // We use a little hack here: we take the frame state before the binary | 140 // We use a little hack here: we take the frame state before the binary |
111 // operation and use it to construct the frame states for the conversion | 141 // operation and use it to construct the frame states for the conversion |
112 // so that after the deoptimization, the binary operation IC gets | 142 // so that after the deoptimization, the binary operation IC gets |
113 // already converted values from full code. This way we are sure that we | 143 // already converted values from full code. This way we are sure that we |
114 // will not re-do any of the side effects. | 144 // will not re-do any of the side effects. |
115 | 145 |
116 Node* left_input = nullptr; | 146 Node* left_input = nullptr; |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
310 } | 340 } |
311 | 341 |
312 bool LeftInputIs(Type* t) { return left_type()->Is(t); } | 342 bool LeftInputIs(Type* t) { return left_type()->Is(t); } |
313 | 343 |
314 bool RightInputIs(Type* t) { return right_type()->Is(t); } | 344 bool RightInputIs(Type* t) { return right_type()->Is(t); } |
315 | 345 |
316 bool OneInputIs(Type* t) { return LeftInputIs(t) || RightInputIs(t); } | 346 bool OneInputIs(Type* t) { return LeftInputIs(t) || RightInputIs(t); } |
317 | 347 |
318 bool BothInputsAre(Type* t) { return LeftInputIs(t) && RightInputIs(t); } | 348 bool BothInputsAre(Type* t) { return LeftInputIs(t) && RightInputIs(t); } |
319 | 349 |
| 350 bool BothInputsMaybe(Type* t) { |
| 351 return left_type()->Maybe(t) && right_type()->Maybe(t); |
| 352 } |
| 353 |
320 bool OneInputCannotBe(Type* t) { | 354 bool OneInputCannotBe(Type* t) { |
321 return !left_type()->Maybe(t) || !right_type()->Maybe(t); | 355 return !left_type()->Maybe(t) || !right_type()->Maybe(t); |
322 } | 356 } |
323 | 357 |
324 bool NeitherInputCanBe(Type* t) { | 358 bool NeitherInputCanBe(Type* t) { |
325 return !left_type()->Maybe(t) && !right_type()->Maybe(t); | 359 return !left_type()->Maybe(t) && !right_type()->Maybe(t); |
326 } | 360 } |
327 | 361 |
328 Node* effect() { return NodeProperties::GetEffectInput(node_); } | 362 Node* effect() { return NodeProperties::GetEffectInput(node_); } |
329 Node* control() { return NodeProperties::GetControlInput(node_); } | 363 Node* control() { return NodeProperties::GetControlInput(node_); } |
(...skipping 514 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
844 } | 878 } |
845 return NoChange(); | 879 return NoChange(); |
846 } | 880 } |
847 | 881 |
848 Reduction JSTypedLowering::ReduceJSEqual(Node* node, bool invert) { | 882 Reduction JSTypedLowering::ReduceJSEqual(Node* node, bool invert) { |
849 Reduction const reduction = ReduceJSEqualTypeOf(node, invert); | 883 Reduction const reduction = ReduceJSEqualTypeOf(node, invert); |
850 if (reduction.Changed()) return reduction; | 884 if (reduction.Changed()) return reduction; |
851 | 885 |
852 JSBinopReduction r(this, node); | 886 JSBinopReduction r(this, node); |
853 | 887 |
| 888 if (r.BothInputsAre(Type::UniqueName())) { |
| 889 return r.ChangeToPureOperator(simplified()->ReferenceEqual(), invert); |
| 890 } |
| 891 if (r.IsInternalizedStringCompareOperation()) { |
| 892 r.CheckInputsToInternalizedString(); |
| 893 return r.ChangeToPureOperator(simplified()->ReferenceEqual(), invert); |
| 894 } |
854 if (r.BothInputsAre(Type::String())) { | 895 if (r.BothInputsAre(Type::String())) { |
855 return r.ChangeToPureOperator(simplified()->StringEqual(), invert); | 896 return r.ChangeToPureOperator(simplified()->StringEqual(), invert); |
856 } | 897 } |
857 if (r.BothInputsAre(Type::Boolean())) { | 898 if (r.BothInputsAre(Type::Boolean())) { |
858 return r.ChangeToPureOperator(simplified()->ReferenceEqual(), invert); | 899 return r.ChangeToPureOperator(simplified()->ReferenceEqual(), invert); |
859 } | 900 } |
860 if (r.BothInputsAre(Type::Receiver())) { | 901 if (r.BothInputsAre(Type::Receiver())) { |
861 return r.ChangeToPureOperator(simplified()->ReferenceEqual(), invert); | 902 return r.ChangeToPureOperator(simplified()->ReferenceEqual(), invert); |
862 } | 903 } |
863 if (r.OneInputIs(Type::Undetectable())) { | 904 if (r.OneInputIs(Type::Undetectable())) { |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
927 } | 968 } |
928 if (r.OneInputIs(Type::Object())) { | 969 if (r.OneInputIs(Type::Object())) { |
929 return r.ChangeToPureOperator(simplified()->ReferenceEqual(), invert); | 970 return r.ChangeToPureOperator(simplified()->ReferenceEqual(), invert); |
930 } | 971 } |
931 if (r.OneInputIs(Type::Receiver())) { | 972 if (r.OneInputIs(Type::Receiver())) { |
932 return r.ChangeToPureOperator(simplified()->ReferenceEqual(), invert); | 973 return r.ChangeToPureOperator(simplified()->ReferenceEqual(), invert); |
933 } | 974 } |
934 if (r.BothInputsAre(Type::Unique())) { | 975 if (r.BothInputsAre(Type::Unique())) { |
935 return r.ChangeToPureOperator(simplified()->ReferenceEqual(), invert); | 976 return r.ChangeToPureOperator(simplified()->ReferenceEqual(), invert); |
936 } | 977 } |
| 978 if (r.IsInternalizedStringCompareOperation()) { |
| 979 r.CheckInputsToInternalizedString(); |
| 980 return r.ChangeToPureOperator(simplified()->ReferenceEqual(), invert); |
| 981 } |
937 if (r.BothInputsAre(Type::String())) { | 982 if (r.BothInputsAre(Type::String())) { |
938 return r.ChangeToPureOperator(simplified()->StringEqual(), invert); | 983 return r.ChangeToPureOperator(simplified()->StringEqual(), invert); |
939 } | 984 } |
940 | 985 |
941 NumberOperationHint hint; | 986 NumberOperationHint hint; |
942 if (r.BothInputsAre(Type::Signed32()) || | 987 if (r.BothInputsAre(Type::Signed32()) || |
943 r.BothInputsAre(Type::Unsigned32())) { | 988 r.BothInputsAre(Type::Unsigned32())) { |
944 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert); | 989 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert); |
945 } else if (r.GetCompareNumberOperationHint(&hint)) { | 990 } else if (r.GetCompareNumberOperationHint(&hint)) { |
946 return r.ChangeToSpeculativeOperator( | 991 return r.ChangeToSpeculativeOperator( |
(...skipping 1368 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2315 } | 2360 } |
2316 | 2361 |
2317 | 2362 |
2318 CompilationDependencies* JSTypedLowering::dependencies() const { | 2363 CompilationDependencies* JSTypedLowering::dependencies() const { |
2319 return dependencies_; | 2364 return dependencies_; |
2320 } | 2365 } |
2321 | 2366 |
2322 } // namespace compiler | 2367 } // namespace compiler |
2323 } // namespace internal | 2368 } // namespace internal |
2324 } // namespace v8 | 2369 } // namespace v8 |
OLD | NEW |