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/code-factory.h" | 7 #include "src/code-factory.h" |
8 #include "src/compilation-dependencies.h" | 8 #include "src/compilation-dependencies.h" |
9 #include "src/compiler/access-builder.h" | 9 #include "src/compiler/access-builder.h" |
10 #include "src/compiler/js-graph.h" | 10 #include "src/compiler/js-graph.h" |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
48 case BinaryOperationHints::kNone: | 48 case BinaryOperationHints::kNone: |
49 case BinaryOperationHints::kString: | 49 case BinaryOperationHints::kString: |
50 break; | 50 break; |
51 } | 51 } |
52 } | 52 } |
53 return false; | 53 return false; |
54 } | 54 } |
55 | 55 |
56 bool GetCompareNumberOperationHint(NumberOperationHint* hint) { | 56 bool GetCompareNumberOperationHint(NumberOperationHint* hint) { |
57 if (lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) { | 57 if (lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) { |
58 DCHECK_NE(0, node_->op()->ControlOutputCount()); | |
59 DCHECK_EQ(1, node_->op()->EffectOutputCount()); | 58 DCHECK_EQ(1, node_->op()->EffectOutputCount()); |
60 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node_->op())); | |
61 CompareOperationHints hints = CompareOperationHintsOf(node_->op()); | 59 CompareOperationHints hints = CompareOperationHintsOf(node_->op()); |
62 switch (hints.combined()) { | 60 switch (hints.combined()) { |
63 case CompareOperationHints::kSignedSmall: | 61 case CompareOperationHints::kSignedSmall: |
64 *hint = NumberOperationHint::kSignedSmall; | 62 *hint = NumberOperationHint::kSignedSmall; |
65 return true; | 63 return true; |
66 case CompareOperationHints::kNumber: | 64 case CompareOperationHints::kNumber: |
67 *hint = NumberOperationHint::kNumber; | 65 *hint = NumberOperationHint::kNumber; |
68 return true; | 66 return true; |
69 case CompareOperationHints::kNumberOrOddball: | 67 case CompareOperationHints::kNumberOrOddball: |
70 *hint = NumberOperationHint::kNumberOrOddball; | 68 *hint = NumberOperationHint::kNumberOrOddball; |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
168 DCHECK_EQ(1, op->EffectOutputCount()); | 166 DCHECK_EQ(1, op->EffectOutputCount()); |
169 DCHECK_EQ(false, OperatorProperties::HasContextInput(op)); | 167 DCHECK_EQ(false, OperatorProperties::HasContextInput(op)); |
170 DCHECK_EQ(1, op->ControlInputCount()); | 168 DCHECK_EQ(1, op->ControlInputCount()); |
171 DCHECK_EQ(0, op->ControlOutputCount()); | 169 DCHECK_EQ(0, op->ControlOutputCount()); |
172 DCHECK_EQ(0, OperatorProperties::GetFrameStateInputCount(op)); | 170 DCHECK_EQ(0, OperatorProperties::GetFrameStateInputCount(op)); |
173 DCHECK_EQ(2, op->ValueInputCount()); | 171 DCHECK_EQ(2, op->ValueInputCount()); |
174 | 172 |
175 DCHECK_EQ(1, node_->op()->EffectInputCount()); | 173 DCHECK_EQ(1, node_->op()->EffectInputCount()); |
176 DCHECK_EQ(1, node_->op()->EffectOutputCount()); | 174 DCHECK_EQ(1, node_->op()->EffectOutputCount()); |
177 DCHECK_EQ(1, node_->op()->ControlInputCount()); | 175 DCHECK_EQ(1, node_->op()->ControlInputCount()); |
178 DCHECK_LT(1, node_->op()->ControlOutputCount()); | |
179 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node_->op())); | |
180 DCHECK_EQ(2, node_->op()->ValueInputCount()); | 176 DCHECK_EQ(2, node_->op()->ValueInputCount()); |
181 | 177 |
182 // Reconnect the control output to bypass the IfSuccess node and | 178 // Reconnect the control output to bypass the IfSuccess node and |
183 // possibly disconnect from the IfException node. | 179 // possibly disconnect from the IfException node. |
184 for (Edge edge : node_->use_edges()) { | 180 for (Edge edge : node_->use_edges()) { |
185 Node* const user = edge.from(); | 181 Node* const user = edge.from(); |
186 DCHECK(!user->IsDead()); | 182 DCHECK(!user->IsDead()); |
187 if (NodeProperties::IsControlEdge(edge)) { | 183 if (NodeProperties::IsControlEdge(edge)) { |
188 if (user->opcode() == IrOpcode::kIfSuccess) { | 184 if (user->opcode() == IrOpcode::kIfSuccess) { |
189 user->ReplaceUses(NodeProperties::GetControlInput(node_)); | 185 user->ReplaceUses(NodeProperties::GetControlInput(node_)); |
190 user->Kill(); | 186 user->Kill(); |
191 } else { | 187 } else { |
192 DCHECK_EQ(user->opcode(), IrOpcode::kIfException); | 188 DCHECK_EQ(user->opcode(), IrOpcode::kIfException); |
193 edge.UpdateTo(jsgraph()->Dead()); | 189 edge.UpdateTo(jsgraph()->Dead()); |
194 } | 190 } |
195 } | 191 } |
196 } | 192 } |
197 | 193 |
198 // Remove the frame state and the context. | 194 // Remove the frame state and the context. |
199 node_->RemoveInput(NodeProperties::FirstFrameStateIndex(node_)); | 195 if (OperatorProperties::HasFrameStateInput(node_->op())) { |
| 196 node_->RemoveInput(NodeProperties::FirstFrameStateIndex(node_)); |
| 197 } |
200 node_->RemoveInput(NodeProperties::FirstContextIndex(node_)); | 198 node_->RemoveInput(NodeProperties::FirstContextIndex(node_)); |
201 | 199 |
202 NodeProperties::ChangeOp(node_, op); | 200 NodeProperties::ChangeOp(node_, op); |
203 | 201 |
204 // Update the type to number. | 202 // Update the type to number. |
205 Type* node_type = NodeProperties::GetType(node_); | 203 Type* node_type = NodeProperties::GetType(node_); |
206 NodeProperties::SetType(node_, | 204 NodeProperties::SetType(node_, |
207 Type::Intersect(node_type, upper_bound, zone())); | 205 Type::Intersect(node_type, upper_bound, zone())); |
208 | 206 |
209 if (invert) { | 207 if (invert) { |
(...skipping 477 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
687 graph()->NewNode(simplified()->ReferenceEqual(Type::Any()), input, | 685 graph()->NewNode(simplified()->ReferenceEqual(Type::Any()), input, |
688 jsgraph()->NullConstant()), | 686 jsgraph()->NullConstant()), |
689 jsgraph()->FalseConstant(), | 687 jsgraph()->FalseConstant(), |
690 graph()->NewNode(simplified()->ObjectIsUndetectable(), input)); | 688 graph()->NewNode(simplified()->ObjectIsUndetectable(), input)); |
691 } else { | 689 } else { |
692 return NoChange(); | 690 return NoChange(); |
693 } | 691 } |
694 if (invert) { | 692 if (invert) { |
695 replacement = graph()->NewNode(simplified()->BooleanNot(), replacement); | 693 replacement = graph()->NewNode(simplified()->BooleanNot(), replacement); |
696 } | 694 } |
| 695 ReplaceWithValue(node, replacement); |
697 return Replace(replacement); | 696 return Replace(replacement); |
698 } | 697 } |
699 return NoChange(); | 698 return NoChange(); |
700 } | 699 } |
701 | 700 |
702 Reduction JSTypedLowering::ReduceJSEqual(Node* node, bool invert) { | 701 Reduction JSTypedLowering::ReduceJSEqual(Node* node, bool invert) { |
703 Reduction const reduction = ReduceJSEqualTypeOf(node, invert); | 702 Reduction const reduction = ReduceJSEqualTypeOf(node, invert); |
704 if (reduction.Changed()) { | 703 if (reduction.Changed()) return reduction; |
705 ReplaceWithValue(node, reduction.replacement()); | |
706 return reduction; | |
707 } | |
708 | 704 |
709 JSBinopReduction r(this, node); | 705 JSBinopReduction r(this, node); |
710 | 706 |
711 if (r.BothInputsAre(Type::String())) { | 707 if (r.BothInputsAre(Type::String())) { |
712 return r.ChangeToPureOperator(simplified()->StringEqual(), invert); | 708 return r.ChangeToPureOperator(simplified()->StringEqual(), invert); |
713 } | 709 } |
714 if (r.BothInputsAre(Type::Boolean())) { | 710 if (r.BothInputsAre(Type::Boolean())) { |
715 return r.ChangeToPureOperator(simplified()->ReferenceEqual(Type::Boolean()), | 711 return r.ChangeToPureOperator(simplified()->ReferenceEqual(Type::Boolean()), |
716 invert); | 712 invert); |
717 } | 713 } |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
762 if (r.OneInputCannotBe(Type::NumberOrSimdOrString())) { | 758 if (r.OneInputCannotBe(Type::NumberOrSimdOrString())) { |
763 // For values with canonical representation (i.e. neither String, nor | 759 // For values with canonical representation (i.e. neither String, nor |
764 // Simd128Value nor Number) an empty type intersection means the values | 760 // Simd128Value nor Number) an empty type intersection means the values |
765 // cannot be strictly equal. | 761 // cannot be strictly equal. |
766 if (!r.left_type()->Maybe(r.right_type())) { | 762 if (!r.left_type()->Maybe(r.right_type())) { |
767 Node* replacement = jsgraph()->BooleanConstant(invert); | 763 Node* replacement = jsgraph()->BooleanConstant(invert); |
768 ReplaceWithValue(node, replacement); | 764 ReplaceWithValue(node, replacement); |
769 return Replace(replacement); | 765 return Replace(replacement); |
770 } | 766 } |
771 } | 767 } |
| 768 |
772 Reduction const reduction = ReduceJSEqualTypeOf(node, invert); | 769 Reduction const reduction = ReduceJSEqualTypeOf(node, invert); |
773 if (reduction.Changed()) { | 770 if (reduction.Changed()) return reduction; |
774 return reduction; | 771 |
775 } | |
776 if (r.OneInputIs(the_hole_type_)) { | 772 if (r.OneInputIs(the_hole_type_)) { |
777 return r.ChangeToPureOperator(simplified()->ReferenceEqual(the_hole_type_), | 773 return r.ChangeToPureOperator(simplified()->ReferenceEqual(the_hole_type_), |
778 invert); | 774 invert); |
779 } | 775 } |
780 if (r.OneInputIs(Type::Undefined())) { | 776 if (r.OneInputIs(Type::Undefined())) { |
781 return r.ChangeToPureOperator( | 777 return r.ChangeToPureOperator( |
782 simplified()->ReferenceEqual(Type::Undefined()), invert); | 778 simplified()->ReferenceEqual(Type::Undefined()), invert); |
783 } | 779 } |
784 if (r.OneInputIs(Type::Null())) { | 780 if (r.OneInputIs(Type::Null())) { |
785 return r.ChangeToPureOperator(simplified()->ReferenceEqual(Type::Null()), | 781 return r.ChangeToPureOperator(simplified()->ReferenceEqual(Type::Null()), |
(...skipping 11 matching lines...) Expand all Loading... |
797 return r.ChangeToPureOperator( | 793 return r.ChangeToPureOperator( |
798 simplified()->ReferenceEqual(Type::Receiver()), invert); | 794 simplified()->ReferenceEqual(Type::Receiver()), invert); |
799 } | 795 } |
800 if (r.BothInputsAre(Type::Unique())) { | 796 if (r.BothInputsAre(Type::Unique())) { |
801 return r.ChangeToPureOperator(simplified()->ReferenceEqual(Type::Unique()), | 797 return r.ChangeToPureOperator(simplified()->ReferenceEqual(Type::Unique()), |
802 invert); | 798 invert); |
803 } | 799 } |
804 if (r.BothInputsAre(Type::String())) { | 800 if (r.BothInputsAre(Type::String())) { |
805 return r.ChangeToPureOperator(simplified()->StringEqual(), invert); | 801 return r.ChangeToPureOperator(simplified()->StringEqual(), invert); |
806 } | 802 } |
807 if (r.BothInputsAre(Type::Number())) { | 803 |
| 804 NumberOperationHint hint; |
| 805 if (r.BothInputsAre(Type::Signed32()) || |
| 806 r.BothInputsAre(Type::Unsigned32())) { |
| 807 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert); |
| 808 } else if (r.GetCompareNumberOperationHint(&hint)) { |
| 809 return r.ChangeToSpeculativeOperator( |
| 810 simplified()->SpeculativeNumberEqual(hint), invert, Type::Boolean()); |
| 811 } else if (r.BothInputsAre(Type::Number())) { |
808 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert); | 812 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert); |
809 } | 813 } |
810 // TODO(turbofan): js-typed-lowering of StrictEqual(mixed types) | |
811 return NoChange(); | 814 return NoChange(); |
812 } | 815 } |
813 | 816 |
814 | 817 |
815 Reduction JSTypedLowering::ReduceJSToBoolean(Node* node) { | 818 Reduction JSTypedLowering::ReduceJSToBoolean(Node* node) { |
816 Node* const input = node->InputAt(0); | 819 Node* const input = node->InputAt(0); |
817 Type* const input_type = NodeProperties::GetType(input); | 820 Type* const input_type = NodeProperties::GetType(input); |
818 if (input_type->Is(Type::Boolean())) { | 821 if (input_type->Is(Type::Boolean())) { |
819 // JSToBoolean(x:boolean) => x | 822 // JSToBoolean(x:boolean) => x |
820 return Replace(input); | 823 return Replace(input); |
(...skipping 1302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2123 } | 2126 } |
2124 | 2127 |
2125 | 2128 |
2126 CompilationDependencies* JSTypedLowering::dependencies() const { | 2129 CompilationDependencies* JSTypedLowering::dependencies() const { |
2127 return dependencies_; | 2130 return dependencies_; |
2128 } | 2131 } |
2129 | 2132 |
2130 } // namespace compiler | 2133 } // namespace compiler |
2131 } // namespace internal | 2134 } // namespace internal |
2132 } // namespace v8 | 2135 } // namespace v8 |
OLD | NEW |