e1e8c30aad64a1aac99ebb45d1db8d35b00ff595
[platform/upstream/nodejs.git] / deps / v8 / src / compiler / simplified-operator.cc
1 // Copyright 2012 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/simplified-operator.h"
6
7 #include "src/base/lazy-instance.h"
8 #include "src/compiler/opcodes.h"
9 #include "src/compiler/operator.h"
10 #include "src/types-inl.h"
11
12 namespace v8 {
13 namespace internal {
14 namespace compiler {
15
16 std::ostream& operator<<(std::ostream& os, BaseTaggedness base_taggedness) {
17   switch (base_taggedness) {
18     case kUntaggedBase:
19       return os << "untagged base";
20     case kTaggedBase:
21       return os << "tagged base";
22   }
23   UNREACHABLE();
24   return os;
25 }
26
27
28 MachineType BufferAccess::machine_type() const {
29   switch (external_array_type_) {
30     case kExternalUint8Array:
31     case kExternalUint8ClampedArray:
32       return kMachUint8;
33     case kExternalInt8Array:
34       return kMachInt8;
35     case kExternalUint16Array:
36       return kMachUint16;
37     case kExternalInt16Array:
38       return kMachInt16;
39     case kExternalUint32Array:
40       return kMachUint32;
41     case kExternalInt32Array:
42       return kMachInt32;
43     case kExternalFloat32Array:
44       return kMachFloat32;
45     case kExternalFloat64Array:
46       return kMachFloat64;
47   }
48   UNREACHABLE();
49   return kMachNone;
50 }
51
52
53 bool operator==(BufferAccess lhs, BufferAccess rhs) {
54   return lhs.external_array_type() == rhs.external_array_type();
55 }
56
57
58 bool operator!=(BufferAccess lhs, BufferAccess rhs) { return !(lhs == rhs); }
59
60
61 size_t hash_value(BufferAccess access) {
62   return base::hash<ExternalArrayType>()(access.external_array_type());
63 }
64
65
66 std::ostream& operator<<(std::ostream& os, BufferAccess access) {
67   switch (access.external_array_type()) {
68 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
69   case kExternal##Type##Array:                          \
70     return os << #Type;
71     TYPED_ARRAYS(TYPED_ARRAY_CASE)
72 #undef TYPED_ARRAY_CASE
73   }
74   UNREACHABLE();
75   return os;
76 }
77
78
79 BufferAccess const BufferAccessOf(const Operator* op) {
80   DCHECK(op->opcode() == IrOpcode::kLoadBuffer ||
81          op->opcode() == IrOpcode::kStoreBuffer);
82   return OpParameter<BufferAccess>(op);
83 }
84
85
86 bool operator==(FieldAccess const& lhs, FieldAccess const& rhs) {
87   return lhs.base_is_tagged == rhs.base_is_tagged && lhs.offset == rhs.offset &&
88          lhs.machine_type == rhs.machine_type;
89 }
90
91
92 bool operator!=(FieldAccess const& lhs, FieldAccess const& rhs) {
93   return !(lhs == rhs);
94 }
95
96
97 size_t hash_value(FieldAccess const& access) {
98   return base::hash_combine(access.base_is_tagged, access.offset,
99                             access.machine_type);
100 }
101
102
103 std::ostream& operator<<(std::ostream& os, FieldAccess const& access) {
104   os << "[" << access.base_is_tagged << ", " << access.offset << ", ";
105 #ifdef OBJECT_PRINT
106   Handle<Name> name;
107   if (access.name.ToHandle(&name)) {
108     name->Print(os);
109     os << ", ";
110   }
111 #endif
112   access.type->PrintTo(os);
113   os << ", " << access.machine_type << "]";
114   return os;
115 }
116
117
118 bool operator==(ElementAccess const& lhs, ElementAccess const& rhs) {
119   return lhs.base_is_tagged == rhs.base_is_tagged &&
120          lhs.header_size == rhs.header_size &&
121          lhs.machine_type == rhs.machine_type;
122 }
123
124
125 bool operator!=(ElementAccess const& lhs, ElementAccess const& rhs) {
126   return !(lhs == rhs);
127 }
128
129
130 size_t hash_value(ElementAccess const& access) {
131   return base::hash_combine(access.base_is_tagged, access.header_size,
132                             access.machine_type);
133 }
134
135
136 std::ostream& operator<<(std::ostream& os, ElementAccess const& access) {
137   os << access.base_is_tagged << ", " << access.header_size << ", ";
138   access.type->PrintTo(os);
139   os << ", " << access.machine_type;
140   return os;
141 }
142
143
144 const FieldAccess& FieldAccessOf(const Operator* op) {
145   DCHECK_NOT_NULL(op);
146   DCHECK(op->opcode() == IrOpcode::kLoadField ||
147          op->opcode() == IrOpcode::kStoreField);
148   return OpParameter<FieldAccess>(op);
149 }
150
151
152 const ElementAccess& ElementAccessOf(const Operator* op) {
153   DCHECK_NOT_NULL(op);
154   DCHECK(op->opcode() == IrOpcode::kLoadElement ||
155          op->opcode() == IrOpcode::kStoreElement);
156   return OpParameter<ElementAccess>(op);
157 }
158
159
160 #define PURE_OP_LIST(V)                                 \
161   V(AnyToBoolean, Operator::kNoProperties, 1)           \
162   V(BooleanNot, Operator::kNoProperties, 1)             \
163   V(BooleanToNumber, Operator::kNoProperties, 1)        \
164   V(NumberEqual, Operator::kCommutative, 2)             \
165   V(NumberLessThan, Operator::kNoProperties, 2)         \
166   V(NumberLessThanOrEqual, Operator::kNoProperties, 2)  \
167   V(NumberAdd, Operator::kCommutative, 2)               \
168   V(NumberSubtract, Operator::kNoProperties, 2)         \
169   V(NumberMultiply, Operator::kCommutative, 2)          \
170   V(NumberDivide, Operator::kNoProperties, 2)           \
171   V(NumberModulus, Operator::kNoProperties, 2)          \
172   V(NumberToInt32, Operator::kNoProperties, 1)          \
173   V(NumberToUint32, Operator::kNoProperties, 1)         \
174   V(PlainPrimitiveToNumber, Operator::kNoProperties, 1) \
175   V(StringEqual, Operator::kCommutative, 2)             \
176   V(StringLessThan, Operator::kNoProperties, 2)         \
177   V(StringLessThanOrEqual, Operator::kNoProperties, 2)  \
178   V(StringAdd, Operator::kNoProperties, 2)              \
179   V(ChangeTaggedToInt32, Operator::kNoProperties, 1)    \
180   V(ChangeTaggedToUint32, Operator::kNoProperties, 1)   \
181   V(ChangeTaggedToFloat64, Operator::kNoProperties, 1)  \
182   V(ChangeInt32ToTagged, Operator::kNoProperties, 1)    \
183   V(ChangeUint32ToTagged, Operator::kNoProperties, 1)   \
184   V(ChangeFloat64ToTagged, Operator::kNoProperties, 1)  \
185   V(ChangeBoolToBit, Operator::kNoProperties, 1)        \
186   V(ChangeBitToBool, Operator::kNoProperties, 1)        \
187   V(ObjectIsSmi, Operator::kNoProperties, 1)            \
188   V(ObjectIsNonNegativeSmi, Operator::kNoProperties, 1)
189
190
191 struct SimplifiedOperatorGlobalCache FINAL {
192 #define PURE(Name, properties, input_count)                                \
193   struct Name##Operator FINAL : public Operator {                          \
194     Name##Operator()                                                       \
195         : Operator(IrOpcode::k##Name, Operator::kPure | properties, #Name, \
196                    input_count, 0, 0, 1, 0, 0) {}                          \
197   };                                                                       \
198   Name##Operator k##Name;
199   PURE_OP_LIST(PURE)
200 #undef PURE
201
202 #define BUFFER_ACCESS(Type, type, TYPE, ctype, size)                          \
203   struct LoadBuffer##Type##Operator FINAL : public Operator1<BufferAccess> {  \
204     LoadBuffer##Type##Operator()                                              \
205         : Operator1<BufferAccess>(IrOpcode::kLoadBuffer,                      \
206                                   Operator::kNoThrow | Operator::kNoWrite,    \
207                                   "LoadBuffer", 3, 1, 1, 1, 1, 0,             \
208                                   BufferAccess(kExternal##Type##Array)) {}    \
209   };                                                                          \
210   struct StoreBuffer##Type##Operator FINAL : public Operator1<BufferAccess> { \
211     StoreBuffer##Type##Operator()                                             \
212         : Operator1<BufferAccess>(IrOpcode::kStoreBuffer,                     \
213                                   Operator::kNoRead | Operator::kNoThrow,     \
214                                   "StoreBuffer", 4, 1, 1, 0, 1, 0,            \
215                                   BufferAccess(kExternal##Type##Array)) {}    \
216   };                                                                          \
217   LoadBuffer##Type##Operator kLoadBuffer##Type;                               \
218   StoreBuffer##Type##Operator kStoreBuffer##Type;
219   TYPED_ARRAYS(BUFFER_ACCESS)
220 #undef BUFFER_ACCESS
221 };
222
223
224 static base::LazyInstance<SimplifiedOperatorGlobalCache>::type kCache =
225     LAZY_INSTANCE_INITIALIZER;
226
227
228 SimplifiedOperatorBuilder::SimplifiedOperatorBuilder(Zone* zone)
229     : cache_(kCache.Get()), zone_(zone) {}
230
231
232 #define PURE(Name, properties, input_count) \
233   const Operator* SimplifiedOperatorBuilder::Name() { return &cache_.k##Name; }
234 PURE_OP_LIST(PURE)
235 #undef PURE
236
237
238 const Operator* SimplifiedOperatorBuilder::ReferenceEqual(Type* type) {
239   // TODO(titzer): What about the type parameter?
240   return new (zone()) Operator(IrOpcode::kReferenceEqual,
241                                Operator::kCommutative | Operator::kPure,
242                                "ReferenceEqual", 2, 0, 0, 1, 0, 0);
243 }
244
245
246 const Operator* SimplifiedOperatorBuilder::LoadBuffer(BufferAccess access) {
247   switch (access.external_array_type()) {
248 #define LOAD_BUFFER(Type, type, TYPE, ctype, size) \
249   case kExternal##Type##Array:                     \
250     return &cache_.kLoadBuffer##Type;
251     TYPED_ARRAYS(LOAD_BUFFER)
252 #undef LOAD_BUFFER
253   }
254   UNREACHABLE();
255   return nullptr;
256 }
257
258
259 const Operator* SimplifiedOperatorBuilder::StoreBuffer(BufferAccess access) {
260   switch (access.external_array_type()) {
261 #define STORE_BUFFER(Type, type, TYPE, ctype, size) \
262   case kExternal##Type##Array:                      \
263     return &cache_.kStoreBuffer##Type;
264     TYPED_ARRAYS(STORE_BUFFER)
265 #undef STORE_BUFFER
266   }
267   UNREACHABLE();
268   return nullptr;
269 }
270
271
272 #define ACCESS_OP_LIST(V)                                    \
273   V(LoadField, FieldAccess, Operator::kNoWrite, 1, 1, 1)     \
274   V(StoreField, FieldAccess, Operator::kNoRead, 2, 1, 0)     \
275   V(LoadElement, ElementAccess, Operator::kNoWrite, 2, 1, 1) \
276   V(StoreElement, ElementAccess, Operator::kNoRead, 3, 1, 0)
277
278
279 #define ACCESS(Name, Type, properties, value_input_count, control_input_count, \
280                output_count)                                                   \
281   const Operator* SimplifiedOperatorBuilder::Name(const Type& access) {        \
282     return new (zone())                                                        \
283         Operator1<Type>(IrOpcode::k##Name, Operator::kNoThrow | properties,    \
284                         #Name, value_input_count, 1, control_input_count,      \
285                         output_count, 1, 0, access);                           \
286   }
287 ACCESS_OP_LIST(ACCESS)
288 #undef ACCESS
289
290 }  // namespace compiler
291 }  // namespace internal
292 }  // namespace v8