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 1656 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1667 | 1667 |
1668 __ lw(CMPRES1, | 1668 __ lw(CMPRES1, |
1669 FieldAddress(value_reg, | 1669 FieldAddress(value_reg, |
1670 field().guarded_list_length_in_object_offset())); | 1670 field().guarded_list_length_in_object_offset())); |
1671 __ LoadImmediate(TMP, Smi::RawValue(field().guarded_list_length())); | 1671 __ LoadImmediate(TMP, Smi::RawValue(field().guarded_list_length())); |
1672 __ bne(CMPRES1, TMP, deopt); | 1672 __ bne(CMPRES1, TMP, deopt); |
1673 } | 1673 } |
1674 } | 1674 } |
1675 | 1675 |
1676 | 1676 |
1677 class StoreInstanceFieldSlowPath : public SlowPathCode { | 1677 class BoxAllocationSlowPath : public SlowPathCode { |
1678 public: | 1678 public: |
1679 StoreInstanceFieldSlowPath(StoreInstanceFieldInstr* instruction, | 1679 BoxAllocationSlowPath(Instruction* instruction, |
1680 const Class& cls) | 1680 const Class& cls, |
1681 : instruction_(instruction), cls_(cls) { } | 1681 Register result) |
| 1682 : instruction_(instruction), |
| 1683 cls_(cls), |
| 1684 result_(result) { } |
1682 | 1685 |
1683 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 1686 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
1684 Isolate* isolate = compiler->isolate(); | 1687 Isolate* isolate = compiler->isolate(); |
1685 StubCode* stub_code = isolate->stub_code(); | 1688 StubCode* stub_code = isolate->stub_code(); |
1686 | 1689 |
1687 __ Comment("StoreInstanceFieldSlowPath"); | 1690 if (Assembler::EmittingComments()) { |
| 1691 __ Comment("%s slow path allocation of %s", |
| 1692 instruction_->DebugName(), |
| 1693 String::Handle(cls_.PrettyName()).ToCString()); |
| 1694 } |
1688 __ Bind(entry_label()); | 1695 __ Bind(entry_label()); |
1689 const Code& stub = | 1696 const Code& stub = |
1690 Code::Handle(isolate, stub_code->GetAllocationStubForClass(cls_)); | 1697 Code::Handle(isolate, stub_code->GetAllocationStubForClass(cls_)); |
1691 const ExternalLabel label(stub.EntryPoint()); | 1698 const ExternalLabel label(stub.EntryPoint()); |
1692 | 1699 |
1693 LocationSummary* locs = instruction_->locs(); | 1700 LocationSummary* locs = instruction_->locs(); |
1694 locs->live_registers()->Remove(locs->temp(0)); | 1701 locs->live_registers()->Remove(Location::RegisterLocation(result_)); |
1695 | 1702 |
1696 compiler->SaveLiveRegisters(locs); | 1703 compiler->SaveLiveRegisters(locs); |
1697 compiler->GenerateCall(Scanner::kNoSourcePos, // No token position. | 1704 compiler->GenerateCall(Scanner::kNoSourcePos, // No token position. |
1698 &label, | 1705 &label, |
1699 RawPcDescriptors::kOther, | 1706 RawPcDescriptors::kOther, |
1700 locs); | 1707 locs); |
1701 __ mov(locs->temp(0).reg(), V0); | 1708 if (result_ != V0) { |
| 1709 __ mov(result_, V0); |
| 1710 } |
1702 compiler->RestoreLiveRegisters(locs); | 1711 compiler->RestoreLiveRegisters(locs); |
1703 | 1712 |
1704 __ b(exit_label()); | 1713 __ b(exit_label()); |
1705 } | 1714 } |
1706 | 1715 |
| 1716 static void Allocate(FlowGraphCompiler* compiler, |
| 1717 Instruction* instruction, |
| 1718 const Class& cls, |
| 1719 Register result, |
| 1720 Register temp) { |
| 1721 BoxAllocationSlowPath* slow_path = |
| 1722 new BoxAllocationSlowPath(instruction, cls, result); |
| 1723 compiler->AddSlowPathCode(slow_path); |
| 1724 |
| 1725 __ TryAllocate(cls, |
| 1726 slow_path->entry_label(), |
| 1727 result, |
| 1728 temp); |
| 1729 __ Bind(slow_path->exit_label()); |
| 1730 } |
| 1731 |
1707 private: | 1732 private: |
1708 StoreInstanceFieldInstr* instruction_; | 1733 Instruction* instruction_; |
1709 const Class& cls_; | 1734 const Class& cls_; |
| 1735 Register result_; |
1710 }; | 1736 }; |
1711 | 1737 |
1712 | 1738 |
1713 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(Isolate* isolate, | 1739 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(Isolate* isolate, |
1714 bool opt) const { | 1740 bool opt) const { |
1715 const intptr_t kNumInputs = 2; | 1741 const intptr_t kNumInputs = 2; |
1716 const intptr_t kNumTemps = | 1742 const intptr_t kNumTemps = |
1717 (IsUnboxedStore() && opt) ? 2 : | 1743 (IsUnboxedStore() && opt) ? 2 : |
1718 ((IsPotentialUnboxedStore()) ? 3 : 0); | 1744 ((IsPotentialUnboxedStore()) ? 3 : 0); |
1719 LocationSummary* summary = new(isolate) LocationSummary( | 1745 LocationSummary* summary = new(isolate) LocationSummary( |
(...skipping 18 matching lines...) Expand all Loading... |
1738 : Location::FpuRegisterLocation(D1)); | 1764 : Location::FpuRegisterLocation(D1)); |
1739 } else { | 1765 } else { |
1740 summary->set_in(1, ShouldEmitStoreBarrier() | 1766 summary->set_in(1, ShouldEmitStoreBarrier() |
1741 ? Location::WritableRegister() | 1767 ? Location::WritableRegister() |
1742 : Location::RegisterOrConstant(value())); | 1768 : Location::RegisterOrConstant(value())); |
1743 } | 1769 } |
1744 return summary; | 1770 return summary; |
1745 } | 1771 } |
1746 | 1772 |
1747 | 1773 |
| 1774 static void EnsureMutableBox(FlowGraphCompiler* compiler, |
| 1775 StoreInstanceFieldInstr* instruction, |
| 1776 Register box_reg, |
| 1777 const Class& cls, |
| 1778 Register instance_reg, |
| 1779 intptr_t offset, |
| 1780 Register temp) { |
| 1781 Label done; |
| 1782 __ lw(box_reg, FieldAddress(instance_reg, offset)); |
| 1783 __ BranchNotEqual(box_reg, reinterpret_cast<int32_t>(Object::null()), |
| 1784 &done); |
| 1785 BoxAllocationSlowPath::Allocate(compiler, instruction, cls, box_reg, temp); |
| 1786 __ mov(temp, box_reg); |
| 1787 __ StoreIntoObjectOffset(instance_reg, offset, temp); |
| 1788 __ Bind(&done); |
| 1789 } |
| 1790 |
| 1791 |
1748 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1792 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1749 Label skip_store; | 1793 Label skip_store; |
1750 | 1794 |
1751 Register instance_reg = locs()->in(0).reg(); | 1795 Register instance_reg = locs()->in(0).reg(); |
1752 | 1796 |
1753 if (IsUnboxedStore() && compiler->is_optimizing()) { | 1797 if (IsUnboxedStore() && compiler->is_optimizing()) { |
1754 DRegister value = locs()->in(1).fpu_reg(); | 1798 DRegister value = locs()->in(1).fpu_reg(); |
1755 Register temp = locs()->temp(0).reg(); | 1799 Register temp = locs()->temp(0).reg(); |
1756 Register temp2 = locs()->temp(1).reg(); | 1800 Register temp2 = locs()->temp(1).reg(); |
1757 const intptr_t cid = field().UnboxedFieldCid(); | 1801 const intptr_t cid = field().UnboxedFieldCid(); |
1758 | 1802 |
1759 if (is_initialization_) { | 1803 if (is_initialization_) { |
1760 const Class* cls = NULL; | 1804 const Class* cls = NULL; |
1761 switch (cid) { | 1805 switch (cid) { |
1762 case kDoubleCid: | 1806 case kDoubleCid: |
1763 cls = &compiler->double_class(); | 1807 cls = &compiler->double_class(); |
1764 break; | 1808 break; |
1765 default: | 1809 default: |
1766 UNREACHABLE(); | 1810 UNREACHABLE(); |
1767 } | 1811 } |
1768 | 1812 |
1769 StoreInstanceFieldSlowPath* slow_path = | 1813 BoxAllocationSlowPath::Allocate(compiler, this, *cls, temp, temp2); |
1770 new StoreInstanceFieldSlowPath(this, *cls); | |
1771 compiler->AddSlowPathCode(slow_path); | |
1772 | |
1773 __ TryAllocate(*cls, | |
1774 slow_path->entry_label(), | |
1775 temp, | |
1776 temp2); | |
1777 __ Bind(slow_path->exit_label()); | |
1778 __ mov(temp2, temp); | 1814 __ mov(temp2, temp); |
1779 __ StoreIntoObjectOffset(instance_reg, offset_in_bytes_, temp2); | 1815 __ StoreIntoObjectOffset(instance_reg, offset_in_bytes_, temp2); |
1780 } else { | 1816 } else { |
1781 __ lw(temp, FieldAddress(instance_reg, offset_in_bytes_)); | 1817 __ lw(temp, FieldAddress(instance_reg, offset_in_bytes_)); |
1782 } | 1818 } |
1783 switch (cid) { | 1819 switch (cid) { |
1784 case kDoubleCid: | 1820 case kDoubleCid: |
1785 __ StoreDToOffset(value, temp, Double::value_offset() - kHeapObjectTag); | 1821 __ StoreDToOffset(value, temp, Double::value_offset() - kHeapObjectTag); |
1786 break; | 1822 break; |
1787 default: | 1823 default: |
(...skipping 26 matching lines...) Expand all Loading... |
1814 // Fall through. | 1850 // Fall through. |
1815 __ b(&store_pointer); | 1851 __ b(&store_pointer); |
1816 | 1852 |
1817 if (!compiler->is_optimizing()) { | 1853 if (!compiler->is_optimizing()) { |
1818 locs()->live_registers()->Add(locs()->in(0)); | 1854 locs()->live_registers()->Add(locs()->in(0)); |
1819 locs()->live_registers()->Add(locs()->in(1)); | 1855 locs()->live_registers()->Add(locs()->in(1)); |
1820 } | 1856 } |
1821 | 1857 |
1822 { | 1858 { |
1823 __ Bind(&store_double); | 1859 __ Bind(&store_double); |
1824 Label copy_double; | 1860 EnsureMutableBox(compiler, |
1825 | 1861 this, |
1826 __ lw(temp, FieldAddress(instance_reg, offset_in_bytes_)); | 1862 temp, |
1827 __ BranchNotEqual(temp, reinterpret_cast<int32_t>(Object::null()), | 1863 compiler->double_class(), |
1828 ©_double); | 1864 instance_reg, |
1829 | 1865 offset_in_bytes_, |
1830 StoreInstanceFieldSlowPath* slow_path = | 1866 temp2); |
1831 new StoreInstanceFieldSlowPath(this, compiler->double_class()); | |
1832 compiler->AddSlowPathCode(slow_path); | |
1833 | |
1834 __ TryAllocate(compiler->double_class(), | |
1835 slow_path->entry_label(), | |
1836 temp, | |
1837 temp2); | |
1838 __ Bind(slow_path->exit_label()); | |
1839 __ mov(temp2, temp); | |
1840 __ StoreIntoObjectOffset(instance_reg, offset_in_bytes_, temp2); | |
1841 | |
1842 __ Bind(©_double); | |
1843 __ LoadDFromOffset(fpu_temp, | 1867 __ LoadDFromOffset(fpu_temp, |
1844 value_reg, | 1868 value_reg, |
1845 Double::value_offset() - kHeapObjectTag); | 1869 Double::value_offset() - kHeapObjectTag); |
1846 __ StoreDToOffset(fpu_temp, temp, | 1870 __ StoreDToOffset(fpu_temp, temp, |
1847 Double::value_offset() - kHeapObjectTag); | 1871 Double::value_offset() - kHeapObjectTag); |
1848 __ b(&skip_store); | 1872 __ b(&skip_store); |
1849 } | 1873 } |
1850 | 1874 |
1851 __ Bind(&store_pointer); | 1875 __ Bind(&store_pointer); |
1852 } | 1876 } |
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2076 StubCode* stub_code = compiler->isolate()->stub_code(); | 2100 StubCode* stub_code = compiler->isolate()->stub_code(); |
2077 compiler->GenerateCall(token_pos(), | 2101 compiler->GenerateCall(token_pos(), |
2078 &stub_code->AllocateArrayLabel(), | 2102 &stub_code->AllocateArrayLabel(), |
2079 RawPcDescriptors::kOther, | 2103 RawPcDescriptors::kOther, |
2080 locs()); | 2104 locs()); |
2081 __ Bind(&done); | 2105 __ Bind(&done); |
2082 ASSERT(locs()->out(0).reg() == kResultReg); | 2106 ASSERT(locs()->out(0).reg() == kResultReg); |
2083 } | 2107 } |
2084 | 2108 |
2085 | 2109 |
2086 class BoxDoubleSlowPath : public SlowPathCode { | |
2087 public: | |
2088 explicit BoxDoubleSlowPath(Instruction* instruction) | |
2089 : instruction_(instruction) { } | |
2090 | |
2091 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | |
2092 __ Comment("BoxDoubleSlowPath"); | |
2093 __ Bind(entry_label()); | |
2094 Isolate* isolate = compiler->isolate(); | |
2095 StubCode* stub_code = isolate->stub_code(); | |
2096 const Class& double_class = compiler->double_class(); | |
2097 const Code& stub = | |
2098 Code::Handle(isolate, | |
2099 stub_code->GetAllocationStubForClass(double_class)); | |
2100 const ExternalLabel label(stub.EntryPoint()); | |
2101 | |
2102 LocationSummary* locs = instruction_->locs(); | |
2103 ASSERT(!locs->live_registers()->Contains(locs->out(0))); | |
2104 | |
2105 compiler->SaveLiveRegisters(locs); | |
2106 compiler->GenerateCall(Scanner::kNoSourcePos, // No token position. | |
2107 &label, | |
2108 RawPcDescriptors::kOther, | |
2109 locs); | |
2110 if (locs->out(0).reg() != V0) { | |
2111 __ mov(locs->out(0).reg(), V0); | |
2112 } | |
2113 compiler->RestoreLiveRegisters(locs); | |
2114 | |
2115 __ b(exit_label()); | |
2116 } | |
2117 | |
2118 private: | |
2119 Instruction* instruction_; | |
2120 }; | |
2121 | |
2122 | |
2123 LocationSummary* LoadFieldInstr::MakeLocationSummary(Isolate* isolate, | 2110 LocationSummary* LoadFieldInstr::MakeLocationSummary(Isolate* isolate, |
2124 bool opt) const { | 2111 bool opt) const { |
2125 const intptr_t kNumInputs = 1; | 2112 const intptr_t kNumInputs = 1; |
2126 const intptr_t kNumTemps = | 2113 const intptr_t kNumTemps = |
2127 (IsUnboxedLoad() && opt) ? 1 : | 2114 (IsUnboxedLoad() && opt) ? 1 : |
2128 ((IsPotentialUnboxedLoad()) ? 2 : 0); | 2115 ((IsPotentialUnboxedLoad()) ? 2 : 0); |
2129 LocationSummary* locs = new(isolate) LocationSummary( | 2116 LocationSummary* locs = new(isolate) LocationSummary( |
2130 isolate, kNumInputs, kNumTemps, | 2117 isolate, kNumInputs, kNumTemps, |
2131 (opt && !IsPotentialUnboxedLoad()) | 2118 (opt && !IsPotentialUnboxedLoad()) |
2132 ? LocationSummary::kNoCall | 2119 ? LocationSummary::kNoCall |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2187 | 2174 |
2188 // Fall through. | 2175 // Fall through. |
2189 __ b(&load_pointer); | 2176 __ b(&load_pointer); |
2190 | 2177 |
2191 if (!compiler->is_optimizing()) { | 2178 if (!compiler->is_optimizing()) { |
2192 locs()->live_registers()->Add(locs()->in(0)); | 2179 locs()->live_registers()->Add(locs()->in(0)); |
2193 } | 2180 } |
2194 | 2181 |
2195 { | 2182 { |
2196 __ Bind(&load_double); | 2183 __ Bind(&load_double); |
2197 BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this); | 2184 BoxAllocationSlowPath::Allocate( |
2198 compiler->AddSlowPathCode(slow_path); | 2185 compiler, this, compiler->double_class(), result_reg, temp); |
2199 | |
2200 __ TryAllocate(compiler->double_class(), | |
2201 slow_path->entry_label(), | |
2202 result_reg, | |
2203 temp); | |
2204 __ Bind(slow_path->exit_label()); | |
2205 __ lw(temp, FieldAddress(instance_reg, offset_in_bytes())); | 2186 __ lw(temp, FieldAddress(instance_reg, offset_in_bytes())); |
2206 __ LoadDFromOffset(value, temp, Double::value_offset() - kHeapObjectTag); | 2187 __ LoadDFromOffset(value, temp, Double::value_offset() - kHeapObjectTag); |
2207 __ StoreDToOffset(value, | 2188 __ StoreDToOffset(value, |
2208 result_reg, | 2189 result_reg, |
2209 Double::value_offset() - kHeapObjectTag); | 2190 Double::value_offset() - kHeapObjectTag); |
2210 __ b(&done); | 2191 __ b(&done); |
2211 } | 2192 } |
2212 | 2193 |
2213 __ Bind(&load_pointer); | 2194 __ Bind(&load_pointer); |
2214 } | 2195 } |
(...skipping 824 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3039 kNumTemps, | 3020 kNumTemps, |
3040 LocationSummary::kCallOnSlowPath); | 3021 LocationSummary::kCallOnSlowPath); |
3041 summary->set_in(0, Location::RequiresFpuRegister()); | 3022 summary->set_in(0, Location::RequiresFpuRegister()); |
3042 summary->set_temp(0, Location::RequiresRegister()); | 3023 summary->set_temp(0, Location::RequiresRegister()); |
3043 summary->set_out(0, Location::RequiresRegister()); | 3024 summary->set_out(0, Location::RequiresRegister()); |
3044 return summary; | 3025 return summary; |
3045 } | 3026 } |
3046 | 3027 |
3047 | 3028 |
3048 void BoxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3029 void BoxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3049 BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this); | |
3050 compiler->AddSlowPathCode(slow_path); | |
3051 | |
3052 Register out_reg = locs()->out(0).reg(); | 3030 Register out_reg = locs()->out(0).reg(); |
3053 DRegister value = locs()->in(0).fpu_reg(); | 3031 DRegister value = locs()->in(0).fpu_reg(); |
3054 | 3032 |
3055 __ TryAllocate(compiler->double_class(), | 3033 BoxAllocationSlowPath::Allocate( |
3056 slow_path->entry_label(), | 3034 compiler, this, compiler->double_class(), out_reg, locs()->temp(0).reg()); |
3057 out_reg, | |
3058 locs()->temp(0).reg()); | |
3059 __ Bind(slow_path->exit_label()); | |
3060 __ StoreDToOffset(value, out_reg, Double::value_offset() - kHeapObjectTag); | 3035 __ StoreDToOffset(value, out_reg, Double::value_offset() - kHeapObjectTag); |
3061 } | 3036 } |
3062 | 3037 |
3063 | 3038 |
3064 LocationSummary* UnboxDoubleInstr::MakeLocationSummary(Isolate* isolate, | 3039 LocationSummary* UnboxDoubleInstr::MakeLocationSummary(Isolate* isolate, |
3065 bool opt) const { | 3040 bool opt) const { |
3066 const intptr_t kNumInputs = 1; | 3041 const intptr_t kNumInputs = 1; |
3067 const intptr_t kNumTemps = 0; | 3042 const intptr_t kNumTemps = 0; |
3068 LocationSummary* summary = new(isolate) LocationSummary( | 3043 LocationSummary* summary = new(isolate) LocationSummary( |
3069 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3044 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
(...skipping 1735 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4805 compiler->GenerateCall(token_pos(), &label, stub_kind_, locs()); | 4780 compiler->GenerateCall(token_pos(), &label, stub_kind_, locs()); |
4806 #if defined(DEBUG) | 4781 #if defined(DEBUG) |
4807 __ LoadImmediate(S4, kInvalidObjectPointer); | 4782 __ LoadImmediate(S4, kInvalidObjectPointer); |
4808 __ LoadImmediate(S5, kInvalidObjectPointer); | 4783 __ LoadImmediate(S5, kInvalidObjectPointer); |
4809 #endif | 4784 #endif |
4810 } | 4785 } |
4811 | 4786 |
4812 } // namespace dart | 4787 } // namespace dart |
4813 | 4788 |
4814 #endif // defined TARGET_ARCH_MIPS | 4789 #endif // defined TARGET_ARCH_MIPS |
OLD | NEW |