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 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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()); | 58 DCHECK_NE(0, node_->op()->ControlOutputCount()); |
59 DCHECK_EQ(1, node_->op()->EffectOutputCount()); | 59 DCHECK_EQ(1, node_->op()->EffectOutputCount()); |
60 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node_->op())); | 60 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node_->op())); |
61 CompareOperationHints hints = CompareOperationHintsOf(node_->op()); | 61 CompareOperationHints hints = CompareOperationHintsOf(node_->op()); |
62 switch (hints.combined()) { | 62 switch (hints.combined()) { |
63 case CompareOperationHints::kSignedSmall: | 63 case CompareOperationHints::kSignedSmall: |
64 *hint = NumberOperationHint::kSignedSmall; | 64 *hint = NumberOperationHint::kSignedSmall; |
65 return true; | 65 return true; |
| 66 case CompareOperationHints::kNumber: |
| 67 *hint = NumberOperationHint::kNumber; |
| 68 return true; |
66 case CompareOperationHints::kNumberOrOddball: | 69 case CompareOperationHints::kNumberOrOddball: |
67 *hint = NumberOperationHint::kNumberOrOddball; | 70 *hint = NumberOperationHint::kNumberOrOddball; |
68 return true; | 71 return true; |
69 case CompareOperationHints::kAny: | 72 case CompareOperationHints::kAny: |
70 case CompareOperationHints::kNone: | 73 case CompareOperationHints::kNone: |
71 case CompareOperationHints::kString: | 74 case CompareOperationHints::kString: |
72 case CompareOperationHints::kBoolean: | 75 case CompareOperationHints::kBoolean: |
73 case CompareOperationHints::kUniqueName: | 76 case CompareOperationHints::kUniqueName: |
74 case CompareOperationHints::kInternalizedString: | 77 case CompareOperationHints::kInternalizedString: |
75 case CompareOperationHints::kReceiver: | 78 case CompareOperationHints::kReceiver: |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
152 // Insert an boolean not to invert the value. | 155 // Insert an boolean not to invert the value. |
153 Node* value = graph()->NewNode(simplified()->BooleanNot(), node_); | 156 Node* value = graph()->NewNode(simplified()->BooleanNot(), node_); |
154 node_->ReplaceUses(value); | 157 node_->ReplaceUses(value); |
155 // Note: ReplaceUses() smashes all uses, so smash it back here. | 158 // Note: ReplaceUses() smashes all uses, so smash it back here. |
156 value->ReplaceInput(0, node_); | 159 value->ReplaceInput(0, node_); |
157 return lowering_->Replace(value); | 160 return lowering_->Replace(value); |
158 } | 161 } |
159 return lowering_->Changed(node_); | 162 return lowering_->Changed(node_); |
160 } | 163 } |
161 | 164 |
162 Reduction ChangeToSpeculativeOperator(const Operator* op, Type* upper_bound) { | 165 Reduction ChangeToSpeculativeOperator(const Operator* op, bool invert, |
| 166 Type* upper_bound) { |
163 DCHECK_EQ(1, op->EffectInputCount()); | 167 DCHECK_EQ(1, op->EffectInputCount()); |
164 DCHECK_EQ(1, op->EffectOutputCount()); | 168 DCHECK_EQ(1, op->EffectOutputCount()); |
165 DCHECK_EQ(false, OperatorProperties::HasContextInput(op)); | 169 DCHECK_EQ(false, OperatorProperties::HasContextInput(op)); |
166 DCHECK_EQ(1, op->ControlInputCount()); | 170 DCHECK_EQ(1, op->ControlInputCount()); |
167 DCHECK_EQ(0, op->ControlOutputCount()); | 171 DCHECK_EQ(0, op->ControlOutputCount()); |
168 DCHECK_EQ(0, OperatorProperties::GetFrameStateInputCount(op)); | 172 DCHECK_EQ(0, OperatorProperties::GetFrameStateInputCount(op)); |
169 DCHECK_EQ(2, op->ValueInputCount()); | 173 DCHECK_EQ(2, op->ValueInputCount()); |
170 | 174 |
171 DCHECK_EQ(1, node_->op()->EffectInputCount()); | 175 DCHECK_EQ(1, node_->op()->EffectInputCount()); |
172 DCHECK_EQ(1, node_->op()->EffectOutputCount()); | 176 DCHECK_EQ(1, node_->op()->EffectOutputCount()); |
(...skipping 22 matching lines...) Expand all Loading... |
195 node_->RemoveInput(NodeProperties::FirstFrameStateIndex(node_)); | 199 node_->RemoveInput(NodeProperties::FirstFrameStateIndex(node_)); |
196 node_->RemoveInput(NodeProperties::FirstContextIndex(node_)); | 200 node_->RemoveInput(NodeProperties::FirstContextIndex(node_)); |
197 | 201 |
198 NodeProperties::ChangeOp(node_, op); | 202 NodeProperties::ChangeOp(node_, op); |
199 | 203 |
200 // Update the type to number. | 204 // Update the type to number. |
201 Type* node_type = NodeProperties::GetType(node_); | 205 Type* node_type = NodeProperties::GetType(node_); |
202 NodeProperties::SetType(node_, | 206 NodeProperties::SetType(node_, |
203 Type::Intersect(node_type, upper_bound, zone())); | 207 Type::Intersect(node_type, upper_bound, zone())); |
204 | 208 |
| 209 if (invert) { |
| 210 // Insert an boolean not to invert the value. |
| 211 Node* value = graph()->NewNode(simplified()->BooleanNot(), node_); |
| 212 node_->ReplaceUses(value); |
| 213 // Note: ReplaceUses() smashes all uses, so smash it back here. |
| 214 value->ReplaceInput(0, node_); |
| 215 return lowering_->Replace(value); |
| 216 } |
205 return lowering_->Changed(node_); | 217 return lowering_->Changed(node_); |
206 } | 218 } |
207 | 219 |
208 Reduction ChangeToPureOperator(const Operator* op, Type* type) { | 220 Reduction ChangeToPureOperator(const Operator* op, Type* type) { |
209 return ChangeToPureOperator(op, false, type); | 221 return ChangeToPureOperator(op, false, type); |
210 } | 222 } |
211 | 223 |
| 224 Reduction ChangeToSpeculativeOperator(const Operator* op, Type* type) { |
| 225 return ChangeToSpeculativeOperator(op, false, type); |
| 226 } |
| 227 |
212 bool LeftInputIs(Type* t) { return left_type()->Is(t); } | 228 bool LeftInputIs(Type* t) { return left_type()->Is(t); } |
213 | 229 |
214 bool RightInputIs(Type* t) { return right_type()->Is(t); } | 230 bool RightInputIs(Type* t) { return right_type()->Is(t); } |
215 | 231 |
216 bool OneInputIs(Type* t) { return LeftInputIs(t) || RightInputIs(t); } | 232 bool OneInputIs(Type* t) { return LeftInputIs(t) || RightInputIs(t); } |
217 | 233 |
218 bool BothInputsAre(Type* t) { return LeftInputIs(t) && RightInputIs(t); } | 234 bool BothInputsAre(Type* t) { return LeftInputIs(t) && RightInputIs(t); } |
219 | 235 |
220 bool OneInputCannotBe(Type* t) { | 236 bool OneInputCannotBe(Type* t) { |
221 return !left_type()->Maybe(t) || !right_type()->Maybe(t); | 237 return !left_type()->Maybe(t) || !right_type()->Maybe(t); |
(...skipping 463 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
685 | 701 |
686 Reduction JSTypedLowering::ReduceJSEqual(Node* node, bool invert) { | 702 Reduction JSTypedLowering::ReduceJSEqual(Node* node, bool invert) { |
687 Reduction const reduction = ReduceJSEqualTypeOf(node, invert); | 703 Reduction const reduction = ReduceJSEqualTypeOf(node, invert); |
688 if (reduction.Changed()) { | 704 if (reduction.Changed()) { |
689 ReplaceWithValue(node, reduction.replacement()); | 705 ReplaceWithValue(node, reduction.replacement()); |
690 return reduction; | 706 return reduction; |
691 } | 707 } |
692 | 708 |
693 JSBinopReduction r(this, node); | 709 JSBinopReduction r(this, node); |
694 | 710 |
695 if (r.BothInputsAre(Type::Number())) { | |
696 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert); | |
697 } | |
698 if (r.BothInputsAre(Type::String())) { | 711 if (r.BothInputsAre(Type::String())) { |
699 return r.ChangeToPureOperator(simplified()->StringEqual(), invert); | 712 return r.ChangeToPureOperator(simplified()->StringEqual(), invert); |
700 } | 713 } |
701 if (r.BothInputsAre(Type::Boolean())) { | 714 if (r.BothInputsAre(Type::Boolean())) { |
702 return r.ChangeToPureOperator(simplified()->ReferenceEqual(Type::Boolean()), | 715 return r.ChangeToPureOperator(simplified()->ReferenceEqual(Type::Boolean()), |
703 invert); | 716 invert); |
704 } | 717 } |
705 if (r.BothInputsAre(Type::Receiver())) { | 718 if (r.BothInputsAre(Type::Receiver())) { |
706 return r.ChangeToPureOperator( | 719 return r.ChangeToPureOperator( |
707 simplified()->ReferenceEqual(Type::Receiver()), invert); | 720 simplified()->ReferenceEqual(Type::Receiver()), invert); |
708 } | 721 } |
709 if (r.OneInputIs(Type::Undetectable())) { | 722 if (r.OneInputIs(Type::Undetectable())) { |
710 RelaxEffectsAndControls(node); | 723 RelaxEffectsAndControls(node); |
711 node->RemoveInput(r.LeftInputIs(Type::Undetectable()) ? 0 : 1); | 724 node->RemoveInput(r.LeftInputIs(Type::Undetectable()) ? 0 : 1); |
712 node->TrimInputCount(1); | 725 node->TrimInputCount(1); |
713 NodeProperties::ChangeOp(node, simplified()->ObjectIsUndetectable()); | 726 NodeProperties::ChangeOp(node, simplified()->ObjectIsUndetectable()); |
714 if (invert) { | 727 if (invert) { |
715 // Insert an boolean not to invert the value. | 728 // Insert an boolean not to invert the value. |
716 Node* value = graph()->NewNode(simplified()->BooleanNot(), node); | 729 Node* value = graph()->NewNode(simplified()->BooleanNot(), node); |
717 node->ReplaceUses(value); | 730 node->ReplaceUses(value); |
718 // Note: ReplaceUses() smashes all uses, so smash it back here. | 731 // Note: ReplaceUses() smashes all uses, so smash it back here. |
719 value->ReplaceInput(0, node); | 732 value->ReplaceInput(0, node); |
720 return Replace(value); | 733 return Replace(value); |
721 } | 734 } |
722 return Changed(node); | 735 return Changed(node); |
723 } | 736 } |
| 737 |
| 738 NumberOperationHint hint; |
| 739 if (r.BothInputsAre(Type::Signed32()) || |
| 740 r.BothInputsAre(Type::Unsigned32())) { |
| 741 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert); |
| 742 } else if (r.GetCompareNumberOperationHint(&hint)) { |
| 743 return r.ChangeToSpeculativeOperator( |
| 744 simplified()->SpeculativeNumberEqual(hint), invert, Type::Boolean()); |
| 745 } else if (r.BothInputsAre(Type::Number())) { |
| 746 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert); |
| 747 } |
724 return NoChange(); | 748 return NoChange(); |
725 } | 749 } |
726 | 750 |
727 | 751 |
728 Reduction JSTypedLowering::ReduceJSStrictEqual(Node* node, bool invert) { | 752 Reduction JSTypedLowering::ReduceJSStrictEqual(Node* node, bool invert) { |
729 JSBinopReduction r(this, node); | 753 JSBinopReduction r(this, node); |
730 if (r.left() == r.right()) { | 754 if (r.left() == r.right()) { |
731 // x === x is always true if x != NaN | 755 // x === x is always true if x != NaN |
732 if (!r.left_type()->Maybe(Type::NaN())) { | 756 if (!r.left_type()->Maybe(Type::NaN())) { |
733 Node* replacement = jsgraph()->BooleanConstant(!invert); | 757 Node* replacement = jsgraph()->BooleanConstant(!invert); |
(...skipping 1365 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2099 } | 2123 } |
2100 | 2124 |
2101 | 2125 |
2102 CompilationDependencies* JSTypedLowering::dependencies() const { | 2126 CompilationDependencies* JSTypedLowering::dependencies() const { |
2103 return dependencies_; | 2127 return dependencies_; |
2104 } | 2128 } |
2105 | 2129 |
2106 } // namespace compiler | 2130 } // namespace compiler |
2107 } // namespace internal | 2131 } // namespace internal |
2108 } // namespace v8 | 2132 } // namespace v8 |
OLD | NEW |