| 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/builtins/builtins-utils.h" | 7 #include "src/builtins/builtins-utils.h" |
| 8 #include "src/code-factory.h" | 8 #include "src/code-factory.h" |
| 9 #include "src/compilation-dependencies.h" | 9 #include "src/compilation-dependencies.h" |
| 10 #include "src/compiler/access-builder.h" | 10 #include "src/compiler/access-builder.h" |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 75 } | 75 } |
| 76 | 76 |
| 77 // Check if a string addition will definitely result in creating a ConsString, | 77 // Check if a string addition will definitely result in creating a ConsString, |
| 78 // i.e. if the combined length of the resulting string exceeds the ConsString | 78 // i.e. if the combined length of the resulting string exceeds the ConsString |
| 79 // minimum length. | 79 // minimum length. |
| 80 bool ShouldCreateConsString() { | 80 bool ShouldCreateConsString() { |
| 81 DCHECK_EQ(IrOpcode::kJSAdd, node_->opcode()); | 81 DCHECK_EQ(IrOpcode::kJSAdd, node_->opcode()); |
| 82 if (BothInputsAre(Type::String()) || | 82 if (BothInputsAre(Type::String()) || |
| 83 ((lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) && | 83 ((lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) && |
| 84 BinaryOperationHintOf(node_->op()) == BinaryOperationHint::kString)) { | 84 BinaryOperationHintOf(node_->op()) == BinaryOperationHint::kString)) { |
| 85 if (left_type()->IsHeapConstant() && | 85 HeapObjectBinopMatcher m(node_); |
| 86 left_type()->AsHeapConstant()->Value()->IsString()) { | 86 if (m.left().HasValue() && m.left().Value()->IsString()) { |
| 87 Handle<String> left_string = | 87 Handle<String> left_string = Handle<String>::cast(m.left().Value()); |
| 88 Handle<String>::cast(left_type()->AsHeapConstant()->Value()); | |
| 89 if (left_string->length() >= ConsString::kMinLength) return true; | 88 if (left_string->length() >= ConsString::kMinLength) return true; |
| 90 } | 89 } |
| 91 if (right_type()->IsHeapConstant() && | 90 if (m.right().HasValue() && m.right().Value()->IsString()) { |
| 92 right_type()->AsHeapConstant()->Value()->IsString()) { | 91 Handle<String> right_string = Handle<String>::cast(m.right().Value()); |
| 93 Handle<String> right_string = | |
| 94 Handle<String>::cast(right_type()->AsHeapConstant()->Value()); | |
| 95 if (right_string->length() >= ConsString::kMinLength) return true; | 92 if (right_string->length() >= ConsString::kMinLength) return true; |
| 96 } | 93 } |
| 97 } | 94 } |
| 98 return false; | 95 return false; |
| 99 } | 96 } |
| 100 | 97 |
| 101 void ConvertInputsToNumber() { | 98 void ConvertInputsToNumber() { |
| 102 // To convert the inputs to numbers, we have to provide frame states | 99 // To convert the inputs to numbers, we have to provide frame states |
| 103 // for lazy bailouts in the ToNumber conversions. | 100 // for lazy bailouts in the ToNumber conversions. |
| 104 // We use a little hack here: we take the frame state before the binary | 101 // We use a little hack here: we take the frame state before the binary |
| (...skipping 484 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 589 | 586 |
| 590 // Make sure {second} is actually a String. | 587 // Make sure {second} is actually a String. |
| 591 Type* second_type = NodeProperties::GetType(second); | 588 Type* second_type = NodeProperties::GetType(second); |
| 592 if (!second_type->Is(Type::String())) { | 589 if (!second_type->Is(Type::String())) { |
| 593 second = effect = | 590 second = effect = |
| 594 graph()->NewNode(simplified()->CheckString(), second, effect, control); | 591 graph()->NewNode(simplified()->CheckString(), second, effect, control); |
| 595 second_type = NodeProperties::GetType(second); | 592 second_type = NodeProperties::GetType(second); |
| 596 } | 593 } |
| 597 | 594 |
| 598 // Determine the {first} length. | 595 // Determine the {first} length. |
| 596 HeapObjectBinopMatcher m(node); |
| 599 Node* first_length = | 597 Node* first_length = |
| 600 first_type->IsHeapConstant() | 598 (m.left().HasValue() && m.left().Value()->IsString()) |
| 601 ? jsgraph()->Constant( | 599 ? jsgraph()->Constant( |
| 602 Handle<String>::cast(first_type->AsHeapConstant()->Value()) | 600 Handle<String>::cast(m.left().Value())->length()) |
| 603 ->length()) | |
| 604 : effect = graph()->NewNode( | 601 : effect = graph()->NewNode( |
| 605 simplified()->LoadField(AccessBuilder::ForStringLength()), | 602 simplified()->LoadField(AccessBuilder::ForStringLength()), |
| 606 first, effect, control); | 603 first, effect, control); |
| 607 | 604 |
| 608 // Determine the {second} length. | 605 // Determine the {second} length. |
| 609 Node* second_length = | 606 Node* second_length = |
| 610 second_type->IsHeapConstant() | 607 (m.right().HasValue() && m.right().Value()->IsString()) |
| 611 ? jsgraph()->Constant( | 608 ? jsgraph()->Constant( |
| 612 Handle<String>::cast(second_type->AsHeapConstant()->Value()) | 609 Handle<String>::cast(m.right().Value())->length()) |
| 613 ->length()) | |
| 614 : effect = graph()->NewNode( | 610 : effect = graph()->NewNode( |
| 615 simplified()->LoadField(AccessBuilder::ForStringLength()), | 611 simplified()->LoadField(AccessBuilder::ForStringLength()), |
| 616 second, effect, control); | 612 second, effect, control); |
| 617 | 613 |
| 618 // Compute the resulting length. | 614 // Compute the resulting length. |
| 619 Node* length = | 615 Node* length = |
| 620 graph()->NewNode(simplified()->NumberAdd(), first_length, second_length); | 616 graph()->NewNode(simplified()->NumberAdd(), first_length, second_length); |
| 621 | 617 |
| 622 // Check if we would overflow the allowed maximum string length. | 618 // Check if we would overflow the allowed maximum string length. |
| 623 Node* check = graph()->NewNode(simplified()->NumberLessThanOrEqual(), length, | 619 Node* check = graph()->NewNode(simplified()->NumberLessThanOrEqual(), length, |
| (...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 972 } | 968 } |
| 973 ReplaceWithValue(node, input); | 969 ReplaceWithValue(node, input); |
| 974 return Replace(input); | 970 return Replace(input); |
| 975 } | 971 } |
| 976 return NoChange(); | 972 return NoChange(); |
| 977 } | 973 } |
| 978 | 974 |
| 979 Reduction JSTypedLowering::ReduceJSToNumberInput(Node* input) { | 975 Reduction JSTypedLowering::ReduceJSToNumberInput(Node* input) { |
| 980 // Try constant-folding of JSToNumber with constant inputs. | 976 // Try constant-folding of JSToNumber with constant inputs. |
| 981 Type* input_type = NodeProperties::GetType(input); | 977 Type* input_type = NodeProperties::GetType(input); |
| 978 if (input_type->Is(Type::String())) { |
| 979 HeapObjectMatcher m(input); |
| 980 if (m.HasValue() && m.Value()->IsString()) { |
| 981 Handle<Object> input_value = m.Value(); |
| 982 return Replace(jsgraph()->Constant( |
| 983 String::ToNumber(Handle<String>::cast(input_value)))); |
| 984 } |
| 985 } |
| 982 if (input_type->IsHeapConstant()) { | 986 if (input_type->IsHeapConstant()) { |
| 983 Handle<Object> input_value = input_type->AsHeapConstant()->Value(); | 987 Handle<Object> input_value = input_type->AsHeapConstant()->Value(); |
| 984 if (input_value->IsString()) { | 988 if (input_value->IsOddball()) { |
| 985 return Replace(jsgraph()->Constant( | |
| 986 String::ToNumber(Handle<String>::cast(input_value)))); | |
| 987 } else if (input_value->IsOddball()) { | |
| 988 return Replace(jsgraph()->Constant( | 989 return Replace(jsgraph()->Constant( |
| 989 Oddball::ToNumber(Handle<Oddball>::cast(input_value)))); | 990 Oddball::ToNumber(Handle<Oddball>::cast(input_value)))); |
| 990 } | 991 } |
| 991 } | 992 } |
| 992 if (input_type->Is(Type::Number())) { | 993 if (input_type->Is(Type::Number())) { |
| 993 // JSToNumber(x:number) => x | 994 // JSToNumber(x:number) => x |
| 994 return Changed(input); | 995 return Changed(input); |
| 995 } | 996 } |
| 996 if (input_type->Is(Type::Undefined())) { | 997 if (input_type->Is(Type::Undefined())) { |
| 997 // JSToNumber(undefined) => #NaN | 998 // JSToNumber(undefined) => #NaN |
| (...skipping 1142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2140 } | 2141 } |
| 2141 | 2142 |
| 2142 | 2143 |
| 2143 CompilationDependencies* JSTypedLowering::dependencies() const { | 2144 CompilationDependencies* JSTypedLowering::dependencies() const { |
| 2144 return dependencies_; | 2145 return dependencies_; |
| 2145 } | 2146 } |
| 2146 | 2147 |
| 2147 } // namespace compiler | 2148 } // namespace compiler |
| 2148 } // namespace internal | 2149 } // namespace internal |
| 2149 } // namespace v8 | 2150 } // namespace v8 |
| OLD | NEW |