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