OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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_X64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. |
6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
7 | 7 |
8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
9 | 9 |
10 #include "lib/error.h" | 10 #include "lib/error.h" |
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
242 UNREACHABLE(); | 242 UNREACHABLE(); |
243 return OVERFLOW; | 243 return OVERFLOW; |
244 } | 244 } |
245 } | 245 } |
246 | 246 |
247 | 247 |
248 LocationSummary* EqualityCompareComp::MakeLocationSummary() const { | 248 LocationSummary* EqualityCompareComp::MakeLocationSummary() const { |
249 const intptr_t kNumInputs = 2; | 249 const intptr_t kNumInputs = 2; |
250 const bool is_checked_strict_equal = | 250 const bool is_checked_strict_equal = |
251 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); | 251 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); |
252 if ((receiver_class_id() == kSmiCid) || | 252 if (receiver_class_id() == kDoubleCid) { |
253 (receiver_class_id() == kDoubleCid) || | 253 const intptr_t kNumTemps = 0; |
254 is_checked_strict_equal) { | 254 LocationSummary* locs = |
255 const intptr_t kNumTemps = 1; | 255 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 256 locs->set_in(0, Location::RequiresXmmRegister()); |
| 257 locs->set_in(1, Location::RequiresXmmRegister()); |
| 258 locs->set_out(Location::RequiresRegister()); |
| 259 return locs; |
| 260 } |
| 261 if ((receiver_class_id() == kSmiCid) || is_checked_strict_equal) { |
| 262 const intptr_t kNumTemps = 1; |
256 LocationSummary* locs = | 263 LocationSummary* locs = |
257 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 264 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
258 locs->set_in(0, Location::RequiresRegister()); | 265 locs->set_in(0, Location::RequiresRegister()); |
259 locs->set_in(1, Location::RequiresRegister()); | 266 locs->set_in(1, Location::RequiresRegister()); |
260 locs->set_temp(0, Location::RequiresRegister()); | 267 locs->set_temp(0, Location::RequiresRegister()); |
261 locs->set_out(Location::RequiresRegister()); | 268 locs->set_out(Location::RequiresRegister()); |
262 return locs; | 269 return locs; |
263 } | 270 } |
264 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { | 271 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
265 const intptr_t kNumTemps = 1; | 272 const intptr_t kNumTemps = 1; |
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
583 default: | 590 default: |
584 UNREACHABLE(); | 591 UNREACHABLE(); |
585 return OVERFLOW; | 592 return OVERFLOW; |
586 } | 593 } |
587 } | 594 } |
588 | 595 |
589 | 596 |
590 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler, | 597 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler, |
591 const LocationSummary& locs, | 598 const LocationSummary& locs, |
592 Token::Kind kind, | 599 Token::Kind kind, |
593 BranchInstr* branch, | 600 BranchInstr* branch) { |
594 intptr_t deopt_id) { | 601 XmmRegister left = locs.in(0).xmm_reg(); |
595 Register left = locs.in(0).reg(); | 602 XmmRegister right = locs.in(1).xmm_reg(); |
596 Register right = locs.in(1).reg(); | |
597 // TODO(srdjan): temp is only needed if a conversion Smi->Double occurs. | |
598 Register temp = locs.temp(0).reg(); | |
599 Label* deopt = compiler->AddDeoptStub(deopt_id, kDeoptDoubleComparison); | |
600 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); | |
601 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); | |
602 | 603 |
603 Condition true_condition = TokenKindToDoubleCondition(kind); | 604 Condition true_condition = TokenKindToDoubleCondition(kind); |
604 if (branch != NULL) { | 605 if (branch != NULL) { |
605 compiler->EmitDoubleCompareBranch( | 606 compiler->EmitDoubleCompareBranch( |
606 true_condition, XMM0, XMM1, branch); | 607 true_condition, left, right, branch); |
607 } else { | 608 } else { |
608 compiler->EmitDoubleCompareBool( | 609 compiler->EmitDoubleCompareBool( |
609 true_condition, XMM0, XMM1, locs.out().reg()); | 610 true_condition, left, right, locs.out().reg()); |
610 } | 611 } |
611 } | 612 } |
612 | 613 |
613 | 614 |
614 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 615 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
615 ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE)); | 616 ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE)); |
616 BranchInstr* kNoBranch = NULL; | 617 BranchInstr* kNoBranch = NULL; |
617 if (receiver_class_id() == kSmiCid) { | 618 if (receiver_class_id() == kSmiCid) { |
618 // Deoptimizes if both arguments not Smi. | 619 // Deoptimizes if both arguments not Smi. |
619 EmitSmiComparisonOp(compiler, *locs(), kind(), kNoBranch, deopt_id()); | 620 EmitSmiComparisonOp(compiler, *locs(), kind(), kNoBranch, deopt_id()); |
620 return; | 621 return; |
621 } | 622 } |
622 if (receiver_class_id() == kDoubleCid) { | 623 if (receiver_class_id() == kDoubleCid) { |
623 // Deoptimizes if both arguments are Smi, or if none is Double or Smi. | 624 // Deoptimizes if both arguments are Smi, or if none is Double or Smi. |
624 EmitDoubleComparisonOp(compiler, *locs(), kind(), kNoBranch, deopt_id()); | 625 EmitDoubleComparisonOp(compiler, *locs(), kind(), kNoBranch); |
625 return; | 626 return; |
626 } | 627 } |
627 const bool is_checked_strict_equal = | 628 const bool is_checked_strict_equal = |
628 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); | 629 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); |
629 if (is_checked_strict_equal) { | 630 if (is_checked_strict_equal) { |
630 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), kNoBranch, | 631 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), kNoBranch, |
631 deopt_id()); | 632 deopt_id()); |
632 return; | 633 return; |
633 } | 634 } |
634 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { | 635 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
(...skipping 17 matching lines...) Expand all Loading... |
652 void EqualityCompareComp::EmitBranchCode(FlowGraphCompiler* compiler, | 653 void EqualityCompareComp::EmitBranchCode(FlowGraphCompiler* compiler, |
653 BranchInstr* branch) { | 654 BranchInstr* branch) { |
654 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); | 655 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); |
655 if (receiver_class_id() == kSmiCid) { | 656 if (receiver_class_id() == kSmiCid) { |
656 // Deoptimizes if both arguments not Smi. | 657 // Deoptimizes if both arguments not Smi. |
657 EmitSmiComparisonOp(compiler, *locs(), kind(), branch, deopt_id()); | 658 EmitSmiComparisonOp(compiler, *locs(), kind(), branch, deopt_id()); |
658 return; | 659 return; |
659 } | 660 } |
660 if (receiver_class_id() == kDoubleCid) { | 661 if (receiver_class_id() == kDoubleCid) { |
661 // Deoptimizes if both arguments are Smi, or if none is Double or Smi. | 662 // Deoptimizes if both arguments are Smi, or if none is Double or Smi. |
662 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch, deopt_id()); | 663 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch); |
663 return; | 664 return; |
664 } | 665 } |
665 const bool is_checked_strict_equal = | 666 const bool is_checked_strict_equal = |
666 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); | 667 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); |
667 if (is_checked_strict_equal) { | 668 if (is_checked_strict_equal) { |
668 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), branch, | 669 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), branch, |
669 deopt_id()); | 670 deopt_id()); |
670 return; | 671 return; |
671 } | 672 } |
672 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { | 673 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
(...skipping 11 matching lines...) Expand all Loading... |
684 Token::kEQ, // kNE reverse occurs at branch. | 685 Token::kEQ, // kNE reverse occurs at branch. |
685 locs()); | 686 locs()); |
686 Condition branch_condition = (kind() == Token::kNE) ? NOT_EQUAL : EQUAL; | 687 Condition branch_condition = (kind() == Token::kNE) ? NOT_EQUAL : EQUAL; |
687 __ CompareObject(RAX, compiler->bool_true()); | 688 __ CompareObject(RAX, compiler->bool_true()); |
688 branch->EmitBranchOnCondition(compiler, branch_condition); | 689 branch->EmitBranchOnCondition(compiler, branch_condition); |
689 } | 690 } |
690 | 691 |
691 | 692 |
692 LocationSummary* RelationalOpComp::MakeLocationSummary() const { | 693 LocationSummary* RelationalOpComp::MakeLocationSummary() const { |
693 const intptr_t kNumInputs = 2; | 694 const intptr_t kNumInputs = 2; |
694 if (operands_class_id() == kSmiCid || operands_class_id() == kDoubleCid) { | 695 if (operands_class_id() == kDoubleCid) { |
| 696 const intptr_t kNumTemps = 0; |
| 697 LocationSummary* summary = |
| 698 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 699 summary->set_in(0, Location::RequiresXmmRegister()); |
| 700 summary->set_in(1, Location::RequiresXmmRegister()); |
| 701 summary->set_out(Location::RequiresRegister()); |
| 702 return summary; |
| 703 } else if (operands_class_id() == kSmiCid) { |
695 const intptr_t kNumTemps = 1; | 704 const intptr_t kNumTemps = 1; |
696 LocationSummary* summary = | 705 LocationSummary* summary = |
697 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 706 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
698 summary->set_in(0, Location::RequiresRegister()); | 707 summary->set_in(0, Location::RequiresRegister()); |
699 summary->set_in(1, Location::RequiresRegister()); | 708 summary->set_in(1, Location::RequiresRegister()); |
700 summary->set_out(Location::RequiresRegister()); | 709 summary->set_out(Location::RequiresRegister()); |
701 summary->set_temp(0, Location::RequiresRegister()); | 710 summary->set_temp(0, Location::RequiresRegister()); |
702 return summary; | 711 return summary; |
703 } | 712 } |
704 const intptr_t kNumTemps = 0; | 713 const intptr_t kNumTemps = 0; |
705 LocationSummary* locs = | 714 LocationSummary* locs = |
706 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 715 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
707 // Pick arbitrary fixed input registers because this is a call. | 716 // Pick arbitrary fixed input registers because this is a call. |
708 locs->set_in(0, Location::RegisterLocation(RAX)); | 717 locs->set_in(0, Location::RegisterLocation(RAX)); |
709 locs->set_in(1, Location::RegisterLocation(RCX)); | 718 locs->set_in(1, Location::RegisterLocation(RCX)); |
710 locs->set_out(Location::RegisterLocation(RAX)); | 719 locs->set_out(Location::RegisterLocation(RAX)); |
711 return locs; | 720 return locs; |
712 } | 721 } |
713 | 722 |
714 | 723 |
715 void RelationalOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 724 void RelationalOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
716 if (operands_class_id() == kSmiCid) { | 725 if (operands_class_id() == kSmiCid) { |
717 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL, deopt_id()); | 726 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL, deopt_id()); |
718 return; | 727 return; |
719 } | 728 } |
720 if (operands_class_id() == kDoubleCid) { | 729 if (operands_class_id() == kDoubleCid) { |
721 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL, deopt_id()); | 730 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL); |
722 return; | 731 return; |
723 } | 732 } |
724 | 733 |
725 // Push arguments for the call. | 734 // Push arguments for the call. |
726 // TODO(fschneider): Split this instruction into different types to avoid | 735 // TODO(fschneider): Split this instruction into different types to avoid |
727 // explicitly pushing arguments to the call here. | 736 // explicitly pushing arguments to the call here. |
728 Register left = locs()->in(0).reg(); | 737 Register left = locs()->in(0).reg(); |
729 Register right = locs()->in(1).reg(); | 738 Register right = locs()->in(1).reg(); |
730 __ pushq(left); | 739 __ pushq(left); |
731 __ pushq(right); | 740 __ pushq(right); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
769 } | 778 } |
770 | 779 |
771 | 780 |
772 void RelationalOpComp::EmitBranchCode(FlowGraphCompiler* compiler, | 781 void RelationalOpComp::EmitBranchCode(FlowGraphCompiler* compiler, |
773 BranchInstr* branch) { | 782 BranchInstr* branch) { |
774 if (operands_class_id() == kSmiCid) { | 783 if (operands_class_id() == kSmiCid) { |
775 EmitSmiComparisonOp(compiler, *locs(), kind(), branch, deopt_id()); | 784 EmitSmiComparisonOp(compiler, *locs(), kind(), branch, deopt_id()); |
776 return; | 785 return; |
777 } | 786 } |
778 if (operands_class_id() == kDoubleCid) { | 787 if (operands_class_id() == kDoubleCid) { |
779 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch, deopt_id()); | 788 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch); |
780 return; | 789 return; |
781 } | 790 } |
782 EmitNativeCode(compiler); | 791 EmitNativeCode(compiler); |
783 __ CompareObject(RAX, compiler->bool_true()); | 792 __ CompareObject(RAX, compiler->bool_true()); |
784 branch->EmitBranchOnCondition(compiler, EQUAL); | 793 branch->EmitBranchOnCondition(compiler, EQUAL); |
785 } | 794 } |
786 | 795 |
787 | 796 |
788 LocationSummary* NativeCallComp::MakeLocationSummary() const { | 797 LocationSummary* NativeCallComp::MakeLocationSummary() const { |
789 const intptr_t kNumInputs = 0; | 798 const intptr_t kNumInputs = 0; |
(...skipping 1038 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1828 explicit BoxDoubleSlowPath(BoxDoubleComp* computation) | 1837 explicit BoxDoubleSlowPath(BoxDoubleComp* computation) |
1829 : computation_(computation) { } | 1838 : computation_(computation) { } |
1830 | 1839 |
1831 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 1840 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
1832 __ Bind(entry_label()); | 1841 __ Bind(entry_label()); |
1833 const Class& double_class = compiler->double_class(); | 1842 const Class& double_class = compiler->double_class(); |
1834 const Code& stub = | 1843 const Code& stub = |
1835 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 1844 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
1836 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 1845 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
1837 | 1846 |
1838 // TODO(vegorov): here stack map needs to be set up correctly to skip | |
1839 // double registers. | |
1840 LocationSummary* locs = computation_->locs(); | 1847 LocationSummary* locs = computation_->locs(); |
1841 locs->live_registers()->Remove(locs->out()); | 1848 locs->live_registers()->Remove(locs->out()); |
1842 | 1849 |
1843 compiler->SaveLiveRegisters(locs); | 1850 compiler->SaveLiveRegisters(locs); |
1844 compiler->GenerateCall(computation_->instance_call()->token_pos(), | 1851 compiler->GenerateCall(computation_->token_pos(), |
1845 &label, | 1852 &label, |
1846 PcDescriptors::kOther, | 1853 PcDescriptors::kOther, |
1847 locs); | 1854 locs); |
1848 if (RAX != locs->out().reg()) __ movq(locs->out().reg(), RAX); | 1855 if (RAX != locs->out().reg()) __ movq(locs->out().reg(), RAX); |
1849 compiler->RestoreLiveRegisters(locs); | 1856 compiler->RestoreLiveRegisters(locs); |
1850 | 1857 |
1851 __ jmp(exit_label()); | 1858 __ jmp(exit_label()); |
1852 } | 1859 } |
1853 | 1860 |
1854 private: | 1861 private: |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1886 return summary; | 1893 return summary; |
1887 } | 1894 } |
1888 | 1895 |
1889 | 1896 |
1890 void UnboxDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1897 void UnboxDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
1891 const intptr_t v_cid = value()->ResultCid(); | 1898 const intptr_t v_cid = value()->ResultCid(); |
1892 | 1899 |
1893 const Register value = locs()->in(0).reg(); | 1900 const Register value = locs()->in(0).reg(); |
1894 const XmmRegister result = locs()->out().xmm_reg(); | 1901 const XmmRegister result = locs()->out().xmm_reg(); |
1895 if (v_cid != kDoubleCid) { | 1902 if (v_cid != kDoubleCid) { |
1896 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), | 1903 Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptBinaryDoubleOp); |
1897 kDeoptBinaryDoubleOp); | |
1898 compiler->LoadDoubleOrSmiToXmm(result, | 1904 compiler->LoadDoubleOrSmiToXmm(result, |
1899 value, | 1905 value, |
1900 locs()->temp(0).reg(), | 1906 locs()->temp(0).reg(), |
1901 deopt); | 1907 deopt); |
1902 } else { | 1908 } else { |
1903 __ movsd(result, FieldAddress(value, Double::value_offset())); | 1909 __ movsd(result, FieldAddress(value, Double::value_offset())); |
1904 } | 1910 } |
1905 } | 1911 } |
1906 | 1912 |
1907 | 1913 |
(...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2221 } | 2227 } |
2222 __ j(ABOVE_EQUAL, deopt); | 2228 __ j(ABOVE_EQUAL, deopt); |
2223 } | 2229 } |
2224 | 2230 |
2225 | 2231 |
2226 } // namespace dart | 2232 } // namespace dart |
2227 | 2233 |
2228 #undef __ | 2234 #undef __ |
2229 | 2235 |
2230 #endif // defined TARGET_ARCH_X64 | 2236 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |