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. |
173 BranchLabels labels = {NULL, NULL, NULL}; | 175 BranchLabels labels = {NULL, NULL, NULL}; |
174 Condition true_condition = comparison()->EmitComparisonCode(compiler, labels); | 176 Condition true_condition = comparison()->EmitComparisonCode(compiler, labels); |
| 177 ASSERT(true_condition != kInvalidCondition); |
175 | 178 |
176 const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_); | 179 const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_); |
177 | 180 |
178 intptr_t true_value = if_true_; | 181 intptr_t true_value = if_true_; |
179 intptr_t false_value = if_false_; | 182 intptr_t false_value = if_false_; |
180 | 183 |
181 if (is_power_of_two_kind) { | 184 if (is_power_of_two_kind) { |
182 if (true_value == 0) { | 185 if (true_value == 0) { |
183 // We need to have zero in result on true_condition. | 186 // We need to have zero in result on true_condition. |
184 true_condition = NegateCondition(true_condition); | 187 true_condition = NegateCondition(true_condition); |
(...skipping 475 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
660 return GE; | 663 return GE; |
661 default: | 664 default: |
662 UNREACHABLE(); | 665 UNREACHABLE(); |
663 return VS; | 666 return VS; |
664 } | 667 } |
665 } | 668 } |
666 | 669 |
667 | 670 |
668 static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler, | 671 static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler, |
669 LocationSummary* locs, | 672 LocationSummary* locs, |
| 673 BranchLabels labels, |
670 Token::Kind kind) { | 674 Token::Kind kind) { |
671 const QRegister left = locs->in(0).fpu_reg(); | 675 const QRegister left = locs->in(0).fpu_reg(); |
672 const QRegister right = locs->in(1).fpu_reg(); | 676 const QRegister right = locs->in(1).fpu_reg(); |
673 const DRegister dleft = EvenDRegisterOf(left); | 677 const DRegister dleft = EvenDRegisterOf(left); |
674 const DRegister dright = EvenDRegisterOf(right); | 678 const DRegister dright = EvenDRegisterOf(right); |
675 __ vcmpd(dleft, dright); | 679 __ vcmpd(dleft, dright); |
676 __ vmstat(); | 680 __ vmstat(); |
677 Condition true_condition = TokenKindToDoubleCondition(kind); | 681 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 } |
678 return true_condition; | 687 return true_condition; |
679 } | 688 } |
680 | 689 |
681 | 690 |
682 Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 691 Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
683 BranchLabels labels) { | 692 BranchLabels labels) { |
684 if (operation_cid() == kSmiCid) { | 693 if (operation_cid() == kSmiCid) { |
685 return EmitSmiComparisonOp(compiler, locs(), kind()); | 694 return EmitSmiComparisonOp(compiler, locs(), kind()); |
686 } else if (operation_cid() == kMintCid) { | 695 } else if (operation_cid() == kMintCid) { |
687 return EmitUnboxedMintEqualityOp(compiler, locs(), kind()); | 696 return EmitUnboxedMintEqualityOp(compiler, locs(), kind()); |
688 } else { | 697 } else { |
689 ASSERT(operation_cid() == kDoubleCid); | 698 ASSERT(operation_cid() == kDoubleCid); |
690 return EmitDoubleComparisonOp(compiler, locs(), kind()); | 699 return EmitDoubleComparisonOp(compiler, locs(), labels, kind()); |
691 } | 700 } |
692 } | 701 } |
693 | 702 |
694 | 703 |
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 | |
735 LocationSummary* TestSmiInstr::MakeLocationSummary(Zone* zone, bool opt) const { | 704 LocationSummary* TestSmiInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
736 const intptr_t kNumInputs = 2; | 705 const intptr_t kNumInputs = 2; |
737 const intptr_t kNumTemps = 0; | 706 const intptr_t kNumTemps = 0; |
738 LocationSummary* locs = new (zone) | 707 LocationSummary* locs = new (zone) |
739 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 708 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
740 locs->set_in(0, Location::RequiresRegister()); | 709 locs->set_in(0, Location::RequiresRegister()); |
741 // Only one input can be a constant operand. The case of two constant | 710 // Only one input can be a constant operand. The case of two constant |
742 // operands should be handled by constant propagation. | 711 // operands should be handled by constant propagation. |
743 locs->set_in(1, Location::RegisterOrConstant(right())); | 712 locs->set_in(1, Location::RegisterOrConstant(right())); |
744 return locs; | 713 return locs; |
745 } | 714 } |
746 | 715 |
747 | 716 |
748 Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 717 Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
749 BranchLabels labels) { | 718 BranchLabels labels) { |
750 const Register left = locs()->in(0).reg(); | 719 const Register left = locs()->in(0).reg(); |
751 Location right = locs()->in(1); | 720 Location right = locs()->in(1); |
752 if (right.IsConstant()) { | 721 if (right.IsConstant()) { |
753 ASSERT(right.constant().IsSmi()); | 722 ASSERT(right.constant().IsSmi()); |
754 const int32_t imm = reinterpret_cast<int32_t>(right.constant().raw()); | 723 const int32_t imm = reinterpret_cast<int32_t>(right.constant().raw()); |
755 __ TestImmediate(left, imm); | 724 __ TestImmediate(left, imm); |
756 } else { | 725 } else { |
757 __ tst(left, Operand(right.reg())); | 726 __ tst(left, Operand(right.reg())); |
758 } | 727 } |
759 Condition true_condition = (kind() == Token::kNE) ? NE : EQ; | 728 Condition true_condition = (kind() == Token::kNE) ? NE : EQ; |
760 return true_condition; | 729 return true_condition; |
761 } | 730 } |
762 | 731 |
763 | 732 |
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 | |
778 LocationSummary* TestCidsInstr::MakeLocationSummary(Zone* zone, | 733 LocationSummary* TestCidsInstr::MakeLocationSummary(Zone* zone, |
779 bool opt) const { | 734 bool opt) const { |
780 const intptr_t kNumInputs = 1; | 735 const intptr_t kNumInputs = 1; |
781 const intptr_t kNumTemps = 1; | 736 const intptr_t kNumTemps = 1; |
782 LocationSummary* locs = new (zone) | 737 LocationSummary* locs = new (zone) |
783 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 738 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
784 locs->set_in(0, Location::RequiresRegister()); | 739 locs->set_in(0, Location::RequiresRegister()); |
785 locs->set_temp(0, Location::RequiresRegister()); | 740 locs->set_temp(0, Location::RequiresRegister()); |
786 locs->set_out(0, Location::RequiresRegister()); | 741 locs->set_out(0, Location::RequiresRegister()); |
787 return locs; | 742 return locs; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
820 // If the cid is not in the list, jump to the opposite label from the cids | 775 // If the cid is not in the list, jump to the opposite label from the cids |
821 // that are in the list. These must be all the same (see asserts in the | 776 // that are in the list. These must be all the same (see asserts in the |
822 // constructor). | 777 // constructor). |
823 Label* target = result ? labels.false_label : labels.true_label; | 778 Label* target = result ? labels.false_label : labels.true_label; |
824 if (target != labels.fall_through) { | 779 if (target != labels.fall_through) { |
825 __ b(target); | 780 __ b(target); |
826 } | 781 } |
827 } else { | 782 } else { |
828 __ b(deopt); | 783 __ b(deopt); |
829 } | 784 } |
830 // Dummy result as the last instruction is a jump, any conditional | 785 // Dummy result as this method already did the jump, there's no need |
831 // branch using the result will therefore be skipped. | 786 // for the caller to branch on a condition. |
832 return EQ; | 787 return kInvalidCondition; |
833 } | 788 } |
834 | 789 |
835 | 790 |
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 | |
857 LocationSummary* RelationalOpInstr::MakeLocationSummary(Zone* zone, | 791 LocationSummary* RelationalOpInstr::MakeLocationSummary(Zone* zone, |
858 bool opt) const { | 792 bool opt) const { |
859 const intptr_t kNumInputs = 2; | 793 const intptr_t kNumInputs = 2; |
860 const intptr_t kNumTemps = 0; | 794 const intptr_t kNumTemps = 0; |
861 if (operation_cid() == kMintCid) { | 795 if (operation_cid() == kMintCid) { |
862 const intptr_t kNumTemps = 0; | 796 const intptr_t kNumTemps = 0; |
863 LocationSummary* locs = new (zone) | 797 LocationSummary* locs = new (zone) |
864 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 798 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
865 locs->set_in(0, Location::Pair(Location::RequiresRegister(), | 799 locs->set_in(0, Location::Pair(Location::RequiresRegister(), |
866 Location::RequiresRegister())); | 800 Location::RequiresRegister())); |
(...skipping 25 matching lines...) Expand all Loading... |
892 | 826 |
893 | 827 |
894 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 828 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
895 BranchLabels labels) { | 829 BranchLabels labels) { |
896 if (operation_cid() == kSmiCid) { | 830 if (operation_cid() == kSmiCid) { |
897 return EmitSmiComparisonOp(compiler, locs(), kind()); | 831 return EmitSmiComparisonOp(compiler, locs(), kind()); |
898 } else if (operation_cid() == kMintCid) { | 832 } else if (operation_cid() == kMintCid) { |
899 return EmitUnboxedMintComparisonOp(compiler, locs(), kind(), labels); | 833 return EmitUnboxedMintComparisonOp(compiler, locs(), kind(), labels); |
900 } else { | 834 } else { |
901 ASSERT(operation_cid() == kDoubleCid); | 835 ASSERT(operation_cid() == kDoubleCid); |
902 return EmitDoubleComparisonOp(compiler, locs(), kind()); | 836 return EmitDoubleComparisonOp(compiler, locs(), labels, kind()); |
903 } | 837 } |
904 } | 838 } |
905 | 839 |
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 | |
953 | 840 |
954 LocationSummary* NativeCallInstr::MakeLocationSummary(Zone* zone, | 841 LocationSummary* NativeCallInstr::MakeLocationSummary(Zone* zone, |
955 bool opt) const { | 842 bool opt) const { |
956 return MakeCallSummary(zone); | 843 return MakeCallSummary(zone); |
957 } | 844 } |
958 | 845 |
959 | 846 |
960 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 847 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
961 SetupNative(); | 848 SetupNative(); |
962 const Register result = locs()->out(0).reg(); | 849 const Register result = locs()->out(0).reg(); |
(...skipping 2415 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3378 | 3265 |
3379 void CheckedSmiComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 3266 void CheckedSmiComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
3380 BranchInstr* branch) { | 3267 BranchInstr* branch) { |
3381 BranchLabels labels = compiler->CreateBranchLabels(branch); | 3268 BranchLabels labels = compiler->CreateBranchLabels(branch); |
3382 CheckedSmiComparisonSlowPath* slow_path = new CheckedSmiComparisonSlowPath( | 3269 CheckedSmiComparisonSlowPath* slow_path = new CheckedSmiComparisonSlowPath( |
3383 this, compiler->CurrentTryIndex(), labels, | 3270 this, compiler->CurrentTryIndex(), labels, |
3384 /* merged = */ true); | 3271 /* merged = */ true); |
3385 compiler->AddSlowPathCode(slow_path); | 3272 compiler->AddSlowPathCode(slow_path); |
3386 EMIT_SMI_CHECK; | 3273 EMIT_SMI_CHECK; |
3387 Condition true_condition = EmitComparisonCode(compiler, labels); | 3274 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 3275 ASSERT(true_condition != kInvalidCondition); |
3388 EmitBranchOnCondition(compiler, true_condition, labels); | 3276 EmitBranchOnCondition(compiler, true_condition, labels); |
3389 __ Bind(slow_path->exit_label()); | 3277 __ Bind(slow_path->exit_label()); |
3390 } | 3278 } |
3391 | 3279 |
3392 | 3280 |
3393 void CheckedSmiComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3281 void CheckedSmiComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3394 BranchLabels labels = {NULL, NULL, NULL}; | 3282 BranchLabels labels = {NULL, NULL, NULL}; |
3395 CheckedSmiComparisonSlowPath* slow_path = new CheckedSmiComparisonSlowPath( | 3283 CheckedSmiComparisonSlowPath* slow_path = new CheckedSmiComparisonSlowPath( |
3396 this, compiler->CurrentTryIndex(), labels, | 3284 this, compiler->CurrentTryIndex(), labels, |
3397 /* merged = */ false); | 3285 /* merged = */ false); |
3398 compiler->AddSlowPathCode(slow_path); | 3286 compiler->AddSlowPathCode(slow_path); |
3399 EMIT_SMI_CHECK; | 3287 EMIT_SMI_CHECK; |
3400 Condition true_condition = EmitComparisonCode(compiler, labels); | 3288 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 3289 ASSERT(true_condition != kInvalidCondition); |
3401 Register result = locs()->out(0).reg(); | 3290 Register result = locs()->out(0).reg(); |
3402 __ LoadObject(result, Bool::True(), true_condition); | 3291 __ LoadObject(result, Bool::True(), true_condition); |
3403 __ LoadObject(result, Bool::False(), NegateCondition(true_condition)); | 3292 __ LoadObject(result, Bool::False(), NegateCondition(true_condition)); |
3404 __ Bind(slow_path->exit_label()); | 3293 __ Bind(slow_path->exit_label()); |
3405 } | 3294 } |
3406 #undef EMIT_SMI_CHECK | 3295 #undef EMIT_SMI_CHECK |
3407 | 3296 |
3408 | 3297 |
3409 LocationSummary* BinarySmiOpInstr::MakeLocationSummary(Zone* zone, | 3298 LocationSummary* BinarySmiOpInstr::MakeLocationSummary(Zone* zone, |
3410 bool opt) const { | 3299 bool opt) const { |
(...skipping 943 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4354 __ b(is_negated ? labels.true_label : labels.false_label, NE); | 4243 __ b(is_negated ? labels.true_label : labels.false_label, NE); |
4355 | 4244 |
4356 // Mask off the sign bit. | 4245 // Mask off the sign bit. |
4357 __ AndImmediate(temp, temp, 0x7FFFFFFF); | 4246 __ AndImmediate(temp, temp, 0x7FFFFFFF); |
4358 // Compare with +infinity. | 4247 // Compare with +infinity. |
4359 __ CompareImmediate(temp, 0x7FF00000); | 4248 __ CompareImmediate(temp, 0x7FF00000); |
4360 return is_negated ? NE : EQ; | 4249 return is_negated ? NE : EQ; |
4361 } | 4250 } |
4362 } | 4251 } |
4363 | 4252 |
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 | |
4396 LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(Zone* zone, | 4253 LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(Zone* zone, |
4397 bool opt) const { | 4254 bool opt) const { |
4398 const intptr_t kNumInputs = 2; | 4255 const intptr_t kNumInputs = 2; |
4399 const intptr_t kNumTemps = 0; | 4256 const intptr_t kNumTemps = 0; |
4400 LocationSummary* summary = new (zone) | 4257 LocationSummary* summary = new (zone) |
4401 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4258 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4402 summary->set_in(0, Location::RequiresFpuRegister()); | 4259 summary->set_in(0, Location::RequiresFpuRegister()); |
4403 summary->set_in(1, Location::RequiresFpuRegister()); | 4260 summary->set_in(1, Location::RequiresFpuRegister()); |
4404 summary->set_out(0, Location::RequiresFpuRegister()); | 4261 summary->set_out(0, Location::RequiresFpuRegister()); |
4405 return summary; | 4262 return summary; |
(...skipping 2761 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7167 left.reg(), right.reg(), needs_number_check(), token_pos(), deopt_id_); | 7024 left.reg(), right.reg(), needs_number_check(), token_pos(), deopt_id_); |
7168 } | 7025 } |
7169 if (kind() != Token::kEQ_STRICT) { | 7026 if (kind() != Token::kEQ_STRICT) { |
7170 ASSERT(kind() == Token::kNE_STRICT); | 7027 ASSERT(kind() == Token::kNE_STRICT); |
7171 true_condition = NegateCondition(true_condition); | 7028 true_condition = NegateCondition(true_condition); |
7172 } | 7029 } |
7173 return true_condition; | 7030 return true_condition; |
7174 } | 7031 } |
7175 | 7032 |
7176 | 7033 |
7177 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 7034 void ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
7178 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); | 7035 // The ARM code may not use true- and false-labels here. |
7179 | 7036 Label is_true, is_false, done; |
7180 // The ARM code does not use true- and false-labels here. | 7037 BranchLabels labels = {&is_true, &is_false, &is_false}; |
7181 BranchLabels labels = {NULL, NULL, NULL}; | |
7182 Condition true_condition = EmitComparisonCode(compiler, labels); | 7038 Condition true_condition = EmitComparisonCode(compiler, labels); |
7183 | 7039 |
7184 const Register result = locs()->out(0).reg(); | 7040 const Register result = this->locs()->out(0).reg(); |
7185 __ LoadObject(result, Bool::True(), true_condition); | 7041 if (is_false.IsLinked() || is_true.IsLinked()) { |
7186 __ LoadObject(result, Bool::False(), NegateCondition(true_condition)); | 7042 if (true_condition != kInvalidCondition) { |
| 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 } |
7187 } | 7058 } |
7188 | 7059 |
7189 | 7060 |
7190 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 7061 void ComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
7191 BranchInstr* branch) { | 7062 BranchInstr* branch) { |
7192 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); | |
7193 | |
7194 BranchLabels labels = compiler->CreateBranchLabels(branch); | 7063 BranchLabels labels = compiler->CreateBranchLabels(branch); |
7195 Condition true_condition = EmitComparisonCode(compiler, labels); | 7064 Condition true_condition = EmitComparisonCode(compiler, labels); |
7196 EmitBranchOnCondition(compiler, true_condition, labels); | 7065 if (true_condition != kInvalidCondition) { |
| 7066 EmitBranchOnCondition(compiler, true_condition, labels); |
| 7067 } |
7197 } | 7068 } |
7198 | 7069 |
7199 | 7070 |
7200 LocationSummary* BooleanNegateInstr::MakeLocationSummary(Zone* zone, | 7071 LocationSummary* BooleanNegateInstr::MakeLocationSummary(Zone* zone, |
7201 bool opt) const { | 7072 bool opt) const { |
7202 return LocationSummary::Make(zone, 1, Location::RequiresRegister(), | 7073 return LocationSummary::Make(zone, 1, Location::RequiresRegister(), |
7203 LocationSummary::kNoCall); | 7074 LocationSummary::kNoCall); |
7204 } | 7075 } |
7205 | 7076 |
7206 | 7077 |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7259 compiler->GenerateRuntimeCall(TokenPosition::kNoSource, deopt_id(), | 7130 compiler->GenerateRuntimeCall(TokenPosition::kNoSource, deopt_id(), |
7260 kGrowRegExpStackRuntimeEntry, 1, locs()); | 7131 kGrowRegExpStackRuntimeEntry, 1, locs()); |
7261 __ Drop(1); | 7132 __ Drop(1); |
7262 __ Pop(result); | 7133 __ Pop(result); |
7263 } | 7134 } |
7264 | 7135 |
7265 | 7136 |
7266 } // namespace dart | 7137 } // namespace dart |
7267 | 7138 |
7268 #endif // defined TARGET_ARCH_ARM | 7139 #endif // defined TARGET_ARCH_ARM |
OLD | NEW |