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 EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 603 void ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
604 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); | |
605 | |
606 Label is_true, is_false; | 604 Label is_true, is_false; |
607 BranchLabels labels = {&is_true, &is_false, &is_false}; | 605 BranchLabels labels = {&is_true, &is_false, &is_false}; |
608 Condition true_condition = EmitComparisonCode(compiler, labels); | 606 Condition true_condition = EmitComparisonCode(compiler, labels); |
609 EmitBranchOnCondition(compiler, true_condition, labels); | 607 if (true_condition != INVALID_CONDITION) { |
| 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 EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 622 void ComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
623 BranchInstr* branch) { | 623 BranchInstr* branch) { |
624 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); | |
625 | |
626 BranchLabels labels = compiler->CreateBranchLabels(branch); | 624 BranchLabels labels = compiler->CreateBranchLabels(branch); |
627 Condition true_condition = EmitComparisonCode(compiler, labels); | 625 Condition true_condition = EmitComparisonCode(compiler, labels); |
628 EmitBranchOnCondition(compiler, true_condition, labels); | 626 if (true_condition != INVALID_CONDITION) { |
| 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 | |
675 LocationSummary* TestCidsInstr::MakeLocationSummary(Zone* zone, | 661 LocationSummary* TestCidsInstr::MakeLocationSummary(Zone* zone, |
676 bool opt) const { | 662 bool opt) const { |
677 const intptr_t kNumInputs = 1; | 663 const intptr_t kNumInputs = 1; |
678 const intptr_t kNumTemps = 1; | 664 const intptr_t kNumTemps = 1; |
679 LocationSummary* locs = new (zone) | 665 LocationSummary* locs = new (zone) |
680 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 666 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
681 locs->set_in(0, Location::RequiresRegister()); | 667 locs->set_in(0, Location::RequiresRegister()); |
682 locs->set_temp(0, Location::RequiresRegister()); | 668 locs->set_temp(0, Location::RequiresRegister()); |
683 locs->set_out(0, Location::RequiresRegister()); | 669 locs->set_out(0, Location::RequiresRegister()); |
684 return locs; | 670 return locs; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
716 // If the cid is not in the list, jump to the opposite label from the cids | 702 // If the cid is not in the list, jump to the opposite label from the cids |
717 // that are in the list. These must be all the same (see asserts in the | 703 // that are in the list. These must be all the same (see asserts in the |
718 // constructor). | 704 // constructor). |
719 Label* target = result ? labels.false_label : labels.true_label; | 705 Label* target = result ? labels.false_label : labels.true_label; |
720 if (target != labels.fall_through) { | 706 if (target != labels.fall_through) { |
721 __ jmp(target); | 707 __ jmp(target); |
722 } | 708 } |
723 } else { | 709 } else { |
724 __ jmp(deopt); | 710 __ jmp(deopt); |
725 } | 711 } |
726 // Dummy result as the last instruction is a jump, any conditional | 712 // Dummy result as this method already did the jump, there's no need |
727 // branch using the result will therefore be skipped. | 713 // for the caller to branch on a condition. |
728 return ZERO; | 714 return INVALID_CONDITION; |
729 } | 715 } |
730 | 716 |
731 | 717 |
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 | |
753 LocationSummary* RelationalOpInstr::MakeLocationSummary(Zone* zone, | 718 LocationSummary* RelationalOpInstr::MakeLocationSummary(Zone* zone, |
754 bool opt) const { | 719 bool opt) const { |
755 const intptr_t kNumInputs = 2; | 720 const intptr_t kNumInputs = 2; |
756 const intptr_t kNumTemps = 0; | 721 const intptr_t kNumTemps = 0; |
757 if (operation_cid() == kMintCid) { | 722 if (operation_cid() == kMintCid) { |
758 const intptr_t kNumTemps = 0; | 723 const intptr_t kNumTemps = 0; |
759 LocationSummary* locs = new (zone) | 724 LocationSummary* locs = new (zone) |
760 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 725 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
761 locs->set_in(0, Location::Pair(Location::RequiresRegister(), | 726 locs->set_in(0, Location::Pair(Location::RequiresRegister(), |
762 Location::RequiresRegister())); | 727 Location::RequiresRegister())); |
(...skipping 30 matching lines...) Expand all Loading... |
793 return EmitSmiComparisonOp(compiler, *locs(), kind(), labels); | 758 return EmitSmiComparisonOp(compiler, *locs(), kind(), labels); |
794 } else if (operation_cid() == kMintCid) { | 759 } else if (operation_cid() == kMintCid) { |
795 return EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), labels); | 760 return EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), labels); |
796 } else { | 761 } else { |
797 ASSERT(operation_cid() == kDoubleCid); | 762 ASSERT(operation_cid() == kDoubleCid); |
798 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); | 763 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); |
799 } | 764 } |
800 } | 765 } |
801 | 766 |
802 | 767 |
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 | |
828 LocationSummary* NativeCallInstr::MakeLocationSummary(Zone* zone, | 768 LocationSummary* NativeCallInstr::MakeLocationSummary(Zone* zone, |
829 bool opt) const { | 769 bool opt) const { |
830 return MakeCallSummary(zone); | 770 return MakeCallSummary(zone); |
831 } | 771 } |
832 | 772 |
833 | 773 |
834 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 774 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
835 SetupNative(); | 775 SetupNative(); |
836 Register result = locs()->out(0).reg(); | 776 Register result = locs()->out(0).reg(); |
837 const intptr_t argc_tag = NativeArguments::ComputeArgcTag(function()); | 777 const intptr_t argc_tag = NativeArguments::ComputeArgcTag(function()); |
(...skipping 3150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3988 __ AddImmediate(ESP, Immediate(kDoubleSize)); | 3928 __ AddImmediate(ESP, Immediate(kDoubleSize)); |
3989 // Mask off sign bit. | 3929 // Mask off sign bit. |
3990 __ andl(temp, Immediate(0x7FFFFFFF)); | 3930 __ andl(temp, Immediate(0x7FFFFFFF)); |
3991 // Compare with +infinity. | 3931 // Compare with +infinity. |
3992 __ cmpl(temp, Immediate(0x7FF00000)); | 3932 __ cmpl(temp, Immediate(0x7FF00000)); |
3993 return is_negated ? NOT_EQUAL : EQUAL; | 3933 return is_negated ? NOT_EQUAL : EQUAL; |
3994 } | 3934 } |
3995 } | 3935 } |
3996 | 3936 |
3997 | 3937 |
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 | |
4024 LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(Zone* zone, | 3938 LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(Zone* zone, |
4025 bool opt) const { | 3939 bool opt) const { |
4026 const intptr_t kNumInputs = 2; | 3940 const intptr_t kNumInputs = 2; |
4027 const intptr_t kNumTemps = 0; | 3941 const intptr_t kNumTemps = 0; |
4028 LocationSummary* summary = new (zone) | 3942 LocationSummary* summary = new (zone) |
4029 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3943 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4030 summary->set_in(0, Location::RequiresFpuRegister()); | 3944 summary->set_in(0, Location::RequiresFpuRegister()); |
4031 summary->set_in(1, Location::RequiresFpuRegister()); | 3945 summary->set_in(1, Location::RequiresFpuRegister()); |
4032 summary->set_out(0, Location::SameAsFirstInput()); | 3946 summary->set_out(0, Location::SameAsFirstInput()); |
4033 return summary; | 3947 return summary; |
(...skipping 2676 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6710 left.reg(), right.reg(), needs_number_check(), token_pos(), deopt_id_); | 6624 left.reg(), right.reg(), needs_number_check(), token_pos(), deopt_id_); |
6711 } | 6625 } |
6712 if (kind() != Token::kEQ_STRICT) { | 6626 if (kind() != Token::kEQ_STRICT) { |
6713 ASSERT(kind() == Token::kNE_STRICT); | 6627 ASSERT(kind() == Token::kNE_STRICT); |
6714 true_condition = NegateCondition(true_condition); | 6628 true_condition = NegateCondition(true_condition); |
6715 } | 6629 } |
6716 return true_condition; | 6630 return true_condition; |
6717 } | 6631 } |
6718 | 6632 |
6719 | 6633 |
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 | |
6749 // Detect pattern when one value is zero and another is a power of 2. | 6634 // Detect pattern when one value is zero and another is a power of 2. |
6750 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) { | 6635 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) { |
6751 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) || | 6636 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) || |
6752 (Utils::IsPowerOfTwo(v2) && (v1 == 0)); | 6637 (Utils::IsPowerOfTwo(v2) && (v1 == 0)); |
6753 } | 6638 } |
6754 | 6639 |
6755 | 6640 |
6756 LocationSummary* IfThenElseInstr::MakeLocationSummary(Zone* zone, | 6641 LocationSummary* IfThenElseInstr::MakeLocationSummary(Zone* zone, |
6757 bool opt) const { | 6642 bool opt) const { |
6758 comparison()->InitializeLocationSummary(zone, opt); | 6643 comparison()->InitializeLocationSummary(zone, opt); |
6759 // TODO(vegorov): support byte register constraints in the register allocator. | 6644 // TODO(vegorov): support byte register constraints in the register allocator. |
6760 comparison()->locs()->set_out(0, Location::RegisterLocation(EDX)); | 6645 comparison()->locs()->set_out(0, Location::RegisterLocation(EDX)); |
6761 return comparison()->locs(); | 6646 return comparison()->locs(); |
6762 } | 6647 } |
6763 | 6648 |
6764 | 6649 |
6765 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6650 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6766 ASSERT(locs()->out(0).reg() == EDX); | 6651 ASSERT(locs()->out(0).reg() == EDX); |
6767 | 6652 |
6768 // Clear upper part of the out register. We are going to use setcc on it | 6653 // Clear upper part of the out register. We are going to use setcc on it |
6769 // which is a byte move. | 6654 // which is a byte move. |
6770 __ xorl(EDX, EDX); | 6655 __ xorl(EDX, EDX); |
6771 | 6656 |
6772 // Emit comparison code. This must not overwrite the result register. | 6657 // 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. |
6773 BranchLabels labels = {NULL, NULL, NULL}; | 6660 BranchLabels labels = {NULL, NULL, NULL}; |
6774 Condition true_condition = comparison()->EmitComparisonCode(compiler, labels); | 6661 Condition true_condition = comparison()->EmitComparisonCode(compiler, labels); |
| 6662 ASSERT(true_condition != INVALID_CONDITION); |
6775 | 6663 |
6776 const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_); | 6664 const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_); |
6777 | 6665 |
6778 intptr_t true_value = if_true_; | 6666 intptr_t true_value = if_true_; |
6779 intptr_t false_value = if_false_; | 6667 intptr_t false_value = if_false_; |
6780 | 6668 |
6781 if (is_power_of_two_kind) { | 6669 if (is_power_of_two_kind) { |
6782 if (true_value == 0) { | 6670 if (true_value == 0) { |
6783 // We need to have zero in EDX on true_condition. | 6671 // We need to have zero in EDX on true_condition. |
6784 true_condition = NegateCondition(true_condition); | 6672 true_condition = NegateCondition(true_condition); |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6921 __ Drop(1); | 6809 __ Drop(1); |
6922 __ popl(result); | 6810 __ popl(result); |
6923 } | 6811 } |
6924 | 6812 |
6925 | 6813 |
6926 } // namespace dart | 6814 } // namespace dart |
6927 | 6815 |
6928 #undef __ | 6816 #undef __ |
6929 | 6817 |
6930 #endif // defined TARGET_ARCH_IA32 | 6818 #endif // defined TARGET_ARCH_IA32 |
OLD | NEW |