blob: a6cca456d2bf219bf0c1639c47ef960b11416a48 [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// 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
3// found in the LICENSE file.
4
5#include "src/compiler/common-operator.h"
6
7#include "src/assembler.h"
8#include "src/base/lazy-instance.h"
9#include "src/compiler/linkage.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040010#include "src/compiler/opcodes.h"
11#include "src/compiler/operator.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012#include "src/unique.h"
13#include "src/zone.h"
14
15namespace v8 {
16namespace internal {
17namespace compiler {
18
Emily Bernierd0a1eb72015-03-24 16:35:39 -040019std::ostream& operator<<(std::ostream& os, BranchHint hint) {
20 switch (hint) {
21 case BranchHint::kNone:
22 return os << "None";
23 case BranchHint::kTrue:
24 return os << "True";
25 case BranchHint::kFalse:
26 return os << "False";
Ben Murdochb8a8cc12014-11-26 15:28:44 +000027 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -040028 UNREACHABLE();
29 return os;
30}
31
32
33BranchHint BranchHintOf(const Operator* const op) {
34 DCHECK_EQ(IrOpcode::kBranch, op->opcode());
35 return OpParameter<BranchHint>(op);
36}
37
38
39bool operator==(SelectParameters const& lhs, SelectParameters const& rhs) {
40 return lhs.type() == rhs.type() && lhs.hint() == rhs.hint();
41}
42
43
44bool operator!=(SelectParameters const& lhs, SelectParameters const& rhs) {
45 return !(lhs == rhs);
46}
47
48
49size_t hash_value(SelectParameters const& p) {
50 return base::hash_combine(p.type(), p.hint());
51}
52
53
54std::ostream& operator<<(std::ostream& os, SelectParameters const& p) {
55 return os << p.type() << "|" << p.hint();
56}
57
58
59SelectParameters const& SelectParametersOf(const Operator* const op) {
60 DCHECK_EQ(IrOpcode::kSelect, op->opcode());
61 return OpParameter<SelectParameters>(op);
62}
63
64
65size_t hash_value(OutputFrameStateCombine const& sc) {
66 return base::hash_combine(sc.kind_, sc.parameter_);
67}
68
69
70std::ostream& operator<<(std::ostream& os, OutputFrameStateCombine const& sc) {
71 switch (sc.kind_) {
72 case OutputFrameStateCombine::kPushOutput:
73 if (sc.parameter_ == 0) return os << "Ignore";
74 return os << "Push(" << sc.parameter_ << ")";
75 case OutputFrameStateCombine::kPokeAt:
76 return os << "PokeAt(" << sc.parameter_ << ")";
Ben Murdochb8a8cc12014-11-26 15:28:44 +000077 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -040078 UNREACHABLE();
79 return os;
80}
Ben Murdochb8a8cc12014-11-26 15:28:44 +000081
82
Emily Bernierd0a1eb72015-03-24 16:35:39 -040083bool operator==(FrameStateCallInfo const& lhs, FrameStateCallInfo const& rhs) {
84 return lhs.type() == rhs.type() && lhs.bailout_id() == rhs.bailout_id() &&
85 lhs.state_combine() == rhs.state_combine();
86}
Ben Murdochb8a8cc12014-11-26 15:28:44 +000087
88
Emily Bernierd0a1eb72015-03-24 16:35:39 -040089bool operator!=(FrameStateCallInfo const& lhs, FrameStateCallInfo const& rhs) {
90 return !(lhs == rhs);
91}
92
93
94size_t hash_value(FrameStateCallInfo const& info) {
95 return base::hash_combine(info.type(), info.bailout_id(),
96 info.state_combine());
97}
98
99
100std::ostream& operator<<(std::ostream& os, FrameStateCallInfo const& info) {
101 return os << info.type() << ", " << info.bailout_id() << ", "
102 << info.state_combine();
103}
104
105
106#define CACHED_OP_LIST(V) \
107 V(Dead, Operator::kFoldable, 0, 0, 0, 1) \
108 V(End, Operator::kFoldable, 0, 0, 1, 0) \
109 V(IfTrue, Operator::kFoldable, 0, 0, 1, 1) \
110 V(IfFalse, Operator::kFoldable, 0, 0, 1, 1) \
111 V(Throw, Operator::kFoldable, 1, 1, 1, 1) \
112 V(Return, Operator::kNoProperties, 1, 1, 1, 1)
113
114
115#define CACHED_LOOP_LIST(V) \
116 V(1) \
117 V(2)
118
119
120#define CACHED_MERGE_LIST(V) \
121 V(1) \
122 V(2) \
123 V(3) \
124 V(4) \
125 V(5) \
126 V(6) \
127 V(7) \
128 V(8)
129
130
131#define CACHED_PARAMETER_LIST(V) \
132 V(0) \
133 V(1) \
134 V(2) \
135 V(3) \
136 V(4) \
137 V(5) \
138 V(6)
139
140
141struct CommonOperatorGlobalCache FINAL {
142#define CACHED(Name, properties, value_input_count, effect_input_count, \
143 control_input_count, control_output_count) \
144 struct Name##Operator FINAL : public Operator { \
145 Name##Operator() \
146 : Operator(IrOpcode::k##Name, properties, #Name, value_input_count, \
147 effect_input_count, control_input_count, 0, 0, \
148 control_output_count) {} \
149 }; \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000150 Name##Operator k##Name##Operator;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400151 CACHED_OP_LIST(CACHED)
152#undef CACHED
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000153
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400154 template <BranchHint kBranchHint>
155 struct BranchOperator FINAL : public Operator1<BranchHint> {
156 BranchOperator()
157 : Operator1<BranchHint>( // --
158 IrOpcode::kBranch, Operator::kFoldable, // opcode
159 "Branch", // name
160 1, 0, 1, 0, 0, 2, // counts
161 kBranchHint) {} // parameter
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000162 };
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400163 BranchOperator<BranchHint::kNone> kBranchNoneOperator;
164 BranchOperator<BranchHint::kTrue> kBranchTrueOperator;
165 BranchOperator<BranchHint::kFalse> kBranchFalseOperator;
166
167 template <size_t kInputCount>
168 struct LoopOperator FINAL : public Operator {
169 LoopOperator()
170 : Operator( // --
171 IrOpcode::kLoop, Operator::kFoldable, // opcode
172 "Loop", // name
173 0, 0, kInputCount, 0, 0, 1) {} // counts
174 };
175#define CACHED_LOOP(input_count) \
176 LoopOperator<input_count> kLoop##input_count##Operator;
177 CACHED_LOOP_LIST(CACHED_LOOP)
178#undef CACHED_LOOP
179
180 template <size_t kInputCount>
181 struct MergeOperator FINAL : public Operator {
182 MergeOperator()
183 : Operator( // --
184 IrOpcode::kMerge, Operator::kFoldable, // opcode
185 "Merge", // name
186 0, 0, kInputCount, 0, 0, 1) {} // counts
187 };
188#define CACHED_MERGE(input_count) \
189 MergeOperator<input_count> kMerge##input_count##Operator;
190 CACHED_MERGE_LIST(CACHED_MERGE)
191#undef CACHED_MERGE
192
193 template <int kIndex>
194 struct ParameterOperator FINAL : public Operator1<int> {
195 ParameterOperator()
196 : Operator1<int>( // --
197 IrOpcode::kParameter, Operator::kPure, // opcode
198 "Parameter", // name
199 1, 0, 0, 1, 0, 0, // counts,
200 kIndex) {} // parameter
201 };
202#define CACHED_PARAMETER(index) \
203 ParameterOperator<index> kParameter##index##Operator;
204 CACHED_PARAMETER_LIST(CACHED_PARAMETER)
205#undef CACHED_PARAMETER
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000206};
207
208
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400209static base::LazyInstance<CommonOperatorGlobalCache>::type kCache =
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000210 LAZY_INSTANCE_INITIALIZER;
211
212
213CommonOperatorBuilder::CommonOperatorBuilder(Zone* zone)
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400214 : cache_(kCache.Get()), zone_(zone) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000215
216
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400217#define CACHED(Name, properties, value_input_count, effect_input_count, \
218 control_input_count, control_output_count) \
219 const Operator* CommonOperatorBuilder::Name() { \
220 return &cache_.k##Name##Operator; \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000221 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400222CACHED_OP_LIST(CACHED)
223#undef CACHED
224
225
226const Operator* CommonOperatorBuilder::Branch(BranchHint hint) {
227 switch (hint) {
228 case BranchHint::kNone:
229 return &cache_.kBranchNoneOperator;
230 case BranchHint::kTrue:
231 return &cache_.kBranchTrueOperator;
232 case BranchHint::kFalse:
233 return &cache_.kBranchFalseOperator;
234 }
235 UNREACHABLE();
236 return nullptr;
237}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000238
239
240const Operator* CommonOperatorBuilder::Start(int num_formal_parameters) {
241 // Outputs are formal parameters, plus context, receiver, and JSFunction.
242 const int value_output_count = num_formal_parameters + 3;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400243 return new (zone()) Operator( // --
244 IrOpcode::kStart, Operator::kFoldable, // opcode
245 "Start", // name
246 0, 0, 0, value_output_count, 1, 1); // counts
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000247}
248
249
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400250const Operator* CommonOperatorBuilder::Loop(int control_input_count) {
251 switch (control_input_count) {
252#define CACHED_LOOP(input_count) \
253 case input_count: \
254 return &cache_.kLoop##input_count##Operator;
255 CACHED_LOOP_LIST(CACHED_LOOP)
256#undef CACHED_LOOP
257 default:
258 break;
259 }
260 // Uncached.
261 return new (zone()) Operator( // --
262 IrOpcode::kLoop, Operator::kFoldable, // opcode
263 "Loop", // name
264 0, 0, control_input_count, 0, 0, 1); // counts
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000265}
266
267
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400268const Operator* CommonOperatorBuilder::Merge(int control_input_count) {
269 switch (control_input_count) {
270#define CACHED_MERGE(input_count) \
271 case input_count: \
272 return &cache_.kMerge##input_count##Operator;
273 CACHED_MERGE_LIST(CACHED_MERGE)
274#undef CACHED_MERGE
275 default:
276 break;
277 }
278 // Uncached.
279 return new (zone()) Operator( // --
280 IrOpcode::kMerge, Operator::kFoldable, // opcode
281 "Merge", // name
282 0, 0, control_input_count, 0, 0, 1); // counts
283}
284
285
286const Operator* CommonOperatorBuilder::Terminate(int effects) {
287 return new (zone()) Operator( // --
288 IrOpcode::kTerminate, Operator::kPure, // opcode
289 "Terminate", // name
290 0, effects, 1, 0, 0, 1); // counts
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000291}
292
293
294const Operator* CommonOperatorBuilder::Parameter(int index) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400295 switch (index) {
296#define CACHED_PARAMETER(index) \
297 case index: \
298 return &cache_.kParameter##index##Operator;
299 CACHED_PARAMETER_LIST(CACHED_PARAMETER)
300#undef CACHED_PARAMETER
301 default:
302 break;
303 }
304 // Uncached.
305 return new (zone()) Operator1<int>( // --
306 IrOpcode::kParameter, Operator::kPure, // opcode
307 "Parameter", // name
308 1, 0, 0, 1, 0, 0, // counts
309 index); // parameter
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000310}
311
312
313const Operator* CommonOperatorBuilder::Int32Constant(int32_t value) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400314 return new (zone()) Operator1<int32_t>( // --
315 IrOpcode::kInt32Constant, Operator::kPure, // opcode
316 "Int32Constant", // name
317 0, 0, 0, 1, 0, 0, // counts
318 value); // parameter
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000319}
320
321
322const Operator* CommonOperatorBuilder::Int64Constant(int64_t value) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400323 return new (zone()) Operator1<int64_t>( // --
324 IrOpcode::kInt64Constant, Operator::kPure, // opcode
325 "Int64Constant", // name
326 0, 0, 0, 1, 0, 0, // counts
327 value); // parameter
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000328}
329
330
331const Operator* CommonOperatorBuilder::Float32Constant(volatile float value) {
332 return new (zone())
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400333 Operator1<float, base::bit_equal_to<float>, base::bit_hash<float>>( // --
334 IrOpcode::kFloat32Constant, Operator::kPure, // opcode
335 "Float32Constant", // name
336 0, 0, 0, 1, 0, 0, // counts
337 value); // parameter
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000338}
339
340
341const Operator* CommonOperatorBuilder::Float64Constant(volatile double value) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400342 return new (zone()) Operator1<double, base::bit_equal_to<double>,
343 base::bit_hash<double>>( // --
344 IrOpcode::kFloat64Constant, Operator::kPure, // opcode
345 "Float64Constant", // name
346 0, 0, 0, 1, 0, 0, // counts
347 value); // parameter
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000348}
349
350
351const Operator* CommonOperatorBuilder::ExternalConstant(
352 const ExternalReference& value) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400353 return new (zone()) Operator1<ExternalReference>( // --
354 IrOpcode::kExternalConstant, Operator::kPure, // opcode
355 "ExternalConstant", // name
356 0, 0, 0, 1, 0, 0, // counts
357 value); // parameter
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000358}
359
360
361const Operator* CommonOperatorBuilder::NumberConstant(volatile double value) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400362 return new (zone()) Operator1<double, base::bit_equal_to<double>,
363 base::bit_hash<double>>( // --
364 IrOpcode::kNumberConstant, Operator::kPure, // opcode
365 "NumberConstant", // name
366 0, 0, 0, 1, 0, 0, // counts
367 value); // parameter
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000368}
369
370
371const Operator* CommonOperatorBuilder::HeapConstant(
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400372 const Unique<HeapObject>& value) {
373 return new (zone()) Operator1<Unique<HeapObject>>( // --
374 IrOpcode::kHeapConstant, Operator::kPure, // opcode
375 "HeapConstant", // name
376 0, 0, 0, 1, 0, 0, // counts
377 value); // parameter
378}
379
380
381const Operator* CommonOperatorBuilder::Select(MachineType type,
382 BranchHint hint) {
383 return new (zone()) Operator1<SelectParameters>( // --
384 IrOpcode::kSelect, Operator::kPure, // opcode
385 "Select", // name
386 3, 0, 0, 1, 0, 0, // counts
387 SelectParameters(type, hint)); // parameter
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000388}
389
390
391const Operator* CommonOperatorBuilder::Phi(MachineType type, int arguments) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400392 DCHECK(arguments > 0); // Disallow empty phis.
393 return new (zone()) Operator1<MachineType>( // --
394 IrOpcode::kPhi, Operator::kPure, // opcode
395 "Phi", // name
396 arguments, 0, 1, 1, 0, 0, // counts
397 type); // parameter
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000398}
399
400
401const Operator* CommonOperatorBuilder::EffectPhi(int arguments) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400402 DCHECK(arguments > 0); // Disallow empty phis.
403 return new (zone()) Operator( // --
404 IrOpcode::kEffectPhi, Operator::kPure, // opcode
405 "EffectPhi", // name
406 0, arguments, 1, 0, 1, 0); // counts
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000407}
408
409
410const Operator* CommonOperatorBuilder::ValueEffect(int arguments) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400411 DCHECK(arguments > 0); // Disallow empty value effects.
412 return new (zone()) Operator( // --
413 IrOpcode::kValueEffect, Operator::kPure, // opcode
414 "ValueEffect", // name
415 arguments, 0, 0, 0, 1, 0); // counts
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000416}
417
418
419const Operator* CommonOperatorBuilder::Finish(int arguments) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400420 DCHECK(arguments > 0); // Disallow empty finishes.
421 return new (zone()) Operator( // --
422 IrOpcode::kFinish, Operator::kPure, // opcode
423 "Finish", // name
424 1, arguments, 0, 1, 0, 0); // counts
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000425}
426
427
428const Operator* CommonOperatorBuilder::StateValues(int arguments) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400429 return new (zone()) Operator( // --
430 IrOpcode::kStateValues, Operator::kPure, // opcode
431 "StateValues", // name
432 arguments, 0, 0, 1, 0, 0); // counts
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000433}
434
435
436const Operator* CommonOperatorBuilder::FrameState(
437 FrameStateType type, BailoutId bailout_id,
438 OutputFrameStateCombine state_combine, MaybeHandle<JSFunction> jsfunction) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400439 return new (zone()) Operator1<FrameStateCallInfo>( // --
440 IrOpcode::kFrameState, Operator::kPure, // opcode
441 "FrameState", // name
442 4, 0, 0, 1, 0, 0, // counts
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000443 FrameStateCallInfo(type, bailout_id, state_combine, jsfunction));
444}
445
446
447const Operator* CommonOperatorBuilder::Call(const CallDescriptor* descriptor) {
448 class CallOperator FINAL : public Operator1<const CallDescriptor*> {
449 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000450 CallOperator(const CallDescriptor* descriptor, const char* mnemonic)
451 : Operator1<const CallDescriptor*>(
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400452 IrOpcode::kCall, descriptor->properties(), mnemonic,
453 descriptor->InputCount() + descriptor->FrameStateCount(),
454 Operator::ZeroIfPure(descriptor->properties()),
455 Operator::ZeroIfPure(descriptor->properties()),
456 descriptor->ReturnCount(),
457 Operator::ZeroIfPure(descriptor->properties()), 0, descriptor) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000458
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400459 void PrintParameter(std::ostream& os) const OVERRIDE {
460 os << "[" << *parameter() << "]";
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000461 }
462 };
463 return new (zone()) CallOperator(descriptor, "Call");
464}
465
466
467const Operator* CommonOperatorBuilder::Projection(size_t index) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400468 return new (zone()) Operator1<size_t>( // --
469 IrOpcode::kProjection, Operator::kPure, // opcode
470 "Projection", // name
471 1, 0, 0, 1, 0, 0, // counts
472 index); // parameter
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000473}
474
475} // namespace compiler
476} // namespace internal
477} // namespace v8