| 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 |