| 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_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 "lib/error.h" | 10 #include "lib/error.h" |
| (...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 233 UNREACHABLE(); | 233 UNREACHABLE(); |
| 234 return OVERFLOW; | 234 return OVERFLOW; |
| 235 } | 235 } |
| 236 } | 236 } |
| 237 | 237 |
| 238 | 238 |
| 239 LocationSummary* EqualityCompareComp::MakeLocationSummary() const { | 239 LocationSummary* EqualityCompareComp::MakeLocationSummary() const { |
| 240 const intptr_t kNumInputs = 2; | 240 const intptr_t kNumInputs = 2; |
| 241 const bool is_checked_strict_equal = | 241 const bool is_checked_strict_equal = |
| 242 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); | 242 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); |
| 243 if ((receiver_class_id() == kSmiCid) || | 243 if (receiver_class_id() == kDoubleCid) { |
| 244 (receiver_class_id() == kDoubleCid) || | 244 const intptr_t kNumTemps = 0; |
| 245 is_checked_strict_equal) { | 245 LocationSummary* locs = |
| 246 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 247 locs->set_in(0, Location::RequiresXmmRegister()); |
| 248 locs->set_in(1, Location::RequiresXmmRegister()); |
| 249 locs->set_out(Location::RequiresRegister()); |
| 250 return locs; |
| 251 } |
| 252 if ((receiver_class_id() == kSmiCid) || is_checked_strict_equal) { |
| 246 const intptr_t kNumTemps = 1; | 253 const intptr_t kNumTemps = 1; |
| 247 LocationSummary* locs = | 254 LocationSummary* locs = |
| 248 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 255 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 249 locs->set_in(0, Location::RequiresRegister()); | 256 locs->set_in(0, Location::RequiresRegister()); |
| 250 locs->set_in(1, Location::RequiresRegister()); | 257 locs->set_in(1, Location::RequiresRegister()); |
| 251 locs->set_temp(0, Location::RequiresRegister()); | 258 locs->set_temp(0, Location::RequiresRegister()); |
| 252 locs->set_out(Location::RequiresRegister()); | 259 locs->set_out(Location::RequiresRegister()); |
| 253 return locs; | 260 return locs; |
| 254 } | 261 } |
| 255 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { | 262 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
| (...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 573 default: | 580 default: |
| 574 UNREACHABLE(); | 581 UNREACHABLE(); |
| 575 return OVERFLOW; | 582 return OVERFLOW; |
| 576 } | 583 } |
| 577 } | 584 } |
| 578 | 585 |
| 579 | 586 |
| 580 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler, | 587 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler, |
| 581 const LocationSummary& locs, | 588 const LocationSummary& locs, |
| 582 Token::Kind kind, | 589 Token::Kind kind, |
| 583 BranchInstr* branch, | 590 BranchInstr* branch) { |
| 584 intptr_t deopt_id) { | 591 XmmRegister left = locs.in(0).xmm_reg(); |
| 585 Register left = locs.in(0).reg(); | 592 XmmRegister right = locs.in(1).xmm_reg(); |
| 586 Register right = locs.in(1).reg(); | |
| 587 // TODO(srdjan): temp is only needed if a conversion Smi->Double occurs. | |
| 588 Register temp = locs.temp(0).reg(); | |
| 589 Label* deopt = compiler->AddDeoptStub(deopt_id, kDeoptDoubleComparison); | |
| 590 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); | |
| 591 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); | |
| 592 | 593 |
| 593 Condition true_condition = TokenKindToDoubleCondition(kind); | 594 Condition true_condition = TokenKindToDoubleCondition(kind); |
| 594 if (branch != NULL) { | 595 if (branch != NULL) { |
| 595 compiler->EmitDoubleCompareBranch( | 596 compiler->EmitDoubleCompareBranch( |
| 596 true_condition, XMM0, XMM1, branch); | 597 true_condition, left, right, branch); |
| 597 } else { | 598 } else { |
| 598 compiler->EmitDoubleCompareBool( | 599 compiler->EmitDoubleCompareBool( |
| 599 true_condition, XMM0, XMM1, locs.out().reg()); | 600 true_condition, left, right, locs.out().reg()); |
| 600 } | 601 } |
| 601 } | 602 } |
| 602 | 603 |
| 603 | 604 |
| 604 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 605 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 605 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); | 606 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); |
| 606 BranchInstr* kNoBranch = NULL; | 607 BranchInstr* kNoBranch = NULL; |
| 607 if (receiver_class_id() == kSmiCid) { | 608 if (receiver_class_id() == kSmiCid) { |
| 608 // Deoptimizes if both arguments not Smi. | 609 // Deoptimizes if both arguments not Smi. |
| 609 EmitSmiComparisonOp(compiler, *locs(), kind(), kNoBranch, deopt_id()); | 610 EmitSmiComparisonOp(compiler, *locs(), kind(), kNoBranch, deopt_id()); |
| 610 return; | 611 return; |
| 611 } | 612 } |
| 612 if (receiver_class_id() == kDoubleCid) { | 613 if (receiver_class_id() == kDoubleCid) { |
| 613 // Deoptimizes if both arguments are Smi, or if none is Double or Smi. | 614 EmitDoubleComparisonOp(compiler, *locs(), kind(), kNoBranch); |
| 614 EmitDoubleComparisonOp(compiler, *locs(), kind(), kNoBranch, deopt_id()); | |
| 615 return; | 615 return; |
| 616 } | 616 } |
| 617 const bool is_checked_strict_equal = | 617 const bool is_checked_strict_equal = |
| 618 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); | 618 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); |
| 619 if (is_checked_strict_equal) { | 619 if (is_checked_strict_equal) { |
| 620 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), kNoBranch, | 620 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), kNoBranch, |
| 621 deopt_id()); | 621 deopt_id()); |
| 622 return; | 622 return; |
| 623 } | 623 } |
| 624 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { | 624 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 637 | 637 |
| 638 void EqualityCompareComp::EmitBranchCode(FlowGraphCompiler* compiler, | 638 void EqualityCompareComp::EmitBranchCode(FlowGraphCompiler* compiler, |
| 639 BranchInstr* branch) { | 639 BranchInstr* branch) { |
| 640 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); | 640 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); |
| 641 if (receiver_class_id() == kSmiCid) { | 641 if (receiver_class_id() == kSmiCid) { |
| 642 // Deoptimizes if both arguments not Smi. | 642 // Deoptimizes if both arguments not Smi. |
| 643 EmitSmiComparisonOp(compiler, *locs(), kind(), branch, deopt_id()); | 643 EmitSmiComparisonOp(compiler, *locs(), kind(), branch, deopt_id()); |
| 644 return; | 644 return; |
| 645 } | 645 } |
| 646 if (receiver_class_id() == kDoubleCid) { | 646 if (receiver_class_id() == kDoubleCid) { |
| 647 // Deoptimizes if both arguments are Smi, or if none is Double or Smi. | 647 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch); |
| 648 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch, deopt_id()); | |
| 649 return; | 648 return; |
| 650 } | 649 } |
| 651 const bool is_checked_strict_equal = | 650 const bool is_checked_strict_equal = |
| 652 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); | 651 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); |
| 653 if (is_checked_strict_equal) { | 652 if (is_checked_strict_equal) { |
| 654 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), branch, | 653 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), branch, |
| 655 deopt_id()); | 654 deopt_id()); |
| 656 return; | 655 return; |
| 657 } | 656 } |
| 658 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { | 657 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 670 Token::kEQ, // kNE reverse occurs at branch. | 669 Token::kEQ, // kNE reverse occurs at branch. |
| 671 locs()); | 670 locs()); |
| 672 Condition branch_condition = (kind() == Token::kNE) ? NOT_EQUAL : EQUAL; | 671 Condition branch_condition = (kind() == Token::kNE) ? NOT_EQUAL : EQUAL; |
| 673 __ CompareObject(EAX, compiler->bool_true()); | 672 __ CompareObject(EAX, compiler->bool_true()); |
| 674 branch->EmitBranchOnCondition(compiler, branch_condition); | 673 branch->EmitBranchOnCondition(compiler, branch_condition); |
| 675 } | 674 } |
| 676 | 675 |
| 677 | 676 |
| 678 LocationSummary* RelationalOpComp::MakeLocationSummary() const { | 677 LocationSummary* RelationalOpComp::MakeLocationSummary() const { |
| 679 const intptr_t kNumInputs = 2; | 678 const intptr_t kNumInputs = 2; |
| 680 if ((operands_class_id() == kSmiCid) || (operands_class_id() == kDoubleCid)) { | 679 if (operands_class_id() == kDoubleCid) { |
| 680 const intptr_t kNumTemps = 0; |
| 681 LocationSummary* summary = |
| 682 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 683 summary->set_in(0, Location::RequiresXmmRegister()); |
| 684 summary->set_in(1, Location::RequiresXmmRegister()); |
| 685 summary->set_out(Location::RequiresRegister()); |
| 686 return summary; |
| 687 } else if (operands_class_id() == kSmiCid) { |
| 681 const intptr_t kNumTemps = 1; | 688 const intptr_t kNumTemps = 1; |
| 682 LocationSummary* summary = | 689 LocationSummary* summary = |
| 683 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 690 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 684 summary->set_in(0, Location::RequiresRegister()); | 691 summary->set_in(0, Location::RequiresRegister()); |
| 685 summary->set_in(1, Location::RequiresRegister()); | 692 summary->set_in(1, Location::RequiresRegister()); |
| 686 summary->set_out(Location::RequiresRegister()); | 693 summary->set_out(Location::RequiresRegister()); |
| 687 summary->set_temp(0, Location::RequiresRegister()); | 694 summary->set_temp(0, Location::RequiresRegister()); |
| 688 return summary; | 695 return summary; |
| 689 } | 696 } |
| 690 const intptr_t kNumTemps = 0; | 697 const intptr_t kNumTemps = 0; |
| 691 LocationSummary* locs = | 698 LocationSummary* locs = |
| 692 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 699 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 693 // Pick arbitrary fixed input registers because this is a call. | 700 // Pick arbitrary fixed input registers because this is a call. |
| 694 locs->set_in(0, Location::RegisterLocation(EAX)); | 701 locs->set_in(0, Location::RegisterLocation(EAX)); |
| 695 locs->set_in(1, Location::RegisterLocation(ECX)); | 702 locs->set_in(1, Location::RegisterLocation(ECX)); |
| 696 locs->set_out(Location::RegisterLocation(EAX)); | 703 locs->set_out(Location::RegisterLocation(EAX)); |
| 697 return locs; | 704 return locs; |
| 698 } | 705 } |
| 699 | 706 |
| 700 | 707 |
| 701 void RelationalOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 708 void RelationalOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 702 if (operands_class_id() == kSmiCid) { | 709 if (operands_class_id() == kSmiCid) { |
| 703 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL, deopt_id()); | 710 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL, deopt_id()); |
| 704 return; | 711 return; |
| 705 } | 712 } |
| 706 if (operands_class_id() == kDoubleCid) { | 713 if (operands_class_id() == kDoubleCid) { |
| 707 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL, deopt_id()); | 714 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL); |
| 708 return; | 715 return; |
| 709 } | 716 } |
| 710 | 717 |
| 711 // Push arguments for the call. | 718 // Push arguments for the call. |
| 712 // TODO(fschneider): Split this instruction into different types to avoid | 719 // TODO(fschneider): Split this instruction into different types to avoid |
| 713 // explicitly pushing arguments to the call here. | 720 // explicitly pushing arguments to the call here. |
| 714 Register left = locs()->in(0).reg(); | 721 Register left = locs()->in(0).reg(); |
| 715 Register right = locs()->in(1).reg(); | 722 Register right = locs()->in(1).reg(); |
| 716 __ pushl(left); | 723 __ pushl(left); |
| 717 __ pushl(right); | 724 __ pushl(right); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 754 } | 761 } |
| 755 | 762 |
| 756 | 763 |
| 757 void RelationalOpComp::EmitBranchCode(FlowGraphCompiler* compiler, | 764 void RelationalOpComp::EmitBranchCode(FlowGraphCompiler* compiler, |
| 758 BranchInstr* branch) { | 765 BranchInstr* branch) { |
| 759 if (operands_class_id() == kSmiCid) { | 766 if (operands_class_id() == kSmiCid) { |
| 760 EmitSmiComparisonOp(compiler, *locs(), kind(), branch, deopt_id()); | 767 EmitSmiComparisonOp(compiler, *locs(), kind(), branch, deopt_id()); |
| 761 return; | 768 return; |
| 762 } | 769 } |
| 763 if (operands_class_id() == kDoubleCid) { | 770 if (operands_class_id() == kDoubleCid) { |
| 764 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch, deopt_id()); | 771 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch); |
| 765 return; | 772 return; |
| 766 } | 773 } |
| 767 EmitNativeCode(compiler); | 774 EmitNativeCode(compiler); |
| 768 __ CompareObject(EAX, compiler->bool_true()); | 775 __ CompareObject(EAX, compiler->bool_true()); |
| 769 branch->EmitBranchOnCondition(compiler, EQUAL); | 776 branch->EmitBranchOnCondition(compiler, EQUAL); |
| 770 } | 777 } |
| 771 | 778 |
| 772 | 779 |
| 773 LocationSummary* NativeCallComp::MakeLocationSummary() const { | 780 LocationSummary* NativeCallComp::MakeLocationSummary() const { |
| 774 const intptr_t kNumInputs = 0; | 781 const intptr_t kNumInputs = 0; |
| (...skipping 1039 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1814 explicit BoxDoubleSlowPath(BoxDoubleComp* computation) | 1821 explicit BoxDoubleSlowPath(BoxDoubleComp* computation) |
| 1815 : computation_(computation) { } | 1822 : computation_(computation) { } |
| 1816 | 1823 |
| 1817 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 1824 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1818 __ Bind(entry_label()); | 1825 __ Bind(entry_label()); |
| 1819 const Class& double_class = compiler->double_class(); | 1826 const Class& double_class = compiler->double_class(); |
| 1820 const Code& stub = | 1827 const Code& stub = |
| 1821 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 1828 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
| 1822 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 1829 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
| 1823 | 1830 |
| 1824 // TODO(vegorov): here stack map needs to be set up correctly to skip | |
| 1825 // double registers. | |
| 1826 LocationSummary* locs = computation_->locs(); | 1831 LocationSummary* locs = computation_->locs(); |
| 1827 locs->live_registers()->Remove(locs->out()); | 1832 locs->live_registers()->Remove(locs->out()); |
| 1828 | 1833 |
| 1829 compiler->SaveLiveRegisters(locs); | 1834 compiler->SaveLiveRegisters(locs); |
| 1830 compiler->GenerateCall(computation_->instance_call()->token_pos(), | 1835 compiler->GenerateCall(computation_->token_pos(), |
| 1831 &label, | 1836 &label, |
| 1832 PcDescriptors::kOther, | 1837 PcDescriptors::kOther, |
| 1833 locs); | 1838 locs); |
| 1834 if (EAX != locs->out().reg()) __ movl(locs->out().reg(), EAX); | 1839 if (EAX != locs->out().reg()) __ movl(locs->out().reg(), EAX); |
| 1835 compiler->RestoreLiveRegisters(locs); | 1840 compiler->RestoreLiveRegisters(locs); |
| 1836 | 1841 |
| 1837 __ jmp(exit_label()); | 1842 __ jmp(exit_label()); |
| 1838 } | 1843 } |
| 1839 | 1844 |
| 1840 private: | 1845 private: |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1872 return summary; | 1877 return summary; |
| 1873 } | 1878 } |
| 1874 | 1879 |
| 1875 | 1880 |
| 1876 void UnboxDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1881 void UnboxDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1877 const intptr_t v_cid = value()->ResultCid(); | 1882 const intptr_t v_cid = value()->ResultCid(); |
| 1878 | 1883 |
| 1879 const Register value = locs()->in(0).reg(); | 1884 const Register value = locs()->in(0).reg(); |
| 1880 const XmmRegister result = locs()->out().xmm_reg(); | 1885 const XmmRegister result = locs()->out().xmm_reg(); |
| 1881 if (v_cid != kDoubleCid) { | 1886 if (v_cid != kDoubleCid) { |
| 1882 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), | 1887 Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptBinaryDoubleOp); |
| 1883 kDeoptBinaryDoubleOp); | |
| 1884 compiler->LoadDoubleOrSmiToXmm(result, | 1888 compiler->LoadDoubleOrSmiToXmm(result, |
| 1885 value, | 1889 value, |
| 1886 locs()->temp(0).reg(), | 1890 locs()->temp(0).reg(), |
| 1887 deopt); | 1891 deopt); |
| 1888 } else { | 1892 } else { |
| 1889 __ movsd(result, FieldAddress(value, Double::value_offset())); | 1893 __ movsd(result, FieldAddress(value, Double::value_offset())); |
| 1890 } | 1894 } |
| 1891 } | 1895 } |
| 1892 | 1896 |
| 1893 | 1897 |
| (...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2209 } | 2213 } |
| 2210 __ j(ABOVE_EQUAL, deopt); | 2214 __ j(ABOVE_EQUAL, deopt); |
| 2211 } | 2215 } |
| 2212 | 2216 |
| 2213 | 2217 |
| 2214 } // namespace dart | 2218 } // namespace dart |
| 2215 | 2219 |
| 2216 #undef __ | 2220 #undef __ |
| 2217 | 2221 |
| 2218 #endif // defined TARGET_ARCH_X64 | 2222 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |