| 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 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 299 } | 299 } |
| 300 | 300 |
| 301 | 301 |
| 302 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler, | 302 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler, |
| 303 EqualityCompareComp* comp, | 303 EqualityCompareComp* comp, |
| 304 Register left, | 304 Register left, |
| 305 Register right) { | 305 Register right) { |
| 306 ASSERT(comp->HasICData()); | 306 ASSERT(comp->HasICData()); |
| 307 const ICData& ic_data = *comp->ic_data(); | 307 const ICData& ic_data = *comp->ic_data(); |
| 308 ASSERT(ic_data.NumberOfChecks() > 0); | 308 ASSERT(ic_data.NumberOfChecks() > 0); |
| 309 ASSERT(ic_data.num_args_tested() == 1); |
| 309 Label* deopt = compiler->AddDeoptStub(comp->cid(), | 310 Label* deopt = compiler->AddDeoptStub(comp->cid(), |
| 310 comp->token_index(), | 311 comp->token_index(), |
| 311 comp->try_index(), | 312 comp->try_index(), |
| 312 kDeoptEquality); | 313 kDeoptEquality); |
| 313 __ testl(left, Immediate(kSmiTagMask)); | 314 __ testl(left, Immediate(kSmiTagMask)); |
| 314 Register temp = comp->locs()->temp(0).reg(); | 315 Register temp = comp->locs()->temp(0).reg(); |
| 315 if (ic_data.GetReceiverClassIdAt(0) == kSmi) { | 316 if (ic_data.GetReceiverClassIdAt(0) == kSmi) { |
| 316 Label done, load_class_id; | 317 Label done, load_class_id; |
| 317 __ j(NOT_ZERO, &load_class_id, Assembler::kNearJump); | 318 __ j(NOT_ZERO, &load_class_id, Assembler::kNearJump); |
| 318 __ movl(temp, Immediate(kSmi)); | 319 __ movl(temp, Immediate(kSmi)); |
| (...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 630 locs->set_temp(0, Location::RequiresRegister()); | 631 locs->set_temp(0, Location::RequiresRegister()); |
| 631 locs->set_out(Location::RequiresRegister()); | 632 locs->set_out(Location::RequiresRegister()); |
| 632 return locs; | 633 return locs; |
| 633 } else { | 634 } else { |
| 634 ASSERT(receiver_type() == kIllegalObjectKind); | 635 ASSERT(receiver_type() == kIllegalObjectKind); |
| 635 return MakeCallSummary(); | 636 return MakeCallSummary(); |
| 636 } | 637 } |
| 637 } | 638 } |
| 638 | 639 |
| 639 | 640 |
| 641 static void EmitLoadIndexedPolymorphic(FlowGraphCompiler* compiler, |
| 642 LoadIndexedComp* comp) { |
| 643 Label* deopt = compiler->AddDeoptStub(comp->cid(), |
| 644 comp->token_index(), |
| 645 comp->try_index(), |
| 646 kDeoptLoadIndexedPolymorphic); |
| 647 if (comp->ic_data()->NumberOfChecks() == 0) { |
| 648 __ jmp(deopt); |
| 649 return; |
| 650 } |
| 651 ASSERT(comp->HasICData()); |
| 652 const ICData& ic_data = *comp->ic_data(); |
| 653 ASSERT(ic_data.num_args_tested() == 1); |
| 654 // No indexed access on Smi. |
| 655 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmi); |
| 656 // Load receiver into EAX. |
| 657 const intptr_t kNumArguments = 2; |
| 658 __ movl(EAX, Address(ESP, (kNumArguments - 1) * kWordSize)); |
| 659 __ testl(EAX, Immediate(kSmiTagMask)); |
| 660 __ j(ZERO, deopt); |
| 661 Label done; |
| 662 __ LoadClassId(EDI, EAX); |
| 663 compiler->EmitTestAndCall(ic_data, |
| 664 EDI, // Class id register. |
| 665 kNumArguments, |
| 666 Array::Handle(), // No named arguments. |
| 667 deopt, &done, // Labels. |
| 668 comp->cid(), |
| 669 comp->token_index(), |
| 670 comp->try_index()); |
| 671 __ Bind(&done); |
| 672 } |
| 673 |
| 640 | 674 |
| 641 void LoadIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 675 void LoadIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 642 if (receiver_type() == kIllegalObjectKind) { | 676 if (receiver_type() == kIllegalObjectKind) { |
| 643 compiler->EmitLoadIndexedGeneric(this); | 677 if (HasICData()) { |
| 678 EmitLoadIndexedPolymorphic(compiler, this); |
| 679 } else { |
| 680 compiler->EmitLoadIndexedGeneric(this); |
| 681 } |
| 644 ASSERT(locs()->out().reg() == EAX); | 682 ASSERT(locs()->out().reg() == EAX); |
| 645 return; | 683 return; |
| 646 } | 684 } |
| 647 Register receiver = locs()->in(0).reg(); | 685 Register receiver = locs()->in(0).reg(); |
| 648 Register index = locs()->in(1).reg(); | 686 Register index = locs()->in(1).reg(); |
| 649 Register result = locs()->out().reg(); | 687 Register result = locs()->out().reg(); |
| 650 Register temp = locs()->temp(0).reg(); | 688 Register temp = locs()->temp(0).reg(); |
| 651 | 689 |
| 652 const Class& receiver_class = | 690 const Class& receiver_class = |
| 653 Class::ZoneHandle(Isolate::Current()->class_table()->At( | 691 Class::ZoneHandle(Isolate::Current()->class_table()->At( |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 712 locs->set_temp(0, Location::RequiresRegister()); | 750 locs->set_temp(0, Location::RequiresRegister()); |
| 713 locs->set_out(Location::NoLocation()); | 751 locs->set_out(Location::NoLocation()); |
| 714 return locs; | 752 return locs; |
| 715 } else { | 753 } else { |
| 716 ASSERT(receiver_type() == kIllegalObjectKind); | 754 ASSERT(receiver_type() == kIllegalObjectKind); |
| 717 return MakeCallSummary(); | 755 return MakeCallSummary(); |
| 718 } | 756 } |
| 719 } | 757 } |
| 720 | 758 |
| 721 | 759 |
| 722 | |
| 723 static void EmitStoreIndexedGeneric(FlowGraphCompiler* compiler, | 760 static void EmitStoreIndexedGeneric(FlowGraphCompiler* compiler, |
| 724 StoreIndexedComp* comp) { | 761 StoreIndexedComp* comp) { |
| 725 const String& function_name = | 762 const String& function_name = |
| 726 String::ZoneHandle(String::NewSymbol(Token::Str(Token::kASSIGN_INDEX))); | 763 String::ZoneHandle(String::NewSymbol(Token::Str(Token::kASSIGN_INDEX))); |
| 727 | 764 |
| 728 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 765 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
| 729 comp->cid(), | 766 comp->cid(), |
| 730 comp->token_index(), | 767 comp->token_index(), |
| 731 comp->try_index()); | 768 comp->try_index()); |
| 732 | 769 |
| 733 const intptr_t kNumArguments = 3; | 770 const intptr_t kNumArguments = 3; |
| 734 const intptr_t kNumArgsChecked = 1; // Type-feedback. | 771 const intptr_t kNumArgsChecked = 1; // Type-feedback. |
| 735 compiler->GenerateInstanceCall(comp->cid(), | 772 compiler->GenerateInstanceCall(comp->cid(), |
| 736 comp->token_index(), | 773 comp->token_index(), |
| 737 comp->try_index(), | 774 comp->try_index(), |
| 738 function_name, | 775 function_name, |
| 739 kNumArguments, | 776 kNumArguments, |
| 740 Array::ZoneHandle(), // No optional arguments. | 777 Array::ZoneHandle(), // No named args. |
| 741 kNumArgsChecked); | 778 kNumArgsChecked); |
| 742 } | 779 } |
| 743 | 780 |
| 744 | 781 |
| 782 static void EmitStoreIndexedPolymorphic(FlowGraphCompiler* compiler, |
| 783 StoreIndexedComp* comp) { |
| 784 Label* deopt = compiler->AddDeoptStub(comp->cid(), |
| 785 comp->token_index(), |
| 786 comp->try_index(), |
| 787 kDeoptStoreIndexedPolymorphic); |
| 788 if (comp->ic_data()->NumberOfChecks() == 0) { |
| 789 __ jmp(deopt); |
| 790 return; |
| 791 } |
| 792 ASSERT(comp->HasICData()); |
| 793 const ICData& ic_data = *comp->ic_data(); |
| 794 ASSERT(ic_data.num_args_tested() == 1); |
| 795 // No indexed access on Smi. |
| 796 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmi); |
| 797 // Load receiver into EAX. |
| 798 const intptr_t kNumArguments = 3; |
| 799 __ movl(EAX, Address(ESP, (kNumArguments - 1) * kWordSize)); |
| 800 __ testl(EAX, Immediate(kSmiTagMask)); |
| 801 __ j(ZERO, deopt); |
| 802 Label done; |
| 803 __ LoadClassId(EDI, EAX); |
| 804 compiler->EmitTestAndCall(ic_data, |
| 805 EDI, // Class id register. |
| 806 kNumArguments, |
| 807 Array::Handle(), // No named arguments. |
| 808 deopt, &done, // Labels. |
| 809 comp->cid(), |
| 810 comp->token_index(), |
| 811 comp->try_index()); |
| 812 __ Bind(&done); |
| 813 } |
| 814 |
| 815 |
| 745 void StoreIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 816 void StoreIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 746 if (receiver_type() == kIllegalObjectKind) { | 817 if (receiver_type() == kIllegalObjectKind) { |
| 747 EmitStoreIndexedGeneric(compiler, this); | 818 if (HasICData()) { |
| 819 EmitStoreIndexedPolymorphic(compiler, this); |
| 820 } else { |
| 821 EmitStoreIndexedGeneric(compiler, this); |
| 822 } |
| 748 return; | 823 return; |
| 749 } | 824 } |
| 750 | 825 |
| 751 Register receiver = locs()->in(0).reg(); | 826 Register receiver = locs()->in(0).reg(); |
| 752 Register index = locs()->in(1).reg(); | 827 Register index = locs()->in(1).reg(); |
| 753 Register value = locs()->in(2).reg(); | 828 Register value = locs()->in(2).reg(); |
| 754 Register temp = locs()->temp(0).reg(); | 829 Register temp = locs()->temp(0).reg(); |
| 755 | 830 |
| 756 Label* deopt = compiler->AddDeoptStub(cid(), | 831 Label* deopt = compiler->AddDeoptStub(cid(), |
| 757 token_index(), | 832 token_index(), |
| (...skipping 995 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1753 } | 1828 } |
| 1754 | 1829 |
| 1755 | 1830 |
| 1756 LocationSummary* PolymorphicInstanceCallComp::MakeLocationSummary() const { | 1831 LocationSummary* PolymorphicInstanceCallComp::MakeLocationSummary() const { |
| 1757 return MakeCallSummary(); | 1832 return MakeCallSummary(); |
| 1758 } | 1833 } |
| 1759 | 1834 |
| 1760 | 1835 |
| 1761 void PolymorphicInstanceCallComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1836 void PolymorphicInstanceCallComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1762 ASSERT(instance_call()->VerifyComputation()); | 1837 ASSERT(instance_call()->VerifyComputation()); |
| 1763 ASSERT(HasICData()); | |
| 1764 ASSERT(ic_data()->num_args_tested() == 1); | |
| 1765 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), | 1838 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), |
| 1766 instance_call()->token_index(), | 1839 instance_call()->token_index(), |
| 1767 instance_call()->try_index(), | 1840 instance_call()->try_index(), |
| 1768 kDeoptPolymorphicInstanceCallTestFail); | 1841 kDeoptPolymorphicInstanceCallTestFail); |
| 1842 if (!HasICData() || (ic_data()->NumberOfChecks() == 0)) { |
| 1843 __ jmp(deopt); |
| 1844 return; |
| 1845 } |
| 1846 ASSERT(HasICData()); |
| 1847 ASSERT(ic_data()->num_args_tested() == 1); |
| 1769 Label handle_smi; | 1848 Label handle_smi; |
| 1770 Label* is_smi_label = | 1849 Label* is_smi_label = |
| 1771 ic_data()->GetReceiverClassIdAt(0) == kSmi ? &handle_smi : deopt; | 1850 ic_data()->GetReceiverClassIdAt(0) == kSmi ? &handle_smi : deopt; |
| 1772 | 1851 |
| 1773 // Load receiver into EAX. | 1852 // Load receiver into EAX. |
| 1774 __ movl(EAX, | 1853 __ movl(EAX, |
| 1775 Address(ESP, (instance_call()->ArgumentCount() - 1) * kWordSize)); | 1854 Address(ESP, (instance_call()->ArgumentCount() - 1) * kWordSize)); |
| 1776 __ testl(EAX, Immediate(kSmiTagMask)); | 1855 __ testl(EAX, Immediate(kSmiTagMask)); |
| 1777 __ j(ZERO, is_smi_label); | 1856 __ j(ZERO, is_smi_label); |
| 1778 Label done; | 1857 Label done; |
| 1779 __ LoadClassId(EDI, EAX); | 1858 __ LoadClassId(EDI, EAX); |
| 1780 for (intptr_t i = 0; i < ic_data()->NumberOfChecks(); i++) { | 1859 compiler->EmitTestAndCall(*ic_data(), |
| 1781 Label next_test; | 1860 EDI, // Class id register. |
| 1782 __ cmpl(EDI, Immediate(ic_data()->GetReceiverClassIdAt(i))); | 1861 instance_call()->ArgumentCount(), |
| 1783 __ j(NOT_EQUAL, &next_test); | 1862 instance_call()->argument_names(), |
| 1784 const Function& target = Function::ZoneHandle(ic_data()->GetTargetAt(i)); | 1863 deopt, &done, // Labels. |
| 1785 compiler->GenerateStaticCall(instance_call()->cid(), | 1864 instance_call()->cid(), |
| 1786 instance_call()->token_index(), | 1865 instance_call()->token_index(), |
| 1787 instance_call()->try_index(), | 1866 instance_call()->try_index()); |
| 1788 target, | |
| 1789 instance_call()->ArgumentCount(), | |
| 1790 instance_call()->argument_names()); | |
| 1791 __ jmp(&done); | |
| 1792 __ Bind(&next_test); | |
| 1793 } | |
| 1794 __ jmp(deopt); | |
| 1795 if (is_smi_label == &handle_smi) { | 1867 if (is_smi_label == &handle_smi) { |
| 1796 __ Bind(&handle_smi); | 1868 __ Bind(&handle_smi); |
| 1797 ASSERT(ic_data()->GetReceiverClassIdAt(0) == kSmi); | 1869 ASSERT(ic_data()->GetReceiverClassIdAt(0) == kSmi); |
| 1798 const Function& target = Function::ZoneHandle(ic_data()->GetTargetAt(0)); | 1870 const Function& target = Function::ZoneHandle(ic_data()->GetTargetAt(0)); |
| 1799 compiler->GenerateStaticCall(instance_call()->cid(), | 1871 compiler->GenerateStaticCall(instance_call()->cid(), |
| 1800 instance_call()->token_index(), | 1872 instance_call()->token_index(), |
| 1801 instance_call()->try_index(), | 1873 instance_call()->try_index(), |
| 1802 target, | 1874 target, |
| 1803 instance_call()->ArgumentCount(), | 1875 instance_call()->ArgumentCount(), |
| 1804 instance_call()->argument_names()); | 1876 instance_call()->argument_names()); |
| 1805 } | 1877 } |
| 1806 __ Bind(&done); | 1878 __ Bind(&done); |
| 1807 } | 1879 } |
| 1808 | 1880 |
| 1809 | 1881 |
| 1810 } // namespace dart | 1882 } // namespace dart |
| 1811 | 1883 |
| 1812 #undef __ | 1884 #undef __ |
| 1813 | 1885 |
| 1814 #endif // defined TARGET_ARCH_X64 | 1886 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |