Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4)

Side by Side Diff: src/compiler/js-typed-lowering.cc

Issue 2639883002: [turbofan] Add Receiver feedback for abstract/strict equality. (Closed)
Patch Set: Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/compiler/js-operator.cc ('k') | src/compiler/opcodes.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
63 return true; 63 return true;
64 case CompareOperationHint::kNumber: 64 case CompareOperationHint::kNumber:
65 *hint = NumberOperationHint::kNumber; 65 *hint = NumberOperationHint::kNumber;
66 return true; 66 return true;
67 case CompareOperationHint::kNumberOrOddball: 67 case CompareOperationHint::kNumberOrOddball:
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 case CompareOperationHint::kReceiver:
73 case CompareOperationHint::kInternalizedString: 74 case CompareOperationHint::kInternalizedString:
74 break; 75 break;
75 } 76 }
76 } 77 }
77 return false; 78 return false;
78 } 79 }
79 80
80 bool IsInternalizedStringCompareOperation() { 81 bool IsInternalizedStringCompareOperation() {
81 if (lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) { 82 if (lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) {
82 DCHECK_EQ(1, node_->op()->EffectOutputCount()); 83 DCHECK_EQ(1, node_->op()->EffectOutputCount());
83 return (CompareOperationHintOf(node_->op()) == 84 return (CompareOperationHintOf(node_->op()) ==
84 CompareOperationHint::kInternalizedString) && 85 CompareOperationHint::kInternalizedString) &&
85 BothInputsMaybe(Type::InternalizedString()); 86 BothInputsMaybe(Type::InternalizedString());
86 } 87 }
87 return false; 88 return false;
88 } 89 }
89 90
91 bool IsReceiverCompareOperation() {
92 if (lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) {
93 DCHECK_EQ(1, node_->op()->EffectOutputCount());
94 return (CompareOperationHintOf(node_->op()) ==
95 CompareOperationHint::kReceiver) &&
96 BothInputsMaybe(Type::Receiver());
97 }
98 return false;
99 }
100
90 // Check if a string addition will definitely result in creating a ConsString, 101 // Check if a string addition will definitely result in creating a ConsString,
91 // i.e. if the combined length of the resulting string exceeds the ConsString 102 // i.e. if the combined length of the resulting string exceeds the ConsString
92 // minimum length. 103 // minimum length.
93 bool ShouldCreateConsString() { 104 bool ShouldCreateConsString() {
94 DCHECK_EQ(IrOpcode::kJSAdd, node_->opcode()); 105 DCHECK_EQ(IrOpcode::kJSAdd, node_->opcode());
95 if (BothInputsAre(Type::String()) || 106 if (BothInputsAre(Type::String()) ||
96 ((lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) && 107 ((lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) &&
97 BinaryOperationHintOf(node_->op()) == BinaryOperationHint::kString)) { 108 BinaryOperationHintOf(node_->op()) == BinaryOperationHint::kString)) {
98 HeapObjectBinopMatcher m(node_); 109 HeapObjectBinopMatcher m(node_);
99 if (m.right().HasValue() && m.right().Value()->IsString()) { 110 if (m.right().HasValue() && m.right().Value()->IsString()) {
100 Handle<String> right_string = Handle<String>::cast(m.right().Value()); 111 Handle<String> right_string = Handle<String>::cast(m.right().Value());
101 if (right_string->length() >= ConsString::kMinLength) return true; 112 if (right_string->length() >= ConsString::kMinLength) return true;
102 } 113 }
103 if (m.left().HasValue() && m.left().Value()->IsString()) { 114 if (m.left().HasValue() && m.left().Value()->IsString()) {
104 Handle<String> left_string = Handle<String>::cast(m.left().Value()); 115 Handle<String> left_string = Handle<String>::cast(m.left().Value());
105 if (left_string->length() >= ConsString::kMinLength) { 116 if (left_string->length() >= ConsString::kMinLength) {
106 // The invariant for ConsString requires the left hand side to be 117 // The invariant for ConsString requires the left hand side to be
107 // a sequential or external string if the right hand side is the 118 // a sequential or external string if the right hand side is the
108 // empty string. Since we don't know anything about the right hand 119 // empty string. Since we don't know anything about the right hand
109 // side here, we must ensure that the left hand side satisfy the 120 // side here, we must ensure that the left hand side satisfy the
110 // constraints independent of the right hand side. 121 // constraints independent of the right hand side.
111 return left_string->IsSeqString() || left_string->IsExternalString(); 122 return left_string->IsSeqString() || left_string->IsExternalString();
112 } 123 }
113 } 124 }
114 } 125 }
115 return false; 126 return false;
116 } 127 }
117 128
129 // Inserts a CheckReceiver for the left input.
130 void CheckLeftInputToReceiver() {
131 Node* left_input = graph()->NewNode(simplified()->CheckReceiver(), left(),
132 effect(), control());
133 node_->ReplaceInput(0, left_input);
134 update_effect(left_input);
135 }
136
137 // Checks that both inputs are Receiver, and if we don't know
138 // statically that one side is already a Receiver, insert a
139 // CheckReceiver node.
140 void CheckInputsToReceiver() {
141 if (!left_type()->Is(Type::Receiver())) {
142 CheckLeftInputToReceiver();
143 }
144 if (!right_type()->Is(Type::Receiver())) {
145 Node* right_input = graph()->NewNode(simplified()->CheckReceiver(),
146 right(), effect(), control());
147 node_->ReplaceInput(1, right_input);
148 update_effect(right_input);
149 }
150 }
151
118 // Checks that both inputs are InternalizedString, and if we don't know 152 // Checks that both inputs are InternalizedString, and if we don't know
119 // statically that one side is already an InternalizedString, insert a 153 // statically that one side is already an InternalizedString, insert a
120 // CheckInternalizedString node. 154 // CheckInternalizedString node.
121 void CheckInputsToInternalizedString() { 155 void CheckInputsToInternalizedString() {
122 if (!left_type()->Is(Type::UniqueName())) { 156 if (!left_type()->Is(Type::UniqueName())) {
123 Node* left_input = graph()->NewNode( 157 Node* left_input = graph()->NewNode(
124 simplified()->CheckInternalizedString(), left(), effect(), control()); 158 simplified()->CheckInternalizedString(), left(), effect(), control());
125 node_->ReplaceInput(0, left_input); 159 node_->ReplaceInput(0, left_input);
126 update_effect(left_input); 160 update_effect(left_input);
127 } 161 }
(...skipping 789 matching lines...) Expand 10 before | Expand all | Expand 10 after
917 951
918 NumberOperationHint hint; 952 NumberOperationHint hint;
919 if (r.BothInputsAre(Type::Signed32()) || 953 if (r.BothInputsAre(Type::Signed32()) ||
920 r.BothInputsAre(Type::Unsigned32())) { 954 r.BothInputsAre(Type::Unsigned32())) {
921 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert); 955 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert);
922 } else if (r.GetCompareNumberOperationHint(&hint)) { 956 } else if (r.GetCompareNumberOperationHint(&hint)) {
923 return r.ChangeToSpeculativeOperator( 957 return r.ChangeToSpeculativeOperator(
924 simplified()->SpeculativeNumberEqual(hint), invert, Type::Boolean()); 958 simplified()->SpeculativeNumberEqual(hint), invert, Type::Boolean());
925 } else if (r.BothInputsAre(Type::Number())) { 959 } else if (r.BothInputsAre(Type::Number())) {
926 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert); 960 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert);
961 } else if (r.IsReceiverCompareOperation()) {
962 r.CheckInputsToReceiver();
963 return r.ChangeToPureOperator(simplified()->ReferenceEqual(), invert);
927 } 964 }
928 return NoChange(); 965 return NoChange();
929 } 966 }
930 967
931 Reduction JSTypedLowering::ReduceJSStrictEqual(Node* node, bool invert) { 968 Reduction JSTypedLowering::ReduceJSStrictEqual(Node* node, bool invert) {
932 JSBinopReduction r(this, node); 969 JSBinopReduction r(this, node);
933 if (r.left() == r.right()) { 970 if (r.left() == r.right()) {
934 // x === x is always true if x != NaN 971 // x === x is always true if x != NaN
935 if (!r.left_type()->Maybe(Type::NaN())) { 972 if (!r.left_type()->Maybe(Type::NaN())) {
936 Node* replacement = jsgraph()->BooleanConstant(!invert); 973 Node* replacement = jsgraph()->BooleanConstant(!invert);
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
968 1005
969 NumberOperationHint hint; 1006 NumberOperationHint hint;
970 if (r.BothInputsAre(Type::Signed32()) || 1007 if (r.BothInputsAre(Type::Signed32()) ||
971 r.BothInputsAre(Type::Unsigned32())) { 1008 r.BothInputsAre(Type::Unsigned32())) {
972 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert); 1009 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert);
973 } else if (r.GetCompareNumberOperationHint(&hint)) { 1010 } else if (r.GetCompareNumberOperationHint(&hint)) {
974 return r.ChangeToSpeculativeOperator( 1011 return r.ChangeToSpeculativeOperator(
975 simplified()->SpeculativeNumberEqual(hint), invert, Type::Boolean()); 1012 simplified()->SpeculativeNumberEqual(hint), invert, Type::Boolean());
976 } else if (r.BothInputsAre(Type::Number())) { 1013 } else if (r.BothInputsAre(Type::Number())) {
977 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert); 1014 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert);
1015 } else if (r.IsReceiverCompareOperation()) {
1016 // For strict equality, it's enough to know that one input is a Receiver,
1017 // as a strict equality comparison with a Receiver can only yield true if
1018 // both sides refer to the same Receiver than.
1019 r.CheckLeftInputToReceiver();
1020 return r.ChangeToPureOperator(simplified()->ReferenceEqual(), invert);
978 } 1021 }
979 return NoChange(); 1022 return NoChange();
980 } 1023 }
981 1024
982 Reduction JSTypedLowering::ReduceJSToBoolean(Node* node) { 1025 Reduction JSTypedLowering::ReduceJSToBoolean(Node* node) {
983 Node* const input = node->InputAt(0); 1026 Node* const input = node->InputAt(0);
984 Type* const input_type = NodeProperties::GetType(input); 1027 Type* const input_type = NodeProperties::GetType(input);
985 if (input_type->Is(Type::Boolean())) { 1028 if (input_type->Is(Type::Boolean())) {
986 // JSToBoolean(x:boolean) => x 1029 // JSToBoolean(x:boolean) => x
987 return Replace(input); 1030 return Replace(input);
(...skipping 1355 matching lines...) Expand 10 before | Expand all | Expand 10 after
2343 } 2386 }
2344 2387
2345 2388
2346 CompilationDependencies* JSTypedLowering::dependencies() const { 2389 CompilationDependencies* JSTypedLowering::dependencies() const {
2347 return dependencies_; 2390 return dependencies_;
2348 } 2391 }
2349 2392
2350 } // namespace compiler 2393 } // namespace compiler
2351 } // namespace internal 2394 } // namespace internal
2352 } // namespace v8 2395 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/js-operator.cc ('k') | src/compiler/opcodes.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698