Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / v8 / src / compiler / common-operator.h
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
3 // found in the LICENSE file.
4
5 #ifndef V8_COMPILER_COMMON_OPERATOR_H_
6 #define V8_COMPILER_COMMON_OPERATOR_H_
7
8 #include "src/v8.h"
9
10 #include "src/assembler.h"
11 #include "src/compiler/linkage.h"
12 #include "src/compiler/opcodes.h"
13 #include "src/compiler/operator.h"
14 #include "src/unique.h"
15
16 namespace v8 {
17 namespace internal {
18
19 class OStream;
20
21 namespace compiler {
22
23 class ControlOperator : public Operator1<int> {
24  public:
25   ControlOperator(IrOpcode::Value opcode, uint16_t properties, int inputs,
26                   int outputs, int controls, const char* mnemonic)
27       : Operator1<int>(opcode, properties, inputs, outputs, mnemonic,
28                        controls) {}
29
30   virtual OStream& PrintParameter(OStream& os) const { return os; }  // NOLINT
31   int ControlInputCount() const { return parameter(); }
32 };
33
34 class CallOperator : public Operator1<CallDescriptor*> {
35  public:
36   CallOperator(CallDescriptor* descriptor, const char* mnemonic)
37       : Operator1<CallDescriptor*>(
38             IrOpcode::kCall, descriptor->properties(), descriptor->InputCount(),
39             descriptor->ReturnCount(), mnemonic, descriptor) {}
40
41   virtual OStream& PrintParameter(OStream& os) const {  // NOLINT
42     return os << "[" << *parameter() << "]";
43   }
44 };
45
46 // Interface for building common operators that can be used at any level of IR,
47 // including JavaScript, mid-level, and low-level.
48 // TODO(titzer): Move the mnemonics into SimpleOperator and Operator1 classes.
49 class CommonOperatorBuilder {
50  public:
51   explicit CommonOperatorBuilder(Zone* zone) : zone_(zone) {}
52
53 #define CONTROL_OP(name, inputs, controls)                                   \
54   return new (zone_) ControlOperator(IrOpcode::k##name, Operator::kFoldable, \
55                                      inputs, 0, controls, #name);
56
57   Operator* Start(int num_formal_parameters) {
58     // Outputs are formal parameters, plus context, receiver, and JSFunction.
59     int outputs = num_formal_parameters + 3;
60     return new (zone_) ControlOperator(IrOpcode::kStart, Operator::kFoldable, 0,
61                                        outputs, 0, "Start");
62   }
63   Operator* Dead() { CONTROL_OP(Dead, 0, 0); }
64   Operator* End() { CONTROL_OP(End, 0, 1); }
65   Operator* Branch() { CONTROL_OP(Branch, 1, 1); }
66   Operator* IfTrue() { CONTROL_OP(IfTrue, 0, 1); }
67   Operator* IfFalse() { CONTROL_OP(IfFalse, 0, 1); }
68   Operator* Throw() { CONTROL_OP(Throw, 1, 1); }
69   Operator* LazyDeoptimization() { CONTROL_OP(LazyDeoptimization, 0, 1); }
70   Operator* Continuation() { CONTROL_OP(Continuation, 0, 1); }
71
72   Operator* Deoptimize() {
73     return new (zone_)
74         ControlOperator(IrOpcode::kDeoptimize, 0, 1, 0, 1, "Deoptimize");
75   }
76
77   Operator* Return() {
78     return new (zone_) ControlOperator(IrOpcode::kReturn, 0, 1, 0, 1, "Return");
79   }
80
81   Operator* Merge(int controls) {
82     return new (zone_) ControlOperator(IrOpcode::kMerge, Operator::kFoldable, 0,
83                                        0, controls, "Merge");
84   }
85
86   Operator* Loop(int controls) {
87     return new (zone_) ControlOperator(IrOpcode::kLoop, Operator::kFoldable, 0,
88                                        0, controls, "Loop");
89   }
90
91   Operator* Parameter(int index) {
92     return new (zone_) Operator1<int>(IrOpcode::kParameter, Operator::kPure, 1,
93                                       1, "Parameter", index);
94   }
95   Operator* Int32Constant(int32_t value) {
96     return new (zone_) Operator1<int>(IrOpcode::kInt32Constant, Operator::kPure,
97                                       0, 1, "Int32Constant", value);
98   }
99   Operator* Int64Constant(int64_t value) {
100     return new (zone_)
101         Operator1<int64_t>(IrOpcode::kInt64Constant, Operator::kPure, 0, 1,
102                            "Int64Constant", value);
103   }
104   Operator* Float64Constant(double value) {
105     return new (zone_)
106         Operator1<double>(IrOpcode::kFloat64Constant, Operator::kPure, 0, 1,
107                           "Float64Constant", value);
108   }
109   Operator* ExternalConstant(ExternalReference value) {
110     return new (zone_) Operator1<ExternalReference>(IrOpcode::kExternalConstant,
111                                                     Operator::kPure, 0, 1,
112                                                     "ExternalConstant", value);
113   }
114   Operator* NumberConstant(double value) {
115     return new (zone_)
116         Operator1<double>(IrOpcode::kNumberConstant, Operator::kPure, 0, 1,
117                           "NumberConstant", value);
118   }
119   Operator* HeapConstant(PrintableUnique<Object> value) {
120     return new (zone_) Operator1<PrintableUnique<Object> >(
121         IrOpcode::kHeapConstant, Operator::kPure, 0, 1, "HeapConstant", value);
122   }
123   Operator* Phi(int arguments) {
124     DCHECK(arguments > 0);  // Disallow empty phis.
125     return new (zone_) Operator1<int>(IrOpcode::kPhi, Operator::kPure,
126                                       arguments, 1, "Phi", arguments);
127   }
128   Operator* EffectPhi(int arguments) {
129     DCHECK(arguments > 0);  // Disallow empty phis.
130     return new (zone_) Operator1<int>(IrOpcode::kEffectPhi, Operator::kPure, 0,
131                                       0, "EffectPhi", arguments);
132   }
133   Operator* StateValues(int arguments) {
134     return new (zone_) Operator1<int>(IrOpcode::kStateValues, Operator::kPure,
135                                       arguments, 1, "StateValues", arguments);
136   }
137   Operator* FrameState(BailoutId ast_id) {
138     return new (zone_) Operator1<BailoutId>(
139         IrOpcode::kFrameState, Operator::kPure, 3, 1, "FrameState", ast_id);
140   }
141   Operator* Call(CallDescriptor* descriptor) {
142     return new (zone_) CallOperator(descriptor, "Call");
143   }
144   Operator* Projection(int index) {
145     return new (zone_) Operator1<int>(IrOpcode::kProjection, Operator::kPure, 1,
146                                       1, "Projection", index);
147   }
148
149  private:
150   Zone* zone_;
151 };
152
153
154 template <typename T>
155 struct CommonOperatorTraits {
156   static inline bool Equals(T a, T b);
157   static inline bool HasValue(Operator* op);
158   static inline T ValueOf(Operator* op);
159 };
160
161 template <>
162 struct CommonOperatorTraits<int32_t> {
163   static inline bool Equals(int32_t a, int32_t b) { return a == b; }
164   static inline bool HasValue(Operator* op) {
165     return op->opcode() == IrOpcode::kInt32Constant ||
166            op->opcode() == IrOpcode::kNumberConstant;
167   }
168   static inline int32_t ValueOf(Operator* op) {
169     if (op->opcode() == IrOpcode::kNumberConstant) {
170       // TODO(titzer): cache the converted int32 value in NumberConstant.
171       return FastD2I(reinterpret_cast<Operator1<double>*>(op)->parameter());
172     }
173     CHECK_EQ(IrOpcode::kInt32Constant, op->opcode());
174     return static_cast<Operator1<int32_t>*>(op)->parameter();
175   }
176 };
177
178 template <>
179 struct CommonOperatorTraits<uint32_t> {
180   static inline bool Equals(uint32_t a, uint32_t b) { return a == b; }
181   static inline bool HasValue(Operator* op) {
182     return CommonOperatorTraits<int32_t>::HasValue(op);
183   }
184   static inline uint32_t ValueOf(Operator* op) {
185     if (op->opcode() == IrOpcode::kNumberConstant) {
186       // TODO(titzer): cache the converted uint32 value in NumberConstant.
187       return FastD2UI(reinterpret_cast<Operator1<double>*>(op)->parameter());
188     }
189     return static_cast<uint32_t>(CommonOperatorTraits<int32_t>::ValueOf(op));
190   }
191 };
192
193 template <>
194 struct CommonOperatorTraits<int64_t> {
195   static inline bool Equals(int64_t a, int64_t b) { return a == b; }
196   static inline bool HasValue(Operator* op) {
197     return op->opcode() == IrOpcode::kInt32Constant ||
198            op->opcode() == IrOpcode::kInt64Constant ||
199            op->opcode() == IrOpcode::kNumberConstant;
200   }
201   static inline int64_t ValueOf(Operator* op) {
202     if (op->opcode() == IrOpcode::kInt32Constant) {
203       return static_cast<int64_t>(CommonOperatorTraits<int32_t>::ValueOf(op));
204     }
205     CHECK_EQ(IrOpcode::kInt64Constant, op->opcode());
206     return static_cast<Operator1<int64_t>*>(op)->parameter();
207   }
208 };
209
210 template <>
211 struct CommonOperatorTraits<uint64_t> {
212   static inline bool Equals(uint64_t a, uint64_t b) { return a == b; }
213   static inline bool HasValue(Operator* op) {
214     return CommonOperatorTraits<int64_t>::HasValue(op);
215   }
216   static inline uint64_t ValueOf(Operator* op) {
217     return static_cast<uint64_t>(CommonOperatorTraits<int64_t>::ValueOf(op));
218   }
219 };
220
221 template <>
222 struct CommonOperatorTraits<double> {
223   static inline bool Equals(double a, double b) {
224     return DoubleRepresentation(a).bits == DoubleRepresentation(b).bits;
225   }
226   static inline bool HasValue(Operator* op) {
227     return op->opcode() == IrOpcode::kFloat64Constant ||
228            op->opcode() == IrOpcode::kInt32Constant ||
229            op->opcode() == IrOpcode::kNumberConstant;
230   }
231   static inline double ValueOf(Operator* op) {
232     if (op->opcode() == IrOpcode::kFloat64Constant ||
233         op->opcode() == IrOpcode::kNumberConstant) {
234       return reinterpret_cast<Operator1<double>*>(op)->parameter();
235     }
236     return static_cast<double>(CommonOperatorTraits<int32_t>::ValueOf(op));
237   }
238 };
239
240 template <>
241 struct CommonOperatorTraits<ExternalReference> {
242   static inline bool Equals(ExternalReference a, ExternalReference b) {
243     return a == b;
244   }
245   static inline bool HasValue(Operator* op) {
246     return op->opcode() == IrOpcode::kExternalConstant;
247   }
248   static inline ExternalReference ValueOf(Operator* op) {
249     CHECK_EQ(IrOpcode::kExternalConstant, op->opcode());
250     return static_cast<Operator1<ExternalReference>*>(op)->parameter();
251   }
252 };
253
254 template <typename T>
255 struct CommonOperatorTraits<PrintableUnique<T> > {
256   static inline bool HasValue(Operator* op) {
257     return op->opcode() == IrOpcode::kHeapConstant;
258   }
259   static inline PrintableUnique<T> ValueOf(Operator* op) {
260     CHECK_EQ(IrOpcode::kHeapConstant, op->opcode());
261     return static_cast<Operator1<PrintableUnique<T> >*>(op)->parameter();
262   }
263 };
264
265 template <typename T>
266 struct CommonOperatorTraits<Handle<T> > {
267   static inline bool HasValue(Operator* op) {
268     return CommonOperatorTraits<PrintableUnique<T> >::HasValue(op);
269   }
270   static inline Handle<T> ValueOf(Operator* op) {
271     return CommonOperatorTraits<PrintableUnique<T> >::ValueOf(op).handle();
272   }
273 };
274
275
276 template <typename T>
277 inline T ValueOf(Operator* op) {
278   return CommonOperatorTraits<T>::ValueOf(op);
279 }
280 }
281 }
282 }  // namespace v8::internal::compiler
283
284 #endif  // V8_COMPILER_COMMON_OPERATOR_H_