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 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
308 } | 308 } |
309 | 309 |
310 | 310 |
311 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler, | 311 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler, |
312 EqualityCompareComp* comp, | 312 EqualityCompareComp* comp, |
313 Register left, | 313 Register left, |
314 Register right) { | 314 Register right) { |
315 ASSERT(comp->HasICData()); | 315 ASSERT(comp->HasICData()); |
316 const ICData& ic_data = *comp->ic_data(); | 316 const ICData& ic_data = *comp->ic_data(); |
317 ASSERT(ic_data.NumberOfChecks() > 0); | 317 ASSERT(ic_data.NumberOfChecks() > 0); |
| 318 ASSERT(ic_data.num_args_tested() == 1); |
318 Label* deopt = compiler->AddDeoptStub(comp->cid(), | 319 Label* deopt = compiler->AddDeoptStub(comp->cid(), |
319 comp->token_index(), | 320 comp->token_index(), |
320 comp->try_index(), | 321 comp->try_index(), |
321 kDeoptEquality); | 322 kDeoptEquality); |
322 __ testq(left, Immediate(kSmiTagMask)); | 323 __ testq(left, Immediate(kSmiTagMask)); |
323 Register temp = comp->locs()->temp(0).reg(); | 324 Register temp = comp->locs()->temp(0).reg(); |
324 if (ic_data.GetReceiverClassIdAt(0) == kSmi) { | 325 if (ic_data.GetReceiverClassIdAt(0) == kSmi) { |
325 Label done, load_class_id; | 326 Label done, load_class_id; |
326 __ j(NOT_ZERO, &load_class_id, Assembler::kNearJump); | 327 __ j(NOT_ZERO, &load_class_id, Assembler::kNearJump); |
327 __ movq(temp, Immediate(kSmi)); | 328 __ movq(temp, Immediate(kSmi)); |
(...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
644 return locs; | 645 return locs; |
645 } else if (receiver_type() == kArray || receiver_type() == kImmutableArray) { | 646 } else if (receiver_type() == kArray || receiver_type() == kImmutableArray) { |
646 return LocationSummary::Make(kNumInputs, Location::RequiresRegister()); | 647 return LocationSummary::Make(kNumInputs, Location::RequiresRegister()); |
647 } else { | 648 } else { |
648 ASSERT(receiver_type() == kIllegalObjectKind); | 649 ASSERT(receiver_type() == kIllegalObjectKind); |
649 return MakeCallSummary(); | 650 return MakeCallSummary(); |
650 } | 651 } |
651 } | 652 } |
652 | 653 |
653 | 654 |
| 655 static void EmitLoadIndexedPolymorphic(FlowGraphCompiler* compiler, |
| 656 LoadIndexedComp* comp) { |
| 657 Label* deopt = compiler->AddDeoptStub(comp->cid(), |
| 658 comp->token_index(), |
| 659 comp->try_index(), |
| 660 kDeoptLoadIndexedPolymorphic); |
| 661 if (comp->ic_data()->NumberOfChecks() == 0) { |
| 662 __ jmp(deopt); |
| 663 return; |
| 664 } |
| 665 ASSERT(comp->HasICData()); |
| 666 const ICData& ic_data = *comp->ic_data(); |
| 667 ASSERT(ic_data.num_args_tested() == 1); |
| 668 // No indexed access on Smi. |
| 669 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmi); |
| 670 // Load receiver into RAX. |
| 671 const intptr_t kNumArguments = 2; |
| 672 __ movq(RAX, Address(RSP, (kNumArguments - 1) * kWordSize)); |
| 673 __ testq(RAX, Immediate(kSmiTagMask)); |
| 674 __ j(ZERO, deopt); |
| 675 Label done; |
| 676 __ LoadClassId(RDI, RAX); |
| 677 compiler->EmitTestAndCall(ic_data, |
| 678 RDI, // Class id register. |
| 679 kNumArguments, |
| 680 Array::Handle(), // No named arguments. |
| 681 deopt, &done, // Labels. |
| 682 comp->cid(), |
| 683 comp->token_index(), |
| 684 comp->try_index()); |
| 685 __ Bind(&done); |
| 686 } |
| 687 |
| 688 |
| 689 |
654 void LoadIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 690 void LoadIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
655 if (receiver_type() == kIllegalObjectKind) { | 691 if (receiver_type() == kIllegalObjectKind) { |
656 compiler->EmitLoadIndexedGeneric(this); | 692 if (HasICData()) { |
| 693 EmitLoadIndexedPolymorphic(compiler, this); |
| 694 } else { |
| 695 compiler->EmitLoadIndexedGeneric(this); |
| 696 } |
657 ASSERT(locs()->out().reg() == RAX); | 697 ASSERT(locs()->out().reg() == RAX); |
658 return; | 698 return; |
659 } | 699 } |
660 | 700 |
661 Register receiver = locs()->in(0).reg(); | 701 Register receiver = locs()->in(0).reg(); |
662 Register index = locs()->in(1).reg(); | 702 Register index = locs()->in(1).reg(); |
663 Register result = locs()->out().reg(); | 703 Register result = locs()->out().reg(); |
664 | 704 |
665 const DeoptReasonId deopt_reason = (receiver_type() == kGrowableObjectArray) ? | 705 const DeoptReasonId deopt_reason = (receiver_type() == kGrowableObjectArray) ? |
666 kDeoptLoadIndexedGrowableArray : kDeoptLoadIndexedFixedArray; | 706 kDeoptLoadIndexedGrowableArray : kDeoptLoadIndexedFixedArray; |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
741 comp->token_index(), | 781 comp->token_index(), |
742 comp->try_index()); | 782 comp->try_index()); |
743 | 783 |
744 const intptr_t kNumArguments = 3; | 784 const intptr_t kNumArguments = 3; |
745 const intptr_t kNumArgsChecked = 1; // Type-feedback. | 785 const intptr_t kNumArgsChecked = 1; // Type-feedback. |
746 compiler->GenerateInstanceCall(comp->cid(), | 786 compiler->GenerateInstanceCall(comp->cid(), |
747 comp->token_index(), | 787 comp->token_index(), |
748 comp->try_index(), | 788 comp->try_index(), |
749 function_name, | 789 function_name, |
750 kNumArguments, | 790 kNumArguments, |
751 Array::ZoneHandle(), // No optional arguments. | 791 Array::ZoneHandle(), // No names arguments. |
752 kNumArgsChecked); | 792 kNumArgsChecked); |
753 } | 793 } |
754 | 794 |
755 | 795 |
| 796 static void EmitStoreIndexedPolymorphic(FlowGraphCompiler* compiler, |
| 797 StoreIndexedComp* comp) { |
| 798 Label* deopt = compiler->AddDeoptStub(comp->cid(), |
| 799 comp->token_index(), |
| 800 comp->try_index(), |
| 801 kDeoptStoreIndexedPolymorphic); |
| 802 if (comp->ic_data()->NumberOfChecks() == 0) { |
| 803 __ jmp(deopt); |
| 804 return; |
| 805 } |
| 806 ASSERT(comp->HasICData()); |
| 807 const ICData& ic_data = *comp->ic_data(); |
| 808 ASSERT(ic_data.num_args_tested() == 1); |
| 809 // No indexed access on Smi. |
| 810 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmi); |
| 811 // Load receiver into RAX. |
| 812 const intptr_t kNumArguments = 3; |
| 813 __ movq(RAX, Address(RSP, (kNumArguments - 1) * kWordSize)); |
| 814 __ testq(RAX, Immediate(kSmiTagMask)); |
| 815 __ j(ZERO, deopt); |
| 816 Label done; |
| 817 __ LoadClassId(RDI, RAX); |
| 818 compiler->EmitTestAndCall(ic_data, |
| 819 RDI, // Class id register. |
| 820 kNumArguments, |
| 821 Array::Handle(), // No named arguments. |
| 822 deopt, &done, // Labels. |
| 823 comp->cid(), |
| 824 comp->token_index(), |
| 825 comp->try_index()); |
| 826 __ Bind(&done); |
| 827 } |
| 828 |
| 829 |
756 void StoreIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 830 void StoreIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
757 if (receiver_type() == kIllegalObjectKind) { | 831 if (receiver_type() == kIllegalObjectKind) { |
758 EmitStoreIndexedGeneric(compiler, this); | 832 if (HasICData()) { |
| 833 EmitStoreIndexedPolymorphic(compiler, this); |
| 834 } else { |
| 835 EmitStoreIndexedGeneric(compiler, this); |
| 836 } |
759 return; | 837 return; |
760 } | 838 } |
761 | 839 |
762 Register receiver = locs()->in(0).reg(); | 840 Register receiver = locs()->in(0).reg(); |
763 Register index = locs()->in(1).reg(); | 841 Register index = locs()->in(1).reg(); |
764 Register value = locs()->in(2).reg(); | 842 Register value = locs()->in(2).reg(); |
765 | 843 |
766 const Class& receiver_class = | 844 const Class& receiver_class = |
767 Class::ZoneHandle(Isolate::Current()->class_table()->At( | 845 Class::ZoneHandle(Isolate::Current()->class_table()->At( |
768 receiver_type())); | 846 receiver_type())); |
(...skipping 998 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1767 } | 1845 } |
1768 | 1846 |
1769 | 1847 |
1770 LocationSummary* PolymorphicInstanceCallComp::MakeLocationSummary() const { | 1848 LocationSummary* PolymorphicInstanceCallComp::MakeLocationSummary() const { |
1771 return MakeCallSummary(); | 1849 return MakeCallSummary(); |
1772 } | 1850 } |
1773 | 1851 |
1774 | 1852 |
1775 void PolymorphicInstanceCallComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1853 void PolymorphicInstanceCallComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
1776 ASSERT(instance_call()->VerifyComputation()); | 1854 ASSERT(instance_call()->VerifyComputation()); |
1777 ASSERT(HasICData()); | |
1778 ASSERT(ic_data()->num_args_tested() == 1); | |
1779 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), | 1855 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), |
1780 instance_call()->token_index(), | 1856 instance_call()->token_index(), |
1781 instance_call()->try_index(), | 1857 instance_call()->try_index(), |
1782 kDeoptPolymorphicInstanceCallTestFail); | 1858 kDeoptPolymorphicInstanceCallTestFail); |
| 1859 if (!HasICData() || (ic_data()->NumberOfChecks() == 0)) { |
| 1860 __ jmp(deopt); |
| 1861 return; |
| 1862 } |
| 1863 ASSERT(HasICData()); |
| 1864 ASSERT(ic_data()->num_args_tested() == 1); |
1783 Label handle_smi; | 1865 Label handle_smi; |
1784 Label* is_smi_label = | 1866 Label* is_smi_label = |
1785 ic_data()->GetReceiverClassIdAt(0) == kSmi ? &handle_smi : deopt; | 1867 ic_data()->GetReceiverClassIdAt(0) == kSmi ? &handle_smi : deopt; |
1786 // Load receiver into RAX. | 1868 // Load receiver into RAX. |
1787 __ movq(RAX, | 1869 __ movq(RAX, |
1788 Address(RSP, (instance_call()->ArgumentCount() - 1) * kWordSize)); | 1870 Address(RSP, (instance_call()->ArgumentCount() - 1) * kWordSize)); |
1789 __ testq(RAX, Immediate(kSmiTagMask)); | 1871 __ testq(RAX, Immediate(kSmiTagMask)); |
1790 __ j(ZERO, is_smi_label); | 1872 __ j(ZERO, is_smi_label); |
1791 Label done; | 1873 Label done; |
1792 __ LoadClassId(RDI, RAX); | 1874 __ LoadClassId(RDI, RAX); |
1793 for (intptr_t i = 0; i < ic_data()->NumberOfChecks(); i++) { | 1875 compiler->EmitTestAndCall(*ic_data(), |
1794 Label next_test; | 1876 RDI, // Class id register. |
1795 __ cmpq(RDI, Immediate(ic_data()->GetReceiverClassIdAt(i))); | 1877 instance_call()->ArgumentCount(), |
1796 __ j(NOT_EQUAL, &next_test); | 1878 instance_call()->argument_names(), |
1797 const Function& target = Function::ZoneHandle(ic_data()->GetTargetAt(i)); | 1879 deopt, &done, // Labels. |
1798 compiler->GenerateStaticCall(instance_call()->cid(), | 1880 instance_call()->cid(), |
1799 instance_call()->token_index(), | 1881 instance_call()->token_index(), |
1800 instance_call()->try_index(), | 1882 instance_call()->try_index()); |
1801 target, | |
1802 instance_call()->ArgumentCount(), | |
1803 instance_call()->argument_names()); | |
1804 __ jmp(&done); | |
1805 __ Bind(&next_test); | |
1806 } | |
1807 __ jmp(deopt); | |
1808 if (is_smi_label == &handle_smi) { | 1883 if (is_smi_label == &handle_smi) { |
1809 __ Bind(&handle_smi); | 1884 __ Bind(&handle_smi); |
1810 ASSERT(ic_data()->GetReceiverClassIdAt(0) == kSmi); | 1885 ASSERT(ic_data()->GetReceiverClassIdAt(0) == kSmi); |
1811 const Function& target = Function::ZoneHandle(ic_data()->GetTargetAt(0)); | 1886 const Function& target = Function::ZoneHandle(ic_data()->GetTargetAt(0)); |
1812 compiler->GenerateStaticCall(instance_call()->cid(), | 1887 compiler->GenerateStaticCall(instance_call()->cid(), |
1813 instance_call()->token_index(), | 1888 instance_call()->token_index(), |
1814 instance_call()->try_index(), | 1889 instance_call()->try_index(), |
1815 target, | 1890 target, |
1816 instance_call()->ArgumentCount(), | 1891 instance_call()->ArgumentCount(), |
1817 instance_call()->argument_names()); | 1892 instance_call()->argument_names()); |
1818 } | 1893 } |
1819 __ Bind(&done); | 1894 __ Bind(&done); |
1820 } | 1895 } |
1821 | 1896 |
1822 } // namespace dart | 1897 } // namespace dart |
1823 | 1898 |
1824 #undef __ | 1899 #undef __ |
1825 | 1900 |
1826 #endif // defined TARGET_ARCH_X64 | 1901 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |