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 |