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_MIPS. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_MIPS. |
6 #if defined(TARGET_ARCH_MIPS) | 6 #if defined(TARGET_ARCH_MIPS) |
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 1640 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1651 UNREACHABLE(); | 1651 UNREACHABLE(); |
1652 } | 1652 } |
1653 } | 1653 } |
1654 } | 1654 } |
1655 __ Bind(&ok); | 1655 __ Bind(&ok); |
1656 } | 1656 } |
1657 | 1657 |
1658 | 1658 |
1659 class StoreInstanceFieldSlowPath : public SlowPathCode { | 1659 class StoreInstanceFieldSlowPath : public SlowPathCode { |
1660 public: | 1660 public: |
1661 explicit StoreInstanceFieldSlowPath(StoreInstanceFieldInstr* instruction) | 1661 StoreInstanceFieldSlowPath(StoreInstanceFieldInstr* instruction, |
1662 : instruction_(instruction) { } | 1662 const Class& cls) |
| 1663 : instruction_(instruction), cls_(cls) { } |
1663 | 1664 |
1664 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 1665 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
1665 __ Comment("StoreInstanceFieldSlowPath"); | 1666 __ Comment("StoreInstanceFieldSlowPath"); |
1666 __ Bind(entry_label()); | 1667 __ Bind(entry_label()); |
1667 const Class& double_class = compiler->double_class(); | |
1668 const Code& stub = | 1668 const Code& stub = |
1669 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 1669 Code::Handle(StubCode::GetAllocationStubForClass(cls_)); |
1670 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 1670 const ExternalLabel label(cls_.ToCString(), stub.EntryPoint()); |
1671 | 1671 |
1672 LocationSummary* locs = instruction_->locs(); | 1672 LocationSummary* locs = instruction_->locs(); |
1673 locs->live_registers()->Remove(locs->out()); | 1673 locs->live_registers()->Remove(locs->out()); |
1674 | 1674 |
1675 compiler->SaveLiveRegisters(locs); | 1675 compiler->SaveLiveRegisters(locs); |
1676 compiler->GenerateCall(Scanner::kNoSourcePos, // No token position. | 1676 compiler->GenerateCall(Scanner::kNoSourcePos, // No token position. |
1677 &label, | 1677 &label, |
1678 PcDescriptors::kOther, | 1678 PcDescriptors::kOther, |
1679 locs); | 1679 locs); |
1680 __ mov(locs->temp(0).reg(), V0); | 1680 __ mov(locs->temp(0).reg(), V0); |
1681 compiler->RestoreLiveRegisters(locs); | 1681 compiler->RestoreLiveRegisters(locs); |
1682 | 1682 |
1683 __ b(exit_label()); | 1683 __ b(exit_label()); |
1684 } | 1684 } |
1685 | 1685 |
1686 private: | 1686 private: |
1687 StoreInstanceFieldInstr* instruction_; | 1687 StoreInstanceFieldInstr* instruction_; |
| 1688 const Class& cls_; |
1688 }; | 1689 }; |
1689 | 1690 |
1690 | 1691 |
1691 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(bool opt) const { | 1692 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(bool opt) const { |
1692 const intptr_t kNumInputs = 2; | 1693 const intptr_t kNumInputs = 2; |
1693 const intptr_t kNumTemps = 0; | 1694 const intptr_t kNumTemps = 0; |
1694 LocationSummary* summary = | 1695 LocationSummary* summary = |
1695 new LocationSummary(kNumInputs, kNumTemps, | 1696 new LocationSummary(kNumInputs, kNumTemps, |
1696 (field().guarded_cid() == kIllegalCid) || (is_initialization_) | 1697 (field().guarded_cid() == kIllegalCid) || (is_initialization_) |
1697 ? LocationSummary::kCallOnSlowPath | 1698 ? LocationSummary::kCallOnSlowPath |
(...skipping 23 matching lines...) Expand all Loading... |
1721 | 1722 |
1722 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1723 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1723 Label skip_store; | 1724 Label skip_store; |
1724 | 1725 |
1725 Register instance_reg = locs()->in(0).reg(); | 1726 Register instance_reg = locs()->in(0).reg(); |
1726 | 1727 |
1727 if (IsUnboxedStore() && compiler->is_optimizing()) { | 1728 if (IsUnboxedStore() && compiler->is_optimizing()) { |
1728 DRegister value = locs()->in(1).fpu_reg(); | 1729 DRegister value = locs()->in(1).fpu_reg(); |
1729 Register temp = locs()->temp(0).reg(); | 1730 Register temp = locs()->temp(0).reg(); |
1730 Register temp2 = locs()->temp(1).reg(); | 1731 Register temp2 = locs()->temp(1).reg(); |
| 1732 const intptr_t cid = field().UnboxedFieldCid(); |
1731 | 1733 |
1732 if (is_initialization_) { | 1734 if (is_initialization_) { |
| 1735 const Class* cls = NULL; |
| 1736 switch (cid) { |
| 1737 case kDoubleCid: |
| 1738 cls = &compiler->double_class(); |
| 1739 break; |
| 1740 default: |
| 1741 UNREACHABLE(); |
| 1742 } |
1733 StoreInstanceFieldSlowPath* slow_path = | 1743 StoreInstanceFieldSlowPath* slow_path = |
1734 new StoreInstanceFieldSlowPath(this); | 1744 new StoreInstanceFieldSlowPath(this, *cls); |
1735 compiler->AddSlowPathCode(slow_path); | 1745 compiler->AddSlowPathCode(slow_path); |
1736 __ TryAllocate(compiler->double_class(), | 1746 __ TryAllocate(*cls, |
1737 slow_path->entry_label(), | 1747 slow_path->entry_label(), |
1738 temp, | 1748 temp, |
1739 temp2); | 1749 temp2); |
1740 __ Bind(slow_path->exit_label()); | 1750 __ Bind(slow_path->exit_label()); |
1741 __ mov(temp2, temp); | 1751 __ mov(temp2, temp); |
1742 __ StoreIntoObject(instance_reg, | 1752 __ StoreIntoObject(instance_reg, |
1743 FieldAddress(instance_reg, field().Offset()), | 1753 FieldAddress(instance_reg, field().Offset()), |
1744 temp2); | 1754 temp2); |
1745 } else { | 1755 } else { |
1746 __ lw(temp, FieldAddress(instance_reg, field().Offset())); | 1756 __ lw(temp, FieldAddress(instance_reg, field().Offset())); |
1747 } | 1757 } |
1748 __ StoreDToOffset(value, temp, Double::value_offset() - kHeapObjectTag); | 1758 switch (cid) { |
| 1759 case kDoubleCid: |
| 1760 __ StoreDToOffset(value, temp, Double::value_offset() - kHeapObjectTag); |
| 1761 break; |
| 1762 default: |
| 1763 UNREACHABLE(); |
| 1764 } |
1749 return; | 1765 return; |
1750 } | 1766 } |
1751 | 1767 |
1752 if (IsPotentialUnboxedStore()) { | 1768 if (IsPotentialUnboxedStore()) { |
1753 Register value_reg = locs()->in(1).reg(); | 1769 Register value_reg = locs()->in(1).reg(); |
1754 Register temp = locs()->temp(0).reg(); | 1770 Register temp = locs()->temp(0).reg(); |
1755 Register temp2 = locs()->temp(1).reg(); | 1771 Register temp2 = locs()->temp(1).reg(); |
1756 DRegister fpu_temp = locs()->temp(2).fpu_reg(); | 1772 DRegister fpu_temp = locs()->temp(2).fpu_reg(); |
1757 | 1773 |
1758 Label store_pointer, copy_payload; | 1774 Label store_pointer; |
| 1775 Label copy_double; |
| 1776 Label store_double; |
| 1777 |
1759 __ LoadObject(temp, Field::ZoneHandle(field().raw())); | 1778 __ LoadObject(temp, Field::ZoneHandle(field().raw())); |
1760 __ lw(temp2, FieldAddress(temp, Field::guarded_cid_offset())); | 1779 |
1761 __ BranchNotEqual(temp2, kDoubleCid, &store_pointer); | |
1762 __ lw(temp2, FieldAddress(temp, Field::is_nullable_offset())); | 1780 __ lw(temp2, FieldAddress(temp, Field::is_nullable_offset())); |
1763 __ BranchEqual(temp2, kNullCid, &store_pointer); | 1781 __ BranchEqual(temp2, kNullCid, &store_pointer); |
| 1782 |
1764 __ lbu(temp2, FieldAddress(temp, Field::kind_bits_offset())); | 1783 __ lbu(temp2, FieldAddress(temp, Field::kind_bits_offset())); |
1765 __ andi(CMPRES1, temp2, Immediate(1 << Field::kUnboxingCandidateBit)); | 1784 __ andi(CMPRES1, temp2, Immediate(1 << Field::kUnboxingCandidateBit)); |
1766 __ beq(CMPRES1, ZR, &store_pointer); | 1785 __ beq(CMPRES1, ZR, &store_pointer); |
1767 | 1786 |
| 1787 __ lw(temp2, FieldAddress(temp, Field::guarded_cid_offset())); |
| 1788 __ BranchEqual(temp2, kDoubleCid, &store_double); |
| 1789 |
| 1790 // Fall through. |
| 1791 __ b(&store_pointer); |
| 1792 |
| 1793 __ Bind(&store_double); |
| 1794 |
1768 __ lw(temp, FieldAddress(instance_reg, field().Offset())); | 1795 __ lw(temp, FieldAddress(instance_reg, field().Offset())); |
1769 __ BranchNotEqual(temp, reinterpret_cast<int32_t>(Object::null()), | 1796 __ BranchNotEqual(temp, reinterpret_cast<int32_t>(Object::null()), |
1770 ©_payload); | 1797 ©_double); |
1771 | 1798 |
1772 StoreInstanceFieldSlowPath* slow_path = | 1799 StoreInstanceFieldSlowPath* slow_path = |
1773 new StoreInstanceFieldSlowPath(this); | 1800 new StoreInstanceFieldSlowPath(this, compiler->double_class()); |
1774 compiler->AddSlowPathCode(slow_path); | 1801 compiler->AddSlowPathCode(slow_path); |
1775 | 1802 |
1776 if (!compiler->is_optimizing()) { | 1803 if (!compiler->is_optimizing()) { |
1777 locs()->live_registers()->Add(locs()->in(0)); | 1804 locs()->live_registers()->Add(locs()->in(0)); |
1778 locs()->live_registers()->Add(locs()->in(1)); | 1805 locs()->live_registers()->Add(locs()->in(1)); |
1779 } | 1806 } |
1780 | 1807 |
1781 __ TryAllocate(compiler->double_class(), | 1808 __ TryAllocate(compiler->double_class(), |
1782 slow_path->entry_label(), | 1809 slow_path->entry_label(), |
1783 temp, | 1810 temp, |
1784 temp2); | 1811 temp2); |
1785 __ Bind(slow_path->exit_label()); | 1812 __ Bind(slow_path->exit_label()); |
1786 __ mov(temp2, temp); | 1813 __ mov(temp2, temp); |
1787 __ StoreIntoObject(instance_reg, | 1814 __ StoreIntoObject(instance_reg, |
1788 FieldAddress(instance_reg, field().Offset()), | 1815 FieldAddress(instance_reg, field().Offset()), |
1789 temp2); | 1816 temp2); |
1790 | 1817 |
1791 __ Bind(©_payload); | 1818 __ Bind(©_double); |
1792 __ LoadDFromOffset(fpu_temp, | 1819 __ LoadDFromOffset(fpu_temp, |
1793 value_reg, | 1820 value_reg, |
1794 Double::value_offset() - kHeapObjectTag); | 1821 Double::value_offset() - kHeapObjectTag); |
1795 __ StoreDToOffset(fpu_temp, temp, Double::value_offset() - kHeapObjectTag); | 1822 __ StoreDToOffset(fpu_temp, temp, Double::value_offset() - kHeapObjectTag); |
1796 __ b(&skip_store); | 1823 __ b(&skip_store); |
1797 __ Bind(&store_pointer); | 1824 __ Bind(&store_pointer); |
1798 } | 1825 } |
1799 | 1826 |
1800 if (ShouldEmitStoreBarrier()) { | 1827 if (ShouldEmitStoreBarrier()) { |
1801 Register value_reg = locs()->in(1).reg(); | 1828 Register value_reg = locs()->in(1).reg(); |
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1997 return locs; | 2024 return locs; |
1998 } | 2025 } |
1999 | 2026 |
2000 | 2027 |
2001 void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2028 void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2002 Register instance_reg = locs()->in(0).reg(); | 2029 Register instance_reg = locs()->in(0).reg(); |
2003 if (IsUnboxedLoad() && compiler->is_optimizing()) { | 2030 if (IsUnboxedLoad() && compiler->is_optimizing()) { |
2004 DRegister result = locs()->out().fpu_reg(); | 2031 DRegister result = locs()->out().fpu_reg(); |
2005 Register temp = locs()->temp(0).reg(); | 2032 Register temp = locs()->temp(0).reg(); |
2006 __ lw(temp, FieldAddress(instance_reg, offset_in_bytes())); | 2033 __ lw(temp, FieldAddress(instance_reg, offset_in_bytes())); |
2007 __ LoadDFromOffset(result, temp, Double::value_offset() - kHeapObjectTag); | 2034 intptr_t cid = field()->UnboxedFieldCid(); |
| 2035 switch (cid) { |
| 2036 case kDoubleCid: |
| 2037 __ LoadDFromOffset(result, temp, |
| 2038 Double::value_offset() - kHeapObjectTag); |
| 2039 break; |
| 2040 default: |
| 2041 UNREACHABLE(); |
| 2042 } |
2008 return; | 2043 return; |
2009 } | 2044 } |
2010 | 2045 |
2011 Label done; | 2046 Label done; |
2012 Register result_reg = locs()->out().reg(); | 2047 Register result_reg = locs()->out().reg(); |
2013 if (IsPotentialUnboxedLoad()) { | 2048 if (IsPotentialUnboxedLoad()) { |
2014 Register temp = locs()->temp(1).reg(); | 2049 Register temp = locs()->temp(1).reg(); |
2015 DRegister value = locs()->temp(0).fpu_reg(); | 2050 DRegister value = locs()->temp(0).fpu_reg(); |
2016 | 2051 |
2017 Label load_pointer; | 2052 Label load_pointer; |
| 2053 Label load_double; |
| 2054 |
2018 __ LoadObject(result_reg, Field::ZoneHandle(field()->raw())); | 2055 __ LoadObject(result_reg, Field::ZoneHandle(field()->raw())); |
2019 | 2056 |
2020 FieldAddress field_cid_operand(result_reg, Field::guarded_cid_offset()); | 2057 FieldAddress field_cid_operand(result_reg, Field::guarded_cid_offset()); |
2021 FieldAddress field_nullability_operand(result_reg, | 2058 FieldAddress field_nullability_operand(result_reg, |
2022 Field::is_nullable_offset()); | 2059 Field::is_nullable_offset()); |
2023 | 2060 |
2024 __ lw(temp, field_cid_operand); | |
2025 __ BranchNotEqual(temp, kDoubleCid, &load_pointer); | |
2026 | |
2027 __ lw(temp, field_nullability_operand); | 2061 __ lw(temp, field_nullability_operand); |
2028 __ BranchEqual(temp, kNullCid, &load_pointer); | 2062 __ BranchEqual(temp, kNullCid, &load_pointer); |
2029 | 2063 |
| 2064 __ lw(temp, field_cid_operand); |
| 2065 __ BranchEqual(temp, kDoubleCid, &load_double); |
| 2066 |
| 2067 // Fall through. |
| 2068 __ b(&load_pointer); |
| 2069 |
| 2070 __ Bind(&load_double); |
| 2071 |
2030 BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this); | 2072 BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this); |
2031 compiler->AddSlowPathCode(slow_path); | 2073 compiler->AddSlowPathCode(slow_path); |
2032 | 2074 |
2033 if (!compiler->is_optimizing()) { | 2075 if (!compiler->is_optimizing()) { |
2034 locs()->live_registers()->Add(locs()->in(0)); | 2076 locs()->live_registers()->Add(locs()->in(0)); |
2035 } | 2077 } |
2036 | 2078 |
2037 __ TryAllocate(compiler->double_class(), | 2079 __ TryAllocate(compiler->double_class(), |
2038 slow_path->entry_label(), | 2080 slow_path->entry_label(), |
2039 result_reg, | 2081 result_reg, |
(...skipping 2162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4202 compiler->GenerateCall(token_pos(), | 4244 compiler->GenerateCall(token_pos(), |
4203 &label, | 4245 &label, |
4204 PcDescriptors::kOther, | 4246 PcDescriptors::kOther, |
4205 locs()); | 4247 locs()); |
4206 __ Drop(2); // Discard type arguments and receiver. | 4248 __ Drop(2); // Discard type arguments and receiver. |
4207 } | 4249 } |
4208 | 4250 |
4209 } // namespace dart | 4251 } // namespace dart |
4210 | 4252 |
4211 #endif // defined TARGET_ARCH_MIPS | 4253 #endif // defined TARGET_ARCH_MIPS |
OLD | NEW |