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 |