OLD | NEW |
---|---|
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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 #include "src/compiler/common-operator.h" | 5 #include "src/compiler/common-operator.h" |
6 | 6 |
7 #include "src/assembler.h" | 7 #include "src/assembler.h" |
8 #include "src/base/lazy-instance.h" | 8 #include "src/base/lazy-instance.h" |
9 #include "src/compiler/linkage.h" | 9 #include "src/compiler/linkage.h" |
10 #include "src/unique.h" | 10 #include "src/unique.h" |
11 #include "src/zone.h" | 11 #include "src/zone.h" |
12 | 12 |
13 namespace v8 { | 13 namespace v8 { |
14 namespace internal { | 14 namespace internal { |
15 namespace compiler { | 15 namespace compiler { |
16 | 16 |
17 namespace { | |
18 | |
19 // TODO(turbofan): Use size_t instead of int here. | |
20 class ControlOperator : public Operator1<int> { | |
21 public: | |
22 ControlOperator(IrOpcode::Value opcode, Properties properties, int inputs, | |
23 int outputs, int controls, const char* mnemonic) | |
24 : Operator1<int>(opcode, properties, inputs, outputs, mnemonic, | |
25 controls) {} | |
26 | |
27 virtual void PrintParameter(std::ostream& os) const FINAL {} | |
28 }; | |
29 | |
30 } // namespace | |
31 | |
32 | |
33 std::ostream& operator<<(std::ostream& os, BranchHint hint) { | 17 std::ostream& operator<<(std::ostream& os, BranchHint hint) { |
34 switch (hint) { | 18 switch (hint) { |
35 case BranchHint::kNone: | 19 case BranchHint::kNone: |
36 return os << "None"; | 20 return os << "None"; |
37 case BranchHint::kTrue: | 21 case BranchHint::kTrue: |
38 return os << "True"; | 22 return os << "True"; |
39 case BranchHint::kFalse: | 23 case BranchHint::kFalse: |
40 return os << "False"; | 24 return os << "False"; |
41 } | 25 } |
42 UNREACHABLE(); | 26 UNREACHABLE(); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
84 info.state_combine()); | 68 info.state_combine()); |
85 } | 69 } |
86 | 70 |
87 | 71 |
88 std::ostream& operator<<(std::ostream& os, FrameStateCallInfo const& info) { | 72 std::ostream& operator<<(std::ostream& os, FrameStateCallInfo const& info) { |
89 return os << info.type() << ", " << info.bailout_id() << ", " | 73 return os << info.type() << ", " << info.bailout_id() << ", " |
90 << info.state_combine(); | 74 << info.state_combine(); |
91 } | 75 } |
92 | 76 |
93 | 77 |
94 #define SHARED_OP_LIST(V) \ | 78 #define CACHED_OP_LIST(V) \ |
95 V(Dead, Operator::kFoldable, 0, 0) \ | 79 V(Dead, Operator::kFoldable, 0, 0, 0, 1) \ |
96 V(End, Operator::kFoldable, 0, 1) \ | 80 V(End, Operator::kFoldable, 0, 0, 1, 0) \ |
97 V(IfTrue, Operator::kFoldable, 0, 1) \ | 81 V(IfTrue, Operator::kFoldable, 0, 0, 1, 1) \ |
98 V(IfFalse, Operator::kFoldable, 0, 1) \ | 82 V(IfFalse, Operator::kFoldable, 0, 0, 1, 1) \ |
99 V(Throw, Operator::kFoldable, 1, 1) \ | 83 V(Throw, Operator::kFoldable, 1, 1, 1, 1) \ |
100 V(Return, Operator::kNoProperties, 1, 1) | 84 V(Return, Operator::kNoProperties, 1, 1, 1, 1) |
101 | 85 |
102 | 86 |
103 struct CommonOperatorBuilderImpl FINAL { | 87 struct CommonOperatorGlobalCache FINAL { |
104 #define SHARED(Name, properties, value_input_count, control_input_count) \ | 88 #define CACHED(Name, properties, value_input_count, effect_input_count, \ |
105 struct Name##Operator FINAL : public ControlOperator { \ | 89 control_input_count, control_output_count) \ |
106 Name##Operator() \ | 90 struct Name##Operator FINAL : public Operator { \ |
107 : ControlOperator(IrOpcode::k##Name, properties, value_input_count, 0, \ | 91 Name##Operator() \ |
108 control_input_count, #Name) {} \ | 92 : Operator(IrOpcode::k##Name, properties, #Name, value_input_count, \ |
109 }; \ | 93 effect_input_count, control_input_count, 0, 0, \ |
94 control_output_count) {} \ | |
95 }; \ | |
110 Name##Operator k##Name##Operator; | 96 Name##Operator k##Name##Operator; |
111 SHARED_OP_LIST(SHARED) | 97 CACHED_OP_LIST(CACHED) |
112 #undef SHARED | 98 #undef CACHED |
113 }; | 99 }; |
114 | 100 |
115 | 101 |
116 static base::LazyInstance<CommonOperatorBuilderImpl>::type kImpl = | 102 static base::LazyInstance<CommonOperatorGlobalCache>::type kCache = |
117 LAZY_INSTANCE_INITIALIZER; | 103 LAZY_INSTANCE_INITIALIZER; |
118 | 104 |
119 | 105 |
120 CommonOperatorBuilder::CommonOperatorBuilder(Zone* zone) | 106 CommonOperatorBuilder::CommonOperatorBuilder(Zone* zone) |
121 : impl_(kImpl.Get()), zone_(zone) {} | 107 : cache_(kCache.Get()), zone_(zone) {} |
122 | 108 |
123 | 109 |
124 #define SHARED(Name, properties, value_input_count, control_input_count) \ | 110 #define CACHED(Name, properties, value_input_count, effect_input_count, \ |
125 const Operator* CommonOperatorBuilder::Name() { \ | 111 control_input_count, control_output_count) \ |
126 return &impl_.k##Name##Operator; \ | 112 const Operator* CommonOperatorBuilder::Name() { \ |
113 return &cache_.k##Name##Operator; \ | |
127 } | 114 } |
128 SHARED_OP_LIST(SHARED) | 115 CACHED_OP_LIST(CACHED) |
129 #undef SHARED | 116 #undef CACHED |
130 | 117 |
131 | 118 |
132 const Operator* CommonOperatorBuilder::Branch(BranchHint hint) { | 119 const Operator* CommonOperatorBuilder::Branch(BranchHint hint) { |
133 return new (zone()) Operator1<BranchHint>( | 120 return new (zone()) Operator1<BranchHint>( |
134 IrOpcode::kBranch, Operator::kFoldable, 1, 0, "Branch", hint); | 121 IrOpcode::kBranch, Operator::kFoldable, "Branch", 1, 0, 1, 0, 0, 2, hint); |
135 } | 122 } |
136 | 123 |
137 | 124 |
138 const Operator* CommonOperatorBuilder::Start(int num_formal_parameters) { | 125 const Operator* CommonOperatorBuilder::Start(int num_formal_parameters) { |
139 // Outputs are formal parameters, plus context, receiver, and JSFunction. | 126 // Outputs are formal parameters, plus context, receiver, and JSFunction. |
140 const int value_output_count = num_formal_parameters + 3; | 127 const int value_output_count = num_formal_parameters + 3; |
141 return new (zone()) ControlOperator(IrOpcode::kStart, Operator::kFoldable, 0, | 128 return new (zone()) Operator( // -- |
142 value_output_count, 0, "Start"); | 129 IrOpcode::kStart, Operator::kFoldable, // opcode |
130 "Start", // name | |
131 0, 0, 0, value_output_count, 1, 1); // counts | |
143 } | 132 } |
144 | 133 |
145 | 134 |
146 const Operator* CommonOperatorBuilder::Merge(int controls) { | 135 const Operator* CommonOperatorBuilder::Merge(int controls) { |
147 return new (zone()) ControlOperator(IrOpcode::kMerge, Operator::kFoldable, 0, | 136 return new (zone()) Operator( // -- |
148 0, controls, "Merge"); | 137 IrOpcode::kMerge, Operator::kFoldable, // opcode |
138 "Merge", // name | |
139 0, 0, controls, 0, 0, 1); // counts | |
149 } | 140 } |
150 | 141 |
151 | 142 |
152 const Operator* CommonOperatorBuilder::Loop(int controls) { | 143 const Operator* CommonOperatorBuilder::Loop(int controls) { |
153 return new (zone()) ControlOperator(IrOpcode::kLoop, Operator::kFoldable, 0, | 144 return new (zone()) Operator( // -- |
154 0, controls, "Loop"); | 145 IrOpcode::kLoop, Operator::kFoldable, // opcode |
146 "Loop", // name | |
147 0, 0, controls, 0, 0, 1); // counts | |
155 } | 148 } |
156 | 149 |
157 | 150 |
158 const Operator* CommonOperatorBuilder::Terminate(int effects) { | 151 const Operator* CommonOperatorBuilder::Terminate(int effects) { |
159 return new (zone()) Operator1<int>(IrOpcode::kTerminate, | 152 return new (zone()) Operator( // -- |
160 Operator::kNoRead | Operator::kNoWrite, 0, | 153 IrOpcode::kTerminate, Operator::kPure, // opcode |
161 0, "Terminate", effects); | 154 "Terminate", // name |
155 0, effects, 1, 0, 0, 1); // counts | |
162 } | 156 } |
163 | 157 |
164 | 158 |
165 const Operator* CommonOperatorBuilder::Parameter(int index) { | 159 const Operator* CommonOperatorBuilder::Parameter(int index) { |
166 return new (zone()) Operator1<int>(IrOpcode::kParameter, Operator::kPure, 1, | 160 return new (zone()) Operator1<int>( // -- |
167 1, "Parameter", index); | 161 IrOpcode::kParameter, Operator::kPure, // opcode |
162 "Parameter", // name | |
163 1, 0, 0, 1, 0, 0, // counts | |
164 index); // parameter | |
168 } | 165 } |
169 | 166 |
170 | 167 |
171 const Operator* CommonOperatorBuilder::Int32Constant(int32_t value) { | 168 const Operator* CommonOperatorBuilder::Int32Constant(int32_t value) { |
172 return new (zone()) Operator1<int32_t>( | 169 return new (zone()) Operator1<int32_t>( // -- |
173 IrOpcode::kInt32Constant, Operator::kPure, 0, 1, "Int32Constant", value); | 170 IrOpcode::kInt32Constant, Operator::kPure, // opcode |
171 "Int32Constant", // name | |
172 0, 0, 0, 1, 0, 0, // counts | |
173 value); // parameter | |
174 } | 174 } |
175 | 175 |
176 | 176 |
177 const Operator* CommonOperatorBuilder::Int64Constant(int64_t value) { | 177 const Operator* CommonOperatorBuilder::Int64Constant(int64_t value) { |
178 return new (zone()) Operator1<int64_t>( | 178 return new (zone()) Operator1<int64_t>( // -- |
179 IrOpcode::kInt64Constant, Operator::kPure, 0, 1, "Int64Constant", value); | 179 IrOpcode::kInt64Constant, Operator::kPure, // opcode |
180 "Int64Constant", // name | |
181 0, 0, 0, 1, 0, 0, // counts | |
182 value); // parameter | |
180 } | 183 } |
181 | 184 |
182 | 185 |
183 const Operator* CommonOperatorBuilder::Float32Constant(volatile float value) { | 186 const Operator* CommonOperatorBuilder::Float32Constant(volatile float value) { |
184 return new (zone()) | 187 return new (zone()) |
185 Operator1<float, base::bit_equal_to<float>, base::bit_hash<float>>( | 188 Operator1<float, base::bit_equal_to<float>, base::bit_hash<float>>( // -- |
186 IrOpcode::kFloat32Constant, Operator::kPure, 0, 1, "Float32Constant", | 189 IrOpcode::kFloat32Constant, Operator::kPure, // opcode |
187 value); | 190 "Float32Constant", // name |
191 0, 0, 0, 1, 0, 0, // counts | |
192 value); // parameter | |
188 } | 193 } |
189 | 194 |
190 | 195 |
191 const Operator* CommonOperatorBuilder::Float64Constant(volatile double value) { | 196 const Operator* CommonOperatorBuilder::Float64Constant(volatile double value) { |
192 return new (zone()) | 197 return new (zone()) Operator1<double, base::bit_equal_to<double>, |
193 Operator1<double, base::bit_equal_to<double>, base::bit_hash<double>>( | 198 base::bit_hash<double>>( // -- |
194 IrOpcode::kFloat64Constant, Operator::kPure, 0, 1, "Float64Constant", | 199 IrOpcode::kFloat64Constant, Operator::kPure, // opcode |
195 value); | 200 "Float64Constant", // name |
201 0, 0, 0, 1, 0, 0, // counts | |
202 value); // parameter | |
196 } | 203 } |
197 | 204 |
198 | 205 |
199 const Operator* CommonOperatorBuilder::ExternalConstant( | 206 const Operator* CommonOperatorBuilder::ExternalConstant( |
200 const ExternalReference& value) { | 207 const ExternalReference& value) { |
201 return new (zone()) | 208 return new (zone()) Operator1<ExternalReference>( // -- |
202 Operator1<ExternalReference>(IrOpcode::kExternalConstant, Operator::kPure, | 209 IrOpcode::kExternalConstant, Operator::kPure, // opcode |
203 0, 1, "ExternalConstant", value); | 210 "ExternalConstant", // name |
211 0, 0, 0, 1, 0, 0, // counts | |
212 value); // parameter | |
204 } | 213 } |
205 | 214 |
206 | 215 |
207 const Operator* CommonOperatorBuilder::NumberConstant(volatile double value) { | 216 const Operator* CommonOperatorBuilder::NumberConstant(volatile double value) { |
208 return new (zone()) | 217 return new (zone()) Operator1<double, base::bit_equal_to<double>, |
209 Operator1<double, base::bit_equal_to<double>, base::bit_hash<double>>( | 218 base::bit_hash<double>>( // -- |
210 IrOpcode::kNumberConstant, Operator::kPure, 0, 1, "NumberConstant", | 219 IrOpcode::kNumberConstant, Operator::kPure, // opcode |
211 value); | 220 "NumberConstant", // name |
221 0, 0, 0, 1, 0, 0, // counts | |
222 value); // parameter | |
212 } | 223 } |
213 | 224 |
214 | 225 |
215 const Operator* CommonOperatorBuilder::HeapConstant( | 226 const Operator* CommonOperatorBuilder::HeapConstant( |
216 const Unique<HeapObject>& value) { | 227 const Unique<HeapObject>& value) { |
217 return new (zone()) Operator1<Unique<HeapObject>>( | 228 return new (zone()) Operator1<Unique<HeapObject>>( // -- |
218 IrOpcode::kHeapConstant, Operator::kPure, 0, 1, "HeapConstant", value); | 229 IrOpcode::kHeapConstant, Operator::kPure, // opcode |
230 "HeapConstant", // name | |
231 0, 0, 0, 1, 0, 0, // counts | |
232 value); // parameter | |
219 } | 233 } |
220 | 234 |
221 | 235 |
222 const Operator* CommonOperatorBuilder::Phi(MachineType type, int arguments) { | 236 const Operator* CommonOperatorBuilder::Phi(MachineType type, int arguments) { |
223 DCHECK(arguments > 0); // Disallow empty phis. | 237 DCHECK(arguments > 0); // Disallow empty phis. |
224 return new (zone()) Operator1<MachineType>(IrOpcode::kPhi, Operator::kPure, | 238 return new (zone()) Operator1<MachineType>( // -- |
225 arguments, 1, "Phi", type); | 239 IrOpcode::kPhi, Operator::kPure, // opcode |
240 "Phi", // name | |
241 arguments, 0, 1, 1, 0, 0, // counts | |
242 type); // parameter | |
226 } | 243 } |
227 | 244 |
228 | 245 |
229 const Operator* CommonOperatorBuilder::EffectPhi(int arguments) { | 246 const Operator* CommonOperatorBuilder::EffectPhi(int arguments) { |
230 DCHECK(arguments > 0); // Disallow empty phis. | 247 DCHECK(arguments > 0); // Disallow empty phis. |
231 return new (zone()) Operator1<int>(IrOpcode::kEffectPhi, Operator::kPure, 0, | 248 return new (zone()) Operator( // -- |
232 0, "EffectPhi", arguments); | 249 IrOpcode::kEffectPhi, Operator::kPure, // opcode |
250 "EffectPhi", // name | |
251 0, arguments, 1, 0, 1, 0); // counts | |
233 } | 252 } |
234 | 253 |
235 | 254 |
236 const Operator* CommonOperatorBuilder::ValueEffect(int arguments) { | 255 const Operator* CommonOperatorBuilder::ValueEffect(int arguments) { |
237 DCHECK(arguments > 0); // Disallow empty value effects. | 256 DCHECK(arguments > 0); // Disallow empty value effects. |
238 return new (zone()) Operator1<int>(IrOpcode::kValueEffect, Operator::kPure, | 257 return new (zone()) Operator( // -- |
239 arguments, 0, "ValueEffect", arguments); | 258 IrOpcode::kValueEffect, Operator::kPure, // opcode |
259 "ValueEffect", // name | |
260 arguments, 0, 0, 0, 1, 0); // counts | |
240 } | 261 } |
241 | 262 |
242 | 263 |
243 const Operator* CommonOperatorBuilder::Finish(int arguments) { | 264 const Operator* CommonOperatorBuilder::Finish(int arguments) { |
244 DCHECK(arguments > 0); // Disallow empty finishes. | 265 DCHECK(arguments > 0); // Disallow empty finishes. |
245 return new (zone()) Operator1<int>(IrOpcode::kFinish, Operator::kPure, 1, 1, | 266 return new (zone()) Operator( // -- |
246 "Finish", arguments); | 267 IrOpcode::kFinish, Operator::kPure, // opcode |
268 "Finish", // name | |
269 1, arguments, 0, 1, 0, 0); // counts | |
247 } | 270 } |
248 | 271 |
249 | 272 |
250 const Operator* CommonOperatorBuilder::StateValues(int arguments) { | 273 const Operator* CommonOperatorBuilder::StateValues(int arguments) { |
251 return new (zone()) Operator1<int>(IrOpcode::kStateValues, Operator::kPure, | 274 return new (zone()) Operator( // -- |
252 arguments, 1, "StateValues", arguments); | 275 IrOpcode::kStateValues, Operator::kPure, // opcode |
276 "StateValues", // name | |
277 arguments, 0, 0, 1, 0, 0); // counts | |
253 } | 278 } |
254 | 279 |
255 | 280 |
256 const Operator* CommonOperatorBuilder::FrameState( | 281 const Operator* CommonOperatorBuilder::FrameState( |
257 FrameStateType type, BailoutId bailout_id, | 282 FrameStateType type, BailoutId bailout_id, |
258 OutputFrameStateCombine state_combine, MaybeHandle<JSFunction> jsfunction) { | 283 OutputFrameStateCombine state_combine, MaybeHandle<JSFunction> jsfunction) { |
259 return new (zone()) Operator1<FrameStateCallInfo>( | 284 return new (zone()) Operator1<FrameStateCallInfo>( // -- |
260 IrOpcode::kFrameState, Operator::kPure, 4, 1, "FrameState", | 285 IrOpcode::kFrameState, Operator::kPure, // opcode |
286 "FrameState", // name | |
287 4, 0, 0, 1, 0, 0, // counts | |
261 FrameStateCallInfo(type, bailout_id, state_combine, jsfunction)); | 288 FrameStateCallInfo(type, bailout_id, state_combine, jsfunction)); |
262 } | 289 } |
263 | 290 |
264 | 291 |
292 static inline size_t CE(Operator::Properties properties) { | |
rossberg
2014/10/29 09:43:21
Nit: Make this a static private method of class Ca
titzer
2014/10/29 11:59:26
Added Operator::ZeroIfPure(Operator::Properties)
| |
293 // TODO(titzer): this is ugly. | |
294 return (properties & Operator::kPure) == Operator::kPure ? 0 : 1; | |
295 } | |
296 | |
297 | |
265 const Operator* CommonOperatorBuilder::Call(const CallDescriptor* descriptor) { | 298 const Operator* CommonOperatorBuilder::Call(const CallDescriptor* descriptor) { |
266 class CallOperator FINAL : public Operator1<const CallDescriptor*> { | 299 class CallOperator FINAL : public Operator1<const CallDescriptor*> { |
267 public: | 300 public: |
268 // TODO(titzer): Operator still uses int, whereas CallDescriptor uses | |
269 // size_t. | |
270 CallOperator(const CallDescriptor* descriptor, const char* mnemonic) | 301 CallOperator(const CallDescriptor* descriptor, const char* mnemonic) |
271 : Operator1<const CallDescriptor*>( | 302 : Operator1<const CallDescriptor*>( |
272 IrOpcode::kCall, descriptor->properties(), | 303 IrOpcode::kCall, descriptor->properties(), mnemonic, |
273 static_cast<int>(descriptor->InputCount() + | 304 descriptor->InputCount() + descriptor->FrameStateCount(), |
274 descriptor->FrameStateCount()), | 305 CE(descriptor->properties()), CE(descriptor->properties()), |
275 static_cast<int>(descriptor->ReturnCount()), mnemonic, | 306 descriptor->ReturnCount(), CE(descriptor->properties()), 0, |
276 descriptor) {} | 307 descriptor) {} |
277 | 308 |
278 virtual void PrintParameter(std::ostream& os) const OVERRIDE { | 309 virtual void PrintParameter(std::ostream& os) const OVERRIDE { |
279 os << "[" << *parameter() << "]"; | 310 os << "[" << *parameter() << "]"; |
280 } | 311 } |
281 }; | 312 }; |
282 return new (zone()) CallOperator(descriptor, "Call"); | 313 return new (zone()) CallOperator(descriptor, "Call"); |
283 } | 314 } |
284 | 315 |
285 | 316 |
286 const Operator* CommonOperatorBuilder::Projection(size_t index) { | 317 const Operator* CommonOperatorBuilder::Projection(size_t index) { |
287 return new (zone()) Operator1<size_t>(IrOpcode::kProjection, Operator::kPure, | 318 return new (zone()) Operator1<size_t>( // -- |
288 1, 1, "Projection", index); | 319 IrOpcode::kProjection, Operator::kPure, // opcode |
320 "Projection", // name | |
321 1, 0, 0, 1, 0, 0, // counts | |
322 index); // parameter | |
289 } | 323 } |
290 | 324 |
291 } // namespace compiler | 325 } // namespace compiler |
292 } // namespace internal | 326 } // namespace internal |
293 } // namespace v8 | 327 } // namespace v8 |
OLD | NEW |