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 1565 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1576 UNREACHABLE(); | 1576 UNREACHABLE(); |
1577 } | 1577 } |
1578 } | 1578 } |
1579 } | 1579 } |
1580 __ Bind(&ok); | 1580 __ Bind(&ok); |
1581 } | 1581 } |
1582 | 1582 |
1583 | 1583 |
1584 class StoreInstanceFieldSlowPath : public SlowPathCode { | 1584 class StoreInstanceFieldSlowPath : public SlowPathCode { |
1585 public: | 1585 public: |
1586 explicit StoreInstanceFieldSlowPath(StoreInstanceFieldInstr* instruction) | 1586 StoreInstanceFieldSlowPath(StoreInstanceFieldInstr* instruction, |
1587 : instruction_(instruction) { } | 1587 const Class& cls) |
| 1588 : instruction_(instruction), cls_(cls) { } |
1588 | 1589 |
1589 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 1590 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
1590 __ Comment("StoreInstanceFieldSlowPath"); | 1591 __ Comment("StoreInstanceFieldSlowPath"); |
1591 __ Bind(entry_label()); | 1592 __ Bind(entry_label()); |
1592 const Class& double_class = compiler->double_class(); | |
1593 const Code& stub = | 1593 const Code& stub = |
1594 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 1594 Code::Handle(StubCode::GetAllocationStubForClass(cls_)); |
1595 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 1595 const ExternalLabel label(cls_.ToCString(), stub.EntryPoint()); |
1596 | 1596 |
1597 LocationSummary* locs = instruction_->locs(); | 1597 LocationSummary* locs = instruction_->locs(); |
1598 locs->live_registers()->Remove(locs->out()); | 1598 locs->live_registers()->Remove(locs->out()); |
1599 | 1599 |
1600 compiler->SaveLiveRegisters(locs); | 1600 compiler->SaveLiveRegisters(locs); |
1601 compiler->GenerateCall(Scanner::kNoSourcePos, // No token position. | 1601 compiler->GenerateCall(Scanner::kNoSourcePos, // No token position. |
1602 &label, | 1602 &label, |
1603 PcDescriptors::kOther, | 1603 PcDescriptors::kOther, |
1604 locs); | 1604 locs); |
1605 __ MoveRegister(locs->temp(0).reg(), R0); | 1605 __ MoveRegister(locs->temp(0).reg(), R0); |
1606 compiler->RestoreLiveRegisters(locs); | 1606 compiler->RestoreLiveRegisters(locs); |
1607 | 1607 |
1608 __ b(exit_label()); | 1608 __ b(exit_label()); |
1609 } | 1609 } |
1610 | 1610 |
1611 private: | 1611 private: |
1612 StoreInstanceFieldInstr* instruction_; | 1612 StoreInstanceFieldInstr* instruction_; |
| 1613 const Class& cls_; |
1613 }; | 1614 }; |
1614 | 1615 |
1615 | 1616 |
1616 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(bool opt) const { | 1617 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(bool opt) const { |
1617 const intptr_t kNumInputs = 2; | 1618 const intptr_t kNumInputs = 2; |
1618 const intptr_t kNumTemps = 0; | 1619 const intptr_t kNumTemps = 0; |
1619 LocationSummary* summary = | 1620 LocationSummary* summary = |
1620 new LocationSummary(kNumInputs, kNumTemps, | 1621 new LocationSummary(kNumInputs, kNumTemps, |
1621 (field().guarded_cid() == kIllegalCid) || (is_initialization_) | 1622 (field().guarded_cid() == kIllegalCid) || (is_initialization_) |
1622 ? LocationSummary::kCallOnSlowPath | 1623 ? LocationSummary::kCallOnSlowPath |
(...skipping 23 matching lines...) Expand all Loading... |
1646 | 1647 |
1647 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1648 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1648 Label skip_store; | 1649 Label skip_store; |
1649 | 1650 |
1650 Register instance_reg = locs()->in(0).reg(); | 1651 Register instance_reg = locs()->in(0).reg(); |
1651 | 1652 |
1652 if (IsUnboxedStore() && compiler->is_optimizing()) { | 1653 if (IsUnboxedStore() && compiler->is_optimizing()) { |
1653 DRegister value = EvenDRegisterOf(locs()->in(1).fpu_reg()); | 1654 DRegister value = EvenDRegisterOf(locs()->in(1).fpu_reg()); |
1654 Register temp = locs()->temp(0).reg(); | 1655 Register temp = locs()->temp(0).reg(); |
1655 Register temp2 = locs()->temp(1).reg(); | 1656 Register temp2 = locs()->temp(1).reg(); |
| 1657 const intptr_t cid = field().UnboxedFieldCid(); |
1656 | 1658 |
1657 if (is_initialization_) { | 1659 if (is_initialization_) { |
| 1660 const Class* cls = NULL; |
| 1661 switch (cid) { |
| 1662 case kDoubleCid: |
| 1663 cls = &compiler->double_class(); |
| 1664 break; |
| 1665 // TODO(johnmccutchan): Add kFloat32x4Cid here. |
| 1666 default: |
| 1667 UNREACHABLE(); |
| 1668 } |
1658 StoreInstanceFieldSlowPath* slow_path = | 1669 StoreInstanceFieldSlowPath* slow_path = |
1659 new StoreInstanceFieldSlowPath(this); | 1670 new StoreInstanceFieldSlowPath(this, *cls); |
1660 compiler->AddSlowPathCode(slow_path); | 1671 compiler->AddSlowPathCode(slow_path); |
1661 __ TryAllocate(compiler->double_class(), | 1672 __ TryAllocate(*cls, |
1662 slow_path->entry_label(), | 1673 slow_path->entry_label(), |
1663 temp, | 1674 temp, |
1664 temp2); | 1675 temp2); |
1665 __ Bind(slow_path->exit_label()); | 1676 __ Bind(slow_path->exit_label()); |
1666 __ MoveRegister(temp2, temp); | 1677 __ MoveRegister(temp2, temp); |
1667 __ StoreIntoObject(instance_reg, | 1678 __ StoreIntoObject(instance_reg, |
1668 FieldAddress(instance_reg, field().Offset()), | 1679 FieldAddress(instance_reg, field().Offset()), |
1669 temp2); | 1680 temp2); |
1670 } else { | 1681 } else { |
1671 __ ldr(temp, FieldAddress(instance_reg, field().Offset())); | 1682 __ ldr(temp, FieldAddress(instance_reg, field().Offset())); |
1672 } | 1683 } |
1673 __ StoreDToOffset(value, temp, Double::value_offset() - kHeapObjectTag); | 1684 switch (cid) { |
| 1685 case kDoubleCid: |
| 1686 __ StoreDToOffset(value, temp, Double::value_offset() - kHeapObjectTag); |
| 1687 // TODO(johnmccutchan): Add kFloat32x4Cid here. |
| 1688 break; |
| 1689 default: |
| 1690 UNREACHABLE(); |
| 1691 } |
| 1692 |
1674 return; | 1693 return; |
1675 } | 1694 } |
1676 | 1695 |
1677 if (IsPotentialUnboxedStore()) { | 1696 if (IsPotentialUnboxedStore()) { |
1678 Register value_reg = locs()->in(1).reg(); | 1697 Register value_reg = locs()->in(1).reg(); |
1679 Register temp = locs()->temp(0).reg(); | 1698 Register temp = locs()->temp(0).reg(); |
1680 Register temp2 = locs()->temp(1).reg(); | 1699 Register temp2 = locs()->temp(1).reg(); |
1681 DRegister fpu_temp = EvenDRegisterOf(locs()->temp(2).fpu_reg()); | 1700 DRegister fpu_temp = EvenDRegisterOf(locs()->temp(2).fpu_reg()); |
1682 | 1701 |
1683 Label store_pointer, copy_payload; | 1702 Label store_pointer; |
| 1703 Label copy_double; |
| 1704 Label store_double; |
| 1705 |
1684 __ LoadObject(temp, Field::ZoneHandle(field().raw())); | 1706 __ LoadObject(temp, Field::ZoneHandle(field().raw())); |
1685 __ ldr(temp2, FieldAddress(temp, Field::guarded_cid_offset())); | 1707 |
1686 __ CompareImmediate(temp2, kDoubleCid); | |
1687 __ b(&store_pointer, NE); | |
1688 __ ldr(temp2, FieldAddress(temp, Field::is_nullable_offset())); | 1708 __ ldr(temp2, FieldAddress(temp, Field::is_nullable_offset())); |
1689 __ CompareImmediate(temp2, kNullCid); | 1709 __ CompareImmediate(temp2, kNullCid); |
1690 __ b(&store_pointer, EQ); | 1710 __ b(&store_pointer, EQ); |
| 1711 |
1691 __ ldrb(temp2, FieldAddress(temp, Field::kind_bits_offset())); | 1712 __ ldrb(temp2, FieldAddress(temp, Field::kind_bits_offset())); |
1692 __ tst(temp2, ShifterOperand(1 << Field::kUnboxingCandidateBit)); | 1713 __ tst(temp2, ShifterOperand(1 << Field::kUnboxingCandidateBit)); |
1693 __ b(&store_pointer, EQ); | 1714 __ b(&store_pointer, EQ); |
1694 | 1715 |
| 1716 __ ldr(temp2, FieldAddress(temp, Field::guarded_cid_offset())); |
| 1717 __ CompareImmediate(temp2, kDoubleCid); |
| 1718 __ b(&store_double, EQ); |
| 1719 |
| 1720 // Fall through. |
| 1721 __ b(&store_pointer); |
| 1722 |
| 1723 __ Bind(&store_double); |
| 1724 |
1695 __ ldr(temp, FieldAddress(instance_reg, field().Offset())); | 1725 __ ldr(temp, FieldAddress(instance_reg, field().Offset())); |
1696 __ CompareImmediate(temp, | 1726 __ CompareImmediate(temp, |
1697 reinterpret_cast<intptr_t>(Object::null())); | 1727 reinterpret_cast<intptr_t>(Object::null())); |
1698 __ b(©_payload, NE); | 1728 __ b(©_double, NE); |
1699 | 1729 |
1700 StoreInstanceFieldSlowPath* slow_path = | 1730 StoreInstanceFieldSlowPath* slow_path = |
1701 new StoreInstanceFieldSlowPath(this); | 1731 new StoreInstanceFieldSlowPath(this, compiler->double_class()); |
1702 compiler->AddSlowPathCode(slow_path); | 1732 compiler->AddSlowPathCode(slow_path); |
1703 | 1733 |
1704 if (!compiler->is_optimizing()) { | 1734 if (!compiler->is_optimizing()) { |
1705 locs()->live_registers()->Add(locs()->in(0)); | 1735 locs()->live_registers()->Add(locs()->in(0)); |
1706 locs()->live_registers()->Add(locs()->in(1)); | 1736 locs()->live_registers()->Add(locs()->in(1)); |
1707 } | 1737 } |
1708 | 1738 |
1709 __ TryAllocate(compiler->double_class(), | 1739 __ TryAllocate(compiler->double_class(), |
1710 slow_path->entry_label(), | 1740 slow_path->entry_label(), |
1711 temp, | 1741 temp, |
1712 temp2); | 1742 temp2); |
1713 __ Bind(slow_path->exit_label()); | 1743 __ Bind(slow_path->exit_label()); |
1714 __ MoveRegister(temp2, temp); | 1744 __ MoveRegister(temp2, temp); |
1715 __ StoreIntoObject(instance_reg, | 1745 __ StoreIntoObject(instance_reg, |
1716 FieldAddress(instance_reg, field().Offset()), | 1746 FieldAddress(instance_reg, field().Offset()), |
1717 temp2); | 1747 temp2); |
1718 __ Bind(©_payload); | 1748 __ Bind(©_double); |
1719 __ LoadDFromOffset(fpu_temp, | 1749 __ LoadDFromOffset(fpu_temp, |
1720 value_reg, | 1750 value_reg, |
1721 Double::value_offset() - kHeapObjectTag); | 1751 Double::value_offset() - kHeapObjectTag); |
1722 __ StoreDToOffset(fpu_temp, temp, Double::value_offset() - kHeapObjectTag); | 1752 __ StoreDToOffset(fpu_temp, temp, Double::value_offset() - kHeapObjectTag); |
1723 __ b(&skip_store); | 1753 __ b(&skip_store); |
1724 __ Bind(&store_pointer); | 1754 __ Bind(&store_pointer); |
1725 } | 1755 } |
1726 | 1756 |
1727 if (ShouldEmitStoreBarrier()) { | 1757 if (ShouldEmitStoreBarrier()) { |
1728 Register value_reg = locs()->in(1).reg(); | 1758 Register value_reg = locs()->in(1).reg(); |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1919 return locs; | 1949 return locs; |
1920 } | 1950 } |
1921 | 1951 |
1922 | 1952 |
1923 void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1953 void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1924 Register instance_reg = locs()->in(0).reg(); | 1954 Register instance_reg = locs()->in(0).reg(); |
1925 if (IsUnboxedLoad() && compiler->is_optimizing()) { | 1955 if (IsUnboxedLoad() && compiler->is_optimizing()) { |
1926 DRegister result = EvenDRegisterOf(locs()->out().fpu_reg()); | 1956 DRegister result = EvenDRegisterOf(locs()->out().fpu_reg()); |
1927 Register temp = locs()->temp(0).reg(); | 1957 Register temp = locs()->temp(0).reg(); |
1928 __ ldr(temp, FieldAddress(instance_reg, offset_in_bytes())); | 1958 __ ldr(temp, FieldAddress(instance_reg, offset_in_bytes())); |
1929 __ LoadDFromOffset(result, temp, Double::value_offset() - kHeapObjectTag); | 1959 intptr_t cid = field()->UnboxedFieldCid(); |
| 1960 switch (cid) { |
| 1961 case kDoubleCid: |
| 1962 __ LoadDFromOffset(result, temp, |
| 1963 Double::value_offset() - kHeapObjectTag); |
| 1964 break; |
| 1965 // TODO(johnmccutchan): Add Float32x4 path here. |
| 1966 default: |
| 1967 UNREACHABLE(); |
| 1968 } |
1930 return; | 1969 return; |
1931 } | 1970 } |
1932 | 1971 |
1933 Label done; | 1972 Label done; |
1934 Register result_reg = locs()->out().reg(); | 1973 Register result_reg = locs()->out().reg(); |
1935 if (IsPotentialUnboxedLoad()) { | 1974 if (IsPotentialUnboxedLoad()) { |
1936 Register temp = locs()->temp(1).reg(); | 1975 Register temp = locs()->temp(1).reg(); |
1937 DRegister value = EvenDRegisterOf(locs()->temp(0).fpu_reg()); | 1976 DRegister value = EvenDRegisterOf(locs()->temp(0).fpu_reg()); |
1938 | 1977 |
1939 Label load_pointer; | 1978 Label load_pointer; |
| 1979 Label load_double; |
| 1980 |
1940 __ LoadObject(result_reg, Field::ZoneHandle(field()->raw())); | 1981 __ LoadObject(result_reg, Field::ZoneHandle(field()->raw())); |
1941 | 1982 |
1942 FieldAddress field_cid_operand(result_reg, Field::guarded_cid_offset()); | 1983 FieldAddress field_cid_operand(result_reg, Field::guarded_cid_offset()); |
1943 FieldAddress field_nullability_operand(result_reg, | 1984 FieldAddress field_nullability_operand(result_reg, |
1944 Field::is_nullable_offset()); | 1985 Field::is_nullable_offset()); |
1945 | 1986 |
1946 __ ldr(temp, field_cid_operand); | |
1947 __ CompareImmediate(temp, kDoubleCid); | |
1948 __ b(&load_pointer, NE); | |
1949 | |
1950 __ ldr(temp, field_nullability_operand); | 1987 __ ldr(temp, field_nullability_operand); |
1951 __ CompareImmediate(temp, kNullCid); | 1988 __ CompareImmediate(temp, kNullCid); |
1952 __ b(&load_pointer, EQ); | 1989 __ b(&load_pointer, EQ); |
1953 | 1990 |
| 1991 __ ldr(temp, field_cid_operand); |
| 1992 __ CompareImmediate(temp, kDoubleCid); |
| 1993 __ b(&load_double, EQ); |
| 1994 |
| 1995 // Fall through. |
| 1996 __ b(&load_pointer); |
| 1997 |
| 1998 __ Bind(&load_double); |
| 1999 |
1954 BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this); | 2000 BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this); |
1955 compiler->AddSlowPathCode(slow_path); | 2001 compiler->AddSlowPathCode(slow_path); |
1956 | 2002 |
1957 if (!compiler->is_optimizing()) { | 2003 if (!compiler->is_optimizing()) { |
1958 locs()->live_registers()->Add(locs()->in(0)); | 2004 locs()->live_registers()->Add(locs()->in(0)); |
1959 } | 2005 } |
1960 | 2006 |
1961 __ TryAllocate(compiler->double_class(), | 2007 __ TryAllocate(compiler->double_class(), |
1962 slow_path->entry_label(), | 2008 slow_path->entry_label(), |
1963 result_reg, | 2009 result_reg, |
1964 temp); | 2010 temp); |
1965 __ Bind(slow_path->exit_label()); | 2011 __ Bind(slow_path->exit_label()); |
1966 __ ldr(temp, FieldAddress(instance_reg, offset_in_bytes())); | 2012 __ ldr(temp, FieldAddress(instance_reg, offset_in_bytes())); |
1967 __ LoadDFromOffset(value, temp, Double::value_offset() - kHeapObjectTag); | 2013 __ LoadDFromOffset(value, temp, Double::value_offset() - kHeapObjectTag); |
1968 __ StoreDToOffset(value, | 2014 __ StoreDToOffset(value, |
1969 result_reg, | 2015 result_reg, |
1970 Double::value_offset() - kHeapObjectTag); | 2016 Double::value_offset() - kHeapObjectTag); |
1971 __ b(&done); | 2017 __ b(&done); |
| 2018 |
| 2019 // TODO(johnmccutchan): Add Float32x4 path here. |
| 2020 |
1972 __ Bind(&load_pointer); | 2021 __ Bind(&load_pointer); |
1973 } | 2022 } |
1974 __ LoadFromOffset(kWord, result_reg, | 2023 __ LoadFromOffset(kWord, result_reg, |
1975 instance_reg, offset_in_bytes() - kHeapObjectTag); | 2024 instance_reg, offset_in_bytes() - kHeapObjectTag); |
1976 __ Bind(&done); | 2025 __ Bind(&done); |
1977 } | 2026 } |
1978 | 2027 |
1979 | 2028 |
1980 LocationSummary* InstantiateTypeInstr::MakeLocationSummary(bool opt) const { | 2029 LocationSummary* InstantiateTypeInstr::MakeLocationSummary(bool opt) const { |
1981 const intptr_t kNumInputs = 1; | 2030 const intptr_t kNumInputs = 1; |
(...skipping 2856 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4838 compiler->GenerateCall(token_pos(), | 4887 compiler->GenerateCall(token_pos(), |
4839 &label, | 4888 &label, |
4840 PcDescriptors::kOther, | 4889 PcDescriptors::kOther, |
4841 locs()); | 4890 locs()); |
4842 __ Drop(2); // Discard type arguments and receiver. | 4891 __ Drop(2); // Discard type arguments and receiver. |
4843 } | 4892 } |
4844 | 4893 |
4845 } // namespace dart | 4894 } // namespace dart |
4846 | 4895 |
4847 #endif // defined TARGET_ARCH_ARM | 4896 #endif // defined TARGET_ARCH_ARM |
OLD | NEW |