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