| OLD | NEW |
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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/effect-control-linearizer.h" | 5 #include "src/compiler/effect-control-linearizer.h" |
| 6 | 6 |
| 7 #include "src/code-factory.h" | 7 #include "src/code-factory.h" |
| 8 #include "src/compiler/access-builder.h" | 8 #include "src/compiler/access-builder.h" |
| 9 #include "src/compiler/compiler-source-position-table.h" | 9 #include "src/compiler/compiler-source-position-table.h" |
| 10 #include "src/compiler/graph-assembler.h" |
| 10 #include "src/compiler/js-graph.h" | 11 #include "src/compiler/js-graph.h" |
| 11 #include "src/compiler/linkage.h" | 12 #include "src/compiler/linkage.h" |
| 12 #include "src/compiler/node-matchers.h" | 13 #include "src/compiler/node-matchers.h" |
| 13 #include "src/compiler/node-properties.h" | 14 #include "src/compiler/node-properties.h" |
| 14 #include "src/compiler/node.h" | 15 #include "src/compiler/node.h" |
| 15 #include "src/compiler/schedule.h" | 16 #include "src/compiler/schedule.h" |
| 16 | 17 |
| 17 namespace v8 { | 18 namespace v8 { |
| 18 namespace internal { | 19 namespace internal { |
| 19 namespace compiler { | 20 namespace compiler { |
| 20 | 21 |
| 21 EffectControlLinearizer::EffectControlLinearizer( | 22 EffectControlLinearizer::EffectControlLinearizer( |
| 22 JSGraph* js_graph, Schedule* schedule, Zone* temp_zone, | 23 JSGraph* js_graph, Schedule* schedule, Zone* temp_zone, |
| 23 SourcePositionTable* source_positions) | 24 SourcePositionTable* source_positions) |
| 24 : js_graph_(js_graph), | 25 : js_graph_(js_graph), |
| 25 schedule_(schedule), | 26 schedule_(schedule), |
| 26 temp_zone_(temp_zone), | 27 temp_zone_(temp_zone), |
| 27 source_positions_(source_positions) {} | 28 source_positions_(source_positions), |
| 29 graph_assembler_(js_graph, nullptr, nullptr, temp_zone) {} |
| 28 | 30 |
| 29 Graph* EffectControlLinearizer::graph() const { return js_graph_->graph(); } | 31 Graph* EffectControlLinearizer::graph() const { return js_graph_->graph(); } |
| 30 CommonOperatorBuilder* EffectControlLinearizer::common() const { | 32 CommonOperatorBuilder* EffectControlLinearizer::common() const { |
| 31 return js_graph_->common(); | 33 return js_graph_->common(); |
| 32 } | 34 } |
| 33 SimplifiedOperatorBuilder* EffectControlLinearizer::simplified() const { | 35 SimplifiedOperatorBuilder* EffectControlLinearizer::simplified() const { |
| 34 return js_graph_->simplified(); | 36 return js_graph_->simplified(); |
| 35 } | 37 } |
| 36 MachineOperatorBuilder* EffectControlLinearizer::machine() const { | 38 MachineOperatorBuilder* EffectControlLinearizer::machine() const { |
| 37 return js_graph_->machine(); | 39 return js_graph_->machine(); |
| (...skipping 551 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 589 // Schedule the call's IfSuccess node (if there is no exception use). | 591 // Schedule the call's IfSuccess node (if there is no exception use). |
| 590 TryScheduleCallIfSuccess(node, control); | 592 TryScheduleCallIfSuccess(node, control); |
| 591 } | 593 } |
| 592 } | 594 } |
| 593 } | 595 } |
| 594 | 596 |
| 595 bool EffectControlLinearizer::TryWireInStateEffect(Node* node, | 597 bool EffectControlLinearizer::TryWireInStateEffect(Node* node, |
| 596 Node* frame_state, | 598 Node* frame_state, |
| 597 Node** effect, | 599 Node** effect, |
| 598 Node** control) { | 600 Node** control) { |
| 599 ValueEffectControl state(nullptr, nullptr, nullptr); | 601 gasm()->Reset(*effect, *control); |
| 602 Node* result = nullptr; |
| 600 switch (node->opcode()) { | 603 switch (node->opcode()) { |
| 601 case IrOpcode::kChangeBitToTagged: | 604 case IrOpcode::kChangeBitToTagged: |
| 602 state = LowerChangeBitToTagged(node, *effect, *control); | 605 result = LowerChangeBitToTagged(node); |
| 603 break; | 606 break; |
| 604 case IrOpcode::kChangeInt31ToTaggedSigned: | 607 case IrOpcode::kChangeInt31ToTaggedSigned: |
| 605 state = LowerChangeInt31ToTaggedSigned(node, *effect, *control); | 608 result = LowerChangeInt31ToTaggedSigned(node); |
| 606 break; | 609 break; |
| 607 case IrOpcode::kChangeInt32ToTagged: | 610 case IrOpcode::kChangeInt32ToTagged: |
| 608 state = LowerChangeInt32ToTagged(node, *effect, *control); | 611 result = LowerChangeInt32ToTagged(node); |
| 609 break; | 612 break; |
| 610 case IrOpcode::kChangeUint32ToTagged: | 613 case IrOpcode::kChangeUint32ToTagged: |
| 611 state = LowerChangeUint32ToTagged(node, *effect, *control); | 614 result = LowerChangeUint32ToTagged(node); |
| 612 break; | 615 break; |
| 613 case IrOpcode::kChangeFloat64ToTagged: | 616 case IrOpcode::kChangeFloat64ToTagged: |
| 614 state = LowerChangeFloat64ToTagged(node, *effect, *control); | 617 result = LowerChangeFloat64ToTagged(node); |
| 615 break; | 618 break; |
| 616 case IrOpcode::kChangeFloat64ToTaggedPointer: | 619 case IrOpcode::kChangeFloat64ToTaggedPointer: |
| 617 state = LowerChangeFloat64ToTaggedPointer(node, *effect, *control); | 620 result = LowerChangeFloat64ToTaggedPointer(node); |
| 618 break; | 621 break; |
| 619 case IrOpcode::kChangeTaggedSignedToInt32: | 622 case IrOpcode::kChangeTaggedSignedToInt32: |
| 620 state = LowerChangeTaggedSignedToInt32(node, *effect, *control); | 623 result = LowerChangeTaggedSignedToInt32(node); |
| 621 break; | 624 break; |
| 622 case IrOpcode::kChangeTaggedToBit: | 625 case IrOpcode::kChangeTaggedToBit: |
| 623 state = LowerChangeTaggedToBit(node, *effect, *control); | 626 result = LowerChangeTaggedToBit(node); |
| 624 break; | 627 break; |
| 625 case IrOpcode::kChangeTaggedToInt32: | 628 case IrOpcode::kChangeTaggedToInt32: |
| 626 state = LowerChangeTaggedToInt32(node, *effect, *control); | 629 result = LowerChangeTaggedToInt32(node); |
| 627 break; | 630 break; |
| 628 case IrOpcode::kChangeTaggedToUint32: | 631 case IrOpcode::kChangeTaggedToUint32: |
| 629 state = LowerChangeTaggedToUint32(node, *effect, *control); | 632 result = LowerChangeTaggedToUint32(node); |
| 630 break; | 633 break; |
| 631 case IrOpcode::kChangeTaggedToFloat64: | 634 case IrOpcode::kChangeTaggedToFloat64: |
| 632 state = LowerChangeTaggedToFloat64(node, *effect, *control); | 635 result = LowerChangeTaggedToFloat64(node); |
| 633 break; | 636 break; |
| 634 case IrOpcode::kTruncateTaggedToBit: | 637 case IrOpcode::kTruncateTaggedToBit: |
| 635 state = LowerTruncateTaggedToBit(node, *effect, *control); | 638 result = LowerTruncateTaggedToBit(node); |
| 636 break; | 639 break; |
| 637 case IrOpcode::kTruncateTaggedToFloat64: | 640 case IrOpcode::kTruncateTaggedToFloat64: |
| 638 state = LowerTruncateTaggedToFloat64(node, *effect, *control); | 641 result = LowerTruncateTaggedToFloat64(node); |
| 639 break; | 642 break; |
| 640 case IrOpcode::kCheckBounds: | 643 case IrOpcode::kCheckBounds: |
| 641 state = LowerCheckBounds(node, frame_state, *effect, *control); | 644 result = LowerCheckBounds(node, frame_state); |
| 642 break; | 645 break; |
| 643 case IrOpcode::kCheckMaps: | 646 case IrOpcode::kCheckMaps: |
| 644 state = LowerCheckMaps(node, frame_state, *effect, *control); | 647 result = LowerCheckMaps(node, frame_state); |
| 645 break; | 648 break; |
| 646 case IrOpcode::kCheckNumber: | 649 case IrOpcode::kCheckNumber: |
| 647 state = LowerCheckNumber(node, frame_state, *effect, *control); | 650 result = LowerCheckNumber(node, frame_state); |
| 648 break; | 651 break; |
| 649 case IrOpcode::kCheckString: | 652 case IrOpcode::kCheckString: |
| 650 state = LowerCheckString(node, frame_state, *effect, *control); | 653 result = LowerCheckString(node, frame_state); |
| 651 break; | 654 break; |
| 652 case IrOpcode::kCheckIf: | 655 case IrOpcode::kCheckIf: |
| 653 state = LowerCheckIf(node, frame_state, *effect, *control); | 656 result = LowerCheckIf(node, frame_state); |
| 654 break; | 657 break; |
| 655 case IrOpcode::kCheckedInt32Add: | 658 case IrOpcode::kCheckedInt32Add: |
| 656 state = LowerCheckedInt32Add(node, frame_state, *effect, *control); | 659 result = LowerCheckedInt32Add(node, frame_state); |
| 657 break; | 660 break; |
| 658 case IrOpcode::kCheckedInt32Sub: | 661 case IrOpcode::kCheckedInt32Sub: |
| 659 state = LowerCheckedInt32Sub(node, frame_state, *effect, *control); | 662 result = LowerCheckedInt32Sub(node, frame_state); |
| 660 break; | 663 break; |
| 661 case IrOpcode::kCheckedInt32Div: | 664 case IrOpcode::kCheckedInt32Div: |
| 662 state = LowerCheckedInt32Div(node, frame_state, *effect, *control); | 665 result = LowerCheckedInt32Div(node, frame_state); |
| 663 break; | 666 break; |
| 664 case IrOpcode::kCheckedInt32Mod: | 667 case IrOpcode::kCheckedInt32Mod: |
| 665 state = LowerCheckedInt32Mod(node, frame_state, *effect, *control); | 668 result = LowerCheckedInt32Mod(node, frame_state); |
| 666 break; | 669 break; |
| 667 case IrOpcode::kCheckedUint32Div: | 670 case IrOpcode::kCheckedUint32Div: |
| 668 state = LowerCheckedUint32Div(node, frame_state, *effect, *control); | 671 result = LowerCheckedUint32Div(node, frame_state); |
| 669 break; | 672 break; |
| 670 case IrOpcode::kCheckedUint32Mod: | 673 case IrOpcode::kCheckedUint32Mod: |
| 671 state = LowerCheckedUint32Mod(node, frame_state, *effect, *control); | 674 result = LowerCheckedUint32Mod(node, frame_state); |
| 672 break; | 675 break; |
| 673 case IrOpcode::kCheckedInt32Mul: | 676 case IrOpcode::kCheckedInt32Mul: |
| 674 state = LowerCheckedInt32Mul(node, frame_state, *effect, *control); | 677 result = LowerCheckedInt32Mul(node, frame_state); |
| 675 break; | 678 break; |
| 676 case IrOpcode::kCheckedInt32ToTaggedSigned: | 679 case IrOpcode::kCheckedInt32ToTaggedSigned: |
| 677 state = | 680 result = LowerCheckedInt32ToTaggedSigned(node, frame_state); |
| 678 LowerCheckedInt32ToTaggedSigned(node, frame_state, *effect, *control); | |
| 679 break; | 681 break; |
| 680 case IrOpcode::kCheckedUint32ToInt32: | 682 case IrOpcode::kCheckedUint32ToInt32: |
| 681 state = LowerCheckedUint32ToInt32(node, frame_state, *effect, *control); | 683 result = LowerCheckedUint32ToInt32(node, frame_state); |
| 682 break; | 684 break; |
| 683 case IrOpcode::kCheckedUint32ToTaggedSigned: | 685 case IrOpcode::kCheckedUint32ToTaggedSigned: |
| 684 state = LowerCheckedUint32ToTaggedSigned(node, frame_state, *effect, | 686 result = LowerCheckedUint32ToTaggedSigned(node, frame_state); |
| 685 *control); | |
| 686 break; | 687 break; |
| 687 case IrOpcode::kCheckedFloat64ToInt32: | 688 case IrOpcode::kCheckedFloat64ToInt32: |
| 688 state = LowerCheckedFloat64ToInt32(node, frame_state, *effect, *control); | 689 result = LowerCheckedFloat64ToInt32(node, frame_state); |
| 689 break; | 690 break; |
| 690 case IrOpcode::kCheckedTaggedSignedToInt32: | 691 case IrOpcode::kCheckedTaggedSignedToInt32: |
| 691 state = | 692 result = LowerCheckedTaggedSignedToInt32(node, frame_state); |
| 692 LowerCheckedTaggedSignedToInt32(node, frame_state, *effect, *control); | |
| 693 break; | 693 break; |
| 694 case IrOpcode::kCheckedTaggedToInt32: | 694 case IrOpcode::kCheckedTaggedToInt32: |
| 695 state = LowerCheckedTaggedToInt32(node, frame_state, *effect, *control); | 695 result = LowerCheckedTaggedToInt32(node, frame_state); |
| 696 break; | 696 break; |
| 697 case IrOpcode::kCheckedTaggedToFloat64: | 697 case IrOpcode::kCheckedTaggedToFloat64: |
| 698 state = LowerCheckedTaggedToFloat64(node, frame_state, *effect, *control); | 698 result = LowerCheckedTaggedToFloat64(node, frame_state); |
| 699 break; | 699 break; |
| 700 case IrOpcode::kCheckedTaggedToTaggedSigned: | 700 case IrOpcode::kCheckedTaggedToTaggedSigned: |
| 701 state = LowerCheckedTaggedToTaggedSigned(node, frame_state, *effect, | 701 result = LowerCheckedTaggedToTaggedSigned(node, frame_state); |
| 702 *control); | |
| 703 break; | 702 break; |
| 704 case IrOpcode::kCheckedTaggedToTaggedPointer: | 703 case IrOpcode::kCheckedTaggedToTaggedPointer: |
| 705 state = LowerCheckedTaggedToTaggedPointer(node, frame_state, *effect, | 704 result = LowerCheckedTaggedToTaggedPointer(node, frame_state); |
| 706 *control); | |
| 707 break; | 705 break; |
| 708 case IrOpcode::kTruncateTaggedToWord32: | 706 case IrOpcode::kTruncateTaggedToWord32: |
| 709 state = LowerTruncateTaggedToWord32(node, *effect, *control); | 707 result = LowerTruncateTaggedToWord32(node); |
| 710 break; | 708 break; |
| 711 case IrOpcode::kCheckedTruncateTaggedToWord32: | 709 case IrOpcode::kCheckedTruncateTaggedToWord32: |
| 712 state = LowerCheckedTruncateTaggedToWord32(node, frame_state, *effect, | 710 result = LowerCheckedTruncateTaggedToWord32(node, frame_state); |
| 713 *control); | |
| 714 break; | 711 break; |
| 715 case IrOpcode::kObjectIsCallable: | 712 case IrOpcode::kObjectIsCallable: |
| 716 state = LowerObjectIsCallable(node, *effect, *control); | 713 result = LowerObjectIsCallable(node); |
| 717 break; | 714 break; |
| 718 case IrOpcode::kObjectIsNumber: | 715 case IrOpcode::kObjectIsNumber: |
| 719 state = LowerObjectIsNumber(node, *effect, *control); | 716 result = LowerObjectIsNumber(node); |
| 720 break; | 717 break; |
| 721 case IrOpcode::kObjectIsReceiver: | 718 case IrOpcode::kObjectIsReceiver: |
| 722 state = LowerObjectIsReceiver(node, *effect, *control); | 719 result = LowerObjectIsReceiver(node); |
| 723 break; | 720 break; |
| 724 case IrOpcode::kObjectIsSmi: | 721 case IrOpcode::kObjectIsSmi: |
| 725 state = LowerObjectIsSmi(node, *effect, *control); | 722 result = LowerObjectIsSmi(node); |
| 726 break; | 723 break; |
| 727 case IrOpcode::kObjectIsString: | 724 case IrOpcode::kObjectIsString: |
| 728 state = LowerObjectIsString(node, *effect, *control); | 725 result = LowerObjectIsString(node); |
| 729 break; | 726 break; |
| 730 case IrOpcode::kObjectIsUndetectable: | 727 case IrOpcode::kObjectIsUndetectable: |
| 731 state = LowerObjectIsUndetectable(node, *effect, *control); | 728 result = LowerObjectIsUndetectable(node); |
| 732 break; | 729 break; |
| 733 case IrOpcode::kNewRestParameterElements: | 730 case IrOpcode::kNewRestParameterElements: |
| 734 state = LowerNewRestParameterElements(node, *effect, *control); | 731 result = LowerNewRestParameterElements(node); |
| 735 break; | 732 break; |
| 736 case IrOpcode::kNewUnmappedArgumentsElements: | 733 case IrOpcode::kNewUnmappedArgumentsElements: |
| 737 state = LowerNewUnmappedArgumentsElements(node, *effect, *control); | 734 result = LowerNewUnmappedArgumentsElements(node); |
| 738 break; | 735 break; |
| 739 case IrOpcode::kArrayBufferWasNeutered: | 736 case IrOpcode::kArrayBufferWasNeutered: |
| 740 state = LowerArrayBufferWasNeutered(node, *effect, *control); | 737 result = LowerArrayBufferWasNeutered(node); |
| 741 break; | 738 break; |
| 742 case IrOpcode::kStringFromCharCode: | 739 case IrOpcode::kStringFromCharCode: |
| 743 state = LowerStringFromCharCode(node, *effect, *control); | 740 result = LowerStringFromCharCode(node); |
| 744 break; | 741 break; |
| 745 case IrOpcode::kStringFromCodePoint: | 742 case IrOpcode::kStringFromCodePoint: |
| 746 state = LowerStringFromCodePoint(node, *effect, *control); | 743 result = LowerStringFromCodePoint(node); |
| 747 break; | 744 break; |
| 748 case IrOpcode::kStringCharAt: | 745 case IrOpcode::kStringCharAt: |
| 749 state = LowerStringCharAt(node, *effect, *control); | 746 result = LowerStringCharAt(node); |
| 750 break; | 747 break; |
| 751 case IrOpcode::kStringCharCodeAt: | 748 case IrOpcode::kStringCharCodeAt: |
| 752 state = LowerStringCharCodeAt(node, *effect, *control); | 749 result = LowerStringCharCodeAt(node); |
| 753 break; | 750 break; |
| 754 case IrOpcode::kStringEqual: | 751 case IrOpcode::kStringEqual: |
| 755 state = LowerStringEqual(node, *effect, *control); | 752 result = LowerStringEqual(node); |
| 756 break; | 753 break; |
| 757 case IrOpcode::kStringLessThan: | 754 case IrOpcode::kStringLessThan: |
| 758 state = LowerStringLessThan(node, *effect, *control); | 755 result = LowerStringLessThan(node); |
| 759 break; | 756 break; |
| 760 case IrOpcode::kStringLessThanOrEqual: | 757 case IrOpcode::kStringLessThanOrEqual: |
| 761 state = LowerStringLessThanOrEqual(node, *effect, *control); | 758 result = LowerStringLessThanOrEqual(node); |
| 762 break; | 759 break; |
| 763 case IrOpcode::kCheckFloat64Hole: | 760 case IrOpcode::kCheckFloat64Hole: |
| 764 state = LowerCheckFloat64Hole(node, frame_state, *effect, *control); | 761 result = LowerCheckFloat64Hole(node, frame_state); |
| 765 break; | 762 break; |
| 766 case IrOpcode::kCheckTaggedHole: | 763 case IrOpcode::kCheckTaggedHole: |
| 767 state = LowerCheckTaggedHole(node, frame_state, *effect, *control); | 764 result = LowerCheckTaggedHole(node, frame_state); |
| 768 break; | 765 break; |
| 769 case IrOpcode::kConvertTaggedHoleToUndefined: | 766 case IrOpcode::kConvertTaggedHoleToUndefined: |
| 770 state = LowerConvertTaggedHoleToUndefined(node, *effect, *control); | 767 result = LowerConvertTaggedHoleToUndefined(node); |
| 771 break; | 768 break; |
| 772 case IrOpcode::kPlainPrimitiveToNumber: | 769 case IrOpcode::kPlainPrimitiveToNumber: |
| 773 state = LowerPlainPrimitiveToNumber(node, *effect, *control); | 770 result = LowerPlainPrimitiveToNumber(node); |
| 774 break; | 771 break; |
| 775 case IrOpcode::kPlainPrimitiveToWord32: | 772 case IrOpcode::kPlainPrimitiveToWord32: |
| 776 state = LowerPlainPrimitiveToWord32(node, *effect, *control); | 773 result = LowerPlainPrimitiveToWord32(node); |
| 777 break; | 774 break; |
| 778 case IrOpcode::kPlainPrimitiveToFloat64: | 775 case IrOpcode::kPlainPrimitiveToFloat64: |
| 779 state = LowerPlainPrimitiveToFloat64(node, *effect, *control); | 776 result = LowerPlainPrimitiveToFloat64(node); |
| 780 break; | 777 break; |
| 781 case IrOpcode::kEnsureWritableFastElements: | 778 case IrOpcode::kEnsureWritableFastElements: |
| 782 state = LowerEnsureWritableFastElements(node, *effect, *control); | 779 result = LowerEnsureWritableFastElements(node); |
| 783 break; | 780 break; |
| 784 case IrOpcode::kMaybeGrowFastElements: | 781 case IrOpcode::kMaybeGrowFastElements: |
| 785 state = LowerMaybeGrowFastElements(node, frame_state, *effect, *control); | 782 result = LowerMaybeGrowFastElements(node, frame_state); |
| 786 break; | 783 break; |
| 787 case IrOpcode::kTransitionElementsKind: | 784 case IrOpcode::kTransitionElementsKind: |
| 788 state = LowerTransitionElementsKind(node, *effect, *control); | 785 LowerTransitionElementsKind(node); |
| 789 break; | 786 break; |
| 790 case IrOpcode::kLoadTypedElement: | 787 case IrOpcode::kLoadTypedElement: |
| 791 state = LowerLoadTypedElement(node, *effect, *control); | 788 result = LowerLoadTypedElement(node); |
| 792 break; | 789 break; |
| 793 case IrOpcode::kStoreTypedElement: | 790 case IrOpcode::kStoreTypedElement: |
| 794 state = LowerStoreTypedElement(node, *effect, *control); | 791 LowerStoreTypedElement(node); |
| 795 break; | 792 break; |
| 796 case IrOpcode::kFloat64RoundUp: | 793 case IrOpcode::kFloat64RoundUp: |
| 797 state = LowerFloat64RoundUp(node, *effect, *control); | 794 if (!LowerFloat64RoundUp(node).To(&result)) { |
| 795 return false; |
| 796 } |
| 798 break; | 797 break; |
| 799 case IrOpcode::kFloat64RoundDown: | 798 case IrOpcode::kFloat64RoundDown: |
| 800 state = LowerFloat64RoundDown(node, *effect, *control); | 799 if (!LowerFloat64RoundDown(node).To(&result)) { |
| 800 return false; |
| 801 } |
| 801 break; | 802 break; |
| 802 case IrOpcode::kFloat64RoundTruncate: | 803 case IrOpcode::kFloat64RoundTruncate: |
| 803 state = LowerFloat64RoundTruncate(node, *effect, *control); | 804 if (!LowerFloat64RoundTruncate(node).To(&result)) { |
| 805 return false; |
| 806 } |
| 804 break; | 807 break; |
| 805 case IrOpcode::kFloat64RoundTiesEven: | 808 case IrOpcode::kFloat64RoundTiesEven: |
| 806 state = LowerFloat64RoundTiesEven(node, *effect, *control); | 809 if (!LowerFloat64RoundTiesEven(node).To(&result)) { |
| 810 return false; |
| 811 } |
| 807 break; | 812 break; |
| 808 default: | 813 default: |
| 809 return false; | 814 return false; |
| 810 } | 815 } |
| 811 NodeProperties::ReplaceUses(node, state.value, state.effect, state.control); | 816 *effect = gasm()->ExtractCurrentEffect(); |
| 812 *effect = state.effect; | 817 *control = gasm()->ExtractCurrentControl(); |
| 813 *control = state.control; | 818 NodeProperties::ReplaceUses(node, result, *effect, *control); |
| 814 return true; | 819 return true; |
| 815 } | 820 } |
| 816 | 821 |
| 817 EffectControlLinearizer::ValueEffectControl | 822 #define __ gasm()-> |
| 818 EffectControlLinearizer::LowerChangeFloat64ToTagged(Node* node, Node* effect, | 823 |
| 819 Node* control) { | 824 Node* EffectControlLinearizer::LowerChangeFloat64ToTagged(Node* node) { |
| 820 Node* value = node->InputAt(0); | 825 Node* value = node->InputAt(0); |
| 821 return AllocateHeapNumberWithValue(value, effect, control); | 826 return AllocateHeapNumberWithValue(value); |
| 822 } | 827 } |
| 823 | 828 |
| 824 EffectControlLinearizer::ValueEffectControl | 829 Node* EffectControlLinearizer::LowerChangeFloat64ToTaggedPointer(Node* node) { |
| 825 EffectControlLinearizer::LowerChangeFloat64ToTaggedPointer(Node* node, | 830 Node* value = node->InputAt(0); |
| 826 Node* effect, | 831 return AllocateHeapNumberWithValue(value); |
| 827 Node* control) { | 832 } |
| 828 Node* value = node->InputAt(0); | 833 |
| 829 return AllocateHeapNumberWithValue(value, effect, control); | 834 Node* EffectControlLinearizer::LowerChangeBitToTagged(Node* node) { |
| 830 } | 835 Node* value = node->InputAt(0); |
| 831 | 836 |
| 832 EffectControlLinearizer::ValueEffectControl | 837 auto if_true = __ MakeLabel<1>(); |
| 833 EffectControlLinearizer::LowerChangeBitToTagged(Node* node, Node* effect, | 838 auto done = __ MakeLabel<2>(MachineRepresentation::kTagged); |
| 834 Node* control) { | 839 |
| 835 Node* value = node->InputAt(0); | 840 __ GotoIf(value, &if_true); |
| 836 | 841 __ Goto(&done, __ FalseConstant()); |
| 837 Node* branch = graph()->NewNode(common()->Branch(), value, control); | 842 |
| 838 | 843 __ Bind(&if_true); |
| 839 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); | 844 __ Goto(&done, __ TrueConstant()); |
| 840 Node* vtrue = jsgraph()->TrueConstant(); | 845 |
| 841 | 846 __ Bind(&done); |
| 842 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); | 847 return done.PhiAt(0); |
| 843 Node* vfalse = jsgraph()->FalseConstant(); | 848 } |
| 844 | 849 |
| 845 control = graph()->NewNode(common()->Merge(2), if_true, if_false); | 850 Node* EffectControlLinearizer::LowerChangeInt31ToTaggedSigned(Node* node) { |
| 846 value = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), | 851 Node* value = node->InputAt(0); |
| 847 vtrue, vfalse, control); | 852 return ChangeInt32ToSmi(value); |
| 848 | 853 } |
| 849 return ValueEffectControl(value, effect, control); | 854 |
| 850 } | 855 Node* EffectControlLinearizer::LowerChangeInt32ToTagged(Node* node) { |
| 851 | |
| 852 EffectControlLinearizer::ValueEffectControl | |
| 853 EffectControlLinearizer::LowerChangeInt31ToTaggedSigned(Node* node, | |
| 854 Node* effect, | |
| 855 Node* control) { | |
| 856 Node* value = node->InputAt(0); | |
| 857 value = ChangeInt32ToSmi(value); | |
| 858 return ValueEffectControl(value, effect, control); | |
| 859 } | |
| 860 | |
| 861 EffectControlLinearizer::ValueEffectControl | |
| 862 EffectControlLinearizer::LowerChangeInt32ToTagged(Node* node, Node* effect, | |
| 863 Node* control) { | |
| 864 Node* value = node->InputAt(0); | 856 Node* value = node->InputAt(0); |
| 865 | 857 |
| 866 if (machine()->Is64()) { | 858 if (machine()->Is64()) { |
| 867 return ValueEffectControl(ChangeInt32ToSmi(value), effect, control); | 859 return ChangeInt32ToSmi(value); |
| 868 } | 860 } |
| 869 | 861 |
| 870 Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(), value, value, | 862 auto if_overflow = __ MakeDeferredLabel<1>(); |
| 871 control); | 863 auto done = __ MakeLabel<2>(MachineRepresentation::kTagged); |
| 872 | 864 |
| 873 Node* ovf = graph()->NewNode(common()->Projection(1), add, control); | 865 Node* add = __ Int32AddWithOverflow(value, value); |
| 874 Node* branch = | 866 Node* ovf = __ Projection(1, add); |
| 875 graph()->NewNode(common()->Branch(BranchHint::kFalse), ovf, control); | 867 __ GotoIf(ovf, &if_overflow); |
| 876 | 868 __ Goto(&done, __ Projection(0, add)); |
| 877 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); | 869 |
| 878 ValueEffectControl alloc = | 870 __ Bind(&if_overflow); |
| 879 AllocateHeapNumberWithValue(ChangeInt32ToFloat64(value), effect, if_true); | 871 Node* number = AllocateHeapNumberWithValue(__ ChangeInt32ToFloat64(value)); |
| 880 | 872 __ Goto(&done, number); |
| 881 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); | 873 |
| 882 Node* vfalse = graph()->NewNode(common()->Projection(0), add, if_false); | 874 __ Bind(&done); |
| 883 | 875 return done.PhiAt(0); |
| 884 Node* merge = graph()->NewNode(common()->Merge(2), alloc.control, if_false); | 876 } |
| 885 Node* phi = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), | 877 |
| 886 alloc.value, vfalse, merge); | 878 Node* EffectControlLinearizer::LowerChangeUint32ToTagged(Node* node) { |
| 887 Node* ephi = | 879 Node* value = node->InputAt(0); |
| 888 graph()->NewNode(common()->EffectPhi(2), alloc.effect, effect, merge); | 880 |
| 889 | 881 auto if_not_in_smi_range = __ MakeDeferredLabel<1>(); |
| 890 return ValueEffectControl(phi, ephi, merge); | 882 auto done = __ MakeLabel<2>(MachineRepresentation::kTagged); |
| 891 } | 883 |
| 892 | 884 Node* check = __ Uint32LessThanOrEqual(value, SmiMaxValueConstant()); |
| 893 EffectControlLinearizer::ValueEffectControl | 885 __ GotoUnless(check, &if_not_in_smi_range); |
| 894 EffectControlLinearizer::LowerChangeUint32ToTagged(Node* node, Node* effect, | 886 __ Goto(&done, ChangeUint32ToSmi(value)); |
| 895 Node* control) { | 887 |
| 896 Node* value = node->InputAt(0); | 888 __ Bind(&if_not_in_smi_range); |
| 897 | 889 Node* number = AllocateHeapNumberWithValue(__ ChangeUint32ToFloat64(value)); |
| 898 Node* check = graph()->NewNode(machine()->Uint32LessThanOrEqual(), value, | 890 |
| 899 SmiMaxValueConstant()); | 891 __ Goto(&done, number); |
| 900 Node* branch = | 892 __ Bind(&done); |
| 901 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control); | 893 |
| 902 | 894 return done.PhiAt(0); |
| 903 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); | 895 } |
| 904 Node* vtrue = ChangeUint32ToSmi(value); | 896 |
| 905 | 897 Node* EffectControlLinearizer::LowerChangeTaggedSignedToInt32(Node* node) { |
| 906 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); | 898 Node* value = node->InputAt(0); |
| 907 ValueEffectControl alloc = AllocateHeapNumberWithValue( | 899 return ChangeSmiToInt32(value); |
| 908 ChangeUint32ToFloat64(value), effect, if_false); | 900 } |
| 909 | 901 |
| 910 Node* merge = graph()->NewNode(common()->Merge(2), if_true, alloc.control); | 902 Node* EffectControlLinearizer::LowerChangeTaggedToBit(Node* node) { |
| 911 Node* phi = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), | 903 Node* value = node->InputAt(0); |
| 912 vtrue, alloc.value, merge); | 904 return __ WordEqual(value, __ TrueConstant()); |
| 913 Node* ephi = | 905 } |
| 914 graph()->NewNode(common()->EffectPhi(2), effect, alloc.effect, merge); | 906 |
| 915 | 907 Node* EffectControlLinearizer::LowerTruncateTaggedToBit(Node* node) { |
| 916 return ValueEffectControl(phi, ephi, merge); | 908 Node* value = node->InputAt(0); |
| 917 } | 909 |
| 918 | 910 auto if_smi = __ MakeDeferredLabel<1>(); |
| 919 EffectControlLinearizer::ValueEffectControl | 911 auto if_not_oddball = __ MakeDeferredLabel<1>(); |
| 920 EffectControlLinearizer::LowerChangeTaggedSignedToInt32(Node* node, | 912 auto if_not_string = __ MakeDeferredLabel<1>(); |
| 921 Node* effect, | 913 auto if_not_heapnumber = __ MakeDeferredLabel<1>(); |
| 922 Node* control) { | 914 auto done = __ MakeLabel<5>(MachineRepresentation::kBit); |
| 923 Node* value = node->InputAt(0); | 915 |
| 924 value = ChangeSmiToInt32(value); | 916 Node* zero = __ Int32Constant(0); |
| 925 return ValueEffectControl(value, effect, control); | 917 Node* fzero = __ Float64Constant(0.0); |
| 926 } | |
| 927 | |
| 928 EffectControlLinearizer::ValueEffectControl | |
| 929 EffectControlLinearizer::LowerChangeTaggedToBit(Node* node, Node* effect, | |
| 930 Node* control) { | |
| 931 Node* value = node->InputAt(0); | |
| 932 value = graph()->NewNode(machine()->WordEqual(), value, | |
| 933 jsgraph()->TrueConstant()); | |
| 934 return ValueEffectControl(value, effect, control); | |
| 935 } | |
| 936 | |
| 937 EffectControlLinearizer::ValueEffectControl | |
| 938 EffectControlLinearizer::LowerTruncateTaggedToBit(Node* node, Node* effect, | |
| 939 Node* control) { | |
| 940 Node* value = node->InputAt(0); | |
| 941 Node* zero = jsgraph()->Int32Constant(0); | |
| 942 Node* fzero = jsgraph()->Float64Constant(0.0); | |
| 943 | |
| 944 // Collect effect/control/value triples. | |
| 945 int count = 0; | |
| 946 Node* values[6]; | |
| 947 Node* effects[6]; | |
| 948 Node* controls[5]; | |
| 949 | 918 |
| 950 // Check if {value} is a Smi. | 919 // Check if {value} is a Smi. |
| 951 Node* check_smi = ObjectIsSmi(value); | 920 Node* check_smi = ObjectIsSmi(value); |
| 952 Node* branch_smi = graph()->NewNode(common()->Branch(BranchHint::kFalse), | 921 __ GotoIf(check_smi, &if_smi); |
| 953 check_smi, control); | |
| 954 | |
| 955 // If {value} is a Smi, then we only need to check that it's not zero. | |
| 956 Node* if_smi = graph()->NewNode(common()->IfTrue(), branch_smi); | |
| 957 Node* esmi = effect; | |
| 958 { | |
| 959 controls[count] = if_smi; | |
| 960 effects[count] = esmi; | |
| 961 values[count] = | |
| 962 graph()->NewNode(machine()->Word32Equal(), | |
| 963 graph()->NewNode(machine()->WordEqual(), value, | |
| 964 jsgraph()->IntPtrConstant(0)), | |
| 965 zero); | |
| 966 count++; | |
| 967 } | |
| 968 control = graph()->NewNode(common()->IfFalse(), branch_smi); | |
| 969 | 922 |
| 970 // Load the map instance type of {value}. | 923 // Load the map instance type of {value}. |
| 971 Node* value_map = effect = graph()->NewNode( | 924 Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); |
| 972 simplified()->LoadField(AccessBuilder::ForMap()), value, effect, control); | 925 Node* value_instance_type = |
| 973 Node* value_instance_type = effect = graph()->NewNode( | 926 __ LoadField(AccessBuilder::ForMapInstanceType(), value_map); |
| 974 simplified()->LoadField(AccessBuilder::ForMapInstanceType()), value_map, | |
| 975 effect, control); | |
| 976 | 927 |
| 977 // Check if {value} is an Oddball. | 928 // Check if {value} is an Oddball. |
| 978 Node* check_oddball = | 929 Node* check_oddball = |
| 979 graph()->NewNode(machine()->Word32Equal(), value_instance_type, | 930 __ Word32Equal(value_instance_type, __ Int32Constant(ODDBALL_TYPE)); |
| 980 jsgraph()->Int32Constant(ODDBALL_TYPE)); | 931 |
| 981 Node* branch_oddball = graph()->NewNode(common()->Branch(BranchHint::kTrue), | 932 __ GotoUnless(check_oddball, &if_not_oddball); |
| 982 check_oddball, control); | |
| 983 | |
| 984 // The only Oddball {value} that is trueish is true itself. | 933 // The only Oddball {value} that is trueish is true itself. |
| 985 Node* if_oddball = graph()->NewNode(common()->IfTrue(), branch_oddball); | 934 __ Goto(&done, __ WordEqual(value, __ TrueConstant())); |
| 986 Node* eoddball = effect; | 935 |
| 987 { | 936 __ Bind(&if_not_oddball); |
| 988 controls[count] = if_oddball; | |
| 989 effects[count] = eoddball; | |
| 990 values[count] = graph()->NewNode(machine()->WordEqual(), value, | |
| 991 jsgraph()->TrueConstant()); | |
| 992 count++; | |
| 993 } | |
| 994 control = graph()->NewNode(common()->IfFalse(), branch_oddball); | |
| 995 | |
| 996 // Check if {value} is a String. | 937 // Check if {value} is a String. |
| 997 Node* check_string = | 938 Node* check_string = __ Int32LessThan(value_instance_type, |
| 998 graph()->NewNode(machine()->Int32LessThan(), value_instance_type, | 939 __ Int32Constant(FIRST_NONSTRING_TYPE)); |
| 999 jsgraph()->Int32Constant(FIRST_NONSTRING_TYPE)); | 940 __ GotoUnless(check_string, &if_not_string); |
| 1000 Node* branch_string = | |
| 1001 graph()->NewNode(common()->Branch(), check_string, control); | |
| 1002 | |
| 1003 // For String {value}, we need to check that the length is not zero. | 941 // For String {value}, we need to check that the length is not zero. |
| 1004 Node* if_string = graph()->NewNode(common()->IfTrue(), branch_string); | 942 Node* value_length = __ LoadField(AccessBuilder::ForStringLength(), value); |
| 1005 Node* estring = effect; | 943 __ Goto(&done, __ Word32Equal( |
| 1006 { | 944 __ WordEqual(value_length, __ IntPtrConstant(0)), zero)); |
| 1007 // Load the {value} length. | 945 |
| 1008 Node* value_length = estring = graph()->NewNode( | 946 __ Bind(&if_not_string); |
| 1009 simplified()->LoadField(AccessBuilder::ForStringLength()), value, | |
| 1010 estring, if_string); | |
| 1011 | |
| 1012 controls[count] = if_string; | |
| 1013 effects[count] = estring; | |
| 1014 values[count] = | |
| 1015 graph()->NewNode(machine()->Word32Equal(), | |
| 1016 graph()->NewNode(machine()->WordEqual(), value_length, | |
| 1017 jsgraph()->IntPtrConstant(0)), | |
| 1018 zero); | |
| 1019 count++; | |
| 1020 } | |
| 1021 control = graph()->NewNode(common()->IfFalse(), branch_string); | |
| 1022 | |
| 1023 // Check if {value} is a HeapNumber. | 947 // Check if {value} is a HeapNumber. |
| 1024 Node* check_heapnumber = | 948 Node* check_heapnumber = |
| 1025 graph()->NewNode(machine()->Word32Equal(), value_instance_type, | 949 __ Word32Equal(value_instance_type, __ Int32Constant(HEAP_NUMBER_TYPE)); |
| 1026 jsgraph()->Int32Constant(HEAP_NUMBER_TYPE)); | 950 __ GotoUnless(check_heapnumber, &if_not_heapnumber); |
| 1027 Node* branch_heapnumber = | 951 |
| 1028 graph()->NewNode(common()->Branch(), check_heapnumber, control); | 952 // For HeapNumber {value}, just check that its value is not 0.0, -0.0 or |
| 1029 | 953 // NaN. |
| 1030 // For HeapNumber {value}, just check that its value is not 0.0, -0.0 or NaN. | 954 // Load the raw value of {value}. |
| 1031 Node* if_heapnumber = graph()->NewNode(common()->IfTrue(), branch_heapnumber); | 955 Node* value_value = __ LoadField(AccessBuilder::ForHeapNumberValue(), value); |
| 1032 Node* eheapnumber = effect; | 956 __ Goto(&done, __ Float64LessThan(fzero, __ Float64Abs(value_value))); |
| 1033 { | |
| 1034 // Load the raw value of {value}. | |
| 1035 Node* value_value = eheapnumber = graph()->NewNode( | |
| 1036 simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), value, | |
| 1037 eheapnumber, if_heapnumber); | |
| 1038 | |
| 1039 // Check if {value} is not one of 0, -0, or NaN. | |
| 1040 controls[count] = if_heapnumber; | |
| 1041 effects[count] = eheapnumber; | |
| 1042 values[count] = graph()->NewNode( | |
| 1043 machine()->Float64LessThan(), fzero, | |
| 1044 graph()->NewNode(machine()->Float64Abs(), value_value)); | |
| 1045 count++; | |
| 1046 } | |
| 1047 control = graph()->NewNode(common()->IfFalse(), branch_heapnumber); | |
| 1048 | 957 |
| 1049 // The {value} is either a JSReceiver, a Symbol or some Simd128Value. In | 958 // The {value} is either a JSReceiver, a Symbol or some Simd128Value. In |
| 1050 // those cases we can just the undetectable bit on the map, which will only | 959 // those cases we can just the undetectable bit on the map, which will only |
| 1051 // be set for certain JSReceivers, i.e. document.all. | 960 // be set for certain JSReceivers, i.e. document.all. |
| 1052 { | 961 __ Bind(&if_not_heapnumber); |
| 1053 // Load the {value} map bit field. | 962 |
| 1054 Node* value_map_bitfield = effect = graph()->NewNode( | 963 // Load the {value} map bit field. |
| 1055 simplified()->LoadField(AccessBuilder::ForMapBitField()), value_map, | 964 Node* value_map_bitfield = |
| 1056 effect, control); | 965 __ LoadField(AccessBuilder::ForMapBitField(), value_map); |
| 1057 | 966 __ Goto(&done, __ Word32Equal( |
| 1058 controls[count] = control; | 967 __ Word32And(value_map_bitfield, |
| 1059 effects[count] = effect; | 968 __ Int32Constant(1 << Map::kIsUndetectable)), |
| 1060 values[count] = graph()->NewNode( | 969 zero)); |
| 1061 machine()->Word32Equal(), | 970 |
| 1062 graph()->NewNode(machine()->Word32And(), value_map_bitfield, | 971 __ Bind(&if_smi); |
| 1063 jsgraph()->Int32Constant(1 << Map::kIsUndetectable)), | 972 // If {value} is a Smi, then we only need to check that it's not zero. |
| 1064 zero); | 973 __ Goto(&done, |
| 1065 count++; | 974 __ Word32Equal(__ WordEqual(value, __ IntPtrConstant(0)), zero)); |
| 1066 } | 975 |
| 1067 | 976 __ Bind(&done); |
| 1068 // Merge the different controls. | 977 return done.PhiAt(0); |
| 1069 control = graph()->NewNode(common()->Merge(count), count, controls); | 978 } |
| 1070 effects[count] = control; | 979 |
| 1071 effect = graph()->NewNode(common()->EffectPhi(count), count + 1, effects); | 980 Node* EffectControlLinearizer::LowerChangeTaggedToInt32(Node* node) { |
| 1072 values[count] = control; | 981 Node* value = node->InputAt(0); |
| 1073 value = graph()->NewNode(common()->Phi(MachineRepresentation::kBit, count), | 982 |
| 1074 count + 1, values); | 983 auto if_not_smi = __ MakeDeferredLabel<1>(); |
| 1075 | 984 auto done = __ MakeLabel<2>(MachineRepresentation::kWord32); |
| 1076 return ValueEffectControl(value, effect, control); | |
| 1077 } | |
| 1078 | |
| 1079 EffectControlLinearizer::ValueEffectControl | |
| 1080 EffectControlLinearizer::LowerChangeTaggedToInt32(Node* node, Node* effect, | |
| 1081 Node* control) { | |
| 1082 Node* value = node->InputAt(0); | |
| 1083 | 985 |
| 1084 Node* check = ObjectIsSmi(value); | 986 Node* check = ObjectIsSmi(value); |
| 1085 Node* branch = | 987 __ GotoUnless(check, &if_not_smi); |
| 1086 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control); | 988 __ Goto(&done, ChangeSmiToInt32(value)); |
| 1087 | 989 |
| 1088 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); | 990 __ Bind(&if_not_smi); |
| 1089 Node* etrue = effect; | 991 STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset); |
| 992 Node* vfalse = __ LoadField(AccessBuilder::ForHeapNumberValue(), value); |
| 993 vfalse = __ ChangeFloat64ToInt32(vfalse); |
| 994 __ Goto(&done, vfalse); |
| 995 |
| 996 __ Bind(&done); |
| 997 return done.PhiAt(0); |
| 998 } |
| 999 |
| 1000 Node* EffectControlLinearizer::LowerChangeTaggedToUint32(Node* node) { |
| 1001 Node* value = node->InputAt(0); |
| 1002 |
| 1003 auto if_not_smi = __ MakeDeferredLabel<1>(); |
| 1004 auto done = __ MakeLabel<2>(MachineRepresentation::kWord32); |
| 1005 |
| 1006 Node* check = ObjectIsSmi(value); |
| 1007 __ GotoUnless(check, &if_not_smi); |
| 1008 __ Goto(&done, ChangeSmiToInt32(value)); |
| 1009 |
| 1010 __ Bind(&if_not_smi); |
| 1011 STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset); |
| 1012 Node* vfalse = __ LoadField(AccessBuilder::ForHeapNumberValue(), value); |
| 1013 vfalse = __ ChangeFloat64ToUint32(vfalse); |
| 1014 __ Goto(&done, vfalse); |
| 1015 |
| 1016 __ Bind(&done); |
| 1017 return done.PhiAt(0); |
| 1018 } |
| 1019 |
| 1020 Node* EffectControlLinearizer::LowerChangeTaggedToFloat64(Node* node) { |
| 1021 return LowerTruncateTaggedToFloat64(node); |
| 1022 } |
| 1023 |
| 1024 Node* EffectControlLinearizer::LowerTruncateTaggedToFloat64(Node* node) { |
| 1025 Node* value = node->InputAt(0); |
| 1026 |
| 1027 auto if_not_smi = __ MakeDeferredLabel<1>(); |
| 1028 auto done = __ MakeLabel<2>(MachineRepresentation::kFloat64); |
| 1029 |
| 1030 Node* check = ObjectIsSmi(value); |
| 1031 __ GotoUnless(check, &if_not_smi); |
| 1090 Node* vtrue = ChangeSmiToInt32(value); | 1032 Node* vtrue = ChangeSmiToInt32(value); |
| 1091 | 1033 vtrue = __ ChangeInt32ToFloat64(vtrue); |
| 1092 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); | 1034 __ Goto(&done, vtrue); |
| 1093 Node* efalse = effect; | 1035 |
| 1094 Node* vfalse; | 1036 __ Bind(&if_not_smi); |
| 1095 { | 1037 STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset); |
| 1096 STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset); | 1038 Node* vfalse = __ LoadField(AccessBuilder::ForHeapNumberValue(), value); |
| 1097 vfalse = efalse = graph()->NewNode( | 1039 __ Goto(&done, vfalse); |
| 1098 simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), value, | 1040 |
| 1099 efalse, if_false); | 1041 __ Bind(&done); |
| 1100 vfalse = graph()->NewNode(machine()->ChangeFloat64ToInt32(), vfalse); | 1042 return done.PhiAt(0); |
| 1101 } | 1043 } |
| 1102 | 1044 |
| 1103 control = graph()->NewNode(common()->Merge(2), if_true, if_false); | 1045 Node* EffectControlLinearizer::LowerCheckBounds(Node* node, Node* frame_state) { |
| 1104 effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control); | |
| 1105 value = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2), | |
| 1106 vtrue, vfalse, control); | |
| 1107 | |
| 1108 return ValueEffectControl(value, effect, control); | |
| 1109 } | |
| 1110 | |
| 1111 EffectControlLinearizer::ValueEffectControl | |
| 1112 EffectControlLinearizer::LowerChangeTaggedToUint32(Node* node, Node* effect, | |
| 1113 Node* control) { | |
| 1114 Node* value = node->InputAt(0); | |
| 1115 | |
| 1116 Node* check = ObjectIsSmi(value); | |
| 1117 Node* branch = | |
| 1118 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control); | |
| 1119 | |
| 1120 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); | |
| 1121 Node* etrue = effect; | |
| 1122 Node* vtrue = ChangeSmiToInt32(value); | |
| 1123 | |
| 1124 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); | |
| 1125 Node* efalse = effect; | |
| 1126 Node* vfalse; | |
| 1127 { | |
| 1128 STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset); | |
| 1129 vfalse = efalse = graph()->NewNode( | |
| 1130 simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), value, | |
| 1131 efalse, if_false); | |
| 1132 vfalse = graph()->NewNode(machine()->ChangeFloat64ToUint32(), vfalse); | |
| 1133 } | |
| 1134 | |
| 1135 control = graph()->NewNode(common()->Merge(2), if_true, if_false); | |
| 1136 effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control); | |
| 1137 value = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2), | |
| 1138 vtrue, vfalse, control); | |
| 1139 | |
| 1140 return ValueEffectControl(value, effect, control); | |
| 1141 } | |
| 1142 | |
| 1143 EffectControlLinearizer::ValueEffectControl | |
| 1144 EffectControlLinearizer::LowerChangeTaggedToFloat64(Node* node, Node* effect, | |
| 1145 Node* control) { | |
| 1146 return LowerTruncateTaggedToFloat64(node, effect, control); | |
| 1147 } | |
| 1148 | |
| 1149 EffectControlLinearizer::ValueEffectControl | |
| 1150 EffectControlLinearizer::LowerTruncateTaggedToFloat64(Node* node, Node* effect, | |
| 1151 Node* control) { | |
| 1152 Node* value = node->InputAt(0); | |
| 1153 | |
| 1154 Node* check = ObjectIsSmi(value); | |
| 1155 Node* branch = | |
| 1156 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control); | |
| 1157 | |
| 1158 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); | |
| 1159 Node* etrue = effect; | |
| 1160 Node* vtrue; | |
| 1161 { | |
| 1162 vtrue = ChangeSmiToInt32(value); | |
| 1163 vtrue = graph()->NewNode(machine()->ChangeInt32ToFloat64(), vtrue); | |
| 1164 } | |
| 1165 | |
| 1166 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); | |
| 1167 Node* efalse = effect; | |
| 1168 Node* vfalse; | |
| 1169 { | |
| 1170 STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset); | |
| 1171 vfalse = efalse = graph()->NewNode( | |
| 1172 simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), value, | |
| 1173 efalse, if_false); | |
| 1174 } | |
| 1175 | |
| 1176 control = graph()->NewNode(common()->Merge(2), if_true, if_false); | |
| 1177 effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control); | |
| 1178 value = graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2), | |
| 1179 vtrue, vfalse, control); | |
| 1180 | |
| 1181 return ValueEffectControl(value, effect, control); | |
| 1182 } | |
| 1183 | |
| 1184 EffectControlLinearizer::ValueEffectControl | |
| 1185 EffectControlLinearizer::LowerCheckBounds(Node* node, Node* frame_state, | |
| 1186 Node* effect, Node* control) { | |
| 1187 Node* index = node->InputAt(0); | 1046 Node* index = node->InputAt(0); |
| 1188 Node* limit = node->InputAt(1); | 1047 Node* limit = node->InputAt(1); |
| 1189 | 1048 |
| 1190 Node* check = graph()->NewNode(machine()->Uint32LessThan(), index, limit); | 1049 Node* check = __ Uint32LessThan(index, limit); |
| 1191 control = effect = graph()->NewNode( | 1050 __ DeoptimizeUnless(DeoptimizeReason::kOutOfBounds, check, frame_state); |
| 1192 common()->DeoptimizeUnless(DeoptimizeReason::kOutOfBounds), check, | 1051 return index; |
| 1193 frame_state, effect, control); | 1052 } |
| 1194 | 1053 |
| 1195 return ValueEffectControl(index, effect, control); | 1054 Node* EffectControlLinearizer::LowerCheckMaps(Node* node, Node* frame_state) { |
| 1196 } | 1055 Node* value = node->InputAt(0); |
| 1197 | 1056 |
| 1198 EffectControlLinearizer::ValueEffectControl | 1057 int const map_count = node->op()->ValueInputCount() - 1; |
| 1199 EffectControlLinearizer::LowerCheckMaps(Node* node, Node* frame_state, | 1058 auto done = __ MakeLabelFor(GraphAssemblerLabelType::kNonDeferred, |
| 1200 Node* effect, Node* control) { | 1059 static_cast<size_t>(map_count)); |
| 1201 Node* value = node->InputAt(0); | |
| 1202 | 1060 |
| 1203 // Load the current map of the {value}. | 1061 // Load the current map of the {value}. |
| 1204 Node* value_map = effect = graph()->NewNode( | 1062 Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); |
| 1205 simplified()->LoadField(AccessBuilder::ForMap()), value, effect, control); | |
| 1206 | |
| 1207 int const map_count = node->op()->ValueInputCount() - 1; | |
| 1208 Node** controls = temp_zone()->NewArray<Node*>(map_count); | |
| 1209 Node** effects = temp_zone()->NewArray<Node*>(map_count + 1); | |
| 1210 | 1063 |
| 1211 for (int i = 0; i < map_count; ++i) { | 1064 for (int i = 0; i < map_count; ++i) { |
| 1212 Node* map = node->InputAt(1 + i); | 1065 Node* map = node->InputAt(1 + i); |
| 1213 | 1066 Node* check = __ WordEqual(value_map, map); |
| 1214 Node* check = graph()->NewNode(machine()->WordEqual(), value_map, map); | |
| 1215 if (i == map_count - 1) { | 1067 if (i == map_count - 1) { |
| 1216 controls[i] = effects[i] = graph()->NewNode( | 1068 __ DeoptimizeUnless(DeoptimizeReason::kWrongMap, check, frame_state); |
| 1217 common()->DeoptimizeUnless(DeoptimizeReason::kWrongMap), check, | |
| 1218 frame_state, effect, control); | |
| 1219 } else { | 1069 } else { |
| 1220 control = graph()->NewNode(common()->Branch(), check, control); | 1070 __ GotoIf(check, &done); |
| 1221 controls[i] = graph()->NewNode(common()->IfTrue(), control); | |
| 1222 control = graph()->NewNode(common()->IfFalse(), control); | |
| 1223 effects[i] = effect; | |
| 1224 } | 1071 } |
| 1225 } | 1072 } |
| 1226 | 1073 __ Goto(&done); |
| 1227 control = graph()->NewNode(common()->Merge(map_count), map_count, controls); | 1074 __ Bind(&done); |
| 1228 effects[map_count] = control; | 1075 return value; |
| 1229 effect = | 1076 } |
| 1230 graph()->NewNode(common()->EffectPhi(map_count), map_count + 1, effects); | 1077 |
| 1231 | 1078 Node* EffectControlLinearizer::LowerCheckNumber(Node* node, Node* frame_state) { |
| 1232 return ValueEffectControl(value, effect, control); | 1079 Node* value = node->InputAt(0); |
| 1233 } | 1080 |
| 1234 | 1081 auto if_not_smi = __ MakeDeferredLabel<1>(); |
| 1235 EffectControlLinearizer::ValueEffectControl | 1082 auto done = __ MakeLabel<2>(); |
| 1236 EffectControlLinearizer::LowerCheckNumber(Node* node, Node* frame_state, | |
| 1237 Node* effect, Node* control) { | |
| 1238 Node* value = node->InputAt(0); | |
| 1239 | 1083 |
| 1240 Node* check0 = ObjectIsSmi(value); | 1084 Node* check0 = ObjectIsSmi(value); |
| 1241 Node* branch0 = | 1085 __ GotoUnless(check0, &if_not_smi); |
| 1242 graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control); | 1086 __ Goto(&done); |
| 1243 | 1087 |
| 1244 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0); | 1088 __ Bind(&if_not_smi); |
| 1245 Node* etrue0 = effect; | 1089 Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); |
| 1246 | 1090 Node* check1 = __ WordEqual(value_map, __ HeapNumberMapConstant()); |
| 1247 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0); | 1091 __ DeoptimizeUnless(DeoptimizeReason::kNotAHeapNumber, check1, frame_state); |
| 1248 Node* efalse0 = effect; | 1092 __ Goto(&done); |
| 1249 { | 1093 |
| 1250 Node* value_map = efalse0 = | 1094 __ Bind(&done); |
| 1251 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), | 1095 return value; |
| 1252 value, efalse0, if_false0); | 1096 } |
| 1253 Node* check1 = graph()->NewNode(machine()->WordEqual(), value_map, | 1097 |
| 1254 jsgraph()->HeapNumberMapConstant()); | 1098 Node* EffectControlLinearizer::LowerCheckString(Node* node, Node* frame_state) { |
| 1255 if_false0 = efalse0 = graph()->NewNode( | |
| 1256 common()->DeoptimizeUnless(DeoptimizeReason::kNotAHeapNumber), check1, | |
| 1257 frame_state, efalse0, if_false0); | |
| 1258 } | |
| 1259 | |
| 1260 control = graph()->NewNode(common()->Merge(2), if_true0, if_false0); | |
| 1261 effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control); | |
| 1262 | |
| 1263 return ValueEffectControl(value, effect, control); | |
| 1264 } | |
| 1265 | |
| 1266 EffectControlLinearizer::ValueEffectControl | |
| 1267 EffectControlLinearizer::LowerCheckString(Node* node, Node* frame_state, | |
| 1268 Node* effect, Node* control) { | |
| 1269 Node* value = node->InputAt(0); | 1099 Node* value = node->InputAt(0); |
| 1270 | 1100 |
| 1271 Node* check0 = ObjectIsSmi(value); | 1101 Node* check0 = ObjectIsSmi(value); |
| 1272 control = effect = | 1102 __ DeoptimizeIf(DeoptimizeReason::kSmi, check0, frame_state); |
| 1273 graph()->NewNode(common()->DeoptimizeIf(DeoptimizeReason::kSmi), check0, | 1103 |
| 1274 frame_state, effect, control); | 1104 Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); |
| 1275 | 1105 Node* value_instance_type = |
| 1276 Node* value_map = effect = graph()->NewNode( | 1106 __ LoadField(AccessBuilder::ForMapInstanceType(), value_map); |
| 1277 simplified()->LoadField(AccessBuilder::ForMap()), value, effect, control); | 1107 |
| 1278 Node* value_instance_type = effect = graph()->NewNode( | 1108 Node* check1 = __ Uint32LessThan(value_instance_type, |
| 1279 simplified()->LoadField(AccessBuilder::ForMapInstanceType()), value_map, | 1109 __ Uint32Constant(FIRST_NONSTRING_TYPE)); |
| 1280 effect, control); | 1110 __ DeoptimizeUnless(DeoptimizeReason::kWrongInstanceType, check1, |
| 1281 | 1111 frame_state); |
| 1282 Node* check1 = | 1112 return value; |
| 1283 graph()->NewNode(machine()->Uint32LessThan(), value_instance_type, | 1113 } |
| 1284 jsgraph()->Uint32Constant(FIRST_NONSTRING_TYPE)); | 1114 |
| 1285 control = effect = graph()->NewNode( | 1115 Node* EffectControlLinearizer::LowerCheckIf(Node* node, Node* frame_state) { |
| 1286 common()->DeoptimizeUnless(DeoptimizeReason::kWrongInstanceType), check1, | 1116 Node* value = node->InputAt(0); |
| 1287 frame_state, effect, control); | 1117 __ DeoptimizeUnless(DeoptimizeReason::kNoReason, value, frame_state); |
| 1288 | 1118 return value; |
| 1289 return ValueEffectControl(value, effect, control); | 1119 } |
| 1290 } | 1120 |
| 1291 | 1121 Node* EffectControlLinearizer::LowerCheckedInt32Add(Node* node, |
| 1292 EffectControlLinearizer::ValueEffectControl | 1122 Node* frame_state) { |
| 1293 EffectControlLinearizer::LowerCheckIf(Node* node, Node* frame_state, | |
| 1294 Node* effect, Node* control) { | |
| 1295 Node* value = node->InputAt(0); | |
| 1296 | |
| 1297 control = effect = | |
| 1298 graph()->NewNode(common()->DeoptimizeUnless(DeoptimizeReason::kNoReason), | |
| 1299 value, frame_state, effect, control); | |
| 1300 | |
| 1301 return ValueEffectControl(value, effect, control); | |
| 1302 } | |
| 1303 | |
| 1304 EffectControlLinearizer::ValueEffectControl | |
| 1305 EffectControlLinearizer::LowerCheckedInt32Add(Node* node, Node* frame_state, | |
| 1306 Node* effect, Node* control) { | |
| 1307 Node* lhs = node->InputAt(0); | 1123 Node* lhs = node->InputAt(0); |
| 1308 Node* rhs = node->InputAt(1); | 1124 Node* rhs = node->InputAt(1); |
| 1309 | 1125 |
| 1310 Node* value = | 1126 Node* value = __ Int32AddWithOverflow(lhs, rhs); |
| 1311 graph()->NewNode(machine()->Int32AddWithOverflow(), lhs, rhs, control); | 1127 Node* check = __ Projection(1, value); |
| 1312 | 1128 __ DeoptimizeIf(DeoptimizeReason::kOverflow, check, frame_state); |
| 1313 Node* check = graph()->NewNode(common()->Projection(1), value, control); | 1129 return __ Projection(0, value); |
| 1314 control = effect = | 1130 } |
| 1315 graph()->NewNode(common()->DeoptimizeIf(DeoptimizeReason::kOverflow), | 1131 |
| 1316 check, frame_state, effect, control); | 1132 Node* EffectControlLinearizer::LowerCheckedInt32Sub(Node* node, |
| 1317 | 1133 Node* frame_state) { |
| 1318 value = graph()->NewNode(common()->Projection(0), value, control); | |
| 1319 | |
| 1320 return ValueEffectControl(value, effect, control); | |
| 1321 } | |
| 1322 | |
| 1323 EffectControlLinearizer::ValueEffectControl | |
| 1324 EffectControlLinearizer::LowerCheckedInt32Sub(Node* node, Node* frame_state, | |
| 1325 Node* effect, Node* control) { | |
| 1326 Node* lhs = node->InputAt(0); | 1134 Node* lhs = node->InputAt(0); |
| 1327 Node* rhs = node->InputAt(1); | 1135 Node* rhs = node->InputAt(1); |
| 1328 | 1136 |
| 1329 Node* value = | 1137 Node* value = __ Int32SubWithOverflow(lhs, rhs); |
| 1330 graph()->NewNode(machine()->Int32SubWithOverflow(), lhs, rhs, control); | 1138 Node* check = __ Projection(1, value); |
| 1331 | 1139 __ DeoptimizeIf(DeoptimizeReason::kOverflow, check, frame_state); |
| 1332 Node* check = graph()->NewNode(common()->Projection(1), value, control); | 1140 return __ Projection(0, value); |
| 1333 control = effect = | 1141 } |
| 1334 graph()->NewNode(common()->DeoptimizeIf(DeoptimizeReason::kOverflow), | 1142 |
| 1335 check, frame_state, effect, control); | 1143 Node* EffectControlLinearizer::LowerCheckedInt32Div(Node* node, |
| 1336 | 1144 Node* frame_state) { |
| 1337 value = graph()->NewNode(common()->Projection(0), value, control); | |
| 1338 | |
| 1339 return ValueEffectControl(value, effect, control); | |
| 1340 } | |
| 1341 | |
| 1342 EffectControlLinearizer::ValueEffectControl | |
| 1343 EffectControlLinearizer::LowerCheckedInt32Div(Node* node, Node* frame_state, | |
| 1344 Node* effect, Node* control) { | |
| 1345 Node* zero = jsgraph()->Int32Constant(0); | |
| 1346 Node* minusone = jsgraph()->Int32Constant(-1); | |
| 1347 Node* minint = jsgraph()->Int32Constant(std::numeric_limits<int32_t>::min()); | |
| 1348 | |
| 1349 Node* lhs = node->InputAt(0); | 1145 Node* lhs = node->InputAt(0); |
| 1350 Node* rhs = node->InputAt(1); | 1146 Node* rhs = node->InputAt(1); |
| 1351 | 1147 |
| 1148 auto if_not_positive = __ MakeDeferredLabel<1>(); |
| 1149 auto if_is_minint = __ MakeDeferredLabel<1>(); |
| 1150 auto done = __ MakeLabel<2>(MachineRepresentation::kWord32); |
| 1151 auto minint_check_done = __ MakeLabel<2>(); |
| 1152 |
| 1153 Node* zero = __ Int32Constant(0); |
| 1154 |
| 1352 // Check if {rhs} is positive (and not zero). | 1155 // Check if {rhs} is positive (and not zero). |
| 1353 Node* check0 = graph()->NewNode(machine()->Int32LessThan(), zero, rhs); | 1156 Node* check0 = __ Int32LessThan(zero, rhs); |
| 1354 Node* branch0 = | 1157 __ GotoUnless(check0, &if_not_positive); |
| 1355 graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control); | 1158 |
| 1356 | 1159 // Fast case, no additional checking required. |
| 1357 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0); | 1160 __ Goto(&done, __ Int32Div(lhs, rhs)); |
| 1358 Node* etrue0 = effect; | 1161 |
| 1359 Node* vtrue0; | |
| 1360 { | 1162 { |
| 1361 // Fast case, no additional checking required. | 1163 __ Bind(&if_not_positive); |
| 1362 vtrue0 = graph()->NewNode(machine()->Int32Div(), lhs, rhs, if_true0); | 1164 |
| 1363 } | |
| 1364 | |
| 1365 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0); | |
| 1366 Node* efalse0 = effect; | |
| 1367 Node* vfalse0; | |
| 1368 { | |
| 1369 // Check if {rhs} is zero. | 1165 // Check if {rhs} is zero. |
| 1370 Node* check = graph()->NewNode(machine()->Word32Equal(), rhs, zero); | 1166 Node* check = __ Word32Equal(rhs, zero); |
| 1371 if_false0 = efalse0 = graph()->NewNode( | 1167 __ DeoptimizeIf(DeoptimizeReason::kDivisionByZero, check, frame_state); |
| 1372 common()->DeoptimizeIf(DeoptimizeReason::kDivisionByZero), check, | |
| 1373 frame_state, efalse0, if_false0); | |
| 1374 | 1168 |
| 1375 // Check if {lhs} is zero, as that would produce minus zero. | 1169 // Check if {lhs} is zero, as that would produce minus zero. |
| 1376 check = graph()->NewNode(machine()->Word32Equal(), lhs, zero); | 1170 check = __ Word32Equal(lhs, zero); |
| 1377 if_false0 = efalse0 = | 1171 __ DeoptimizeIf(DeoptimizeReason::kMinusZero, check, frame_state); |
| 1378 graph()->NewNode(common()->DeoptimizeIf(DeoptimizeReason::kMinusZero), | |
| 1379 check, frame_state, efalse0, if_false0); | |
| 1380 | 1172 |
| 1381 // Check if {lhs} is kMinInt and {rhs} is -1, in which case we'd have | 1173 // Check if {lhs} is kMinInt and {rhs} is -1, in which case we'd have |
| 1382 // to return -kMinInt, which is not representable. | 1174 // to return -kMinInt, which is not representable. |
| 1175 Node* minint = __ Int32Constant(std::numeric_limits<int32_t>::min()); |
| 1383 Node* check1 = graph()->NewNode(machine()->Word32Equal(), lhs, minint); | 1176 Node* check1 = graph()->NewNode(machine()->Word32Equal(), lhs, minint); |
| 1384 Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kFalse), | 1177 __ GotoIf(check1, &if_is_minint); |
| 1385 check1, if_false0); | 1178 __ Goto(&minint_check_done); |
| 1386 | 1179 |
| 1387 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); | 1180 __ Bind(&if_is_minint); |
| 1388 Node* etrue1 = efalse0; | 1181 // Check if {rhs} is -1. |
| 1389 { | 1182 Node* minusone = __ Int32Constant(-1); |
| 1390 // Check if {rhs} is -1. | 1183 Node* is_minus_one = __ Word32Equal(rhs, minusone); |
| 1391 Node* check = graph()->NewNode(machine()->Word32Equal(), rhs, minusone); | 1184 __ DeoptimizeIf(DeoptimizeReason::kOverflow, is_minus_one, frame_state); |
| 1392 if_true1 = etrue1 = | 1185 __ Goto(&minint_check_done); |
| 1393 graph()->NewNode(common()->DeoptimizeIf(DeoptimizeReason::kOverflow), | 1186 |
| 1394 check, frame_state, etrue1, if_true1); | 1187 __ Bind(&minint_check_done); |
| 1395 } | |
| 1396 | |
| 1397 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); | |
| 1398 Node* efalse1 = efalse0; | |
| 1399 | |
| 1400 if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1); | |
| 1401 efalse0 = | |
| 1402 graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_false0); | |
| 1403 | |
| 1404 // Perform the actual integer division. | 1188 // Perform the actual integer division. |
| 1405 vfalse0 = graph()->NewNode(machine()->Int32Div(), lhs, rhs, if_false0); | 1189 __ Goto(&done, __ Int32Div(lhs, rhs)); |
| 1406 } | 1190 } |
| 1407 | 1191 |
| 1408 control = graph()->NewNode(common()->Merge(2), if_true0, if_false0); | 1192 __ Bind(&done); |
| 1409 effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control); | 1193 Node* value = done.PhiAt(0); |
| 1410 Node* value = | |
| 1411 graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2), vtrue0, | |
| 1412 vfalse0, control); | |
| 1413 | 1194 |
| 1414 // Check if the remainder is non-zero. | 1195 // Check if the remainder is non-zero. |
| 1415 Node* check = | 1196 Node* check = __ Word32Equal(lhs, __ Int32Mul(rhs, value)); |
| 1416 graph()->NewNode(machine()->Word32Equal(), lhs, | 1197 __ DeoptimizeUnless(DeoptimizeReason::kLostPrecision, check, frame_state); |
| 1417 graph()->NewNode(machine()->Int32Mul(), rhs, value)); | 1198 |
| 1418 control = effect = graph()->NewNode( | 1199 return value; |
| 1419 common()->DeoptimizeUnless(DeoptimizeReason::kLostPrecision), check, | 1200 } |
| 1420 frame_state, effect, control); | 1201 |
| 1421 | 1202 Node* EffectControlLinearizer::LowerCheckedInt32Mod(Node* node, |
| 1422 return ValueEffectControl(value, effect, control); | 1203 Node* frame_state) { |
| 1423 } | |
| 1424 | |
| 1425 EffectControlLinearizer::ValueEffectControl | |
| 1426 EffectControlLinearizer::LowerCheckedInt32Mod(Node* node, Node* frame_state, | |
| 1427 Node* effect, Node* control) { | |
| 1428 Node* zero = jsgraph()->Int32Constant(0); | |
| 1429 Node* one = jsgraph()->Int32Constant(1); | |
| 1430 | |
| 1431 // General case for signed integer modulus, with optimization for (unknown) | 1204 // General case for signed integer modulus, with optimization for (unknown) |
| 1432 // power of 2 right hand side. | 1205 // power of 2 right hand side. |
| 1433 // | 1206 // |
| 1434 // if rhs <= 0 then | 1207 // if rhs <= 0 then |
| 1435 // rhs = -rhs | 1208 // rhs = -rhs |
| 1436 // deopt if rhs == 0 | 1209 // deopt if rhs == 0 |
| 1437 // if lhs < 0 then | 1210 // if lhs < 0 then |
| 1438 // let res = lhs % rhs in | 1211 // let res = lhs % rhs in |
| 1439 // deopt if res == 0 | 1212 // deopt if res == 0 |
| 1440 // res | 1213 // res |
| 1441 // else | 1214 // else |
| 1442 // let msk = rhs - 1 in | 1215 // let msk = rhs - 1 in |
| 1443 // if rhs & msk == 0 then | 1216 // if rhs & msk == 0 then |
| 1444 // lhs & msk | 1217 // lhs & msk |
| 1445 // else | 1218 // else |
| 1446 // lhs % rhs | 1219 // lhs % rhs |
| 1447 // | 1220 // |
| 1448 Node* lhs = node->InputAt(0); | 1221 Node* lhs = node->InputAt(0); |
| 1449 Node* rhs = node->InputAt(1); | 1222 Node* rhs = node->InputAt(1); |
| 1450 | 1223 |
| 1224 auto if_rhs_not_positive = __ MakeDeferredLabel<1>(); |
| 1225 auto if_lhs_negative = __ MakeDeferredLabel<1>(); |
| 1226 auto if_power_of_two = __ MakeLabel<1>(); |
| 1227 auto rhs_checked = __ MakeLabel<2>(MachineRepresentation::kWord32); |
| 1228 auto done = __ MakeLabel<3>(MachineRepresentation::kWord32); |
| 1229 |
| 1230 Node* zero = __ Int32Constant(0); |
| 1231 |
| 1451 // Check if {rhs} is not strictly positive. | 1232 // Check if {rhs} is not strictly positive. |
| 1452 Node* check0 = graph()->NewNode(machine()->Int32LessThanOrEqual(), rhs, zero); | 1233 Node* check0 = __ Int32LessThanOrEqual(rhs, zero); |
| 1453 Node* branch0 = | 1234 __ GotoIf(check0, &if_rhs_not_positive); |
| 1454 graph()->NewNode(common()->Branch(BranchHint::kFalse), check0, control); | 1235 __ Goto(&rhs_checked, rhs); |
| 1455 | 1236 |
| 1456 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0); | 1237 __ Bind(&if_rhs_not_positive); |
| 1457 Node* etrue0 = effect; | |
| 1458 Node* vtrue0; | |
| 1459 { | 1238 { |
| 1460 // Negate {rhs}, might still produce a negative result in case of | 1239 // Negate {rhs}, might still produce a negative result in case of |
| 1461 // -2^31, but that is handled safely below. | 1240 // -2^31, but that is handled safely below. |
| 1462 vtrue0 = graph()->NewNode(machine()->Int32Sub(), zero, rhs); | 1241 Node* vtrue0 = __ Int32Sub(zero, rhs); |
| 1463 | 1242 |
| 1464 // Ensure that {rhs} is not zero, otherwise we'd have to return NaN. | 1243 // Ensure that {rhs} is not zero, otherwise we'd have to return NaN. |
| 1465 Node* check = graph()->NewNode(machine()->Word32Equal(), vtrue0, zero); | 1244 Node* check = __ Word32Equal(vtrue0, zero); |
| 1466 if_true0 = etrue0 = graph()->NewNode( | 1245 __ DeoptimizeIf(DeoptimizeReason::kDivisionByZero, check, frame_state); |
| 1467 common()->DeoptimizeIf(DeoptimizeReason::kDivisionByZero), check, | 1246 __ Goto(&rhs_checked, vtrue0); |
| 1468 frame_state, etrue0, if_true0); | 1247 } |
| 1469 } | 1248 |
| 1470 | 1249 __ Bind(&rhs_checked); |
| 1471 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0); | 1250 rhs = rhs_checked.PhiAt(0); |
| 1472 Node* efalse0 = effect; | |
| 1473 Node* vfalse0 = rhs; | |
| 1474 | |
| 1475 // At this point {rhs} is either greater than zero or -2^31, both are | |
| 1476 // fine for the code that follows. | |
| 1477 control = graph()->NewNode(common()->Merge(2), if_true0, if_false0); | |
| 1478 effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control); | |
| 1479 rhs = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2), | |
| 1480 vtrue0, vfalse0, control); | |
| 1481 | 1251 |
| 1482 // Check if {lhs} is negative. | 1252 // Check if {lhs} is negative. |
| 1483 Node* check1 = graph()->NewNode(machine()->Int32LessThan(), lhs, zero); | 1253 Node* check1 = __ Int32LessThan(lhs, zero); |
| 1484 Node* branch1 = | 1254 __ GotoIf(check1, &if_lhs_negative); |
| 1485 graph()->NewNode(common()->Branch(BranchHint::kFalse), check1, control); | 1255 |
| 1486 | 1256 // {lhs} non-negative. |
| 1487 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); | 1257 { |
| 1488 Node* etrue1 = effect; | 1258 Node* one = __ Int32Constant(1); |
| 1489 Node* vtrue1; | 1259 Node* msk = __ Int32Sub(rhs, one); |
| 1260 |
| 1261 // Check if {rhs} minus one is a valid mask. |
| 1262 Node* check2 = __ Word32Equal(__ Word32And(rhs, msk), zero); |
| 1263 __ GotoIf(check2, &if_power_of_two); |
| 1264 // Compute the remainder using the generic {lhs % rhs}. |
| 1265 __ Goto(&done, __ Int32Mod(lhs, rhs)); |
| 1266 |
| 1267 __ Bind(&if_power_of_two); |
| 1268 // Compute the remainder using {lhs & msk}. |
| 1269 __ Goto(&done, __ Word32And(lhs, msk)); |
| 1270 } |
| 1271 |
| 1272 __ Bind(&if_lhs_negative); |
| 1490 { | 1273 { |
| 1491 // Compute the remainder using {lhs % msk}. | 1274 // Compute the remainder using {lhs % msk}. |
| 1492 vtrue1 = graph()->NewNode(machine()->Int32Mod(), lhs, rhs, if_true1); | 1275 Node* vtrue1 = __ Int32Mod(lhs, rhs); |
| 1493 | 1276 |
| 1494 // Check if we would have to return -0. | 1277 // Check if we would have to return -0. |
| 1495 Node* check = graph()->NewNode(machine()->Word32Equal(), vtrue1, zero); | 1278 Node* check = __ Word32Equal(vtrue1, zero); |
| 1496 if_true1 = etrue1 = | 1279 __ DeoptimizeIf(DeoptimizeReason::kMinusZero, check, frame_state); |
| 1497 graph()->NewNode(common()->DeoptimizeIf(DeoptimizeReason::kMinusZero), | 1280 __ Goto(&done, vtrue1); |
| 1498 check, frame_state, etrue1, if_true1); | 1281 } |
| 1499 } | 1282 |
| 1500 | 1283 __ Bind(&done); |
| 1501 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); | 1284 return done.PhiAt(0); |
| 1502 Node* efalse1 = effect; | 1285 } |
| 1503 Node* vfalse1; | 1286 |
| 1504 { | 1287 Node* EffectControlLinearizer::LowerCheckedUint32Div(Node* node, |
| 1505 Node* msk = graph()->NewNode(machine()->Int32Sub(), rhs, one); | 1288 Node* frame_state) { |
| 1506 | |
| 1507 // Check if {rhs} minus one is a valid mask. | |
| 1508 Node* check2 = graph()->NewNode( | |
| 1509 machine()->Word32Equal(), | |
| 1510 graph()->NewNode(machine()->Word32And(), rhs, msk), zero); | |
| 1511 Node* branch2 = graph()->NewNode(common()->Branch(), check2, if_false1); | |
| 1512 | |
| 1513 // Compute the remainder using {lhs & msk}. | |
| 1514 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2); | |
| 1515 Node* vtrue2 = graph()->NewNode(machine()->Word32And(), lhs, msk); | |
| 1516 | |
| 1517 // Compute the remainder using the generic {lhs % rhs}. | |
| 1518 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2); | |
| 1519 Node* vfalse2 = | |
| 1520 graph()->NewNode(machine()->Int32Mod(), lhs, rhs, if_false2); | |
| 1521 | |
| 1522 if_false1 = graph()->NewNode(common()->Merge(2), if_true2, if_false2); | |
| 1523 vfalse1 = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2), | |
| 1524 vtrue2, vfalse2, if_false1); | |
| 1525 } | |
| 1526 | |
| 1527 control = graph()->NewNode(common()->Merge(2), if_true1, if_false1); | |
| 1528 effect = graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, control); | |
| 1529 Node* value = | |
| 1530 graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2), vtrue1, | |
| 1531 vfalse1, control); | |
| 1532 | |
| 1533 return ValueEffectControl(value, effect, control); | |
| 1534 } | |
| 1535 | |
| 1536 EffectControlLinearizer::ValueEffectControl | |
| 1537 EffectControlLinearizer::LowerCheckedUint32Div(Node* node, Node* frame_state, | |
| 1538 Node* effect, Node* control) { | |
| 1539 Node* zero = jsgraph()->Int32Constant(0); | |
| 1540 | |
| 1541 Node* lhs = node->InputAt(0); | 1289 Node* lhs = node->InputAt(0); |
| 1542 Node* rhs = node->InputAt(1); | 1290 Node* rhs = node->InputAt(1); |
| 1543 | 1291 |
| 1292 Node* zero = __ Int32Constant(0); |
| 1293 |
| 1544 // Ensure that {rhs} is not zero, otherwise we'd have to return NaN. | 1294 // Ensure that {rhs} is not zero, otherwise we'd have to return NaN. |
| 1545 Node* check = graph()->NewNode(machine()->Word32Equal(), rhs, zero); | 1295 Node* check = __ Word32Equal(rhs, zero); |
| 1546 control = effect = graph()->NewNode( | 1296 __ DeoptimizeIf(DeoptimizeReason::kDivisionByZero, check, frame_state); |
| 1547 common()->DeoptimizeIf(DeoptimizeReason::kDivisionByZero), check, | |
| 1548 frame_state, effect, control); | |
| 1549 | 1297 |
| 1550 // Perform the actual unsigned integer division. | 1298 // Perform the actual unsigned integer division. |
| 1551 Node* value = graph()->NewNode(machine()->Uint32Div(), lhs, rhs, control); | 1299 Node* value = __ Uint32Div(lhs, rhs); |
| 1552 | 1300 |
| 1553 // Check if the remainder is non-zero. | 1301 // Check if the remainder is non-zero. |
| 1554 check = graph()->NewNode(machine()->Word32Equal(), lhs, | 1302 check = __ Word32Equal(lhs, __ Int32Mul(rhs, value)); |
| 1555 graph()->NewNode(machine()->Int32Mul(), rhs, value)); | 1303 __ DeoptimizeUnless(DeoptimizeReason::kLostPrecision, check, frame_state); |
| 1556 control = effect = graph()->NewNode( | 1304 return value; |
| 1557 common()->DeoptimizeUnless(DeoptimizeReason::kLostPrecision), check, | 1305 } |
| 1558 frame_state, effect, control); | 1306 |
| 1559 | 1307 Node* EffectControlLinearizer::LowerCheckedUint32Mod(Node* node, |
| 1560 return ValueEffectControl(value, effect, control); | 1308 Node* frame_state) { |
| 1561 } | |
| 1562 | |
| 1563 EffectControlLinearizer::ValueEffectControl | |
| 1564 EffectControlLinearizer::LowerCheckedUint32Mod(Node* node, Node* frame_state, | |
| 1565 Node* effect, Node* control) { | |
| 1566 Node* zero = jsgraph()->Int32Constant(0); | |
| 1567 | |
| 1568 Node* lhs = node->InputAt(0); | 1309 Node* lhs = node->InputAt(0); |
| 1569 Node* rhs = node->InputAt(1); | 1310 Node* rhs = node->InputAt(1); |
| 1570 | 1311 |
| 1312 Node* zero = __ Int32Constant(0); |
| 1313 |
| 1571 // Ensure that {rhs} is not zero, otherwise we'd have to return NaN. | 1314 // Ensure that {rhs} is not zero, otherwise we'd have to return NaN. |
| 1572 Node* check = graph()->NewNode(machine()->Word32Equal(), rhs, zero); | 1315 Node* check = __ Word32Equal(rhs, zero); |
| 1573 control = effect = graph()->NewNode( | 1316 __ DeoptimizeIf(DeoptimizeReason::kDivisionByZero, check, frame_state); |
| 1574 common()->DeoptimizeIf(DeoptimizeReason::kDivisionByZero), check, | |
| 1575 frame_state, effect, control); | |
| 1576 | 1317 |
| 1577 // Perform the actual unsigned integer modulus. | 1318 // Perform the actual unsigned integer modulus. |
| 1578 Node* value = graph()->NewNode(machine()->Uint32Mod(), lhs, rhs, control); | 1319 return __ Uint32Mod(lhs, rhs); |
| 1579 | 1320 } |
| 1580 return ValueEffectControl(value, effect, control); | 1321 |
| 1581 } | 1322 Node* EffectControlLinearizer::LowerCheckedInt32Mul(Node* node, |
| 1582 | 1323 Node* frame_state) { |
| 1583 EffectControlLinearizer::ValueEffectControl | |
| 1584 EffectControlLinearizer::LowerCheckedInt32Mul(Node* node, Node* frame_state, | |
| 1585 Node* effect, Node* control) { | |
| 1586 CheckForMinusZeroMode mode = CheckMinusZeroModeOf(node->op()); | 1324 CheckForMinusZeroMode mode = CheckMinusZeroModeOf(node->op()); |
| 1587 Node* zero = jsgraph()->Int32Constant(0); | |
| 1588 Node* lhs = node->InputAt(0); | 1325 Node* lhs = node->InputAt(0); |
| 1589 Node* rhs = node->InputAt(1); | 1326 Node* rhs = node->InputAt(1); |
| 1590 | 1327 |
| 1591 Node* projection = | 1328 Node* projection = __ Int32MulWithOverflow(lhs, rhs); |
| 1592 graph()->NewNode(machine()->Int32MulWithOverflow(), lhs, rhs, control); | 1329 Node* check = __ Projection(1, projection); |
| 1593 | 1330 __ DeoptimizeIf(DeoptimizeReason::kOverflow, check, frame_state); |
| 1594 Node* check = graph()->NewNode(common()->Projection(1), projection, control); | 1331 |
| 1595 control = effect = | 1332 Node* value = __ Projection(0, projection); |
| 1596 graph()->NewNode(common()->DeoptimizeIf(DeoptimizeReason::kOverflow), | |
| 1597 check, frame_state, effect, control); | |
| 1598 | |
| 1599 Node* value = graph()->NewNode(common()->Projection(0), projection, control); | |
| 1600 | 1333 |
| 1601 if (mode == CheckForMinusZeroMode::kCheckForMinusZero) { | 1334 if (mode == CheckForMinusZeroMode::kCheckForMinusZero) { |
| 1602 Node* check_zero = graph()->NewNode(machine()->Word32Equal(), value, zero); | 1335 auto if_zero = __ MakeDeferredLabel<1>(); |
| 1603 Node* branch_zero = graph()->NewNode(common()->Branch(BranchHint::kFalse), | 1336 auto check_done = __ MakeLabel<2>(); |
| 1604 check_zero, control); | 1337 Node* zero = __ Int32Constant(0); |
| 1605 | 1338 Node* check_zero = __ Word32Equal(value, zero); |
| 1606 Node* if_zero = graph()->NewNode(common()->IfTrue(), branch_zero); | 1339 __ GotoIf(check_zero, &if_zero); |
| 1607 Node* e_if_zero = effect; | 1340 __ Goto(&check_done); |
| 1608 { | 1341 |
| 1609 // We may need to return negative zero. | 1342 __ Bind(&if_zero); |
| 1610 Node* or_inputs = graph()->NewNode(machine()->Word32Or(), lhs, rhs); | 1343 // We may need to return negative zero. |
| 1611 Node* check_or = | 1344 Node* check_or = __ Int32LessThan(__ Word32Or(lhs, rhs), zero); |
| 1612 graph()->NewNode(machine()->Int32LessThan(), or_inputs, zero); | 1345 __ DeoptimizeIf(DeoptimizeReason::kMinusZero, check_or, frame_state); |
| 1613 if_zero = e_if_zero = | 1346 __ Goto(&check_done); |
| 1614 graph()->NewNode(common()->DeoptimizeIf(DeoptimizeReason::kMinusZero), | 1347 |
| 1615 check_or, frame_state, e_if_zero, if_zero); | 1348 __ Bind(&check_done); |
| 1616 } | 1349 } |
| 1617 | 1350 |
| 1618 Node* if_not_zero = graph()->NewNode(common()->IfFalse(), branch_zero); | 1351 return value; |
| 1619 Node* e_if_not_zero = effect; | 1352 } |
| 1620 | 1353 |
| 1621 control = graph()->NewNode(common()->Merge(2), if_zero, if_not_zero); | 1354 Node* EffectControlLinearizer::LowerCheckedInt32ToTaggedSigned( |
| 1622 effect = graph()->NewNode(common()->EffectPhi(2), e_if_zero, e_if_not_zero, | 1355 Node* node, Node* frame_state) { |
| 1623 control); | |
| 1624 } | |
| 1625 | |
| 1626 return ValueEffectControl(value, effect, control); | |
| 1627 } | |
| 1628 | |
| 1629 EffectControlLinearizer::ValueEffectControl | |
| 1630 EffectControlLinearizer::LowerCheckedInt32ToTaggedSigned(Node* node, | |
| 1631 Node* frame_state, | |
| 1632 Node* effect, | |
| 1633 Node* control) { | |
| 1634 DCHECK(SmiValuesAre31Bits()); | 1356 DCHECK(SmiValuesAre31Bits()); |
| 1635 Node* value = node->InputAt(0); | 1357 Node* value = node->InputAt(0); |
| 1636 | 1358 |
| 1637 Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(), value, value, | 1359 Node* add = __ Int32AddWithOverflow(value, value); |
| 1638 control); | 1360 Node* check = __ Projection(1, add); |
| 1639 | 1361 __ DeoptimizeIf(DeoptimizeReason::kOverflow, check, frame_state); |
| 1640 Node* check = graph()->NewNode(common()->Projection(1), add, control); | 1362 return __ Projection(0, add); |
| 1641 control = effect = | 1363 } |
| 1642 graph()->NewNode(common()->DeoptimizeIf(DeoptimizeReason::kOverflow), | 1364 |
| 1643 check, frame_state, effect, control); | 1365 Node* EffectControlLinearizer::LowerCheckedUint32ToInt32(Node* node, |
| 1644 | 1366 Node* frame_state) { |
| 1645 value = graph()->NewNode(common()->Projection(0), add, control); | 1367 Node* value = node->InputAt(0); |
| 1646 | 1368 Node* max_int = __ Int32Constant(std::numeric_limits<int32_t>::max()); |
| 1647 return ValueEffectControl(value, effect, control); | 1369 Node* is_safe = __ Uint32LessThanOrEqual(value, max_int); |
| 1648 } | 1370 __ DeoptimizeUnless(DeoptimizeReason::kLostPrecision, is_safe, frame_state); |
| 1649 | 1371 return value; |
| 1650 EffectControlLinearizer::ValueEffectControl | 1372 } |
| 1651 EffectControlLinearizer::LowerCheckedUint32ToInt32(Node* node, | 1373 |
| 1652 Node* frame_state, | 1374 Node* EffectControlLinearizer::LowerCheckedUint32ToTaggedSigned( |
| 1653 Node* effect, | 1375 Node* node, Node* frame_state) { |
| 1654 Node* control) { | 1376 Node* value = node->InputAt(0); |
| 1655 Node* value = node->InputAt(0); | 1377 Node* check = __ Uint32LessThanOrEqual(value, SmiMaxValueConstant()); |
| 1656 Node* max_int = jsgraph()->Int32Constant(std::numeric_limits<int32_t>::max()); | 1378 __ DeoptimizeUnless(DeoptimizeReason::kLostPrecision, check, frame_state); |
| 1657 Node* is_safe = | 1379 return ChangeUint32ToSmi(value); |
| 1658 graph()->NewNode(machine()->Uint32LessThanOrEqual(), value, max_int); | 1380 } |
| 1659 control = effect = graph()->NewNode( | 1381 |
| 1660 common()->DeoptimizeUnless(DeoptimizeReason::kLostPrecision), is_safe, | 1382 Node* EffectControlLinearizer::BuildCheckedFloat64ToInt32( |
| 1661 frame_state, effect, control); | 1383 CheckForMinusZeroMode mode, Node* value, Node* frame_state) { |
| 1662 | 1384 Node* value32 = __ RoundFloat64ToInt32(value); |
| 1663 return ValueEffectControl(value, effect, control); | 1385 Node* check_same = __ Float64Equal(value, __ ChangeInt32ToFloat64(value32)); |
| 1664 } | 1386 __ DeoptimizeUnless(DeoptimizeReason::kLostPrecisionOrNaN, check_same, |
| 1665 | 1387 frame_state); |
| 1666 EffectControlLinearizer::ValueEffectControl | |
| 1667 EffectControlLinearizer::LowerCheckedUint32ToTaggedSigned(Node* node, | |
| 1668 Node* frame_state, | |
| 1669 Node* effect, | |
| 1670 Node* control) { | |
| 1671 Node* value = node->InputAt(0); | |
| 1672 Node* check = graph()->NewNode(machine()->Uint32LessThanOrEqual(), value, | |
| 1673 SmiMaxValueConstant()); | |
| 1674 control = effect = graph()->NewNode( | |
| 1675 common()->DeoptimizeUnless(DeoptimizeReason::kLostPrecision), check, | |
| 1676 frame_state, effect, control); | |
| 1677 value = ChangeUint32ToSmi(value); | |
| 1678 | |
| 1679 return ValueEffectControl(value, effect, control); | |
| 1680 } | |
| 1681 | |
| 1682 EffectControlLinearizer::ValueEffectControl | |
| 1683 EffectControlLinearizer::BuildCheckedFloat64ToInt32(CheckForMinusZeroMode mode, | |
| 1684 Node* value, | |
| 1685 Node* frame_state, | |
| 1686 Node* effect, | |
| 1687 Node* control) { | |
| 1688 Node* value32 = graph()->NewNode(machine()->RoundFloat64ToInt32(), value); | |
| 1689 Node* check_same = graph()->NewNode( | |
| 1690 machine()->Float64Equal(), value, | |
| 1691 graph()->NewNode(machine()->ChangeInt32ToFloat64(), value32)); | |
| 1692 control = effect = graph()->NewNode( | |
| 1693 common()->DeoptimizeUnless(DeoptimizeReason::kLostPrecisionOrNaN), | |
| 1694 check_same, frame_state, effect, control); | |
| 1695 | 1388 |
| 1696 if (mode == CheckForMinusZeroMode::kCheckForMinusZero) { | 1389 if (mode == CheckForMinusZeroMode::kCheckForMinusZero) { |
| 1697 // Check if {value} is -0. | 1390 // Check if {value} is -0. |
| 1698 Node* check_zero = graph()->NewNode(machine()->Word32Equal(), value32, | 1391 auto if_zero = __ MakeDeferredLabel<1>(); |
| 1699 jsgraph()->Int32Constant(0)); | 1392 auto check_done = __ MakeLabel<2>(); |
| 1700 Node* branch_zero = graph()->NewNode(common()->Branch(BranchHint::kFalse), | 1393 |
| 1701 check_zero, control); | 1394 Node* check_zero = __ Word32Equal(value32, __ Int32Constant(0)); |
| 1702 | 1395 __ GotoIf(check_zero, &if_zero); |
| 1703 Node* if_zero = graph()->NewNode(common()->IfTrue(), branch_zero); | 1396 __ Goto(&check_done); |
| 1704 Node* if_notzero = graph()->NewNode(common()->IfFalse(), branch_zero); | 1397 |
| 1705 | 1398 __ Bind(&if_zero); |
| 1706 // In case of 0, we need to check the high bits for the IEEE -0 pattern. | 1399 // In case of 0, we need to check the high bits for the IEEE -0 pattern. |
| 1707 Node* check_negative = graph()->NewNode( | 1400 Node* check_negative = __ Int32LessThan(__ Float64ExtractHighWord32(value), |
| 1708 machine()->Int32LessThan(), | 1401 __ Int32Constant(0)); |
| 1709 graph()->NewNode(machine()->Float64ExtractHighWord32(), value), | 1402 __ DeoptimizeIf(DeoptimizeReason::kMinusZero, check_negative, frame_state); |
| 1710 jsgraph()->Int32Constant(0)); | 1403 __ Goto(&check_done); |
| 1711 | 1404 |
| 1712 Node* deopt_minus_zero = | 1405 __ Bind(&check_done); |
| 1713 graph()->NewNode(common()->DeoptimizeIf(DeoptimizeReason::kMinusZero), | 1406 } |
| 1714 check_negative, frame_state, effect, if_zero); | 1407 return value32; |
| 1715 | 1408 } |
| 1716 control = | 1409 |
| 1717 graph()->NewNode(common()->Merge(2), deopt_minus_zero, if_notzero); | 1410 Node* EffectControlLinearizer::LowerCheckedFloat64ToInt32(Node* node, |
| 1718 effect = graph()->NewNode(common()->EffectPhi(2), deopt_minus_zero, effect, | 1411 Node* frame_state) { |
| 1719 control); | |
| 1720 } | |
| 1721 | |
| 1722 return ValueEffectControl(value32, effect, control); | |
| 1723 } | |
| 1724 | |
| 1725 EffectControlLinearizer::ValueEffectControl | |
| 1726 EffectControlLinearizer::LowerCheckedFloat64ToInt32(Node* node, | |
| 1727 Node* frame_state, | |
| 1728 Node* effect, | |
| 1729 Node* control) { | |
| 1730 CheckForMinusZeroMode mode = CheckMinusZeroModeOf(node->op()); | 1412 CheckForMinusZeroMode mode = CheckMinusZeroModeOf(node->op()); |
| 1731 Node* value = node->InputAt(0); | 1413 Node* value = node->InputAt(0); |
| 1732 | 1414 return BuildCheckedFloat64ToInt32(mode, value, frame_state); |
| 1733 return BuildCheckedFloat64ToInt32(mode, value, frame_state, effect, control); | 1415 } |
| 1734 } | 1416 |
| 1735 | 1417 Node* EffectControlLinearizer::LowerCheckedTaggedSignedToInt32( |
| 1736 EffectControlLinearizer::ValueEffectControl | 1418 Node* node, Node* frame_state) { |
| 1737 EffectControlLinearizer::LowerCheckedTaggedSignedToInt32(Node* node, | 1419 Node* value = node->InputAt(0); |
| 1738 Node* frame_state, | 1420 Node* check = ObjectIsSmi(value); |
| 1739 Node* effect, | 1421 __ DeoptimizeUnless(DeoptimizeReason::kNotASmi, check, frame_state); |
| 1740 Node* control) { | 1422 return ChangeSmiToInt32(value); |
| 1741 Node* value = node->InputAt(0); | 1423 } |
| 1742 | 1424 |
| 1743 Node* check = ObjectIsSmi(value); | 1425 Node* EffectControlLinearizer::LowerCheckedTaggedToInt32(Node* node, |
| 1744 control = effect = | 1426 Node* frame_state) { |
| 1745 graph()->NewNode(common()->DeoptimizeUnless(DeoptimizeReason::kNotASmi), | |
| 1746 check, frame_state, effect, control); | |
| 1747 value = ChangeSmiToInt32(value); | |
| 1748 | |
| 1749 return ValueEffectControl(value, effect, control); | |
| 1750 } | |
| 1751 | |
| 1752 EffectControlLinearizer::ValueEffectControl | |
| 1753 EffectControlLinearizer::LowerCheckedTaggedToInt32(Node* node, | |
| 1754 Node* frame_state, | |
| 1755 Node* effect, | |
| 1756 Node* control) { | |
| 1757 CheckForMinusZeroMode mode = CheckMinusZeroModeOf(node->op()); | 1427 CheckForMinusZeroMode mode = CheckMinusZeroModeOf(node->op()); |
| 1758 Node* value = node->InputAt(0); | 1428 Node* value = node->InputAt(0); |
| 1759 | 1429 |
| 1760 Node* check = ObjectIsSmi(value); | 1430 auto if_not_smi = __ MakeDeferredLabel<1>(); |
| 1761 Node* branch = | 1431 auto done = __ MakeLabel<2>(MachineRepresentation::kWord32); |
| 1762 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control); | 1432 |
| 1763 | 1433 Node* check = ObjectIsSmi(value); |
| 1434 __ GotoUnless(check, &if_not_smi); |
| 1764 // In the Smi case, just convert to int32. | 1435 // In the Smi case, just convert to int32. |
| 1765 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); | 1436 __ Goto(&done, ChangeSmiToInt32(value)); |
| 1766 Node* etrue = effect; | |
| 1767 Node* vtrue = ChangeSmiToInt32(value); | |
| 1768 | 1437 |
| 1769 // In the non-Smi case, check the heap numberness, load the number and convert | 1438 // In the non-Smi case, check the heap numberness, load the number and convert |
| 1770 // to int32. | 1439 // to int32. |
| 1771 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); | 1440 __ Bind(&if_not_smi); |
| 1772 Node* efalse = effect; | 1441 Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); |
| 1773 Node* vfalse; | 1442 Node* check_map = __ WordEqual(value_map, __ HeapNumberMapConstant()); |
| 1774 { | 1443 __ DeoptimizeUnless(DeoptimizeReason::kNotAHeapNumber, check_map, |
| 1775 Node* value_map = efalse = | 1444 frame_state); |
| 1776 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), | 1445 Node* vfalse = __ LoadField(AccessBuilder::ForHeapNumberValue(), value); |
| 1777 value, efalse, if_false); | 1446 vfalse = BuildCheckedFloat64ToInt32(mode, vfalse, frame_state); |
| 1778 Node* check = graph()->NewNode(machine()->WordEqual(), value_map, | 1447 __ Goto(&done, vfalse); |
| 1779 jsgraph()->HeapNumberMapConstant()); | 1448 |
| 1780 if_false = efalse = graph()->NewNode( | 1449 __ Bind(&done); |
| 1781 common()->DeoptimizeUnless(DeoptimizeReason::kNotAHeapNumber), check, | 1450 return done.PhiAt(0); |
| 1782 frame_state, efalse, if_false); | 1451 } |
| 1783 vfalse = efalse = graph()->NewNode( | 1452 |
| 1784 simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), value, | 1453 Node* EffectControlLinearizer::BuildCheckedHeapNumberOrOddballToFloat64( |
| 1785 efalse, if_false); | 1454 CheckTaggedInputMode mode, Node* value, Node* frame_state) { |
| 1786 ValueEffectControl state = | 1455 Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); |
| 1787 BuildCheckedFloat64ToInt32(mode, vfalse, frame_state, efalse, if_false); | 1456 Node* check_number = __ WordEqual(value_map, __ HeapNumberMapConstant()); |
| 1788 if_false = state.control; | |
| 1789 efalse = state.effect; | |
| 1790 vfalse = state.value; | |
| 1791 } | |
| 1792 | |
| 1793 control = graph()->NewNode(common()->Merge(2), if_true, if_false); | |
| 1794 effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control); | |
| 1795 value = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2), | |
| 1796 vtrue, vfalse, control); | |
| 1797 | |
| 1798 return ValueEffectControl(value, effect, control); | |
| 1799 } | |
| 1800 | |
| 1801 EffectControlLinearizer::ValueEffectControl | |
| 1802 EffectControlLinearizer::BuildCheckedHeapNumberOrOddballToFloat64( | |
| 1803 CheckTaggedInputMode mode, Node* value, Node* frame_state, Node* effect, | |
| 1804 Node* control) { | |
| 1805 Node* value_map = effect = graph()->NewNode( | |
| 1806 simplified()->LoadField(AccessBuilder::ForMap()), value, effect, control); | |
| 1807 | |
| 1808 Node* check_number = graph()->NewNode(machine()->WordEqual(), value_map, | |
| 1809 jsgraph()->HeapNumberMapConstant()); | |
| 1810 | |
| 1811 switch (mode) { | 1457 switch (mode) { |
| 1812 case CheckTaggedInputMode::kNumber: { | 1458 case CheckTaggedInputMode::kNumber: { |
| 1813 control = effect = graph()->NewNode( | 1459 __ DeoptimizeUnless(DeoptimizeReason::kNotAHeapNumber, check_number, |
| 1814 common()->DeoptimizeUnless(DeoptimizeReason::kNotAHeapNumber), | 1460 frame_state); |
| 1815 check_number, frame_state, effect, control); | |
| 1816 break; | 1461 break; |
| 1817 } | 1462 } |
| 1818 case CheckTaggedInputMode::kNumberOrOddball: { | 1463 case CheckTaggedInputMode::kNumberOrOddball: { |
| 1819 Node* branch = | 1464 auto check_done = __ MakeLabel<2>(); |
| 1820 graph()->NewNode(common()->Branch(), check_number, control); | 1465 |
| 1821 | 1466 __ GotoIf(check_number, &check_done); |
| 1822 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); | |
| 1823 Node* etrue = effect; | |
| 1824 | |
| 1825 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); | |
| 1826 // For oddballs also contain the numeric value, let us just check that | 1467 // For oddballs also contain the numeric value, let us just check that |
| 1827 // we have an oddball here. | 1468 // we have an oddball here. |
| 1828 Node* efalse = effect; | 1469 Node* instance_type = |
| 1829 Node* instance_type = efalse = graph()->NewNode( | 1470 __ LoadField(AccessBuilder::ForMapInstanceType(), value_map); |
| 1830 simplified()->LoadField(AccessBuilder::ForMapInstanceType()), | |
| 1831 value_map, efalse, if_false); | |
| 1832 Node* check_oddball = | 1471 Node* check_oddball = |
| 1833 graph()->NewNode(machine()->Word32Equal(), instance_type, | 1472 __ Word32Equal(instance_type, __ Int32Constant(ODDBALL_TYPE)); |
| 1834 jsgraph()->Int32Constant(ODDBALL_TYPE)); | 1473 __ DeoptimizeUnless(DeoptimizeReason::kNotANumberOrOddball, check_oddball, |
| 1835 if_false = efalse = graph()->NewNode( | 1474 frame_state); |
| 1836 common()->DeoptimizeUnless(DeoptimizeReason::kNotANumberOrOddball), | |
| 1837 check_oddball, frame_state, efalse, if_false); | |
| 1838 STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset); | 1475 STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset); |
| 1839 | 1476 __ Goto(&check_done); |
| 1840 control = graph()->NewNode(common()->Merge(2), if_true, if_false); | 1477 |
| 1841 effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control); | 1478 __ Bind(&check_done); |
| 1842 break; | 1479 break; |
| 1843 } | 1480 } |
| 1844 } | 1481 } |
| 1845 | 1482 return __ LoadField(AccessBuilder::ForHeapNumberValue(), value); |
| 1846 value = effect = graph()->NewNode( | 1483 } |
| 1847 simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), value, | 1484 |
| 1848 effect, control); | 1485 Node* EffectControlLinearizer::LowerCheckedTaggedToFloat64(Node* node, |
| 1849 return ValueEffectControl(value, effect, control); | 1486 Node* frame_state) { |
| 1850 } | |
| 1851 | |
| 1852 EffectControlLinearizer::ValueEffectControl | |
| 1853 EffectControlLinearizer::LowerCheckedTaggedToFloat64(Node* node, | |
| 1854 Node* frame_state, | |
| 1855 Node* effect, | |
| 1856 Node* control) { | |
| 1857 CheckTaggedInputMode mode = CheckTaggedInputModeOf(node->op()); | 1487 CheckTaggedInputMode mode = CheckTaggedInputModeOf(node->op()); |
| 1858 Node* value = node->InputAt(0); | 1488 Node* value = node->InputAt(0); |
| 1859 | 1489 |
| 1860 Node* check = ObjectIsSmi(value); | 1490 auto if_smi = __ MakeLabel<1>(); |
| 1861 Node* branch = graph()->NewNode(common()->Branch(), check, control); | 1491 auto done = __ MakeLabel<2>(MachineRepresentation::kFloat64); |
| 1492 |
| 1493 Node* check = ObjectIsSmi(value); |
| 1494 __ GotoIf(check, &if_smi); |
| 1862 | 1495 |
| 1863 // In the Smi case, just convert to int32 and then float64. | 1496 // In the Smi case, just convert to int32 and then float64. |
| 1864 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); | |
| 1865 Node* etrue = effect; | |
| 1866 Node* vtrue = ChangeSmiToInt32(value); | |
| 1867 vtrue = graph()->NewNode(machine()->ChangeInt32ToFloat64(), vtrue); | |
| 1868 | |
| 1869 // Otherwise, check heap numberness and load the number. | 1497 // Otherwise, check heap numberness and load the number. |
| 1870 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); | 1498 Node* number = |
| 1871 ValueEffectControl number_state = BuildCheckedHeapNumberOrOddballToFloat64( | 1499 BuildCheckedHeapNumberOrOddballToFloat64(mode, value, frame_state); |
| 1872 mode, value, frame_state, effect, if_false); | 1500 __ Goto(&done, number); |
| 1873 | 1501 |
| 1874 Node* merge = | 1502 __ Bind(&if_smi); |
| 1875 graph()->NewNode(common()->Merge(2), if_true, number_state.control); | 1503 Node* from_smi = ChangeSmiToInt32(value); |
| 1876 Node* effect_phi = graph()->NewNode(common()->EffectPhi(2), etrue, | 1504 from_smi = __ ChangeInt32ToFloat64(from_smi); |
| 1877 number_state.effect, merge); | 1505 __ Goto(&done, from_smi); |
| 1878 Node* result = | 1506 |
| 1879 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2), vtrue, | 1507 __ Bind(&done); |
| 1880 number_state.value, merge); | 1508 return done.PhiAt(0); |
| 1881 | 1509 } |
| 1882 return ValueEffectControl(result, effect_phi, merge); | 1510 |
| 1883 } | 1511 Node* EffectControlLinearizer::LowerCheckedTaggedToTaggedSigned( |
| 1884 | 1512 Node* node, Node* frame_state) { |
| 1885 EffectControlLinearizer::ValueEffectControl | 1513 Node* value = node->InputAt(0); |
| 1886 EffectControlLinearizer::LowerCheckedTaggedToTaggedSigned(Node* node, | 1514 |
| 1887 Node* frame_state, | 1515 Node* check = ObjectIsSmi(value); |
| 1888 Node* effect, | 1516 __ DeoptimizeUnless(DeoptimizeReason::kNotASmi, check, frame_state); |
| 1889 Node* control) { | 1517 |
| 1890 Node* value = node->InputAt(0); | 1518 return value; |
| 1891 | 1519 } |
| 1892 Node* check = ObjectIsSmi(value); | 1520 |
| 1893 control = effect = | 1521 Node* EffectControlLinearizer::LowerCheckedTaggedToTaggedPointer( |
| 1894 graph()->NewNode(common()->DeoptimizeUnless(DeoptimizeReason::kNotASmi), | 1522 Node* node, Node* frame_state) { |
| 1895 check, frame_state, effect, control); | 1523 Node* value = node->InputAt(0); |
| 1896 | 1524 |
| 1897 return ValueEffectControl(value, effect, control); | 1525 Node* check = ObjectIsSmi(value); |
| 1898 } | 1526 __ DeoptimizeIf(DeoptimizeReason::kSmi, check, frame_state); |
| 1899 | 1527 return value; |
| 1900 EffectControlLinearizer::ValueEffectControl | 1528 } |
| 1901 EffectControlLinearizer::LowerCheckedTaggedToTaggedPointer(Node* node, | 1529 |
| 1902 Node* frame_state, | 1530 Node* EffectControlLinearizer::LowerTruncateTaggedToWord32(Node* node) { |
| 1903 Node* effect, | 1531 Node* value = node->InputAt(0); |
| 1904 Node* control) { | 1532 |
| 1905 Node* value = node->InputAt(0); | 1533 auto if_not_smi = __ MakeDeferredLabel<1>(); |
| 1906 | 1534 auto done = __ MakeLabel<2>(MachineRepresentation::kWord32); |
| 1907 Node* check = ObjectIsSmi(value); | 1535 |
| 1908 control = effect = | 1536 Node* check = ObjectIsSmi(value); |
| 1909 graph()->NewNode(common()->DeoptimizeIf(DeoptimizeReason::kSmi), check, | 1537 __ GotoUnless(check, &if_not_smi); |
| 1910 frame_state, effect, control); | 1538 __ Goto(&done, ChangeSmiToInt32(value)); |
| 1911 | 1539 |
| 1912 return ValueEffectControl(value, effect, control); | 1540 __ Bind(&if_not_smi); |
| 1913 } | 1541 STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset); |
| 1914 | 1542 Node* vfalse = __ LoadField(AccessBuilder::ForHeapNumberValue(), value); |
| 1915 EffectControlLinearizer::ValueEffectControl | 1543 vfalse = __ TruncateFloat64ToWord32(vfalse); |
| 1916 EffectControlLinearizer::LowerTruncateTaggedToWord32(Node* node, Node* effect, | 1544 __ Goto(&done, vfalse); |
| 1917 Node* control) { | 1545 |
| 1918 Node* value = node->InputAt(0); | 1546 __ Bind(&done); |
| 1919 | 1547 return done.PhiAt(0); |
| 1920 Node* check = ObjectIsSmi(value); | 1548 } |
| 1921 Node* branch = | 1549 |
| 1922 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control); | 1550 Node* EffectControlLinearizer::LowerCheckedTruncateTaggedToWord32( |
| 1923 | 1551 Node* node, Node* frame_state) { |
| 1924 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); | 1552 Node* value = node->InputAt(0); |
| 1925 Node* etrue = effect; | 1553 |
| 1926 Node* vtrue = ChangeSmiToInt32(value); | 1554 auto if_not_smi = __ MakeLabel<1>(); |
| 1927 | 1555 auto done = __ MakeLabel<2>(MachineRepresentation::kWord32); |
| 1928 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); | 1556 |
| 1929 Node* efalse = effect; | 1557 Node* check = ObjectIsSmi(value); |
| 1930 Node* vfalse; | 1558 __ GotoUnless(check, &if_not_smi); |
| 1931 { | |
| 1932 STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset); | |
| 1933 vfalse = efalse = graph()->NewNode( | |
| 1934 simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), value, | |
| 1935 efalse, if_false); | |
| 1936 vfalse = graph()->NewNode(machine()->TruncateFloat64ToWord32(), vfalse); | |
| 1937 } | |
| 1938 | |
| 1939 control = graph()->NewNode(common()->Merge(2), if_true, if_false); | |
| 1940 effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control); | |
| 1941 value = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2), | |
| 1942 vtrue, vfalse, control); | |
| 1943 | |
| 1944 return ValueEffectControl(value, effect, control); | |
| 1945 } | |
| 1946 | |
| 1947 EffectControlLinearizer::ValueEffectControl | |
| 1948 EffectControlLinearizer::LowerCheckedTruncateTaggedToWord32(Node* node, | |
| 1949 Node* frame_state, | |
| 1950 Node* effect, | |
| 1951 Node* control) { | |
| 1952 Node* value = node->InputAt(0); | |
| 1953 | |
| 1954 Node* check = ObjectIsSmi(value); | |
| 1955 Node* branch = | |
| 1956 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control); | |
| 1957 | |
| 1958 // In the Smi case, just convert to int32. | 1559 // In the Smi case, just convert to int32. |
| 1959 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); | 1560 __ Goto(&done, ChangeSmiToInt32(value)); |
| 1960 Node* etrue = effect; | |
| 1961 Node* vtrue = ChangeSmiToInt32(value); | |
| 1962 | 1561 |
| 1963 // Otherwise, check that it's a heap number or oddball and truncate the value | 1562 // Otherwise, check that it's a heap number or oddball and truncate the value |
| 1964 // to int32. | 1563 // to int32. |
| 1965 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); | 1564 __ Bind(&if_not_smi); |
| 1966 ValueEffectControl false_state = BuildCheckedHeapNumberOrOddballToFloat64( | 1565 Node* number = BuildCheckedHeapNumberOrOddballToFloat64( |
| 1967 CheckTaggedInputMode::kNumberOrOddball, value, frame_state, effect, | 1566 CheckTaggedInputMode::kNumberOrOddball, value, frame_state); |
| 1968 if_false); | 1567 number = __ TruncateFloat64ToWord32(number); |
| 1969 false_state.value = | 1568 __ Goto(&done, number); |
| 1970 graph()->NewNode(machine()->TruncateFloat64ToWord32(), false_state.value); | 1569 |
| 1971 | 1570 __ Bind(&done); |
| 1972 Node* merge = | 1571 return done.PhiAt(0); |
| 1973 graph()->NewNode(common()->Merge(2), if_true, false_state.control); | 1572 } |
| 1974 Node* effect_phi = graph()->NewNode(common()->EffectPhi(2), etrue, | 1573 |
| 1975 false_state.effect, merge); | 1574 Node* EffectControlLinearizer::LowerObjectIsCallable(Node* node) { |
| 1976 Node* result = | 1575 Node* value = node->InputAt(0); |
| 1977 graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2), vtrue, | 1576 |
| 1978 false_state.value, merge); | 1577 auto if_smi = __ MakeDeferredLabel<1>(); |
| 1979 | 1578 auto done = __ MakeLabel<2>(MachineRepresentation::kBit); |
| 1980 return ValueEffectControl(result, effect_phi, merge); | 1579 |
| 1981 } | 1580 Node* check = ObjectIsSmi(value); |
| 1982 | 1581 __ GotoIf(check, &if_smi); |
| 1983 EffectControlLinearizer::ValueEffectControl | 1582 |
| 1984 EffectControlLinearizer::LowerObjectIsCallable(Node* node, Node* effect, | 1583 Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); |
| 1985 Node* control) { | 1584 Node* value_bit_field = |
| 1986 Node* value = node->InputAt(0); | 1585 __ LoadField(AccessBuilder::ForMapBitField(), value_map); |
| 1987 | 1586 Node* vfalse = __ Word32Equal( |
| 1988 Node* check = ObjectIsSmi(value); | 1587 __ Int32Constant(1 << Map::kIsCallable), |
| 1989 Node* branch = | 1588 __ Word32And(value_bit_field, |
| 1990 graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control); | 1589 __ Int32Constant((1 << Map::kIsCallable) | |
| 1991 | 1590 (1 << Map::kIsUndetectable)))); |
| 1992 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); | 1591 __ Goto(&done, vfalse); |
| 1993 Node* etrue = effect; | 1592 |
| 1994 Node* vtrue = jsgraph()->Int32Constant(0); | 1593 __ Bind(&if_smi); |
| 1995 | 1594 __ Goto(&done, __ Int32Constant(0)); |
| 1996 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); | 1595 |
| 1997 Node* efalse = effect; | 1596 __ Bind(&done); |
| 1998 Node* vfalse; | 1597 return done.PhiAt(0); |
| 1999 { | 1598 } |
| 2000 Node* value_map = efalse = | 1599 |
| 2001 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), | 1600 Node* EffectControlLinearizer::LowerObjectIsNumber(Node* node) { |
| 2002 value, efalse, if_false); | 1601 Node* value = node->InputAt(0); |
| 2003 Node* value_bit_field = efalse = graph()->NewNode( | 1602 |
| 2004 simplified()->LoadField(AccessBuilder::ForMapBitField()), value_map, | 1603 auto if_smi = __ MakeLabel<1>(); |
| 2005 efalse, if_false); | 1604 auto done = __ MakeLabel<2>(MachineRepresentation::kBit); |
| 2006 vfalse = graph()->NewNode( | 1605 |
| 2007 machine()->Word32Equal(), | 1606 __ GotoIf(ObjectIsSmi(value), &if_smi); |
| 2008 jsgraph()->Int32Constant(1 << Map::kIsCallable), | 1607 Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); |
| 2009 graph()->NewNode( | 1608 __ Goto(&done, __ WordEqual(value_map, __ HeapNumberMapConstant())); |
| 2010 machine()->Word32And(), value_bit_field, | 1609 |
| 2011 jsgraph()->Int32Constant((1 << Map::kIsCallable) | | 1610 __ Bind(&if_smi); |
| 2012 (1 << Map::kIsUndetectable)))); | 1611 __ Goto(&done, __ Int32Constant(1)); |
| 2013 } | 1612 |
| 2014 | 1613 __ Bind(&done); |
| 2015 control = graph()->NewNode(common()->Merge(2), if_true, if_false); | 1614 return done.PhiAt(0); |
| 2016 effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control); | 1615 } |
| 2017 value = graph()->NewNode(common()->Phi(MachineRepresentation::kBit, 2), vtrue, | 1616 |
| 2018 vfalse, control); | 1617 Node* EffectControlLinearizer::LowerObjectIsReceiver(Node* node) { |
| 2019 | 1618 Node* value = node->InputAt(0); |
| 2020 return ValueEffectControl(value, effect, control); | 1619 |
| 2021 } | 1620 auto if_smi = __ MakeDeferredLabel<1>(); |
| 2022 | 1621 auto done = __ MakeLabel<2>(MachineRepresentation::kBit); |
| 2023 EffectControlLinearizer::ValueEffectControl | 1622 |
| 2024 EffectControlLinearizer::LowerObjectIsNumber(Node* node, Node* effect, | 1623 __ GotoIf(ObjectIsSmi(value), &if_smi); |
| 2025 Node* control) { | 1624 |
| 2026 Node* value = node->InputAt(0); | 1625 STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE); |
| 2027 | 1626 Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); |
| 2028 Node* check = ObjectIsSmi(value); | 1627 Node* value_instance_type = |
| 2029 Node* branch = graph()->NewNode(common()->Branch(), check, control); | 1628 __ LoadField(AccessBuilder::ForMapInstanceType(), value_map); |
| 2030 | 1629 Node* result = __ Uint32LessThanOrEqual( |
| 2031 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); | 1630 __ Uint32Constant(FIRST_JS_RECEIVER_TYPE), value_instance_type); |
| 2032 Node* etrue = effect; | 1631 __ Goto(&done, result); |
| 2033 Node* vtrue = jsgraph()->Int32Constant(1); | 1632 |
| 2034 | 1633 __ Bind(&if_smi); |
| 2035 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); | 1634 __ Goto(&done, __ Int32Constant(0)); |
| 2036 Node* efalse = effect; | 1635 |
| 2037 Node* vfalse; | 1636 __ Bind(&done); |
| 2038 { | 1637 return done.PhiAt(0); |
| 2039 Node* value_map = efalse = | 1638 } |
| 2040 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), | 1639 |
| 2041 value, efalse, if_false); | 1640 Node* EffectControlLinearizer::LowerObjectIsSmi(Node* node) { |
| 2042 vfalse = graph()->NewNode(machine()->WordEqual(), value_map, | 1641 Node* value = node->InputAt(0); |
| 2043 jsgraph()->HeapNumberMapConstant()); | 1642 return ObjectIsSmi(value); |
| 2044 } | 1643 } |
| 2045 | 1644 |
| 2046 control = graph()->NewNode(common()->Merge(2), if_true, if_false); | 1645 Node* EffectControlLinearizer::LowerObjectIsString(Node* node) { |
| 2047 effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control); | 1646 Node* value = node->InputAt(0); |
| 2048 value = graph()->NewNode(common()->Phi(MachineRepresentation::kBit, 2), vtrue, | 1647 |
| 2049 vfalse, control); | 1648 auto if_smi = __ MakeDeferredLabel<1>(); |
| 2050 | 1649 auto done = __ MakeLabel<2>(MachineRepresentation::kBit); |
| 2051 return ValueEffectControl(value, effect, control); | 1650 |
| 2052 } | 1651 Node* check = ObjectIsSmi(value); |
| 2053 | 1652 __ GotoIf(check, &if_smi); |
| 2054 EffectControlLinearizer::ValueEffectControl | 1653 Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); |
| 2055 EffectControlLinearizer::LowerObjectIsReceiver(Node* node, Node* effect, | 1654 Node* value_instance_type = |
| 2056 Node* control) { | 1655 __ LoadField(AccessBuilder::ForMapInstanceType(), value_map); |
| 2057 Node* value = node->InputAt(0); | 1656 Node* vfalse = __ Uint32LessThan(value_instance_type, |
| 2058 | 1657 __ Uint32Constant(FIRST_NONSTRING_TYPE)); |
| 2059 Node* check = ObjectIsSmi(value); | 1658 __ Goto(&done, vfalse); |
| 2060 Node* branch = | 1659 |
| 2061 graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control); | 1660 __ Bind(&if_smi); |
| 2062 | 1661 __ Goto(&done, __ Int32Constant(0)); |
| 2063 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); | 1662 |
| 2064 Node* etrue = effect; | 1663 __ Bind(&done); |
| 2065 Node* vtrue = jsgraph()->Int32Constant(0); | 1664 return done.PhiAt(0); |
| 2066 | 1665 } |
| 2067 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); | 1666 |
| 2068 Node* efalse = effect; | 1667 Node* EffectControlLinearizer::LowerObjectIsUndetectable(Node* node) { |
| 2069 Node* vfalse; | 1668 Node* value = node->InputAt(0); |
| 2070 { | 1669 |
| 2071 STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE); | 1670 auto if_smi = __ MakeDeferredLabel<1>(); |
| 2072 Node* value_map = efalse = | 1671 auto done = __ MakeLabel<2>(MachineRepresentation::kBit); |
| 2073 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), | 1672 |
| 2074 value, efalse, if_false); | 1673 Node* check = ObjectIsSmi(value); |
| 2075 Node* value_instance_type = efalse = graph()->NewNode( | 1674 __ GotoIf(check, &if_smi); |
| 2076 simplified()->LoadField(AccessBuilder::ForMapInstanceType()), value_map, | 1675 |
| 2077 efalse, if_false); | 1676 Node* value_map = __ LoadField(AccessBuilder::ForMap(), value); |
| 2078 vfalse = graph()->NewNode(machine()->Uint32LessThanOrEqual(), | 1677 Node* value_bit_field = |
| 2079 jsgraph()->Uint32Constant(FIRST_JS_RECEIVER_TYPE), | 1678 __ LoadField(AccessBuilder::ForMapBitField(), value_map); |
| 2080 value_instance_type); | 1679 Node* vfalse = __ Word32Equal( |
| 2081 } | 1680 __ Word32Equal(__ Int32Constant(0), |
| 2082 | 1681 __ Word32And(value_bit_field, |
| 2083 control = graph()->NewNode(common()->Merge(2), if_true, if_false); | 1682 __ Int32Constant(1 << Map::kIsUndetectable))), |
| 2084 effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control); | 1683 __ Int32Constant(0)); |
| 2085 value = graph()->NewNode(common()->Phi(MachineRepresentation::kBit, 2), vtrue, | 1684 __ Goto(&done, vfalse); |
| 2086 vfalse, control); | 1685 |
| 2087 | 1686 __ Bind(&if_smi); |
| 2088 return ValueEffectControl(value, effect, control); | 1687 __ Goto(&done, __ Int32Constant(0)); |
| 2089 } | 1688 |
| 2090 | 1689 __ Bind(&done); |
| 2091 EffectControlLinearizer::ValueEffectControl | 1690 return done.PhiAt(0); |
| 2092 EffectControlLinearizer::LowerObjectIsSmi(Node* node, Node* effect, | 1691 } |
| 2093 Node* control) { | 1692 |
| 2094 Node* value = node->InputAt(0); | 1693 Node* EffectControlLinearizer::LowerNewRestParameterElements(Node* node) { |
| 2095 value = ObjectIsSmi(value); | |
| 2096 return ValueEffectControl(value, effect, control); | |
| 2097 } | |
| 2098 | |
| 2099 EffectControlLinearizer::ValueEffectControl | |
| 2100 EffectControlLinearizer::LowerObjectIsString(Node* node, Node* effect, | |
| 2101 Node* control) { | |
| 2102 Node* value = node->InputAt(0); | |
| 2103 | |
| 2104 Node* check = ObjectIsSmi(value); | |
| 2105 Node* branch = | |
| 2106 graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control); | |
| 2107 | |
| 2108 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); | |
| 2109 Node* etrue = effect; | |
| 2110 Node* vtrue = jsgraph()->Int32Constant(0); | |
| 2111 | |
| 2112 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); | |
| 2113 Node* efalse = effect; | |
| 2114 Node* vfalse; | |
| 2115 { | |
| 2116 Node* value_map = efalse = | |
| 2117 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), | |
| 2118 value, efalse, if_false); | |
| 2119 Node* value_instance_type = efalse = graph()->NewNode( | |
| 2120 simplified()->LoadField(AccessBuilder::ForMapInstanceType()), value_map, | |
| 2121 efalse, if_false); | |
| 2122 vfalse = graph()->NewNode(machine()->Uint32LessThan(), value_instance_type, | |
| 2123 jsgraph()->Uint32Constant(FIRST_NONSTRING_TYPE)); | |
| 2124 } | |
| 2125 | |
| 2126 control = graph()->NewNode(common()->Merge(2), if_true, if_false); | |
| 2127 effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control); | |
| 2128 value = graph()->NewNode(common()->Phi(MachineRepresentation::kBit, 2), vtrue, | |
| 2129 vfalse, control); | |
| 2130 | |
| 2131 return ValueEffectControl(value, effect, control); | |
| 2132 } | |
| 2133 | |
| 2134 EffectControlLinearizer::ValueEffectControl | |
| 2135 EffectControlLinearizer::LowerObjectIsUndetectable(Node* node, Node* effect, | |
| 2136 Node* control) { | |
| 2137 Node* value = node->InputAt(0); | |
| 2138 | |
| 2139 Node* check = ObjectIsSmi(value); | |
| 2140 Node* branch = | |
| 2141 graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control); | |
| 2142 | |
| 2143 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); | |
| 2144 Node* etrue = effect; | |
| 2145 Node* vtrue = jsgraph()->Int32Constant(0); | |
| 2146 | |
| 2147 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); | |
| 2148 Node* efalse = effect; | |
| 2149 Node* vfalse; | |
| 2150 { | |
| 2151 Node* value_map = efalse = | |
| 2152 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), | |
| 2153 value, efalse, if_false); | |
| 2154 Node* value_bit_field = efalse = graph()->NewNode( | |
| 2155 simplified()->LoadField(AccessBuilder::ForMapBitField()), value_map, | |
| 2156 efalse, if_false); | |
| 2157 vfalse = graph()->NewNode( | |
| 2158 machine()->Word32Equal(), | |
| 2159 graph()->NewNode( | |
| 2160 machine()->Word32Equal(), jsgraph()->Int32Constant(0), | |
| 2161 graph()->NewNode( | |
| 2162 machine()->Word32And(), value_bit_field, | |
| 2163 jsgraph()->Int32Constant(1 << Map::kIsUndetectable))), | |
| 2164 jsgraph()->Int32Constant(0)); | |
| 2165 } | |
| 2166 | |
| 2167 control = graph()->NewNode(common()->Merge(2), if_true, if_false); | |
| 2168 effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control); | |
| 2169 value = graph()->NewNode(common()->Phi(MachineRepresentation::kBit, 2), vtrue, | |
| 2170 vfalse, control); | |
| 2171 | |
| 2172 return ValueEffectControl(value, effect, control); | |
| 2173 } | |
| 2174 | |
| 2175 EffectControlLinearizer::ValueEffectControl | |
| 2176 EffectControlLinearizer::LowerNewRestParameterElements(Node* node, Node* effect, | |
| 2177 Node* control) { | |
| 2178 int const formal_parameter_count = ParameterCountOf(node->op()); | 1694 int const formal_parameter_count = ParameterCountOf(node->op()); |
| 2179 | 1695 |
| 2180 Callable const callable = CodeFactory::NewRestParameterElements(isolate()); | 1696 Callable const callable = CodeFactory::NewRestParameterElements(isolate()); |
| 2181 Operator::Properties const properties = node->op()->properties(); | 1697 Operator::Properties const properties = node->op()->properties(); |
| 2182 CallDescriptor::Flags const flags = CallDescriptor::kNoFlags; | 1698 CallDescriptor::Flags const flags = CallDescriptor::kNoFlags; |
| 2183 CallDescriptor* desc = Linkage::GetStubCallDescriptor( | 1699 CallDescriptor* desc = Linkage::GetStubCallDescriptor( |
| 2184 isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties); | 1700 isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties); |
| 2185 Node* value = effect = graph()->NewNode( | 1701 return __ Call(desc, __ HeapConstant(callable.code()), |
| 2186 common()->Call(desc), jsgraph()->HeapConstant(callable.code()), | 1702 __ IntPtrConstant(formal_parameter_count), |
| 2187 jsgraph()->IntPtrConstant(formal_parameter_count), | 1703 __ NoContextConstant()); |
| 2188 jsgraph()->NoContextConstant(), effect); | |
| 2189 return ValueEffectControl(value, effect, control); | |
| 2190 } | 1704 } |
| 2191 | 1705 |
| 2192 EffectControlLinearizer::ValueEffectControl | 1706 Node* EffectControlLinearizer::LowerNewUnmappedArgumentsElements(Node* node) { |
| 2193 EffectControlLinearizer::LowerNewUnmappedArgumentsElements(Node* node, | |
| 2194 Node* effect, | |
| 2195 Node* control) { | |
| 2196 int const formal_parameter_count = ParameterCountOf(node->op()); | 1707 int const formal_parameter_count = ParameterCountOf(node->op()); |
| 2197 | 1708 |
| 2198 Callable const callable = | 1709 Callable const callable = |
| 2199 CodeFactory::NewUnmappedArgumentsElements(isolate()); | 1710 CodeFactory::NewUnmappedArgumentsElements(isolate()); |
| 2200 Operator::Properties const properties = node->op()->properties(); | 1711 Operator::Properties const properties = node->op()->properties(); |
| 2201 CallDescriptor::Flags const flags = CallDescriptor::kNoFlags; | 1712 CallDescriptor::Flags const flags = CallDescriptor::kNoFlags; |
| 2202 CallDescriptor* desc = Linkage::GetStubCallDescriptor( | 1713 CallDescriptor* desc = Linkage::GetStubCallDescriptor( |
| 2203 isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties); | 1714 isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties); |
| 2204 Node* value = effect = graph()->NewNode( | 1715 return __ Call(desc, __ HeapConstant(callable.code()), |
| 2205 common()->Call(desc), jsgraph()->HeapConstant(callable.code()), | 1716 __ IntPtrConstant(formal_parameter_count), |
| 2206 jsgraph()->IntPtrConstant(formal_parameter_count), | 1717 __ NoContextConstant()); |
| 2207 jsgraph()->NoContextConstant(), effect); | |
| 2208 return ValueEffectControl(value, effect, control); | |
| 2209 } | 1718 } |
| 2210 | 1719 |
| 2211 EffectControlLinearizer::ValueEffectControl | 1720 Node* EffectControlLinearizer::LowerArrayBufferWasNeutered(Node* node) { |
| 2212 EffectControlLinearizer::LowerArrayBufferWasNeutered(Node* node, Node* effect, | |
| 2213 Node* control) { | |
| 2214 Node* value = node->InputAt(0); | 1721 Node* value = node->InputAt(0); |
| 2215 | 1722 |
| 2216 Node* value_bit_field = effect = graph()->NewNode( | 1723 Node* value_bit_field = |
| 2217 simplified()->LoadField(AccessBuilder::ForJSArrayBufferBitField()), value, | 1724 __ LoadField(AccessBuilder::ForJSArrayBufferBitField(), value); |
| 2218 effect, control); | 1725 return __ Word32Equal( |
| 2219 value = graph()->NewNode( | 1726 __ Word32Equal( |
| 2220 machine()->Word32Equal(), | 1727 __ Word32And(value_bit_field, |
| 2221 graph()->NewNode(machine()->Word32Equal(), | 1728 __ Int32Constant(JSArrayBuffer::WasNeutered::kMask)), |
| 2222 graph()->NewNode(machine()->Word32And(), value_bit_field, | 1729 __ Int32Constant(0)), |
| 2223 jsgraph()->Int32Constant( | 1730 __ Int32Constant(0)); |
| 2224 JSArrayBuffer::WasNeutered::kMask)), | |
| 2225 jsgraph()->Int32Constant(0)), | |
| 2226 jsgraph()->Int32Constant(0)); | |
| 2227 | |
| 2228 return ValueEffectControl(value, effect, control); | |
| 2229 } | 1731 } |
| 2230 | 1732 |
| 2231 EffectControlLinearizer::ValueEffectControl | 1733 Node* EffectControlLinearizer::LowerStringCharAt(Node* node) { |
| 2232 EffectControlLinearizer::LowerStringCharAt(Node* node, Node* effect, | 1734 Node* receiver = node->InputAt(0); |
| 2233 Node* control) { | 1735 Node* position = node->InputAt(1); |
| 1736 |
| 2234 Callable const callable = CodeFactory::StringCharAt(isolate()); | 1737 Callable const callable = CodeFactory::StringCharAt(isolate()); |
| 2235 Operator::Properties properties = Operator::kNoThrow | Operator::kNoWrite; | 1738 Operator::Properties properties = Operator::kNoThrow | Operator::kNoWrite; |
| 2236 CallDescriptor::Flags flags = CallDescriptor::kNoFlags; | 1739 CallDescriptor::Flags flags = CallDescriptor::kNoFlags; |
| 2237 CallDescriptor* desc = Linkage::GetStubCallDescriptor( | 1740 CallDescriptor* desc = Linkage::GetStubCallDescriptor( |
| 2238 isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties); | 1741 isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties); |
| 2239 node->InsertInput(graph()->zone(), 0, | 1742 return __ Call(desc, __ HeapConstant(callable.code()), receiver, position, |
| 2240 jsgraph()->HeapConstant(callable.code())); | 1743 __ NoContextConstant()); |
| 2241 node->InsertInput(graph()->zone(), 3, jsgraph()->NoContextConstant()); | |
| 2242 node->InsertInput(graph()->zone(), 4, effect); | |
| 2243 NodeProperties::ChangeOp(node, common()->Call(desc)); | |
| 2244 return ValueEffectControl(node, node, control); | |
| 2245 } | 1744 } |
| 2246 | 1745 |
| 2247 EffectControlLinearizer::ValueEffectControl | 1746 Node* EffectControlLinearizer::LowerStringCharCodeAt(Node* node) { |
| 2248 EffectControlLinearizer::LowerStringCharCodeAt(Node* node, Node* effect, | 1747 Node* receiver = node->InputAt(0); |
| 2249 Node* control) { | 1748 Node* position = node->InputAt(1); |
| 1749 |
| 2250 Callable const callable = CodeFactory::StringCharCodeAt(isolate()); | 1750 Callable const callable = CodeFactory::StringCharCodeAt(isolate()); |
| 2251 Operator::Properties properties = Operator::kNoThrow | Operator::kNoWrite; | 1751 Operator::Properties properties = Operator::kNoThrow | Operator::kNoWrite; |
| 2252 CallDescriptor::Flags flags = CallDescriptor::kNoFlags; | 1752 CallDescriptor::Flags flags = CallDescriptor::kNoFlags; |
| 2253 CallDescriptor* desc = Linkage::GetStubCallDescriptor( | 1753 CallDescriptor* desc = Linkage::GetStubCallDescriptor( |
| 2254 isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties, | 1754 isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties, |
| 2255 MachineType::TaggedSigned()); | 1755 MachineType::TaggedSigned()); |
| 2256 node->InsertInput(graph()->zone(), 0, | 1756 return __ Call(desc, __ HeapConstant(callable.code()), receiver, position, |
| 2257 jsgraph()->HeapConstant(callable.code())); | 1757 __ NoContextConstant()); |
| 2258 node->InsertInput(graph()->zone(), 3, jsgraph()->NoContextConstant()); | |
| 2259 node->InsertInput(graph()->zone(), 4, effect); | |
| 2260 NodeProperties::ChangeOp(node, common()->Call(desc)); | |
| 2261 return ValueEffectControl(node, node, control); | |
| 2262 } | 1758 } |
| 2263 | 1759 |
| 2264 EffectControlLinearizer::ValueEffectControl | 1760 Node* EffectControlLinearizer::LowerStringFromCharCode(Node* node) { |
| 2265 EffectControlLinearizer::LowerStringFromCharCode(Node* node, Node* effect, | |
| 2266 Node* control) { | |
| 2267 Node* value = node->InputAt(0); | 1761 Node* value = node->InputAt(0); |
| 2268 | 1762 |
| 1763 auto runtime_call = __ MakeDeferredLabel<2>(); |
| 1764 auto if_undefined = __ MakeDeferredLabel<1>(); |
| 1765 auto done = __ MakeLabel<2>(MachineRepresentation::kTagged); |
| 1766 |
| 2269 // Compute the character code. | 1767 // Compute the character code. |
| 2270 Node* code = | 1768 Node* code = __ Word32And(value, __ Int32Constant(String::kMaxUtf16CodeUnit)); |
| 2271 graph()->NewNode(machine()->Word32And(), value, | |
| 2272 jsgraph()->Int32Constant(String::kMaxUtf16CodeUnit)); | |
| 2273 | 1769 |
| 2274 // Check if the {code} is a one-byte char code. | 1770 // Check if the {code} is a one-byte char code. |
| 2275 Node* check0 = | 1771 Node* check0 = __ Int32LessThanOrEqual( |
| 2276 graph()->NewNode(machine()->Int32LessThanOrEqual(), code, | 1772 code, __ Int32Constant(String::kMaxOneByteCharCode)); |
| 2277 jsgraph()->Int32Constant(String::kMaxOneByteCharCode)); | 1773 __ GotoUnless(check0, &runtime_call); |
| 2278 Node* branch0 = | |
| 2279 graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control); | |
| 2280 | |
| 2281 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0); | |
| 2282 Node* efalse0 = effect; | |
| 2283 | |
| 2284 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0); | |
| 2285 Node* etrue0 = effect; | |
| 2286 | 1774 |
| 2287 // Load the isolate wide single character string cache. | 1775 // Load the isolate wide single character string cache. |
| 2288 Node* cache = | 1776 Node* cache = __ HeapConstant(factory()->single_character_string_cache()); |
| 2289 jsgraph()->HeapConstant(factory()->single_character_string_cache()); | |
| 2290 | 1777 |
| 2291 // Compute the {cache} index for {code}. | 1778 // Compute the {cache} index for {code}. |
| 2292 Node* index = machine()->Is32() | 1779 Node* index = machine()->Is32() ? code : __ ChangeUint32ToUint64(code); |
| 2293 ? code | |
| 2294 : graph()->NewNode(machine()->ChangeUint32ToUint64(), code); | |
| 2295 | 1780 |
| 2296 // Check if we have an entry for the {code} in the single character string | 1781 // Check if we have an entry for the {code} in the single character string |
| 2297 // cache already. | 1782 // cache already. |
| 2298 Node* entry = etrue0 = graph()->NewNode( | 1783 Node* entry = |
| 2299 simplified()->LoadElement(AccessBuilder::ForFixedArrayElement()), cache, | 1784 __ LoadElement(AccessBuilder::ForFixedArrayElement(), cache, index); |
| 2300 index, etrue0, if_true0); | |
| 2301 | 1785 |
| 2302 Node* check1 = graph()->NewNode(machine()->WordEqual(), entry, | 1786 Node* check1 = __ WordEqual(entry, __ UndefinedConstant()); |
| 2303 jsgraph()->UndefinedConstant()); | 1787 __ GotoIf(check1, &runtime_call); |
| 2304 Node* branch1 = | 1788 __ Goto(&done, entry); |
| 2305 graph()->NewNode(common()->Branch(BranchHint::kFalse), check1, if_true0); | |
| 2306 | |
| 2307 // Use the {entry} from the {cache}. | |
| 2308 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); | |
| 2309 Node* efalse1 = etrue0; | |
| 2310 Node* vfalse1 = entry; | |
| 2311 | 1789 |
| 2312 // Let %StringFromCharCode handle this case. | 1790 // Let %StringFromCharCode handle this case. |
| 2313 // TODO(turbofan): At some point we may consider adding a stub for this | 1791 // TODO(turbofan): At some point we may consider adding a stub for this |
| 2314 // deferred case, so that we don't need to call to C++ here. | 1792 // deferred case, so that we don't need to call to C++ here. |
| 2315 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); | 1793 __ Bind(&runtime_call); |
| 2316 Node* etrue1 = etrue0; | |
| 2317 Node* vtrue1; | |
| 2318 { | 1794 { |
| 2319 if_true1 = graph()->NewNode(common()->Merge(2), if_true1, if_false0); | |
| 2320 etrue1 = | |
| 2321 graph()->NewNode(common()->EffectPhi(2), etrue1, efalse0, if_true1); | |
| 2322 Operator::Properties properties = Operator::kNoDeopt | Operator::kNoThrow; | 1795 Operator::Properties properties = Operator::kNoDeopt | Operator::kNoThrow; |
| 2323 Runtime::FunctionId id = Runtime::kStringCharFromCode; | 1796 Runtime::FunctionId id = Runtime::kStringCharFromCode; |
| 2324 CallDescriptor const* desc = Linkage::GetRuntimeCallDescriptor( | 1797 CallDescriptor const* desc = Linkage::GetRuntimeCallDescriptor( |
| 2325 graph()->zone(), id, 1, properties, CallDescriptor::kNoFlags); | 1798 graph()->zone(), id, 1, properties, CallDescriptor::kNoFlags); |
| 2326 vtrue1 = etrue1 = graph()->NewNode( | 1799 Node* vtrue1 = |
| 2327 common()->Call(desc), jsgraph()->CEntryStubConstant(1), | 1800 __ Call(desc, __ CEntryStubConstant(1), ChangeInt32ToSmi(code), |
| 2328 ChangeInt32ToSmi(code), | 1801 __ ExternalConstant(ExternalReference(id, isolate())), |
| 2329 jsgraph()->ExternalConstant(ExternalReference(id, isolate())), | 1802 __ Int32Constant(1), __ NoContextConstant()); |
| 2330 jsgraph()->Int32Constant(1), jsgraph()->NoContextConstant(), etrue1, | 1803 __ Goto(&done, vtrue1); |
| 2331 if_true1); | |
| 2332 } | 1804 } |
| 2333 | 1805 __ Bind(&done); |
| 2334 control = graph()->NewNode(common()->Merge(2), if_true1, if_false1); | 1806 return done.PhiAt(0); |
| 2335 effect = graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, control); | |
| 2336 value = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), | |
| 2337 vtrue1, vfalse1, control); | |
| 2338 | |
| 2339 return ValueEffectControl(value, effect, control); | |
| 2340 } | 1807 } |
| 2341 | 1808 |
| 2342 EffectControlLinearizer::ValueEffectControl | 1809 Node* EffectControlLinearizer::LowerStringFromCodePoint(Node* node) { |
| 2343 EffectControlLinearizer::LowerStringFromCodePoint(Node* node, Node* effect, | |
| 2344 Node* control) { | |
| 2345 Node* value = node->InputAt(0); | 1810 Node* value = node->InputAt(0); |
| 2346 Node* code = value; | 1811 Node* code = value; |
| 2347 | 1812 |
| 2348 Node* etrue0 = effect; | 1813 auto if_not_single_code = __ MakeDeferredLabel<1>(); |
| 2349 Node* vtrue0; | 1814 auto if_not_one_byte = __ MakeDeferredLabel<1>(); |
| 1815 auto cache_miss = __ MakeDeferredLabel<1>(); |
| 1816 auto done = __ MakeLabel<4>(MachineRepresentation::kTagged); |
| 2350 | 1817 |
| 2351 // Check if the {code} is a single code unit | 1818 // Check if the {code} is a single code unit |
| 2352 Node* check0 = graph()->NewNode(machine()->Uint32LessThanOrEqual(), code, | 1819 Node* check0 = __ Uint32LessThanOrEqual(code, __ Uint32Constant(0xFFFF)); |
| 2353 jsgraph()->Uint32Constant(0xFFFF)); | 1820 __ GotoUnless(check0, &if_not_single_code); |
| 2354 Node* branch0 = | |
| 2355 graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control); | |
| 2356 | 1821 |
| 2357 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0); | |
| 2358 { | 1822 { |
| 2359 // Check if the {code} is a one byte character | 1823 // Check if the {code} is a one byte character |
| 2360 Node* check1 = graph()->NewNode( | 1824 Node* check1 = __ Uint32LessThanOrEqual( |
| 2361 machine()->Uint32LessThanOrEqual(), code, | 1825 code, __ Uint32Constant(String::kMaxOneByteCharCode)); |
| 2362 jsgraph()->Uint32Constant(String::kMaxOneByteCharCode)); | 1826 __ GotoUnless(check1, &if_not_one_byte); |
| 2363 Node* branch1 = | |
| 2364 graph()->NewNode(common()->Branch(BranchHint::kTrue), check1, if_true0); | |
| 2365 | |
| 2366 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); | |
| 2367 Node* etrue1 = etrue0; | |
| 2368 Node* vtrue1; | |
| 2369 { | 1827 { |
| 2370 // Load the isolate wide single character string cache. | 1828 // Load the isolate wide single character string cache. |
| 2371 Node* cache = | 1829 Node* cache = __ HeapConstant(factory()->single_character_string_cache()); |
| 2372 jsgraph()->HeapConstant(factory()->single_character_string_cache()); | |
| 2373 | 1830 |
| 2374 // Compute the {cache} index for {code}. | 1831 // Compute the {cache} index for {code}. |
| 2375 Node* index = | 1832 Node* index = machine()->Is32() ? code : __ ChangeUint32ToUint64(code); |
| 2376 machine()->Is32() | |
| 2377 ? code | |
| 2378 : graph()->NewNode(machine()->ChangeUint32ToUint64(), code); | |
| 2379 | 1833 |
| 2380 // Check if we have an entry for the {code} in the single character string | 1834 // Check if we have an entry for the {code} in the single character string |
| 2381 // cache already. | 1835 // cache already. |
| 2382 Node* entry = etrue1 = graph()->NewNode( | 1836 Node* entry = |
| 2383 simplified()->LoadElement(AccessBuilder::ForFixedArrayElement()), | 1837 __ LoadElement(AccessBuilder::ForFixedArrayElement(), cache, index); |
| 2384 cache, index, etrue1, if_true1); | |
| 2385 | 1838 |
| 2386 Node* check2 = graph()->NewNode(machine()->WordEqual(), entry, | 1839 Node* check2 = __ WordEqual(entry, __ UndefinedConstant()); |
| 2387 jsgraph()->UndefinedConstant()); | 1840 __ GotoIf(check2, &cache_miss); |
| 2388 Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kFalse), | |
| 2389 check2, if_true1); | |
| 2390 | 1841 |
| 2391 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2); | 1842 // Use the {entry} from the {cache}. |
| 2392 Node* etrue2 = etrue1; | 1843 __ Goto(&done, entry); |
| 2393 Node* vtrue2; | 1844 |
| 1845 __ Bind(&cache_miss); |
| 2394 { | 1846 { |
| 2395 // Allocate a new SeqOneByteString for {code}. | 1847 // Allocate a new SeqOneByteString for {code}. |
| 2396 vtrue2 = etrue2 = graph()->NewNode( | 1848 Node* vtrue2 = __ Allocate( |
| 2397 simplified()->Allocate(NOT_TENURED), | 1849 NOT_TENURED, __ Int32Constant(SeqOneByteString::SizeFor(1))); |
| 2398 jsgraph()->Int32Constant(SeqOneByteString::SizeFor(1)), etrue2, | 1850 __ StoreField(AccessBuilder::ForMap(), vtrue2, |
| 2399 if_true2); | 1851 __ HeapConstant(factory()->one_byte_string_map())); |
| 2400 etrue2 = graph()->NewNode( | 1852 __ StoreField(AccessBuilder::ForNameHashField(), vtrue2, |
| 2401 simplified()->StoreField(AccessBuilder::ForMap()), vtrue2, | 1853 __ IntPtrConstant(Name::kEmptyHashField)); |
| 2402 jsgraph()->HeapConstant(factory()->one_byte_string_map()), etrue2, | 1854 __ StoreField(AccessBuilder::ForStringLength(), vtrue2, |
| 2403 if_true2); | 1855 __ SmiConstant(1)); |
| 2404 etrue2 = graph()->NewNode( | 1856 __ Store( |
| 2405 simplified()->StoreField(AccessBuilder::ForNameHashField()), vtrue2, | 1857 StoreRepresentation(MachineRepresentation::kWord8, kNoWriteBarrier), |
| 2406 jsgraph()->IntPtrConstant(Name::kEmptyHashField), etrue2, if_true2); | 1858 vtrue2, |
| 2407 etrue2 = graph()->NewNode( | 1859 __ IntPtrConstant(SeqOneByteString::kHeaderSize - kHeapObjectTag), |
| 2408 simplified()->StoreField(AccessBuilder::ForStringLength()), vtrue2, | 1860 code); |
| 2409 jsgraph()->SmiConstant(1), etrue2, if_true2); | |
| 2410 etrue2 = graph()->NewNode( | |
| 2411 machine()->Store(StoreRepresentation(MachineRepresentation::kWord8, | |
| 2412 kNoWriteBarrier)), | |
| 2413 vtrue2, jsgraph()->IntPtrConstant(SeqOneByteString::kHeaderSize - | |
| 2414 kHeapObjectTag), | |
| 2415 code, etrue2, if_true2); | |
| 2416 | 1861 |
| 2417 // Remember it in the {cache}. | 1862 // Remember it in the {cache}. |
| 2418 etrue2 = graph()->NewNode( | 1863 __ StoreElement(AccessBuilder::ForFixedArrayElement(), cache, index, |
| 2419 simplified()->StoreElement(AccessBuilder::ForFixedArrayElement()), | 1864 vtrue2); |
| 2420 cache, index, vtrue2, etrue2, if_true2); | 1865 __ Goto(&done, vtrue2); |
| 2421 } | 1866 } |
| 2422 | |
| 2423 // Use the {entry} from the {cache}. | |
| 2424 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2); | |
| 2425 Node* efalse2 = etrue0; | |
| 2426 Node* vfalse2 = entry; | |
| 2427 | |
| 2428 if_true1 = graph()->NewNode(common()->Merge(2), if_true2, if_false2); | |
| 2429 etrue1 = | |
| 2430 graph()->NewNode(common()->EffectPhi(2), etrue2, efalse2, if_true1); | |
| 2431 vtrue1 = | |
| 2432 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), | |
| 2433 vtrue2, vfalse2, if_true1); | |
| 2434 } | 1867 } |
| 2435 | 1868 |
| 2436 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); | 1869 __ Bind(&if_not_one_byte); |
| 2437 Node* efalse1 = effect; | |
| 2438 Node* vfalse1; | |
| 2439 { | 1870 { |
| 2440 // Allocate a new SeqTwoByteString for {code}. | 1871 // Allocate a new SeqTwoByteString for {code}. |
| 2441 vfalse1 = efalse1 = graph()->NewNode( | 1872 Node* vfalse1 = __ Allocate( |
| 2442 simplified()->Allocate(NOT_TENURED), | 1873 NOT_TENURED, __ Int32Constant(SeqTwoByteString::SizeFor(1))); |
| 2443 jsgraph()->Int32Constant(SeqTwoByteString::SizeFor(1)), efalse1, | 1874 __ StoreField(AccessBuilder::ForMap(), vfalse1, |
| 2444 if_false1); | 1875 __ HeapConstant(factory()->string_map())); |
| 2445 efalse1 = graph()->NewNode( | 1876 __ StoreField(AccessBuilder::ForNameHashField(), vfalse1, |
| 2446 simplified()->StoreField(AccessBuilder::ForMap()), vfalse1, | 1877 __ IntPtrConstant(Name::kEmptyHashField)); |
| 2447 jsgraph()->HeapConstant(factory()->string_map()), efalse1, if_false1); | 1878 __ StoreField(AccessBuilder::ForStringLength(), vfalse1, |
| 2448 efalse1 = graph()->NewNode( | 1879 __ SmiConstant(1)); |
| 2449 simplified()->StoreField(AccessBuilder::ForNameHashField()), vfalse1, | 1880 __ Store( |
| 2450 jsgraph()->IntPtrConstant(Name::kEmptyHashField), efalse1, if_false1); | 1881 StoreRepresentation(MachineRepresentation::kWord16, kNoWriteBarrier), |
| 2451 efalse1 = graph()->NewNode( | 1882 vfalse1, |
| 2452 simplified()->StoreField(AccessBuilder::ForStringLength()), vfalse1, | 1883 __ IntPtrConstant(SeqTwoByteString::kHeaderSize - kHeapObjectTag), |
| 2453 jsgraph()->SmiConstant(1), efalse1, if_false1); | 1884 code); |
| 2454 efalse1 = graph()->NewNode( | 1885 __ Goto(&done, vfalse1); |
| 2455 machine()->Store(StoreRepresentation(MachineRepresentation::kWord16, | |
| 2456 kNoWriteBarrier)), | |
| 2457 vfalse1, jsgraph()->IntPtrConstant(SeqTwoByteString::kHeaderSize - | |
| 2458 kHeapObjectTag), | |
| 2459 code, efalse1, if_false1); | |
| 2460 } | 1886 } |
| 2461 | |
| 2462 if_true0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1); | |
| 2463 etrue0 = | |
| 2464 graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_true0); | |
| 2465 vtrue0 = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), | |
| 2466 vtrue1, vfalse1, if_true0); | |
| 2467 } | 1887 } |
| 2468 | 1888 |
| 1889 __ Bind(&if_not_single_code); |
| 2469 // Generate surrogate pair string | 1890 // Generate surrogate pair string |
| 2470 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0); | |
| 2471 Node* efalse0 = effect; | |
| 2472 Node* vfalse0; | |
| 2473 { | 1891 { |
| 2474 switch (UnicodeEncodingOf(node->op())) { | 1892 switch (UnicodeEncodingOf(node->op())) { |
| 2475 case UnicodeEncoding::UTF16: | 1893 case UnicodeEncoding::UTF16: |
| 2476 break; | 1894 break; |
| 2477 | 1895 |
| 2478 case UnicodeEncoding::UTF32: { | 1896 case UnicodeEncoding::UTF32: { |
| 2479 // Convert UTF32 to UTF16 code units, and store as a 32 bit word. | 1897 // Convert UTF32 to UTF16 code units, and store as a 32 bit word. |
| 2480 Node* lead_offset = jsgraph()->Int32Constant(0xD800 - (0x10000 >> 10)); | 1898 Node* lead_offset = __ Int32Constant(0xD800 - (0x10000 >> 10)); |
| 2481 | 1899 |
| 2482 // lead = (codepoint >> 10) + LEAD_OFFSET | 1900 // lead = (codepoint >> 10) + LEAD_OFFSET |
| 2483 Node* lead = | 1901 Node* lead = |
| 2484 graph()->NewNode(machine()->Int32Add(), | 1902 __ Int32Add(__ Word32Shr(code, __ Int32Constant(10)), lead_offset); |
| 2485 graph()->NewNode(machine()->Word32Shr(), code, | |
| 2486 jsgraph()->Int32Constant(10)), | |
| 2487 lead_offset); | |
| 2488 | 1903 |
| 2489 // trail = (codepoint & 0x3FF) + 0xDC00; | 1904 // trail = (codepoint & 0x3FF) + 0xDC00; |
| 2490 Node* trail = | 1905 Node* trail = __ Int32Add(__ Word32And(code, __ Int32Constant(0x3FF)), |
| 2491 graph()->NewNode(machine()->Int32Add(), | 1906 __ Int32Constant(0xDC00)); |
| 2492 graph()->NewNode(machine()->Word32And(), code, | |
| 2493 jsgraph()->Int32Constant(0x3FF)), | |
| 2494 jsgraph()->Int32Constant(0xDC00)); | |
| 2495 | 1907 |
| 2496 // codpoint = (trail << 16) | lead; | 1908 // codpoint = (trail << 16) | lead; |
| 2497 code = graph()->NewNode(machine()->Word32Or(), | 1909 code = __ Word32Or(__ Word32Shl(trail, __ Int32Constant(16)), lead); |
| 2498 graph()->NewNode(machine()->Word32Shl(), trail, | |
| 2499 jsgraph()->Int32Constant(16)), | |
| 2500 lead); | |
| 2501 break; | 1910 break; |
| 2502 } | 1911 } |
| 2503 } | 1912 } |
| 2504 | 1913 |
| 2505 // Allocate a new SeqTwoByteString for {code}. | 1914 // Allocate a new SeqTwoByteString for {code}. |
| 2506 vfalse0 = efalse0 = | 1915 Node* vfalse0 = __ Allocate(NOT_TENURED, |
| 2507 graph()->NewNode(simplified()->Allocate(NOT_TENURED), | 1916 __ Int32Constant(SeqTwoByteString::SizeFor(2))); |
| 2508 jsgraph()->Int32Constant(SeqTwoByteString::SizeFor(2)), | 1917 __ StoreField(AccessBuilder::ForMap(), vfalse0, |
| 2509 efalse0, if_false0); | 1918 __ HeapConstant(factory()->string_map())); |
| 2510 efalse0 = graph()->NewNode( | 1919 __ StoreField(AccessBuilder::ForNameHashField(), vfalse0, |
| 2511 simplified()->StoreField(AccessBuilder::ForMap()), vfalse0, | 1920 __ IntPtrConstant(Name::kEmptyHashField)); |
| 2512 jsgraph()->HeapConstant(factory()->string_map()), efalse0, if_false0); | 1921 __ StoreField(AccessBuilder::ForStringLength(), vfalse0, __ SmiConstant(2)); |
| 2513 efalse0 = graph()->NewNode( | 1922 __ Store( |
| 2514 simplified()->StoreField(AccessBuilder::ForNameHashField()), vfalse0, | 1923 StoreRepresentation(MachineRepresentation::kWord32, kNoWriteBarrier), |
| 2515 jsgraph()->IntPtrConstant(Name::kEmptyHashField), efalse0, if_false0); | 1924 vfalse0, |
| 2516 efalse0 = graph()->NewNode( | 1925 __ IntPtrConstant(SeqTwoByteString::kHeaderSize - kHeapObjectTag), |
| 2517 simplified()->StoreField(AccessBuilder::ForStringLength()), vfalse0, | 1926 code); |
| 2518 jsgraph()->SmiConstant(2), efalse0, if_false0); | 1927 __ Goto(&done, vfalse0); |
| 2519 efalse0 = graph()->NewNode( | 1928 } |
| 2520 machine()->Store(StoreRepresentation(MachineRepresentation::kWord32, | 1929 |
| 2521 kNoWriteBarrier)), | 1930 __ Bind(&done); |
| 2522 vfalse0, jsgraph()->IntPtrConstant(SeqTwoByteString::kHeaderSize - | 1931 return done.PhiAt(0); |
| 2523 kHeapObjectTag), | 1932 } |
| 2524 code, efalse0, if_false0); | 1933 |
| 2525 } | 1934 Node* EffectControlLinearizer::LowerStringComparison(Callable const& callable, |
| 2526 | 1935 Node* node) { |
| 2527 control = graph()->NewNode(common()->Merge(2), if_true0, if_false0); | 1936 Node* lhs = node->InputAt(0); |
| 2528 effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control); | 1937 Node* rhs = node->InputAt(1); |
| 2529 value = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), | 1938 |
| 2530 vtrue0, vfalse0, control); | |
| 2531 | |
| 2532 return ValueEffectControl(value, effect, control); | |
| 2533 } | |
| 2534 | |
| 2535 EffectControlLinearizer::ValueEffectControl | |
| 2536 EffectControlLinearizer::LowerStringComparison(Callable const& callable, | |
| 2537 Node* node, Node* effect, | |
| 2538 Node* control) { | |
| 2539 Operator::Properties properties = Operator::kEliminatable; | 1939 Operator::Properties properties = Operator::kEliminatable; |
| 2540 CallDescriptor::Flags flags = CallDescriptor::kNoFlags; | 1940 CallDescriptor::Flags flags = CallDescriptor::kNoFlags; |
| 2541 CallDescriptor* desc = Linkage::GetStubCallDescriptor( | 1941 CallDescriptor* desc = Linkage::GetStubCallDescriptor( |
| 2542 isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties); | 1942 isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties); |
| 2543 node->InsertInput(graph()->zone(), 0, | 1943 return __ Call(desc, __ HeapConstant(callable.code()), lhs, rhs, |
| 2544 jsgraph()->HeapConstant(callable.code())); | 1944 __ NoContextConstant()); |
| 2545 node->AppendInput(graph()->zone(), jsgraph()->NoContextConstant()); | 1945 } |
| 2546 node->AppendInput(graph()->zone(), effect); | 1946 |
| 2547 NodeProperties::ChangeOp(node, common()->Call(desc)); | 1947 Node* EffectControlLinearizer::LowerStringEqual(Node* node) { |
| 2548 return ValueEffectControl(node, node, control); | 1948 return LowerStringComparison(CodeFactory::StringEqual(isolate()), node); |
| 2549 } | 1949 } |
| 2550 | 1950 |
| 2551 EffectControlLinearizer::ValueEffectControl | 1951 Node* EffectControlLinearizer::LowerStringLessThan(Node* node) { |
| 2552 EffectControlLinearizer::LowerStringEqual(Node* node, Node* effect, | 1952 return LowerStringComparison(CodeFactory::StringLessThan(isolate()), node); |
| 2553 Node* control) { | 1953 } |
| 2554 return LowerStringComparison(CodeFactory::StringEqual(isolate()), node, | 1954 |
| 2555 effect, control); | 1955 Node* EffectControlLinearizer::LowerStringLessThanOrEqual(Node* node) { |
| 2556 } | |
| 2557 | |
| 2558 EffectControlLinearizer::ValueEffectControl | |
| 2559 EffectControlLinearizer::LowerStringLessThan(Node* node, Node* effect, | |
| 2560 Node* control) { | |
| 2561 return LowerStringComparison(CodeFactory::StringLessThan(isolate()), node, | |
| 2562 effect, control); | |
| 2563 } | |
| 2564 | |
| 2565 EffectControlLinearizer::ValueEffectControl | |
| 2566 EffectControlLinearizer::LowerStringLessThanOrEqual(Node* node, Node* effect, | |
| 2567 Node* control) { | |
| 2568 return LowerStringComparison(CodeFactory::StringLessThanOrEqual(isolate()), | 1956 return LowerStringComparison(CodeFactory::StringLessThanOrEqual(isolate()), |
| 2569 node, effect, control); | 1957 node); |
| 2570 } | 1958 } |
| 2571 | 1959 |
| 2572 EffectControlLinearizer::ValueEffectControl | 1960 Node* EffectControlLinearizer::LowerCheckFloat64Hole(Node* node, |
| 2573 EffectControlLinearizer::LowerCheckFloat64Hole(Node* node, Node* frame_state, | 1961 Node* frame_state) { |
| 2574 Node* effect, Node* control) { | |
| 2575 // If we reach this point w/o eliminating the {node} that's marked | 1962 // If we reach this point w/o eliminating the {node} that's marked |
| 2576 // with allow-return-hole, we cannot do anything, so just deoptimize | 1963 // with allow-return-hole, we cannot do anything, so just deoptimize |
| 2577 // in case of the hole NaN (similar to Crankshaft). | 1964 // in case of the hole NaN (similar to Crankshaft). |
| 2578 Node* value = node->InputAt(0); | 1965 Node* value = node->InputAt(0); |
| 2579 Node* check = graph()->NewNode( | 1966 Node* check = __ Word32Equal(__ Float64ExtractHighWord32(value), |
| 2580 machine()->Word32Equal(), | 1967 __ Int32Constant(kHoleNanUpper32)); |
| 2581 graph()->NewNode(machine()->Float64ExtractHighWord32(), value), | 1968 __ DeoptimizeIf(DeoptimizeReason::kHole, check, frame_state); |
| 2582 jsgraph()->Int32Constant(kHoleNanUpper32)); | 1969 return value; |
| 2583 control = effect = | 1970 } |
| 2584 graph()->NewNode(common()->DeoptimizeIf(DeoptimizeReason::kHole), check, | 1971 |
| 2585 frame_state, effect, control); | 1972 Node* EffectControlLinearizer::LowerCheckTaggedHole(Node* node, |
| 2586 | 1973 Node* frame_state) { |
| 2587 return ValueEffectControl(value, effect, control); | 1974 Node* value = node->InputAt(0); |
| 2588 } | 1975 Node* check = __ WordEqual(value, __ TheHoleConstant()); |
| 2589 | 1976 __ DeoptimizeIf(DeoptimizeReason::kHole, check, frame_state); |
| 2590 EffectControlLinearizer::ValueEffectControl | 1977 return value; |
| 2591 EffectControlLinearizer::LowerCheckTaggedHole(Node* node, Node* frame_state, | 1978 } |
| 2592 Node* effect, Node* control) { | 1979 |
| 2593 Node* value = node->InputAt(0); | 1980 Node* EffectControlLinearizer::LowerConvertTaggedHoleToUndefined(Node* node) { |
| 2594 Node* check = graph()->NewNode(machine()->WordEqual(), value, | 1981 Node* value = node->InputAt(0); |
| 2595 jsgraph()->TheHoleConstant()); | 1982 |
| 2596 control = effect = | 1983 auto if_is_hole = __ MakeDeferredLabel<1>(); |
| 2597 graph()->NewNode(common()->DeoptimizeIf(DeoptimizeReason::kHole), check, | 1984 auto done = __ MakeLabel<2>(MachineRepresentation::kTagged); |
| 2598 frame_state, effect, control); | 1985 |
| 2599 | 1986 Node* check = __ WordEqual(value, __ TheHoleConstant()); |
| 2600 return ValueEffectControl(value, effect, control); | 1987 __ GotoIf(check, &if_is_hole); |
| 2601 } | 1988 __ Goto(&done, value); |
| 2602 | 1989 |
| 2603 EffectControlLinearizer::ValueEffectControl | 1990 __ Bind(&if_is_hole); |
| 2604 EffectControlLinearizer::LowerConvertTaggedHoleToUndefined(Node* node, | 1991 __ Goto(&done, __ UndefinedConstant()); |
| 2605 Node* effect, | 1992 |
| 2606 Node* control) { | 1993 __ Bind(&done); |
| 2607 Node* value = node->InputAt(0); | 1994 return done.PhiAt(0); |
| 2608 Node* check = graph()->NewNode(machine()->WordEqual(), value, | 1995 } |
| 2609 jsgraph()->TheHoleConstant()); | 1996 |
| 2610 Node* branch = | 1997 Node* EffectControlLinearizer::AllocateHeapNumberWithValue(Node* value) { |
| 2611 graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control); | 1998 Node* result = __ Allocate(NOT_TENURED, __ Int32Constant(HeapNumber::kSize)); |
| 2612 | 1999 __ StoreField(AccessBuilder::ForMap(), result, __ HeapNumberMapConstant()); |
| 2613 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); | 2000 __ StoreField(AccessBuilder::ForHeapNumberValue(), result, value); |
| 2614 Node* vtrue = jsgraph()->UndefinedConstant(); | 2001 return result; |
| 2615 | |
| 2616 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); | |
| 2617 Node* vfalse = value; | |
| 2618 | |
| 2619 control = graph()->NewNode(common()->Merge(2), if_true, if_false); | |
| 2620 value = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), | |
| 2621 vtrue, vfalse, control); | |
| 2622 | |
| 2623 return ValueEffectControl(value, effect, control); | |
| 2624 } | |
| 2625 | |
| 2626 EffectControlLinearizer::ValueEffectControl | |
| 2627 EffectControlLinearizer::AllocateHeapNumberWithValue(Node* value, Node* effect, | |
| 2628 Node* control) { | |
| 2629 Node* result = effect = graph()->NewNode( | |
| 2630 simplified()->Allocate(NOT_TENURED), | |
| 2631 jsgraph()->Int32Constant(HeapNumber::kSize), effect, control); | |
| 2632 effect = graph()->NewNode(simplified()->StoreField(AccessBuilder::ForMap()), | |
| 2633 result, jsgraph()->HeapNumberMapConstant(), effect, | |
| 2634 control); | |
| 2635 effect = graph()->NewNode( | |
| 2636 simplified()->StoreField(AccessBuilder::ForHeapNumberValue()), result, | |
| 2637 value, effect, control); | |
| 2638 return ValueEffectControl(result, effect, control); | |
| 2639 } | 2002 } |
| 2640 | 2003 |
| 2641 Node* EffectControlLinearizer::ChangeInt32ToSmi(Node* value) { | 2004 Node* EffectControlLinearizer::ChangeInt32ToSmi(Node* value) { |
| 2642 if (machine()->Is64()) { | 2005 if (machine()->Is64()) { |
| 2643 value = graph()->NewNode(machine()->ChangeInt32ToInt64(), value); | 2006 value = __ ChangeInt32ToInt64(value); |
| 2644 } | 2007 } |
| 2645 return graph()->NewNode(machine()->WordShl(), value, SmiShiftBitsConstant()); | 2008 return __ WordShl(value, SmiShiftBitsConstant()); |
| 2646 } | 2009 } |
| 2647 | 2010 |
| 2648 Node* EffectControlLinearizer::ChangeUint32ToSmi(Node* value) { | 2011 Node* EffectControlLinearizer::ChangeUint32ToSmi(Node* value) { |
| 2649 if (machine()->Is64()) { | 2012 if (machine()->Is64()) { |
| 2650 value = graph()->NewNode(machine()->ChangeUint32ToUint64(), value); | 2013 value = __ ChangeUint32ToUint64(value); |
| 2651 } | 2014 } |
| 2652 return graph()->NewNode(machine()->WordShl(), value, SmiShiftBitsConstant()); | 2015 return __ WordShl(value, SmiShiftBitsConstant()); |
| 2653 } | |
| 2654 | |
| 2655 Node* EffectControlLinearizer::ChangeInt32ToFloat64(Node* value) { | |
| 2656 return graph()->NewNode(machine()->ChangeInt32ToFloat64(), value); | |
| 2657 } | |
| 2658 | |
| 2659 Node* EffectControlLinearizer::ChangeUint32ToFloat64(Node* value) { | |
| 2660 return graph()->NewNode(machine()->ChangeUint32ToFloat64(), value); | |
| 2661 } | 2016 } |
| 2662 | 2017 |
| 2663 Node* EffectControlLinearizer::ChangeSmiToInt32(Node* value) { | 2018 Node* EffectControlLinearizer::ChangeSmiToInt32(Node* value) { |
| 2664 value = graph()->NewNode(machine()->WordSar(), value, SmiShiftBitsConstant()); | 2019 value = __ WordSar(value, SmiShiftBitsConstant()); |
| 2665 if (machine()->Is64()) { | 2020 if (machine()->Is64()) { |
| 2666 value = graph()->NewNode(machine()->TruncateInt64ToInt32(), value); | 2021 value = __ TruncateInt64ToInt32(value); |
| 2667 } | 2022 } |
| 2668 return value; | 2023 return value; |
| 2669 } | 2024 } |
| 2025 |
| 2670 Node* EffectControlLinearizer::ObjectIsSmi(Node* value) { | 2026 Node* EffectControlLinearizer::ObjectIsSmi(Node* value) { |
| 2671 return graph()->NewNode( | 2027 return __ WordEqual(__ WordAnd(value, __ IntPtrConstant(kSmiTagMask)), |
| 2672 machine()->WordEqual(), | 2028 __ IntPtrConstant(kSmiTag)); |
| 2673 graph()->NewNode(machine()->WordAnd(), value, | |
| 2674 jsgraph()->IntPtrConstant(kSmiTagMask)), | |
| 2675 jsgraph()->IntPtrConstant(kSmiTag)); | |
| 2676 } | 2029 } |
| 2677 | 2030 |
| 2678 Node* EffectControlLinearizer::SmiMaxValueConstant() { | 2031 Node* EffectControlLinearizer::SmiMaxValueConstant() { |
| 2679 return jsgraph()->Int32Constant(Smi::kMaxValue); | 2032 return __ Int32Constant(Smi::kMaxValue); |
| 2680 } | 2033 } |
| 2681 | 2034 |
| 2682 Node* EffectControlLinearizer::SmiShiftBitsConstant() { | 2035 Node* EffectControlLinearizer::SmiShiftBitsConstant() { |
| 2683 return jsgraph()->IntPtrConstant(kSmiShiftSize + kSmiTagSize); | 2036 return __ IntPtrConstant(kSmiShiftSize + kSmiTagSize); |
| 2684 } | 2037 } |
| 2685 | 2038 |
| 2686 EffectControlLinearizer::ValueEffectControl | 2039 Node* EffectControlLinearizer::LowerPlainPrimitiveToNumber(Node* node) { |
| 2687 EffectControlLinearizer::LowerPlainPrimitiveToNumber(Node* node, Node* effect, | 2040 Node* value = node->InputAt(0); |
| 2688 Node* control) { | 2041 return __ ToNumber(value); |
| 2689 Node* value = node->InputAt(0); | 2042 } |
| 2690 Node* result = effect = | 2043 |
| 2691 graph()->NewNode(ToNumberOperator(), jsgraph()->ToNumberBuiltinConstant(), | 2044 Node* EffectControlLinearizer::LowerPlainPrimitiveToWord32(Node* node) { |
| 2692 value, jsgraph()->NoContextConstant(), effect); | 2045 Node* value = node->InputAt(0); |
| 2693 return ValueEffectControl(result, effect, control); | 2046 |
| 2694 } | 2047 auto if_not_smi = __ MakeDeferredLabel<1>(); |
| 2695 | 2048 auto if_to_number_smi = __ MakeLabel<1>(); |
| 2696 EffectControlLinearizer::ValueEffectControl | 2049 auto done = __ MakeLabel<3>(MachineRepresentation::kWord32); |
| 2697 EffectControlLinearizer::LowerPlainPrimitiveToWord32(Node* node, Node* effect, | |
| 2698 Node* control) { | |
| 2699 Node* value = node->InputAt(0); | |
| 2700 | 2050 |
| 2701 Node* check0 = ObjectIsSmi(value); | 2051 Node* check0 = ObjectIsSmi(value); |
| 2702 Node* branch0 = | 2052 __ GotoUnless(check0, &if_not_smi); |
| 2703 graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control); | 2053 __ Goto(&done, ChangeSmiToInt32(value)); |
| 2704 | 2054 |
| 2705 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0); | 2055 __ Bind(&if_not_smi); |
| 2706 Node* etrue0 = effect; | 2056 Node* to_number = __ ToNumber(value); |
| 2707 Node* vtrue0 = ChangeSmiToInt32(value); | 2057 |
| 2708 | 2058 Node* check1 = ObjectIsSmi(to_number); |
| 2709 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0); | 2059 __ GotoIf(check1, &if_to_number_smi); |
| 2710 Node* efalse0 = effect; | 2060 Node* number = __ LoadField(AccessBuilder::ForHeapNumberValue(), to_number); |
| 2711 Node* vfalse0; | 2061 __ Goto(&done, __ TruncateFloat64ToWord32(number)); |
| 2712 { | 2062 |
| 2713 vfalse0 = efalse0 = graph()->NewNode( | 2063 __ Bind(&if_to_number_smi); |
| 2714 ToNumberOperator(), jsgraph()->ToNumberBuiltinConstant(), value, | 2064 __ Goto(&done, ChangeSmiToInt32(to_number)); |
| 2715 jsgraph()->NoContextConstant(), efalse0); | 2065 |
| 2716 | 2066 __ Bind(&done); |
| 2717 Node* check1 = ObjectIsSmi(vfalse0); | 2067 return done.PhiAt(0); |
| 2718 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0); | 2068 } |
| 2719 | 2069 |
| 2720 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); | 2070 Node* EffectControlLinearizer::LowerPlainPrimitiveToFloat64(Node* node) { |
| 2721 Node* etrue1 = efalse0; | 2071 Node* value = node->InputAt(0); |
| 2722 Node* vtrue1 = ChangeSmiToInt32(vfalse0); | 2072 |
| 2723 | 2073 auto if_not_smi = __ MakeDeferredLabel<1>(); |
| 2724 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); | 2074 auto if_to_number_smi = __ MakeLabel<1>(); |
| 2725 Node* efalse1 = efalse0; | 2075 auto done = __ MakeLabel<3>(MachineRepresentation::kFloat64); |
| 2726 Node* vfalse1; | |
| 2727 { | |
| 2728 vfalse1 = efalse1 = graph()->NewNode( | |
| 2729 simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), efalse0, | |
| 2730 efalse1, if_false1); | |
| 2731 vfalse1 = graph()->NewNode(machine()->TruncateFloat64ToWord32(), vfalse1); | |
| 2732 } | |
| 2733 | |
| 2734 if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1); | |
| 2735 efalse0 = | |
| 2736 graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_false0); | |
| 2737 vfalse0 = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2), | |
| 2738 vtrue1, vfalse1, if_false0); | |
| 2739 } | |
| 2740 | |
| 2741 control = graph()->NewNode(common()->Merge(2), if_true0, if_false0); | |
| 2742 effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control); | |
| 2743 value = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2), | |
| 2744 vtrue0, vfalse0, control); | |
| 2745 return ValueEffectControl(value, effect, control); | |
| 2746 } | |
| 2747 | |
| 2748 EffectControlLinearizer::ValueEffectControl | |
| 2749 EffectControlLinearizer::LowerPlainPrimitiveToFloat64(Node* node, Node* effect, | |
| 2750 Node* control) { | |
| 2751 Node* value = node->InputAt(0); | |
| 2752 | 2076 |
| 2753 Node* check0 = ObjectIsSmi(value); | 2077 Node* check0 = ObjectIsSmi(value); |
| 2754 Node* branch0 = | 2078 __ GotoUnless(check0, &if_not_smi); |
| 2755 graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control); | 2079 Node* from_smi = ChangeSmiToInt32(value); |
| 2756 | 2080 __ Goto(&done, __ ChangeInt32ToFloat64(from_smi)); |
| 2757 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0); | 2081 |
| 2758 Node* etrue0 = effect; | 2082 __ Bind(&if_not_smi); |
| 2759 Node* vtrue0; | 2083 Node* to_number = __ ToNumber(value); |
| 2760 { | 2084 Node* check1 = ObjectIsSmi(to_number); |
| 2761 vtrue0 = ChangeSmiToInt32(value); | 2085 __ GotoIf(check1, &if_to_number_smi); |
| 2762 vtrue0 = graph()->NewNode(machine()->ChangeInt32ToFloat64(), vtrue0); | 2086 |
| 2763 } | 2087 Node* number = __ LoadField(AccessBuilder::ForHeapNumberValue(), to_number); |
| 2764 | 2088 __ Goto(&done, number); |
| 2765 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0); | 2089 |
| 2766 Node* efalse0 = effect; | 2090 __ Bind(&if_to_number_smi); |
| 2767 Node* vfalse0; | 2091 Node* number_from_smi = ChangeSmiToInt32(to_number); |
| 2768 { | 2092 number_from_smi = __ ChangeInt32ToFloat64(number_from_smi); |
| 2769 vfalse0 = efalse0 = graph()->NewNode( | 2093 __ Goto(&done, number_from_smi); |
| 2770 ToNumberOperator(), jsgraph()->ToNumberBuiltinConstant(), value, | 2094 |
| 2771 jsgraph()->NoContextConstant(), efalse0); | 2095 __ Bind(&done); |
| 2772 | 2096 return done.PhiAt(0); |
| 2773 Node* check1 = ObjectIsSmi(vfalse0); | 2097 } |
| 2774 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0); | 2098 |
| 2775 | 2099 Node* EffectControlLinearizer::LowerEnsureWritableFastElements(Node* node) { |
| 2776 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); | |
| 2777 Node* etrue1 = efalse0; | |
| 2778 Node* vtrue1; | |
| 2779 { | |
| 2780 vtrue1 = ChangeSmiToInt32(vfalse0); | |
| 2781 vtrue1 = graph()->NewNode(machine()->ChangeInt32ToFloat64(), vtrue1); | |
| 2782 } | |
| 2783 | |
| 2784 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); | |
| 2785 Node* efalse1 = efalse0; | |
| 2786 Node* vfalse1; | |
| 2787 { | |
| 2788 vfalse1 = efalse1 = graph()->NewNode( | |
| 2789 simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), efalse0, | |
| 2790 efalse1, if_false1); | |
| 2791 } | |
| 2792 | |
| 2793 if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1); | |
| 2794 efalse0 = | |
| 2795 graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_false0); | |
| 2796 vfalse0 = | |
| 2797 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2), | |
| 2798 vtrue1, vfalse1, if_false0); | |
| 2799 } | |
| 2800 | |
| 2801 control = graph()->NewNode(common()->Merge(2), if_true0, if_false0); | |
| 2802 effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control); | |
| 2803 value = graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2), | |
| 2804 vtrue0, vfalse0, control); | |
| 2805 return ValueEffectControl(value, effect, control); | |
| 2806 } | |
| 2807 | |
| 2808 EffectControlLinearizer::ValueEffectControl | |
| 2809 EffectControlLinearizer::LowerEnsureWritableFastElements(Node* node, | |
| 2810 Node* effect, | |
| 2811 Node* control) { | |
| 2812 Node* object = node->InputAt(0); | 2100 Node* object = node->InputAt(0); |
| 2813 Node* elements = node->InputAt(1); | 2101 Node* elements = node->InputAt(1); |
| 2814 | 2102 |
| 2103 auto if_not_fixed_array = __ MakeDeferredLabel<1>(); |
| 2104 auto done = __ MakeLabel<2>(MachineRepresentation::kTagged); |
| 2105 |
| 2815 // Load the current map of {elements}. | 2106 // Load the current map of {elements}. |
| 2816 Node* elements_map = effect = | 2107 Node* elements_map = __ LoadField(AccessBuilder::ForMap(), elements); |
| 2817 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), | |
| 2818 elements, effect, control); | |
| 2819 | 2108 |
| 2820 // Check if {elements} is not a copy-on-write FixedArray. | 2109 // Check if {elements} is not a copy-on-write FixedArray. |
| 2821 Node* check = graph()->NewNode(machine()->WordEqual(), elements_map, | 2110 Node* check = __ WordEqual(elements_map, __ FixedArrayMapConstant()); |
| 2822 jsgraph()->FixedArrayMapConstant()); | 2111 __ GotoUnless(check, &if_not_fixed_array); |
| 2823 Node* branch = | |
| 2824 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control); | |
| 2825 | |
| 2826 // Nothing to do if the {elements} are not copy-on-write. | 2112 // Nothing to do if the {elements} are not copy-on-write. |
| 2827 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); | 2113 __ Goto(&done, elements); |
| 2828 Node* etrue = effect; | 2114 |
| 2829 Node* vtrue = elements; | 2115 __ Bind(&if_not_fixed_array); |
| 2830 | |
| 2831 // We need to take a copy of the {elements} and set them up for {object}. | 2116 // We need to take a copy of the {elements} and set them up for {object}. |
| 2832 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); | 2117 Operator::Properties properties = Operator::kEliminatable; |
| 2833 Node* efalse = effect; | 2118 Callable callable = CodeFactory::CopyFastSmiOrObjectElements(isolate()); |
| 2834 Node* vfalse; | 2119 CallDescriptor::Flags flags = CallDescriptor::kNoFlags; |
| 2835 { | 2120 CallDescriptor const* const desc = Linkage::GetStubCallDescriptor( |
| 2836 // We need to create a copy of the {elements} for {object}. | 2121 isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties); |
| 2837 Operator::Properties properties = Operator::kEliminatable; | 2122 Node* result = __ Call(desc, __ HeapConstant(callable.code()), object, |
| 2838 Callable callable = CodeFactory::CopyFastSmiOrObjectElements(isolate()); | 2123 __ NoContextConstant()); |
| 2839 CallDescriptor::Flags flags = CallDescriptor::kNoFlags; | 2124 __ Goto(&done, result); |
| 2840 CallDescriptor const* const desc = Linkage::GetStubCallDescriptor( | 2125 |
| 2841 isolate(), graph()->zone(), callable.descriptor(), 0, flags, | 2126 __ Bind(&done); |
| 2842 properties); | 2127 return done.PhiAt(0); |
| 2843 vfalse = efalse = graph()->NewNode( | 2128 } |
| 2844 common()->Call(desc), jsgraph()->HeapConstant(callable.code()), object, | 2129 |
| 2845 jsgraph()->NoContextConstant(), efalse); | 2130 Node* EffectControlLinearizer::LowerMaybeGrowFastElements(Node* node, |
| 2846 } | 2131 Node* frame_state) { |
| 2847 | |
| 2848 control = graph()->NewNode(common()->Merge(2), if_true, if_false); | |
| 2849 effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control); | |
| 2850 Node* value = graph()->NewNode( | |
| 2851 common()->Phi(MachineRepresentation::kTagged, 2), vtrue, vfalse, control); | |
| 2852 | |
| 2853 return ValueEffectControl(value, effect, control); | |
| 2854 } | |
| 2855 | |
| 2856 EffectControlLinearizer::ValueEffectControl | |
| 2857 EffectControlLinearizer::LowerMaybeGrowFastElements(Node* node, | |
| 2858 Node* frame_state, | |
| 2859 Node* effect, | |
| 2860 Node* control) { | |
| 2861 GrowFastElementsFlags flags = GrowFastElementsFlagsOf(node->op()); | 2132 GrowFastElementsFlags flags = GrowFastElementsFlagsOf(node->op()); |
| 2862 Node* object = node->InputAt(0); | 2133 Node* object = node->InputAt(0); |
| 2863 Node* elements = node->InputAt(1); | 2134 Node* elements = node->InputAt(1); |
| 2864 Node* index = node->InputAt(2); | 2135 Node* index = node->InputAt(2); |
| 2865 Node* length = node->InputAt(3); | 2136 Node* length = node->InputAt(3); |
| 2866 | 2137 |
| 2867 Node* check0 = graph()->NewNode((flags & GrowFastElementsFlag::kHoleyElements) | 2138 auto done = __ MakeLabel<2>(MachineRepresentation::kTagged); |
| 2868 ? machine()->Uint32LessThanOrEqual() | 2139 auto done_grow = __ MakeLabel<2>(MachineRepresentation::kTagged); |
| 2869 : machine()->Word32Equal(), | 2140 auto if_not_grow = __ MakeLabel<1>(); |
| 2870 length, index); | 2141 auto if_not_grow_backing_store = __ MakeLabel<1>(); |
| 2871 Node* branch0 = graph()->NewNode(common()->Branch(), check0, control); | 2142 |
| 2872 | 2143 Node* check0 = (flags & GrowFastElementsFlag::kHoleyElements) |
| 2873 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0); | 2144 ? __ Uint32LessThanOrEqual(length, index) |
| 2874 Node* etrue0 = effect; | 2145 : __ Word32Equal(length, index); |
| 2875 Node* vtrue0 = elements; | 2146 __ GotoUnless(check0, &if_not_grow); |
| 2876 { | 2147 { |
| 2877 // Load the length of the {elements} backing store. | 2148 // Load the length of the {elements} backing store. |
| 2878 Node* elements_length = etrue0 = graph()->NewNode( | 2149 Node* elements_length = |
| 2879 simplified()->LoadField(AccessBuilder::ForFixedArrayLength()), elements, | 2150 __ LoadField(AccessBuilder::ForFixedArrayLength(), elements); |
| 2880 etrue0, if_true0); | |
| 2881 elements_length = ChangeSmiToInt32(elements_length); | 2151 elements_length = ChangeSmiToInt32(elements_length); |
| 2882 | 2152 |
| 2883 // Check if we need to grow the {elements} backing store. | 2153 // Check if we need to grow the {elements} backing store. |
| 2884 Node* check1 = | 2154 Node* check1 = __ Uint32LessThan(index, elements_length); |
| 2885 graph()->NewNode(machine()->Uint32LessThan(), index, elements_length); | 2155 __ GotoUnless(check1, &if_not_grow_backing_store); |
| 2886 Node* branch1 = | 2156 __ Goto(&done_grow, elements); |
| 2887 graph()->NewNode(common()->Branch(BranchHint::kTrue), check1, if_true0); | 2157 |
| 2888 | 2158 __ Bind(&if_not_grow_backing_store); |
| 2889 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); | 2159 // We need to grow the {elements} for {object}. |
| 2890 Node* etrue1 = etrue0; | 2160 Operator::Properties properties = Operator::kEliminatable; |
| 2891 Node* vtrue1 = vtrue0; | 2161 Callable callable = |
| 2892 | 2162 (flags & GrowFastElementsFlag::kDoubleElements) |
| 2893 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); | 2163 ? CodeFactory::GrowFastDoubleElements(isolate()) |
| 2894 Node* efalse1 = etrue0; | 2164 : CodeFactory::GrowFastSmiOrObjectElements(isolate()); |
| 2895 Node* vfalse1 = vtrue0; | 2165 CallDescriptor::Flags call_flags = CallDescriptor::kNoFlags; |
| 2896 { | 2166 CallDescriptor const* const desc = Linkage::GetStubCallDescriptor( |
| 2897 // We need to grow the {elements} for {object}. | 2167 isolate(), graph()->zone(), callable.descriptor(), 0, call_flags, |
| 2898 Operator::Properties properties = Operator::kEliminatable; | 2168 properties); |
| 2899 Callable callable = | 2169 Node* new_object = __ Call(desc, __ HeapConstant(callable.code()), object, |
| 2900 (flags & GrowFastElementsFlag::kDoubleElements) | 2170 ChangeInt32ToSmi(index), __ NoContextConstant()); |
| 2901 ? CodeFactory::GrowFastDoubleElements(isolate()) | 2171 |
| 2902 : CodeFactory::GrowFastSmiOrObjectElements(isolate()); | 2172 // Ensure that we were able to grow the {elements}. |
| 2903 CallDescriptor::Flags flags = CallDescriptor::kNoFlags; | 2173 // TODO(turbofan): We use kSmi as reason here similar to Crankshaft, |
| 2904 CallDescriptor const* const desc = Linkage::GetStubCallDescriptor( | 2174 // but maybe we should just introduce a reason that makes sense. |
| 2905 isolate(), graph()->zone(), callable.descriptor(), 0, flags, | 2175 __ DeoptimizeIf(DeoptimizeReason::kSmi, ObjectIsSmi(new_object), |
| 2906 properties); | 2176 frame_state); |
| 2907 vfalse1 = efalse1 = graph()->NewNode( | 2177 __ Goto(&done_grow, new_object); |
| 2908 common()->Call(desc), jsgraph()->HeapConstant(callable.code()), | 2178 |
| 2909 object, ChangeInt32ToSmi(index), jsgraph()->NoContextConstant(), | 2179 __ Bind(&done_grow); |
| 2910 efalse1); | |
| 2911 | |
| 2912 // Ensure that we were able to grow the {elements}. | |
| 2913 // TODO(turbofan): We use kSmi as reason here similar to Crankshaft, | |
| 2914 // but maybe we should just introduce a reason that makes sense. | |
| 2915 efalse1 = if_false1 = graph()->NewNode( | |
| 2916 common()->DeoptimizeIf(DeoptimizeReason::kSmi), ObjectIsSmi(vfalse1), | |
| 2917 frame_state, efalse1, if_false1); | |
| 2918 } | |
| 2919 | |
| 2920 if_true0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1); | |
| 2921 etrue0 = | |
| 2922 graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_true0); | |
| 2923 vtrue0 = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), | |
| 2924 vtrue1, vfalse1, if_true0); | |
| 2925 | 2180 |
| 2926 // For JSArray {object}s we also need to update the "length". | 2181 // For JSArray {object}s we also need to update the "length". |
| 2927 if (flags & GrowFastElementsFlag::kArrayObject) { | 2182 if (flags & GrowFastElementsFlag::kArrayObject) { |
| 2928 // Compute the new {length}. | 2183 // Compute the new {length}. |
| 2929 Node* object_length = ChangeInt32ToSmi(graph()->NewNode( | 2184 Node* object_length = |
| 2930 machine()->Int32Add(), index, jsgraph()->Int32Constant(1))); | 2185 ChangeInt32ToSmi(__ Int32Add(index, __ Int32Constant(1))); |
| 2931 | 2186 |
| 2932 // Update the "length" property of the {object}. | 2187 // Update the "length" property of the {object}. |
| 2933 etrue0 = | 2188 __ StoreField(AccessBuilder::ForJSArrayLength(FAST_ELEMENTS), object, |
| 2934 graph()->NewNode(simplified()->StoreField( | 2189 object_length); |
| 2935 AccessBuilder::ForJSArrayLength(FAST_ELEMENTS)), | |
| 2936 object, object_length, etrue0, if_true0); | |
| 2937 } | 2190 } |
| 2938 } | 2191 __ Goto(&done, done_grow.PhiAt(0)); |
| 2939 | 2192 } |
| 2940 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0); | 2193 |
| 2941 Node* efalse0 = effect; | 2194 __ Bind(&if_not_grow); |
| 2942 Node* vfalse0 = elements; | |
| 2943 { | 2195 { |
| 2944 // In case of non-holey {elements}, we need to verify that the {index} is | 2196 // In case of non-holey {elements}, we need to verify that the {index} is |
| 2945 // in-bounds, otherwise for holey {elements}, the check above already | 2197 // in-bounds, otherwise for holey {elements}, the check above already |
| 2946 // guards the index (and the operator forces {index} to be unsigned). | 2198 // guards the index (and the operator forces {index} to be unsigned). |
| 2947 if (!(flags & GrowFastElementsFlag::kHoleyElements)) { | 2199 if (!(flags & GrowFastElementsFlag::kHoleyElements)) { |
| 2948 Node* check1 = | 2200 Node* check1 = __ Uint32LessThan(index, length); |
| 2949 graph()->NewNode(machine()->Uint32LessThan(), index, length); | 2201 __ DeoptimizeUnless(DeoptimizeReason::kOutOfBounds, check1, frame_state); |
| 2950 efalse0 = if_false0 = graph()->NewNode( | |
| 2951 common()->DeoptimizeUnless(DeoptimizeReason::kOutOfBounds), check1, | |
| 2952 frame_state, efalse0, if_false0); | |
| 2953 } | 2202 } |
| 2954 } | 2203 __ Goto(&done, elements); |
| 2955 | 2204 } |
| 2956 control = graph()->NewNode(common()->Merge(2), if_true0, if_false0); | 2205 __ Bind(&done); |
| 2957 effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control); | 2206 return done.PhiAt(0); |
| 2958 Node* value = | 2207 } |
| 2959 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), vtrue0, | 2208 |
| 2960 vfalse0, control); | 2209 void EffectControlLinearizer::LowerTransitionElementsKind(Node* node) { |
| 2961 | |
| 2962 return ValueEffectControl(value, effect, control); | |
| 2963 } | |
| 2964 | |
| 2965 EffectControlLinearizer::ValueEffectControl | |
| 2966 EffectControlLinearizer::LowerTransitionElementsKind(Node* node, Node* effect, | |
| 2967 Node* control) { | |
| 2968 ElementsTransition const transition = ElementsTransitionOf(node->op()); | 2210 ElementsTransition const transition = ElementsTransitionOf(node->op()); |
| 2969 Node* object = node->InputAt(0); | 2211 Node* object = node->InputAt(0); |
| 2970 Node* source_map = node->InputAt(1); | 2212 Node* source_map = node->InputAt(1); |
| 2971 Node* target_map = node->InputAt(2); | 2213 Node* target_map = node->InputAt(2); |
| 2972 | 2214 |
| 2215 auto if_map_same = __ MakeDeferredLabel<1>(); |
| 2216 auto done = __ MakeLabel<2>(); |
| 2217 |
| 2973 // Load the current map of {object}. | 2218 // Load the current map of {object}. |
| 2974 Node* object_map = effect = | 2219 Node* object_map = __ LoadField(AccessBuilder::ForMap(), object); |
| 2975 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), object, | |
| 2976 effect, control); | |
| 2977 | 2220 |
| 2978 // Check if {object_map} is the same as {source_map}. | 2221 // Check if {object_map} is the same as {source_map}. |
| 2979 Node* check = | 2222 Node* check = __ WordEqual(object_map, source_map); |
| 2980 graph()->NewNode(machine()->WordEqual(), object_map, source_map); | 2223 __ GotoIf(check, &if_map_same); |
| 2981 Node* branch = | 2224 __ Goto(&done); |
| 2982 graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control); | 2225 |
| 2983 | 2226 __ Bind(&if_map_same); |
| 2984 // Migrate the {object} from {source_map} to {target_map}. | 2227 switch (transition) { |
| 2985 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); | 2228 case ElementsTransition::kFastTransition: |
| 2986 Node* etrue = effect; | 2229 // In-place migration of {object}, just store the {target_map}. |
| 2987 { | 2230 __ StoreField(AccessBuilder::ForMap(), object, target_map); |
| 2988 switch (transition) { | 2231 break; |
| 2989 case ElementsTransition::kFastTransition: { | 2232 case ElementsTransition::kSlowTransition: { |
| 2990 // In-place migration of {object}, just store the {target_map}. | 2233 // Instance migration, call out to the runtime for {object}. |
| 2991 etrue = | 2234 Operator::Properties properties = Operator::kNoDeopt | Operator::kNoThrow; |
| 2992 graph()->NewNode(simplified()->StoreField(AccessBuilder::ForMap()), | 2235 Runtime::FunctionId id = Runtime::kTransitionElementsKind; |
| 2993 object, target_map, etrue, if_true); | 2236 CallDescriptor const* desc = Linkage::GetRuntimeCallDescriptor( |
| 2994 break; | 2237 graph()->zone(), id, 2, properties, CallDescriptor::kNoFlags); |
| 2995 } | 2238 __ Call(desc, __ CEntryStubConstant(1), object, target_map, |
| 2996 case ElementsTransition::kSlowTransition: { | 2239 __ ExternalConstant(ExternalReference(id, isolate())), |
| 2997 // Instance migration, call out to the runtime for {object}. | 2240 __ Int32Constant(2), __ NoContextConstant()); |
| 2998 Operator::Properties properties = | 2241 break; |
| 2999 Operator::kNoDeopt | Operator::kNoThrow; | |
| 3000 Runtime::FunctionId id = Runtime::kTransitionElementsKind; | |
| 3001 CallDescriptor const* desc = Linkage::GetRuntimeCallDescriptor( | |
| 3002 graph()->zone(), id, 2, properties, CallDescriptor::kNoFlags); | |
| 3003 etrue = graph()->NewNode( | |
| 3004 common()->Call(desc), jsgraph()->CEntryStubConstant(1), object, | |
| 3005 target_map, | |
| 3006 jsgraph()->ExternalConstant(ExternalReference(id, isolate())), | |
| 3007 jsgraph()->Int32Constant(2), jsgraph()->NoContextConstant(), etrue, | |
| 3008 if_true); | |
| 3009 break; | |
| 3010 } | |
| 3011 } | 2242 } |
| 3012 } | 2243 } |
| 3013 | 2244 __ Goto(&done); |
| 3014 // Nothing to do if the {object} doesn't have the {source_map}. | 2245 |
| 3015 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); | 2246 __ Bind(&done); |
| 3016 Node* efalse = effect; | 2247 } |
| 3017 | 2248 |
| 3018 control = graph()->NewNode(common()->Merge(2), if_true, if_false); | 2249 Node* EffectControlLinearizer::LowerLoadTypedElement(Node* node) { |
| 3019 effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control); | |
| 3020 | |
| 3021 return ValueEffectControl(nullptr, effect, control); | |
| 3022 } | |
| 3023 | |
| 3024 EffectControlLinearizer::ValueEffectControl | |
| 3025 EffectControlLinearizer::LowerLoadTypedElement(Node* node, Node* effect, | |
| 3026 Node* control) { | |
| 3027 ExternalArrayType array_type = ExternalArrayTypeOf(node->op()); | 2250 ExternalArrayType array_type = ExternalArrayTypeOf(node->op()); |
| 3028 Node* buffer = node->InputAt(0); | 2251 Node* buffer = node->InputAt(0); |
| 3029 Node* base = node->InputAt(1); | 2252 Node* base = node->InputAt(1); |
| 3030 Node* external = node->InputAt(2); | 2253 Node* external = node->InputAt(2); |
| 3031 Node* index = node->InputAt(3); | 2254 Node* index = node->InputAt(3); |
| 3032 | 2255 |
| 3033 // We need to keep the {buffer} alive so that the GC will not release the | 2256 // We need to keep the {buffer} alive so that the GC will not release the |
| 3034 // ArrayBuffer (if there's any) as long as we are still operating on it. | 2257 // ArrayBuffer (if there's any) as long as we are still operating on it. |
| 3035 effect = graph()->NewNode(common()->Retain(), buffer, effect); | 2258 __ Retain(buffer); |
| 3036 | 2259 |
| 3037 // Compute the effective storage pointer, handling the case where the | 2260 // Compute the effective storage pointer, handling the case where the |
| 3038 // {external} pointer is the effective storage pointer (i.e. the {base} | 2261 // {external} pointer is the effective storage pointer (i.e. the {base} |
| 3039 // is Smi zero). | 2262 // is Smi zero). |
| 3040 Node* storage = | 2263 Node* storage = NumberMatcher(base).Is(0) ? external : __ UnsafePointerAdd( |
| 3041 NumberMatcher(base).Is(0) | 2264 base, external); |
| 3042 ? external | |
| 3043 : effect = graph()->NewNode(machine()->UnsafePointerAdd(), base, | |
| 3044 external, effect, control); | |
| 3045 | 2265 |
| 3046 // Perform the actual typed element access. | 2266 // Perform the actual typed element access. |
| 3047 Node* value = effect = graph()->NewNode( | 2267 return __ LoadElement(AccessBuilder::ForTypedArrayElement(array_type, true), |
| 3048 simplified()->LoadElement( | 2268 storage, index); |
| 3049 AccessBuilder::ForTypedArrayElement(array_type, true)), | |
| 3050 storage, index, effect, control); | |
| 3051 | |
| 3052 return ValueEffectControl(value, effect, control); | |
| 3053 } | 2269 } |
| 3054 | 2270 |
| 3055 EffectControlLinearizer::ValueEffectControl | 2271 void EffectControlLinearizer::LowerStoreTypedElement(Node* node) { |
| 3056 EffectControlLinearizer::LowerStoreTypedElement(Node* node, Node* effect, | |
| 3057 Node* control) { | |
| 3058 ExternalArrayType array_type = ExternalArrayTypeOf(node->op()); | 2272 ExternalArrayType array_type = ExternalArrayTypeOf(node->op()); |
| 3059 Node* buffer = node->InputAt(0); | 2273 Node* buffer = node->InputAt(0); |
| 3060 Node* base = node->InputAt(1); | 2274 Node* base = node->InputAt(1); |
| 3061 Node* external = node->InputAt(2); | 2275 Node* external = node->InputAt(2); |
| 3062 Node* index = node->InputAt(3); | 2276 Node* index = node->InputAt(3); |
| 3063 Node* value = node->InputAt(4); | 2277 Node* value = node->InputAt(4); |
| 3064 | 2278 |
| 3065 // We need to keep the {buffer} alive so that the GC will not release the | 2279 // We need to keep the {buffer} alive so that the GC will not release the |
| 3066 // ArrayBuffer (if there's any) as long as we are still operating on it. | 2280 // ArrayBuffer (if there's any) as long as we are still operating on it. |
| 3067 effect = graph()->NewNode(common()->Retain(), buffer, effect); | 2281 __ Retain(buffer); |
| 3068 | 2282 |
| 3069 // Compute the effective storage pointer, handling the case where the | 2283 // Compute the effective storage pointer, handling the case where the |
| 3070 // {external} pointer is the effective storage pointer (i.e. the {base} | 2284 // {external} pointer is the effective storage pointer (i.e. the {base} |
| 3071 // is Smi zero). | 2285 // is Smi zero). |
| 3072 Node* storage = | 2286 Node* storage = NumberMatcher(base).Is(0) ? external : __ UnsafePointerAdd( |
| 3073 NumberMatcher(base).Is(0) | 2287 base, external); |
| 3074 ? external | |
| 3075 : effect = graph()->NewNode(machine()->UnsafePointerAdd(), base, | |
| 3076 external, effect, control); | |
| 3077 | 2288 |
| 3078 // Perform the actual typed element access. | 2289 // Perform the actual typed element access. |
| 3079 effect = graph()->NewNode( | 2290 __ StoreElement(AccessBuilder::ForTypedArrayElement(array_type, true), |
| 3080 simplified()->StoreElement( | 2291 storage, index, value); |
| 3081 AccessBuilder::ForTypedArrayElement(array_type, true)), | |
| 3082 storage, index, value, effect, control); | |
| 3083 | |
| 3084 return ValueEffectControl(nullptr, effect, control); | |
| 3085 } | 2292 } |
| 3086 | 2293 |
| 3087 EffectControlLinearizer::ValueEffectControl | 2294 Maybe<Node*> EffectControlLinearizer::LowerFloat64RoundUp(Node* node) { |
| 3088 EffectControlLinearizer::LowerFloat64RoundUp(Node* node, Node* effect, | |
| 3089 Node* control) { | |
| 3090 // Nothing to be done if a fast hardware instruction is available. | 2295 // Nothing to be done if a fast hardware instruction is available. |
| 3091 if (machine()->Float64RoundUp().IsSupported()) { | 2296 if (machine()->Float64RoundUp().IsSupported()) { |
| 3092 return ValueEffectControl(node, effect, control); | 2297 return Nothing<Node*>(); |
| 3093 } | 2298 } |
| 3094 | 2299 |
| 3095 Node* const one = jsgraph()->Float64Constant(1.0); | |
| 3096 Node* const zero = jsgraph()->Float64Constant(0.0); | |
| 3097 Node* const minus_zero = jsgraph()->Float64Constant(-0.0); | |
| 3098 Node* const two_52 = jsgraph()->Float64Constant(4503599627370496.0E0); | |
| 3099 Node* const minus_two_52 = jsgraph()->Float64Constant(-4503599627370496.0E0); | |
| 3100 Node* const input = node->InputAt(0); | 2300 Node* const input = node->InputAt(0); |
| 3101 | 2301 |
| 3102 // General case for ceil. | 2302 // General case for ceil. |
| 3103 // | 2303 // |
| 3104 // if 0.0 < input then | 2304 // if 0.0 < input then |
| 3105 // if 2^52 <= input then | 2305 // if 2^52 <= input then |
| 3106 // input | 2306 // input |
| 3107 // else | 2307 // else |
| 3108 // let temp1 = (2^52 + input) - 2^52 in | 2308 // let temp1 = (2^52 + input) - 2^52 in |
| 3109 // if temp1 < input then | 2309 // if temp1 < input then |
| 3110 // temp1 + 1 | 2310 // temp1 + 1 |
| 3111 // else | 2311 // else |
| 3112 // temp1 | 2312 // temp1 |
| 3113 // else | 2313 // else |
| 3114 // if input == 0 then | 2314 // if input == 0 then |
| 3115 // input | 2315 // input |
| 3116 // else | 2316 // else |
| 3117 // if input <= -2^52 then | 2317 // if input <= -2^52 then |
| 3118 // input | 2318 // input |
| 3119 // else | 2319 // else |
| 3120 // let temp1 = -0 - input in | 2320 // let temp1 = -0 - input in |
| 3121 // let temp2 = (2^52 + temp1) - 2^52 in | 2321 // let temp2 = (2^52 + temp1) - 2^52 in |
| 3122 // let temp3 = (if temp1 < temp2 then temp2 - 1 else temp2) in | 2322 // let temp3 = (if temp1 < temp2 then temp2 - 1 else temp2) in |
| 3123 // -0 - temp3 | 2323 // -0 - temp3 |
| 3124 // | |
| 3125 // Note: We do not use the Diamond helper class here, because it really hurts | |
| 3126 // readability with nested diamonds. | |
| 3127 | 2324 |
| 3128 Node* check0 = graph()->NewNode(machine()->Float64LessThan(), zero, input); | 2325 auto if_not_positive = __ MakeDeferredLabel<1>(); |
| 3129 Node* branch0 = | 2326 auto if_greater_than_two_52 = __ MakeDeferredLabel<1>(); |
| 3130 graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control); | 2327 auto if_less_than_minus_two_52 = __ MakeDeferredLabel<1>(); |
| 2328 auto if_zero = __ MakeDeferredLabel<1>(); |
| 2329 auto done_temp3 = __ MakeLabel<2>(MachineRepresentation::kFloat64); |
| 2330 auto done = __ MakeLabel<6>(MachineRepresentation::kFloat64); |
| 3131 | 2331 |
| 3132 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0); | 2332 Node* const zero = __ Float64Constant(0.0); |
| 3133 Node* vtrue0; | 2333 Node* const two_52 = __ Float64Constant(4503599627370496.0E0); |
| 2334 Node* const one = __ Float64Constant(1.0); |
| 2335 |
| 2336 Node* check0 = __ Float64LessThan(zero, input); |
| 2337 __ GotoUnless(check0, &if_not_positive); |
| 3134 { | 2338 { |
| 3135 Node* check1 = | 2339 Node* check1 = __ Float64LessThanOrEqual(two_52, input); |
| 3136 graph()->NewNode(machine()->Float64LessThanOrEqual(), two_52, input); | 2340 __ GotoIf(check1, &if_greater_than_two_52); |
| 3137 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_true0); | |
| 3138 | |
| 3139 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); | |
| 3140 Node* vtrue1 = input; | |
| 3141 | |
| 3142 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); | |
| 3143 Node* vfalse1; | |
| 3144 { | 2341 { |
| 3145 Node* temp1 = graph()->NewNode( | 2342 Node* temp1 = __ Float64Sub(__ Float64Add(two_52, input), two_52); |
| 3146 machine()->Float64Sub(), | 2343 __ GotoUnless(__ Float64LessThan(temp1, input), &done, temp1); |
| 3147 graph()->NewNode(machine()->Float64Add(), two_52, input), two_52); | 2344 __ Goto(&done, __ Float64Add(temp1, one)); |
| 3148 vfalse1 = graph()->NewNode( | |
| 3149 common()->Select(MachineRepresentation::kFloat64), | |
| 3150 graph()->NewNode(machine()->Float64LessThan(), temp1, input), | |
| 3151 graph()->NewNode(machine()->Float64Add(), temp1, one), temp1); | |
| 3152 } | 2345 } |
| 3153 | 2346 |
| 3154 if_true0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1); | 2347 __ Bind(&if_greater_than_two_52); |
| 3155 vtrue0 = graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2), | 2348 __ Goto(&done, input); |
| 3156 vtrue1, vfalse1, if_true0); | |
| 3157 } | 2349 } |
| 3158 | 2350 |
| 3159 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0); | 2351 __ Bind(&if_not_positive); |
| 3160 Node* vfalse0; | |
| 3161 { | 2352 { |
| 3162 Node* check1 = graph()->NewNode(machine()->Float64Equal(), input, zero); | 2353 Node* check1 = __ Float64Equal(input, zero); |
| 3163 Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kFalse), | 2354 __ GotoIf(check1, &if_zero); |
| 3164 check1, if_false0); | |
| 3165 | 2355 |
| 3166 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); | 2356 Node* const minus_two_52 = __ Float64Constant(-4503599627370496.0E0); |
| 3167 Node* vtrue1 = input; | 2357 Node* check2 = __ Float64LessThanOrEqual(input, minus_two_52); |
| 2358 __ GotoIf(check2, &if_less_than_minus_two_52); |
| 3168 | 2359 |
| 3169 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); | |
| 3170 Node* vfalse1; | |
| 3171 { | 2360 { |
| 3172 Node* check2 = graph()->NewNode(machine()->Float64LessThanOrEqual(), | 2361 Node* const minus_zero = __ Float64Constant(-0.0); |
| 3173 input, minus_two_52); | 2362 Node* temp1 = __ Float64Sub(minus_zero, input); |
| 3174 Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kFalse), | 2363 Node* temp2 = __ Float64Sub(__ Float64Add(two_52, temp1), two_52); |
| 3175 check2, if_false1); | 2364 Node* check3 = __ Float64LessThan(temp1, temp2); |
| 2365 __ GotoUnless(check3, &done_temp3, temp2); |
| 2366 __ Goto(&done_temp3, __ Float64Sub(temp2, one)); |
| 3176 | 2367 |
| 3177 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2); | 2368 __ Bind(&done_temp3); |
| 3178 Node* vtrue2 = input; | 2369 Node* temp3 = done_temp3.PhiAt(0); |
| 2370 __ Goto(&done, __ Float64Sub(minus_zero, temp3)); |
| 2371 } |
| 2372 __ Bind(&if_less_than_minus_two_52); |
| 2373 __ Goto(&done, input); |
| 3179 | 2374 |
| 3180 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2); | 2375 __ Bind(&if_zero); |
| 3181 Node* vfalse2; | 2376 __ Goto(&done, input); |
| 3182 { | 2377 } |
| 3183 Node* temp1 = | 2378 __ Bind(&done); |
| 3184 graph()->NewNode(machine()->Float64Sub(), minus_zero, input); | 2379 return Just(done.PhiAt(0)); |
| 3185 Node* temp2 = graph()->NewNode( | 2380 } |
| 3186 machine()->Float64Sub(), | |
| 3187 graph()->NewNode(machine()->Float64Add(), two_52, temp1), two_52); | |
| 3188 Node* temp3 = graph()->NewNode( | |
| 3189 common()->Select(MachineRepresentation::kFloat64), | |
| 3190 graph()->NewNode(machine()->Float64LessThan(), temp1, temp2), | |
| 3191 graph()->NewNode(machine()->Float64Sub(), temp2, one), temp2); | |
| 3192 vfalse2 = graph()->NewNode(machine()->Float64Sub(), minus_zero, temp3); | |
| 3193 } | |
| 3194 | 2381 |
| 3195 if_false1 = graph()->NewNode(common()->Merge(2), if_true2, if_false2); | 2382 Node* EffectControlLinearizer::BuildFloat64RoundDown(Node* value) { |
| 3196 vfalse1 = | 2383 Node* round_down = __ Float64RoundDown(value); |
| 3197 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2), | 2384 if (round_down != nullptr) { |
| 3198 vtrue2, vfalse2, if_false1); | 2385 return round_down; |
| 2386 } |
| 2387 |
| 2388 Node* const input = value; |
| 2389 |
| 2390 // General case for floor. |
| 2391 // |
| 2392 // if 0.0 < input then |
| 2393 // if 2^52 <= input then |
| 2394 // input |
| 2395 // else |
| 2396 // let temp1 = (2^52 + input) - 2^52 in |
| 2397 // if input < temp1 then |
| 2398 // temp1 - 1 |
| 2399 // else |
| 2400 // temp1 |
| 2401 // else |
| 2402 // if input == 0 then |
| 2403 // input |
| 2404 // else |
| 2405 // if input <= -2^52 then |
| 2406 // input |
| 2407 // else |
| 2408 // let temp1 = -0 - input in |
| 2409 // let temp2 = (2^52 + temp1) - 2^52 in |
| 2410 // if temp2 < temp1 then |
| 2411 // -1 - temp2 |
| 2412 // else |
| 2413 // -0 - temp2 |
| 2414 |
| 2415 auto if_not_positive = __ MakeDeferredLabel<1>(); |
| 2416 auto if_greater_than_two_52 = __ MakeDeferredLabel<1>(); |
| 2417 auto if_less_than_minus_two_52 = __ MakeDeferredLabel<1>(); |
| 2418 auto if_temp2_lt_temp1 = __ MakeLabel<1>(); |
| 2419 auto if_zero = __ MakeDeferredLabel<1>(); |
| 2420 auto done = __ MakeLabel<7>(MachineRepresentation::kFloat64); |
| 2421 |
| 2422 Node* const zero = __ Float64Constant(0.0); |
| 2423 Node* const two_52 = __ Float64Constant(4503599627370496.0E0); |
| 2424 |
| 2425 Node* check0 = __ Float64LessThan(zero, input); |
| 2426 __ GotoUnless(check0, &if_not_positive); |
| 2427 { |
| 2428 Node* check1 = __ Float64LessThanOrEqual(two_52, input); |
| 2429 __ GotoIf(check1, &if_greater_than_two_52); |
| 2430 { |
| 2431 Node* const one = __ Float64Constant(1.0); |
| 2432 Node* temp1 = __ Float64Sub(__ Float64Add(two_52, input), two_52); |
| 2433 __ GotoUnless(__ Float64LessThan(input, temp1), &done, temp1); |
| 2434 __ Goto(&done, __ Float64Sub(temp1, one)); |
| 3199 } | 2435 } |
| 3200 | 2436 |
| 3201 if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1); | 2437 __ Bind(&if_greater_than_two_52); |
| 3202 vfalse0 = | 2438 __ Goto(&done, input); |
| 3203 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2), | |
| 3204 vtrue1, vfalse1, if_false0); | |
| 3205 } | 2439 } |
| 3206 | 2440 |
| 3207 Node* merge0 = graph()->NewNode(common()->Merge(2), if_true0, if_false0); | 2441 __ Bind(&if_not_positive); |
| 3208 Node* value = | 2442 { |
| 3209 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2), | 2443 Node* check1 = __ Float64Equal(input, zero); |
| 3210 vtrue0, vfalse0, merge0); | 2444 __ GotoIf(check1, &if_zero); |
| 3211 return ValueEffectControl(value, effect, merge0); | 2445 |
| 2446 Node* const minus_two_52 = __ Float64Constant(-4503599627370496.0E0); |
| 2447 Node* check2 = __ Float64LessThanOrEqual(input, minus_two_52); |
| 2448 __ GotoIf(check2, &if_less_than_minus_two_52); |
| 2449 |
| 2450 { |
| 2451 Node* const minus_zero = __ Float64Constant(-0.0); |
| 2452 Node* temp1 = __ Float64Sub(minus_zero, input); |
| 2453 Node* temp2 = __ Float64Sub(__ Float64Add(two_52, temp1), two_52); |
| 2454 Node* check3 = __ Float64LessThan(temp2, temp1); |
| 2455 __ GotoIf(check3, &if_temp2_lt_temp1); |
| 2456 __ Goto(&done, __ Float64Sub(minus_zero, temp2)); |
| 2457 |
| 2458 __ Bind(&if_temp2_lt_temp1); |
| 2459 __ Goto(&done, __ Float64Sub(__ Float64Constant(-1.0), temp2)); |
| 2460 } |
| 2461 __ Bind(&if_less_than_minus_two_52); |
| 2462 __ Goto(&done, input); |
| 2463 |
| 2464 __ Bind(&if_zero); |
| 2465 __ Goto(&done, input); |
| 2466 } |
| 2467 __ Bind(&done); |
| 2468 return done.PhiAt(0); |
| 3212 } | 2469 } |
| 3213 | 2470 |
| 3214 EffectControlLinearizer::ValueEffectControl | 2471 Maybe<Node*> EffectControlLinearizer::LowerFloat64RoundDown(Node* node) { |
| 3215 EffectControlLinearizer::BuildFloat64RoundDown(Node* value, Node* effect, | |
| 3216 Node* control) { | |
| 3217 if (machine()->Float64RoundDown().IsSupported()) { | |
| 3218 value = graph()->NewNode(machine()->Float64RoundDown().op(), value); | |
| 3219 } else { | |
| 3220 Node* const one = jsgraph()->Float64Constant(1.0); | |
| 3221 Node* const zero = jsgraph()->Float64Constant(0.0); | |
| 3222 Node* const minus_one = jsgraph()->Float64Constant(-1.0); | |
| 3223 Node* const minus_zero = jsgraph()->Float64Constant(-0.0); | |
| 3224 Node* const two_52 = jsgraph()->Float64Constant(4503599627370496.0E0); | |
| 3225 Node* const minus_two_52 = | |
| 3226 jsgraph()->Float64Constant(-4503599627370496.0E0); | |
| 3227 Node* const input = value; | |
| 3228 | |
| 3229 // General case for floor. | |
| 3230 // | |
| 3231 // if 0.0 < input then | |
| 3232 // if 2^52 <= input then | |
| 3233 // input | |
| 3234 // else | |
| 3235 // let temp1 = (2^52 + input) - 2^52 in | |
| 3236 // if input < temp1 then | |
| 3237 // temp1 - 1 | |
| 3238 // else | |
| 3239 // temp1 | |
| 3240 // else | |
| 3241 // if input == 0 then | |
| 3242 // input | |
| 3243 // else | |
| 3244 // if input <= -2^52 then | |
| 3245 // input | |
| 3246 // else | |
| 3247 // let temp1 = -0 - input in | |
| 3248 // let temp2 = (2^52 + temp1) - 2^52 in | |
| 3249 // if temp2 < temp1 then | |
| 3250 // -1 - temp2 | |
| 3251 // else | |
| 3252 // -0 - temp2 | |
| 3253 // | |
| 3254 // Note: We do not use the Diamond helper class here, because it really | |
| 3255 // hurts | |
| 3256 // readability with nested diamonds. | |
| 3257 | |
| 3258 Node* check0 = graph()->NewNode(machine()->Float64LessThan(), zero, input); | |
| 3259 Node* branch0 = | |
| 3260 graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control); | |
| 3261 | |
| 3262 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0); | |
| 3263 Node* vtrue0; | |
| 3264 { | |
| 3265 Node* check1 = | |
| 3266 graph()->NewNode(machine()->Float64LessThanOrEqual(), two_52, input); | |
| 3267 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_true0); | |
| 3268 | |
| 3269 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); | |
| 3270 Node* vtrue1 = input; | |
| 3271 | |
| 3272 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); | |
| 3273 Node* vfalse1; | |
| 3274 { | |
| 3275 Node* temp1 = graph()->NewNode( | |
| 3276 machine()->Float64Sub(), | |
| 3277 graph()->NewNode(machine()->Float64Add(), two_52, input), two_52); | |
| 3278 vfalse1 = graph()->NewNode( | |
| 3279 common()->Select(MachineRepresentation::kFloat64), | |
| 3280 graph()->NewNode(machine()->Float64LessThan(), input, temp1), | |
| 3281 graph()->NewNode(machine()->Float64Sub(), temp1, one), temp1); | |
| 3282 } | |
| 3283 | |
| 3284 if_true0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1); | |
| 3285 vtrue0 = | |
| 3286 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2), | |
| 3287 vtrue1, vfalse1, if_true0); | |
| 3288 } | |
| 3289 | |
| 3290 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0); | |
| 3291 Node* vfalse0; | |
| 3292 { | |
| 3293 Node* check1 = graph()->NewNode(machine()->Float64Equal(), input, zero); | |
| 3294 Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kFalse), | |
| 3295 check1, if_false0); | |
| 3296 | |
| 3297 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); | |
| 3298 Node* vtrue1 = input; | |
| 3299 | |
| 3300 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); | |
| 3301 Node* vfalse1; | |
| 3302 { | |
| 3303 Node* check2 = graph()->NewNode(machine()->Float64LessThanOrEqual(), | |
| 3304 input, minus_two_52); | |
| 3305 Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kFalse), | |
| 3306 check2, if_false1); | |
| 3307 | |
| 3308 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2); | |
| 3309 Node* vtrue2 = input; | |
| 3310 | |
| 3311 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2); | |
| 3312 Node* vfalse2; | |
| 3313 { | |
| 3314 Node* temp1 = | |
| 3315 graph()->NewNode(machine()->Float64Sub(), minus_zero, input); | |
| 3316 Node* temp2 = graph()->NewNode( | |
| 3317 machine()->Float64Sub(), | |
| 3318 graph()->NewNode(machine()->Float64Add(), two_52, temp1), two_52); | |
| 3319 vfalse2 = graph()->NewNode( | |
| 3320 common()->Select(MachineRepresentation::kFloat64), | |
| 3321 graph()->NewNode(machine()->Float64LessThan(), temp2, temp1), | |
| 3322 graph()->NewNode(machine()->Float64Sub(), minus_one, temp2), | |
| 3323 graph()->NewNode(machine()->Float64Sub(), minus_zero, temp2)); | |
| 3324 } | |
| 3325 | |
| 3326 if_false1 = graph()->NewNode(common()->Merge(2), if_true2, if_false2); | |
| 3327 vfalse1 = | |
| 3328 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2), | |
| 3329 vtrue2, vfalse2, if_false1); | |
| 3330 } | |
| 3331 | |
| 3332 if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1); | |
| 3333 vfalse0 = | |
| 3334 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2), | |
| 3335 vtrue1, vfalse1, if_false0); | |
| 3336 } | |
| 3337 | |
| 3338 control = graph()->NewNode(common()->Merge(2), if_true0, if_false0); | |
| 3339 value = graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2), | |
| 3340 vtrue0, vfalse0, control); | |
| 3341 } | |
| 3342 return ValueEffectControl(value, effect, control); | |
| 3343 } | |
| 3344 | |
| 3345 EffectControlLinearizer::ValueEffectControl | |
| 3346 EffectControlLinearizer::LowerFloat64RoundDown(Node* node, Node* effect, | |
| 3347 Node* control) { | |
| 3348 // Nothing to be done if a fast hardware instruction is available. | 2472 // Nothing to be done if a fast hardware instruction is available. |
| 3349 if (machine()->Float64RoundDown().IsSupported()) { | 2473 if (machine()->Float64RoundDown().IsSupported()) { |
| 3350 return ValueEffectControl(node, effect, control); | 2474 return Nothing<Node*>(); |
| 3351 } | 2475 } |
| 3352 | 2476 |
| 3353 Node* const input = node->InputAt(0); | 2477 Node* const input = node->InputAt(0); |
| 3354 return BuildFloat64RoundDown(input, effect, control); | 2478 return Just(BuildFloat64RoundDown(input)); |
| 3355 } | 2479 } |
| 3356 | 2480 |
| 3357 EffectControlLinearizer::ValueEffectControl | 2481 Maybe<Node*> EffectControlLinearizer::LowerFloat64RoundTiesEven(Node* node) { |
| 3358 EffectControlLinearizer::LowerFloat64RoundTiesEven(Node* node, Node* effect, | |
| 3359 Node* control) { | |
| 3360 // Nothing to be done if a fast hardware instruction is available. | 2482 // Nothing to be done if a fast hardware instruction is available. |
| 3361 if (machine()->Float64RoundTiesEven().IsSupported()) { | 2483 if (machine()->Float64RoundTiesEven().IsSupported()) { |
| 3362 return ValueEffectControl(node, effect, control); | 2484 return Nothing<Node*>(); |
| 3363 } | 2485 } |
| 3364 | 2486 |
| 3365 Node* const one = jsgraph()->Float64Constant(1.0); | |
| 3366 Node* const two = jsgraph()->Float64Constant(2.0); | |
| 3367 Node* const half = jsgraph()->Float64Constant(0.5); | |
| 3368 Node* const zero = jsgraph()->Float64Constant(0.0); | |
| 3369 Node* const input = node->InputAt(0); | 2487 Node* const input = node->InputAt(0); |
| 3370 | 2488 |
| 3371 // Generate case for round ties to even: | 2489 // Generate case for round ties to even: |
| 3372 // | 2490 // |
| 3373 // let value = floor(input) in | 2491 // let value = floor(input) in |
| 3374 // let temp1 = input - value in | 2492 // let temp1 = input - value in |
| 3375 // if temp1 < 0.5 then | 2493 // if temp1 < 0.5 then |
| 3376 // value | 2494 // value |
| 3377 // else if 0.5 < temp1 then | 2495 // else if 0.5 < temp1 then |
| 3378 // value + 1.0 | 2496 // value + 1.0 |
| 3379 // else | 2497 // else |
| 3380 // let temp2 = value % 2.0 in | 2498 // let temp2 = value % 2.0 in |
| 3381 // if temp2 == 0.0 then | 2499 // if temp2 == 0.0 then |
| 3382 // value | 2500 // value |
| 3383 // else | 2501 // else |
| 3384 // value + 1.0 | 2502 // value + 1.0 |
| 3385 // | |
| 3386 // Note: We do not use the Diamond helper class here, because it really hurts | |
| 3387 // readability with nested diamonds. | |
| 3388 | 2503 |
| 3389 ValueEffectControl continuation = | 2504 auto if_is_half = __ MakeLabel<1>(); |
| 3390 BuildFloat64RoundDown(input, effect, control); | 2505 auto done = __ MakeLabel<4>(MachineRepresentation::kFloat64); |
| 3391 Node* value = continuation.value; | |
| 3392 effect = continuation.effect; | |
| 3393 control = continuation.control; | |
| 3394 | 2506 |
| 3395 Node* temp1 = graph()->NewNode(machine()->Float64Sub(), input, value); | 2507 Node* value = BuildFloat64RoundDown(input); |
| 2508 Node* temp1 = __ Float64Sub(input, value); |
| 3396 | 2509 |
| 3397 Node* check0 = graph()->NewNode(machine()->Float64LessThan(), temp1, half); | 2510 Node* const half = __ Float64Constant(0.5); |
| 3398 Node* branch0 = graph()->NewNode(common()->Branch(), check0, control); | 2511 Node* check0 = __ Float64LessThan(temp1, half); |
| 2512 __ GotoIf(check0, &done, value); |
| 3399 | 2513 |
| 3400 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0); | 2514 Node* const one = __ Float64Constant(1.0); |
| 3401 Node* vtrue0 = value; | 2515 Node* check1 = __ Float64LessThan(half, temp1); |
| 2516 __ GotoUnless(check1, &if_is_half); |
| 2517 __ Goto(&done, __ Float64Add(value, one)); |
| 3402 | 2518 |
| 3403 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0); | 2519 __ Bind(&if_is_half); |
| 3404 Node* vfalse0; | 2520 Node* temp2 = __ Float64Mod(value, __ Float64Constant(2.0)); |
| 3405 { | 2521 Node* check2 = __ Float64Equal(temp2, __ Float64Constant(0.0)); |
| 3406 Node* check1 = graph()->NewNode(machine()->Float64LessThan(), half, temp1); | 2522 __ GotoIf(check2, &done, value); |
| 3407 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0); | 2523 __ Goto(&done, __ Float64Add(value, one)); |
| 3408 | 2524 |
| 3409 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); | 2525 __ Bind(&done); |
| 3410 Node* vtrue1 = graph()->NewNode(machine()->Float64Add(), value, one); | 2526 return Just(done.PhiAt(0)); |
| 2527 } |
| 3411 | 2528 |
| 3412 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); | 2529 Maybe<Node*> EffectControlLinearizer::LowerFloat64RoundTruncate(Node* node) { |
| 3413 Node* vfalse1; | 2530 // Nothing to be done if a fast hardware instruction is available. |
| 3414 { | 2531 if (machine()->Float64RoundTruncate().IsSupported()) { |
| 3415 Node* temp2 = graph()->NewNode(machine()->Float64Mod(), value, two); | 2532 return Nothing<Node*>(); |
| 3416 | |
| 3417 Node* check2 = graph()->NewNode(machine()->Float64Equal(), temp2, zero); | |
| 3418 Node* branch2 = graph()->NewNode(common()->Branch(), check2, if_false1); | |
| 3419 | |
| 3420 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2); | |
| 3421 Node* vtrue2 = value; | |
| 3422 | |
| 3423 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2); | |
| 3424 Node* vfalse2 = graph()->NewNode(machine()->Float64Add(), value, one); | |
| 3425 | |
| 3426 if_false1 = graph()->NewNode(common()->Merge(2), if_true2, if_false2); | |
| 3427 vfalse1 = | |
| 3428 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2), | |
| 3429 vtrue2, vfalse2, if_false1); | |
| 3430 } | |
| 3431 | |
| 3432 if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1); | |
| 3433 vfalse0 = | |
| 3434 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2), | |
| 3435 vtrue1, vfalse1, if_false0); | |
| 3436 } | 2533 } |
| 3437 | 2534 |
| 3438 control = graph()->NewNode(common()->Merge(2), if_true0, if_false0); | |
| 3439 value = graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2), | |
| 3440 vtrue0, vfalse0, control); | |
| 3441 | |
| 3442 return ValueEffectControl(value, effect, control); | |
| 3443 } | |
| 3444 | |
| 3445 EffectControlLinearizer::ValueEffectControl | |
| 3446 EffectControlLinearizer::LowerFloat64RoundTruncate(Node* node, Node* effect, | |
| 3447 Node* control) { | |
| 3448 // Nothing to be done if a fast hardware instruction is available. | |
| 3449 if (machine()->Float64RoundTruncate().IsSupported()) { | |
| 3450 return ValueEffectControl(node, effect, control); | |
| 3451 } | |
| 3452 | |
| 3453 Node* const one = jsgraph()->Float64Constant(1.0); | |
| 3454 Node* const zero = jsgraph()->Float64Constant(0.0); | |
| 3455 Node* const minus_zero = jsgraph()->Float64Constant(-0.0); | |
| 3456 Node* const two_52 = jsgraph()->Float64Constant(4503599627370496.0E0); | |
| 3457 Node* const minus_two_52 = jsgraph()->Float64Constant(-4503599627370496.0E0); | |
| 3458 Node* const input = node->InputAt(0); | 2535 Node* const input = node->InputAt(0); |
| 3459 | 2536 |
| 3460 // General case for trunc. | 2537 // General case for trunc. |
| 3461 // | 2538 // |
| 3462 // if 0.0 < input then | 2539 // if 0.0 < input then |
| 3463 // if 2^52 <= input then | 2540 // if 2^52 <= input then |
| 3464 // input | 2541 // input |
| 3465 // else | 2542 // else |
| 3466 // let temp1 = (2^52 + input) - 2^52 in | 2543 // let temp1 = (2^52 + input) - 2^52 in |
| 3467 // if input < temp1 then | 2544 // if input < temp1 then |
| 3468 // temp1 - 1 | 2545 // temp1 - 1 |
| 3469 // else | 2546 // else |
| 3470 // temp1 | 2547 // temp1 |
| 3471 // else | 2548 // else |
| 3472 // if input == 0 then | 2549 // if input == 0 then |
| 3473 // input | 2550 // input |
| 3474 // else | 2551 // else |
| 3475 // if input <= -2^52 then | 2552 // if input <= -2^52 then |
| 3476 // input | 2553 // input |
| 3477 // else | 2554 // else |
| 3478 // let temp1 = -0 - input in | 2555 // let temp1 = -0 - input in |
| 3479 // let temp2 = (2^52 + temp1) - 2^52 in | 2556 // let temp2 = (2^52 + temp1) - 2^52 in |
| 3480 // let temp3 = (if temp1 < temp2 then temp2 - 1 else temp2) in | 2557 // let temp3 = (if temp1 < temp2 then temp2 - 1 else temp2) in |
| 3481 // -0 - temp3 | 2558 // -0 - temp3 |
| 3482 // | 2559 // |
| 3483 // Note: We do not use the Diamond helper class here, because it really hurts | 2560 // Note: We do not use the Diamond helper class here, because it really hurts |
| 3484 // readability with nested diamonds. | 2561 // readability with nested diamonds. |
| 3485 | 2562 |
| 3486 Node* check0 = graph()->NewNode(machine()->Float64LessThan(), zero, input); | 2563 auto if_not_positive = __ MakeDeferredLabel<1>(); |
| 3487 Node* branch0 = | 2564 auto if_greater_than_two_52 = __ MakeDeferredLabel<1>(); |
| 3488 graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control); | 2565 auto if_less_than_minus_two_52 = __ MakeDeferredLabel<1>(); |
| 2566 auto if_zero = __ MakeDeferredLabel<1>(); |
| 2567 auto done_temp3 = __ MakeLabel<2>(MachineRepresentation::kFloat64); |
| 2568 auto done = __ MakeLabel<6>(MachineRepresentation::kFloat64); |
| 3489 | 2569 |
| 3490 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0); | 2570 Node* const zero = __ Float64Constant(0.0); |
| 3491 Node* vtrue0; | 2571 Node* const two_52 = __ Float64Constant(4503599627370496.0E0); |
| 2572 Node* const one = __ Float64Constant(1.0); |
| 2573 |
| 2574 Node* check0 = __ Float64LessThan(zero, input); |
| 2575 __ GotoUnless(check0, &if_not_positive); |
| 3492 { | 2576 { |
| 3493 Node* check1 = | 2577 Node* check1 = __ Float64LessThanOrEqual(two_52, input); |
| 3494 graph()->NewNode(machine()->Float64LessThanOrEqual(), two_52, input); | 2578 __ GotoIf(check1, &if_greater_than_two_52); |
| 3495 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_true0); | |
| 3496 | |
| 3497 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); | |
| 3498 Node* vtrue1 = input; | |
| 3499 | |
| 3500 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); | |
| 3501 Node* vfalse1; | |
| 3502 { | 2579 { |
| 3503 Node* temp1 = graph()->NewNode( | 2580 Node* temp1 = __ Float64Sub(__ Float64Add(two_52, input), two_52); |
| 3504 machine()->Float64Sub(), | 2581 __ GotoUnless(__ Float64LessThan(input, temp1), &done, temp1); |
| 3505 graph()->NewNode(machine()->Float64Add(), two_52, input), two_52); | 2582 __ Goto(&done, __ Float64Sub(temp1, one)); |
| 3506 vfalse1 = graph()->NewNode( | |
| 3507 common()->Select(MachineRepresentation::kFloat64), | |
| 3508 graph()->NewNode(machine()->Float64LessThan(), input, temp1), | |
| 3509 graph()->NewNode(machine()->Float64Sub(), temp1, one), temp1); | |
| 3510 } | 2583 } |
| 3511 | 2584 |
| 3512 if_true0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1); | 2585 __ Bind(&if_greater_than_two_52); |
| 3513 vtrue0 = graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2), | 2586 __ Goto(&done, input); |
| 3514 vtrue1, vfalse1, if_true0); | |
| 3515 } | 2587 } |
| 3516 | 2588 |
| 3517 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0); | 2589 __ Bind(&if_not_positive); |
| 3518 Node* vfalse0; | |
| 3519 { | 2590 { |
| 3520 Node* check1 = graph()->NewNode(machine()->Float64Equal(), input, zero); | 2591 Node* check1 = __ Float64Equal(input, zero); |
| 3521 Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kFalse), | 2592 __ GotoIf(check1, &if_zero); |
| 3522 check1, if_false0); | |
| 3523 | 2593 |
| 3524 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); | 2594 Node* const minus_two_52 = __ Float64Constant(-4503599627370496.0E0); |
| 3525 Node* vtrue1 = input; | 2595 Node* check2 = __ Float64LessThanOrEqual(input, minus_two_52); |
| 2596 __ GotoIf(check2, &if_less_than_minus_two_52); |
| 3526 | 2597 |
| 3527 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); | |
| 3528 Node* vfalse1; | |
| 3529 { | 2598 { |
| 3530 Node* check2 = graph()->NewNode(machine()->Float64LessThanOrEqual(), | 2599 Node* const minus_zero = __ Float64Constant(-0.0); |
| 3531 input, minus_two_52); | 2600 Node* temp1 = __ Float64Sub(minus_zero, input); |
| 3532 Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kFalse), | 2601 Node* temp2 = __ Float64Sub(__ Float64Add(two_52, temp1), two_52); |
| 3533 check2, if_false1); | 2602 Node* check3 = __ Float64LessThan(temp1, temp2); |
| 2603 __ GotoUnless(check3, &done_temp3, temp2); |
| 2604 __ Goto(&done_temp3, __ Float64Sub(temp2, one)); |
| 3534 | 2605 |
| 3535 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2); | 2606 __ Bind(&done_temp3); |
| 3536 Node* vtrue2 = input; | 2607 Node* temp3 = done_temp3.PhiAt(0); |
| 2608 __ Goto(&done, __ Float64Sub(minus_zero, temp3)); |
| 2609 } |
| 2610 __ Bind(&if_less_than_minus_two_52); |
| 2611 __ Goto(&done, input); |
| 3537 | 2612 |
| 3538 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2); | 2613 __ Bind(&if_zero); |
| 3539 Node* vfalse2; | 2614 __ Goto(&done, input); |
| 3540 { | 2615 } |
| 3541 Node* temp1 = | 2616 __ Bind(&done); |
| 3542 graph()->NewNode(machine()->Float64Sub(), minus_zero, input); | 2617 return Just(done.PhiAt(0)); |
| 3543 Node* temp2 = graph()->NewNode( | 2618 } |
| 3544 machine()->Float64Sub(), | |
| 3545 graph()->NewNode(machine()->Float64Add(), two_52, temp1), two_52); | |
| 3546 Node* temp3 = graph()->NewNode( | |
| 3547 common()->Select(MachineRepresentation::kFloat64), | |
| 3548 graph()->NewNode(machine()->Float64LessThan(), temp1, temp2), | |
| 3549 graph()->NewNode(machine()->Float64Sub(), temp2, one), temp2); | |
| 3550 vfalse2 = graph()->NewNode(machine()->Float64Sub(), minus_zero, temp3); | |
| 3551 } | |
| 3552 | 2619 |
| 3553 if_false1 = graph()->NewNode(common()->Merge(2), if_true2, if_false2); | 2620 #undef __ |
| 3554 vfalse1 = | |
| 3555 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2), | |
| 3556 vtrue2, vfalse2, if_false1); | |
| 3557 } | |
| 3558 | |
| 3559 if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1); | |
| 3560 vfalse0 = | |
| 3561 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2), | |
| 3562 vtrue1, vfalse1, if_false0); | |
| 3563 } | |
| 3564 | |
| 3565 Node* merge0 = graph()->NewNode(common()->Merge(2), if_true0, if_false0); | |
| 3566 Node* value = | |
| 3567 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2), | |
| 3568 vtrue0, vfalse0, merge0); | |
| 3569 return ValueEffectControl(value, effect, merge0); | |
| 3570 } | |
| 3571 | 2621 |
| 3572 Factory* EffectControlLinearizer::factory() const { | 2622 Factory* EffectControlLinearizer::factory() const { |
| 3573 return isolate()->factory(); | 2623 return isolate()->factory(); |
| 3574 } | 2624 } |
| 3575 | 2625 |
| 3576 Isolate* EffectControlLinearizer::isolate() const { | 2626 Isolate* EffectControlLinearizer::isolate() const { |
| 3577 return jsgraph()->isolate(); | 2627 return jsgraph()->isolate(); |
| 3578 } | 2628 } |
| 3579 | 2629 |
| 3580 Operator const* EffectControlLinearizer::ToNumberOperator() { | |
| 3581 if (!to_number_operator_.is_set()) { | |
| 3582 Callable callable = CodeFactory::ToNumber(isolate()); | |
| 3583 CallDescriptor::Flags flags = CallDescriptor::kNoFlags; | |
| 3584 CallDescriptor* desc = Linkage::GetStubCallDescriptor( | |
| 3585 isolate(), graph()->zone(), callable.descriptor(), 0, flags, | |
| 3586 Operator::kEliminatable); | |
| 3587 to_number_operator_.set(common()->Call(desc)); | |
| 3588 } | |
| 3589 return to_number_operator_.get(); | |
| 3590 } | |
| 3591 | |
| 3592 } // namespace compiler | 2630 } // namespace compiler |
| 3593 } // namespace internal | 2631 } // namespace internal |
| 3594 } // namespace v8 | 2632 } // namespace v8 |
| OLD | NEW |