OLD | NEW |
1 | 1 |
2 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 2 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
3 // for details. All rights reserved. Use of this source code is governed by a | 3 // for details. All rights reserved. Use of this source code is governed by a |
4 // BSD-style license that can be found in the LICENSE file. | 4 // BSD-style license that can be found in the LICENSE file. |
5 | 5 |
6 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. | 6 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. |
7 #if defined(TARGET_ARCH_ARM) | 7 #if defined(TARGET_ARCH_ARM) |
8 | 8 |
9 #include "vm/intermediate_language.h" | 9 #include "vm/intermediate_language.h" |
10 | 10 |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
163 const Register result = locs()->out(0).reg(); | 163 const Register result = locs()->out(0).reg(); |
164 | 164 |
165 Location left = locs()->in(0); | 165 Location left = locs()->in(0); |
166 Location right = locs()->in(1); | 166 Location right = locs()->in(1); |
167 ASSERT(!left.IsConstant() || !right.IsConstant()); | 167 ASSERT(!left.IsConstant() || !right.IsConstant()); |
168 | 168 |
169 // Clear out register. | 169 // Clear out register. |
170 __ eor(result, result, Operand(result)); | 170 __ eor(result, result, Operand(result)); |
171 | 171 |
172 // Emit comparison code. This must not overwrite the result register. | 172 // Emit comparison code. This must not overwrite the result register. |
173 // IfThenElseInstr::Supports() should prevent EmitComparisonCode from using | |
174 // the labels or returning an invalid condition. | |
175 BranchLabels labels = {NULL, NULL, NULL}; | 173 BranchLabels labels = {NULL, NULL, NULL}; |
176 Condition true_condition = comparison()->EmitComparisonCode(compiler, labels); | 174 Condition true_condition = comparison()->EmitComparisonCode(compiler, labels); |
177 ASSERT(true_condition != kInvalidCondition); | |
178 | 175 |
179 const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_); | 176 const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_); |
180 | 177 |
181 intptr_t true_value = if_true_; | 178 intptr_t true_value = if_true_; |
182 intptr_t false_value = if_false_; | 179 intptr_t false_value = if_false_; |
183 | 180 |
184 if (is_power_of_two_kind) { | 181 if (is_power_of_two_kind) { |
185 if (true_value == 0) { | 182 if (true_value == 0) { |
186 // We need to have zero in result on true_condition. | 183 // We need to have zero in result on true_condition. |
187 true_condition = NegateCondition(true_condition); | 184 true_condition = NegateCondition(true_condition); |
(...skipping 475 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
663 return GE; | 660 return GE; |
664 default: | 661 default: |
665 UNREACHABLE(); | 662 UNREACHABLE(); |
666 return VS; | 663 return VS; |
667 } | 664 } |
668 } | 665 } |
669 | 666 |
670 | 667 |
671 static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler, | 668 static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler, |
672 LocationSummary* locs, | 669 LocationSummary* locs, |
673 BranchLabels labels, | |
674 Token::Kind kind) { | 670 Token::Kind kind) { |
675 const QRegister left = locs->in(0).fpu_reg(); | 671 const QRegister left = locs->in(0).fpu_reg(); |
676 const QRegister right = locs->in(1).fpu_reg(); | 672 const QRegister right = locs->in(1).fpu_reg(); |
677 const DRegister dleft = EvenDRegisterOf(left); | 673 const DRegister dleft = EvenDRegisterOf(left); |
678 const DRegister dright = EvenDRegisterOf(right); | 674 const DRegister dright = EvenDRegisterOf(right); |
679 __ vcmpd(dleft, dright); | 675 __ vcmpd(dleft, dright); |
680 __ vmstat(); | 676 __ vmstat(); |
681 Condition true_condition = TokenKindToDoubleCondition(kind); | 677 Condition true_condition = TokenKindToDoubleCondition(kind); |
682 if (true_condition != NE) { | |
683 // Special case for NaN comparison. Result is always false unless | |
684 // relational operator is !=. | |
685 __ b(labels.false_label, VS); | |
686 } | |
687 return true_condition; | 678 return true_condition; |
688 } | 679 } |
689 | 680 |
690 | 681 |
691 Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 682 Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
692 BranchLabels labels) { | 683 BranchLabels labels) { |
693 if (operation_cid() == kSmiCid) { | 684 if (operation_cid() == kSmiCid) { |
694 return EmitSmiComparisonOp(compiler, locs(), kind()); | 685 return EmitSmiComparisonOp(compiler, locs(), kind()); |
695 } else if (operation_cid() == kMintCid) { | 686 } else if (operation_cid() == kMintCid) { |
696 return EmitUnboxedMintEqualityOp(compiler, locs(), kind()); | 687 return EmitUnboxedMintEqualityOp(compiler, locs(), kind()); |
697 } else { | 688 } else { |
698 ASSERT(operation_cid() == kDoubleCid); | 689 ASSERT(operation_cid() == kDoubleCid); |
699 return EmitDoubleComparisonOp(compiler, locs(), labels, kind()); | 690 return EmitDoubleComparisonOp(compiler, locs(), kind()); |
700 } | 691 } |
701 } | 692 } |
702 | 693 |
703 | 694 |
| 695 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 696 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); |
| 697 |
| 698 // The ARM code does not use true- and false-labels here. |
| 699 BranchLabels labels = {NULL, NULL, NULL}; |
| 700 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 701 |
| 702 const Register result = locs()->out(0).reg(); |
| 703 if ((operation_cid() == kSmiCid) || (operation_cid() == kMintCid)) { |
| 704 __ LoadObject(result, Bool::True(), true_condition); |
| 705 __ LoadObject(result, Bool::False(), NegateCondition(true_condition)); |
| 706 } else { |
| 707 ASSERT(operation_cid() == kDoubleCid); |
| 708 Label done; |
| 709 __ LoadObject(result, Bool::False()); |
| 710 if (true_condition != NE) { |
| 711 __ b(&done, VS); // x == NaN -> false, x != NaN -> true. |
| 712 } |
| 713 __ LoadObject(result, Bool::True(), true_condition); |
| 714 __ Bind(&done); |
| 715 } |
| 716 } |
| 717 |
| 718 |
| 719 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 720 BranchInstr* branch) { |
| 721 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); |
| 722 |
| 723 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 724 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 725 |
| 726 if (operation_cid() == kDoubleCid) { |
| 727 Label* nan_result = |
| 728 (true_condition == NE) ? labels.true_label : labels.false_label; |
| 729 __ b(nan_result, VS); |
| 730 } |
| 731 EmitBranchOnCondition(compiler, true_condition, labels); |
| 732 } |
| 733 |
| 734 |
704 LocationSummary* TestSmiInstr::MakeLocationSummary(Zone* zone, bool opt) const { | 735 LocationSummary* TestSmiInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
705 const intptr_t kNumInputs = 2; | 736 const intptr_t kNumInputs = 2; |
706 const intptr_t kNumTemps = 0; | 737 const intptr_t kNumTemps = 0; |
707 LocationSummary* locs = new (zone) | 738 LocationSummary* locs = new (zone) |
708 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 739 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
709 locs->set_in(0, Location::RequiresRegister()); | 740 locs->set_in(0, Location::RequiresRegister()); |
710 // Only one input can be a constant operand. The case of two constant | 741 // Only one input can be a constant operand. The case of two constant |
711 // operands should be handled by constant propagation. | 742 // operands should be handled by constant propagation. |
712 locs->set_in(1, Location::RegisterOrConstant(right())); | 743 locs->set_in(1, Location::RegisterOrConstant(right())); |
713 return locs; | 744 return locs; |
714 } | 745 } |
715 | 746 |
716 | 747 |
717 Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 748 Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
718 BranchLabels labels) { | 749 BranchLabels labels) { |
719 const Register left = locs()->in(0).reg(); | 750 const Register left = locs()->in(0).reg(); |
720 Location right = locs()->in(1); | 751 Location right = locs()->in(1); |
721 if (right.IsConstant()) { | 752 if (right.IsConstant()) { |
722 ASSERT(right.constant().IsSmi()); | 753 ASSERT(right.constant().IsSmi()); |
723 const int32_t imm = reinterpret_cast<int32_t>(right.constant().raw()); | 754 const int32_t imm = reinterpret_cast<int32_t>(right.constant().raw()); |
724 __ TestImmediate(left, imm); | 755 __ TestImmediate(left, imm); |
725 } else { | 756 } else { |
726 __ tst(left, Operand(right.reg())); | 757 __ tst(left, Operand(right.reg())); |
727 } | 758 } |
728 Condition true_condition = (kind() == Token::kNE) ? NE : EQ; | 759 Condition true_condition = (kind() == Token::kNE) ? NE : EQ; |
729 return true_condition; | 760 return true_condition; |
730 } | 761 } |
731 | 762 |
732 | 763 |
| 764 void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 765 // Never emitted outside of the BranchInstr. |
| 766 UNREACHABLE(); |
| 767 } |
| 768 |
| 769 |
| 770 void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 771 BranchInstr* branch) { |
| 772 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 773 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 774 EmitBranchOnCondition(compiler, true_condition, labels); |
| 775 } |
| 776 |
| 777 |
733 LocationSummary* TestCidsInstr::MakeLocationSummary(Zone* zone, | 778 LocationSummary* TestCidsInstr::MakeLocationSummary(Zone* zone, |
734 bool opt) const { | 779 bool opt) const { |
735 const intptr_t kNumInputs = 1; | 780 const intptr_t kNumInputs = 1; |
736 const intptr_t kNumTemps = 1; | 781 const intptr_t kNumTemps = 1; |
737 LocationSummary* locs = new (zone) | 782 LocationSummary* locs = new (zone) |
738 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 783 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
739 locs->set_in(0, Location::RequiresRegister()); | 784 locs->set_in(0, Location::RequiresRegister()); |
740 locs->set_temp(0, Location::RequiresRegister()); | 785 locs->set_temp(0, Location::RequiresRegister()); |
741 locs->set_out(0, Location::RequiresRegister()); | 786 locs->set_out(0, Location::RequiresRegister()); |
742 return locs; | 787 return locs; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
775 // If the cid is not in the list, jump to the opposite label from the cids | 820 // If the cid is not in the list, jump to the opposite label from the cids |
776 // that are in the list. These must be all the same (see asserts in the | 821 // that are in the list. These must be all the same (see asserts in the |
777 // constructor). | 822 // constructor). |
778 Label* target = result ? labels.false_label : labels.true_label; | 823 Label* target = result ? labels.false_label : labels.true_label; |
779 if (target != labels.fall_through) { | 824 if (target != labels.fall_through) { |
780 __ b(target); | 825 __ b(target); |
781 } | 826 } |
782 } else { | 827 } else { |
783 __ b(deopt); | 828 __ b(deopt); |
784 } | 829 } |
785 // Dummy result as this method already did the jump, there's no need | 830 // Dummy result as the last instruction is a jump, any conditional |
786 // for the caller to branch on a condition. | 831 // branch using the result will therefore be skipped. |
787 return kInvalidCondition; | 832 return EQ; |
788 } | 833 } |
789 | 834 |
790 | 835 |
| 836 void TestCidsInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 837 BranchInstr* branch) { |
| 838 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 839 EmitComparisonCode(compiler, labels); |
| 840 } |
| 841 |
| 842 |
| 843 void TestCidsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 844 const Register result_reg = locs()->out(0).reg(); |
| 845 Label is_true, is_false, done; |
| 846 BranchLabels labels = {&is_true, &is_false, &is_false}; |
| 847 EmitComparisonCode(compiler, labels); |
| 848 __ Bind(&is_false); |
| 849 __ LoadObject(result_reg, Bool::False()); |
| 850 __ b(&done); |
| 851 __ Bind(&is_true); |
| 852 __ LoadObject(result_reg, Bool::True()); |
| 853 __ Bind(&done); |
| 854 } |
| 855 |
| 856 |
791 LocationSummary* RelationalOpInstr::MakeLocationSummary(Zone* zone, | 857 LocationSummary* RelationalOpInstr::MakeLocationSummary(Zone* zone, |
792 bool opt) const { | 858 bool opt) const { |
793 const intptr_t kNumInputs = 2; | 859 const intptr_t kNumInputs = 2; |
794 const intptr_t kNumTemps = 0; | 860 const intptr_t kNumTemps = 0; |
795 if (operation_cid() == kMintCid) { | 861 if (operation_cid() == kMintCid) { |
796 const intptr_t kNumTemps = 0; | 862 const intptr_t kNumTemps = 0; |
797 LocationSummary* locs = new (zone) | 863 LocationSummary* locs = new (zone) |
798 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 864 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
799 locs->set_in(0, Location::Pair(Location::RequiresRegister(), | 865 locs->set_in(0, Location::Pair(Location::RequiresRegister(), |
800 Location::RequiresRegister())); | 866 Location::RequiresRegister())); |
(...skipping 25 matching lines...) Expand all Loading... |
826 | 892 |
827 | 893 |
828 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 894 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
829 BranchLabels labels) { | 895 BranchLabels labels) { |
830 if (operation_cid() == kSmiCid) { | 896 if (operation_cid() == kSmiCid) { |
831 return EmitSmiComparisonOp(compiler, locs(), kind()); | 897 return EmitSmiComparisonOp(compiler, locs(), kind()); |
832 } else if (operation_cid() == kMintCid) { | 898 } else if (operation_cid() == kMintCid) { |
833 return EmitUnboxedMintComparisonOp(compiler, locs(), kind(), labels); | 899 return EmitUnboxedMintComparisonOp(compiler, locs(), kind(), labels); |
834 } else { | 900 } else { |
835 ASSERT(operation_cid() == kDoubleCid); | 901 ASSERT(operation_cid() == kDoubleCid); |
836 return EmitDoubleComparisonOp(compiler, locs(), labels, kind()); | 902 return EmitDoubleComparisonOp(compiler, locs(), kind()); |
837 } | 903 } |
838 } | 904 } |
839 | 905 |
| 906 |
| 907 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 908 Label is_true, is_false; |
| 909 BranchLabels labels = {&is_true, &is_false, &is_false}; |
| 910 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 911 |
| 912 const Register result = locs()->out(0).reg(); |
| 913 if (operation_cid() == kSmiCid) { |
| 914 __ LoadObject(result, Bool::True(), true_condition); |
| 915 __ LoadObject(result, Bool::False(), NegateCondition(true_condition)); |
| 916 } else if (operation_cid() == kMintCid) { |
| 917 EmitBranchOnCondition(compiler, true_condition, labels); |
| 918 Label done; |
| 919 __ Bind(&is_false); |
| 920 __ LoadObject(result, Bool::False()); |
| 921 __ b(&done); |
| 922 __ Bind(&is_true); |
| 923 __ LoadObject(result, Bool::True()); |
| 924 __ Bind(&done); |
| 925 } else { |
| 926 ASSERT(operation_cid() == kDoubleCid); |
| 927 Label done; |
| 928 __ LoadObject(result, Bool::False()); |
| 929 if (true_condition != NE) { |
| 930 __ b(&done, VS); // x == NaN -> false, x != NaN -> true. |
| 931 } |
| 932 __ LoadObject(result, Bool::True(), true_condition); |
| 933 __ Bind(&done); |
| 934 } |
| 935 } |
| 936 |
| 937 |
| 938 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 939 BranchInstr* branch) { |
| 940 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 941 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 942 |
| 943 if ((operation_cid() == kSmiCid) || (operation_cid() == kMintCid)) { |
| 944 EmitBranchOnCondition(compiler, true_condition, labels); |
| 945 } else if (operation_cid() == kDoubleCid) { |
| 946 Label* nan_result = |
| 947 (true_condition == NE) ? labels.true_label : labels.false_label; |
| 948 __ b(nan_result, VS); |
| 949 EmitBranchOnCondition(compiler, true_condition, labels); |
| 950 } |
| 951 } |
| 952 |
840 | 953 |
841 LocationSummary* NativeCallInstr::MakeLocationSummary(Zone* zone, | 954 LocationSummary* NativeCallInstr::MakeLocationSummary(Zone* zone, |
842 bool opt) const { | 955 bool opt) const { |
843 return MakeCallSummary(zone); | 956 return MakeCallSummary(zone); |
844 } | 957 } |
845 | 958 |
846 | 959 |
847 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 960 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
848 SetupNative(); | 961 SetupNative(); |
849 const Register result = locs()->out(0).reg(); | 962 const Register result = locs()->out(0).reg(); |
(...skipping 2415 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3265 | 3378 |
3266 void CheckedSmiComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 3379 void CheckedSmiComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
3267 BranchInstr* branch) { | 3380 BranchInstr* branch) { |
3268 BranchLabels labels = compiler->CreateBranchLabels(branch); | 3381 BranchLabels labels = compiler->CreateBranchLabels(branch); |
3269 CheckedSmiComparisonSlowPath* slow_path = new CheckedSmiComparisonSlowPath( | 3382 CheckedSmiComparisonSlowPath* slow_path = new CheckedSmiComparisonSlowPath( |
3270 this, compiler->CurrentTryIndex(), labels, | 3383 this, compiler->CurrentTryIndex(), labels, |
3271 /* merged = */ true); | 3384 /* merged = */ true); |
3272 compiler->AddSlowPathCode(slow_path); | 3385 compiler->AddSlowPathCode(slow_path); |
3273 EMIT_SMI_CHECK; | 3386 EMIT_SMI_CHECK; |
3274 Condition true_condition = EmitComparisonCode(compiler, labels); | 3387 Condition true_condition = EmitComparisonCode(compiler, labels); |
3275 ASSERT(true_condition != kInvalidCondition); | |
3276 EmitBranchOnCondition(compiler, true_condition, labels); | 3388 EmitBranchOnCondition(compiler, true_condition, labels); |
3277 __ Bind(slow_path->exit_label()); | 3389 __ Bind(slow_path->exit_label()); |
3278 } | 3390 } |
3279 | 3391 |
3280 | 3392 |
3281 void CheckedSmiComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3393 void CheckedSmiComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3282 BranchLabels labels = {NULL, NULL, NULL}; | 3394 BranchLabels labels = {NULL, NULL, NULL}; |
3283 CheckedSmiComparisonSlowPath* slow_path = new CheckedSmiComparisonSlowPath( | 3395 CheckedSmiComparisonSlowPath* slow_path = new CheckedSmiComparisonSlowPath( |
3284 this, compiler->CurrentTryIndex(), labels, | 3396 this, compiler->CurrentTryIndex(), labels, |
3285 /* merged = */ false); | 3397 /* merged = */ false); |
3286 compiler->AddSlowPathCode(slow_path); | 3398 compiler->AddSlowPathCode(slow_path); |
3287 EMIT_SMI_CHECK; | 3399 EMIT_SMI_CHECK; |
3288 Condition true_condition = EmitComparisonCode(compiler, labels); | 3400 Condition true_condition = EmitComparisonCode(compiler, labels); |
3289 ASSERT(true_condition != kInvalidCondition); | |
3290 Register result = locs()->out(0).reg(); | 3401 Register result = locs()->out(0).reg(); |
3291 __ LoadObject(result, Bool::True(), true_condition); | 3402 __ LoadObject(result, Bool::True(), true_condition); |
3292 __ LoadObject(result, Bool::False(), NegateCondition(true_condition)); | 3403 __ LoadObject(result, Bool::False(), NegateCondition(true_condition)); |
3293 __ Bind(slow_path->exit_label()); | 3404 __ Bind(slow_path->exit_label()); |
3294 } | 3405 } |
3295 #undef EMIT_SMI_CHECK | 3406 #undef EMIT_SMI_CHECK |
3296 | 3407 |
3297 | 3408 |
3298 LocationSummary* BinarySmiOpInstr::MakeLocationSummary(Zone* zone, | 3409 LocationSummary* BinarySmiOpInstr::MakeLocationSummary(Zone* zone, |
3299 bool opt) const { | 3410 bool opt) const { |
(...skipping 943 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4243 __ b(is_negated ? labels.true_label : labels.false_label, NE); | 4354 __ b(is_negated ? labels.true_label : labels.false_label, NE); |
4244 | 4355 |
4245 // Mask off the sign bit. | 4356 // Mask off the sign bit. |
4246 __ AndImmediate(temp, temp, 0x7FFFFFFF); | 4357 __ AndImmediate(temp, temp, 0x7FFFFFFF); |
4247 // Compare with +infinity. | 4358 // Compare with +infinity. |
4248 __ CompareImmediate(temp, 0x7FF00000); | 4359 __ CompareImmediate(temp, 0x7FF00000); |
4249 return is_negated ? NE : EQ; | 4360 return is_negated ? NE : EQ; |
4250 } | 4361 } |
4251 } | 4362 } |
4252 | 4363 |
| 4364 void DoubleTestOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 4365 BranchInstr* branch) { |
| 4366 ASSERT(compiler->is_optimizing()); |
| 4367 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 4368 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 4369 EmitBranchOnCondition(compiler, true_condition, labels); |
| 4370 } |
| 4371 |
| 4372 |
| 4373 void DoubleTestOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4374 ASSERT(compiler->is_optimizing()); |
| 4375 Label is_true, is_false; |
| 4376 BranchLabels labels = {&is_true, &is_false, &is_false}; |
| 4377 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 4378 const Register result = locs()->out(0).reg(); |
| 4379 if (op_kind() == MethodRecognizer::kDouble_getIsNaN) { |
| 4380 __ LoadObject(result, Bool::True(), true_condition); |
| 4381 __ LoadObject(result, Bool::False(), NegateCondition(true_condition)); |
| 4382 } else { |
| 4383 ASSERT(op_kind() == MethodRecognizer::kDouble_getIsInfinite); |
| 4384 EmitBranchOnCondition(compiler, true_condition, labels); |
| 4385 Label done; |
| 4386 __ Bind(&is_false); |
| 4387 __ LoadObject(result, Bool::False()); |
| 4388 __ b(&done); |
| 4389 __ Bind(&is_true); |
| 4390 __ LoadObject(result, Bool::True()); |
| 4391 __ Bind(&done); |
| 4392 } |
| 4393 } |
| 4394 |
| 4395 |
4253 LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(Zone* zone, | 4396 LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(Zone* zone, |
4254 bool opt) const { | 4397 bool opt) const { |
4255 const intptr_t kNumInputs = 2; | 4398 const intptr_t kNumInputs = 2; |
4256 const intptr_t kNumTemps = 0; | 4399 const intptr_t kNumTemps = 0; |
4257 LocationSummary* summary = new (zone) | 4400 LocationSummary* summary = new (zone) |
4258 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4401 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4259 summary->set_in(0, Location::RequiresFpuRegister()); | 4402 summary->set_in(0, Location::RequiresFpuRegister()); |
4260 summary->set_in(1, Location::RequiresFpuRegister()); | 4403 summary->set_in(1, Location::RequiresFpuRegister()); |
4261 summary->set_out(0, Location::RequiresFpuRegister()); | 4404 summary->set_out(0, Location::RequiresFpuRegister()); |
4262 return summary; | 4405 return summary; |
(...skipping 2761 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7024 left.reg(), right.reg(), needs_number_check(), token_pos(), deopt_id_); | 7167 left.reg(), right.reg(), needs_number_check(), token_pos(), deopt_id_); |
7025 } | 7168 } |
7026 if (kind() != Token::kEQ_STRICT) { | 7169 if (kind() != Token::kEQ_STRICT) { |
7027 ASSERT(kind() == Token::kNE_STRICT); | 7170 ASSERT(kind() == Token::kNE_STRICT); |
7028 true_condition = NegateCondition(true_condition); | 7171 true_condition = NegateCondition(true_condition); |
7029 } | 7172 } |
7030 return true_condition; | 7173 return true_condition; |
7031 } | 7174 } |
7032 | 7175 |
7033 | 7176 |
7034 void ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 7177 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
7035 // The ARM code may not use true- and false-labels here. | 7178 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
7036 Label is_true, is_false, done; | 7179 |
7037 BranchLabels labels = {&is_true, &is_false, &is_false}; | 7180 // The ARM code does not use true- and false-labels here. |
| 7181 BranchLabels labels = {NULL, NULL, NULL}; |
7038 Condition true_condition = EmitComparisonCode(compiler, labels); | 7182 Condition true_condition = EmitComparisonCode(compiler, labels); |
7039 | 7183 |
7040 const Register result = this->locs()->out(0).reg(); | 7184 const Register result = locs()->out(0).reg(); |
7041 if (is_false.IsLinked() || is_true.IsLinked()) { | 7185 __ LoadObject(result, Bool::True(), true_condition); |
7042 if (true_condition != kInvalidCondition) { | 7186 __ LoadObject(result, Bool::False(), NegateCondition(true_condition)); |
7043 EmitBranchOnCondition(compiler, true_condition, labels); | |
7044 } | |
7045 __ Bind(&is_false); | |
7046 __ LoadObject(result, Bool::False()); | |
7047 __ b(&done); | |
7048 __ Bind(&is_true); | |
7049 __ LoadObject(result, Bool::True()); | |
7050 __ Bind(&done); | |
7051 } else { | |
7052 // If EmitComparisonCode did not use the labels and just returned | |
7053 // a condition we can avoid the branch and use conditional loads. | |
7054 ASSERT(true_condition != kInvalidCondition); | |
7055 __ LoadObject(result, Bool::True(), true_condition); | |
7056 __ LoadObject(result, Bool::False(), NegateCondition(true_condition)); | |
7057 } | |
7058 } | 7187 } |
7059 | 7188 |
7060 | 7189 |
7061 void ComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 7190 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
7062 BranchInstr* branch) { | 7191 BranchInstr* branch) { |
| 7192 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
| 7193 |
7063 BranchLabels labels = compiler->CreateBranchLabels(branch); | 7194 BranchLabels labels = compiler->CreateBranchLabels(branch); |
7064 Condition true_condition = EmitComparisonCode(compiler, labels); | 7195 Condition true_condition = EmitComparisonCode(compiler, labels); |
7065 if (true_condition != kInvalidCondition) { | 7196 EmitBranchOnCondition(compiler, true_condition, labels); |
7066 EmitBranchOnCondition(compiler, true_condition, labels); | |
7067 } | |
7068 } | 7197 } |
7069 | 7198 |
7070 | 7199 |
7071 LocationSummary* BooleanNegateInstr::MakeLocationSummary(Zone* zone, | 7200 LocationSummary* BooleanNegateInstr::MakeLocationSummary(Zone* zone, |
7072 bool opt) const { | 7201 bool opt) const { |
7073 return LocationSummary::Make(zone, 1, Location::RequiresRegister(), | 7202 return LocationSummary::Make(zone, 1, Location::RequiresRegister(), |
7074 LocationSummary::kNoCall); | 7203 LocationSummary::kNoCall); |
7075 } | 7204 } |
7076 | 7205 |
7077 | 7206 |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7130 compiler->GenerateRuntimeCall(TokenPosition::kNoSource, deopt_id(), | 7259 compiler->GenerateRuntimeCall(TokenPosition::kNoSource, deopt_id(), |
7131 kGrowRegExpStackRuntimeEntry, 1, locs()); | 7260 kGrowRegExpStackRuntimeEntry, 1, locs()); |
7132 __ Drop(1); | 7261 __ Drop(1); |
7133 __ Pop(result); | 7262 __ Pop(result); |
7134 } | 7263 } |
7135 | 7264 |
7136 | 7265 |
7137 } // namespace dart | 7266 } // namespace dart |
7138 | 7267 |
7139 #endif // defined TARGET_ARCH_ARM | 7268 #endif // defined TARGET_ARCH_ARM |
OLD | NEW |