| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 #ifndef VM_INTERMEDIATE_LANGUAGE_H_ | 5 #ifndef VM_INTERMEDIATE_LANGUAGE_H_ |
| 6 #define VM_INTERMEDIATE_LANGUAGE_H_ | 6 #define VM_INTERMEDIATE_LANGUAGE_H_ |
| 7 | 7 |
| 8 #include "vm/allocation.h" | 8 #include "vm/allocation.h" |
| 9 #include "vm/ast.h" | 9 #include "vm/ast.h" |
| 10 #include "vm/growable_array.h" | 10 #include "vm/growable_array.h" |
| (...skipping 1092 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1103 // formatting. Otherwise, it prints in the format "opcode(op1, op2, op3)". | 1103 // formatting. Otherwise, it prints in the format "opcode(op1, op2, op3)". |
| 1104 virtual void PrintTo(BufferFormatter* f) const; | 1104 virtual void PrintTo(BufferFormatter* f) const; |
| 1105 virtual void PrintOperandsTo(BufferFormatter* f) const; | 1105 virtual void PrintOperandsTo(BufferFormatter* f) const; |
| 1106 | 1106 |
| 1107 // A value in the constant propagation lattice. | 1107 // A value in the constant propagation lattice. |
| 1108 // - non-constant sentinel | 1108 // - non-constant sentinel |
| 1109 // - a constant (any non-sentinel value) | 1109 // - a constant (any non-sentinel value) |
| 1110 // - unknown sentinel | 1110 // - unknown sentinel |
| 1111 Object& constant_value() const { return constant_value_; } | 1111 Object& constant_value() const { return constant_value_; } |
| 1112 | 1112 |
| 1113 enum RangeOperator { kRangeInit, kRangeWiden, kRangeNarrow }; | 1113 virtual void InferRange(); |
| 1114 | |
| 1115 virtual bool InferRange(RangeOperator op); | |
| 1116 | 1114 |
| 1117 Range* range() const { return range_; } | 1115 Range* range() const { return range_; } |
| 1118 | 1116 |
| 1119 // Definitions can be canonicalized only into definitions to ensure | 1117 // Definitions can be canonicalized only into definitions to ensure |
| 1120 // this check statically we override base Canonicalize with a Canonicalize | 1118 // this check statically we override base Canonicalize with a Canonicalize |
| 1121 // returning Definition (return type is covariant). | 1119 // returning Definition (return type is covariant). |
| 1122 virtual Definition* Canonicalize(); | 1120 virtual Definition* Canonicalize(); |
| 1123 | 1121 |
| 1124 protected: | 1122 protected: |
| 1123 friend class RangeAnalysis; |
| 1124 |
| 1125 Range* range_; | 1125 Range* range_; |
| 1126 | 1126 |
| 1127 private: | 1127 private: |
| 1128 intptr_t temp_index_; | 1128 intptr_t temp_index_; |
| 1129 intptr_t ssa_temp_index_; | 1129 intptr_t ssa_temp_index_; |
| 1130 // TODO(regis): GrowableArray<const AbstractType*> propagated_types_; | 1130 // TODO(regis): GrowableArray<const AbstractType*> propagated_types_; |
| 1131 // For now: | 1131 // For now: |
| 1132 AbstractType& propagated_type_; | 1132 AbstractType& propagated_type_; |
| 1133 intptr_t propagated_cid_; | 1133 intptr_t propagated_cid_; |
| 1134 Value* input_use_list_; | 1134 Value* input_use_list_; |
| 1135 Value* env_use_list_; | 1135 Value* env_use_list_; |
| 1136 UseKind use_kind_; | 1136 UseKind use_kind_; |
| 1137 | 1137 |
| 1138 Object& constant_value_; | 1138 Object& constant_value_; |
| 1139 | 1139 |
| 1140 DISALLOW_COPY_AND_ASSIGN(Definition); | 1140 DISALLOW_COPY_AND_ASSIGN(Definition); |
| 1141 }; | 1141 }; |
| 1142 | 1142 |
| 1143 | 1143 |
| 1144 class PhiInstr : public Definition { | 1144 class PhiInstr : public Definition { |
| 1145 public: | 1145 public: |
| 1146 explicit PhiInstr(JoinEntryInstr* block, intptr_t num_inputs) | 1146 explicit PhiInstr(JoinEntryInstr* block, intptr_t num_inputs) |
| 1147 : block_(block), | 1147 : block_(block), |
| 1148 inputs_(num_inputs), | 1148 inputs_(num_inputs), |
| 1149 is_alive_(false), | 1149 is_alive_(false), |
| 1150 representation_(kTagged), | 1150 representation_(kTagged) { |
| 1151 has_inputs_without_range_(true) { | |
| 1152 for (intptr_t i = 0; i < num_inputs; ++i) { | 1151 for (intptr_t i = 0; i < num_inputs; ++i) { |
| 1153 inputs_.Add(NULL); | 1152 inputs_.Add(NULL); |
| 1154 } | 1153 } |
| 1155 } | 1154 } |
| 1156 | 1155 |
| 1157 // Get the block entry for that instruction. | 1156 // Get the block entry for that instruction. |
| 1158 virtual BlockEntryInstr* GetBlock() const { return block(); } | 1157 virtual BlockEntryInstr* GetBlock() const { return block(); } |
| 1159 JoinEntryInstr* block() const { return block_; } | 1158 JoinEntryInstr* block() const { return block_; } |
| 1160 | 1159 |
| 1161 virtual RawAbstractType* CompileType() const; | 1160 virtual RawAbstractType* CompileType() const; |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1199 | 1198 |
| 1200 virtual intptr_t ResultCid() const { | 1199 virtual intptr_t ResultCid() const { |
| 1201 UNREACHABLE(); | 1200 UNREACHABLE(); |
| 1202 return kIllegalCid; | 1201 return kIllegalCid; |
| 1203 } | 1202 } |
| 1204 | 1203 |
| 1205 DECLARE_INSTRUCTION(Phi) | 1204 DECLARE_INSTRUCTION(Phi) |
| 1206 | 1205 |
| 1207 virtual void PrintTo(BufferFormatter* f) const; | 1206 virtual void PrintTo(BufferFormatter* f) const; |
| 1208 | 1207 |
| 1209 virtual bool InferRange(RangeOperator op); | 1208 virtual void InferRange(); |
| 1210 | 1209 |
| 1211 private: | 1210 private: |
| 1212 friend class ConstantPropagator; // Direct access to inputs_. | 1211 friend class ConstantPropagator; // Direct access to inputs_. |
| 1213 | 1212 |
| 1214 JoinEntryInstr* block_; | 1213 JoinEntryInstr* block_; |
| 1215 GrowableArray<Value*> inputs_; | 1214 GrowableArray<Value*> inputs_; |
| 1216 bool is_alive_; | 1215 bool is_alive_; |
| 1217 Representation representation_; | 1216 Representation representation_; |
| 1218 | 1217 |
| 1219 // Used to determine an interation of a range analysis after all phi inputs | |
| 1220 // were initialized to apply widening. | |
| 1221 bool has_inputs_without_range_; | |
| 1222 | |
| 1223 DISALLOW_COPY_AND_ASSIGN(PhiInstr); | 1218 DISALLOW_COPY_AND_ASSIGN(PhiInstr); |
| 1224 }; | 1219 }; |
| 1225 | 1220 |
| 1226 | 1221 |
| 1227 class ParameterInstr : public Definition { | 1222 class ParameterInstr : public Definition { |
| 1228 public: | 1223 public: |
| 1229 explicit ParameterInstr(intptr_t index, GraphEntryInstr* block) | 1224 explicit ParameterInstr(intptr_t index, GraphEntryInstr* block) |
| 1230 : index_(index), block_(block) { } | 1225 : index_(index), block_(block) { } |
| 1231 | 1226 |
| 1232 DECLARE_INSTRUCTION(Parameter) | 1227 DECLARE_INSTRUCTION(Parameter) |
| (...skipping 413 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1646 } | 1641 } |
| 1647 | 1642 |
| 1648 Definition* symbol() const { | 1643 Definition* symbol() const { |
| 1649 ASSERT(IsSymbol()); | 1644 ASSERT(IsSymbol()); |
| 1650 return reinterpret_cast<Definition*>(value_); | 1645 return reinterpret_cast<Definition*>(value_); |
| 1651 } | 1646 } |
| 1652 | 1647 |
| 1653 RangeBoundary LowerBound() const; | 1648 RangeBoundary LowerBound() const; |
| 1654 RangeBoundary UpperBound() const; | 1649 RangeBoundary UpperBound() const; |
| 1655 | 1650 |
| 1656 static RangeBoundary WidenMin(const RangeBoundary& old_min, | |
| 1657 const RangeBoundary& new_min) { | |
| 1658 if (new_min.LowerBound().value() < old_min.LowerBound().value()) { | |
| 1659 return OverflowedMinSmi(); | |
| 1660 } | |
| 1661 return old_min; | |
| 1662 } | |
| 1663 | |
| 1664 static RangeBoundary WidenMax(const RangeBoundary& old_max, | |
| 1665 const RangeBoundary& new_max) { | |
| 1666 if (new_max.UpperBound().value() > old_max.UpperBound().value()) { | |
| 1667 return OverflowedMaxSmi(); | |
| 1668 } | |
| 1669 return old_max; | |
| 1670 } | |
| 1671 | |
| 1672 static RangeBoundary NarrowMin(const RangeBoundary& old_min, | |
| 1673 const RangeBoundary& new_min) { | |
| 1674 ASSERT(old_min.IsConstant()); | |
| 1675 ASSERT(new_min.IsConstant()); | |
| 1676 return (old_min.value() == kMinusInfinity) ? new_min | |
| 1677 : Min(old_min, new_min); | |
| 1678 } | |
| 1679 | |
| 1680 static RangeBoundary NarrowMax(const RangeBoundary& old_max, | |
| 1681 const RangeBoundary& new_max) { | |
| 1682 return (old_max.value() == kPlusInfinity) ? new_max | |
| 1683 : Max(old_max, new_max); | |
| 1684 } | |
| 1685 | |
| 1686 void PrintTo(BufferFormatter* f) const; | 1651 void PrintTo(BufferFormatter* f) const; |
| 1687 | 1652 |
| 1688 static RangeBoundary Add(const RangeBoundary& a, | 1653 static RangeBoundary Add(const RangeBoundary& a, |
| 1689 const RangeBoundary& b, | 1654 const RangeBoundary& b, |
| 1690 const RangeBoundary& overflow) { | 1655 const RangeBoundary& overflow) { |
| 1691 ASSERT(a.IsConstant() && b.IsConstant()); | 1656 ASSERT(a.IsConstant() && b.IsConstant()); |
| 1692 | 1657 |
| 1693 intptr_t result = a.value() + b.value(); | 1658 intptr_t result = a.value() + b.value(); |
| 1694 if (!Smi::IsValid(result)) { | 1659 if (!Smi::IsValid(result)) { |
| 1695 return overflow; | 1660 return overflow; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1730 void PrintTo(BufferFormatter* f) const; | 1695 void PrintTo(BufferFormatter* f) const; |
| 1731 static const char* ToCString(Range* range); | 1696 static const char* ToCString(Range* range); |
| 1732 | 1697 |
| 1733 const RangeBoundary& min() { return min_; } | 1698 const RangeBoundary& min() { return min_; } |
| 1734 const RangeBoundary& max() { return max_; } | 1699 const RangeBoundary& max() { return max_; } |
| 1735 | 1700 |
| 1736 bool Equals(Range* other) { | 1701 bool Equals(Range* other) { |
| 1737 return min_.Equals(other->min_) && max_.Equals(other->max_); | 1702 return min_.Equals(other->min_) && max_.Equals(other->max_); |
| 1738 } | 1703 } |
| 1739 | 1704 |
| 1740 static bool Update(Range** range_slot, | |
| 1741 const RangeBoundary& min, | |
| 1742 const RangeBoundary& max) { | |
| 1743 if (*range_slot == NULL) { | |
| 1744 *range_slot = new Range(min, max); | |
| 1745 return true; | |
| 1746 } | |
| 1747 | |
| 1748 Range* range = *range_slot; | |
| 1749 if (range->min_.Equals(min) && range->max_.Equals(max)) { | |
| 1750 return false; | |
| 1751 } | |
| 1752 | |
| 1753 range->min_ = min; | |
| 1754 range->max_ = max; | |
| 1755 | |
| 1756 return true; | |
| 1757 } | |
| 1758 | |
| 1759 static RangeBoundary ConstantMin(Range* range) { | 1705 static RangeBoundary ConstantMin(Range* range) { |
| 1760 if (range == NULL) return RangeBoundary::MinSmi(); | 1706 if (range == NULL) return RangeBoundary::MinSmi(); |
| 1761 return range->min().LowerBound(); | 1707 return range->min().LowerBound(); |
| 1762 } | 1708 } |
| 1763 | 1709 |
| 1764 static RangeBoundary ConstantMax(Range* range) { | 1710 static RangeBoundary ConstantMax(Range* range) { |
| 1765 if (range == NULL) return RangeBoundary::MaxSmi(); | 1711 if (range == NULL) return RangeBoundary::MaxSmi(); |
| 1766 return range->max().UpperBound(); | 1712 return range->max().UpperBound(); |
| 1767 } | 1713 } |
| 1768 | 1714 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1795 virtual bool AttributesEqual(Instruction* other) const { | 1741 virtual bool AttributesEqual(Instruction* other) const { |
| 1796 UNREACHABLE(); | 1742 UNREACHABLE(); |
| 1797 return false; | 1743 return false; |
| 1798 } | 1744 } |
| 1799 | 1745 |
| 1800 virtual void PrintOperandsTo(BufferFormatter* f) const; | 1746 virtual void PrintOperandsTo(BufferFormatter* f) const; |
| 1801 | 1747 |
| 1802 Value* value() const { return inputs_[0]; } | 1748 Value* value() const { return inputs_[0]; } |
| 1803 Range* constraint() const { return constraint_; } | 1749 Range* constraint() const { return constraint_; } |
| 1804 | 1750 |
| 1805 virtual bool InferRange(RangeOperator op); | 1751 virtual void InferRange(); |
| 1806 | 1752 |
| 1807 void AddDependency(Definition* defn) { | 1753 void AddDependency(Definition* defn) { |
| 1808 Value* val = new Value(defn); | 1754 Value* val = new Value(defn); |
| 1809 val->set_use_index(1); | 1755 val->set_use_index(1); |
| 1810 val->set_instruction(this); | 1756 val->set_instruction(this); |
| 1811 val->AddToInputUseList(); | 1757 val->AddToInputUseList(); |
| 1812 set_dependency(val); | 1758 set_dependency(val); |
| 1813 } | 1759 } |
| 1814 | 1760 |
| 1815 void RemoveDependency() { | 1761 void RemoveDependency() { |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1848 | 1794 |
| 1849 virtual bool CanDeoptimize() const { return false; } | 1795 virtual bool CanDeoptimize() const { return false; } |
| 1850 | 1796 |
| 1851 virtual bool HasSideEffect() const { return false; } | 1797 virtual bool HasSideEffect() const { return false; } |
| 1852 | 1798 |
| 1853 virtual intptr_t ResultCid() const; | 1799 virtual intptr_t ResultCid() const; |
| 1854 | 1800 |
| 1855 virtual bool AttributesEqual(Instruction* other) const; | 1801 virtual bool AttributesEqual(Instruction* other) const; |
| 1856 virtual bool AffectedBySideEffect() const { return false; } | 1802 virtual bool AffectedBySideEffect() const { return false; } |
| 1857 | 1803 |
| 1858 virtual bool InferRange(RangeOperator op); | 1804 virtual void InferRange(); |
| 1859 | 1805 |
| 1860 private: | 1806 private: |
| 1861 const Object& value_; | 1807 const Object& value_; |
| 1862 | 1808 |
| 1863 DISALLOW_COPY_AND_ASSIGN(ConstantInstr); | 1809 DISALLOW_COPY_AND_ASSIGN(ConstantInstr); |
| 1864 }; | 1810 }; |
| 1865 | 1811 |
| 1866 | 1812 |
| 1867 class AssertAssignableInstr : public TemplateDefinition<3> { | 1813 class AssertAssignableInstr : public TemplateDefinition<3> { |
| 1868 public: | 1814 public: |
| (...skipping 1901 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3770 virtual bool AttributesEqual(Instruction* other) const; | 3716 virtual bool AttributesEqual(Instruction* other) const; |
| 3771 | 3717 |
| 3772 virtual intptr_t ResultCid() const; | 3718 virtual intptr_t ResultCid() const; |
| 3773 | 3719 |
| 3774 void set_overflow(bool overflow) { | 3720 void set_overflow(bool overflow) { |
| 3775 overflow_ = overflow; | 3721 overflow_ = overflow; |
| 3776 } | 3722 } |
| 3777 | 3723 |
| 3778 void PrintTo(BufferFormatter* f) const; | 3724 void PrintTo(BufferFormatter* f) const; |
| 3779 | 3725 |
| 3780 virtual bool InferRange(RangeOperator op); | 3726 virtual void InferRange(); |
| 3781 | 3727 |
| 3782 private: | 3728 private: |
| 3783 const Token::Kind op_kind_; | 3729 const Token::Kind op_kind_; |
| 3784 InstanceCallInstr* instance_call_; | 3730 InstanceCallInstr* instance_call_; |
| 3785 bool overflow_; | 3731 bool overflow_; |
| 3786 | 3732 |
| 3787 DISALLOW_COPY_AND_ASSIGN(BinarySmiOpInstr); | 3733 DISALLOW_COPY_AND_ASSIGN(BinarySmiOpInstr); |
| 3788 }; | 3734 }; |
| 3789 | 3735 |
| 3790 | 3736 |
| (...skipping 455 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4246 ForwardInstructionIterator* current_iterator_; | 4192 ForwardInstructionIterator* current_iterator_; |
| 4247 | 4193 |
| 4248 private: | 4194 private: |
| 4249 DISALLOW_COPY_AND_ASSIGN(FlowGraphVisitor); | 4195 DISALLOW_COPY_AND_ASSIGN(FlowGraphVisitor); |
| 4250 }; | 4196 }; |
| 4251 | 4197 |
| 4252 | 4198 |
| 4253 } // namespace dart | 4199 } // namespace dart |
| 4254 | 4200 |
| 4255 #endif // VM_INTERMEDIATE_LANGUAGE_H_ | 4201 #endif // VM_INTERMEDIATE_LANGUAGE_H_ |
| OLD | NEW |