| 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/code-factory.h" | 5 #include "src/code-factory.h" |
| 6 #include "src/compilation-dependencies.h" | 6 #include "src/compilation-dependencies.h" |
| 7 #include "src/compiler/access-builder.h" | 7 #include "src/compiler/access-builder.h" |
| 8 #include "src/compiler/js-graph.h" | 8 #include "src/compiler/js-graph.h" |
| 9 #include "src/compiler/js-typed-lowering.h" | 9 #include "src/compiler/js-typed-lowering.h" |
| 10 #include "src/compiler/linkage.h" | 10 #include "src/compiler/linkage.h" |
| (...skipping 415 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 426 type_cache_(TypeCache::Get()) { | 426 type_cache_(TypeCache::Get()) { |
| 427 for (size_t k = 0; k < arraysize(shifted_int32_ranges_); ++k) { | 427 for (size_t k = 0; k < arraysize(shifted_int32_ranges_); ++k) { |
| 428 double min = kMinInt / (1 << k); | 428 double min = kMinInt / (1 << k); |
| 429 double max = kMaxInt / (1 << k); | 429 double max = kMaxInt / (1 << k); |
| 430 shifted_int32_ranges_[k] = Type::Range(min, max, graph()->zone()); | 430 shifted_int32_ranges_[k] = Type::Range(min, max, graph()->zone()); |
| 431 } | 431 } |
| 432 } | 432 } |
| 433 | 433 |
| 434 | 434 |
| 435 Reduction JSTypedLowering::ReduceJSAdd(Node* node) { | 435 Reduction JSTypedLowering::ReduceJSAdd(Node* node) { |
| 436 if (flags() & kDisableBinaryOpReduction) return NoChange(); | |
| 437 | |
| 438 JSBinopReduction r(this, node); | 436 JSBinopReduction r(this, node); |
| 439 | |
| 440 BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback(); | 437 BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback(); |
| 441 if (feedback == BinaryOperationHints::kNumberOrUndefined && | 438 if (feedback == BinaryOperationHints::kNumberOrUndefined && |
| 442 r.BothInputsAre(Type::PlainPrimitive()) && | 439 r.BothInputsAre(Type::PlainPrimitive()) && |
| 443 r.NeitherInputCanBe(Type::StringOrReceiver())) { | 440 r.NeitherInputCanBe(Type::StringOrReceiver())) { |
| 444 // JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y)) | 441 // JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y)) |
| 445 r.ConvertInputsToNumber(); | 442 r.ConvertInputsToNumber(); |
| 446 return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number()); | 443 return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number()); |
| 447 } | 444 } |
| 448 if (feedback != BinaryOperationHints::kAny) { | 445 if (feedback != BinaryOperationHints::kAny) { |
| 449 // Lower to the optimistic number binop. | 446 // Lower to the optimistic number binop. |
| (...skipping 30 matching lines...) Expand all Loading... |
| 480 node->InsertInput(graph()->zone(), 0, | 477 node->InsertInput(graph()->zone(), 0, |
| 481 jsgraph()->HeapConstant(callable.code())); | 478 jsgraph()->HeapConstant(callable.code())); |
| 482 NodeProperties::ChangeOp(node, common()->Call(desc)); | 479 NodeProperties::ChangeOp(node, common()->Call(desc)); |
| 483 return Changed(node); | 480 return Changed(node); |
| 484 } | 481 } |
| 485 return NoChange(); | 482 return NoChange(); |
| 486 } | 483 } |
| 487 | 484 |
| 488 | 485 |
| 489 Reduction JSTypedLowering::ReduceJSSubtract(Node* node) { | 486 Reduction JSTypedLowering::ReduceJSSubtract(Node* node) { |
| 490 if (flags() & kDisableBinaryOpReduction) return NoChange(); | |
| 491 JSBinopReduction r(this, node); | 487 JSBinopReduction r(this, node); |
| 492 BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback(); | 488 BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback(); |
| 493 if (feedback == BinaryOperationHints::kNumberOrUndefined && | 489 if (feedback == BinaryOperationHints::kNumberOrUndefined && |
| 494 r.BothInputsAre(Type::PlainPrimitive())) { | 490 r.BothInputsAre(Type::PlainPrimitive())) { |
| 495 // JSSubtract(x:plain-primitive, y:plain-primitive) | 491 // JSSubtract(x:plain-primitive, y:plain-primitive) |
| 496 // => NumberSubtract(ToNumber(x), ToNumber(y)) | 492 // => NumberSubtract(ToNumber(x), ToNumber(y)) |
| 497 r.ConvertInputsToNumber(); | 493 r.ConvertInputsToNumber(); |
| 498 return r.ChangeToPureOperator(simplified()->NumberSubtract(), | 494 return r.ChangeToPureOperator(simplified()->NumberSubtract(), |
| 499 Type::Number()); | 495 Type::Number()); |
| 500 } | 496 } |
| 501 if (feedback != BinaryOperationHints::kAny) { | 497 if (feedback != BinaryOperationHints::kAny) { |
| 502 // Lower to the optimistic number binop. | 498 // Lower to the optimistic number binop. |
| 503 return r.ChangeToSpeculativeOperator( | 499 return r.ChangeToSpeculativeOperator( |
| 504 simplified()->SpeculativeNumberSubtract(feedback), Type::Number()); | 500 simplified()->SpeculativeNumberSubtract(feedback), Type::Number()); |
| 505 } | 501 } |
| 506 | 502 |
| 507 // If deoptimization is enabled we rely on type feedback. | 503 // If deoptimization is enabled we rely on type feedback. |
| 508 if (r.BothInputsAre(Type::PlainPrimitive()) || | 504 if (r.BothInputsAre(Type::PlainPrimitive()) || |
| 509 !(flags() & kDeoptimizationEnabled)) { | 505 !(flags() & kDeoptimizationEnabled)) { |
| 510 r.ConvertInputsToNumber(); | 506 r.ConvertInputsToNumber(); |
| 511 return r.ChangeToPureOperator(simplified()->NumberSubtract(), | 507 return r.ChangeToPureOperator(simplified()->NumberSubtract(), |
| 512 Type::Number()); | 508 Type::Number()); |
| 513 } | 509 } |
| 514 | 510 |
| 515 return NoChange(); | 511 return NoChange(); |
| 516 } | 512 } |
| 517 | 513 |
| 518 Reduction JSTypedLowering::ReduceJSMultiply(Node* node) { | 514 Reduction JSTypedLowering::ReduceJSMultiply(Node* node) { |
| 519 if (flags() & kDisableBinaryOpReduction) return NoChange(); | |
| 520 JSBinopReduction r(this, node); | 515 JSBinopReduction r(this, node); |
| 521 BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback(); | 516 BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback(); |
| 522 if (feedback != BinaryOperationHints::kAny) { | 517 if (feedback != BinaryOperationHints::kAny) { |
| 523 return r.ChangeToSpeculativeOperator( | 518 return r.ChangeToSpeculativeOperator( |
| 524 simplified()->SpeculativeNumberMultiply(feedback), Type::Number()); | 519 simplified()->SpeculativeNumberMultiply(feedback), Type::Number()); |
| 525 } | 520 } |
| 526 | 521 |
| 527 // If deoptimization is enabled we rely on type feedback. | 522 // If deoptimization is enabled we rely on type feedback. |
| 528 if (r.BothInputsAre(Type::PlainPrimitive()) || | 523 if (r.BothInputsAre(Type::PlainPrimitive()) || |
| 529 !(flags() & kDeoptimizationEnabled)) { | 524 !(flags() & kDeoptimizationEnabled)) { |
| 530 r.ConvertInputsToNumber(); | 525 r.ConvertInputsToNumber(); |
| 531 return r.ChangeToPureOperator(simplified()->NumberMultiply(), | 526 return r.ChangeToPureOperator(simplified()->NumberMultiply(), |
| 532 Type::Number()); | 527 Type::Number()); |
| 533 } | 528 } |
| 534 | 529 |
| 535 return NoChange(); | 530 return NoChange(); |
| 536 } | 531 } |
| 537 | 532 |
| 538 Reduction JSTypedLowering::ReduceJSDivide(Node* node) { | 533 Reduction JSTypedLowering::ReduceJSDivide(Node* node) { |
| 539 if (flags() & kDisableBinaryOpReduction) return NoChange(); | |
| 540 JSBinopReduction r(this, node); | 534 JSBinopReduction r(this, node); |
| 541 BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback(); | 535 BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback(); |
| 542 if (feedback == BinaryOperationHints::kNumberOrUndefined && | 536 if (feedback == BinaryOperationHints::kNumberOrUndefined && |
| 543 r.BothInputsAre(Type::PlainPrimitive())) { | 537 r.BothInputsAre(Type::PlainPrimitive())) { |
| 544 // JSDivide(x:plain-primitive, | 538 // JSDivide(x:plain-primitive, |
| 545 // y:plain-primitive) => NumberDivide(ToNumber(x), ToNumber(y)) | 539 // y:plain-primitive) => NumberDivide(ToNumber(x), ToNumber(y)) |
| 546 r.ConvertInputsToNumber(); | 540 r.ConvertInputsToNumber(); |
| 547 return r.ChangeToPureOperator(simplified()->NumberDivide(), Type::Number()); | 541 return r.ChangeToPureOperator(simplified()->NumberDivide(), Type::Number()); |
| 548 } | 542 } |
| 549 if (feedback != BinaryOperationHints::kAny) { | 543 if (feedback != BinaryOperationHints::kAny) { |
| 550 return r.ChangeToSpeculativeOperator( | 544 return r.ChangeToSpeculativeOperator( |
| 551 simplified()->SpeculativeNumberDivide(feedback), Type::Number()); | 545 simplified()->SpeculativeNumberDivide(feedback), Type::Number()); |
| 552 } | 546 } |
| 553 if (r.BothInputsAre(Type::PlainPrimitive())) { | 547 if (r.BothInputsAre(Type::PlainPrimitive())) { |
| 554 // JSDivide(x:plain-primitive, | 548 // JSDivide(x:plain-primitive, |
| 555 // y:plain-primitive) => NumberDivide(ToNumber(x), ToNumber(y)) | 549 // y:plain-primitive) => NumberDivide(ToNumber(x), ToNumber(y)) |
| 556 r.ConvertInputsToNumber(); | 550 r.ConvertInputsToNumber(); |
| 557 return r.ChangeToPureOperator(simplified()->NumberDivide(), Type::Number()); | 551 return r.ChangeToPureOperator(simplified()->NumberDivide(), Type::Number()); |
| 558 } | 552 } |
| 559 return NoChange(); | 553 return NoChange(); |
| 560 } | 554 } |
| 561 | 555 |
| 562 Reduction JSTypedLowering::ReduceJSModulus(Node* node) { | 556 Reduction JSTypedLowering::ReduceJSModulus(Node* node) { |
| 563 if (flags() & kDisableBinaryOpReduction) return NoChange(); | |
| 564 JSBinopReduction r(this, node); | 557 JSBinopReduction r(this, node); |
| 565 BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback(); | 558 BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback(); |
| 566 if (feedback == BinaryOperationHints::kNumberOrUndefined && | 559 if (feedback == BinaryOperationHints::kNumberOrUndefined && |
| 567 r.BothInputsAre(Type::PlainPrimitive())) { | 560 r.BothInputsAre(Type::PlainPrimitive())) { |
| 568 // JSModulus(x:plain-primitive, | 561 // JSModulus(x:plain-primitive, |
| 569 // y:plain-primitive) => NumberModulus(ToNumber(x), ToNumber(y)) | 562 // y:plain-primitive) => NumberModulus(ToNumber(x), ToNumber(y)) |
| 570 r.ConvertInputsToNumber(); | 563 r.ConvertInputsToNumber(); |
| 571 return r.ChangeToPureOperator(simplified()->NumberModulus(), | 564 return r.ChangeToPureOperator(simplified()->NumberModulus(), |
| 572 Type::Number()); | 565 Type::Number()); |
| 573 } | 566 } |
| 574 if (feedback != BinaryOperationHints::kAny) { | 567 if (feedback != BinaryOperationHints::kAny) { |
| 575 return r.ChangeToSpeculativeOperator( | 568 return r.ChangeToSpeculativeOperator( |
| 576 simplified()->SpeculativeNumberModulus(feedback), Type::Number()); | 569 simplified()->SpeculativeNumberModulus(feedback), Type::Number()); |
| 577 } | 570 } |
| 578 if (r.BothInputsAre(Type::PlainPrimitive())) { | 571 if (r.BothInputsAre(Type::PlainPrimitive())) { |
| 579 // JSModulus(x:plain-primitive, | 572 // JSModulus(x:plain-primitive, |
| 580 // y:plain-primitive) => NumberModulus(ToNumber(x), ToNumber(y)) | 573 // y:plain-primitive) => NumberModulus(ToNumber(x), ToNumber(y)) |
| 581 r.ConvertInputsToNumber(); | 574 r.ConvertInputsToNumber(); |
| 582 return r.ChangeToPureOperator(simplified()->NumberModulus(), | 575 return r.ChangeToPureOperator(simplified()->NumberModulus(), |
| 583 Type::Number()); | 576 Type::Number()); |
| 584 } | 577 } |
| 585 return NoChange(); | 578 return NoChange(); |
| 586 } | 579 } |
| 587 | 580 |
| 588 Reduction JSTypedLowering::ReduceInt32Binop(Node* node, const Operator* intOp) { | 581 Reduction JSTypedLowering::ReduceInt32Binop(Node* node, const Operator* intOp) { |
| 589 if (flags() & kDisableBinaryOpReduction) return NoChange(); | 582 if (flags() & kDisableIntegerBinaryOpReduction) return NoChange(); |
| 590 | 583 |
| 591 JSBinopReduction r(this, node); | 584 JSBinopReduction r(this, node); |
| 592 r.ConvertInputsToNumber(); | 585 r.ConvertInputsToNumber(); |
| 593 r.ConvertInputsToUI32(kSigned, kSigned); | 586 r.ConvertInputsToUI32(kSigned, kSigned); |
| 594 return r.ChangeToPureOperator(intOp, Type::Integral32()); | 587 return r.ChangeToPureOperator(intOp, Type::Integral32()); |
| 595 } | 588 } |
| 596 | 589 |
| 597 | 590 |
| 598 Reduction JSTypedLowering::ReduceUI32Shift(Node* node, | 591 Reduction JSTypedLowering::ReduceUI32Shift(Node* node, |
| 599 Signedness left_signedness, | 592 Signedness left_signedness, |
| 600 const Operator* shift_op) { | 593 const Operator* shift_op) { |
| 601 if (flags() & kDisableBinaryOpReduction) return NoChange(); | 594 if (flags() & kDisableIntegerBinaryOpReduction) return NoChange(); |
| 602 | 595 |
| 603 JSBinopReduction r(this, node); | 596 JSBinopReduction r(this, node); |
| 604 r.ConvertInputsToNumber(); | 597 r.ConvertInputsToNumber(); |
| 605 r.ConvertInputsToUI32(left_signedness, kUnsigned); | 598 r.ConvertInputsToUI32(left_signedness, kUnsigned); |
| 606 return r.ChangeToPureOperator(shift_op); | 599 return r.ChangeToPureOperator(shift_op); |
| 607 } | 600 } |
| 608 | 601 |
| 609 | 602 |
| 610 Reduction JSTypedLowering::ReduceJSComparison(Node* node) { | 603 Reduction JSTypedLowering::ReduceJSComparison(Node* node) { |
| 611 if (flags() & kDisableBinaryOpReduction) return NoChange(); | |
| 612 | |
| 613 JSBinopReduction r(this, node); | 604 JSBinopReduction r(this, node); |
| 614 if (r.BothInputsAre(Type::String())) { | 605 if (r.BothInputsAre(Type::String())) { |
| 615 // If both inputs are definitely strings, perform a string comparison. | 606 // If both inputs are definitely strings, perform a string comparison. |
| 616 const Operator* stringOp; | 607 const Operator* stringOp; |
| 617 switch (node->opcode()) { | 608 switch (node->opcode()) { |
| 618 case IrOpcode::kJSLessThan: | 609 case IrOpcode::kJSLessThan: |
| 619 stringOp = simplified()->StringLessThan(); | 610 stringOp = simplified()->StringLessThan(); |
| 620 break; | 611 break; |
| 621 case IrOpcode::kJSGreaterThan: | 612 case IrOpcode::kJSGreaterThan: |
| 622 stringOp = simplified()->StringLessThan(); | 613 stringOp = simplified()->StringLessThan(); |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 714 } | 705 } |
| 715 if (invert) { | 706 if (invert) { |
| 716 replacement = graph()->NewNode(simplified()->BooleanNot(), replacement); | 707 replacement = graph()->NewNode(simplified()->BooleanNot(), replacement); |
| 717 } | 708 } |
| 718 return Replace(replacement); | 709 return Replace(replacement); |
| 719 } | 710 } |
| 720 return NoChange(); | 711 return NoChange(); |
| 721 } | 712 } |
| 722 | 713 |
| 723 Reduction JSTypedLowering::ReduceJSEqual(Node* node, bool invert) { | 714 Reduction JSTypedLowering::ReduceJSEqual(Node* node, bool invert) { |
| 724 if (flags() & kDisableBinaryOpReduction) return NoChange(); | |
| 725 | |
| 726 Reduction const reduction = ReduceJSEqualTypeOf(node, invert); | 715 Reduction const reduction = ReduceJSEqualTypeOf(node, invert); |
| 727 if (reduction.Changed()) { | 716 if (reduction.Changed()) { |
| 728 ReplaceWithValue(node, reduction.replacement()); | 717 ReplaceWithValue(node, reduction.replacement()); |
| 729 return reduction; | 718 return reduction; |
| 730 } | 719 } |
| 731 | 720 |
| 732 JSBinopReduction r(this, node); | 721 JSBinopReduction r(this, node); |
| 733 | 722 |
| 734 if (r.BothInputsAre(Type::Number())) { | 723 if (r.BothInputsAre(Type::Number())) { |
| 735 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert); | 724 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 758 value->ReplaceInput(0, node); | 747 value->ReplaceInput(0, node); |
| 759 return Replace(value); | 748 return Replace(value); |
| 760 } | 749 } |
| 761 return Changed(node); | 750 return Changed(node); |
| 762 } | 751 } |
| 763 return NoChange(); | 752 return NoChange(); |
| 764 } | 753 } |
| 765 | 754 |
| 766 | 755 |
| 767 Reduction JSTypedLowering::ReduceJSStrictEqual(Node* node, bool invert) { | 756 Reduction JSTypedLowering::ReduceJSStrictEqual(Node* node, bool invert) { |
| 768 if (flags() & kDisableBinaryOpReduction) return NoChange(); | |
| 769 | |
| 770 JSBinopReduction r(this, node); | 757 JSBinopReduction r(this, node); |
| 771 if (r.left() == r.right()) { | 758 if (r.left() == r.right()) { |
| 772 // x === x is always true if x != NaN | 759 // x === x is always true if x != NaN |
| 773 if (!r.left_type()->Maybe(Type::NaN())) { | 760 if (!r.left_type()->Maybe(Type::NaN())) { |
| 774 Node* replacement = jsgraph()->BooleanConstant(!invert); | 761 Node* replacement = jsgraph()->BooleanConstant(!invert); |
| 775 ReplaceWithValue(node, replacement); | 762 ReplaceWithValue(node, replacement); |
| 776 return Replace(replacement); | 763 return Replace(replacement); |
| 777 } | 764 } |
| 778 } | 765 } |
| 779 if (r.OneInputCannotBe(Type::NumberOrSimdOrString())) { | 766 if (r.OneInputCannotBe(Type::NumberOrSimdOrString())) { |
| (...skipping 1292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2072 } | 2059 } |
| 2073 | 2060 |
| 2074 | 2061 |
| 2075 CompilationDependencies* JSTypedLowering::dependencies() const { | 2062 CompilationDependencies* JSTypedLowering::dependencies() const { |
| 2076 return dependencies_; | 2063 return dependencies_; |
| 2077 } | 2064 } |
| 2078 | 2065 |
| 2079 } // namespace compiler | 2066 } // namespace compiler |
| 2080 } // namespace internal | 2067 } // namespace internal |
| 2081 } // namespace v8 | 2068 } // namespace v8 |
| OLD | NEW |