Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. |
| 6 #if defined(TARGET_ARCH_ARM) | 6 #if defined(TARGET_ARCH_ARM) |
| 7 | 7 |
| 8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 | 9 |
| 10 #include "vm/cpu.h" | 10 #include "vm/cpu.h" |
| (...skipping 552 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 563 // Compare lower. | 563 // Compare lower. |
| 564 __ cmp(left_lo, Operand(right_lo)); | 564 __ cmp(left_lo, Operand(right_lo)); |
| 565 // Compare upper if lower is equal. | 565 // Compare upper if lower is equal. |
| 566 __ cmp(left_hi, Operand(right_hi), EQ); | 566 __ cmp(left_hi, Operand(right_hi), EQ); |
| 567 return TokenKindToMintCondition(kind); | 567 return TokenKindToMintCondition(kind); |
| 568 } | 568 } |
| 569 | 569 |
| 570 | 570 |
| 571 static Condition EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler, | 571 static Condition EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler, |
| 572 LocationSummary* locs, | 572 LocationSummary* locs, |
| 573 Token::Kind kind) { | 573 Token::Kind kind, |
| 574 BranchLabels labels) { | |
| 574 PairLocation* left_pair = locs->in(0).AsPairLocation(); | 575 PairLocation* left_pair = locs->in(0).AsPairLocation(); |
| 575 Register left_lo = left_pair->At(0).reg(); | 576 Register left_lo = left_pair->At(0).reg(); |
| 576 Register left_hi = left_pair->At(1).reg(); | 577 Register left_hi = left_pair->At(1).reg(); |
| 577 PairLocation* right_pair = locs->in(1).AsPairLocation(); | 578 PairLocation* right_pair = locs->in(1).AsPairLocation(); |
| 578 Register right_lo = right_pair->At(0).reg(); | 579 Register right_lo = right_pair->At(0).reg(); |
| 579 Register right_hi = right_pair->At(1).reg(); | 580 Register right_hi = right_pair->At(1).reg(); |
| 580 | 581 |
| 581 Register out = locs->temp(0).reg(); | 582 // 64-bit comparison. |
| 582 | 583 Condition hi_cond, lo_cond; |
| 583 // 64-bit comparison | |
| 584 Condition hi_true_cond, hi_false_cond, lo_false_cond; | |
| 585 switch (kind) { | 584 switch (kind) { |
| 586 case Token::kLT: | 585 case Token::kLT: |
| 587 case Token::kLTE: | 586 hi_cond = LT; |
| 588 hi_true_cond = LT; | 587 lo_cond = CC; |
| 589 hi_false_cond = GT; | |
| 590 lo_false_cond = (kind == Token::kLT) ? CS : HI; | |
| 591 break; | 588 break; |
| 592 case Token::kGT: | 589 case Token::kGT: |
| 590 hi_cond = GT; | |
| 591 lo_cond = HI; | |
| 592 break; | |
| 593 case Token::kLTE: | |
| 594 hi_cond = LT; | |
| 595 lo_cond = LS; | |
| 596 break; | |
| 593 case Token::kGTE: | 597 case Token::kGTE: |
| 594 hi_true_cond = GT; | 598 hi_cond = GT; |
| 595 hi_false_cond = LT; | 599 lo_cond = CS; |
| 596 lo_false_cond = (kind == Token::kGT) ? LS : CC; | |
| 597 break; | 600 break; |
| 598 default: | 601 default: |
| 599 UNREACHABLE(); | 602 UNREACHABLE(); |
| 600 hi_true_cond = hi_false_cond = lo_false_cond = VS; | 603 hi_cond = lo_cond = VS; |
| 601 } | 604 } |
| 602 | |
| 603 Label done; | |
| 604 // Compare upper halves first. | 605 // Compare upper halves first. |
| 605 __ cmp(left_hi, Operand(right_hi)); | 606 __ cmp(left_hi, Operand(right_hi)); |
| 606 __ LoadImmediate(out, 0, hi_false_cond); | 607 __ b(labels.true_label, hi_cond); |
| 607 __ LoadImmediate(out, 1, hi_true_cond); | 608 __ b(labels.false_label, FlipCondition(hi_cond)); |
| 608 // If higher words aren't equal, skip comparing lower words. | |
| 609 __ b(&done, NE); | |
| 610 | 609 |
| 610 // If higher words are equal, compare lower words. | |
| 611 __ cmp(left_lo, Operand(right_lo)); | 611 __ cmp(left_lo, Operand(right_lo)); |
|
zra
2014/12/01 21:18:18
Do you need to branch to a label here? Maybe we ne
regis
2014/12/01 22:19:51
No, we only return the condition. The branch itsel
zra
2014/12/01 22:34:47
Ah, I see =) Didn't notice the call to EmitBranchO
regis
2014/12/01 22:44:00
I prefer to leave the code in sync with other plat
| |
| 612 __ LoadImmediate(out, 1); | 612 return lo_cond; |
| 613 __ LoadImmediate(out, 0, lo_false_cond); | |
| 614 __ Bind(&done); | |
| 615 | |
| 616 return NegateCondition(lo_false_cond); | |
| 617 } | 613 } |
| 618 | 614 |
| 619 | 615 |
| 620 static Condition TokenKindToDoubleCondition(Token::Kind kind) { | 616 static Condition TokenKindToDoubleCondition(Token::Kind kind) { |
| 621 switch (kind) { | 617 switch (kind) { |
| 622 case Token::kEQ: return EQ; | 618 case Token::kEQ: return EQ; |
| 623 case Token::kNE: return NE; | 619 case Token::kNE: return NE; |
| 624 case Token::kLT: return LT; | 620 case Token::kLT: return LT; |
| 625 case Token::kGT: return GT; | 621 case Token::kGT: return GT; |
| 626 case Token::kLTE: return LE; | 622 case Token::kLTE: return LE; |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 815 __ LoadObject(result_reg, Bool::True()); | 811 __ LoadObject(result_reg, Bool::True()); |
| 816 __ Bind(&done); | 812 __ Bind(&done); |
| 817 } | 813 } |
| 818 | 814 |
| 819 | 815 |
| 820 LocationSummary* RelationalOpInstr::MakeLocationSummary(Isolate* isolate, | 816 LocationSummary* RelationalOpInstr::MakeLocationSummary(Isolate* isolate, |
| 821 bool opt) const { | 817 bool opt) const { |
| 822 const intptr_t kNumInputs = 2; | 818 const intptr_t kNumInputs = 2; |
| 823 const intptr_t kNumTemps = 0; | 819 const intptr_t kNumTemps = 0; |
| 824 if (operation_cid() == kMintCid) { | 820 if (operation_cid() == kMintCid) { |
| 825 const intptr_t kNumTemps = 1; | 821 const intptr_t kNumTemps = 0; |
| 826 LocationSummary* locs = new(isolate) LocationSummary( | 822 LocationSummary* locs = new(isolate) LocationSummary( |
| 827 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 823 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 828 locs->set_in(0, Location::Pair(Location::RequiresRegister(), | 824 locs->set_in(0, Location::Pair(Location::RequiresRegister(), |
| 829 Location::RequiresRegister())); | 825 Location::RequiresRegister())); |
| 830 locs->set_in(1, Location::Pair(Location::RequiresRegister(), | 826 locs->set_in(1, Location::Pair(Location::RequiresRegister(), |
| 831 Location::RequiresRegister())); | 827 Location::RequiresRegister())); |
| 832 locs->set_temp(0, Location::RequiresRegister()); // TODO(regis): Improve. | |
| 833 locs->set_out(0, Location::RequiresRegister()); | 828 locs->set_out(0, Location::RequiresRegister()); |
| 834 return locs; | 829 return locs; |
| 835 } | 830 } |
| 836 if (operation_cid() == kDoubleCid) { | 831 if (operation_cid() == kDoubleCid) { |
| 837 LocationSummary* summary = new(isolate) LocationSummary( | 832 LocationSummary* summary = new(isolate) LocationSummary( |
| 838 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 833 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 839 summary->set_in(0, Location::RequiresFpuRegister()); | 834 summary->set_in(0, Location::RequiresFpuRegister()); |
| 840 summary->set_in(1, Location::RequiresFpuRegister()); | 835 summary->set_in(1, Location::RequiresFpuRegister()); |
| 841 summary->set_out(0, Location::RequiresRegister()); | 836 summary->set_out(0, Location::RequiresRegister()); |
| 842 return summary; | 837 return summary; |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 853 summary->set_out(0, Location::RequiresRegister()); | 848 summary->set_out(0, Location::RequiresRegister()); |
| 854 return summary; | 849 return summary; |
| 855 } | 850 } |
| 856 | 851 |
| 857 | 852 |
| 858 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 853 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 859 BranchLabels labels) { | 854 BranchLabels labels) { |
| 860 if (operation_cid() == kSmiCid) { | 855 if (operation_cid() == kSmiCid) { |
| 861 return EmitSmiComparisonOp(compiler, locs(), kind()); | 856 return EmitSmiComparisonOp(compiler, locs(), kind()); |
| 862 } else if (operation_cid() == kMintCid) { | 857 } else if (operation_cid() == kMintCid) { |
| 863 return EmitUnboxedMintComparisonOp(compiler, locs(), kind()); | 858 return EmitUnboxedMintComparisonOp(compiler, locs(), kind(), labels); |
| 864 } else { | 859 } else { |
| 865 ASSERT(operation_cid() == kDoubleCid); | 860 ASSERT(operation_cid() == kDoubleCid); |
| 866 return EmitDoubleComparisonOp(compiler, locs(), kind()); | 861 return EmitDoubleComparisonOp(compiler, locs(), kind()); |
| 867 } | 862 } |
| 868 } | 863 } |
| 869 | 864 |
| 870 | 865 |
| 871 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 866 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 872 // The ARM code does not use true- and false-labels here. | 867 Label is_true, is_false; |
| 873 BranchLabels labels = { NULL, NULL, NULL }; | 868 BranchLabels labels = { &is_true, &is_false, &is_false }; |
| 874 Condition true_condition = EmitComparisonCode(compiler, labels); | 869 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 875 | 870 |
| 876 const Register result = locs()->out(0).reg(); | 871 const Register result = locs()->out(0).reg(); |
| 877 if (operation_cid() == kSmiCid) { | 872 if (operation_cid() == kSmiCid) { |
| 878 __ LoadObject(result, Bool::True(), true_condition); | 873 __ LoadObject(result, Bool::True(), true_condition); |
| 879 __ LoadObject(result, Bool::False(), NegateCondition(true_condition)); | 874 __ LoadObject(result, Bool::False(), NegateCondition(true_condition)); |
| 880 } else if (operation_cid() == kMintCid) { | 875 } else if (operation_cid() == kMintCid) { |
| 881 const Register cr = locs()->temp(0).reg(); | 876 EmitBranchOnCondition(compiler, true_condition, labels); |
| 877 Label done; | |
| 878 __ Bind(&is_false); | |
| 879 __ LoadObject(result, Bool::False()); | |
| 880 __ b(&done); | |
| 881 __ Bind(&is_true); | |
| 882 __ LoadObject(result, Bool::True()); | 882 __ LoadObject(result, Bool::True()); |
| 883 __ CompareImmediate(cr, 1); | 883 __ Bind(&done); |
| 884 __ LoadObject(result, Bool::False(), NE); | |
| 885 } else { | 884 } else { |
| 886 ASSERT(operation_cid() == kDoubleCid); | 885 ASSERT(operation_cid() == kDoubleCid); |
| 887 Label done; | 886 Label done; |
| 888 __ LoadObject(result, Bool::False()); | 887 __ LoadObject(result, Bool::False()); |
| 889 if (true_condition != NE) { | 888 if (true_condition != NE) { |
| 890 __ b(&done, VS); // x == NaN -> false, x != NaN -> true. | 889 __ b(&done, VS); // x == NaN -> false, x != NaN -> true. |
| 891 } | 890 } |
| 892 __ LoadObject(result, Bool::True(), true_condition); | 891 __ LoadObject(result, Bool::True(), true_condition); |
| 893 __ Bind(&done); | 892 __ Bind(&done); |
| 894 } | 893 } |
| 895 } | 894 } |
| 896 | 895 |
| 897 | 896 |
| 898 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 897 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 899 BranchInstr* branch) { | 898 BranchInstr* branch) { |
| 900 BranchLabels labels = compiler->CreateBranchLabels(branch); | 899 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 901 Condition true_condition = EmitComparisonCode(compiler, labels); | 900 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 902 | 901 |
| 903 if (operation_cid() == kSmiCid) { | 902 if ((operation_cid() == kSmiCid) || (operation_cid() == kMintCid)) { |
| 904 EmitBranchOnCondition(compiler, true_condition, labels); | 903 EmitBranchOnCondition(compiler, true_condition, labels); |
| 905 } else if (operation_cid() == kMintCid) { | |
| 906 const Register result = locs()->temp(0).reg(); // TODO(regis): Improve. | |
| 907 __ CompareImmediate(result, 1); | |
| 908 __ b(labels.true_label, EQ); | |
| 909 __ b(labels.false_label, NE); | |
| 910 } else if (operation_cid() == kDoubleCid) { | 904 } else if (operation_cid() == kDoubleCid) { |
| 911 Label* nan_result = (true_condition == NE) ? | 905 Label* nan_result = (true_condition == NE) ? |
| 912 labels.true_label : labels.false_label; | 906 labels.true_label : labels.false_label; |
| 913 __ b(nan_result, VS); | 907 __ b(nan_result, VS); |
| 914 EmitBranchOnCondition(compiler, true_condition, labels); | 908 EmitBranchOnCondition(compiler, true_condition, labels); |
| 915 } | 909 } |
| 916 } | 910 } |
| 917 | 911 |
| 918 | 912 |
| 919 LocationSummary* NativeCallInstr::MakeLocationSummary(Isolate* isolate, | 913 LocationSummary* NativeCallInstr::MakeLocationSummary(Isolate* isolate, |
| (...skipping 5983 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6903 compiler->GenerateCall(token_pos(), &label, stub_kind_, locs()); | 6897 compiler->GenerateCall(token_pos(), &label, stub_kind_, locs()); |
| 6904 #if defined(DEBUG) | 6898 #if defined(DEBUG) |
| 6905 __ LoadImmediate(R4, kInvalidObjectPointer); | 6899 __ LoadImmediate(R4, kInvalidObjectPointer); |
| 6906 __ LoadImmediate(R5, kInvalidObjectPointer); | 6900 __ LoadImmediate(R5, kInvalidObjectPointer); |
| 6907 #endif | 6901 #endif |
| 6908 } | 6902 } |
| 6909 | 6903 |
| 6910 } // namespace dart | 6904 } // namespace dart |
| 6911 | 6905 |
| 6912 #endif // defined TARGET_ARCH_ARM | 6906 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |