OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
(...skipping 1572 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1583 __ j(NOT_EQUAL, fail); | 1583 __ j(NOT_EQUAL, fail); |
1584 } else { | 1584 } else { |
1585 UNREACHABLE(); | 1585 UNREACHABLE(); |
1586 } | 1586 } |
1587 } | 1587 } |
1588 } | 1588 } |
1589 __ Bind(&ok); | 1589 __ Bind(&ok); |
1590 } | 1590 } |
1591 | 1591 |
1592 | 1592 |
| 1593 bool Field::IsUnboxedField() const { |
| 1594 bool valid_class = (guarded_cid() == kDoubleCid) || |
| 1595 (guarded_cid() == kFloat32x4Cid); |
| 1596 return is_unboxing_candidate() && !is_final() && !is_nullable() && |
| 1597 valid_class; |
| 1598 } |
| 1599 |
| 1600 |
1593 class StoreInstanceFieldSlowPath : public SlowPathCode { | 1601 class StoreInstanceFieldSlowPath : public SlowPathCode { |
1594 public: | 1602 public: |
1595 StoreInstanceFieldSlowPath(StoreInstanceFieldInstr* instruction, | 1603 explicit StoreInstanceFieldSlowPath(StoreInstanceFieldInstr* instruction) |
1596 const Class& cls) | 1604 : instruction_(instruction) { } |
1597 : instruction_(instruction), cls_(cls) { } | |
1598 | 1605 |
1599 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 1606 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
1600 __ Comment("StoreInstanceFieldSlowPath"); | 1607 __ Comment("StoreInstanceFieldSlowPath"); |
1601 __ Bind(entry_label()); | 1608 { |
1602 const Code& stub = | 1609 __ Bind(double_entry_label()); |
1603 Code::Handle(StubCode::GetAllocationStubForClass(cls_)); | 1610 const Class& cls = compiler->double_class(); |
1604 const ExternalLabel label(cls_.ToCString(), stub.EntryPoint()); | 1611 const Code& stub = |
| 1612 Code::Handle(StubCode::GetAllocationStubForClass(cls)); |
| 1613 const ExternalLabel label(cls.ToCString(), stub.EntryPoint()); |
1605 | 1614 |
1606 LocationSummary* locs = instruction_->locs(); | 1615 LocationSummary* locs = instruction_->locs(); |
1607 locs->live_registers()->Remove(locs->out()); | 1616 locs->live_registers()->Remove(locs->out()); |
1608 | 1617 compiler->SaveLiveRegisters(locs); |
1609 compiler->SaveLiveRegisters(locs); | 1618 compiler->GenerateCall(Scanner::kNoSourcePos, // No token position. |
1610 compiler->GenerateCall(Scanner::kNoSourcePos, // No token position. | 1619 &label, |
1611 &label, | 1620 PcDescriptors::kOther, |
1612 PcDescriptors::kOther, | 1621 locs); |
1613 locs); | 1622 __ MoveRegister(locs->temp(0).reg(), EAX); |
1614 __ MoveRegister(locs->temp(0).reg(), EAX); | 1623 compiler->RestoreLiveRegisters(locs); |
1615 compiler->RestoreLiveRegisters(locs); | 1624 __ jmp(double_exit_label()); |
1616 | 1625 } |
1617 __ jmp(exit_label()); | 1626 { |
| 1627 __ Bind(float32x4_entry_label()); |
| 1628 const Class& cls = compiler->float32x4_class(); |
| 1629 const Code& stub = |
| 1630 Code::Handle(StubCode::GetAllocationStubForClass(cls)); |
| 1631 const ExternalLabel label(cls.ToCString(), stub.EntryPoint()); |
| 1632 LocationSummary* locs = instruction_->locs(); |
| 1633 locs->live_registers()->Remove(locs->out()); |
| 1634 compiler->SaveLiveRegisters(locs); |
| 1635 compiler->GenerateCall(Scanner::kNoSourcePos, // No token position. |
| 1636 &label, |
| 1637 PcDescriptors::kOther, |
| 1638 locs); |
| 1639 __ MoveRegister(locs->temp(0).reg(), EAX); |
| 1640 compiler->RestoreLiveRegisters(locs); |
| 1641 __ jmp(float32x4_exit_label()); |
| 1642 } |
1618 } | 1643 } |
1619 | 1644 |
| 1645 Label* double_entry_label() { |
| 1646 // Use default SlowPathCode label for double. |
| 1647 return entry_label(); |
| 1648 } |
| 1649 Label* double_exit_label() { |
| 1650 // Use default SlowPathCode label for double. |
| 1651 return exit_label(); |
| 1652 } |
| 1653 |
| 1654 Label* float32x4_entry_label() { return &float32x4_entry_label_; } |
| 1655 Label* float32x4_exit_label() { return &float32x4_exit_label_; } |
| 1656 |
1620 private: | 1657 private: |
| 1658 Label float32x4_entry_label_; |
| 1659 Label float32x4_exit_label_; |
1621 StoreInstanceFieldInstr* instruction_; | 1660 StoreInstanceFieldInstr* instruction_; |
1622 const Class& cls_; | |
1623 }; | 1661 }; |
1624 | 1662 |
1625 | 1663 |
1626 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(bool opt) const { | 1664 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(bool opt) const { |
1627 const intptr_t kNumInputs = 2; | 1665 const intptr_t kNumInputs = 2; |
1628 const intptr_t kNumTemps = 0; | 1666 const intptr_t kNumTemps = 0; |
1629 LocationSummary* summary = | 1667 LocationSummary* summary = |
1630 new LocationSummary(kNumInputs, kNumTemps, | 1668 new LocationSummary(kNumInputs, kNumTemps, |
1631 (field().guarded_cid() == kIllegalCid) || (is_initialization_) | 1669 (field().guarded_cid() == kIllegalCid) || (is_initialization_) |
1632 ? LocationSummary::kCallOnSlowPath | 1670 ? LocationSummary::kCallOnSlowPath |
(...skipping 26 matching lines...) Expand all Loading... |
1659 | 1697 |
1660 Register instance_reg = locs()->in(0).reg(); | 1698 Register instance_reg = locs()->in(0).reg(); |
1661 | 1699 |
1662 if (IsUnboxedStore() && compiler->is_optimizing()) { | 1700 if (IsUnboxedStore() && compiler->is_optimizing()) { |
1663 XmmRegister value = locs()->in(1).fpu_reg(); | 1701 XmmRegister value = locs()->in(1).fpu_reg(); |
1664 Register temp = locs()->temp(0).reg(); | 1702 Register temp = locs()->temp(0).reg(); |
1665 Register temp2 = locs()->temp(1).reg(); | 1703 Register temp2 = locs()->temp(1).reg(); |
1666 const intptr_t cid = field().UnboxedFieldCid(); | 1704 const intptr_t cid = field().UnboxedFieldCid(); |
1667 | 1705 |
1668 if (is_initialization_) { | 1706 if (is_initialization_) { |
| 1707 StoreInstanceFieldSlowPath* slow_path = |
| 1708 new StoreInstanceFieldSlowPath(this); |
| 1709 compiler->AddSlowPathCode(slow_path); |
| 1710 |
1669 const Class* cls = NULL; | 1711 const Class* cls = NULL; |
| 1712 Label* entry_label = NULL; |
| 1713 Label* exit_label = NULL; |
1670 switch (cid) { | 1714 switch (cid) { |
1671 case kDoubleCid: | 1715 case kDoubleCid: |
1672 cls = &compiler->double_class(); | 1716 cls = &compiler->double_class(); |
| 1717 entry_label = slow_path->double_entry_label(); |
| 1718 exit_label = slow_path->double_exit_label(); |
1673 break; | 1719 break; |
1674 // TODO(johnmccutchan): Add kFloat32x4Cid here. | 1720 case kFloat32x4Cid: |
| 1721 cls = &compiler->float32x4_class(); |
| 1722 entry_label = slow_path->float32x4_entry_label(); |
| 1723 exit_label = slow_path->float32x4_exit_label(); |
| 1724 break; |
1675 default: | 1725 default: |
1676 UNREACHABLE(); | 1726 UNREACHABLE(); |
1677 } | 1727 } |
1678 StoreInstanceFieldSlowPath* slow_path = | |
1679 new StoreInstanceFieldSlowPath(this, *cls); | |
1680 compiler->AddSlowPathCode(slow_path); | |
1681 | 1728 |
1682 __ TryAllocate(*cls, | 1729 __ TryAllocate(*cls, |
1683 slow_path->entry_label(), | 1730 entry_label, |
1684 Assembler::kFarJump, | 1731 Assembler::kFarJump, |
1685 temp, | 1732 temp, |
1686 temp2); | 1733 temp2); |
1687 __ Bind(slow_path->exit_label()); | 1734 __ Bind(exit_label); |
1688 __ movl(temp2, temp); | 1735 __ movl(temp2, temp); |
1689 __ StoreIntoObject(instance_reg, | 1736 __ StoreIntoObject(instance_reg, |
1690 FieldAddress(instance_reg, field().Offset()), | 1737 FieldAddress(instance_reg, field().Offset()), |
1691 temp2); | 1738 temp2); |
1692 } else { | 1739 } else { |
1693 __ movl(temp, FieldAddress(instance_reg, field().Offset())); | 1740 __ movl(temp, FieldAddress(instance_reg, field().Offset())); |
1694 } | 1741 } |
1695 switch (cid) { | 1742 switch (cid) { |
1696 case kDoubleCid: | 1743 case kDoubleCid: |
1697 __ movsd(FieldAddress(temp, Double::value_offset()), value); | 1744 __ Comment("UnboxedDoubleStoreInstanceFieldInstr"); |
1698 // TODO(johnmccutchan): Add kFloat32x4Cid here. | 1745 __ movsd(FieldAddress(temp, Double::value_offset()), value); |
| 1746 break; |
| 1747 case kFloat32x4Cid: |
| 1748 __ Comment("UnboxedFloat32x4StoreInstanceFieldInstr"); |
| 1749 __ movups(FieldAddress(temp, Float32x4::value_offset()), value); |
1699 break; | 1750 break; |
1700 default: | 1751 default: |
1701 UNREACHABLE(); | 1752 UNREACHABLE(); |
1702 } | 1753 } |
1703 return; | 1754 return; |
1704 } | 1755 } |
1705 | 1756 |
1706 if (IsPotentialUnboxedStore()) { | 1757 if (IsPotentialUnboxedStore()) { |
1707 Register value_reg = locs()->in(1).reg(); | 1758 Register value_reg = locs()->in(1).reg(); |
1708 Register temp = locs()->temp(0).reg(); | 1759 Register temp = locs()->temp(0).reg(); |
1709 Register temp2 = locs()->temp(1).reg(); | 1760 Register temp2 = locs()->temp(1).reg(); |
1710 FpuRegister fpu_temp = locs()->temp(2).fpu_reg(); | 1761 FpuRegister fpu_temp = locs()->temp(2).fpu_reg(); |
1711 | 1762 |
1712 Label store_pointer; | 1763 Label store_pointer; |
1713 Label copy_double; | |
1714 Label store_double; | 1764 Label store_double; |
| 1765 Label store_float32x4; |
1715 | 1766 |
1716 __ LoadObject(temp, Field::ZoneHandle(field().raw())); | 1767 __ LoadObject(temp, Field::ZoneHandle(field().raw())); |
1717 | 1768 |
1718 __ cmpl(FieldAddress(temp, Field::is_nullable_offset()), | 1769 __ cmpl(FieldAddress(temp, Field::is_nullable_offset()), |
1719 Immediate(kNullCid)); | 1770 Immediate(kNullCid)); |
1720 __ j(EQUAL, &store_pointer); | 1771 __ j(EQUAL, &store_pointer); |
1721 | 1772 |
1722 __ movzxb(temp2, FieldAddress(temp, Field::kind_bits_offset())); | 1773 __ movzxb(temp2, FieldAddress(temp, Field::kind_bits_offset())); |
1723 __ testl(temp2, Immediate(1 << Field::kUnboxingCandidateBit)); | 1774 __ testl(temp2, Immediate(1 << Field::kUnboxingCandidateBit)); |
1724 __ j(ZERO, &store_pointer); | 1775 __ j(ZERO, &store_pointer); |
1725 | 1776 |
1726 __ cmpl(FieldAddress(temp, Field::guarded_cid_offset()), | 1777 __ cmpl(FieldAddress(temp, Field::guarded_cid_offset()), |
1727 Immediate(kDoubleCid)); | 1778 Immediate(kDoubleCid)); |
1728 __ j(EQUAL, &store_double); | 1779 __ j(EQUAL, &store_double); |
1729 | 1780 |
| 1781 __ cmpl(FieldAddress(temp, Field::guarded_cid_offset()), |
| 1782 Immediate(kFloat32x4Cid)); |
| 1783 __ j(EQUAL, &store_float32x4); |
| 1784 |
1730 // Fall through. | 1785 // Fall through. |
1731 __ jmp(&store_pointer); | 1786 __ jmp(&store_pointer); |
1732 | 1787 |
1733 __ Bind(&store_double); | |
1734 | |
1735 const Immediate& raw_null = | |
1736 Immediate(reinterpret_cast<intptr_t>(Object::null())); | |
1737 __ movl(temp, FieldAddress(instance_reg, field().Offset())); | |
1738 __ cmpl(temp, raw_null); | |
1739 __ j(NOT_EQUAL, ©_double); | |
1740 | |
1741 StoreInstanceFieldSlowPath* slow_path = | 1788 StoreInstanceFieldSlowPath* slow_path = |
1742 new StoreInstanceFieldSlowPath(this, compiler->double_class()); | 1789 new StoreInstanceFieldSlowPath(this); |
1743 compiler->AddSlowPathCode(slow_path); | 1790 compiler->AddSlowPathCode(slow_path); |
1744 | 1791 |
1745 if (!compiler->is_optimizing()) { | 1792 { |
1746 locs()->live_registers()->Add(locs()->in(0)); | 1793 __ Bind(&store_double); |
1747 locs()->live_registers()->Add(locs()->in(1)); | 1794 Label copy_double; |
| 1795 |
| 1796 const Immediate& raw_null = |
| 1797 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 1798 __ movl(temp, FieldAddress(instance_reg, field().Offset())); |
| 1799 __ cmpl(temp, raw_null); |
| 1800 __ j(NOT_EQUAL, ©_double); |
| 1801 |
| 1802 if (!compiler->is_optimizing()) { |
| 1803 locs()->live_registers()->Add(locs()->in(0)); |
| 1804 locs()->live_registers()->Add(locs()->in(1)); |
| 1805 } |
| 1806 |
| 1807 __ TryAllocate(compiler->double_class(), |
| 1808 slow_path->double_entry_label(), |
| 1809 Assembler::kFarJump, |
| 1810 temp, |
| 1811 temp2); |
| 1812 __ Bind(slow_path->double_exit_label()); |
| 1813 __ movl(temp2, temp); |
| 1814 __ StoreIntoObject(instance_reg, |
| 1815 FieldAddress(instance_reg, field().Offset()), |
| 1816 temp2); |
| 1817 |
| 1818 __ Bind(©_double); |
| 1819 __ movsd(fpu_temp, FieldAddress(value_reg, Double::value_offset())); |
| 1820 __ movsd(FieldAddress(temp, Double::value_offset()), fpu_temp); |
| 1821 __ jmp(&skip_store); |
1748 } | 1822 } |
1749 | 1823 |
1750 __ TryAllocate(compiler->double_class(), | 1824 { |
1751 slow_path->entry_label(), | 1825 __ Bind(&store_float32x4); |
1752 Assembler::kFarJump, | 1826 Label copy_float32x4; |
1753 temp, | |
1754 temp2); | |
1755 __ Bind(slow_path->exit_label()); | |
1756 __ movl(temp2, temp); | |
1757 __ StoreIntoObject(instance_reg, | |
1758 FieldAddress(instance_reg, field().Offset()), | |
1759 temp2); | |
1760 | 1827 |
1761 __ Bind(©_double); | 1828 const Immediate& raw_null = |
1762 __ movsd(fpu_temp, FieldAddress(value_reg, Double::value_offset())); | 1829 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
1763 __ movsd(FieldAddress(temp, Double::value_offset()), fpu_temp); | 1830 __ movl(temp, FieldAddress(instance_reg, field().Offset())); |
1764 __ jmp(&skip_store); | 1831 __ cmpl(temp, raw_null); |
| 1832 __ j(NOT_EQUAL, ©_float32x4); |
| 1833 |
| 1834 if (!compiler->is_optimizing()) { |
| 1835 locs()->live_registers()->Add(locs()->in(0)); |
| 1836 locs()->live_registers()->Add(locs()->in(1)); |
| 1837 } |
| 1838 |
| 1839 __ TryAllocate(compiler->float32x4_class(), |
| 1840 slow_path->float32x4_entry_label(), |
| 1841 Assembler::kFarJump, |
| 1842 temp, |
| 1843 temp2); |
| 1844 __ Bind(slow_path->float32x4_exit_label()); |
| 1845 __ movl(temp2, temp); |
| 1846 __ StoreIntoObject(instance_reg, |
| 1847 FieldAddress(instance_reg, field().Offset()), |
| 1848 temp2); |
| 1849 |
| 1850 __ Bind(©_float32x4); |
| 1851 __ movups(fpu_temp, FieldAddress(value_reg, Float32x4::value_offset())); |
| 1852 __ movups(FieldAddress(temp, Float32x4::value_offset()), fpu_temp); |
| 1853 __ jmp(&skip_store); |
| 1854 } |
1765 __ Bind(&store_pointer); | 1855 __ Bind(&store_pointer); |
1766 } | 1856 } |
1767 | 1857 |
1768 if (ShouldEmitStoreBarrier()) { | 1858 if (ShouldEmitStoreBarrier()) { |
1769 Register value_reg = locs()->in(1).reg(); | 1859 Register value_reg = locs()->in(1).reg(); |
1770 __ StoreIntoObject(instance_reg, | 1860 __ StoreIntoObject(instance_reg, |
1771 FieldAddress(instance_reg, field().Offset()), | 1861 FieldAddress(instance_reg, field().Offset()), |
1772 value_reg, | 1862 value_reg, |
1773 CanValueBeSmi()); | 1863 CanValueBeSmi()); |
1774 } else { | 1864 } else { |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1899 deopt_id(), | 1989 deopt_id(), |
1900 kAllocateObjectWithBoundsCheckRuntimeEntry, | 1990 kAllocateObjectWithBoundsCheckRuntimeEntry, |
1901 3, | 1991 3, |
1902 locs()); | 1992 locs()); |
1903 __ Drop(3); | 1993 __ Drop(3); |
1904 ASSERT(locs()->out().reg() == EAX); | 1994 ASSERT(locs()->out().reg() == EAX); |
1905 __ popl(EAX); // Pop new instance. | 1995 __ popl(EAX); // Pop new instance. |
1906 } | 1996 } |
1907 | 1997 |
1908 | 1998 |
1909 class BoxDoubleSlowPath : public SlowPathCode { | 1999 class LoadFieldSlowPath : public SlowPathCode { |
1910 public: | 2000 public: |
1911 explicit BoxDoubleSlowPath(Instruction* instruction) | 2001 explicit LoadFieldSlowPath(Instruction* instruction) |
1912 : instruction_(instruction) { } | 2002 : instruction_(instruction) { } |
1913 | 2003 |
1914 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 2004 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
1915 __ Comment("BoxDoubleSlowPath"); | 2005 __ Comment("LoadFieldSlowPath"); |
1916 __ Bind(entry_label()); | 2006 { |
1917 const Class& double_class = compiler->double_class(); | 2007 __ Bind(double_entry_label()); |
1918 const Code& stub = | 2008 const Class& double_class = compiler->double_class(); |
1919 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 2009 const Code& stub = |
1920 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 2010 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
| 2011 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
1921 | 2012 |
1922 LocationSummary* locs = instruction_->locs(); | 2013 LocationSummary* locs = instruction_->locs(); |
1923 locs->live_registers()->Remove(locs->out()); | 2014 locs->live_registers()->Remove(locs->out()); |
1924 | 2015 |
1925 compiler->SaveLiveRegisters(locs); | 2016 compiler->SaveLiveRegisters(locs); |
1926 compiler->GenerateCall(Scanner::kNoSourcePos, // No token position. | 2017 compiler->GenerateCall(Scanner::kNoSourcePos, // No token position. |
1927 &label, | 2018 &label, |
1928 PcDescriptors::kOther, | 2019 PcDescriptors::kOther, |
1929 locs); | 2020 locs); |
1930 __ MoveRegister(locs->out().reg(), EAX); | 2021 __ MoveRegister(locs->out().reg(), EAX); |
1931 compiler->RestoreLiveRegisters(locs); | 2022 compiler->RestoreLiveRegisters(locs); |
1932 | 2023 |
1933 __ jmp(exit_label()); | 2024 __ jmp(double_exit_label()); |
| 2025 } |
| 2026 { |
| 2027 __ Bind(float32x4_entry_label()); |
| 2028 const Class& float32x4_class = compiler->float32x4_class(); |
| 2029 const Code& stub = |
| 2030 Code::Handle(StubCode::GetAllocationStubForClass(float32x4_class)); |
| 2031 const ExternalLabel label(float32x4_class.ToCString(), stub.EntryPoint()); |
| 2032 |
| 2033 LocationSummary* locs = instruction_->locs(); |
| 2034 locs->live_registers()->Remove(locs->out()); |
| 2035 |
| 2036 compiler->SaveLiveRegisters(locs); |
| 2037 compiler->GenerateCall(Scanner::kNoSourcePos, // No token position. |
| 2038 &label, |
| 2039 PcDescriptors::kOther, |
| 2040 locs); |
| 2041 __ MoveRegister(locs->out().reg(), EAX); |
| 2042 compiler->RestoreLiveRegisters(locs); |
| 2043 |
| 2044 __ jmp(float32x4_exit_label()); |
| 2045 } |
1934 } | 2046 } |
1935 | 2047 |
| 2048 Label* double_entry_label() { |
| 2049 // Use default SlowPathCode label for double. |
| 2050 return entry_label(); |
| 2051 } |
| 2052 Label* double_exit_label() { |
| 2053 // Use default SlowPathCode label for double. |
| 2054 return exit_label(); |
| 2055 } |
| 2056 |
| 2057 Label* float32x4_entry_label() { return &float32x4_entry_label_; } |
| 2058 Label* float32x4_exit_label() { return &float32x4_exit_label_; } |
| 2059 |
1936 private: | 2060 private: |
| 2061 Label float32x4_entry_label_; |
| 2062 Label float32x4_exit_label_; |
1937 Instruction* instruction_; | 2063 Instruction* instruction_; |
1938 }; | 2064 }; |
1939 | 2065 |
1940 | 2066 |
1941 LocationSummary* LoadFieldInstr::MakeLocationSummary(bool opt) const { | 2067 LocationSummary* LoadFieldInstr::MakeLocationSummary(bool opt) const { |
1942 const intptr_t kNumInputs = 1; | 2068 const intptr_t kNumInputs = 1; |
1943 const intptr_t kNumTemps = 0; | 2069 const intptr_t kNumTemps = 0; |
1944 LocationSummary* locs = | 2070 LocationSummary* locs = |
1945 new LocationSummary( | 2071 new LocationSummary( |
1946 kNumInputs, kNumTemps, | 2072 kNumInputs, kNumTemps, |
(...skipping 17 matching lines...) Expand all Loading... |
1964 | 2090 |
1965 void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2091 void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1966 Register instance_reg = locs()->in(0).reg(); | 2092 Register instance_reg = locs()->in(0).reg(); |
1967 if (IsUnboxedLoad() && compiler->is_optimizing()) { | 2093 if (IsUnboxedLoad() && compiler->is_optimizing()) { |
1968 XmmRegister result = locs()->out().fpu_reg(); | 2094 XmmRegister result = locs()->out().fpu_reg(); |
1969 Register temp = locs()->temp(0).reg(); | 2095 Register temp = locs()->temp(0).reg(); |
1970 __ movl(temp, FieldAddress(instance_reg, offset_in_bytes())); | 2096 __ movl(temp, FieldAddress(instance_reg, offset_in_bytes())); |
1971 const intptr_t cid = field()->UnboxedFieldCid(); | 2097 const intptr_t cid = field()->UnboxedFieldCid(); |
1972 switch (cid) { | 2098 switch (cid) { |
1973 case kDoubleCid: | 2099 case kDoubleCid: |
| 2100 __ Comment("UnboxedDoubleLoadFieldInstr"); |
1974 __ movsd(result, FieldAddress(temp, Double::value_offset())); | 2101 __ movsd(result, FieldAddress(temp, Double::value_offset())); |
1975 break; | 2102 break; |
1976 // TODO(johnmccutchan): Add Float32x4 path here. | 2103 case kFloat32x4Cid: |
| 2104 __ Comment("UnboxedFloat32x4LoadFieldInstr"); |
| 2105 __ movups(result, FieldAddress(temp, Float32x4::value_offset())); |
| 2106 break; |
1977 default: | 2107 default: |
1978 UNREACHABLE(); | 2108 UNREACHABLE(); |
1979 } | 2109 } |
1980 return; | 2110 return; |
1981 } | 2111 } |
1982 | 2112 |
1983 Label done; | 2113 Label done; |
1984 Register result = locs()->out().reg(); | 2114 Register result = locs()->out().reg(); |
1985 if (IsPotentialUnboxedLoad()) { | 2115 if (IsPotentialUnboxedLoad()) { |
1986 Register temp = locs()->temp(1).reg(); | 2116 Register temp = locs()->temp(1).reg(); |
1987 XmmRegister value = locs()->temp(0).fpu_reg(); | 2117 XmmRegister value = locs()->temp(0).fpu_reg(); |
| 2118 LoadFieldSlowPath* slow_path = new LoadFieldSlowPath(this); |
| 2119 compiler->AddSlowPathCode(slow_path); |
1988 | 2120 |
1989 Label load_pointer; | 2121 Label load_pointer; |
1990 Label load_double; | 2122 Label load_double; |
| 2123 Label load_float32x4; |
| 2124 |
1991 __ LoadObject(result, Field::ZoneHandle(field()->raw())); | 2125 __ LoadObject(result, Field::ZoneHandle(field()->raw())); |
1992 | 2126 |
1993 FieldAddress field_cid_operand(result, Field::guarded_cid_offset()); | 2127 FieldAddress field_cid_operand(result, Field::guarded_cid_offset()); |
1994 FieldAddress field_nullability_operand(result, Field::is_nullable_offset()); | 2128 FieldAddress field_nullability_operand(result, Field::is_nullable_offset()); |
1995 | 2129 |
1996 __ cmpl(field_nullability_operand, Immediate(kNullCid)); | 2130 __ cmpl(field_nullability_operand, Immediate(kNullCid)); |
1997 __ j(EQUAL, &load_pointer); | 2131 __ j(EQUAL, &load_pointer); |
1998 | 2132 |
1999 __ cmpl(field_cid_operand, Immediate(kDoubleCid)); | 2133 __ cmpl(field_cid_operand, Immediate(kDoubleCid)); |
2000 __ j(EQUAL, &load_double); | 2134 __ j(EQUAL, &load_double); |
2001 | 2135 |
| 2136 __ cmpl(field_cid_operand, Immediate(kFloat32x4Cid)); |
| 2137 __ j(EQUAL, &load_float32x4); |
| 2138 |
2002 // Fall through. | 2139 // Fall through. |
2003 __ jmp(&load_pointer); | 2140 __ jmp(&load_pointer); |
2004 | 2141 |
2005 __ Bind(&load_double); | 2142 { |
2006 BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this); | 2143 __ Bind(&load_double); |
2007 compiler->AddSlowPathCode(slow_path); | |
2008 | 2144 |
2009 if (!compiler->is_optimizing()) { | 2145 if (!compiler->is_optimizing()) { |
2010 locs()->live_registers()->Add(locs()->in(0)); | 2146 locs()->live_registers()->Add(locs()->in(0)); |
| 2147 } |
| 2148 |
| 2149 __ TryAllocate(compiler->double_class(), |
| 2150 slow_path->double_entry_label(), |
| 2151 Assembler::kFarJump, |
| 2152 result, |
| 2153 temp); |
| 2154 __ Bind(slow_path->double_exit_label()); |
| 2155 __ movl(temp, FieldAddress(instance_reg, offset_in_bytes())); |
| 2156 __ movsd(value, FieldAddress(temp, Double::value_offset())); |
| 2157 __ movsd(FieldAddress(result, Double::value_offset()), value); |
| 2158 __ jmp(&done); |
2011 } | 2159 } |
2012 | 2160 |
2013 __ TryAllocate(compiler->double_class(), | 2161 { |
2014 slow_path->entry_label(), | 2162 __ Bind(&load_float32x4); |
2015 Assembler::kFarJump, | |
2016 result, | |
2017 temp); | |
2018 __ Bind(slow_path->exit_label()); | |
2019 __ movl(temp, FieldAddress(instance_reg, offset_in_bytes())); | |
2020 __ movsd(value, FieldAddress(temp, Double::value_offset())); | |
2021 __ movsd(FieldAddress(result, Double::value_offset()), value); | |
2022 __ jmp(&done); | |
2023 | 2163 |
2024 // TODO(johnmccutchan): Add Float32x4 path here. | 2164 if (!compiler->is_optimizing()) { |
| 2165 locs()->live_registers()->Add(locs()->in(0)); |
| 2166 } |
| 2167 |
| 2168 __ TryAllocate(compiler->float32x4_class(), |
| 2169 slow_path->float32x4_entry_label(), |
| 2170 Assembler::kFarJump, |
| 2171 result, |
| 2172 temp); |
| 2173 __ Bind(slow_path->float32x4_exit_label()); |
| 2174 __ movl(temp, FieldAddress(instance_reg, offset_in_bytes())); |
| 2175 __ movups(value, FieldAddress(temp, Float32x4::value_offset())); |
| 2176 __ movups(FieldAddress(result, Float32x4::value_offset()), value); |
| 2177 __ jmp(&done); |
| 2178 } |
2025 | 2179 |
2026 __ Bind(&load_pointer); | 2180 __ Bind(&load_pointer); |
2027 } | 2181 } |
2028 __ movl(result, FieldAddress(instance_reg, offset_in_bytes())); | 2182 __ movl(result, FieldAddress(instance_reg, offset_in_bytes())); |
2029 __ Bind(&done); | 2183 __ Bind(&done); |
2030 } | 2184 } |
2031 | 2185 |
2032 | 2186 |
2033 LocationSummary* InstantiateTypeInstr::MakeLocationSummary(bool opt) const { | 2187 LocationSummary* InstantiateTypeInstr::MakeLocationSummary(bool opt) const { |
2034 const intptr_t kNumInputs = 1; | 2188 const intptr_t kNumInputs = 1; |
(...skipping 835 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2870 } else { | 3024 } else { |
2871 Register temp = locs()->temp(0).reg(); | 3025 Register temp = locs()->temp(0).reg(); |
2872 __ movl(temp, left); | 3026 __ movl(temp, left); |
2873 __ orl(temp, right); | 3027 __ orl(temp, right); |
2874 __ testl(temp, Immediate(kSmiTagMask)); | 3028 __ testl(temp, Immediate(kSmiTagMask)); |
2875 } | 3029 } |
2876 __ j(ZERO, deopt); | 3030 __ j(ZERO, deopt); |
2877 } | 3031 } |
2878 | 3032 |
2879 | 3033 |
| 3034 class BoxDoubleSlowPath : public SlowPathCode { |
| 3035 public: |
| 3036 explicit BoxDoubleSlowPath(BoxDoubleInstr* instruction) |
| 3037 : instruction_(instruction) { } |
| 3038 |
| 3039 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3040 __ Comment("BoxDoubleSlowPath"); |
| 3041 __ Bind(entry_label()); |
| 3042 const Class& double_class = compiler->double_class(); |
| 3043 const Code& stub = |
| 3044 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
| 3045 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
| 3046 |
| 3047 LocationSummary* locs = instruction_->locs(); |
| 3048 locs->live_registers()->Remove(locs->out()); |
| 3049 |
| 3050 compiler->SaveLiveRegisters(locs); |
| 3051 compiler->GenerateCall(Scanner::kNoSourcePos, // No token position. |
| 3052 &label, |
| 3053 PcDescriptors::kOther, |
| 3054 locs); |
| 3055 __ MoveRegister(locs->out().reg(), EAX); |
| 3056 compiler->RestoreLiveRegisters(locs); |
| 3057 |
| 3058 __ jmp(exit_label()); |
| 3059 } |
| 3060 |
| 3061 private: |
| 3062 BoxDoubleInstr* instruction_; |
| 3063 }; |
| 3064 |
| 3065 |
2880 LocationSummary* BoxDoubleInstr::MakeLocationSummary(bool opt) const { | 3066 LocationSummary* BoxDoubleInstr::MakeLocationSummary(bool opt) const { |
2881 const intptr_t kNumInputs = 1; | 3067 const intptr_t kNumInputs = 1; |
2882 const intptr_t kNumTemps = 0; | 3068 const intptr_t kNumTemps = 0; |
2883 LocationSummary* summary = | 3069 LocationSummary* summary = |
2884 new LocationSummary(kNumInputs, | 3070 new LocationSummary(kNumInputs, |
2885 kNumTemps, | 3071 kNumTemps, |
2886 LocationSummary::kCallOnSlowPath); | 3072 LocationSummary::kCallOnSlowPath); |
2887 summary->set_in(0, Location::RequiresFpuRegister()); | 3073 summary->set_in(0, Location::RequiresFpuRegister()); |
2888 summary->set_out(Location::RequiresRegister()); | 3074 summary->set_out(Location::RequiresRegister()); |
2889 return summary; | 3075 return summary; |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2946 __ jmp(&done); | 3132 __ jmp(&done); |
2947 __ Bind(&is_smi); | 3133 __ Bind(&is_smi); |
2948 __ movl(temp, value); | 3134 __ movl(temp, value); |
2949 __ SmiUntag(temp); | 3135 __ SmiUntag(temp); |
2950 __ cvtsi2sd(result, temp); | 3136 __ cvtsi2sd(result, temp); |
2951 __ Bind(&done); | 3137 __ Bind(&done); |
2952 } | 3138 } |
2953 } | 3139 } |
2954 | 3140 |
2955 | 3141 |
2956 LocationSummary* BoxFloat32x4Instr::MakeLocationSummary(bool opt) const { | |
2957 const intptr_t kNumInputs = 1; | |
2958 const intptr_t kNumTemps = 0; | |
2959 LocationSummary* summary = | |
2960 new LocationSummary(kNumInputs, | |
2961 kNumTemps, | |
2962 LocationSummary::kCallOnSlowPath); | |
2963 summary->set_in(0, Location::RequiresFpuRegister()); | |
2964 summary->set_out(Location::RequiresRegister()); | |
2965 return summary; | |
2966 } | |
2967 | |
2968 | |
2969 class BoxFloat32x4SlowPath : public SlowPathCode { | 3142 class BoxFloat32x4SlowPath : public SlowPathCode { |
2970 public: | 3143 public: |
2971 explicit BoxFloat32x4SlowPath(BoxFloat32x4Instr* instruction) | 3144 explicit BoxFloat32x4SlowPath(BoxFloat32x4Instr* instruction) |
2972 : instruction_(instruction) { } | 3145 : instruction_(instruction) { } |
2973 | 3146 |
2974 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 3147 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
2975 __ Comment("BoxFloat32x4SlowPath"); | 3148 __ Comment("BoxFloat32x4SlowPath"); |
2976 __ Bind(entry_label()); | 3149 __ Bind(entry_label()); |
2977 const Class& float32x4_class = compiler->float32x4_class(); | 3150 const Class& float32x4_class = compiler->float32x4_class(); |
2978 const Code& stub = | 3151 const Code& stub = |
(...skipping 12 matching lines...) Expand all Loading... |
2991 compiler->RestoreLiveRegisters(locs); | 3164 compiler->RestoreLiveRegisters(locs); |
2992 | 3165 |
2993 __ jmp(exit_label()); | 3166 __ jmp(exit_label()); |
2994 } | 3167 } |
2995 | 3168 |
2996 private: | 3169 private: |
2997 BoxFloat32x4Instr* instruction_; | 3170 BoxFloat32x4Instr* instruction_; |
2998 }; | 3171 }; |
2999 | 3172 |
3000 | 3173 |
| 3174 LocationSummary* BoxFloat32x4Instr::MakeLocationSummary(bool opt) const { |
| 3175 const intptr_t kNumInputs = 1; |
| 3176 const intptr_t kNumTemps = 0; |
| 3177 LocationSummary* summary = |
| 3178 new LocationSummary(kNumInputs, |
| 3179 kNumTemps, |
| 3180 LocationSummary::kCallOnSlowPath); |
| 3181 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3182 summary->set_out(Location::RequiresRegister()); |
| 3183 return summary; |
| 3184 } |
| 3185 |
| 3186 |
3001 void BoxFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3187 void BoxFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3002 BoxFloat32x4SlowPath* slow_path = new BoxFloat32x4SlowPath(this); | 3188 BoxFloat32x4SlowPath* slow_path = new BoxFloat32x4SlowPath(this); |
3003 compiler->AddSlowPathCode(slow_path); | 3189 compiler->AddSlowPathCode(slow_path); |
3004 | 3190 |
3005 Register out_reg = locs()->out().reg(); | 3191 Register out_reg = locs()->out().reg(); |
3006 XmmRegister value = locs()->in(0).fpu_reg(); | 3192 XmmRegister value = locs()->in(0).fpu_reg(); |
3007 | 3193 |
3008 __ TryAllocate(compiler->float32x4_class(), | 3194 __ TryAllocate(compiler->float32x4_class(), |
3009 slow_path->entry_label(), | 3195 slow_path->entry_label(), |
3010 Assembler::kFarJump, | 3196 Assembler::kFarJump, |
(...skipping 2270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5281 PcDescriptors::kOther, | 5467 PcDescriptors::kOther, |
5282 locs()); | 5468 locs()); |
5283 __ Drop(2); // Discard type arguments and receiver. | 5469 __ Drop(2); // Discard type arguments and receiver. |
5284 } | 5470 } |
5285 | 5471 |
5286 } // namespace dart | 5472 } // namespace dart |
5287 | 5473 |
5288 #undef __ | 5474 #undef __ |
5289 | 5475 |
5290 #endif // defined TARGET_ARCH_IA32 | 5476 #endif // defined TARGET_ARCH_IA32 |
OLD | NEW |