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
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"
10 #include "src/unique.h"
11 #include "src/zone.h"
12
13 namespace v8 {
14 namespace internal {
15 namespace compiler {
16
17 namespace {
18
19 // TODO(turbofan): Use size_t instead of int here.
20 class ControlOperator : public Operator1<int> {
21 public:
ControlOperator(IrOpcode::Value opcode,Properties properties,int inputs,int outputs,int controls,const char * mnemonic)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
PrintParameter(OStream & os) const27 virtual OStream& PrintParameter(OStream& os) const FINAL { return os; }
28 };
29
30 } // namespace
31
32
33 // Specialization for static parameters of type {ExternalReference}.
34 template <>
35 struct StaticParameterTraits<ExternalReference> {
PrintTov8::internal::compiler::StaticParameterTraits36 static OStream& PrintTo(OStream& os, ExternalReference reference) {
37 os << reference.address();
38 // TODO(bmeurer): Move to operator<<(os, ExternalReference)
39 const Runtime::Function* function =
40 Runtime::FunctionForEntry(reference.address());
41 if (function) {
42 os << " <" << function->name << ".entry>";
43 }
44 return os;
45 }
HashCodev8::internal::compiler::StaticParameterTraits46 static int HashCode(ExternalReference reference) {
47 return bit_cast<int>(static_cast<uint32_t>(
48 reinterpret_cast<uintptr_t>(reference.address())));
49 }
Equalsv8::internal::compiler::StaticParameterTraits50 static bool Equals(ExternalReference lhs, ExternalReference rhs) {
51 return lhs == rhs;
52 }
53 };
54
55
56 #define SHARED_OP_LIST(V) \
57 V(Dead, Operator::kFoldable, 0, 0) \
58 V(End, Operator::kFoldable, 0, 1) \
59 V(Branch, Operator::kFoldable, 1, 1) \
60 V(IfTrue, Operator::kFoldable, 0, 1) \
61 V(IfFalse, Operator::kFoldable, 0, 1) \
62 V(Throw, Operator::kFoldable, 1, 1) \
63 V(Return, Operator::kNoProperties, 1, 1)
64
65
66 struct CommonOperatorBuilderImpl FINAL {
67 #define SHARED(Name, properties, value_input_count, control_input_count) \
68 struct Name##Operator FINAL : public ControlOperator { \
69 Name##Operator() \
70 : ControlOperator(IrOpcode::k##Name, properties, value_input_count, 0, \
71 control_input_count, #Name) {} \
72 }; \
73 Name##Operator k##Name##Operator;
74 SHARED_OP_LIST(SHARED)
75 #undef SHARED
76
77 struct ControlEffectOperator FINAL : public SimpleOperator {
ControlEffectOperatorv8::internal::compiler::FINAL::FINAL78 ControlEffectOperator()
79 : SimpleOperator(IrOpcode::kControlEffect, Operator::kPure, 0, 0,
80 "ControlEffect") {}
81 };
82 ControlEffectOperator kControlEffectOperator;
83 };
84
85
86 static base::LazyInstance<CommonOperatorBuilderImpl>::type kImpl =
87 LAZY_INSTANCE_INITIALIZER;
88
89
CommonOperatorBuilder(Zone * zone)90 CommonOperatorBuilder::CommonOperatorBuilder(Zone* zone)
91 : impl_(kImpl.Get()), zone_(zone) {}
92
93
94 #define SHARED(Name, properties, value_input_count, control_input_count) \
95 const Operator* CommonOperatorBuilder::Name() { \
96 return &impl_.k##Name##Operator; \
97 }
SHARED_OP_LIST(SHARED) const98 SHARED_OP_LIST(SHARED)
99 #undef SHARED
100
101
102 const Operator* CommonOperatorBuilder::Start(int num_formal_parameters) {
103 // Outputs are formal parameters, plus context, receiver, and JSFunction.
104 const int value_output_count = num_formal_parameters + 3;
105 return new (zone()) ControlOperator(IrOpcode::kStart, Operator::kFoldable, 0,
106 value_output_count, 0, "Start");
107 }
108
109
Merge(int controls)110 const Operator* CommonOperatorBuilder::Merge(int controls) {
111 return new (zone()) ControlOperator(IrOpcode::kMerge, Operator::kFoldable, 0,
112 0, controls, "Merge");
113 }
114
115
Loop(int controls)116 const Operator* CommonOperatorBuilder::Loop(int controls) {
117 return new (zone()) ControlOperator(IrOpcode::kLoop, Operator::kFoldable, 0,
118 0, controls, "Loop");
119 }
120
121
Parameter(int index)122 const Operator* CommonOperatorBuilder::Parameter(int index) {
123 return new (zone()) Operator1<int>(IrOpcode::kParameter, Operator::kPure, 1,
124 1, "Parameter", index);
125 }
126
127
Int32Constant(int32_t value)128 const Operator* CommonOperatorBuilder::Int32Constant(int32_t value) {
129 return new (zone()) Operator1<int32_t>(
130 IrOpcode::kInt32Constant, Operator::kPure, 0, 1, "Int32Constant", value);
131 }
132
133
Int64Constant(int64_t value)134 const Operator* CommonOperatorBuilder::Int64Constant(int64_t value) {
135 return new (zone()) Operator1<int64_t>(
136 IrOpcode::kInt64Constant, Operator::kPure, 0, 1, "Int64Constant", value);
137 }
138
139
Float32Constant(volatile float value)140 const Operator* CommonOperatorBuilder::Float32Constant(volatile float value) {
141 return new (zone())
142 Operator1<float>(IrOpcode::kFloat32Constant, Operator::kPure, 0, 1,
143 "Float32Constant", value);
144 }
145
146
Float64Constant(volatile double value)147 const Operator* CommonOperatorBuilder::Float64Constant(volatile double value) {
148 return new (zone())
149 Operator1<double>(IrOpcode::kFloat64Constant, Operator::kPure, 0, 1,
150 "Float64Constant", value);
151 }
152
153
ExternalConstant(const ExternalReference & value)154 const Operator* CommonOperatorBuilder::ExternalConstant(
155 const ExternalReference& value) {
156 return new (zone())
157 Operator1<ExternalReference>(IrOpcode::kExternalConstant, Operator::kPure,
158 0, 1, "ExternalConstant", value);
159 }
160
161
NumberConstant(volatile double value)162 const Operator* CommonOperatorBuilder::NumberConstant(volatile double value) {
163 return new (zone())
164 Operator1<double>(IrOpcode::kNumberConstant, Operator::kPure, 0, 1,
165 "NumberConstant", value);
166 }
167
168
HeapConstant(const Unique<Object> & value)169 const Operator* CommonOperatorBuilder::HeapConstant(
170 const Unique<Object>& value) {
171 return new (zone()) Operator1<Unique<Object> >(
172 IrOpcode::kHeapConstant, Operator::kPure, 0, 1, "HeapConstant", value);
173 }
174
175
Phi(MachineType type,int arguments)176 const Operator* CommonOperatorBuilder::Phi(MachineType type, int arguments) {
177 DCHECK(arguments > 0); // Disallow empty phis.
178 return new (zone()) Operator1<MachineType>(IrOpcode::kPhi, Operator::kPure,
179 arguments, 1, "Phi", type);
180 }
181
182
EffectPhi(int arguments)183 const Operator* CommonOperatorBuilder::EffectPhi(int arguments) {
184 DCHECK(arguments > 0); // Disallow empty phis.
185 return new (zone()) Operator1<int>(IrOpcode::kEffectPhi, Operator::kPure, 0,
186 0, "EffectPhi", arguments);
187 }
188
189
ControlEffect()190 const Operator* CommonOperatorBuilder::ControlEffect() {
191 return &impl_.kControlEffectOperator;
192 }
193
194
ValueEffect(int arguments)195 const Operator* CommonOperatorBuilder::ValueEffect(int arguments) {
196 DCHECK(arguments > 0); // Disallow empty value effects.
197 return new (zone()) SimpleOperator(IrOpcode::kValueEffect, Operator::kPure,
198 arguments, 0, "ValueEffect");
199 }
200
201
Finish(int arguments)202 const Operator* CommonOperatorBuilder::Finish(int arguments) {
203 DCHECK(arguments > 0); // Disallow empty finishes.
204 return new (zone()) Operator1<int>(IrOpcode::kFinish, Operator::kPure, 1, 1,
205 "Finish", arguments);
206 }
207
208
StateValues(int arguments)209 const Operator* CommonOperatorBuilder::StateValues(int arguments) {
210 return new (zone()) Operator1<int>(IrOpcode::kStateValues, Operator::kPure,
211 arguments, 1, "StateValues", arguments);
212 }
213
214
FrameState(FrameStateType type,BailoutId bailout_id,OutputFrameStateCombine state_combine,MaybeHandle<JSFunction> jsfunction)215 const Operator* CommonOperatorBuilder::FrameState(
216 FrameStateType type, BailoutId bailout_id,
217 OutputFrameStateCombine state_combine, MaybeHandle<JSFunction> jsfunction) {
218 return new (zone()) Operator1<FrameStateCallInfo>(
219 IrOpcode::kFrameState, Operator::kPure, 4, 1, "FrameState",
220 FrameStateCallInfo(type, bailout_id, state_combine, jsfunction));
221 }
222
223
Call(const CallDescriptor * descriptor)224 const Operator* CommonOperatorBuilder::Call(const CallDescriptor* descriptor) {
225 class CallOperator FINAL : public Operator1<const CallDescriptor*> {
226 public:
227 // TODO(titzer): Operator still uses int, whereas CallDescriptor uses
228 // size_t.
229 CallOperator(const CallDescriptor* descriptor, const char* mnemonic)
230 : Operator1<const CallDescriptor*>(
231 IrOpcode::kCall, descriptor->properties(),
232 static_cast<int>(descriptor->InputCount() +
233 descriptor->FrameStateCount()),
234 static_cast<int>(descriptor->ReturnCount()), mnemonic,
235 descriptor) {}
236
237 virtual OStream& PrintParameter(OStream& os) const OVERRIDE {
238 return os << "[" << *parameter() << "]";
239 }
240 };
241 return new (zone()) CallOperator(descriptor, "Call");
242 }
243
244
Projection(size_t index)245 const Operator* CommonOperatorBuilder::Projection(size_t index) {
246 return new (zone()) Operator1<size_t>(IrOpcode::kProjection, Operator::kPure,
247 1, 1, "Projection", index);
248 }
249
250 } // namespace compiler
251 } // namespace internal
252 } // namespace v8
253