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_IA32. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. |
6 #if defined(TARGET_ARCH_IA32) | 6 #if defined(TARGET_ARCH_IA32) |
7 | 7 |
8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
9 | 9 |
10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
(...skipping 582 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
593 return EmitSmiComparisonOp(compiler, *locs(), kind(), labels); | 593 return EmitSmiComparisonOp(compiler, *locs(), kind(), labels); |
594 } else if (operation_cid() == kMintCid) { | 594 } else if (operation_cid() == kMintCid) { |
595 return EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), labels); | 595 return EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), labels); |
596 } else { | 596 } else { |
597 ASSERT(operation_cid() == kDoubleCid); | 597 ASSERT(operation_cid() == kDoubleCid); |
598 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); | 598 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); |
599 } | 599 } |
600 } | 600 } |
601 | 601 |
602 | 602 |
603 void ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 603 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 604 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); |
| 605 |
604 Label is_true, is_false; | 606 Label is_true, is_false; |
605 BranchLabels labels = {&is_true, &is_false, &is_false}; | 607 BranchLabels labels = {&is_true, &is_false, &is_false}; |
606 Condition true_condition = EmitComparisonCode(compiler, labels); | 608 Condition true_condition = EmitComparisonCode(compiler, labels); |
607 if (true_condition != INVALID_CONDITION) { | 609 EmitBranchOnCondition(compiler, true_condition, labels); |
608 EmitBranchOnCondition(compiler, true_condition, labels); | |
609 } | |
610 | 610 |
611 Register result = locs()->out(0).reg(); | 611 Register result = locs()->out(0).reg(); |
612 Label done; | 612 Label done; |
613 __ Bind(&is_false); | 613 __ Bind(&is_false); |
614 __ LoadObject(result, Bool::False()); | 614 __ LoadObject(result, Bool::False()); |
615 __ jmp(&done, Assembler::kNearJump); | 615 __ jmp(&done, Assembler::kNearJump); |
616 __ Bind(&is_true); | 616 __ Bind(&is_true); |
617 __ LoadObject(result, Bool::True()); | 617 __ LoadObject(result, Bool::True()); |
618 __ Bind(&done); | 618 __ Bind(&done); |
619 } | 619 } |
620 | 620 |
621 | 621 |
622 void ComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 622 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
623 BranchInstr* branch) { | 623 BranchInstr* branch) { |
| 624 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); |
| 625 |
624 BranchLabels labels = compiler->CreateBranchLabels(branch); | 626 BranchLabels labels = compiler->CreateBranchLabels(branch); |
625 Condition true_condition = EmitComparisonCode(compiler, labels); | 627 Condition true_condition = EmitComparisonCode(compiler, labels); |
626 if (true_condition != INVALID_CONDITION) { | 628 EmitBranchOnCondition(compiler, true_condition, labels); |
627 EmitBranchOnCondition(compiler, true_condition, labels); | |
628 } | |
629 } | 629 } |
630 | 630 |
631 | 631 |
632 LocationSummary* TestSmiInstr::MakeLocationSummary(Zone* zone, bool opt) const { | 632 LocationSummary* TestSmiInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
633 const intptr_t kNumInputs = 2; | 633 const intptr_t kNumInputs = 2; |
634 const intptr_t kNumTemps = 0; | 634 const intptr_t kNumTemps = 0; |
635 LocationSummary* locs = new (zone) | 635 LocationSummary* locs = new (zone) |
636 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 636 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
637 locs->set_in(0, Location::RequiresRegister()); | 637 locs->set_in(0, Location::RequiresRegister()); |
638 // Only one input can be a constant operand. The case of two constant | 638 // Only one input can be a constant operand. The case of two constant |
(...skipping 12 matching lines...) Expand all Loading... |
651 const int32_t imm = reinterpret_cast<int32_t>(right.constant().raw()); | 651 const int32_t imm = reinterpret_cast<int32_t>(right.constant().raw()); |
652 __ testl(left, Immediate(imm)); | 652 __ testl(left, Immediate(imm)); |
653 } else { | 653 } else { |
654 __ testl(left, right.reg()); | 654 __ testl(left, right.reg()); |
655 } | 655 } |
656 Condition true_condition = (kind() == Token::kNE) ? NOT_ZERO : ZERO; | 656 Condition true_condition = (kind() == Token::kNE) ? NOT_ZERO : ZERO; |
657 return true_condition; | 657 return true_condition; |
658 } | 658 } |
659 | 659 |
660 | 660 |
| 661 void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 662 // Never emitted outside of the BranchInstr. |
| 663 UNREACHABLE(); |
| 664 } |
| 665 |
| 666 |
| 667 void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 668 BranchInstr* branch) { |
| 669 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 670 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 671 EmitBranchOnCondition(compiler, true_condition, labels); |
| 672 } |
| 673 |
| 674 |
661 LocationSummary* TestCidsInstr::MakeLocationSummary(Zone* zone, | 675 LocationSummary* TestCidsInstr::MakeLocationSummary(Zone* zone, |
662 bool opt) const { | 676 bool opt) const { |
663 const intptr_t kNumInputs = 1; | 677 const intptr_t kNumInputs = 1; |
664 const intptr_t kNumTemps = 1; | 678 const intptr_t kNumTemps = 1; |
665 LocationSummary* locs = new (zone) | 679 LocationSummary* locs = new (zone) |
666 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 680 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
667 locs->set_in(0, Location::RequiresRegister()); | 681 locs->set_in(0, Location::RequiresRegister()); |
668 locs->set_temp(0, Location::RequiresRegister()); | 682 locs->set_temp(0, Location::RequiresRegister()); |
669 locs->set_out(0, Location::RequiresRegister()); | 683 locs->set_out(0, Location::RequiresRegister()); |
670 return locs; | 684 return locs; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
702 // If the cid is not in the list, jump to the opposite label from the cids | 716 // If the cid is not in the list, jump to the opposite label from the cids |
703 // that are in the list. These must be all the same (see asserts in the | 717 // that are in the list. These must be all the same (see asserts in the |
704 // constructor). | 718 // constructor). |
705 Label* target = result ? labels.false_label : labels.true_label; | 719 Label* target = result ? labels.false_label : labels.true_label; |
706 if (target != labels.fall_through) { | 720 if (target != labels.fall_through) { |
707 __ jmp(target); | 721 __ jmp(target); |
708 } | 722 } |
709 } else { | 723 } else { |
710 __ jmp(deopt); | 724 __ jmp(deopt); |
711 } | 725 } |
712 // Dummy result as this method already did the jump, there's no need | 726 // Dummy result as the last instruction is a jump, any conditional |
713 // for the caller to branch on a condition. | 727 // branch using the result will therefore be skipped. |
714 return INVALID_CONDITION; | 728 return ZERO; |
715 } | 729 } |
716 | 730 |
717 | 731 |
| 732 void TestCidsInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 733 BranchInstr* branch) { |
| 734 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 735 EmitComparisonCode(compiler, labels); |
| 736 } |
| 737 |
| 738 |
| 739 void TestCidsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 740 Register result_reg = locs()->out(0).reg(); |
| 741 Label is_true, is_false, done; |
| 742 BranchLabels labels = {&is_true, &is_false, &is_false}; |
| 743 EmitComparisonCode(compiler, labels); |
| 744 __ Bind(&is_false); |
| 745 __ LoadObject(result_reg, Bool::False()); |
| 746 __ jmp(&done, Assembler::kNearJump); |
| 747 __ Bind(&is_true); |
| 748 __ LoadObject(result_reg, Bool::True()); |
| 749 __ Bind(&done); |
| 750 } |
| 751 |
| 752 |
718 LocationSummary* RelationalOpInstr::MakeLocationSummary(Zone* zone, | 753 LocationSummary* RelationalOpInstr::MakeLocationSummary(Zone* zone, |
719 bool opt) const { | 754 bool opt) const { |
720 const intptr_t kNumInputs = 2; | 755 const intptr_t kNumInputs = 2; |
721 const intptr_t kNumTemps = 0; | 756 const intptr_t kNumTemps = 0; |
722 if (operation_cid() == kMintCid) { | 757 if (operation_cid() == kMintCid) { |
723 const intptr_t kNumTemps = 0; | 758 const intptr_t kNumTemps = 0; |
724 LocationSummary* locs = new (zone) | 759 LocationSummary* locs = new (zone) |
725 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 760 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
726 locs->set_in(0, Location::Pair(Location::RequiresRegister(), | 761 locs->set_in(0, Location::Pair(Location::RequiresRegister(), |
727 Location::RequiresRegister())); | 762 Location::RequiresRegister())); |
(...skipping 30 matching lines...) Expand all Loading... |
758 return EmitSmiComparisonOp(compiler, *locs(), kind(), labels); | 793 return EmitSmiComparisonOp(compiler, *locs(), kind(), labels); |
759 } else if (operation_cid() == kMintCid) { | 794 } else if (operation_cid() == kMintCid) { |
760 return EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), labels); | 795 return EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), labels); |
761 } else { | 796 } else { |
762 ASSERT(operation_cid() == kDoubleCid); | 797 ASSERT(operation_cid() == kDoubleCid); |
763 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); | 798 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); |
764 } | 799 } |
765 } | 800 } |
766 | 801 |
767 | 802 |
| 803 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 804 Label is_true, is_false; |
| 805 BranchLabels labels = {&is_true, &is_false, &is_false}; |
| 806 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 807 EmitBranchOnCondition(compiler, true_condition, labels); |
| 808 |
| 809 Register result = locs()->out(0).reg(); |
| 810 Label done; |
| 811 __ Bind(&is_false); |
| 812 __ LoadObject(result, Bool::False()); |
| 813 __ jmp(&done, Assembler::kNearJump); |
| 814 __ Bind(&is_true); |
| 815 __ LoadObject(result, Bool::True()); |
| 816 __ Bind(&done); |
| 817 } |
| 818 |
| 819 |
| 820 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 821 BranchInstr* branch) { |
| 822 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 823 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 824 EmitBranchOnCondition(compiler, true_condition, labels); |
| 825 } |
| 826 |
| 827 |
768 LocationSummary* NativeCallInstr::MakeLocationSummary(Zone* zone, | 828 LocationSummary* NativeCallInstr::MakeLocationSummary(Zone* zone, |
769 bool opt) const { | 829 bool opt) const { |
770 return MakeCallSummary(zone); | 830 return MakeCallSummary(zone); |
771 } | 831 } |
772 | 832 |
773 | 833 |
774 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 834 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
775 SetupNative(); | 835 SetupNative(); |
776 Register result = locs()->out(0).reg(); | 836 Register result = locs()->out(0).reg(); |
777 const intptr_t argc_tag = NativeArguments::ComputeArgcTag(function()); | 837 const intptr_t argc_tag = NativeArguments::ComputeArgcTag(function()); |
(...skipping 3150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3928 __ AddImmediate(ESP, Immediate(kDoubleSize)); | 3988 __ AddImmediate(ESP, Immediate(kDoubleSize)); |
3929 // Mask off sign bit. | 3989 // Mask off sign bit. |
3930 __ andl(temp, Immediate(0x7FFFFFFF)); | 3990 __ andl(temp, Immediate(0x7FFFFFFF)); |
3931 // Compare with +infinity. | 3991 // Compare with +infinity. |
3932 __ cmpl(temp, Immediate(0x7FF00000)); | 3992 __ cmpl(temp, Immediate(0x7FF00000)); |
3933 return is_negated ? NOT_EQUAL : EQUAL; | 3993 return is_negated ? NOT_EQUAL : EQUAL; |
3934 } | 3994 } |
3935 } | 3995 } |
3936 | 3996 |
3937 | 3997 |
| 3998 void DoubleTestOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 3999 BranchInstr* branch) { |
| 4000 ASSERT(compiler->is_optimizing()); |
| 4001 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 4002 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 4003 EmitBranchOnCondition(compiler, true_condition, labels); |
| 4004 } |
| 4005 |
| 4006 |
| 4007 void DoubleTestOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4008 Label is_true, is_false; |
| 4009 BranchLabels labels = {&is_true, &is_false, &is_false}; |
| 4010 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 4011 EmitBranchOnCondition(compiler, true_condition, labels); |
| 4012 |
| 4013 Register result = locs()->out(0).reg(); |
| 4014 Label done; |
| 4015 __ Bind(&is_false); |
| 4016 __ LoadObject(result, Bool::False()); |
| 4017 __ jmp(&done); |
| 4018 __ Bind(&is_true); |
| 4019 __ LoadObject(result, Bool::True()); |
| 4020 __ Bind(&done); |
| 4021 } |
| 4022 |
| 4023 |
3938 LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(Zone* zone, | 4024 LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(Zone* zone, |
3939 bool opt) const { | 4025 bool opt) const { |
3940 const intptr_t kNumInputs = 2; | 4026 const intptr_t kNumInputs = 2; |
3941 const intptr_t kNumTemps = 0; | 4027 const intptr_t kNumTemps = 0; |
3942 LocationSummary* summary = new (zone) | 4028 LocationSummary* summary = new (zone) |
3943 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4029 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3944 summary->set_in(0, Location::RequiresFpuRegister()); | 4030 summary->set_in(0, Location::RequiresFpuRegister()); |
3945 summary->set_in(1, Location::RequiresFpuRegister()); | 4031 summary->set_in(1, Location::RequiresFpuRegister()); |
3946 summary->set_out(0, Location::SameAsFirstInput()); | 4032 summary->set_out(0, Location::SameAsFirstInput()); |
3947 return summary; | 4033 return summary; |
(...skipping 2676 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6624 left.reg(), right.reg(), needs_number_check(), token_pos(), deopt_id_); | 6710 left.reg(), right.reg(), needs_number_check(), token_pos(), deopt_id_); |
6625 } | 6711 } |
6626 if (kind() != Token::kEQ_STRICT) { | 6712 if (kind() != Token::kEQ_STRICT) { |
6627 ASSERT(kind() == Token::kNE_STRICT); | 6713 ASSERT(kind() == Token::kNE_STRICT); |
6628 true_condition = NegateCondition(true_condition); | 6714 true_condition = NegateCondition(true_condition); |
6629 } | 6715 } |
6630 return true_condition; | 6716 return true_condition; |
6631 } | 6717 } |
6632 | 6718 |
6633 | 6719 |
| 6720 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6721 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
| 6722 |
| 6723 Label is_true, is_false; |
| 6724 BranchLabels labels = {&is_true, &is_false, &is_false}; |
| 6725 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 6726 EmitBranchOnCondition(compiler, true_condition, labels); |
| 6727 |
| 6728 Register result = locs()->out(0).reg(); |
| 6729 Label done; |
| 6730 __ Bind(&is_false); |
| 6731 __ LoadObject(result, Bool::False()); |
| 6732 __ jmp(&done, Assembler::kNearJump); |
| 6733 __ Bind(&is_true); |
| 6734 __ LoadObject(result, Bool::True()); |
| 6735 __ Bind(&done); |
| 6736 } |
| 6737 |
| 6738 |
| 6739 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 6740 BranchInstr* branch) { |
| 6741 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
| 6742 |
| 6743 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 6744 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 6745 EmitBranchOnCondition(compiler, true_condition, labels); |
| 6746 } |
| 6747 |
| 6748 |
6634 // Detect pattern when one value is zero and another is a power of 2. | 6749 // Detect pattern when one value is zero and another is a power of 2. |
6635 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) { | 6750 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) { |
6636 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) || | 6751 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) || |
6637 (Utils::IsPowerOfTwo(v2) && (v1 == 0)); | 6752 (Utils::IsPowerOfTwo(v2) && (v1 == 0)); |
6638 } | 6753 } |
6639 | 6754 |
6640 | 6755 |
6641 LocationSummary* IfThenElseInstr::MakeLocationSummary(Zone* zone, | 6756 LocationSummary* IfThenElseInstr::MakeLocationSummary(Zone* zone, |
6642 bool opt) const { | 6757 bool opt) const { |
6643 comparison()->InitializeLocationSummary(zone, opt); | 6758 comparison()->InitializeLocationSummary(zone, opt); |
6644 // TODO(vegorov): support byte register constraints in the register allocator. | 6759 // TODO(vegorov): support byte register constraints in the register allocator. |
6645 comparison()->locs()->set_out(0, Location::RegisterLocation(EDX)); | 6760 comparison()->locs()->set_out(0, Location::RegisterLocation(EDX)); |
6646 return comparison()->locs(); | 6761 return comparison()->locs(); |
6647 } | 6762 } |
6648 | 6763 |
6649 | 6764 |
6650 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6765 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6651 ASSERT(locs()->out(0).reg() == EDX); | 6766 ASSERT(locs()->out(0).reg() == EDX); |
6652 | 6767 |
6653 // Clear upper part of the out register. We are going to use setcc on it | 6768 // Clear upper part of the out register. We are going to use setcc on it |
6654 // which is a byte move. | 6769 // which is a byte move. |
6655 __ xorl(EDX, EDX); | 6770 __ xorl(EDX, EDX); |
6656 | 6771 |
6657 // Emit comparison code. This must not overwrite the result register. | 6772 // Emit comparison code. This must not overwrite the result register. |
6658 // IfThenElseInstr::Supports() should prevent EmitComparisonCode from using | |
6659 // the labels or returning an invalid condition. | |
6660 BranchLabels labels = {NULL, NULL, NULL}; | 6773 BranchLabels labels = {NULL, NULL, NULL}; |
6661 Condition true_condition = comparison()->EmitComparisonCode(compiler, labels); | 6774 Condition true_condition = comparison()->EmitComparisonCode(compiler, labels); |
6662 ASSERT(true_condition != INVALID_CONDITION); | |
6663 | 6775 |
6664 const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_); | 6776 const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_); |
6665 | 6777 |
6666 intptr_t true_value = if_true_; | 6778 intptr_t true_value = if_true_; |
6667 intptr_t false_value = if_false_; | 6779 intptr_t false_value = if_false_; |
6668 | 6780 |
6669 if (is_power_of_two_kind) { | 6781 if (is_power_of_two_kind) { |
6670 if (true_value == 0) { | 6782 if (true_value == 0) { |
6671 // We need to have zero in EDX on true_condition. | 6783 // We need to have zero in EDX on true_condition. |
6672 true_condition = NegateCondition(true_condition); | 6784 true_condition = NegateCondition(true_condition); |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6809 __ Drop(1); | 6921 __ Drop(1); |
6810 __ popl(result); | 6922 __ popl(result); |
6811 } | 6923 } |
6812 | 6924 |
6813 | 6925 |
6814 } // namespace dart | 6926 } // namespace dart |
6815 | 6927 |
6816 #undef __ | 6928 #undef __ |
6817 | 6929 |
6818 #endif // defined TARGET_ARCH_IA32 | 6930 #endif // defined TARGET_ARCH_IA32 |
OLD | NEW |