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-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-properties-inl.h" | 10 #include "src/compiler/node-properties-inl.h" |
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
221 }; | 221 }; |
222 | 222 |
223 | 223 |
224 Reduction JSTypedLowering::ReduceJSAdd(Node* node) { | 224 Reduction JSTypedLowering::ReduceJSAdd(Node* node) { |
225 JSBinopReduction r(this, node); | 225 JSBinopReduction r(this, node); |
226 if (r.BothInputsAre(Type::Number())) { | 226 if (r.BothInputsAre(Type::Number())) { |
227 // JSAdd(x:number, y:number) => NumberAdd(x, y) | 227 // JSAdd(x:number, y:number) => NumberAdd(x, y) |
228 return r.ChangeToPureOperator(simplified()->NumberAdd()); | 228 return r.ChangeToPureOperator(simplified()->NumberAdd()); |
229 } | 229 } |
230 Type* maybe_string = Type::Union(Type::String(), Type::Receiver(), zone()); | 230 Type* maybe_string = Type::Union(Type::String(), Type::Receiver(), zone()); |
231 if (r.NeitherInputCanBe(maybe_string)) { | 231 if (r.BothInputsAre(Type::Primitive()) && r.NeitherInputCanBe(maybe_string)) { |
232 // JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y)) | 232 // JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y)) |
233 r.ConvertInputsToNumber(); | 233 r.ConvertInputsToNumber(); |
234 return r.ChangeToPureOperator(simplified()->NumberAdd()); | 234 return r.ChangeToPureOperator(simplified()->NumberAdd()); |
235 } | 235 } |
236 #if 0 | 236 #if 0 |
| 237 // TODO(turbofan): General ToNumber disabled for now because: |
| 238 // a) The inserted ToNumber operation screws up observability of valueOf. |
| 239 // b) Deoptimization at ToNumber doesn't have corresponding bailout id. |
| 240 Type* maybe_string = Type::Union(Type::String(), Type::Receiver(), zone()); |
| 241 if (r.NeitherInputCanBe(maybe_string)) { |
| 242 ... |
| 243 } |
| 244 #endif |
| 245 #if 0 |
237 // TODO(turbofan): Lowering of StringAdd is disabled for now because: | 246 // TODO(turbofan): Lowering of StringAdd is disabled for now because: |
238 // a) The inserted ToString operation screws up valueOf vs. toString order. | 247 // a) The inserted ToString operation screws up valueOf vs. toString order. |
239 // b) Deoptimization at ToString doesn't have corresponding bailout id. | 248 // b) Deoptimization at ToString doesn't have corresponding bailout id. |
240 // c) Our current StringAddStub is actually non-pure and requires context. | 249 // c) Our current StringAddStub is actually non-pure and requires context. |
241 if (r.OneInputIs(Type::String())) { | 250 if (r.OneInputIs(Type::String())) { |
242 // JSAdd(x:string, y:string) => StringAdd(x, y) | 251 // JSAdd(x:string, y:string) => StringAdd(x, y) |
243 // JSAdd(x:string, y) => StringAdd(x, ToString(y)) | 252 // JSAdd(x:string, y) => StringAdd(x, ToString(y)) |
244 // JSAdd(x, y:string) => StringAdd(ToString(x), y) | 253 // JSAdd(x, y:string) => StringAdd(ToString(x), y) |
245 r.ConvertInputsToString(); | 254 r.ConvertInputsToString(); |
246 return r.ChangeToPureOperator(simplified()->StringAdd()); | 255 return r.ChangeToPureOperator(simplified()->StringAdd()); |
247 } | 256 } |
248 #endif | 257 #endif |
249 return NoChange(); | 258 return NoChange(); |
250 } | 259 } |
251 | 260 |
252 | 261 |
253 Reduction JSTypedLowering::ReduceNumberBinop(Node* node, | 262 Reduction JSTypedLowering::ReduceNumberBinop(Node* node, |
254 const Operator* numberOp) { | 263 const Operator* numberOp) { |
255 JSBinopReduction r(this, node); | 264 JSBinopReduction r(this, node); |
| 265 if (r.BothInputsAre(Type::Primitive())) { |
| 266 r.ConvertInputsToNumber(); |
| 267 return r.ChangeToPureOperator(numberOp); |
| 268 } |
| 269 #if 0 |
| 270 // TODO(turbofan): General ToNumber disabled for now because: |
| 271 // a) The inserted ToNumber operation screws up observability of valueOf. |
| 272 // b) Deoptimization at ToNumber doesn't have corresponding bailout id. |
256 if (r.OneInputIs(Type::Primitive())) { | 273 if (r.OneInputIs(Type::Primitive())) { |
257 // If at least one input is a primitive, then insert appropriate conversions | 274 // If at least one input is a primitive, then insert appropriate conversions |
258 // to number and reduce this operator to the given numeric one. | 275 // to number and reduce this operator to the given numeric one. |
259 // TODO(turbofan): make this heuristic configurable for code size. | 276 // TODO(turbofan): make this heuristic configurable for code size. |
260 r.ConvertInputsToNumber(); | 277 r.ConvertInputsToNumber(); |
261 return r.ChangeToPureOperator(numberOp); | 278 return r.ChangeToPureOperator(numberOp); |
262 } | 279 } |
| 280 #endif |
263 // TODO(turbofan): relax/remove the effects of this operator in other cases. | 281 // TODO(turbofan): relax/remove the effects of this operator in other cases. |
264 return NoChange(); | 282 return NoChange(); |
265 } | 283 } |
266 | 284 |
267 | 285 |
268 Reduction JSTypedLowering::ReduceI32Binop(Node* node, bool left_signed, | 286 Reduction JSTypedLowering::ReduceI32Binop(Node* node, bool left_signed, |
269 bool right_signed, | 287 bool right_signed, |
270 const Operator* intOp) { | 288 const Operator* intOp) { |
271 JSBinopReduction r(this, node); | 289 JSBinopReduction r(this, node); |
272 // TODO(titzer): some Smi bitwise operations don't really require going | 290 if (r.BothInputsAre(Type::Primitive())) { |
273 // all the way to int32, which can save tagging/untagging for some operations | 291 // TODO(titzer): some Smi bitwise operations don't really require going |
274 // on some platforms. | 292 // all the way to int32, which can save tagging/untagging for some |
275 // TODO(turbofan): make this heuristic configurable for code size. | 293 // operations |
276 r.ConvertInputsToInt32(left_signed, right_signed); | 294 // on some platforms. |
277 return r.ChangeToPureOperator(intOp); | 295 // TODO(turbofan): make this heuristic configurable for code size. |
| 296 r.ConvertInputsToInt32(left_signed, right_signed); |
| 297 return r.ChangeToPureOperator(intOp); |
| 298 } |
| 299 return NoChange(); |
278 } | 300 } |
279 | 301 |
280 | 302 |
281 Reduction JSTypedLowering::ReduceI32Shift(Node* node, bool left_signed, | 303 Reduction JSTypedLowering::ReduceI32Shift(Node* node, bool left_signed, |
282 const Operator* shift_op) { | 304 const Operator* shift_op) { |
283 JSBinopReduction r(this, node); | 305 JSBinopReduction r(this, node); |
284 r.ConvertInputsForShift(left_signed); | 306 if (r.BothInputsAre(Type::Primitive())) { |
285 return r.ChangeToPureOperator(shift_op); | 307 r.ConvertInputsForShift(left_signed); |
| 308 return r.ChangeToPureOperator(shift_op); |
| 309 } |
| 310 return NoChange(); |
286 } | 311 } |
287 | 312 |
288 | 313 |
289 Reduction JSTypedLowering::ReduceJSComparison(Node* node) { | 314 Reduction JSTypedLowering::ReduceJSComparison(Node* node) { |
290 JSBinopReduction r(this, node); | 315 JSBinopReduction r(this, node); |
291 if (r.BothInputsAre(Type::String())) { | 316 if (r.BothInputsAre(Type::String())) { |
292 // If both inputs are definitely strings, perform a string comparison. | 317 // If both inputs are definitely strings, perform a string comparison. |
293 const Operator* stringOp; | 318 const Operator* stringOp; |
294 switch (node->opcode()) { | 319 switch (node->opcode()) { |
295 case IrOpcode::kJSLessThan: | 320 case IrOpcode::kJSLessThan: |
296 stringOp = simplified()->StringLessThan(); | 321 stringOp = simplified()->StringLessThan(); |
297 break; | 322 break; |
298 case IrOpcode::kJSGreaterThan: | 323 case IrOpcode::kJSGreaterThan: |
299 stringOp = simplified()->StringLessThan(); | 324 stringOp = simplified()->StringLessThan(); |
300 r.SwapInputs(); // a > b => b < a | 325 r.SwapInputs(); // a > b => b < a |
301 break; | 326 break; |
302 case IrOpcode::kJSLessThanOrEqual: | 327 case IrOpcode::kJSLessThanOrEqual: |
303 stringOp = simplified()->StringLessThanOrEqual(); | 328 stringOp = simplified()->StringLessThanOrEqual(); |
304 break; | 329 break; |
305 case IrOpcode::kJSGreaterThanOrEqual: | 330 case IrOpcode::kJSGreaterThanOrEqual: |
306 stringOp = simplified()->StringLessThanOrEqual(); | 331 stringOp = simplified()->StringLessThanOrEqual(); |
307 r.SwapInputs(); // a >= b => b <= a | 332 r.SwapInputs(); // a >= b => b <= a |
308 break; | 333 break; |
309 default: | 334 default: |
310 return NoChange(); | 335 return NoChange(); |
311 } | 336 } |
312 return r.ChangeToPureOperator(stringOp); | 337 return r.ChangeToPureOperator(stringOp); |
313 } | 338 } |
| 339 #if 0 |
| 340 // TODO(turbofan): General ToNumber disabled for now because: |
| 341 // a) The inserted ToNumber operation screws up observability of valueOf. |
| 342 // b) Deoptimization at ToNumber doesn't have corresponding bailout id. |
314 Type* maybe_string = Type::Union(Type::String(), Type::Receiver(), zone()); | 343 Type* maybe_string = Type::Union(Type::String(), Type::Receiver(), zone()); |
315 if (r.OneInputCannotBe(maybe_string)) { | 344 if (r.OneInputCannotBe(maybe_string)) { |
316 // If one input cannot be a string, then emit a number comparison. | 345 // If one input cannot be a string, then emit a number comparison. |
| 346 ... |
| 347 } |
| 348 #endif |
| 349 Type* maybe_string = Type::Union(Type::String(), Type::Receiver(), zone()); |
| 350 if (r.BothInputsAre(Type::Primitive()) && r.OneInputCannotBe(maybe_string)) { |
317 const Operator* less_than; | 351 const Operator* less_than; |
318 const Operator* less_than_or_equal; | 352 const Operator* less_than_or_equal; |
319 if (r.BothInputsAre(Type::Unsigned32())) { | 353 if (r.BothInputsAre(Type::Unsigned32())) { |
320 less_than = machine()->Uint32LessThan(); | 354 less_than = machine()->Uint32LessThan(); |
321 less_than_or_equal = machine()->Uint32LessThanOrEqual(); | 355 less_than_or_equal = machine()->Uint32LessThanOrEqual(); |
322 } else if (r.BothInputsAre(Type::Signed32())) { | 356 } else if (r.BothInputsAre(Type::Signed32())) { |
323 less_than = machine()->Int32LessThan(); | 357 less_than = machine()->Int32LessThan(); |
324 less_than_or_equal = machine()->Int32LessThanOrEqual(); | 358 less_than_or_equal = machine()->Int32LessThanOrEqual(); |
325 } else { | 359 } else { |
326 // TODO(turbofan): mixed signed/unsigned int32 comparisons. | 360 // TODO(turbofan): mixed signed/unsigned int32 comparisons. |
(...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
682 return JSBuiltinReducer(jsgraph()).Reduce(node); | 716 return JSBuiltinReducer(jsgraph()).Reduce(node); |
683 default: | 717 default: |
684 break; | 718 break; |
685 } | 719 } |
686 return NoChange(); | 720 return NoChange(); |
687 } | 721 } |
688 | 722 |
689 } // namespace compiler | 723 } // namespace compiler |
690 } // namespace internal | 724 } // namespace internal |
691 } // namespace v8 | 725 } // namespace v8 |
OLD | NEW |