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