blob: daa9501b8ca25da632f6cc851a03569d56ed3f15 [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// 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"
Ben Murdoch097c5b22016-05-18 11:27:45 +010010#include "src/types.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011
12namespace v8 {
13namespace internal {
14namespace compiler {
15
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016std::ostream& operator<<(std::ostream& os, BaseTaggedness base_taggedness) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017 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
Emily Bernierd0a1eb72015-03-24 16:35:39 -040028MachineType BufferAccess::machine_type() const {
29 switch (external_array_type_) {
30 case kExternalUint8Array:
31 case kExternalUint8ClampedArray:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000032 return MachineType::Uint8();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040033 case kExternalInt8Array:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000034 return MachineType::Int8();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040035 case kExternalUint16Array:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000036 return MachineType::Uint16();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040037 case kExternalInt16Array:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000038 return MachineType::Int16();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040039 case kExternalUint32Array:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000040 return MachineType::Uint32();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040041 case kExternalInt32Array:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000042 return MachineType::Int32();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040043 case kExternalFloat32Array:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000044 return MachineType::Float32();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040045 case kExternalFloat64Array:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000046 return MachineType::Float64();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040047 }
48 UNREACHABLE();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000049 return MachineType::None();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040050}
51
52
53bool operator==(BufferAccess lhs, BufferAccess rhs) {
54 return lhs.external_array_type() == rhs.external_array_type();
55}
56
57
58bool operator!=(BufferAccess lhs, BufferAccess rhs) { return !(lhs == rhs); }
59
60
61size_t hash_value(BufferAccess access) {
62 return base::hash<ExternalArrayType>()(access.external_array_type());
63}
64
65
66std::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
79BufferAccess const BufferAccessOf(const Operator* op) {
80 DCHECK(op->opcode() == IrOpcode::kLoadBuffer ||
81 op->opcode() == IrOpcode::kStoreBuffer);
82 return OpParameter<BufferAccess>(op);
83}
84
85
86bool 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
92bool operator!=(FieldAccess const& lhs, FieldAccess const& rhs) {
93 return !(lhs == rhs);
94}
95
96
97size_t hash_value(FieldAccess const& access) {
98 return base::hash_combine(access.base_is_tagged, access.offset,
99 access.machine_type);
100}
101
102
103std::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
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000118bool operator==(ElementAccess const& lhs, ElementAccess const& rhs) {
119 return lhs.base_is_tagged == rhs.base_is_tagged &&
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400120 lhs.header_size == rhs.header_size &&
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000121 lhs.machine_type == rhs.machine_type;
122}
123
124
125bool operator!=(ElementAccess const& lhs, ElementAccess const& rhs) {
126 return !(lhs == rhs);
127}
128
129
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400130size_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
136std::ostream& operator<<(std::ostream& os, ElementAccess const& access) {
137 os << access.base_is_tagged << ", " << access.header_size << ", ";
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000138 access.type->PrintTo(os);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400139 os << ", " << access.machine_type;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000140 return os;
141}
142
143
144const 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
152const 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
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000159#define PURE_OP_LIST(V) \
160 V(BooleanNot, Operator::kNoProperties, 1) \
161 V(BooleanToNumber, Operator::kNoProperties, 1) \
162 V(NumberEqual, Operator::kCommutative, 2) \
163 V(NumberLessThan, Operator::kNoProperties, 2) \
164 V(NumberLessThanOrEqual, Operator::kNoProperties, 2) \
165 V(NumberAdd, Operator::kCommutative, 2) \
166 V(NumberSubtract, Operator::kNoProperties, 2) \
167 V(NumberMultiply, Operator::kCommutative, 2) \
168 V(NumberDivide, Operator::kNoProperties, 2) \
169 V(NumberModulus, Operator::kNoProperties, 2) \
170 V(NumberBitwiseOr, Operator::kCommutative, 2) \
171 V(NumberBitwiseXor, Operator::kCommutative, 2) \
172 V(NumberBitwiseAnd, Operator::kCommutative, 2) \
173 V(NumberShiftLeft, Operator::kNoProperties, 2) \
174 V(NumberShiftRight, Operator::kNoProperties, 2) \
175 V(NumberShiftRightLogical, Operator::kNoProperties, 2) \
Ben Murdochda12d292016-06-02 14:46:10 +0100176 V(NumberImul, Operator::kNoProperties, 2) \
177 V(NumberClz32, Operator::kNoProperties, 1) \
178 V(NumberCeil, Operator::kNoProperties, 1) \
179 V(NumberFloor, Operator::kNoProperties, 1) \
180 V(NumberRound, Operator::kNoProperties, 1) \
181 V(NumberTrunc, Operator::kNoProperties, 1) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000182 V(NumberToInt32, Operator::kNoProperties, 1) \
183 V(NumberToUint32, Operator::kNoProperties, 1) \
184 V(NumberIsHoleNaN, Operator::kNoProperties, 1) \
185 V(PlainPrimitiveToNumber, Operator::kNoProperties, 1) \
Ben Murdochda12d292016-06-02 14:46:10 +0100186 V(StringToNumber, Operator::kNoProperties, 1) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000187 V(ChangeTaggedToInt32, Operator::kNoProperties, 1) \
188 V(ChangeTaggedToUint32, Operator::kNoProperties, 1) \
189 V(ChangeTaggedToFloat64, Operator::kNoProperties, 1) \
190 V(ChangeInt32ToTagged, Operator::kNoProperties, 1) \
191 V(ChangeUint32ToTagged, Operator::kNoProperties, 1) \
192 V(ChangeFloat64ToTagged, Operator::kNoProperties, 1) \
193 V(ChangeBoolToBit, Operator::kNoProperties, 1) \
194 V(ChangeBitToBool, Operator::kNoProperties, 1) \
195 V(ObjectIsNumber, Operator::kNoProperties, 1) \
Ben Murdoch097c5b22016-05-18 11:27:45 +0100196 V(ObjectIsReceiver, Operator::kNoProperties, 1) \
Ben Murdochda12d292016-06-02 14:46:10 +0100197 V(ObjectIsSmi, Operator::kNoProperties, 1) \
198 V(ObjectIsUndetectable, Operator::kNoProperties, 1)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000199
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000200#define NO_THROW_OP_LIST(V) \
201 V(StringEqual, Operator::kCommutative, 2) \
202 V(StringLessThan, Operator::kNoThrow, 2) \
203 V(StringLessThanOrEqual, Operator::kNoThrow, 2)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000204
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000205struct SimplifiedOperatorGlobalCache final {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400206#define PURE(Name, properties, input_count) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000207 struct Name##Operator final : public Operator { \
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400208 Name##Operator() \
209 : Operator(IrOpcode::k##Name, Operator::kPure | properties, #Name, \
210 input_count, 0, 0, 1, 0, 0) {} \
211 }; \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000212 Name##Operator k##Name;
213 PURE_OP_LIST(PURE)
214#undef PURE
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400215
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000216#define NO_THROW(Name, properties, input_count) \
217 struct Name##Operator final : public Operator { \
218 Name##Operator() \
219 : Operator(IrOpcode::k##Name, Operator::kNoThrow | properties, #Name, \
220 input_count, 1, 1, 1, 1, 0) {} \
221 }; \
222 Name##Operator k##Name;
223 NO_THROW_OP_LIST(NO_THROW)
224#undef NO_THROW
225
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400226#define BUFFER_ACCESS(Type, type, TYPE, ctype, size) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000227 struct LoadBuffer##Type##Operator final : public Operator1<BufferAccess> { \
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400228 LoadBuffer##Type##Operator() \
229 : Operator1<BufferAccess>(IrOpcode::kLoadBuffer, \
230 Operator::kNoThrow | Operator::kNoWrite, \
231 "LoadBuffer", 3, 1, 1, 1, 1, 0, \
232 BufferAccess(kExternal##Type##Array)) {} \
233 }; \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000234 struct StoreBuffer##Type##Operator final : public Operator1<BufferAccess> { \
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400235 StoreBuffer##Type##Operator() \
236 : Operator1<BufferAccess>(IrOpcode::kStoreBuffer, \
237 Operator::kNoRead | Operator::kNoThrow, \
238 "StoreBuffer", 4, 1, 1, 0, 1, 0, \
239 BufferAccess(kExternal##Type##Array)) {} \
240 }; \
241 LoadBuffer##Type##Operator kLoadBuffer##Type; \
242 StoreBuffer##Type##Operator kStoreBuffer##Type;
243 TYPED_ARRAYS(BUFFER_ACCESS)
244#undef BUFFER_ACCESS
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000245};
246
247
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400248static base::LazyInstance<SimplifiedOperatorGlobalCache>::type kCache =
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000249 LAZY_INSTANCE_INITIALIZER;
250
251
252SimplifiedOperatorBuilder::SimplifiedOperatorBuilder(Zone* zone)
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400253 : cache_(kCache.Get()), zone_(zone) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000254
255
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000256#define GET_FROM_CACHE(Name, properties, input_count) \
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400257 const Operator* SimplifiedOperatorBuilder::Name() { return &cache_.k##Name; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000258PURE_OP_LIST(GET_FROM_CACHE)
259NO_THROW_OP_LIST(GET_FROM_CACHE)
260#undef GET_FROM_CACHE
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000261
262
263const Operator* SimplifiedOperatorBuilder::ReferenceEqual(Type* type) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400264 return new (zone()) Operator(IrOpcode::kReferenceEqual,
265 Operator::kCommutative | Operator::kPure,
266 "ReferenceEqual", 2, 0, 0, 1, 0, 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000267}
268
269
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000270const Operator* SimplifiedOperatorBuilder::Allocate(PretenureFlag pretenure) {
271 return new (zone())
272 Operator1<PretenureFlag>(IrOpcode::kAllocate, Operator::kNoThrow,
273 "Allocate", 1, 1, 1, 1, 1, 0, pretenure);
274}
275
276
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400277const Operator* SimplifiedOperatorBuilder::LoadBuffer(BufferAccess access) {
278 switch (access.external_array_type()) {
279#define LOAD_BUFFER(Type, type, TYPE, ctype, size) \
280 case kExternal##Type##Array: \
281 return &cache_.kLoadBuffer##Type;
282 TYPED_ARRAYS(LOAD_BUFFER)
283#undef LOAD_BUFFER
284 }
285 UNREACHABLE();
286 return nullptr;
287}
288
289
290const Operator* SimplifiedOperatorBuilder::StoreBuffer(BufferAccess access) {
291 switch (access.external_array_type()) {
292#define STORE_BUFFER(Type, type, TYPE, ctype, size) \
293 case kExternal##Type##Array: \
294 return &cache_.kStoreBuffer##Type;
295 TYPED_ARRAYS(STORE_BUFFER)
296#undef STORE_BUFFER
297 }
298 UNREACHABLE();
299 return nullptr;
300}
301
302
303#define ACCESS_OP_LIST(V) \
304 V(LoadField, FieldAccess, Operator::kNoWrite, 1, 1, 1) \
305 V(StoreField, FieldAccess, Operator::kNoRead, 2, 1, 0) \
306 V(LoadElement, ElementAccess, Operator::kNoWrite, 2, 1, 1) \
307 V(StoreElement, ElementAccess, Operator::kNoRead, 3, 1, 0)
308
309
310#define ACCESS(Name, Type, properties, value_input_count, control_input_count, \
311 output_count) \
312 const Operator* SimplifiedOperatorBuilder::Name(const Type& access) { \
313 return new (zone()) \
314 Operator1<Type>(IrOpcode::k##Name, Operator::kNoThrow | properties, \
315 #Name, value_input_count, 1, control_input_count, \
316 output_count, 1, 0, access); \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000317 }
318ACCESS_OP_LIST(ACCESS)
319#undef ACCESS
320
321} // namespace compiler
322} // namespace internal
323} // namespace v8