OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef V8_COMPILER_OPERATOR_H_ | 5 #ifndef V8_COMPILER_OPERATOR_H_ |
6 #define V8_COMPILER_OPERATOR_H_ | 6 #define V8_COMPILER_OPERATOR_H_ |
7 | 7 |
| 8 #include <ostream> // NOLINT(readability/streams) |
| 9 |
8 #include "src/base/flags.h" | 10 #include "src/base/flags.h" |
9 #include "src/ostreams.h" | 11 #include "src/base/functional.h" |
10 #include "src/unique.h" | 12 #include "src/zone.h" |
11 | 13 |
12 namespace v8 { | 14 namespace v8 { |
13 namespace internal { | 15 namespace internal { |
14 namespace compiler { | 16 namespace compiler { |
15 | 17 |
16 // An operator represents description of the "computation" of a node in the | 18 // An operator represents description of the "computation" of a node in the |
17 // compiler IR. A computation takes values (i.e. data) as input and produces | 19 // compiler IR. A computation takes values (i.e. data) as input and produces |
18 // zero or more values as output. The side-effects of a computation must be | 20 // zero or more values as output. The side-effects of a computation must be |
19 // captured by additional control and data dependencies which are part of the | 21 // captured by additional control and data dependencies which are part of the |
20 // IR graph. | 22 // IR graph. |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
56 // the opcode is stored directly in the operator object. | 58 // the opcode is stored directly in the operator object. |
57 Opcode opcode() const { return opcode_; } | 59 Opcode opcode() const { return opcode_; } |
58 | 60 |
59 // Returns a constant string representing the mnemonic of the operator, | 61 // Returns a constant string representing the mnemonic of the operator, |
60 // without the static parameters. Useful for debugging. | 62 // without the static parameters. Useful for debugging. |
61 const char* mnemonic() const { return mnemonic_; } | 63 const char* mnemonic() const { return mnemonic_; } |
62 | 64 |
63 // Check if this operator equals another operator. Equivalent operators can | 65 // Check if this operator equals another operator. Equivalent operators can |
64 // be merged, and nodes with equivalent operators and equivalent inputs | 66 // be merged, and nodes with equivalent operators and equivalent inputs |
65 // can be merged. | 67 // can be merged. |
66 virtual bool Equals(const Operator* other) const = 0; | 68 virtual bool Equals(const Operator*) const = 0; |
67 | 69 |
68 // Compute a hashcode to speed up equivalence-set checking. | 70 // Compute a hashcode to speed up equivalence-set checking. |
69 // Equal operators should always have equal hashcodes, and unequal operators | 71 // Equal operators should always have equal hashcodes, and unequal operators |
70 // should have unequal hashcodes with high probability. | 72 // should have unequal hashcodes with high probability. |
71 virtual int HashCode() const = 0; | 73 virtual size_t HashCode() const = 0; |
72 | 74 |
73 // Check whether this operator has the given property. | 75 // Check whether this operator has the given property. |
74 bool HasProperty(Property property) const { | 76 bool HasProperty(Property property) const { |
75 return (properties() & property) == property; | 77 return (properties() & property) == property; |
76 } | 78 } |
77 | 79 |
78 // Number of data inputs to the operator, for verifying graph structure. | 80 // Number of data inputs to the operator, for verifying graph structure. |
79 virtual int InputCount() const = 0; | 81 virtual int InputCount() const = 0; |
80 | 82 |
81 // Number of data outputs from the operator, for verifying graph structure. | 83 // Number of data outputs from the operator, for verifying graph structure. |
82 virtual int OutputCount() const = 0; | 84 virtual int OutputCount() const = 0; |
83 | 85 |
84 Properties properties() const { return properties_; } | 86 Properties properties() const { return properties_; } |
85 | 87 |
86 // TODO(titzer): API for input and output types, for typechecking graph. | 88 // TODO(titzer): API for input and output types, for typechecking graph. |
87 protected: | 89 protected: |
88 // Print the full operator into the given stream, including any | 90 // Print the full operator into the given stream, including any |
89 // static parameters. Useful for debugging and visualizing the IR. | 91 // static parameters. Useful for debugging and visualizing the IR. |
90 virtual std::ostream& PrintTo(std::ostream& os) const = 0; // NOLINT | 92 virtual void PrintTo(std::ostream& os) const = 0; // NOLINT |
91 friend std::ostream& operator<<(std::ostream& os, const Operator& op); | 93 friend std::ostream& operator<<(std::ostream& os, const Operator& op); |
92 | 94 |
93 private: | 95 private: |
94 Opcode opcode_; | 96 Opcode opcode_; |
95 Properties properties_; | 97 Properties properties_; |
96 const char* mnemonic_; | 98 const char* mnemonic_; |
97 | 99 |
98 DISALLOW_COPY_AND_ASSIGN(Operator); | 100 DISALLOW_COPY_AND_ASSIGN(Operator); |
99 }; | 101 }; |
100 | 102 |
101 DEFINE_OPERATORS_FOR_FLAGS(Operator::Properties) | 103 DEFINE_OPERATORS_FOR_FLAGS(Operator::Properties) |
102 | 104 |
103 std::ostream& operator<<(std::ostream& os, const Operator& op); | 105 std::ostream& operator<<(std::ostream& os, const Operator& op); |
104 | 106 |
| 107 |
105 // An implementation of Operator that has no static parameters. Such operators | 108 // An implementation of Operator that has no static parameters. Such operators |
106 // have just a name, an opcode, and a fixed number of inputs and outputs. | 109 // have just a name, an opcode, and a fixed number of inputs and outputs. |
107 // They can represented by singletons and shared globally. | 110 // They can represented by singletons and shared globally. |
108 class SimpleOperator : public Operator { | 111 class SimpleOperator : public Operator { |
109 public: | 112 public: |
110 SimpleOperator(Opcode opcode, Properties properties, int input_count, | 113 SimpleOperator(Opcode opcode, Properties properties, size_t input_count, |
111 int output_count, const char* mnemonic); | 114 size_t output_count, const char* mnemonic); |
112 ~SimpleOperator(); | 115 ~SimpleOperator(); |
113 | 116 |
114 virtual bool Equals(const Operator* that) const FINAL { | 117 virtual bool Equals(const Operator* that) const FINAL; |
115 return opcode() == that->opcode(); | 118 virtual size_t HashCode() const FINAL; |
116 } | 119 virtual int InputCount() const FINAL; |
117 virtual int HashCode() const FINAL { return opcode(); } | 120 virtual int OutputCount() const FINAL; |
118 virtual int InputCount() const FINAL { return input_count_; } | |
119 virtual int OutputCount() const FINAL { return output_count_; } | |
120 | 121 |
121 private: | 122 private: |
122 virtual std::ostream& PrintTo(std::ostream& os) const FINAL { // NOLINT | 123 virtual void PrintTo(std::ostream& os) const FINAL; |
123 return os << mnemonic(); | |
124 } | |
125 | 124 |
126 int input_count_; | 125 uint8_t input_count_; |
127 int output_count_; | 126 uint8_t output_count_; |
128 | 127 |
129 DISALLOW_COPY_AND_ASSIGN(SimpleOperator); | 128 DISALLOW_COPY_AND_ASSIGN(SimpleOperator); |
130 }; | 129 }; |
131 | 130 |
132 // Template specialization implements a kind of type class for dealing with the | |
133 // static parameters of Operator1 automatically. | |
134 template <typename T> | |
135 struct StaticParameterTraits { | |
136 static std::ostream& PrintTo(std::ostream& os, T val) { // NOLINT | |
137 return os << "??"; | |
138 } | |
139 static int HashCode(T a) { return 0; } | |
140 static bool Equals(T a, T b) { | |
141 return false; // Not every T has a ==. By default, be conservative. | |
142 } | |
143 }; | |
144 | |
145 // Specialization for static parameters of type {int}. | |
146 template <> | |
147 struct StaticParameterTraits<int> { | |
148 static std::ostream& PrintTo(std::ostream& os, int val) { // NOLINT | |
149 return os << val; | |
150 } | |
151 static int HashCode(int a) { return a; } | |
152 static bool Equals(int a, int b) { return a == b; } | |
153 }; | |
154 | |
155 // Specialization for static parameters of type {double}. | |
156 template <> | |
157 struct StaticParameterTraits<double> { | |
158 static std::ostream& PrintTo(std::ostream& os, double val) { // NOLINT | |
159 return os << val; | |
160 } | |
161 static int HashCode(double a) { | |
162 return static_cast<int>(bit_cast<int64_t>(a)); | |
163 } | |
164 static bool Equals(double a, double b) { | |
165 return bit_cast<int64_t>(a) == bit_cast<int64_t>(b); | |
166 } | |
167 }; | |
168 | |
169 // Specialization for static parameters of type {Unique<Object>}. | |
170 template <> | |
171 struct StaticParameterTraits<Unique<Object> > { | |
172 static std::ostream& PrintTo(std::ostream& os, | |
173 Unique<Object> val) { // NOLINT | |
174 return os << Brief(*val.handle()); | |
175 } | |
176 static int HashCode(Unique<Object> a) { | |
177 return static_cast<int>(a.Hashcode()); | |
178 } | |
179 static bool Equals(Unique<Object> a, Unique<Object> b) { return a == b; } | |
180 }; | |
181 | |
182 // Specialization for static parameters of type {Unique<Name>}. | |
183 template <> | |
184 struct StaticParameterTraits<Unique<Name> > { | |
185 static std::ostream& PrintTo(std::ostream& os, Unique<Name> val) { // NOLINT | |
186 return os << Brief(*val.handle()); | |
187 } | |
188 static int HashCode(Unique<Name> a) { return static_cast<int>(a.Hashcode()); } | |
189 static bool Equals(Unique<Name> a, Unique<Name> b) { return a == b; } | |
190 }; | |
191 | |
192 #if DEBUG | |
193 // Specialization for static parameters of type {Handle<Object>} to prevent any | |
194 // direct usage of Handles in constants. | |
195 template <> | |
196 struct StaticParameterTraits<Handle<Object> > { | |
197 static std::ostream& PrintTo(std::ostream& os, | |
198 Handle<Object> val) { // NOLINT | |
199 UNREACHABLE(); // Should use Unique<Object> instead | |
200 return os; | |
201 } | |
202 static int HashCode(Handle<Object> a) { | |
203 UNREACHABLE(); // Should use Unique<Object> instead | |
204 return 0; | |
205 } | |
206 static bool Equals(Handle<Object> a, Handle<Object> b) { | |
207 UNREACHABLE(); // Should use Unique<Object> instead | |
208 return false; | |
209 } | |
210 }; | |
211 #endif | |
212 | 131 |
213 // A templatized implementation of Operator that has one static parameter of | 132 // A templatized implementation of Operator that has one static parameter of |
214 // type {T}. If a specialization of StaticParameterTraits<{T}> exists, then | 133 // type {T}. |
215 // operators of this kind can automatically be hashed, compared, and printed. | 134 template <typename T, typename Pred = std::equal_to<T>, |
216 template <typename T> | 135 typename Hash = base::hash<T>> |
217 class Operator1 : public Operator { | 136 class Operator1 : public Operator { |
218 public: | 137 public: |
219 Operator1(Opcode opcode, Properties properties, int input_count, | 138 Operator1(Opcode opcode, Properties properties, int input_count, |
220 int output_count, const char* mnemonic, T parameter) | 139 int output_count, const char* mnemonic, T parameter, |
| 140 Pred const& pred = Pred(), Hash const& hash = Hash()) |
221 : Operator(opcode, properties, mnemonic), | 141 : Operator(opcode, properties, mnemonic), |
222 input_count_(input_count), | 142 input_count_(input_count), |
223 output_count_(output_count), | 143 output_count_(output_count), |
224 parameter_(parameter) {} | 144 parameter_(parameter), |
| 145 pred_(pred), |
| 146 hash_(hash) {} |
225 | 147 |
226 const T& parameter() const { return parameter_; } | 148 T const& parameter() const { return parameter_; } |
227 | 149 |
228 virtual bool Equals(const Operator* other) const OVERRIDE { | 150 virtual bool Equals(const Operator* other) const FINAL { |
229 if (opcode() != other->opcode()) return false; | 151 if (opcode() != other->opcode()) return false; |
230 const Operator1<T>* that = static_cast<const Operator1<T>*>(other); | 152 const Operator1<T>* that = static_cast<const Operator1<T>*>(other); |
231 return StaticParameterTraits<T>::Equals(this->parameter_, that->parameter_); | 153 return this->pred_(this->parameter(), that->parameter()); |
232 } | 154 } |
233 virtual int HashCode() const OVERRIDE { | 155 virtual size_t HashCode() const FINAL { |
234 return opcode() + 33 * StaticParameterTraits<T>::HashCode(this->parameter_); | 156 return base::hash_combine(this->opcode(), this->hash_(this->parameter())); |
235 } | 157 } |
236 virtual int InputCount() const OVERRIDE { return input_count_; } | 158 virtual int InputCount() const FINAL { return input_count_; } |
237 virtual int OutputCount() const OVERRIDE { return output_count_; } | 159 virtual int OutputCount() const FINAL { return output_count_; } |
238 virtual std::ostream& PrintParameter(std::ostream& os) const { // NOLINT | 160 virtual void PrintParameter(std::ostream& os) const { |
239 return StaticParameterTraits<T>::PrintTo(os << "[", parameter_) << "]"; | 161 os << "[" << this->parameter() << "]"; |
240 } | 162 } |
241 | 163 |
242 protected: | 164 protected: |
243 virtual std::ostream& PrintTo(std::ostream& os) const FINAL { // NOLINT | 165 virtual void PrintTo(std::ostream& os) const FINAL { |
244 return PrintParameter(os << mnemonic()); | 166 os << mnemonic(); |
| 167 PrintParameter(os); |
245 } | 168 } |
246 | 169 |
247 private: | 170 private: |
248 int input_count_; | 171 int const input_count_; |
249 int output_count_; | 172 int const output_count_; |
250 T parameter_; | 173 T const parameter_; |
| 174 Pred const pred_; |
| 175 Hash const hash_; |
251 }; | 176 }; |
252 | 177 |
253 | 178 |
254 // Helper to extract parameters from Operator1<*> operator. | 179 // Helper to extract parameters from Operator1<*> operator. |
255 template <typename T> | 180 template <typename T> |
256 static inline const T& OpParameter(const Operator* op) { | 181 inline T const& OpParameter(const Operator* op) { |
257 return reinterpret_cast<const Operator1<T>*>(op)->parameter(); | 182 return static_cast<const Operator1<T>*>(op)->parameter(); |
258 } | 183 } |
259 | 184 |
260 } // namespace compiler | 185 } // namespace compiler |
261 } // namespace internal | 186 } // namespace internal |
262 } // namespace v8 | 187 } // namespace v8 |
263 | 188 |
264 #endif // V8_COMPILER_OPERATOR_H_ | 189 #endif // V8_COMPILER_OPERATOR_H_ |
OLD | NEW |