| 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_ARM. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. |
| 6 #if defined(TARGET_ARCH_ARM) | 6 #if defined(TARGET_ARCH_ARM) |
| 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 | 1583 |
| 1584 class StoreInstanceFieldSlowPath : public SlowPathCode { | 1584 class StoreInstanceFieldSlowPath : public SlowPathCode { |
| 1585 public: | 1585 public: |
| 1586 StoreInstanceFieldSlowPath(StoreInstanceFieldInstr* instruction, | 1586 StoreInstanceFieldSlowPath(StoreInstanceFieldInstr* instruction, |
| 1587 const Class& cls) | 1587 const Class& cls) |
| 1588 : instruction_(instruction), cls_(cls) { } | 1588 : instruction_(instruction), cls_(cls) { } |
| 1589 | 1589 |
| 1590 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 1590 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1591 __ Comment("StoreInstanceFieldSlowPath"); | 1591 __ Comment("StoreInstanceFieldSlowPath"); |
| 1592 __ Bind(entry_label()); | 1592 __ Bind(entry_label()); |
| 1593 |
| 1593 const Code& stub = | 1594 const Code& stub = |
| 1594 Code::Handle(StubCode::GetAllocationStubForClass(cls_)); | 1595 Code::Handle(StubCode::GetAllocationStubForClass(cls_)); |
| 1595 const ExternalLabel label(cls_.ToCString(), stub.EntryPoint()); | 1596 const ExternalLabel label(cls_.ToCString(), stub.EntryPoint()); |
| 1596 | 1597 |
| 1597 LocationSummary* locs = instruction_->locs(); | 1598 LocationSummary* locs = instruction_->locs(); |
| 1598 locs->live_registers()->Remove(locs->out()); | 1599 locs->live_registers()->Remove(locs->out()); |
| 1599 | 1600 |
| 1600 compiler->SaveLiveRegisters(locs); | 1601 compiler->SaveLiveRegisters(locs); |
| 1601 compiler->GenerateCall(Scanner::kNoSourcePos, // No token position. | 1602 compiler->GenerateCall(Scanner::kNoSourcePos, // No token position. |
| 1602 &label, | 1603 &label, |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1645 } | 1646 } |
| 1646 | 1647 |
| 1647 | 1648 |
| 1648 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1649 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1649 Label skip_store; | 1650 Label skip_store; |
| 1650 | 1651 |
| 1651 Register instance_reg = locs()->in(0).reg(); | 1652 Register instance_reg = locs()->in(0).reg(); |
| 1652 | 1653 |
| 1653 if (IsUnboxedStore() && compiler->is_optimizing()) { | 1654 if (IsUnboxedStore() && compiler->is_optimizing()) { |
| 1654 DRegister value = EvenDRegisterOf(locs()->in(1).fpu_reg()); | 1655 DRegister value = EvenDRegisterOf(locs()->in(1).fpu_reg()); |
| 1656 DRegister value_odd = OddDRegisterOf(locs()->in(1).fpu_reg()); |
| 1655 Register temp = locs()->temp(0).reg(); | 1657 Register temp = locs()->temp(0).reg(); |
| 1656 Register temp2 = locs()->temp(1).reg(); | 1658 Register temp2 = locs()->temp(1).reg(); |
| 1657 const intptr_t cid = field().UnboxedFieldCid(); | 1659 const intptr_t cid = field().UnboxedFieldCid(); |
| 1658 | 1660 |
| 1659 if (is_initialization_) { | 1661 if (is_initialization_) { |
| 1660 const Class* cls = NULL; | 1662 const Class* cls = NULL; |
| 1661 switch (cid) { | 1663 switch (cid) { |
| 1662 case kDoubleCid: | 1664 case kDoubleCid: |
| 1663 cls = &compiler->double_class(); | 1665 cls = &compiler->double_class(); |
| 1664 break; | 1666 break; |
| 1665 // TODO(johnmccutchan): Add kFloat32x4Cid here. | 1667 case kFloat32x4Cid: |
| 1668 cls = &compiler->float32x4_class(); |
| 1669 break; |
| 1666 default: | 1670 default: |
| 1667 UNREACHABLE(); | 1671 UNREACHABLE(); |
| 1668 } | 1672 } |
| 1673 |
| 1669 StoreInstanceFieldSlowPath* slow_path = | 1674 StoreInstanceFieldSlowPath* slow_path = |
| 1670 new StoreInstanceFieldSlowPath(this, *cls); | 1675 new StoreInstanceFieldSlowPath(this, *cls); |
| 1671 compiler->AddSlowPathCode(slow_path); | 1676 compiler->AddSlowPathCode(slow_path); |
| 1677 |
| 1672 __ TryAllocate(*cls, | 1678 __ TryAllocate(*cls, |
| 1673 slow_path->entry_label(), | 1679 slow_path->entry_label(), |
| 1674 temp, | 1680 temp, |
| 1675 temp2); | 1681 temp2); |
| 1676 __ Bind(slow_path->exit_label()); | 1682 __ Bind(slow_path->exit_label()); |
| 1677 __ MoveRegister(temp2, temp); | 1683 __ MoveRegister(temp2, temp); |
| 1678 __ StoreIntoObject(instance_reg, | 1684 __ StoreIntoObject(instance_reg, |
| 1679 FieldAddress(instance_reg, field().Offset()), | 1685 FieldAddress(instance_reg, field().Offset()), |
| 1680 temp2); | 1686 temp2); |
| 1681 } else { | 1687 } else { |
| 1682 __ ldr(temp, FieldAddress(instance_reg, field().Offset())); | 1688 __ ldr(temp, FieldAddress(instance_reg, field().Offset())); |
| 1683 } | 1689 } |
| 1684 switch (cid) { | 1690 switch (cid) { |
| 1685 case kDoubleCid: | 1691 case kDoubleCid: |
| 1686 __ StoreDToOffset(value, temp, Double::value_offset() - kHeapObjectTag); | 1692 __ Comment("UnboxedDoubleStoreInstanceFieldInstr"); |
| 1687 // TODO(johnmccutchan): Add kFloat32x4Cid here. | 1693 __ StoreDToOffset(value, temp, Double::value_offset() - kHeapObjectTag); |
| 1688 break; | 1694 break; |
| 1695 case kFloat32x4Cid: |
| 1696 __ Comment("UnboxedFloat32x4StoreInstanceFieldInstr"); |
| 1697 __ StoreDToOffset(value, temp, |
| 1698 Float32x4::value_offset() - kHeapObjectTag); |
| 1699 __ StoreDToOffset(value_odd, temp, |
| 1700 Float32x4::value_offset() + 2*kWordSize - kHeapObjectTag); |
| 1701 break; |
| 1689 default: | 1702 default: |
| 1690 UNREACHABLE(); | 1703 UNREACHABLE(); |
| 1691 } | 1704 } |
| 1692 | 1705 |
| 1693 return; | 1706 return; |
| 1694 } | 1707 } |
| 1695 | 1708 |
| 1696 if (IsPotentialUnboxedStore()) { | 1709 if (IsPotentialUnboxedStore()) { |
| 1697 Register value_reg = locs()->in(1).reg(); | 1710 Register value_reg = locs()->in(1).reg(); |
| 1698 Register temp = locs()->temp(0).reg(); | 1711 Register temp = locs()->temp(0).reg(); |
| 1699 Register temp2 = locs()->temp(1).reg(); | 1712 Register temp2 = locs()->temp(1).reg(); |
| 1700 DRegister fpu_temp = EvenDRegisterOf(locs()->temp(2).fpu_reg()); | 1713 DRegister fpu_temp = EvenDRegisterOf(locs()->temp(2).fpu_reg()); |
| 1714 DRegister fpu_temp_odd = OddDRegisterOf(locs()->temp(2).fpu_reg()); |
| 1701 | 1715 |
| 1702 Label store_pointer; | 1716 Label store_pointer; |
| 1703 Label copy_double; | |
| 1704 Label store_double; | 1717 Label store_double; |
| 1718 Label store_float32x4; |
| 1705 | 1719 |
| 1706 __ LoadObject(temp, Field::ZoneHandle(field().raw())); | 1720 __ LoadObject(temp, Field::ZoneHandle(field().raw())); |
| 1707 | 1721 |
| 1708 __ ldr(temp2, FieldAddress(temp, Field::is_nullable_offset())); | 1722 __ ldr(temp2, FieldAddress(temp, Field::is_nullable_offset())); |
| 1709 __ CompareImmediate(temp2, kNullCid); | 1723 __ CompareImmediate(temp2, kNullCid); |
| 1710 __ b(&store_pointer, EQ); | 1724 __ b(&store_pointer, EQ); |
| 1711 | 1725 |
| 1712 __ ldrb(temp2, FieldAddress(temp, Field::kind_bits_offset())); | 1726 __ ldrb(temp2, FieldAddress(temp, Field::kind_bits_offset())); |
| 1713 __ tst(temp2, ShifterOperand(1 << Field::kUnboxingCandidateBit)); | 1727 __ tst(temp2, ShifterOperand(1 << Field::kUnboxingCandidateBit)); |
| 1714 __ b(&store_pointer, EQ); | 1728 __ b(&store_pointer, EQ); |
| 1715 | 1729 |
| 1716 __ ldr(temp2, FieldAddress(temp, Field::guarded_cid_offset())); | 1730 __ ldr(temp2, FieldAddress(temp, Field::guarded_cid_offset())); |
| 1717 __ CompareImmediate(temp2, kDoubleCid); | 1731 __ CompareImmediate(temp2, kDoubleCid); |
| 1718 __ b(&store_double, EQ); | 1732 __ b(&store_double, EQ); |
| 1719 | 1733 |
| 1734 __ ldr(temp2, FieldAddress(temp, Field::guarded_cid_offset())); |
| 1735 __ CompareImmediate(temp2, kFloat32x4Cid); |
| 1736 __ b(&store_float32x4, EQ); |
| 1737 |
| 1720 // Fall through. | 1738 // Fall through. |
| 1721 __ b(&store_pointer); | 1739 __ b(&store_pointer); |
| 1722 | 1740 |
| 1723 __ Bind(&store_double); | |
| 1724 | |
| 1725 __ ldr(temp, FieldAddress(instance_reg, field().Offset())); | |
| 1726 __ CompareImmediate(temp, | |
| 1727 reinterpret_cast<intptr_t>(Object::null())); | |
| 1728 __ b(©_double, NE); | |
| 1729 | |
| 1730 StoreInstanceFieldSlowPath* slow_path = | |
| 1731 new StoreInstanceFieldSlowPath(this, compiler->double_class()); | |
| 1732 compiler->AddSlowPathCode(slow_path); | |
| 1733 | |
| 1734 if (!compiler->is_optimizing()) { | 1741 if (!compiler->is_optimizing()) { |
| 1735 locs()->live_registers()->Add(locs()->in(0)); | 1742 locs()->live_registers()->Add(locs()->in(0)); |
| 1736 locs()->live_registers()->Add(locs()->in(1)); | 1743 locs()->live_registers()->Add(locs()->in(1)); |
| 1737 } | 1744 } |
| 1738 | 1745 |
| 1739 __ TryAllocate(compiler->double_class(), | 1746 { |
| 1740 slow_path->entry_label(), | 1747 __ Bind(&store_double); |
| 1741 temp, | 1748 Label copy_double; |
| 1742 temp2); | 1749 StoreInstanceFieldSlowPath* slow_path = |
| 1743 __ Bind(slow_path->exit_label()); | 1750 new StoreInstanceFieldSlowPath(this, compiler->double_class()); |
| 1744 __ MoveRegister(temp2, temp); | 1751 compiler->AddSlowPathCode(slow_path); |
| 1745 __ StoreIntoObject(instance_reg, | 1752 |
| 1746 FieldAddress(instance_reg, field().Offset()), | 1753 __ ldr(temp, FieldAddress(instance_reg, field().Offset())); |
| 1747 temp2); | 1754 __ CompareImmediate(temp, |
| 1748 __ Bind(©_double); | 1755 reinterpret_cast<intptr_t>(Object::null())); |
| 1749 __ LoadDFromOffset(fpu_temp, | 1756 __ b(©_double, NE); |
| 1750 value_reg, | 1757 |
| 1751 Double::value_offset() - kHeapObjectTag); | 1758 __ TryAllocate(compiler->double_class(), |
| 1752 __ StoreDToOffset(fpu_temp, temp, Double::value_offset() - kHeapObjectTag); | 1759 slow_path->entry_label(), |
| 1753 __ b(&skip_store); | 1760 temp, |
| 1761 temp2); |
| 1762 __ Bind(slow_path->exit_label()); |
| 1763 __ MoveRegister(temp2, temp); |
| 1764 __ StoreIntoObject(instance_reg, |
| 1765 FieldAddress(instance_reg, field().Offset()), |
| 1766 temp2); |
| 1767 __ Bind(©_double); |
| 1768 __ LoadDFromOffset(fpu_temp, |
| 1769 value_reg, |
| 1770 Double::value_offset() - kHeapObjectTag); |
| 1771 __ StoreDToOffset(fpu_temp, |
| 1772 temp, |
| 1773 Double::value_offset() - kHeapObjectTag); |
| 1774 __ b(&skip_store); |
| 1775 } |
| 1776 |
| 1777 { |
| 1778 __ Bind(&store_float32x4); |
| 1779 Label copy_float32x4; |
| 1780 StoreInstanceFieldSlowPath* slow_path = |
| 1781 new StoreInstanceFieldSlowPath(this, compiler->float32x4_class()); |
| 1782 compiler->AddSlowPathCode(slow_path); |
| 1783 |
| 1784 __ ldr(temp, FieldAddress(instance_reg, field().Offset())); |
| 1785 __ CompareImmediate(temp, |
| 1786 reinterpret_cast<intptr_t>(Object::null())); |
| 1787 __ b(©_float32x4, NE); |
| 1788 |
| 1789 __ TryAllocate(compiler->float32x4_class(), |
| 1790 slow_path->entry_label(), |
| 1791 temp, |
| 1792 temp2); |
| 1793 __ Bind(slow_path->exit_label()); |
| 1794 __ MoveRegister(temp2, temp); |
| 1795 __ StoreIntoObject(instance_reg, |
| 1796 FieldAddress(instance_reg, field().Offset()), |
| 1797 temp2); |
| 1798 __ Bind(©_float32x4); |
| 1799 __ LoadDFromOffset(fpu_temp, value_reg, |
| 1800 Float32x4::value_offset() - kHeapObjectTag); |
| 1801 __ LoadDFromOffset(fpu_temp_odd, value_reg, |
| 1802 Float32x4::value_offset() + 2*kWordSize - kHeapObjectTag); |
| 1803 __ StoreDToOffset(fpu_temp, temp, |
| 1804 Float32x4::value_offset() - kHeapObjectTag); |
| 1805 __ StoreDToOffset(fpu_temp_odd, temp, |
| 1806 Float32x4::value_offset() + 2*kWordSize - kHeapObjectTag); |
| 1807 __ b(&skip_store); |
| 1808 } |
| 1809 |
| 1754 __ Bind(&store_pointer); | 1810 __ Bind(&store_pointer); |
| 1755 } | 1811 } |
| 1756 | 1812 |
| 1757 if (ShouldEmitStoreBarrier()) { | 1813 if (ShouldEmitStoreBarrier()) { |
| 1758 Register value_reg = locs()->in(1).reg(); | 1814 Register value_reg = locs()->in(1).reg(); |
| 1759 __ StoreIntoObject(instance_reg, | 1815 __ StoreIntoObject(instance_reg, |
| 1760 FieldAddress(instance_reg, field().Offset()), | 1816 FieldAddress(instance_reg, field().Offset()), |
| 1761 value_reg, | 1817 value_reg, |
| 1762 CanValueBeSmi()); | 1818 CanValueBeSmi()); |
| 1763 } else { | 1819 } else { |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1919 compiler->RestoreLiveRegisters(locs); | 1975 compiler->RestoreLiveRegisters(locs); |
| 1920 | 1976 |
| 1921 __ b(exit_label()); | 1977 __ b(exit_label()); |
| 1922 } | 1978 } |
| 1923 | 1979 |
| 1924 private: | 1980 private: |
| 1925 Instruction* instruction_; | 1981 Instruction* instruction_; |
| 1926 }; | 1982 }; |
| 1927 | 1983 |
| 1928 | 1984 |
| 1985 class BoxFloat32x4SlowPath : public SlowPathCode { |
| 1986 public: |
| 1987 explicit BoxFloat32x4SlowPath(Instruction* instruction) |
| 1988 : instruction_(instruction) { } |
| 1989 |
| 1990 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1991 __ Comment("BoxFloat32x4SlowPath"); |
| 1992 __ Bind(entry_label()); |
| 1993 const Class& float32x4_class = compiler->float32x4_class(); |
| 1994 const Code& stub = |
| 1995 Code::Handle(StubCode::GetAllocationStubForClass(float32x4_class)); |
| 1996 const ExternalLabel label(float32x4_class.ToCString(), stub.EntryPoint()); |
| 1997 |
| 1998 LocationSummary* locs = instruction_->locs(); |
| 1999 locs->live_registers()->Remove(locs->out()); |
| 2000 |
| 2001 compiler->SaveLiveRegisters(locs); |
| 2002 compiler->GenerateCall(Scanner::kNoSourcePos, // No token position. |
| 2003 &label, |
| 2004 PcDescriptors::kOther, |
| 2005 locs); |
| 2006 __ mov(locs->out().reg(), ShifterOperand(R0)); |
| 2007 compiler->RestoreLiveRegisters(locs); |
| 2008 |
| 2009 __ b(exit_label()); |
| 2010 } |
| 2011 |
| 2012 private: |
| 2013 Instruction* instruction_; |
| 2014 }; |
| 2015 |
| 2016 |
| 1929 LocationSummary* LoadFieldInstr::MakeLocationSummary(bool opt) const { | 2017 LocationSummary* LoadFieldInstr::MakeLocationSummary(bool opt) const { |
| 1930 const intptr_t kNumInputs = 1; | 2018 const intptr_t kNumInputs = 1; |
| 1931 const intptr_t kNumTemps = 0; | 2019 const intptr_t kNumTemps = 0; |
| 1932 LocationSummary* locs = | 2020 LocationSummary* locs = |
| 1933 new LocationSummary( | 2021 new LocationSummary( |
| 1934 kNumInputs, kNumTemps, | 2022 kNumInputs, kNumTemps, |
| 1935 (opt && !IsPotentialUnboxedLoad()) | 2023 (opt && !IsPotentialUnboxedLoad()) |
| 1936 ? LocationSummary::kNoCall | 2024 ? LocationSummary::kNoCall |
| 1937 : LocationSummary::kCallOnSlowPath); | 2025 : LocationSummary::kCallOnSlowPath); |
| 1938 | 2026 |
| 1939 locs->set_in(0, Location::RequiresRegister()); | 2027 locs->set_in(0, Location::RequiresRegister()); |
| 1940 | 2028 |
| 1941 if (IsUnboxedLoad() && opt) { | 2029 if (IsUnboxedLoad() && opt) { |
| 1942 locs->AddTemp(Location::RequiresRegister()); | 2030 locs->AddTemp(Location::RequiresRegister()); |
| 1943 } else if (IsPotentialUnboxedLoad()) { | 2031 } else if (IsPotentialUnboxedLoad()) { |
| 1944 locs->AddTemp(opt ? Location::RequiresFpuRegister() | 2032 locs->AddTemp(opt ? Location::RequiresFpuRegister() |
| 1945 : Location::FpuRegisterLocation(Q1)); | 2033 : Location::FpuRegisterLocation(Q1)); |
| 1946 locs->AddTemp(Location::RequiresRegister()); | 2034 locs->AddTemp(Location::RequiresRegister()); |
| 1947 } | 2035 } |
| 1948 locs->set_out(Location::RequiresRegister()); | 2036 locs->set_out(Location::RequiresRegister()); |
| 1949 return locs; | 2037 return locs; |
| 1950 } | 2038 } |
| 1951 | 2039 |
| 1952 | 2040 |
| 1953 void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2041 void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1954 Register instance_reg = locs()->in(0).reg(); | 2042 Register instance_reg = locs()->in(0).reg(); |
| 1955 if (IsUnboxedLoad() && compiler->is_optimizing()) { | 2043 if (IsUnboxedLoad() && compiler->is_optimizing()) { |
| 1956 DRegister result = EvenDRegisterOf(locs()->out().fpu_reg()); | 2044 DRegister result = EvenDRegisterOf(locs()->out().fpu_reg()); |
| 2045 DRegister result_odd = OddDRegisterOf(locs()->out().fpu_reg()); |
| 1957 Register temp = locs()->temp(0).reg(); | 2046 Register temp = locs()->temp(0).reg(); |
| 1958 __ ldr(temp, FieldAddress(instance_reg, offset_in_bytes())); | 2047 __ ldr(temp, FieldAddress(instance_reg, offset_in_bytes())); |
| 1959 intptr_t cid = field()->UnboxedFieldCid(); | 2048 intptr_t cid = field()->UnboxedFieldCid(); |
| 1960 switch (cid) { | 2049 switch (cid) { |
| 1961 case kDoubleCid: | 2050 case kDoubleCid: |
| 2051 __ Comment("UnboxedDoubleLoadFieldInstr"); |
| 1962 __ LoadDFromOffset(result, temp, | 2052 __ LoadDFromOffset(result, temp, |
| 1963 Double::value_offset() - kHeapObjectTag); | 2053 Double::value_offset() - kHeapObjectTag); |
| 1964 break; | 2054 break; |
| 1965 // TODO(johnmccutchan): Add Float32x4 path here. | 2055 case kFloat32x4Cid: |
| 2056 __ Comment("UnboxedFloat32x4LoadFieldInstr"); |
| 2057 __ LoadDFromOffset(result, temp, |
| 2058 Float32x4::value_offset() - kHeapObjectTag); |
| 2059 __ LoadDFromOffset(result_odd, temp, |
| 2060 Float32x4::value_offset() + 2*kWordSize - kHeapObjectTag); |
| 2061 break; |
| 1966 default: | 2062 default: |
| 1967 UNREACHABLE(); | 2063 UNREACHABLE(); |
| 1968 } | 2064 } |
| 1969 return; | 2065 return; |
| 1970 } | 2066 } |
| 1971 | 2067 |
| 1972 Label done; | 2068 Label done; |
| 1973 Register result_reg = locs()->out().reg(); | 2069 Register result_reg = locs()->out().reg(); |
| 1974 if (IsPotentialUnboxedLoad()) { | 2070 if (IsPotentialUnboxedLoad()) { |
| 1975 Register temp = locs()->temp(1).reg(); | 2071 Register temp = locs()->temp(1).reg(); |
| 1976 DRegister value = EvenDRegisterOf(locs()->temp(0).fpu_reg()); | 2072 DRegister value = EvenDRegisterOf(locs()->temp(0).fpu_reg()); |
| 2073 DRegister value_odd = OddDRegisterOf(locs()->temp(0).fpu_reg()); |
| 1977 | 2074 |
| 1978 Label load_pointer; | 2075 Label load_pointer; |
| 1979 Label load_double; | 2076 Label load_double; |
| 2077 Label load_float32x4; |
| 1980 | 2078 |
| 1981 __ LoadObject(result_reg, Field::ZoneHandle(field()->raw())); | 2079 __ LoadObject(result_reg, Field::ZoneHandle(field()->raw())); |
| 1982 | 2080 |
| 1983 FieldAddress field_cid_operand(result_reg, Field::guarded_cid_offset()); | 2081 FieldAddress field_cid_operand(result_reg, Field::guarded_cid_offset()); |
| 1984 FieldAddress field_nullability_operand(result_reg, | 2082 FieldAddress field_nullability_operand(result_reg, |
| 1985 Field::is_nullable_offset()); | 2083 Field::is_nullable_offset()); |
| 1986 | 2084 |
| 1987 __ ldr(temp, field_nullability_operand); | 2085 __ ldr(temp, field_nullability_operand); |
| 1988 __ CompareImmediate(temp, kNullCid); | 2086 __ CompareImmediate(temp, kNullCid); |
| 1989 __ b(&load_pointer, EQ); | 2087 __ b(&load_pointer, EQ); |
| 1990 | 2088 |
| 1991 __ ldr(temp, field_cid_operand); | 2089 __ ldr(temp, field_cid_operand); |
| 1992 __ CompareImmediate(temp, kDoubleCid); | 2090 __ CompareImmediate(temp, kDoubleCid); |
| 1993 __ b(&load_double, EQ); | 2091 __ b(&load_double, EQ); |
| 1994 | 2092 |
| 2093 __ ldr(temp, field_cid_operand); |
| 2094 __ CompareImmediate(temp, kFloat32x4Cid); |
| 2095 __ b(&load_float32x4, EQ); |
| 2096 |
| 1995 // Fall through. | 2097 // Fall through. |
| 1996 __ b(&load_pointer); | 2098 __ b(&load_pointer); |
| 1997 | 2099 |
| 1998 __ Bind(&load_double); | |
| 1999 | |
| 2000 BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this); | |
| 2001 compiler->AddSlowPathCode(slow_path); | |
| 2002 | |
| 2003 if (!compiler->is_optimizing()) { | 2100 if (!compiler->is_optimizing()) { |
| 2004 locs()->live_registers()->Add(locs()->in(0)); | 2101 locs()->live_registers()->Add(locs()->in(0)); |
| 2005 } | 2102 } |
| 2006 | 2103 |
| 2007 __ TryAllocate(compiler->double_class(), | 2104 { |
| 2008 slow_path->entry_label(), | 2105 __ Bind(&load_double); |
| 2009 result_reg, | 2106 BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this); |
| 2010 temp); | 2107 compiler->AddSlowPathCode(slow_path); |
| 2011 __ Bind(slow_path->exit_label()); | |
| 2012 __ ldr(temp, FieldAddress(instance_reg, offset_in_bytes())); | |
| 2013 __ LoadDFromOffset(value, temp, Double::value_offset() - kHeapObjectTag); | |
| 2014 __ StoreDToOffset(value, | |
| 2015 result_reg, | |
| 2016 Double::value_offset() - kHeapObjectTag); | |
| 2017 __ b(&done); | |
| 2018 | 2108 |
| 2019 // TODO(johnmccutchan): Add Float32x4 path here. | 2109 __ TryAllocate(compiler->double_class(), |
| 2110 slow_path->entry_label(), |
| 2111 result_reg, |
| 2112 temp); |
| 2113 __ Bind(slow_path->exit_label()); |
| 2114 __ ldr(temp, FieldAddress(instance_reg, offset_in_bytes())); |
| 2115 __ LoadDFromOffset(value, temp, Double::value_offset() - kHeapObjectTag); |
| 2116 __ StoreDToOffset(value, |
| 2117 result_reg, |
| 2118 Double::value_offset() - kHeapObjectTag); |
| 2119 __ b(&done); |
| 2120 } |
| 2121 |
| 2122 { |
| 2123 __ Bind(&load_float32x4); |
| 2124 BoxFloat32x4SlowPath* slow_path = new BoxFloat32x4SlowPath(this); |
| 2125 compiler->AddSlowPathCode(slow_path); |
| 2126 |
| 2127 __ TryAllocate(compiler->float32x4_class(), |
| 2128 slow_path->entry_label(), |
| 2129 result_reg, |
| 2130 temp); |
| 2131 __ Bind(slow_path->exit_label()); |
| 2132 __ ldr(temp, FieldAddress(instance_reg, offset_in_bytes())); |
| 2133 __ LoadDFromOffset(value, temp, |
| 2134 Float32x4::value_offset() - kHeapObjectTag); |
| 2135 __ LoadDFromOffset(value_odd, temp, |
| 2136 Float32x4::value_offset() + 2*kWordSize - kHeapObjectTag); |
| 2137 __ StoreDToOffset(value, result_reg, |
| 2138 Float32x4::value_offset() - kHeapObjectTag); |
| 2139 __ StoreDToOffset(value_odd, result_reg, |
| 2140 Float32x4::value_offset() + 2*kWordSize - kHeapObjectTag); |
| 2141 __ b(&done); |
| 2142 } |
| 2020 | 2143 |
| 2021 __ Bind(&load_pointer); | 2144 __ Bind(&load_pointer); |
| 2022 } | 2145 } |
| 2023 __ LoadFromOffset(kWord, result_reg, | 2146 __ LoadFromOffset(kWord, result_reg, |
| 2024 instance_reg, offset_in_bytes() - kHeapObjectTag); | 2147 instance_reg, offset_in_bytes() - kHeapObjectTag); |
| 2025 __ Bind(&done); | 2148 __ Bind(&done); |
| 2026 } | 2149 } |
| 2027 | 2150 |
| 2028 | 2151 |
| 2029 LocationSummary* InstantiateTypeInstr::MakeLocationSummary(bool opt) const { | 2152 LocationSummary* InstantiateTypeInstr::MakeLocationSummary(bool opt) const { |
| (...skipping 879 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2909 new LocationSummary(kNumInputs, | 3032 new LocationSummary(kNumInputs, |
| 2910 kNumTemps, | 3033 kNumTemps, |
| 2911 LocationSummary::kCallOnSlowPath); | 3034 LocationSummary::kCallOnSlowPath); |
| 2912 summary->set_in(0, Location::RequiresFpuRegister()); | 3035 summary->set_in(0, Location::RequiresFpuRegister()); |
| 2913 summary->set_temp(0, Location::RequiresRegister()); | 3036 summary->set_temp(0, Location::RequiresRegister()); |
| 2914 summary->set_out(Location::RequiresRegister()); | 3037 summary->set_out(Location::RequiresRegister()); |
| 2915 return summary; | 3038 return summary; |
| 2916 } | 3039 } |
| 2917 | 3040 |
| 2918 | 3041 |
| 2919 class BoxFloat32x4SlowPath : public SlowPathCode { | |
| 2920 public: | |
| 2921 explicit BoxFloat32x4SlowPath(BoxFloat32x4Instr* instruction) | |
| 2922 : instruction_(instruction) { } | |
| 2923 | |
| 2924 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 2925 __ Comment("BoxFloat32x4SlowPath"); | |
| 2926 __ Bind(entry_label()); | |
| 2927 const Class& float32x4_class = compiler->float32x4_class(); | |
| 2928 const Code& stub = | |
| 2929 Code::Handle(StubCode::GetAllocationStubForClass(float32x4_class)); | |
| 2930 const ExternalLabel label(float32x4_class.ToCString(), stub.EntryPoint()); | |
| 2931 | |
| 2932 LocationSummary* locs = instruction_->locs(); | |
| 2933 locs->live_registers()->Remove(locs->out()); | |
| 2934 | |
| 2935 compiler->SaveLiveRegisters(locs); | |
| 2936 compiler->GenerateCall(Scanner::kNoSourcePos, // No token position. | |
| 2937 &label, | |
| 2938 PcDescriptors::kOther, | |
| 2939 locs); | |
| 2940 __ mov(locs->out().reg(), ShifterOperand(R0)); | |
| 2941 compiler->RestoreLiveRegisters(locs); | |
| 2942 | |
| 2943 __ b(exit_label()); | |
| 2944 } | |
| 2945 | |
| 2946 private: | |
| 2947 BoxFloat32x4Instr* instruction_; | |
| 2948 }; | |
| 2949 | |
| 2950 | |
| 2951 void BoxFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3042 void BoxFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2952 BoxFloat32x4SlowPath* slow_path = new BoxFloat32x4SlowPath(this); | 3043 BoxFloat32x4SlowPath* slow_path = new BoxFloat32x4SlowPath(this); |
| 2953 compiler->AddSlowPathCode(slow_path); | 3044 compiler->AddSlowPathCode(slow_path); |
| 2954 | 3045 |
| 2955 Register out_reg = locs()->out().reg(); | 3046 Register out_reg = locs()->out().reg(); |
| 2956 QRegister value = locs()->in(0).fpu_reg(); | 3047 QRegister value = locs()->in(0).fpu_reg(); |
| 2957 DRegister value_even = EvenDRegisterOf(value); | 3048 DRegister value_even = EvenDRegisterOf(value); |
| 2958 DRegister value_odd = OddDRegisterOf(value); | 3049 DRegister value_odd = OddDRegisterOf(value); |
| 2959 | 3050 |
| 2960 __ TryAllocate(compiler->float32x4_class(), | 3051 __ TryAllocate(compiler->float32x4_class(), |
| (...skipping 1926 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4887 compiler->GenerateCall(token_pos(), | 4978 compiler->GenerateCall(token_pos(), |
| 4888 &label, | 4979 &label, |
| 4889 PcDescriptors::kOther, | 4980 PcDescriptors::kOther, |
| 4890 locs()); | 4981 locs()); |
| 4891 __ Drop(2); // Discard type arguments and receiver. | 4982 __ Drop(2); // Discard type arguments and receiver. |
| 4892 } | 4983 } |
| 4893 | 4984 |
| 4894 } // namespace dart | 4985 } // namespace dart |
| 4895 | 4986 |
| 4896 #endif // defined TARGET_ARCH_ARM | 4987 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |