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 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
94 M(AllocateContext, AllocateContextComp) \ | 94 M(AllocateContext, AllocateContextComp) \ |
95 M(ChainContext, ChainContextComp) \ | 95 M(ChainContext, ChainContextComp) \ |
96 M(CloneContext, CloneContextComp) \ | 96 M(CloneContext, CloneContextComp) \ |
97 M(CatchEntry, CatchEntryComp) \ | 97 M(CatchEntry, CatchEntryComp) \ |
98 M(BinaryOp, BinaryOpComp) \ | 98 M(BinaryOp, BinaryOpComp) \ |
99 M(DoubleBinaryOp, DoubleBinaryOpComp) \ | 99 M(DoubleBinaryOp, DoubleBinaryOpComp) \ |
100 M(UnarySmiOp, UnarySmiOpComp) \ | 100 M(UnarySmiOp, UnarySmiOpComp) \ |
101 M(NumberNegate, NumberNegateComp) \ | 101 M(NumberNegate, NumberNegateComp) \ |
102 M(CheckStackOverflow, CheckStackOverflowComp) \ | 102 M(CheckStackOverflow, CheckStackOverflowComp) \ |
103 M(DoubleToDouble, DoubleToDoubleComp) \ | 103 M(DoubleToDouble, DoubleToDoubleComp) \ |
104 M(SmiToDouble, SmiToDoubleComp) | 104 M(SmiToDouble, SmiToDoubleComp) \ |
| 105 M(CheckClass, CheckClassComp) |
105 | 106 |
106 | 107 |
107 #define FORWARD_DECLARATION(ShortName, ClassName) class ClassName; | 108 #define FORWARD_DECLARATION(ShortName, ClassName) class ClassName; |
108 FOR_EACH_COMPUTATION(FORWARD_DECLARATION) | 109 FOR_EACH_COMPUTATION(FORWARD_DECLARATION) |
109 #undef FORWARD_DECLARATION | 110 #undef FORWARD_DECLARATION |
110 | 111 |
111 // Forward declarations. | 112 // Forward declarations. |
112 class BindInstr; | 113 class BindInstr; |
113 class BranchInstr; | 114 class BranchInstr; |
114 class BufferFormatter; | 115 class BufferFormatter; |
115 class ComparisonComp; | 116 class ComparisonComp; |
116 class Definition; | 117 class Definition; |
117 class Instruction; | 118 class Instruction; |
118 class PushArgumentInstr; | 119 class PushArgumentInstr; |
119 class Value; | 120 class Value; |
120 | 121 |
121 class Computation : public ZoneAllocated { | 122 class Computation : public ZoneAllocated { |
122 public: | 123 public: |
123 Computation() : deopt_id_(Isolate::kNoDeoptId), ic_data_(NULL), locs_(NULL) { | 124 Computation() : deopt_id_(Isolate::kNoDeoptId), ic_data_(NULL), locs_(NULL) { |
124 Isolate* isolate = Isolate::Current(); | 125 Isolate* isolate = Isolate::Current(); |
125 deopt_id_ = isolate->GetNextDeoptId(); | 126 deopt_id_ = isolate->GetNextDeoptId(); |
126 ic_data_ = isolate->GetICDataForDeoptId(deopt_id_); | 127 ic_data_ = isolate->GetICDataForDeoptId(deopt_id_); |
127 } | 128 } |
128 | 129 |
129 // Unique id used for deoptimization. | 130 // Unique id used for deoptimization. |
130 intptr_t deopt_id() const { return deopt_id_; } | 131 intptr_t deopt_id() const { return deopt_id_; } |
131 | 132 |
132 ICData* ic_data() const { return ic_data_; } | 133 const ICData* ic_data() const { return ic_data_; } |
133 void set_ic_data(ICData* value) { ic_data_ = value; } | 134 void set_ic_data(const ICData* value) { ic_data_ = value; } |
134 bool HasICData() const { | 135 bool HasICData() const { |
135 return (ic_data() != NULL) && !ic_data()->IsNull(); | 136 return (ic_data() != NULL) && !ic_data()->IsNull(); |
136 } | 137 } |
137 | 138 |
138 // Visiting support. | 139 // Visiting support. |
139 virtual void Accept(FlowGraphVisitor* visitor, BindInstr* instr) = 0; | 140 virtual void Accept(FlowGraphVisitor* visitor, BindInstr* instr) = 0; |
140 | 141 |
141 virtual intptr_t InputCount() const = 0; | 142 virtual intptr_t InputCount() const = 0; |
142 virtual Value* InputAt(intptr_t i) const = 0; | 143 virtual Value* InputAt(intptr_t i) const = 0; |
143 virtual void SetInputAt(intptr_t i, Value* value) = 0; | 144 virtual void SetInputAt(intptr_t i, Value* value) = 0; |
144 | 145 |
145 // Call computations override this function and return the | 146 // Call computations override this function and return the |
146 // number of pushed arguments. | 147 // number of pushed arguments. |
147 virtual intptr_t ArgumentCount() const = 0; | 148 virtual intptr_t ArgumentCount() const = 0; |
148 | 149 |
149 // Returns true, if this computation can deoptimize. | 150 // Returns true, if this computation can deoptimize. |
150 virtual bool CanDeoptimize() const = 0; | 151 virtual bool CanDeoptimize() const = 0; |
151 | 152 |
152 // Optimize this computation. Returns a replacement for the instruction | 153 // Optimize this computation. Returns a replacement for the instruction |
153 // that wraps this computation or NULL if nothing to replace. | 154 // that wraps this computation or NULL if nothing to replace. |
154 virtual Definition* TryReplace(BindInstr* instr) { return NULL; } | 155 virtual Definition* TryReplace(BindInstr* instr) { return NULL; } |
155 | 156 |
| 157 // Compares two computations. Returns true, if: |
| 158 // 1. They are of the same kind. |
| 159 // 2. All input operands match. |
| 160 // 3. All other attributes match. |
| 161 bool Equals(Computation* other) const; |
| 162 |
| 163 // Returns a hash code for use with hash maps. |
| 164 virtual intptr_t Hashcode() const; |
| 165 |
| 166 // Compare attributes of an computation (except input operands and kind). |
| 167 // TODO(fschneider): Make this abstract and implement for all computations. |
| 168 virtual bool AttributesEqual(Computation* other) const { return true; } |
| 169 |
| 170 // Returns true if the instruction may have side effects. |
| 171 // TODO(fschneider): Make this abstract and implement for all computations |
| 172 // instead of returning the safe default (true). |
| 173 virtual bool HasSideEffect() const { return true; } |
| 174 |
156 // Compile time type of the computation, which typically depends on the | 175 // Compile time type of the computation, which typically depends on the |
157 // compile time types (and possibly propagated types) of its inputs. | 176 // compile time types (and possibly propagated types) of its inputs. |
158 virtual RawAbstractType* CompileType() const = 0; | 177 virtual RawAbstractType* CompileType() const = 0; |
159 virtual intptr_t ResultCid() const { return kDynamicCid; } | 178 virtual intptr_t ResultCid() const { return kDynamicCid; } |
160 | 179 |
161 // Mutate assigned_vars to add the local variable index for all | 180 // Mutate assigned_vars to add the local variable index for all |
162 // frame-allocated locals assigned to by the computation. | 181 // frame-allocated locals assigned to by the computation. |
163 virtual void RecordAssignedVars(BitVector* assigned_vars, | 182 virtual void RecordAssignedVars(BitVector* assigned_vars, |
164 intptr_t fixed_parameter_count); | 183 intptr_t fixed_parameter_count); |
165 | 184 |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
207 // Declare predicate for each computation. | 226 // Declare predicate for each computation. |
208 #define DECLARE_PREDICATE(ShortName, ClassName) \ | 227 #define DECLARE_PREDICATE(ShortName, ClassName) \ |
209 inline bool Is##ShortName() const; \ | 228 inline bool Is##ShortName() const; \ |
210 inline const ClassName* As##ShortName() const; \ | 229 inline const ClassName* As##ShortName() const; \ |
211 inline ClassName* As##ShortName(); | 230 inline ClassName* As##ShortName(); |
212 FOR_EACH_COMPUTATION(DECLARE_PREDICATE) | 231 FOR_EACH_COMPUTATION(DECLARE_PREDICATE) |
213 #undef DECLARE_PREDICATE | 232 #undef DECLARE_PREDICATE |
214 | 233 |
215 private: | 234 private: |
216 intptr_t deopt_id_; | 235 intptr_t deopt_id_; |
217 ICData* ic_data_; | 236 const ICData* ic_data_; |
218 LocationSummary* locs_; | 237 LocationSummary* locs_; |
219 | 238 |
220 DISALLOW_COPY_AND_ASSIGN(Computation); | 239 DISALLOW_COPY_AND_ASSIGN(Computation); |
221 }; | 240 }; |
222 | 241 |
223 | 242 |
224 // An embedded container with N elements of type T. Used (with partial | 243 // An embedded container with N elements of type T. Used (with partial |
225 // specialization for N=0) because embedded arrays cannot have size 0. | 244 // specialization for N=0) because embedded arrays cannot have size 0. |
226 template<typename T, intptr_t N> | 245 template<typename T, intptr_t N> |
227 class EmbeddedArray { | 246 class EmbeddedArray { |
(...skipping 701 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
929 const intptr_t try_index_; | 948 const intptr_t try_index_; |
930 | 949 |
931 DISALLOW_COPY_AND_ASSIGN(NativeCallComp); | 950 DISALLOW_COPY_AND_ASSIGN(NativeCallComp); |
932 }; | 951 }; |
933 | 952 |
934 | 953 |
935 class LoadInstanceFieldComp : public TemplateComputation<1> { | 954 class LoadInstanceFieldComp : public TemplateComputation<1> { |
936 public: | 955 public: |
937 LoadInstanceFieldComp(const Field& field, | 956 LoadInstanceFieldComp(const Field& field, |
938 Value* instance, | 957 Value* instance, |
939 InstanceCallComp* original) // Maybe NULL. | 958 InstanceCallComp* original, // Maybe NULL. |
940 : field_(field), original_(original) { | 959 bool can_deoptimize) |
| 960 : field_(field), original_(original), can_deoptimize_(can_deoptimize) { |
941 ASSERT(instance != NULL); | 961 ASSERT(instance != NULL); |
942 inputs_[0] = instance; | 962 inputs_[0] = instance; |
943 } | 963 } |
944 | 964 |
945 DECLARE_COMPUTATION(LoadInstanceField) | 965 DECLARE_COMPUTATION(LoadInstanceField) |
946 | 966 |
947 const Field& field() const { return field_; } | 967 const Field& field() const { return field_; } |
948 Value* instance() const { return inputs_[0]; } | 968 Value* instance() const { return inputs_[0]; } |
949 const InstanceCallComp* original() const { return original_; } | 969 const InstanceCallComp* original() const { return original_; } |
950 | 970 |
951 virtual void PrintOperandsTo(BufferFormatter* f) const; | 971 virtual void PrintOperandsTo(BufferFormatter* f) const; |
952 | 972 |
953 virtual bool CanDeoptimize() const { return true; } | 973 virtual bool CanDeoptimize() const { return can_deoptimize_; } |
954 | 974 |
955 private: | 975 private: |
956 const Field& field_; | 976 const Field& field_; |
957 const InstanceCallComp* original_; // For optimizations. | 977 const InstanceCallComp* original_; // For optimizations. |
| 978 const bool can_deoptimize_; |
958 | 979 |
959 DISALLOW_COPY_AND_ASSIGN(LoadInstanceFieldComp); | 980 DISALLOW_COPY_AND_ASSIGN(LoadInstanceFieldComp); |
960 }; | 981 }; |
961 | 982 |
962 | 983 |
963 class StoreInstanceFieldComp : public TemplateComputation<2> { | 984 class StoreInstanceFieldComp : public TemplateComputation<2> { |
964 public: | 985 public: |
965 StoreInstanceFieldComp(const Field& field, | 986 StoreInstanceFieldComp(const Field& field, |
966 Value* instance, | 987 Value* instance, |
967 Value* value, | 988 Value* value, |
(...skipping 798 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1766 virtual bool CanDeoptimize() const { return true; } | 1787 virtual bool CanDeoptimize() const { return true; } |
1767 virtual intptr_t ResultCid() const { return kDoubleCid; } | 1788 virtual intptr_t ResultCid() const { return kDoubleCid; } |
1768 | 1789 |
1769 private: | 1790 private: |
1770 InstanceCallComp* instance_call_; | 1791 InstanceCallComp* instance_call_; |
1771 | 1792 |
1772 DISALLOW_COPY_AND_ASSIGN(SmiToDoubleComp); | 1793 DISALLOW_COPY_AND_ASSIGN(SmiToDoubleComp); |
1773 }; | 1794 }; |
1774 | 1795 |
1775 | 1796 |
| 1797 class CheckClassComp : public TemplateComputation<1> { |
| 1798 public: |
| 1799 CheckClassComp(Value* value, InstanceCallComp* original) |
| 1800 : original_(original) { |
| 1801 ASSERT(value != NULL); |
| 1802 inputs_[0] = value; |
| 1803 } |
| 1804 |
| 1805 DECLARE_COMPUTATION(CheckClass) |
| 1806 |
| 1807 virtual bool CanDeoptimize() const { return true; } |
| 1808 |
| 1809 virtual bool AttributesEqual(Computation* other) const; |
| 1810 |
| 1811 virtual bool HasSideEffect() const { return false; } |
| 1812 |
| 1813 Value* value() const { return inputs_[0]; } |
| 1814 |
| 1815 intptr_t deopt_id() const { return original_->deopt_id(); } |
| 1816 intptr_t try_index() const { return original_->try_index(); } |
| 1817 |
| 1818 private: |
| 1819 InstanceCallComp* original_; |
| 1820 |
| 1821 DISALLOW_COPY_AND_ASSIGN(CheckClassComp); |
| 1822 }; |
| 1823 |
| 1824 |
1776 #undef DECLARE_COMPUTATION | 1825 #undef DECLARE_COMPUTATION |
1777 | 1826 |
1778 | 1827 |
1779 // Implementation of type testers and cast functins. | 1828 // Implementation of type testers and cast functins. |
1780 #define DEFINE_PREDICATE(ShortName, ClassName) \ | 1829 #define DEFINE_PREDICATE(ShortName, ClassName) \ |
1781 bool Computation::Is##ShortName() const { \ | 1830 bool Computation::Is##ShortName() const { \ |
1782 return computation_kind() == k##ShortName; \ | 1831 return computation_kind() == k##ShortName; \ |
1783 } \ | 1832 } \ |
1784 const ClassName* Computation::As##ShortName() const { \ | 1833 const ClassName* Computation::As##ShortName() const { \ |
1785 if (!Is##ShortName()) return NULL; \ | 1834 if (!Is##ShortName()) return NULL; \ |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1875 ASSERT(instr == NULL || !instr->IsBlockEntry()); | 1924 ASSERT(instr == NULL || !instr->IsBlockEntry()); |
1876 // TODO(fschneider): Also add Throw and ReThrow to the list of instructions | 1925 // TODO(fschneider): Also add Throw and ReThrow to the list of instructions |
1877 // that do not have a successor. Currently, the graph builder will continue | 1926 // that do not have a successor. Currently, the graph builder will continue |
1878 // to append instruction in case of a Throw inside an expression. This | 1927 // to append instruction in case of a Throw inside an expression. This |
1879 // condition should be handled in the graph builder | 1928 // condition should be handled in the graph builder |
1880 next_ = instr; | 1929 next_ = instr; |
1881 } | 1930 } |
1882 | 1931 |
1883 // Removed this instruction from the graph. | 1932 // Removed this instruction from the graph. |
1884 Instruction* RemoveFromGraph(bool return_previous = true); | 1933 Instruction* RemoveFromGraph(bool return_previous = true); |
| 1934 |
1885 // Remove value uses within this instruction and its inputs. | 1935 // Remove value uses within this instruction and its inputs. |
1886 virtual void RemoveInputUses() = 0; | 1936 virtual void RemoveInputUses() = 0; |
1887 | 1937 |
1888 // Normal instructions can have 0 (inside a block) or 1 (last instruction in | 1938 // Normal instructions can have 0 (inside a block) or 1 (last instruction in |
1889 // a block) successors. Branch instruction with >1 successors override this | 1939 // a block) successors. Branch instruction with >1 successors override this |
1890 // function. | 1940 // function. |
1891 virtual intptr_t SuccessorCount() const; | 1941 virtual intptr_t SuccessorCount() const; |
1892 virtual BlockEntryInstr* SuccessorAt(intptr_t index) const; | 1942 virtual BlockEntryInstr* SuccessorAt(intptr_t index) const; |
1893 | 1943 |
1894 void Goto(JoinEntryInstr* entry); | 1944 void Goto(JoinEntryInstr* entry); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1948 | 1998 |
1949 Environment* env() const { return env_; } | 1999 Environment* env() const { return env_; } |
1950 void set_env(Environment* env) { env_ = env; } | 2000 void set_env(Environment* env) { env_ = env; } |
1951 | 2001 |
1952 intptr_t lifetime_position() const { return lifetime_position_; } | 2002 intptr_t lifetime_position() const { return lifetime_position_; } |
1953 void set_lifetime_position(intptr_t pos) { | 2003 void set_lifetime_position(intptr_t pos) { |
1954 lifetime_position_ = pos; | 2004 lifetime_position_ = pos; |
1955 } | 2005 } |
1956 | 2006 |
1957 private: | 2007 private: |
| 2008 friend class BindInstr; // Needed for BindInstr::InsertBefore. |
| 2009 |
1958 intptr_t lifetime_position_; // Position used by register allocator. | 2010 intptr_t lifetime_position_; // Position used by register allocator. |
1959 Instruction* previous_; | 2011 Instruction* previous_; |
1960 Instruction* next_; | 2012 Instruction* next_; |
1961 Environment* env_; | 2013 Environment* env_; |
1962 DISALLOW_COPY_AND_ASSIGN(Instruction); | 2014 DISALLOW_COPY_AND_ASSIGN(Instruction); |
1963 }; | 2015 }; |
1964 | 2016 |
1965 | 2017 |
1966 template<intptr_t N> | 2018 template<intptr_t N> |
1967 class TemplateInstruction: public Instruction { | 2019 class TemplateInstruction: public Instruction { |
(...skipping 528 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2496 Computation* computation() const { return computation_; } | 2548 Computation* computation() const { return computation_; } |
2497 void set_computation(Computation* value) { computation_ = value; } | 2549 void set_computation(Computation* value) { computation_ = value; } |
2498 bool is_used() const { return is_used_; } | 2550 bool is_used() const { return is_used_; } |
2499 | 2551 |
2500 virtual RawAbstractType* CompileType() const; | 2552 virtual RawAbstractType* CompileType() const; |
2501 virtual intptr_t GetPropagatedCid(); | 2553 virtual intptr_t GetPropagatedCid(); |
2502 | 2554 |
2503 virtual void RecordAssignedVars(BitVector* assigned_vars, | 2555 virtual void RecordAssignedVars(BitVector* assigned_vars, |
2504 intptr_t fixed_parameter_count); | 2556 intptr_t fixed_parameter_count); |
2505 | 2557 |
| 2558 intptr_t Hashcode() const { return computation()->Hashcode(); } |
| 2559 |
| 2560 bool Equals(BindInstr* other) const { |
| 2561 return computation()->Equals(other->computation()); |
| 2562 } |
| 2563 |
2506 virtual LocationSummary* locs() { | 2564 virtual LocationSummary* locs() { |
2507 return computation()->locs(); | 2565 return computation()->locs(); |
2508 } | 2566 } |
2509 | 2567 |
2510 virtual void EmitNativeCode(FlowGraphCompiler* compiler); | 2568 virtual void EmitNativeCode(FlowGraphCompiler* compiler); |
2511 | 2569 |
2512 virtual void RemoveInputUses() { computation()->RemoveInputUses(); } | 2570 virtual void RemoveInputUses() { computation()->RemoveInputUses(); } |
2513 | 2571 |
| 2572 // Insert this instruction before 'next'. |
| 2573 void InsertBefore(BindInstr* next); |
| 2574 |
2514 private: | 2575 private: |
2515 Computation* computation_; | 2576 Computation* computation_; |
2516 const bool is_used_; | 2577 const bool is_used_; |
2517 | 2578 |
2518 DISALLOW_COPY_AND_ASSIGN(BindInstr); | 2579 DISALLOW_COPY_AND_ASSIGN(BindInstr); |
2519 }; | 2580 }; |
2520 | 2581 |
2521 | 2582 |
2522 class PhiInstr : public Definition { | 2583 class PhiInstr : public Definition { |
2523 public: | 2584 public: |
(...skipping 440 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2964 ForwardInstructionIterator* current_iterator_; | 3025 ForwardInstructionIterator* current_iterator_; |
2965 | 3026 |
2966 private: | 3027 private: |
2967 DISALLOW_COPY_AND_ASSIGN(FlowGraphVisitor); | 3028 DISALLOW_COPY_AND_ASSIGN(FlowGraphVisitor); |
2968 }; | 3029 }; |
2969 | 3030 |
2970 | 3031 |
2971 } // namespace dart | 3032 } // namespace dart |
2972 | 3033 |
2973 #endif // VM_INTERMEDIATE_LANGUAGE_H_ | 3034 #endif // VM_INTERMEDIATE_LANGUAGE_H_ |
OLD | NEW |