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/intermediate_language.h" | 5 #include "vm/intermediate_language.h" |
6 | 6 |
7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
8 #include "vm/cpu.h" | 8 #include "vm/cpu.h" |
9 #include "vm/dart_entry.h" | 9 #include "vm/dart_entry.h" |
10 #include "vm/flow_graph_allocator.h" | 10 #include "vm/flow_graph_allocator.h" |
(...skipping 1150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1161 } | 1161 } |
1162 | 1162 |
1163 | 1163 |
1164 void Instruction::Goto(JoinEntryInstr* entry) { | 1164 void Instruction::Goto(JoinEntryInstr* entry) { |
1165 LinkTo(new GotoInstr(entry)); | 1165 LinkTo(new GotoInstr(entry)); |
1166 } | 1166 } |
1167 | 1167 |
1168 | 1168 |
1169 bool UnboxedIntConverterInstr::CanDeoptimize() const { | 1169 bool UnboxedIntConverterInstr::CanDeoptimize() const { |
1170 return (to() == kUnboxedInt32) && | 1170 return (to() == kUnboxedInt32) && |
| 1171 !is_truncating() && |
1171 !RangeUtils::Fits(value()->definition()->range(), | 1172 !RangeUtils::Fits(value()->definition()->range(), |
1172 RangeBoundary::kRangeBoundaryInt32); | 1173 RangeBoundary::kRangeBoundaryInt32); |
1173 } | 1174 } |
1174 | 1175 |
1175 | 1176 |
1176 bool UnboxInt32Instr::CanDeoptimize() const { | 1177 bool UnboxInt32Instr::CanDeoptimize() const { |
1177 const intptr_t value_cid = value()->Type()->ToCid(); | 1178 const intptr_t value_cid = value()->Type()->ToCid(); |
1178 if (value_cid == kSmiCid) { | 1179 if (value_cid == kSmiCid) { |
1179 return false; | 1180 return (kSmiBits > 32) && |
| 1181 !is_truncating() && |
| 1182 !RangeUtils::Fits(value()->definition()->range(), |
| 1183 RangeBoundary::kRangeBoundaryInt32); |
1180 } else if (value_cid == kMintCid) { | 1184 } else if (value_cid == kMintCid) { |
1181 return !RangeUtils::Fits(value()->definition()->range(), | 1185 return !is_truncating() && |
1182 RangeBoundary::kRangeBoundaryInt32); | 1186 !RangeUtils::Fits(value()->definition()->range(), |
| 1187 RangeBoundary::kRangeBoundaryInt32); |
1183 } else { | 1188 } else { |
1184 return true; | 1189 return true; |
1185 } | 1190 } |
1186 } | 1191 } |
1187 | 1192 |
1188 | 1193 |
1189 bool BinaryInt32OpInstr::CanDeoptimize() const { | 1194 bool BinaryInt32OpInstr::CanDeoptimize() const { |
1190 switch (op_kind()) { | 1195 switch (op_kind()) { |
1191 case Token::kBIT_AND: | 1196 case Token::kBIT_AND: |
1192 case Token::kBIT_OR: | 1197 case Token::kBIT_OR: |
(...skipping 543 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1736 BoxIntNInstr* box_defn = value()->definition()->AsBoxIntN(); | 1741 BoxIntNInstr* box_defn = value()->definition()->AsBoxIntN(); |
1737 if (box_defn != NULL) { | 1742 if (box_defn != NULL) { |
1738 if (box_defn->value()->definition()->representation() == representation()) { | 1743 if (box_defn->value()->definition()->representation() == representation()) { |
1739 return box_defn->value()->definition(); | 1744 return box_defn->value()->definition(); |
1740 } else { | 1745 } else { |
1741 UnboxedIntConverterInstr* converter = new UnboxedIntConverterInstr( | 1746 UnboxedIntConverterInstr* converter = new UnboxedIntConverterInstr( |
1742 box_defn->value()->definition()->representation(), | 1747 box_defn->value()->definition()->representation(), |
1743 representation(), | 1748 representation(), |
1744 box_defn->value()->CopyWithType(), | 1749 box_defn->value()->CopyWithType(), |
1745 representation() == kUnboxedInt32 ? deopt_id_ : Isolate::kNoDeoptId); | 1750 representation() == kUnboxedInt32 ? deopt_id_ : Isolate::kNoDeoptId); |
| 1751 if ((representation() == kUnboxedInt32) && is_truncating()) { |
| 1752 converter->mark_truncating(); |
| 1753 } |
1746 flow_graph->InsertBefore(this, converter, env(), FlowGraph::kValue); | 1754 flow_graph->InsertBefore(this, converter, env(), FlowGraph::kValue); |
1747 return converter; | 1755 return converter; |
1748 } | 1756 } |
1749 } | 1757 } |
1750 | 1758 |
1751 return this; | 1759 return this; |
1752 } | 1760 } |
1753 | 1761 |
1754 | 1762 |
1755 Definition* UnboxedIntConverterInstr::Canonicalize(FlowGraph* flow_graph) { | 1763 Definition* UnboxedIntConverterInstr::Canonicalize(FlowGraph* flow_graph) { |
1756 if (!HasUses()) return NULL; | 1764 if (!HasUses()) return NULL; |
1757 | 1765 |
1758 UnboxedIntConverterInstr* box_defn = | 1766 UnboxedIntConverterInstr* box_defn = |
1759 value()->definition()->AsUnboxedIntConverter(); | 1767 value()->definition()->AsUnboxedIntConverter(); |
1760 if ((box_defn != NULL) && (box_defn->representation() == from())) { | 1768 if ((box_defn != NULL) && (box_defn->representation() == from())) { |
1761 if (box_defn->from() == to()) { | 1769 if (box_defn->from() == to()) { |
1762 return box_defn->value()->definition(); | 1770 return box_defn->value()->definition(); |
1763 } | 1771 } |
1764 | 1772 |
1765 UnboxedIntConverterInstr* converter = new UnboxedIntConverterInstr( | 1773 UnboxedIntConverterInstr* converter = new UnboxedIntConverterInstr( |
1766 box_defn->from(), | 1774 box_defn->from(), |
1767 representation(), | 1775 representation(), |
1768 box_defn->value()->CopyWithType(), | 1776 box_defn->value()->CopyWithType(), |
1769 to() == kUnboxedInt32 ? deopt_id_ : NULL); | 1777 to() == kUnboxedInt32 ? deopt_id_ : NULL); |
| 1778 if ((representation() == kUnboxedInt32) && is_truncating()) { |
| 1779 converter->mark_truncating(); |
| 1780 } |
1770 flow_graph->InsertBefore(this, converter, env(), FlowGraph::kValue); | 1781 flow_graph->InsertBefore(this, converter, env(), FlowGraph::kValue); |
1771 return converter; | 1782 return converter; |
1772 } | 1783 } |
1773 | 1784 |
1774 UnboxIntegerInstr* unbox_defn = value()->definition()->AsUnboxInteger(); | 1785 UnboxIntegerInstr* unbox_defn = value()->definition()->AsUnboxInteger(); |
1775 if (unbox_defn != NULL && | 1786 if (unbox_defn != NULL && |
1776 (from() == kUnboxedMint) && | 1787 (from() == kUnboxedMint) && |
1777 (to() == kUnboxedInt32) && | 1788 (to() == kUnboxedInt32) && |
1778 unbox_defn->HasOnlyInputUse(value())) { | 1789 unbox_defn->HasOnlyInputUse(value())) { |
1779 // TODO(vegorov): there is a duplication of code between UnboxedIntCoverter | 1790 // TODO(vegorov): there is a duplication of code between UnboxedIntCoverter |
1780 // and code path that unboxes Mint into Int32. We should just schedule | 1791 // and code path that unboxes Mint into Int32. We should just schedule |
1781 // these instructions close to each other instead of fusing them. | 1792 // these instructions close to each other instead of fusing them. |
1782 Definition* replacement = | 1793 Definition* replacement = |
1783 new UnboxInt32Instr(unbox_defn->value()->CopyWithType(), deopt_id_); | 1794 new UnboxInt32Instr(unbox_defn->value()->CopyWithType(), deopt_id_); |
| 1795 if (is_truncating()) { |
| 1796 replacement->AsUnboxInt32()->mark_truncating(); |
| 1797 } |
1784 flow_graph->InsertBefore(this, | 1798 flow_graph->InsertBefore(this, |
1785 replacement, | 1799 replacement, |
1786 env(), | 1800 env(), |
1787 FlowGraph::kValue); | 1801 FlowGraph::kValue); |
1788 return replacement; | 1802 return replacement; |
1789 } | 1803 } |
1790 | 1804 |
1791 return this; | 1805 return this; |
1792 } | 1806 } |
1793 | 1807 |
1794 | 1808 |
1795 Definition* UnboxInt32Instr::Canonicalize(FlowGraph* flow_graph) { | 1809 Definition* UnboxInt32Instr::Canonicalize(FlowGraph* flow_graph) { |
1796 Definition* replacement = UnboxIntNInstr::Canonicalize(flow_graph); | 1810 Definition* replacement = UnboxIntNInstr::Canonicalize(flow_graph); |
1797 if (replacement != this) { | 1811 if (replacement != this) { |
1798 return replacement; | 1812 return replacement; |
1799 } | 1813 } |
1800 | 1814 |
1801 ConstantInstr* c = value()->definition()->AsConstant(); | 1815 ConstantInstr* c = value()->definition()->AsConstant(); |
1802 if ((c != NULL) && c->value().IsSmi()) { | 1816 if ((c != NULL) && c->value().IsSmi()) { |
| 1817 if (!is_truncating() && (kSmiBits > 32)) { |
| 1818 // Check that constant fits into 32-bit integer. |
| 1819 const int64_t value = |
| 1820 static_cast<int64_t>(Smi::Cast(c->value()).Value()); |
| 1821 if (!Utils::IsInt(32, value)) { |
| 1822 return this; |
| 1823 } |
| 1824 } |
| 1825 |
1803 UnboxedConstantInstr* uc = | 1826 UnboxedConstantInstr* uc = |
1804 new UnboxedConstantInstr(c->value(), kUnboxedInt32); | 1827 new UnboxedConstantInstr(c->value(), kUnboxedInt32); |
1805 flow_graph->InsertBefore(this, uc, NULL, FlowGraph::kValue); | 1828 flow_graph->InsertBefore(this, uc, NULL, FlowGraph::kValue); |
1806 return uc; | 1829 return uc; |
1807 } | 1830 } |
1808 | 1831 |
1809 return this; | 1832 return this; |
1810 } | 1833 } |
1811 | 1834 |
1812 | 1835 |
(...skipping 1279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3092 case Token::kTRUNCDIV: return 0; | 3115 case Token::kTRUNCDIV: return 0; |
3093 case Token::kMOD: return 1; | 3116 case Token::kMOD: return 1; |
3094 default: UNIMPLEMENTED(); return -1; | 3117 default: UNIMPLEMENTED(); return -1; |
3095 } | 3118 } |
3096 } | 3119 } |
3097 | 3120 |
3098 | 3121 |
3099 #undef __ | 3122 #undef __ |
3100 | 3123 |
3101 } // namespace dart | 3124 } // namespace dart |
OLD | NEW |