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" |
| 6 |
5 #include "src/code-factory.h" | 7 #include "src/code-factory.h" |
6 #include "src/compilation-dependencies.h" | 8 #include "src/compilation-dependencies.h" |
7 #include "src/compiler/access-builder.h" | 9 #include "src/compiler/access-builder.h" |
8 #include "src/compiler/js-graph.h" | 10 #include "src/compiler/js-graph.h" |
9 #include "src/compiler/js-typed-lowering.h" | |
10 #include "src/compiler/linkage.h" | 11 #include "src/compiler/linkage.h" |
11 #include "src/compiler/node-matchers.h" | 12 #include "src/compiler/node-matchers.h" |
12 #include "src/compiler/node-properties.h" | 13 #include "src/compiler/node-properties.h" |
13 #include "src/compiler/operator-properties.h" | 14 #include "src/compiler/operator-properties.h" |
14 #include "src/type-cache.h" | 15 #include "src/type-cache.h" |
15 #include "src/types.h" | 16 #include "src/types.h" |
16 | 17 |
17 namespace v8 { | 18 namespace v8 { |
18 namespace internal { | 19 namespace internal { |
19 namespace compiler { | 20 namespace compiler { |
20 | 21 |
21 // A helper class to simplify the process of reducing a single binop node with a | 22 // A helper class to simplify the process of reducing a single binop node with a |
22 // JSOperator. This class manages the rewriting of context, control, and effect | 23 // JSOperator. This class manages the rewriting of context, control, and effect |
23 // dependencies during lowering of a binop and contains numerous helper | 24 // dependencies during lowering of a binop and contains numerous helper |
24 // functions for matching the types of inputs to an operation. | 25 // functions for matching the types of inputs to an operation. |
25 class JSBinopReduction final { | 26 class JSBinopReduction final { |
26 public: | 27 public: |
27 JSBinopReduction(JSTypedLowering* lowering, Node* node) | 28 JSBinopReduction(JSTypedLowering* lowering, Node* node) |
28 : lowering_(lowering), node_(node) {} | 29 : lowering_(lowering), node_(node) {} |
29 | 30 |
30 BinaryOperationHints::Hint GetNumberBinaryOperationFeedback() { | 31 bool GetBinaryNumberOperationHint(NumberOperationHint* hint) { |
31 if (lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) { | 32 if (lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) { |
32 DCHECK_NE(0, node_->op()->ControlOutputCount()); | 33 DCHECK_NE(0, node_->op()->ControlOutputCount()); |
33 DCHECK_EQ(1, node_->op()->EffectOutputCount()); | 34 DCHECK_EQ(1, node_->op()->EffectOutputCount()); |
34 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node_->op())); | 35 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node_->op())); |
35 BinaryOperationHints hints = BinaryOperationHintsOf(node_->op()); | 36 BinaryOperationHints hints = BinaryOperationHintsOf(node_->op()); |
36 BinaryOperationHints::Hint combined = hints.combined(); | 37 switch (hints.combined()) { |
37 if (combined == BinaryOperationHints::kSignedSmall || | 38 case BinaryOperationHints::kSignedSmall: |
38 combined == BinaryOperationHints::kSigned32 || | 39 *hint = NumberOperationHint::kSignedSmall; |
39 combined == BinaryOperationHints::kNumberOrOddball) { | 40 return true; |
40 return combined; | 41 case BinaryOperationHints::kSigned32: |
| 42 *hint = NumberOperationHint::kSigned32; |
| 43 return true; |
| 44 case BinaryOperationHints::kNumberOrOddball: |
| 45 *hint = NumberOperationHint::kNumberOrOddball; |
| 46 return true; |
| 47 case BinaryOperationHints::kAny: |
| 48 case BinaryOperationHints::kNone: |
| 49 case BinaryOperationHints::kString: |
| 50 break; |
41 } | 51 } |
42 } | 52 } |
43 return BinaryOperationHints::kAny; | 53 return false; |
44 } | 54 } |
45 | 55 |
46 CompareOperationHints::Hint GetNumberCompareOperationFeedback() { | 56 bool GetCompareNumberOperationHint(NumberOperationHint* hint) { |
47 if (lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) { | 57 if (lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) { |
48 DCHECK_NE(0, node_->op()->ControlOutputCount()); | 58 DCHECK_NE(0, node_->op()->ControlOutputCount()); |
49 DCHECK_EQ(1, node_->op()->EffectOutputCount()); | 59 DCHECK_EQ(1, node_->op()->EffectOutputCount()); |
50 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node_->op())); | 60 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node_->op())); |
51 CompareOperationHints hints = CompareOperationHintsOf(node_->op()); | 61 CompareOperationHints hints = CompareOperationHintsOf(node_->op()); |
52 CompareOperationHints::Hint combined = hints.combined(); | 62 switch (hints.combined()) { |
53 if (combined == CompareOperationHints::kSignedSmall || | 63 case CompareOperationHints::kSignedSmall: |
54 combined == CompareOperationHints::kNumberOrOddball) { | 64 *hint = NumberOperationHint::kSignedSmall; |
55 return combined; | 65 return true; |
| 66 case CompareOperationHints::kNumberOrOddball: |
| 67 *hint = NumberOperationHint::kNumberOrOddball; |
| 68 return true; |
| 69 case CompareOperationHints::kAny: |
| 70 case CompareOperationHints::kNone: |
| 71 case CompareOperationHints::kString: |
| 72 case CompareOperationHints::kBoolean: |
| 73 case CompareOperationHints::kUniqueName: |
| 74 case CompareOperationHints::kInternalizedString: |
| 75 case CompareOperationHints::kReceiver: |
| 76 break; |
56 } | 77 } |
57 } | 78 } |
58 return CompareOperationHints::kAny; | 79 return false; |
59 } | 80 } |
60 | 81 |
61 void ConvertInputsToNumber() { | 82 void ConvertInputsToNumber() { |
62 // To convert the inputs to numbers, we have to provide frame states | 83 // To convert the inputs to numbers, we have to provide frame states |
63 // for lazy bailouts in the ToNumber conversions. | 84 // for lazy bailouts in the ToNumber conversions. |
64 // We use a little hack here: we take the frame state before the binary | 85 // We use a little hack here: we take the frame state before the binary |
65 // operation and use it to construct the frame states for the conversion | 86 // operation and use it to construct the frame states for the conversion |
66 // so that after the deoptimization, the binary operation IC gets | 87 // so that after the deoptimization, the binary operation IC gets |
67 // already converted values from full code. This way we are sure that we | 88 // already converted values from full code. This way we are sure that we |
68 // will not re-do any of the side effects. | 89 // will not re-do any of the side effects. |
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
347 for (size_t k = 0; k < arraysize(shifted_int32_ranges_); ++k) { | 368 for (size_t k = 0; k < arraysize(shifted_int32_ranges_); ++k) { |
348 double min = kMinInt / (1 << k); | 369 double min = kMinInt / (1 << k); |
349 double max = kMaxInt / (1 << k); | 370 double max = kMaxInt / (1 << k); |
350 shifted_int32_ranges_[k] = Type::Range(min, max, graph()->zone()); | 371 shifted_int32_ranges_[k] = Type::Range(min, max, graph()->zone()); |
351 } | 372 } |
352 } | 373 } |
353 | 374 |
354 | 375 |
355 Reduction JSTypedLowering::ReduceJSAdd(Node* node) { | 376 Reduction JSTypedLowering::ReduceJSAdd(Node* node) { |
356 JSBinopReduction r(this, node); | 377 JSBinopReduction r(this, node); |
357 BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback(); | 378 NumberOperationHint hint; |
358 if (feedback == BinaryOperationHints::kNumberOrOddball && | 379 if (r.GetBinaryNumberOperationHint(&hint)) { |
359 r.BothInputsAre(Type::PlainPrimitive()) && | 380 if (hint == NumberOperationHint::kNumberOrOddball && |
360 r.NeitherInputCanBe(Type::StringOrReceiver())) { | 381 r.BothInputsAre(Type::PlainPrimitive()) && |
361 // JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y)) | 382 r.NeitherInputCanBe(Type::StringOrReceiver())) { |
362 r.ConvertInputsToNumber(); | 383 // JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y)) |
363 return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number()); | 384 r.ConvertInputsToNumber(); |
364 } | 385 return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number()); |
365 if (feedback != BinaryOperationHints::kAny) { | 386 } |
366 // Lower to the optimistic number binop. | |
367 return r.ChangeToSpeculativeOperator( | 387 return r.ChangeToSpeculativeOperator( |
368 simplified()->SpeculativeNumberAdd(feedback), Type::Number()); | 388 simplified()->SpeculativeNumberAdd(hint), Type::Number()); |
369 } | 389 } |
370 if (r.BothInputsAre(Type::Number())) { | 390 if (r.BothInputsAre(Type::Number())) { |
371 // JSAdd(x:number, y:number) => NumberAdd(x, y) | 391 // JSAdd(x:number, y:number) => NumberAdd(x, y) |
372 r.ConvertInputsToNumber(); | 392 r.ConvertInputsToNumber(); |
373 return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number()); | 393 return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number()); |
374 } | 394 } |
375 if ((r.BothInputsAre(Type::PlainPrimitive()) || | 395 if ((r.BothInputsAre(Type::PlainPrimitive()) || |
376 !(flags() & kDeoptimizationEnabled)) && | 396 !(flags() & kDeoptimizationEnabled)) && |
377 r.NeitherInputCanBe(Type::StringOrReceiver())) { | 397 r.NeitherInputCanBe(Type::StringOrReceiver())) { |
378 // JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y)) | 398 // JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y)) |
(...skipping 16 matching lines...) Expand all Loading... |
395 CallDescriptor::kNeedsFrameState, node->op()->properties()); | 415 CallDescriptor::kNeedsFrameState, node->op()->properties()); |
396 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op())); | 416 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op())); |
397 node->InsertInput(graph()->zone(), 0, | 417 node->InsertInput(graph()->zone(), 0, |
398 jsgraph()->HeapConstant(callable.code())); | 418 jsgraph()->HeapConstant(callable.code())); |
399 NodeProperties::ChangeOp(node, common()->Call(desc)); | 419 NodeProperties::ChangeOp(node, common()->Call(desc)); |
400 return Changed(node); | 420 return Changed(node); |
401 } | 421 } |
402 return NoChange(); | 422 return NoChange(); |
403 } | 423 } |
404 | 424 |
405 | |
406 Reduction JSTypedLowering::ReduceJSSubtract(Node* node) { | 425 Reduction JSTypedLowering::ReduceJSSubtract(Node* node) { |
407 JSBinopReduction r(this, node); | 426 JSBinopReduction r(this, node); |
408 BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback(); | 427 NumberOperationHint hint; |
409 if (feedback == BinaryOperationHints::kNumberOrOddball && | 428 if (r.GetBinaryNumberOperationHint(&hint)) { |
410 r.BothInputsAre(Type::PlainPrimitive())) { | 429 if (hint == NumberOperationHint::kNumberOrOddball && |
411 // JSSubtract(x:plain-primitive, y:plain-primitive) | 430 r.BothInputsAre(Type::PlainPrimitive())) { |
412 // => NumberSubtract(ToNumber(x), ToNumber(y)) | 431 // JSSubtract(x:plain-primitive, y:plain-primitive) |
413 r.ConvertInputsToNumber(); | 432 // => NumberSubtract(ToNumber(x), ToNumber(y)) |
414 return r.ChangeToPureOperator(simplified()->NumberSubtract(), | 433 r.ConvertInputsToNumber(); |
415 Type::Number()); | 434 return r.ChangeToPureOperator(simplified()->NumberSubtract(), |
| 435 Type::Number()); |
| 436 } |
| 437 return r.ChangeToSpeculativeOperator( |
| 438 simplified()->SpeculativeNumberSubtract(hint), Type::Number()); |
416 } | 439 } |
417 if (feedback != BinaryOperationHints::kAny) { | |
418 // Lower to the optimistic number binop. | |
419 return r.ChangeToSpeculativeOperator( | |
420 simplified()->SpeculativeNumberSubtract(feedback), Type::Number()); | |
421 } | |
422 | |
423 // If deoptimization is enabled we rely on type feedback. | |
424 if (r.BothInputsAre(Type::PlainPrimitive()) || | 440 if (r.BothInputsAre(Type::PlainPrimitive()) || |
425 !(flags() & kDeoptimizationEnabled)) { | 441 !(flags() & kDeoptimizationEnabled)) { |
426 r.ConvertInputsToNumber(); | 442 r.ConvertInputsToNumber(); |
427 return r.ChangeToPureOperator(simplified()->NumberSubtract(), | 443 return r.ChangeToPureOperator(simplified()->NumberSubtract(), |
428 Type::Number()); | 444 Type::Number()); |
429 } | 445 } |
430 | |
431 return NoChange(); | 446 return NoChange(); |
432 } | 447 } |
433 | 448 |
434 Reduction JSTypedLowering::ReduceJSMultiply(Node* node) { | 449 Reduction JSTypedLowering::ReduceJSMultiply(Node* node) { |
435 JSBinopReduction r(this, node); | 450 JSBinopReduction r(this, node); |
436 BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback(); | 451 NumberOperationHint hint; |
437 if (feedback == BinaryOperationHints::kNumberOrOddball && | 452 if (r.GetBinaryNumberOperationHint(&hint)) { |
438 r.BothInputsAre(Type::PlainPrimitive())) { | 453 if (hint == NumberOperationHint::kNumberOrOddball && |
439 // JSMultiply(x:plain-primitive, | 454 r.BothInputsAre(Type::PlainPrimitive())) { |
440 // y:plain-primitive) => NumberMultiply(ToNumber(x), ToNumber(y)) | 455 // JSMultiply(x:plain-primitive, |
441 r.ConvertInputsToNumber(); | 456 // y:plain-primitive) => NumberMultiply(ToNumber(x), |
442 return r.ChangeToPureOperator(simplified()->NumberMultiply(), | 457 // ToNumber(y)) |
443 Type::Number()); | 458 r.ConvertInputsToNumber(); |
| 459 return r.ChangeToPureOperator(simplified()->NumberMultiply(), |
| 460 Type::Number()); |
| 461 } |
| 462 return r.ChangeToSpeculativeOperator( |
| 463 simplified()->SpeculativeNumberMultiply(hint), Type::Number()); |
444 } | 464 } |
445 if (feedback != BinaryOperationHints::kAny) { | |
446 return r.ChangeToSpeculativeOperator( | |
447 simplified()->SpeculativeNumberMultiply(feedback), Type::Number()); | |
448 } | |
449 | |
450 // If deoptimization is enabled we rely on type feedback. | |
451 if (r.BothInputsAre(Type::PlainPrimitive()) || | 465 if (r.BothInputsAre(Type::PlainPrimitive()) || |
452 !(flags() & kDeoptimizationEnabled)) { | 466 !(flags() & kDeoptimizationEnabled)) { |
453 r.ConvertInputsToNumber(); | 467 r.ConvertInputsToNumber(); |
454 return r.ChangeToPureOperator(simplified()->NumberMultiply(), | 468 return r.ChangeToPureOperator(simplified()->NumberMultiply(), |
455 Type::Number()); | 469 Type::Number()); |
456 } | 470 } |
457 | |
458 return NoChange(); | 471 return NoChange(); |
459 } | 472 } |
460 | 473 |
461 Reduction JSTypedLowering::ReduceJSDivide(Node* node) { | 474 Reduction JSTypedLowering::ReduceJSDivide(Node* node) { |
462 JSBinopReduction r(this, node); | 475 JSBinopReduction r(this, node); |
463 BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback(); | 476 NumberOperationHint hint; |
464 if (feedback == BinaryOperationHints::kNumberOrOddball && | 477 if (r.GetBinaryNumberOperationHint(&hint)) { |
465 r.BothInputsAre(Type::PlainPrimitive())) { | 478 if (hint == NumberOperationHint::kNumberOrOddball && |
466 // JSDivide(x:plain-primitive, | 479 r.BothInputsAre(Type::PlainPrimitive())) { |
467 // y:plain-primitive) => NumberDivide(ToNumber(x), ToNumber(y)) | 480 // JSDivide(x:plain-primitive, |
468 r.ConvertInputsToNumber(); | 481 // y:plain-primitive) => NumberDivide(ToNumber(x), ToNumber(y)) |
469 return r.ChangeToPureOperator(simplified()->NumberDivide(), Type::Number()); | 482 r.ConvertInputsToNumber(); |
470 } | 483 return r.ChangeToPureOperator(simplified()->NumberDivide(), |
471 if (feedback != BinaryOperationHints::kAny) { | 484 Type::Number()); |
| 485 } |
472 return r.ChangeToSpeculativeOperator( | 486 return r.ChangeToSpeculativeOperator( |
473 simplified()->SpeculativeNumberDivide(feedback), Type::Number()); | 487 simplified()->SpeculativeNumberDivide(hint), Type::Number()); |
474 } | 488 } |
475 if (r.BothInputsAre(Type::PlainPrimitive())) { | 489 if (r.BothInputsAre(Type::PlainPrimitive())) { |
476 // JSDivide(x:plain-primitive, | 490 // JSDivide(x:plain-primitive, |
477 // y:plain-primitive) => NumberDivide(ToNumber(x), ToNumber(y)) | 491 // y:plain-primitive) => NumberDivide(ToNumber(x), ToNumber(y)) |
478 r.ConvertInputsToNumber(); | 492 r.ConvertInputsToNumber(); |
479 return r.ChangeToPureOperator(simplified()->NumberDivide(), Type::Number()); | 493 return r.ChangeToPureOperator(simplified()->NumberDivide(), Type::Number()); |
480 } | 494 } |
481 return NoChange(); | 495 return NoChange(); |
482 } | 496 } |
483 | 497 |
484 Reduction JSTypedLowering::ReduceJSModulus(Node* node) { | 498 Reduction JSTypedLowering::ReduceJSModulus(Node* node) { |
485 JSBinopReduction r(this, node); | 499 JSBinopReduction r(this, node); |
486 BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback(); | 500 NumberOperationHint hint; |
487 if (feedback == BinaryOperationHints::kNumberOrOddball && | 501 if (r.GetBinaryNumberOperationHint(&hint)) { |
488 r.BothInputsAre(Type::PlainPrimitive())) { | 502 if (hint == NumberOperationHint::kNumberOrOddball && |
489 // JSModulus(x:plain-primitive, | 503 r.BothInputsAre(Type::PlainPrimitive())) { |
490 // y:plain-primitive) => NumberModulus(ToNumber(x), ToNumber(y)) | 504 // JSModulus(x:plain-primitive, |
491 r.ConvertInputsToNumber(); | 505 // y:plain-primitive) => NumberModulus(ToNumber(x), ToNumber(y)) |
492 return r.ChangeToPureOperator(simplified()->NumberModulus(), | 506 r.ConvertInputsToNumber(); |
493 Type::Number()); | 507 return r.ChangeToPureOperator(simplified()->NumberModulus(), |
494 } | 508 Type::Number()); |
495 if (feedback != BinaryOperationHints::kAny) { | 509 } |
496 return r.ChangeToSpeculativeOperator( | 510 return r.ChangeToSpeculativeOperator( |
497 simplified()->SpeculativeNumberModulus(feedback), Type::Number()); | 511 simplified()->SpeculativeNumberModulus(hint), Type::Number()); |
498 } | 512 } |
499 if (r.BothInputsAre(Type::PlainPrimitive())) { | 513 if (r.BothInputsAre(Type::PlainPrimitive())) { |
500 // JSModulus(x:plain-primitive, | 514 // JSModulus(x:plain-primitive, |
501 // y:plain-primitive) => NumberModulus(ToNumber(x), ToNumber(y)) | 515 // y:plain-primitive) => NumberModulus(ToNumber(x), ToNumber(y)) |
502 r.ConvertInputsToNumber(); | 516 r.ConvertInputsToNumber(); |
503 return r.ChangeToPureOperator(simplified()->NumberModulus(), | 517 return r.ChangeToPureOperator(simplified()->NumberModulus(), |
504 Type::Number()); | 518 Type::Number()); |
505 } | 519 } |
506 return NoChange(); | 520 return NoChange(); |
507 } | 521 } |
508 | 522 |
509 Reduction JSTypedLowering::ReduceInt32Binop(Node* node, | 523 Reduction JSTypedLowering::ReduceInt32Binop(Node* node, |
510 const Operator* int_op) { | 524 const Operator* int_op) { |
511 JSBinopReduction r(this, node); | 525 JSBinopReduction r(this, node); |
512 BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback(); | 526 NumberOperationHint hint; |
513 if (feedback != BinaryOperationHints::kAny) { | 527 if (r.GetBinaryNumberOperationHint(&hint)) { |
514 Operator const* speculative_op; | 528 Operator const* speculative_op; |
515 if (int_op->opcode() == IrOpcode::kNumberBitwiseAnd) { | 529 if (int_op->opcode() == IrOpcode::kNumberBitwiseAnd) { |
516 speculative_op = simplified()->SpeculativeNumberBitwiseAnd(feedback); | 530 speculative_op = simplified()->SpeculativeNumberBitwiseAnd(hint); |
517 } else if (int_op->opcode() == IrOpcode::kNumberBitwiseOr) { | 531 } else if (int_op->opcode() == IrOpcode::kNumberBitwiseOr) { |
518 speculative_op = simplified()->SpeculativeNumberBitwiseOr(feedback); | 532 speculative_op = simplified()->SpeculativeNumberBitwiseOr(hint); |
519 } else { | 533 } else { |
520 DCHECK_EQ(IrOpcode::kNumberBitwiseXor, int_op->opcode()); | 534 DCHECK_EQ(IrOpcode::kNumberBitwiseXor, int_op->opcode()); |
521 speculative_op = simplified()->SpeculativeNumberBitwiseXor(feedback); | 535 speculative_op = simplified()->SpeculativeNumberBitwiseXor(hint); |
522 } | 536 } |
523 return r.ChangeToSpeculativeOperator(speculative_op, Type::Signed32()); | 537 return r.ChangeToSpeculativeOperator(speculative_op, Type::Signed32()); |
524 } | 538 } |
525 | |
526 // If deoptimization is enabled we rely on type feedback. | |
527 if (r.BothInputsAre(Type::PlainPrimitive()) || | 539 if (r.BothInputsAre(Type::PlainPrimitive()) || |
528 !(flags() & kDeoptimizationEnabled)) { | 540 !(flags() & kDeoptimizationEnabled)) { |
529 r.ConvertInputsToNumber(); | 541 r.ConvertInputsToNumber(); |
530 r.ConvertInputsToUI32(kSigned, kSigned); | 542 r.ConvertInputsToUI32(kSigned, kSigned); |
531 return r.ChangeToPureOperator(int_op, Type::Signed32()); | 543 return r.ChangeToPureOperator(int_op, Type::Signed32()); |
532 } | 544 } |
533 return NoChange(); | 545 return NoChange(); |
534 } | 546 } |
535 | 547 |
536 Reduction JSTypedLowering::ReduceUI32Shift(Node* node, | 548 Reduction JSTypedLowering::ReduceUI32Shift(Node* node, Signedness signedness, |
537 Signedness left_signedness, | |
538 const Operator* shift_op) { | 549 const Operator* shift_op) { |
539 JSBinopReduction r(this, node); | 550 JSBinopReduction r(this, node); |
540 BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback(); | 551 NumberOperationHint hint; |
541 if (feedback != BinaryOperationHints::kAny) { | 552 if (r.GetBinaryNumberOperationHint(&hint)) { |
542 Operator const* speculative_op; | 553 Operator const* speculative_op; |
543 if (shift_op->opcode() == IrOpcode::kNumberShiftLeft) { | 554 if (shift_op->opcode() == IrOpcode::kNumberShiftLeft) { |
544 speculative_op = simplified()->SpeculativeNumberShiftLeft(feedback); | 555 speculative_op = simplified()->SpeculativeNumberShiftLeft(hint); |
545 } else if (shift_op->opcode() == IrOpcode::kNumberShiftRightLogical) { | 556 } else if (shift_op->opcode() == IrOpcode::kNumberShiftRightLogical) { |
546 speculative_op = | 557 speculative_op = simplified()->SpeculativeNumberShiftRightLogical(hint); |
547 simplified()->SpeculativeNumberShiftRightLogical(feedback); | |
548 } else { | 558 } else { |
549 DCHECK_EQ(IrOpcode::kNumberShiftRight, shift_op->opcode()); | 559 DCHECK_EQ(IrOpcode::kNumberShiftRight, shift_op->opcode()); |
550 speculative_op = simplified()->SpeculativeNumberShiftRight(feedback); | 560 speculative_op = simplified()->SpeculativeNumberShiftRight(hint); |
551 } | 561 } |
552 return r.ChangeToSpeculativeOperator( | 562 return r.ChangeToSpeculativeOperator( |
553 speculative_op, shift_op->opcode() == IrOpcode::kNumberShiftRightLogical | 563 speculative_op, |
554 ? Type::Unsigned32() | 564 signedness == kUnsigned ? Type::Unsigned32() : Type::Signed32()); |
555 : Type::Signed32()); | |
556 } | 565 } |
557 | |
558 // If deoptimization is enabled we rely on type feedback. | |
559 if (r.BothInputsAre(Type::PlainPrimitive()) || | 566 if (r.BothInputsAre(Type::PlainPrimitive()) || |
560 !(flags() & kDeoptimizationEnabled)) { | 567 !(flags() & kDeoptimizationEnabled)) { |
561 r.ConvertInputsToNumber(); | 568 r.ConvertInputsToNumber(); |
562 r.ConvertInputsToUI32(left_signedness, kUnsigned); | 569 r.ConvertInputsToUI32(signedness, kUnsigned); |
563 return r.ChangeToPureOperator(shift_op); | 570 return r.ChangeToPureOperator(shift_op); |
564 } | 571 } |
565 return NoChange(); | 572 return NoChange(); |
566 } | 573 } |
567 | 574 |
568 Reduction JSTypedLowering::ReduceJSComparison(Node* node) { | 575 Reduction JSTypedLowering::ReduceJSComparison(Node* node) { |
569 JSBinopReduction r(this, node); | 576 JSBinopReduction r(this, node); |
570 if (r.BothInputsAre(Type::String())) { | 577 if (r.BothInputsAre(Type::String())) { |
571 // If both inputs are definitely strings, perform a string comparison. | 578 // If both inputs are definitely strings, perform a string comparison. |
572 const Operator* stringOp; | 579 const Operator* stringOp; |
(...skipping 12 matching lines...) Expand all Loading... |
585 stringOp = simplified()->StringLessThanOrEqual(); | 592 stringOp = simplified()->StringLessThanOrEqual(); |
586 r.SwapInputs(); // a >= b => b <= a | 593 r.SwapInputs(); // a >= b => b <= a |
587 break; | 594 break; |
588 default: | 595 default: |
589 return NoChange(); | 596 return NoChange(); |
590 } | 597 } |
591 r.ChangeToPureOperator(stringOp); | 598 r.ChangeToPureOperator(stringOp); |
592 return Changed(node); | 599 return Changed(node); |
593 } | 600 } |
594 | 601 |
595 CompareOperationHints::Hint hint = r.GetNumberCompareOperationFeedback(); | 602 NumberOperationHint hint; |
596 if (hint != CompareOperationHints::kAny || | 603 const Operator* less_than; |
597 r.OneInputCannotBe(Type::StringOrReceiver())) { | 604 const Operator* less_than_or_equal; |
598 const Operator* less_than; | 605 if (r.BothInputsAre(Type::Signed32()) || |
599 const Operator* less_than_or_equal; | 606 r.BothInputsAre(Type::Unsigned32())) { |
600 if (r.BothInputsAre(Type::Signed32()) || | 607 less_than = simplified()->NumberLessThan(); |
601 r.BothInputsAre(Type::Unsigned32())) { | 608 less_than_or_equal = simplified()->NumberLessThanOrEqual(); |
602 less_than = simplified()->NumberLessThan(); | 609 } else if (r.GetCompareNumberOperationHint(&hint)) { |
603 less_than_or_equal = simplified()->NumberLessThanOrEqual(); | 610 less_than = simplified()->SpeculativeNumberLessThan(hint); |
604 } else if (hint != CompareOperationHints::kAny) { | 611 less_than_or_equal = simplified()->SpeculativeNumberLessThanOrEqual(hint); |
605 less_than = simplified()->SpeculativeNumberLessThan(hint); | 612 } else if (r.OneInputCannotBe(Type::StringOrReceiver()) && |
606 less_than_or_equal = simplified()->SpeculativeNumberLessThanOrEqual(hint); | 613 (r.BothInputsAre(Type::PlainPrimitive()) || |
607 } else if (r.BothInputsAre(Type::PlainPrimitive()) || | 614 !(flags() & kDeoptimizationEnabled))) { |
608 !(flags() & kDeoptimizationEnabled)) { | 615 r.ConvertInputsToNumber(); |
609 r.ConvertInputsToNumber(); | 616 less_than = simplified()->NumberLessThan(); |
610 less_than = simplified()->NumberLessThan(); | 617 less_than_or_equal = simplified()->NumberLessThanOrEqual(); |
611 less_than_or_equal = simplified()->NumberLessThanOrEqual(); | 618 } else { |
612 } else { | 619 return NoChange(); |
| 620 } |
| 621 const Operator* comparison; |
| 622 switch (node->opcode()) { |
| 623 case IrOpcode::kJSLessThan: |
| 624 comparison = less_than; |
| 625 break; |
| 626 case IrOpcode::kJSGreaterThan: |
| 627 comparison = less_than; |
| 628 r.SwapInputs(); // a > b => b < a |
| 629 break; |
| 630 case IrOpcode::kJSLessThanOrEqual: |
| 631 comparison = less_than_or_equal; |
| 632 break; |
| 633 case IrOpcode::kJSGreaterThanOrEqual: |
| 634 comparison = less_than_or_equal; |
| 635 r.SwapInputs(); // a >= b => b <= a |
| 636 break; |
| 637 default: |
613 return NoChange(); | 638 return NoChange(); |
614 } | |
615 const Operator* comparison; | |
616 switch (node->opcode()) { | |
617 case IrOpcode::kJSLessThan: | |
618 comparison = less_than; | |
619 break; | |
620 case IrOpcode::kJSGreaterThan: | |
621 comparison = less_than; | |
622 r.SwapInputs(); // a > b => b < a | |
623 break; | |
624 case IrOpcode::kJSLessThanOrEqual: | |
625 comparison = less_than_or_equal; | |
626 break; | |
627 case IrOpcode::kJSGreaterThanOrEqual: | |
628 comparison = less_than_or_equal; | |
629 r.SwapInputs(); // a >= b => b <= a | |
630 break; | |
631 default: | |
632 return NoChange(); | |
633 } | |
634 if (comparison->EffectInputCount() > 0) { | |
635 return r.ChangeToSpeculativeOperator(comparison, Type::Boolean()); | |
636 } else { | |
637 return r.ChangeToPureOperator(comparison); | |
638 } | |
639 } | 639 } |
640 // TODO(turbofan): relax/remove effects of this operator in other cases. | 640 if (comparison->EffectInputCount() > 0) { |
641 return NoChange(); // Keep a generic comparison. | 641 return r.ChangeToSpeculativeOperator(comparison, Type::Boolean()); |
| 642 } else { |
| 643 return r.ChangeToPureOperator(comparison); |
| 644 } |
642 } | 645 } |
643 | 646 |
644 Reduction JSTypedLowering::ReduceJSEqualTypeOf(Node* node, bool invert) { | 647 Reduction JSTypedLowering::ReduceJSEqualTypeOf(Node* node, bool invert) { |
645 HeapObjectBinopMatcher m(node); | 648 HeapObjectBinopMatcher m(node); |
646 if (m.left().IsJSTypeOf() && m.right().HasValue() && | 649 if (m.left().IsJSTypeOf() && m.right().HasValue() && |
647 m.right().Value()->IsString()) { | 650 m.right().Value()->IsString()) { |
648 Node* replacement; | 651 Node* replacement; |
649 Node* input = m.left().InputAt(0); | 652 Node* input = m.left().InputAt(0); |
650 Handle<String> value = Handle<String>::cast(m.right().Value()); | 653 Handle<String> value = Handle<String>::cast(m.right().Value()); |
651 if (String::Equals(value, factory()->boolean_string())) { | 654 if (String::Equals(value, factory()->boolean_string())) { |
(...skipping 1444 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2096 } | 2099 } |
2097 | 2100 |
2098 | 2101 |
2099 CompilationDependencies* JSTypedLowering::dependencies() const { | 2102 CompilationDependencies* JSTypedLowering::dependencies() const { |
2100 return dependencies_; | 2103 return dependencies_; |
2101 } | 2104 } |
2102 | 2105 |
2103 } // namespace compiler | 2106 } // namespace compiler |
2104 } // namespace internal | 2107 } // namespace internal |
2105 } // namespace v8 | 2108 } // namespace v8 |
OLD | NEW |