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/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-typed-lowering.h" | 7 #include "src/compiler/js-typed-lowering.h" |
8 #include "src/compiler/node-aux-data-inl.h" | 8 #include "src/compiler/node-aux-data-inl.h" |
9 #include "src/compiler/node-properties-inl.h" | 9 #include "src/compiler/node-properties-inl.h" |
10 #include "src/types.h" | 10 #include "src/types.h" |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
72 void SwapInputs() { | 72 void SwapInputs() { |
73 Node* l = left(); | 73 Node* l = left(); |
74 Node* r = right(); | 74 Node* r = right(); |
75 node_->ReplaceInput(0, r); | 75 node_->ReplaceInput(0, r); |
76 node_->ReplaceInput(1, l); | 76 node_->ReplaceInput(1, l); |
77 std::swap(left_type_, right_type_); | 77 std::swap(left_type_, right_type_); |
78 } | 78 } |
79 | 79 |
80 // Remove all effect and control inputs and outputs to this node and change | 80 // Remove all effect and control inputs and outputs to this node and change |
81 // to the pure operator {op}, possibly inserting a boolean inversion. | 81 // to the pure operator {op}, possibly inserting a boolean inversion. |
82 Reduction ChangeToPureOperator(Operator* op, bool invert = false) { | 82 Reduction ChangeToPureOperator(const Operator* op, bool invert = false) { |
83 DCHECK_EQ(0, OperatorProperties::GetEffectInputCount(op)); | 83 DCHECK_EQ(0, OperatorProperties::GetEffectInputCount(op)); |
84 DCHECK_EQ(false, OperatorProperties::HasContextInput(op)); | 84 DCHECK_EQ(false, OperatorProperties::HasContextInput(op)); |
85 DCHECK_EQ(0, OperatorProperties::GetControlInputCount(op)); | 85 DCHECK_EQ(0, OperatorProperties::GetControlInputCount(op)); |
86 DCHECK_EQ(2, OperatorProperties::GetValueInputCount(op)); | 86 DCHECK_EQ(2, OperatorProperties::GetValueInputCount(op)); |
87 | 87 |
88 // Remove the effects from the node, if any, and update its effect usages. | 88 // Remove the effects from the node, if any, and update its effect usages. |
89 if (OperatorProperties::GetEffectInputCount(node_->op()) > 0) { | 89 if (OperatorProperties::GetEffectInputCount(node_->op()) > 0) { |
90 RelaxEffects(node_); | 90 RelaxEffects(node_); |
91 } | 91 } |
92 // Remove the inputs corresponding to context, effect, and control. | 92 // Remove the inputs corresponding to context, effect, and control. |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
198 // further lowering passes deal with it, which use a full backwards | 198 // further lowering passes deal with it, which use a full backwards |
199 // fixpoint. | 199 // fixpoint. |
200 } | 200 } |
201 | 201 |
202 // Avoid introducing too many eager NumberToXXnt32() operations. | 202 // Avoid introducing too many eager NumberToXXnt32() operations. |
203 node = ConvertToNumber(node); | 203 node = ConvertToNumber(node); |
204 Type* input_type = NodeProperties::GetBounds(node).upper; | 204 Type* input_type = NodeProperties::GetBounds(node).upper; |
205 | 205 |
206 if (input_type->Is(type)) return node; // already in the value range. | 206 if (input_type->Is(type)) return node; // already in the value range. |
207 | 207 |
208 Operator* op = is_signed ? simplified()->NumberToInt32() | 208 const Operator* op = is_signed ? simplified()->NumberToInt32() |
209 : simplified()->NumberToUint32(); | 209 : simplified()->NumberToUint32(); |
210 Node* n = graph()->NewNode(op, node); | 210 Node* n = graph()->NewNode(op, node); |
211 return n; | 211 return n; |
212 } | 212 } |
213 | 213 |
214 void update_effect(Node* effect) { | 214 void update_effect(Node* effect) { |
215 NodeProperties::ReplaceEffectInput(node_, effect); | 215 NodeProperties::ReplaceEffectInput(node_, effect); |
216 } | 216 } |
217 }; | 217 }; |
218 | 218 |
219 | 219 |
220 Reduction JSTypedLowering::ReduceJSAdd(Node* node) { | 220 Reduction JSTypedLowering::ReduceJSAdd(Node* node) { |
221 JSBinopReduction r(this, node); | 221 JSBinopReduction r(this, node); |
222 if (r.OneInputIs(Type::String())) { | 222 if (r.OneInputIs(Type::String())) { |
223 r.ConvertInputsToString(); | 223 r.ConvertInputsToString(); |
224 return r.ChangeToPureOperator(simplified()->StringAdd()); | 224 return r.ChangeToPureOperator(simplified()->StringAdd()); |
225 } | 225 } |
226 if (r.NeitherInputCanBe(Type::String())) { | 226 if (r.NeitherInputCanBe(Type::String())) { |
227 r.ConvertInputsToNumber(); | 227 r.ConvertInputsToNumber(); |
228 return r.ChangeToPureOperator(simplified()->NumberAdd()); | 228 return r.ChangeToPureOperator(simplified()->NumberAdd()); |
229 } | 229 } |
230 return NoChange(); | 230 return NoChange(); |
231 } | 231 } |
232 | 232 |
233 | 233 |
234 Reduction JSTypedLowering::ReduceNumberBinop(Node* node, Operator* numberOp) { | 234 Reduction JSTypedLowering::ReduceNumberBinop(Node* node, |
| 235 const Operator* numberOp) { |
235 JSBinopReduction r(this, node); | 236 JSBinopReduction r(this, node); |
236 if (r.OneInputIs(Type::Primitive())) { | 237 if (r.OneInputIs(Type::Primitive())) { |
237 // If at least one input is a primitive, then insert appropriate conversions | 238 // If at least one input is a primitive, then insert appropriate conversions |
238 // to number and reduce this operator to the given numeric one. | 239 // to number and reduce this operator to the given numeric one. |
239 // TODO(turbofan): make this heuristic configurable for code size. | 240 // TODO(turbofan): make this heuristic configurable for code size. |
240 r.ConvertInputsToNumber(); | 241 r.ConvertInputsToNumber(); |
241 return r.ChangeToPureOperator(numberOp); | 242 return r.ChangeToPureOperator(numberOp); |
242 } | 243 } |
243 // TODO(turbofan): relax/remove the effects of this operator in other cases. | 244 // TODO(turbofan): relax/remove the effects of this operator in other cases. |
244 return NoChange(); | 245 return NoChange(); |
245 } | 246 } |
246 | 247 |
247 | 248 |
248 Reduction JSTypedLowering::ReduceI32Binop(Node* node, bool left_signed, | 249 Reduction JSTypedLowering::ReduceI32Binop(Node* node, bool left_signed, |
249 bool right_signed, Operator* intOp) { | 250 bool right_signed, |
| 251 const Operator* intOp) { |
250 JSBinopReduction r(this, node); | 252 JSBinopReduction r(this, node); |
251 // TODO(titzer): some Smi bitwise operations don't really require going | 253 // TODO(titzer): some Smi bitwise operations don't really require going |
252 // all the way to int32, which can save tagging/untagging for some operations | 254 // all the way to int32, which can save tagging/untagging for some operations |
253 // on some platforms. | 255 // on some platforms. |
254 // TODO(turbofan): make this heuristic configurable for code size. | 256 // TODO(turbofan): make this heuristic configurable for code size. |
255 r.ConvertInputsToInt32(left_signed, right_signed); | 257 r.ConvertInputsToInt32(left_signed, right_signed); |
256 return r.ChangeToPureOperator(intOp); | 258 return r.ChangeToPureOperator(intOp); |
257 } | 259 } |
258 | 260 |
259 | 261 |
260 Reduction JSTypedLowering::ReduceI32Shift(Node* node, bool left_signed, | 262 Reduction JSTypedLowering::ReduceI32Shift(Node* node, bool left_signed, |
261 Operator* shift_op) { | 263 const Operator* shift_op) { |
262 JSBinopReduction r(this, node); | 264 JSBinopReduction r(this, node); |
263 r.ConvertInputsForShift(left_signed); | 265 r.ConvertInputsForShift(left_signed); |
264 return r.ChangeToPureOperator(shift_op); | 266 return r.ChangeToPureOperator(shift_op); |
265 } | 267 } |
266 | 268 |
267 | 269 |
268 Reduction JSTypedLowering::ReduceJSComparison(Node* node) { | 270 Reduction JSTypedLowering::ReduceJSComparison(Node* node) { |
269 JSBinopReduction r(this, node); | 271 JSBinopReduction r(this, node); |
270 if (r.BothInputsAre(Type::String())) { | 272 if (r.BothInputsAre(Type::String())) { |
271 // If both inputs are definitely strings, perform a string comparison. | 273 // If both inputs are definitely strings, perform a string comparison. |
272 Operator* stringOp; | 274 const Operator* stringOp; |
273 switch (node->opcode()) { | 275 switch (node->opcode()) { |
274 case IrOpcode::kJSLessThan: | 276 case IrOpcode::kJSLessThan: |
275 stringOp = simplified()->StringLessThan(); | 277 stringOp = simplified()->StringLessThan(); |
276 break; | 278 break; |
277 case IrOpcode::kJSGreaterThan: | 279 case IrOpcode::kJSGreaterThan: |
278 stringOp = simplified()->StringLessThan(); | 280 stringOp = simplified()->StringLessThan(); |
279 r.SwapInputs(); // a > b => b < a | 281 r.SwapInputs(); // a > b => b < a |
280 break; | 282 break; |
281 case IrOpcode::kJSLessThanOrEqual: | 283 case IrOpcode::kJSLessThanOrEqual: |
282 stringOp = simplified()->StringLessThanOrEqual(); | 284 stringOp = simplified()->StringLessThanOrEqual(); |
283 break; | 285 break; |
284 case IrOpcode::kJSGreaterThanOrEqual: | 286 case IrOpcode::kJSGreaterThanOrEqual: |
285 stringOp = simplified()->StringLessThanOrEqual(); | 287 stringOp = simplified()->StringLessThanOrEqual(); |
286 r.SwapInputs(); // a >= b => b <= a | 288 r.SwapInputs(); // a >= b => b <= a |
287 break; | 289 break; |
288 default: | 290 default: |
289 return NoChange(); | 291 return NoChange(); |
290 } | 292 } |
291 return r.ChangeToPureOperator(stringOp); | 293 return r.ChangeToPureOperator(stringOp); |
292 } else if (r.OneInputCannotBe(Type::String())) { | 294 } else if (r.OneInputCannotBe(Type::String())) { |
293 // If one input cannot be a string, then emit a number comparison. | 295 // If one input cannot be a string, then emit a number comparison. |
294 Operator* less_than; | 296 const Operator* less_than; |
295 Operator* less_than_or_equal; | 297 const Operator* less_than_or_equal; |
296 if (r.BothInputsAre(Type::Unsigned32())) { | 298 if (r.BothInputsAre(Type::Unsigned32())) { |
297 less_than = machine()->Uint32LessThan(); | 299 less_than = machine()->Uint32LessThan(); |
298 less_than_or_equal = machine()->Uint32LessThanOrEqual(); | 300 less_than_or_equal = machine()->Uint32LessThanOrEqual(); |
299 } else if (r.BothInputsAre(Type::Signed32())) { | 301 } else if (r.BothInputsAre(Type::Signed32())) { |
300 less_than = machine()->Int32LessThan(); | 302 less_than = machine()->Int32LessThan(); |
301 less_than_or_equal = machine()->Int32LessThanOrEqual(); | 303 less_than_or_equal = machine()->Int32LessThanOrEqual(); |
302 } else { | 304 } else { |
303 // TODO(turbofan): mixed signed/unsigned int32 comparisons. | 305 // TODO(turbofan): mixed signed/unsigned int32 comparisons. |
304 r.ConvertInputsToNumber(); | 306 r.ConvertInputsToNumber(); |
305 less_than = simplified()->NumberLessThan(); | 307 less_than = simplified()->NumberLessThan(); |
306 less_than_or_equal = simplified()->NumberLessThanOrEqual(); | 308 less_than_or_equal = simplified()->NumberLessThanOrEqual(); |
307 } | 309 } |
308 Operator* comparison; | 310 const Operator* comparison; |
309 switch (node->opcode()) { | 311 switch (node->opcode()) { |
310 case IrOpcode::kJSLessThan: | 312 case IrOpcode::kJSLessThan: |
311 comparison = less_than; | 313 comparison = less_than; |
312 break; | 314 break; |
313 case IrOpcode::kJSGreaterThan: | 315 case IrOpcode::kJSGreaterThan: |
314 comparison = less_than; | 316 comparison = less_than; |
315 r.SwapInputs(); // a > b => b < a | 317 r.SwapInputs(); // a > b => b < a |
316 break; | 318 break; |
317 case IrOpcode::kJSLessThanOrEqual: | 319 case IrOpcode::kJSLessThanOrEqual: |
318 comparison = less_than_or_equal; | 320 comparison = less_than_or_equal; |
(...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
612 case IrOpcode::kJSLoadProperty: | 614 case IrOpcode::kJSLoadProperty: |
613 return ReduceJSPropertyLoad(node); | 615 return ReduceJSPropertyLoad(node); |
614 default: | 616 default: |
615 break; | 617 break; |
616 } | 618 } |
617 return NoChange(); | 619 return NoChange(); |
618 } | 620 } |
619 } | 621 } |
620 } | 622 } |
621 } // namespace v8::internal::compiler | 623 } // namespace v8::internal::compiler |
OLD | NEW |