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 |