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 |