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

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

Issue 741503006: [turbofan] Narrow upper bounds during typed lowering. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 6 years 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 | « no previous file | no next file » | 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/access-builder.h" 5 #include "src/compiler/access-builder.h"
6 #include "src/compiler/graph-inl.h" 6 #include "src/compiler/graph-inl.h"
7 #include "src/compiler/js-builtin-reducer.h" 7 #include "src/compiler/js-builtin-reducer.h"
8 #include "src/compiler/js-typed-lowering.h" 8 #include "src/compiler/js-typed-lowering.h"
9 #include "src/compiler/node-aux-data-inl.h" 9 #include "src/compiler/node-aux-data-inl.h"
10 #include "src/compiler/node-matchers.h" 10 #include "src/compiler/node-matchers.h"
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
107 void SwapInputs() { 107 void SwapInputs() {
108 Node* l = left(); 108 Node* l = left();
109 Node* r = right(); 109 Node* r = right();
110 node_->ReplaceInput(0, r); 110 node_->ReplaceInput(0, r);
111 node_->ReplaceInput(1, l); 111 node_->ReplaceInput(1, l);
112 std::swap(left_type_, right_type_); 112 std::swap(left_type_, right_type_);
113 } 113 }
114 114
115 // Remove all effect and control inputs and outputs to this node and change 115 // Remove all effect and control inputs and outputs to this node and change
116 // to the pure operator {op}, possibly inserting a boolean inversion. 116 // to the pure operator {op}, possibly inserting a boolean inversion.
117 Reduction ChangeToPureOperator(const Operator* op, bool invert = false) { 117 Reduction ChangeToPureOperator(const Operator* op, bool invert = false,
118 Type* type = Type::Any()) {
118 DCHECK_EQ(0, op->EffectInputCount()); 119 DCHECK_EQ(0, op->EffectInputCount());
119 DCHECK_EQ(false, OperatorProperties::HasContextInput(op)); 120 DCHECK_EQ(false, OperatorProperties::HasContextInput(op));
120 DCHECK_EQ(0, op->ControlInputCount()); 121 DCHECK_EQ(0, op->ControlInputCount());
121 DCHECK_EQ(2, op->ValueInputCount()); 122 DCHECK_EQ(2, op->ValueInputCount());
122 123
123 // Remove the effects from the node, if any, and update its effect usages. 124 // Remove the effects from the node, if any, and update its effect usages.
124 if (node_->op()->EffectInputCount() > 0) { 125 if (node_->op()->EffectInputCount() > 0) {
125 RelaxEffects(node_); 126 RelaxEffects(node_);
126 } 127 }
127 // Remove the inputs corresponding to context, effect, and control. 128 // Remove the inputs corresponding to context, effect, and control.
128 NodeProperties::RemoveNonValueInputs(node_); 129 NodeProperties::RemoveNonValueInputs(node_);
129 // Finally, update the operator to the new one. 130 // Finally, update the operator to the new one.
130 node_->set_op(op); 131 node_->set_op(op);
131 132
133 // TODO(jarin): Narrow the type after patching the operator.
Jarin 2014/12/04 10:43:01 This is not really a big fat TODO. Could you write
Benedikt Meurer 2014/12/04 11:19:01 Done.
134 Bounds const bounds = NodeProperties::GetBounds(node_);
135 NodeProperties::SetBounds(node_, Bounds::NarrowUpper(bounds, type, zone()));
136
132 if (invert) { 137 if (invert) {
133 // Insert an boolean not to invert the value. 138 // Insert an boolean not to invert the value.
134 Node* value = graph()->NewNode(simplified()->BooleanNot(), node_); 139 Node* value = graph()->NewNode(simplified()->BooleanNot(), node_);
135 node_->ReplaceUses(value); 140 node_->ReplaceUses(value);
136 // Note: ReplaceUses() smashes all uses, so smash it back here. 141 // Note: ReplaceUses() smashes all uses, so smash it back here.
137 value->ReplaceInput(0, node_); 142 value->ReplaceInput(0, node_);
138 return lowering_->ReplaceWith(value); 143 return lowering_->ReplaceWith(value);
139 } 144 }
140 return lowering_->Changed(node_); 145 return lowering_->Changed(node_);
141 } 146 }
Jarin 2014/12/04 10:43:01 Insert an empty line here?
Benedikt Meurer 2014/12/04 11:19:01 Done.
147 Reduction ChangeToPureOperator(const Operator* op, Type* type) {
148 return ChangeToPureOperator(op, false, type);
149 }
142 150
143 bool OneInputIs(Type* t) { return left_type_->Is(t) || right_type_->Is(t); } 151 bool OneInputIs(Type* t) { return left_type_->Is(t) || right_type_->Is(t); }
144 152
145 bool BothInputsAre(Type* t) { 153 bool BothInputsAre(Type* t) {
146 return left_type_->Is(t) && right_type_->Is(t); 154 return left_type_->Is(t) && right_type_->Is(t);
147 } 155 }
148 156
149 bool OneInputCannotBe(Type* t) { 157 bool OneInputCannotBe(Type* t) {
150 return !left_type_->Maybe(t) || !right_type_->Maybe(t); 158 return !left_type_->Maybe(t) || !right_type_->Maybe(t);
151 } 159 }
152 160
153 bool NeitherInputCanBe(Type* t) { 161 bool NeitherInputCanBe(Type* t) {
154 return !left_type_->Maybe(t) && !right_type_->Maybe(t); 162 return !left_type_->Maybe(t) && !right_type_->Maybe(t);
155 } 163 }
156 164
157 Node* effect() { return NodeProperties::GetEffectInput(node_); } 165 Node* effect() { return NodeProperties::GetEffectInput(node_); }
158 Node* control() { return NodeProperties::GetControlInput(node_); } 166 Node* control() { return NodeProperties::GetControlInput(node_); }
159 Node* context() { return NodeProperties::GetContextInput(node_); } 167 Node* context() { return NodeProperties::GetContextInput(node_); }
160 Node* left() { return NodeProperties::GetValueInput(node_, 0); } 168 Node* left() { return NodeProperties::GetValueInput(node_, 0); }
161 Node* right() { return NodeProperties::GetValueInput(node_, 1); } 169 Node* right() { return NodeProperties::GetValueInput(node_, 1); }
162 Type* left_type() { return left_type_; } 170 Type* left_type() { return left_type_; }
163 Type* right_type() { return right_type_; } 171 Type* right_type() { return right_type_; }
164 172
165 SimplifiedOperatorBuilder* simplified() { return lowering_->simplified(); } 173 SimplifiedOperatorBuilder* simplified() { return lowering_->simplified(); }
166 Graph* graph() { return lowering_->graph(); } 174 Graph* graph() const { return lowering_->graph(); }
167 JSGraph* jsgraph() { return lowering_->jsgraph(); } 175 JSGraph* jsgraph() { return lowering_->jsgraph(); }
168 JSOperatorBuilder* javascript() { return lowering_->javascript(); } 176 JSOperatorBuilder* javascript() { return lowering_->javascript(); }
169 MachineOperatorBuilder* machine() { return lowering_->machine(); } 177 MachineOperatorBuilder* machine() { return lowering_->machine(); }
178 Zone* zone() const { return graph()->zone(); }
170 179
171 private: 180 private:
172 JSTypedLowering* lowering_; // The containing lowering instance. 181 JSTypedLowering* lowering_; // The containing lowering instance.
173 Node* node_; // The original node. 182 Node* node_; // The original node.
174 Type* left_type_; // Cache of the left input's type. 183 Type* left_type_; // Cache of the left input's type.
175 Type* right_type_; // Cache of the right input's type. 184 Type* right_type_; // Cache of the right input's type.
176 185
177 Node* ConvertToString(Node* node) { 186 Node* ConvertToString(Node* node) {
178 // Avoid introducing too many eager ToString() operations. 187 // Avoid introducing too many eager ToString() operations.
179 Reduction reduced = lowering_->ReduceJSToStringInput(node); 188 Reduction reduced = lowering_->ReduceJSToStringInput(node);
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
211 void update_effect(Node* effect) { 220 void update_effect(Node* effect) {
212 NodeProperties::ReplaceEffectInput(node_, effect); 221 NodeProperties::ReplaceEffectInput(node_, effect);
213 } 222 }
214 }; 223 };
215 224
216 225
217 Reduction JSTypedLowering::ReduceJSAdd(Node* node) { 226 Reduction JSTypedLowering::ReduceJSAdd(Node* node) {
218 JSBinopReduction r(this, node); 227 JSBinopReduction r(this, node);
219 if (r.BothInputsAre(Type::Number())) { 228 if (r.BothInputsAre(Type::Number())) {
220 // JSAdd(x:number, y:number) => NumberAdd(x, y) 229 // JSAdd(x:number, y:number) => NumberAdd(x, y)
221 return r.ChangeToPureOperator(simplified()->NumberAdd()); 230 return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number());
222 } 231 }
223 Type* maybe_string = Type::Union(Type::String(), Type::Receiver(), zone()); 232 Type* maybe_string = Type::Union(Type::String(), Type::Receiver(), zone());
224 if (r.BothInputsAre(Type::Primitive()) && r.NeitherInputCanBe(maybe_string)) { 233 if (r.BothInputsAre(Type::Primitive()) && r.NeitherInputCanBe(maybe_string)) {
225 // JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y)) 234 // JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y))
226 r.ConvertInputsToNumber(); 235 r.ConvertInputsToNumber();
227 return r.ChangeToPureOperator(simplified()->NumberAdd()); 236 return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number());
228 } 237 }
229 #if 0 238 #if 0
230 // TODO(turbofan): General ToNumber disabled for now because: 239 // TODO(turbofan): General ToNumber disabled for now because:
231 // a) The inserted ToNumber operation screws up observability of valueOf. 240 // a) The inserted ToNumber operation screws up observability of valueOf.
232 // b) Deoptimization at ToNumber doesn't have corresponding bailout id. 241 // b) Deoptimization at ToNumber doesn't have corresponding bailout id.
233 Type* maybe_string = Type::Union(Type::String(), Type::Receiver(), zone()); 242 Type* maybe_string = Type::Union(Type::String(), Type::Receiver(), zone());
234 if (r.NeitherInputCanBe(maybe_string)) { 243 if (r.NeitherInputCanBe(maybe_string)) {
235 ... 244 ...
236 } 245 }
237 #endif 246 #endif
(...skipping 18 matching lines...) Expand all
256 JSBinopReduction r(this, node); 265 JSBinopReduction r(this, node);
257 if (r.BothInputsAre(Type::Primitive()) || r.OneInputIs(zero_range_)) { 266 if (r.BothInputsAre(Type::Primitive()) || r.OneInputIs(zero_range_)) {
258 // TODO(jarin): Propagate frame state input from non-primitive input node to 267 // TODO(jarin): Propagate frame state input from non-primitive input node to
259 // JSToNumber node. 268 // JSToNumber node.
260 // TODO(titzer): some Smi bitwise operations don't really require going 269 // TODO(titzer): some Smi bitwise operations don't really require going
261 // all the way to int32, which can save tagging/untagging for some 270 // all the way to int32, which can save tagging/untagging for some
262 // operations 271 // operations
263 // on some platforms. 272 // on some platforms.
264 // TODO(turbofan): make this heuristic configurable for code size. 273 // TODO(turbofan): make this heuristic configurable for code size.
265 r.ConvertInputsToInt32(true, true); 274 r.ConvertInputsToInt32(true, true);
266 return r.ChangeToPureOperator(machine()->Word32Or()); 275 return r.ChangeToPureOperator(machine()->Word32Or(), Type::Integral32());
267 } 276 }
268 return NoChange(); 277 return NoChange();
269 } 278 }
270 279
271 280
272 Reduction JSTypedLowering::ReduceJSMultiply(Node* node) { 281 Reduction JSTypedLowering::ReduceJSMultiply(Node* node) {
273 JSBinopReduction r(this, node); 282 JSBinopReduction r(this, node);
274 if (r.BothInputsAre(Type::Primitive()) || r.OneInputIs(one_range_)) { 283 if (r.BothInputsAre(Type::Primitive()) || r.OneInputIs(one_range_)) {
275 // TODO(jarin): Propagate frame state input from non-primitive input node to 284 // TODO(jarin): Propagate frame state input from non-primitive input node to
276 // JSToNumber node. 285 // JSToNumber node.
277 r.ConvertInputsToNumber(); 286 r.ConvertInputsToNumber();
278 return r.ChangeToPureOperator(simplified()->NumberMultiply()); 287 return r.ChangeToPureOperator(simplified()->NumberMultiply(),
288 Type::Number());
279 } 289 }
280 // TODO(turbofan): relax/remove the effects of this operator in other cases. 290 // TODO(turbofan): relax/remove the effects of this operator in other cases.
281 return NoChange(); 291 return NoChange();
282 } 292 }
283 293
284 294
285 Reduction JSTypedLowering::ReduceNumberBinop(Node* node, 295 Reduction JSTypedLowering::ReduceNumberBinop(Node* node,
286 const Operator* numberOp) { 296 const Operator* numberOp) {
287 JSBinopReduction r(this, node); 297 JSBinopReduction r(this, node);
288 if (r.BothInputsAre(Type::Primitive())) { 298 if (r.BothInputsAre(Type::Primitive())) {
289 r.ConvertInputsToNumber(); 299 r.ConvertInputsToNumber();
290 return r.ChangeToPureOperator(numberOp); 300 return r.ChangeToPureOperator(numberOp, Type::Number());
291 } 301 }
292 #if 0 302 #if 0
293 // TODO(turbofan): General ToNumber disabled for now because: 303 // TODO(turbofan): General ToNumber disabled for now because:
294 // a) The inserted ToNumber operation screws up observability of valueOf. 304 // a) The inserted ToNumber operation screws up observability of valueOf.
295 // b) Deoptimization at ToNumber doesn't have corresponding bailout id. 305 // b) Deoptimization at ToNumber doesn't have corresponding bailout id.
296 if (r.OneInputIs(Type::Primitive())) { 306 if (r.OneInputIs(Type::Primitive())) {
297 // If at least one input is a primitive, then insert appropriate conversions 307 // If at least one input is a primitive, then insert appropriate conversions
298 // to number and reduce this operator to the given numeric one. 308 // to number and reduce this operator to the given numeric one.
299 // TODO(turbofan): make this heuristic configurable for code size. 309 // TODO(turbofan): make this heuristic configurable for code size.
300 r.ConvertInputsToNumber(); 310 r.ConvertInputsToNumber();
301 return r.ChangeToPureOperator(numberOp); 311 return r.ChangeToPureOperator(numberOp);
302 } 312 }
303 #endif 313 #endif
304 // TODO(turbofan): relax/remove the effects of this operator in other cases. 314 // TODO(turbofan): relax/remove the effects of this operator in other cases.
305 return NoChange(); 315 return NoChange();
306 } 316 }
307 317
308 318
309 Reduction JSTypedLowering::ReduceI32Binop(Node* node, bool left_signed, 319 Reduction JSTypedLowering::ReduceI32Binop(Node* node, bool left_signed,
310 bool right_signed, 320 bool right_signed,
311 const Operator* intOp) { 321 const Operator* intOp) {
312 JSBinopReduction r(this, node); 322 JSBinopReduction r(this, node);
313 if (r.BothInputsAre(Type::Primitive())) { 323 if (r.BothInputsAre(Type::Primitive())) {
314 // TODO(titzer): some Smi bitwise operations don't really require going 324 // TODO(titzer): some Smi bitwise operations don't really require going
315 // all the way to int32, which can save tagging/untagging for some 325 // all the way to int32, which can save tagging/untagging for some
316 // operations 326 // operations
317 // on some platforms. 327 // on some platforms.
318 // TODO(turbofan): make this heuristic configurable for code size. 328 // TODO(turbofan): make this heuristic configurable for code size.
319 r.ConvertInputsToInt32(left_signed, right_signed); 329 r.ConvertInputsToInt32(left_signed, right_signed);
320 return r.ChangeToPureOperator(intOp); 330 return r.ChangeToPureOperator(intOp, Type::Integral32());
321 } 331 }
322 return NoChange(); 332 return NoChange();
323 } 333 }
324 334
325 335
326 Reduction JSTypedLowering::ReduceI32Shift(Node* node, bool left_signed, 336 Reduction JSTypedLowering::ReduceI32Shift(Node* node, bool left_signed,
327 const Operator* shift_op) { 337 const Operator* shift_op) {
328 JSBinopReduction r(this, node); 338 JSBinopReduction r(this, node);
329 if (r.BothInputsAre(Type::Primitive())) { 339 if (r.BothInputsAre(Type::Primitive())) {
330 r.ConvertInputsForShift(left_signed); 340 r.ConvertInputsForShift(left_signed);
331 return r.ChangeToPureOperator(shift_op); 341 return r.ChangeToPureOperator(shift_op, Type::Integral32());
332 } 342 }
333 return NoChange(); 343 return NoChange();
334 } 344 }
335 345
336 346
337 Reduction JSTypedLowering::ReduceJSComparison(Node* node) { 347 Reduction JSTypedLowering::ReduceJSComparison(Node* node) {
338 JSBinopReduction r(this, node); 348 JSBinopReduction r(this, node);
339 if (r.BothInputsAre(Type::String())) { 349 if (r.BothInputsAre(Type::String())) {
340 // If both inputs are definitely strings, perform a string comparison. 350 // If both inputs are definitely strings, perform a string comparison.
341 const Operator* stringOp; 351 const Operator* stringOp;
(...skipping 557 matching lines...) Expand 10 before | Expand all | Expand 10 after
899 909
900 Node* JSTypedLowering::Word32Shl(Node* const lhs, int32_t const rhs) { 910 Node* JSTypedLowering::Word32Shl(Node* const lhs, int32_t const rhs) {
901 if (rhs == 0) return lhs; 911 if (rhs == 0) return lhs;
902 return graph()->NewNode(machine()->Word32Shl(), lhs, 912 return graph()->NewNode(machine()->Word32Shl(), lhs,
903 jsgraph()->Int32Constant(rhs)); 913 jsgraph()->Int32Constant(rhs));
904 } 914 }
905 915
906 } // namespace compiler 916 } // namespace compiler
907 } // namespace internal 917 } // namespace internal
908 } // namespace v8 918 } // namespace v8
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698