deps: update v8 to 4.3.61.21
[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(BooleanNot, Operator::kNoProperties, 1)             \
162   V(BooleanToNumber, Operator::kNoProperties, 1)        \
163   V(NumberEqual, Operator::kCommutative, 2)             \
164   V(NumberLessThan, Operator::kNoProperties, 2)         \
165   V(NumberLessThanOrEqual, Operator::kNoProperties, 2)  \
166   V(NumberAdd, Operator::kCommutative, 2)               \
167   V(NumberSubtract, Operator::kNoProperties, 2)         \
168   V(NumberMultiply, Operator::kCommutative, 2)          \
169   V(NumberDivide, Operator::kNoProperties, 2)           \
170   V(NumberModulus, Operator::kNoProperties, 2)          \
171   V(NumberToInt32, Operator::kNoProperties, 1)          \
172   V(NumberToUint32, Operator::kNoProperties, 1)         \
173   V(PlainPrimitiveToNumber, Operator::kNoProperties, 1) \
174   V(StringEqual, Operator::kCommutative, 2)             \
175   V(StringLessThan, Operator::kNoProperties, 2)         \
176   V(StringLessThanOrEqual, Operator::kNoProperties, 2)  \
177   V(StringAdd, Operator::kNoProperties, 2)              \
178   V(ChangeTaggedToInt32, Operator::kNoProperties, 1)    \
179   V(ChangeTaggedToUint32, Operator::kNoProperties, 1)   \
180   V(ChangeTaggedToFloat64, Operator::kNoProperties, 1)  \
181   V(ChangeInt32ToTagged, Operator::kNoProperties, 1)    \
182   V(ChangeUint32ToTagged, Operator::kNoProperties, 1)   \
183   V(ChangeFloat64ToTagged, Operator::kNoProperties, 1)  \
184   V(ChangeBoolToBit, Operator::kNoProperties, 1)        \
185   V(ChangeBitToBool, Operator::kNoProperties, 1)        \
186   V(ObjectIsSmi, Operator::kNoProperties, 1)            \
187   V(ObjectIsNonNegativeSmi, Operator::kNoProperties, 1)
188
189
190 struct SimplifiedOperatorGlobalCache FINAL {
191 #define PURE(Name, properties, input_count)                                \
192   struct Name##Operator FINAL : public Operator {                          \
193     Name##Operator()                                                       \
194         : Operator(IrOpcode::k##Name, Operator::kPure | properties, #Name, \
195                    input_count, 0, 0, 1, 0, 0) {}                          \
196   };                                                                       \
197   Name##Operator k##Name;
198   PURE_OP_LIST(PURE)
199 #undef PURE
200
201 #define BUFFER_ACCESS(Type, type, TYPE, ctype, size)                          \
202   struct LoadBuffer##Type##Operator FINAL : public Operator1<BufferAccess> {  \
203     LoadBuffer##Type##Operator()                                              \
204         : Operator1<BufferAccess>(IrOpcode::kLoadBuffer,                      \
205                                   Operator::kNoThrow | Operator::kNoWrite,    \
206                                   "LoadBuffer", 3, 1, 1, 1, 1, 0,             \
207                                   BufferAccess(kExternal##Type##Array)) {}    \
208   };                                                                          \
209   struct StoreBuffer##Type##Operator FINAL : public Operator1<BufferAccess> { \
210     StoreBuffer##Type##Operator()                                             \
211         : Operator1<BufferAccess>(IrOpcode::kStoreBuffer,                     \
212                                   Operator::kNoRead | Operator::kNoThrow,     \
213                                   "StoreBuffer", 4, 1, 1, 0, 1, 0,            \
214                                   BufferAccess(kExternal##Type##Array)) {}    \
215   };                                                                          \
216   LoadBuffer##Type##Operator kLoadBuffer##Type;                               \
217   StoreBuffer##Type##Operator kStoreBuffer##Type;
218   TYPED_ARRAYS(BUFFER_ACCESS)
219 #undef BUFFER_ACCESS
220 };
221
222
223 static base::LazyInstance<SimplifiedOperatorGlobalCache>::type kCache =
224     LAZY_INSTANCE_INITIALIZER;
225
226
227 SimplifiedOperatorBuilder::SimplifiedOperatorBuilder(Zone* zone)
228     : cache_(kCache.Get()), zone_(zone) {}
229
230
231 #define PURE(Name, properties, input_count) \
232   const Operator* SimplifiedOperatorBuilder::Name() { return &cache_.k##Name; }
233 PURE_OP_LIST(PURE)
234 #undef PURE
235
236
237 const Operator* SimplifiedOperatorBuilder::ReferenceEqual(Type* type) {
238   // TODO(titzer): What about the type parameter?
239   return new (zone()) Operator(IrOpcode::kReferenceEqual,
240                                Operator::kCommutative | Operator::kPure,
241                                "ReferenceEqual", 2, 0, 0, 1, 0, 0);
242 }
243
244
245 const Operator* SimplifiedOperatorBuilder::LoadBuffer(BufferAccess access) {
246   switch (access.external_array_type()) {
247 #define LOAD_BUFFER(Type, type, TYPE, ctype, size) \
248   case kExternal##Type##Array:                     \
249     return &cache_.kLoadBuffer##Type;
250     TYPED_ARRAYS(LOAD_BUFFER)
251 #undef LOAD_BUFFER
252   }
253   UNREACHABLE();
254   return nullptr;
255 }
256
257
258 const Operator* SimplifiedOperatorBuilder::StoreBuffer(BufferAccess access) {
259   switch (access.external_array_type()) {
260 #define STORE_BUFFER(Type, type, TYPE, ctype, size) \
261   case kExternal##Type##Array:                      \
262     return &cache_.kStoreBuffer##Type;
263     TYPED_ARRAYS(STORE_BUFFER)
264 #undef STORE_BUFFER
265   }
266   UNREACHABLE();
267   return nullptr;
268 }
269
270
271 #define ACCESS_OP_LIST(V)                                    \
272   V(LoadField, FieldAccess, Operator::kNoWrite, 1, 1, 1)     \
273   V(StoreField, FieldAccess, Operator::kNoRead, 2, 1, 0)     \
274   V(LoadElement, ElementAccess, Operator::kNoWrite, 2, 1, 1) \
275   V(StoreElement, ElementAccess, Operator::kNoRead, 3, 1, 0)
276
277
278 #define ACCESS(Name, Type, properties, value_input_count, control_input_count, \
279                output_count)                                                   \
280   const Operator* SimplifiedOperatorBuilder::Name(const Type& access) {        \
281     return new (zone())                                                        \
282         Operator1<Type>(IrOpcode::k##Name, Operator::kNoThrow | properties,    \
283                         #Name, value_input_count, 1, control_input_count,      \
284                         output_count, 1, 0, access);                           \
285   }
286 ACCESS_OP_LIST(ACCESS)
287 #undef ACCESS
288
289 }  // namespace compiler
290 }  // namespace internal
291 }  // namespace v8