• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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