| 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 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 break; | 73 break; |
| 74 } | 74 } |
| 75 } | 75 } |
| 76 return false; | 76 return false; |
| 77 } | 77 } |
| 78 | |
| 79 bool IsStringCompareOperation() { | |
| 80 if (lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) { | |
| 81 DCHECK_EQ(1, node_->op()->EffectOutputCount()); | |
| 82 return (CompareOperationHintOf(node_->op()) == | |
| 83 CompareOperationHint::kString) && | |
| 84 BothInputsMaybe(Type::String()); | |
| 85 } | |
| 86 return false; | |
| 87 } | |
| 88 | 78 |
| 89 // Check if a string addition will definitely result in creating a ConsString, | 79 // Check if a string addition will definitely result in creating a ConsString, |
| 90 // i.e. if the combined length of the resulting string exceeds the ConsString | 80 // i.e. if the combined length of the resulting string exceeds the ConsString |
| 91 // minimum length. | 81 // minimum length. |
| 92 bool ShouldCreateConsString() { | 82 bool ShouldCreateConsString() { |
| 93 DCHECK_EQ(IrOpcode::kJSAdd, node_->opcode()); | 83 DCHECK_EQ(IrOpcode::kJSAdd, node_->opcode()); |
| 94 if (BothInputsAre(Type::String()) || | 84 if (BothInputsAre(Type::String()) || |
| 95 ((lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) && | 85 ((lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) && |
| 96 BinaryOperationHintOf(node_->op()) == BinaryOperationHint::kString)) { | 86 BinaryOperationHintOf(node_->op()) == BinaryOperationHint::kString)) { |
| 97 HeapObjectBinopMatcher m(node_); | 87 HeapObjectBinopMatcher m(node_); |
| 98 if (m.right().HasValue() && m.right().Value()->IsString()) { | 88 if (m.right().HasValue() && m.right().Value()->IsString()) { |
| 99 Handle<String> right_string = Handle<String>::cast(m.right().Value()); | 89 Handle<String> right_string = Handle<String>::cast(m.right().Value()); |
| 100 if (right_string->length() >= ConsString::kMinLength) return true; | 90 if (right_string->length() >= ConsString::kMinLength) return true; |
| 101 } | 91 } |
| 102 if (m.left().HasValue() && m.left().Value()->IsString()) { | 92 if (m.left().HasValue() && m.left().Value()->IsString()) { |
| 103 Handle<String> left_string = Handle<String>::cast(m.left().Value()); | 93 Handle<String> left_string = Handle<String>::cast(m.left().Value()); |
| 104 if (left_string->length() >= ConsString::kMinLength) { | 94 if (left_string->length() >= ConsString::kMinLength) { |
| 105 // The invariant for ConsString requires the left hand side to be | 95 // The invariant for ConsString requires the left hand side to be |
| 106 // a sequential or external string if the right hand side is the | 96 // a sequential or external string if the right hand side is the |
| 107 // empty string. Since we don't know anything about the right hand | 97 // empty string. Since we don't know anything about the right hand |
| 108 // side here, we must ensure that the left hand side satisfy the | 98 // side here, we must ensure that the left hand side satisfy the |
| 109 // constraints independent of the right hand side. | 99 // constraints independent of the right hand side. |
| 110 return left_string->IsSeqString() || left_string->IsExternalString(); | 100 return left_string->IsSeqString() || left_string->IsExternalString(); |
| 111 } | 101 } |
| 112 } | 102 } |
| 113 } | 103 } |
| 114 return false; | 104 return false; |
| 115 } | 105 } |
| 116 | 106 |
| 117 // Checks that both inputs are String, and if we don't know statically that | |
| 118 // one side is already a String, insert a CheckString node. | |
| 119 void CheckInputsToString() { | |
| 120 if (!left_type()->Is(Type::String())) { | |
| 121 Node* left_input = graph()->NewNode(simplified()->CheckString(), left(), | |
| 122 effect(), control()); | |
| 123 node_->ReplaceInput(0, left_input); | |
| 124 update_effect(left_input); | |
| 125 } | |
| 126 if (!right_type()->Is(Type::String())) { | |
| 127 Node* right_input = graph()->NewNode(simplified()->CheckString(), right(), | |
| 128 effect(), control()); | |
| 129 node_->ReplaceInput(1, right_input); | |
| 130 update_effect(right_input); | |
| 131 } | |
| 132 } | |
| 133 | |
| 134 void ConvertInputsToNumber() { | 107 void ConvertInputsToNumber() { |
| 135 // To convert the inputs to numbers, we have to provide frame states | 108 // To convert the inputs to numbers, we have to provide frame states |
| 136 // for lazy bailouts in the ToNumber conversions. | 109 // for lazy bailouts in the ToNumber conversions. |
| 137 // We use a little hack here: we take the frame state before the binary | 110 // We use a little hack here: we take the frame state before the binary |
| 138 // operation and use it to construct the frame states for the conversion | 111 // operation and use it to construct the frame states for the conversion |
| 139 // so that after the deoptimization, the binary operation IC gets | 112 // so that after the deoptimization, the binary operation IC gets |
| 140 // already converted values from full code. This way we are sure that we | 113 // already converted values from full code. This way we are sure that we |
| 141 // will not re-do any of the side effects. | 114 // will not re-do any of the side effects. |
| 142 | 115 |
| 143 Node* left_input = nullptr; | 116 Node* left_input = nullptr; |
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 337 } | 310 } |
| 338 | 311 |
| 339 bool LeftInputIs(Type* t) { return left_type()->Is(t); } | 312 bool LeftInputIs(Type* t) { return left_type()->Is(t); } |
| 340 | 313 |
| 341 bool RightInputIs(Type* t) { return right_type()->Is(t); } | 314 bool RightInputIs(Type* t) { return right_type()->Is(t); } |
| 342 | 315 |
| 343 bool OneInputIs(Type* t) { return LeftInputIs(t) || RightInputIs(t); } | 316 bool OneInputIs(Type* t) { return LeftInputIs(t) || RightInputIs(t); } |
| 344 | 317 |
| 345 bool BothInputsAre(Type* t) { return LeftInputIs(t) && RightInputIs(t); } | 318 bool BothInputsAre(Type* t) { return LeftInputIs(t) && RightInputIs(t); } |
| 346 | 319 |
| 347 bool BothInputsMaybe(Type* t) { | |
| 348 return left_type()->Maybe(t) && right_type()->Maybe(t); | |
| 349 } | |
| 350 | |
| 351 bool OneInputCannotBe(Type* t) { | 320 bool OneInputCannotBe(Type* t) { |
| 352 return !left_type()->Maybe(t) || !right_type()->Maybe(t); | 321 return !left_type()->Maybe(t) || !right_type()->Maybe(t); |
| 353 } | 322 } |
| 354 | 323 |
| 355 bool NeitherInputCanBe(Type* t) { | 324 bool NeitherInputCanBe(Type* t) { |
| 356 return !left_type()->Maybe(t) && !right_type()->Maybe(t); | 325 return !left_type()->Maybe(t) && !right_type()->Maybe(t); |
| 357 } | 326 } |
| 358 | 327 |
| 359 Node* effect() { return NodeProperties::GetEffectInput(node_); } | 328 Node* effect() { return NodeProperties::GetEffectInput(node_); } |
| 360 Node* control() { return NodeProperties::GetControlInput(node_); } | 329 Node* control() { return NodeProperties::GetControlInput(node_); } |
| (...skipping 410 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 771 less_than_or_equal = simplified()->NumberLessThanOrEqual(); | 740 less_than_or_equal = simplified()->NumberLessThanOrEqual(); |
| 772 } else if (r.GetCompareNumberOperationHint(&hint)) { | 741 } else if (r.GetCompareNumberOperationHint(&hint)) { |
| 773 less_than = simplified()->SpeculativeNumberLessThan(hint); | 742 less_than = simplified()->SpeculativeNumberLessThan(hint); |
| 774 less_than_or_equal = simplified()->SpeculativeNumberLessThanOrEqual(hint); | 743 less_than_or_equal = simplified()->SpeculativeNumberLessThanOrEqual(hint); |
| 775 } else if (r.OneInputCannotBe(Type::StringOrReceiver()) && | 744 } else if (r.OneInputCannotBe(Type::StringOrReceiver()) && |
| 776 (r.BothInputsAre(Type::PlainPrimitive()) || | 745 (r.BothInputsAre(Type::PlainPrimitive()) || |
| 777 !(flags() & kDeoptimizationEnabled))) { | 746 !(flags() & kDeoptimizationEnabled))) { |
| 778 r.ConvertInputsToNumber(); | 747 r.ConvertInputsToNumber(); |
| 779 less_than = simplified()->NumberLessThan(); | 748 less_than = simplified()->NumberLessThan(); |
| 780 less_than_or_equal = simplified()->NumberLessThanOrEqual(); | 749 less_than_or_equal = simplified()->NumberLessThanOrEqual(); |
| 781 } else if (r.IsStringCompareOperation()) { | |
| 782 r.CheckInputsToString(); | |
| 783 less_than = simplified()->StringLessThan(); | |
| 784 less_than_or_equal = simplified()->StringLessThanOrEqual(); | |
| 785 } else { | 750 } else { |
| 786 return NoChange(); | 751 return NoChange(); |
| 787 } | 752 } |
| 788 const Operator* comparison; | 753 const Operator* comparison; |
| 789 switch (node->opcode()) { | 754 switch (node->opcode()) { |
| 790 case IrOpcode::kJSLessThan: | 755 case IrOpcode::kJSLessThan: |
| 791 comparison = less_than; | 756 comparison = less_than; |
| 792 break; | 757 break; |
| 793 case IrOpcode::kJSGreaterThan: | 758 case IrOpcode::kJSGreaterThan: |
| 794 comparison = less_than; | 759 comparison = less_than; |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 913 | 878 |
| 914 NumberOperationHint hint; | 879 NumberOperationHint hint; |
| 915 if (r.BothInputsAre(Type::Signed32()) || | 880 if (r.BothInputsAre(Type::Signed32()) || |
| 916 r.BothInputsAre(Type::Unsigned32())) { | 881 r.BothInputsAre(Type::Unsigned32())) { |
| 917 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert); | 882 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert); |
| 918 } else if (r.GetCompareNumberOperationHint(&hint)) { | 883 } else if (r.GetCompareNumberOperationHint(&hint)) { |
| 919 return r.ChangeToSpeculativeOperator( | 884 return r.ChangeToSpeculativeOperator( |
| 920 simplified()->SpeculativeNumberEqual(hint), invert, Type::Boolean()); | 885 simplified()->SpeculativeNumberEqual(hint), invert, Type::Boolean()); |
| 921 } else if (r.BothInputsAre(Type::Number())) { | 886 } else if (r.BothInputsAre(Type::Number())) { |
| 922 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert); | 887 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert); |
| 923 } else if (r.IsStringCompareOperation()) { | |
| 924 r.CheckInputsToString(); | |
| 925 return r.ChangeToPureOperator(simplified()->StringEqual(), invert); | |
| 926 } | 888 } |
| 927 return NoChange(); | 889 return NoChange(); |
| 928 } | 890 } |
| 929 | 891 |
| 930 Reduction JSTypedLowering::ReduceJSStrictEqual(Node* node, bool invert) { | 892 Reduction JSTypedLowering::ReduceJSStrictEqual(Node* node, bool invert) { |
| 931 JSBinopReduction r(this, node); | 893 JSBinopReduction r(this, node); |
| 932 if (r.left() == r.right()) { | 894 if (r.left() == r.right()) { |
| 933 // x === x is always true if x != NaN | 895 // x === x is always true if x != NaN |
| 934 if (!r.left_type()->Maybe(Type::NaN())) { | 896 if (!r.left_type()->Maybe(Type::NaN())) { |
| 935 Node* replacement = jsgraph()->BooleanConstant(!invert); | 897 Node* replacement = jsgraph()->BooleanConstant(!invert); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 978 | 940 |
| 979 NumberOperationHint hint; | 941 NumberOperationHint hint; |
| 980 if (r.BothInputsAre(Type::Signed32()) || | 942 if (r.BothInputsAre(Type::Signed32()) || |
| 981 r.BothInputsAre(Type::Unsigned32())) { | 943 r.BothInputsAre(Type::Unsigned32())) { |
| 982 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert); | 944 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert); |
| 983 } else if (r.GetCompareNumberOperationHint(&hint)) { | 945 } else if (r.GetCompareNumberOperationHint(&hint)) { |
| 984 return r.ChangeToSpeculativeOperator( | 946 return r.ChangeToSpeculativeOperator( |
| 985 simplified()->SpeculativeNumberEqual(hint), invert, Type::Boolean()); | 947 simplified()->SpeculativeNumberEqual(hint), invert, Type::Boolean()); |
| 986 } else if (r.BothInputsAre(Type::Number())) { | 948 } else if (r.BothInputsAre(Type::Number())) { |
| 987 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert); | 949 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert); |
| 988 } else if (r.IsStringCompareOperation()) { | |
| 989 r.CheckInputsToString(); | |
| 990 return r.ChangeToPureOperator(simplified()->StringEqual(), invert); | |
| 991 } | 950 } |
| 992 return NoChange(); | 951 return NoChange(); |
| 993 } | 952 } |
| 994 | 953 |
| 995 Reduction JSTypedLowering::ReduceJSToBoolean(Node* node) { | 954 Reduction JSTypedLowering::ReduceJSToBoolean(Node* node) { |
| 996 Node* const input = node->InputAt(0); | 955 Node* const input = node->InputAt(0); |
| 997 Type* const input_type = NodeProperties::GetType(input); | 956 Type* const input_type = NodeProperties::GetType(input); |
| 998 if (input_type->Is(Type::Boolean())) { | 957 if (input_type->Is(Type::Boolean())) { |
| 999 // JSToBoolean(x:boolean) => x | 958 // JSToBoolean(x:boolean) => x |
| 1000 return Replace(input); | 959 return Replace(input); |
| (...skipping 1312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2313 } | 2272 } |
| 2314 | 2273 |
| 2315 | 2274 |
| 2316 CompilationDependencies* JSTypedLowering::dependencies() const { | 2275 CompilationDependencies* JSTypedLowering::dependencies() const { |
| 2317 return dependencies_; | 2276 return dependencies_; |
| 2318 } | 2277 } |
| 2319 | 2278 |
| 2320 } // namespace compiler | 2279 } // namespace compiler |
| 2321 } // namespace internal | 2280 } // namespace internal |
| 2322 } // namespace v8 | 2281 } // namespace v8 |
| OLD | NEW |