blob: c7abe9c96ecd3a5d890b7e5999728f7e41cd2c76 [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
159
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000160#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(NumberBitwiseOr, Operator::kCommutative, 2) \
172 V(NumberBitwiseXor, Operator::kCommutative, 2) \
173 V(NumberBitwiseAnd, Operator::kCommutative, 2) \
174 V(NumberShiftLeft, Operator::kNoProperties, 2) \
175 V(NumberShiftRight, Operator::kNoProperties, 2) \
176 V(NumberShiftRightLogical, Operator::kNoProperties, 2) \
177 V(NumberToInt32, Operator::kNoProperties, 1) \
178 V(NumberToUint32, Operator::kNoProperties, 1) \
179 V(NumberIsHoleNaN, Operator::kNoProperties, 1) \
180 V(PlainPrimitiveToNumber, Operator::kNoProperties, 1) \
181 V(ChangeTaggedToInt32, Operator::kNoProperties, 1) \
182 V(ChangeTaggedToUint32, Operator::kNoProperties, 1) \
183 V(ChangeTaggedToFloat64, Operator::kNoProperties, 1) \
184 V(ChangeInt32ToTagged, Operator::kNoProperties, 1) \
185 V(ChangeUint32ToTagged, Operator::kNoProperties, 1) \
186 V(ChangeFloat64ToTagged, Operator::kNoProperties, 1) \
187 V(ChangeBoolToBit, Operator::kNoProperties, 1) \
188 V(ChangeBitToBool, Operator::kNoProperties, 1) \
189 V(ObjectIsNumber, Operator::kNoProperties, 1) \
Ben Murdoch097c5b22016-05-18 11:27:45 +0100190 V(ObjectIsReceiver, Operator::kNoProperties, 1) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000191 V(ObjectIsSmi, Operator::kNoProperties, 1)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000192
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000193#define NO_THROW_OP_LIST(V) \
194 V(StringEqual, Operator::kCommutative, 2) \
195 V(StringLessThan, Operator::kNoThrow, 2) \
196 V(StringLessThanOrEqual, Operator::kNoThrow, 2)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000197
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000198struct SimplifiedOperatorGlobalCache final {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400199#define PURE(Name, properties, input_count) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000200 struct Name##Operator final : public Operator { \
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400201 Name##Operator() \
202 : Operator(IrOpcode::k##Name, Operator::kPure | properties, #Name, \
203 input_count, 0, 0, 1, 0, 0) {} \
204 }; \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000205 Name##Operator k##Name;
206 PURE_OP_LIST(PURE)
207#undef PURE
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400208
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000209#define NO_THROW(Name, properties, input_count) \
210 struct Name##Operator final : public Operator { \
211 Name##Operator() \
212 : Operator(IrOpcode::k##Name, Operator::kNoThrow | properties, #Name, \
213 input_count, 1, 1, 1, 1, 0) {} \
214 }; \
215 Name##Operator k##Name;
216 NO_THROW_OP_LIST(NO_THROW)
217#undef NO_THROW
218
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400219#define BUFFER_ACCESS(Type, type, TYPE, ctype, size) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000220 struct LoadBuffer##Type##Operator final : public Operator1<BufferAccess> { \
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400221 LoadBuffer##Type##Operator() \
222 : Operator1<BufferAccess>(IrOpcode::kLoadBuffer, \
223 Operator::kNoThrow | Operator::kNoWrite, \
224 "LoadBuffer", 3, 1, 1, 1, 1, 0, \
225 BufferAccess(kExternal##Type##Array)) {} \
226 }; \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000227 struct StoreBuffer##Type##Operator final : public Operator1<BufferAccess> { \
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400228 StoreBuffer##Type##Operator() \
229 : Operator1<BufferAccess>(IrOpcode::kStoreBuffer, \
230 Operator::kNoRead | Operator::kNoThrow, \
231 "StoreBuffer", 4, 1, 1, 0, 1, 0, \
232 BufferAccess(kExternal##Type##Array)) {} \
233 }; \
234 LoadBuffer##Type##Operator kLoadBuffer##Type; \
235 StoreBuffer##Type##Operator kStoreBuffer##Type;
236 TYPED_ARRAYS(BUFFER_ACCESS)
237#undef BUFFER_ACCESS
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000238};
239
240
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400241static base::LazyInstance<SimplifiedOperatorGlobalCache>::type kCache =
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000242 LAZY_INSTANCE_INITIALIZER;
243
244
245SimplifiedOperatorBuilder::SimplifiedOperatorBuilder(Zone* zone)
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400246 : cache_(kCache.Get()), zone_(zone) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000247
248
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000249#define GET_FROM_CACHE(Name, properties, input_count) \
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400250 const Operator* SimplifiedOperatorBuilder::Name() { return &cache_.k##Name; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000251PURE_OP_LIST(GET_FROM_CACHE)
252NO_THROW_OP_LIST(GET_FROM_CACHE)
253#undef GET_FROM_CACHE
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000254
255
256const Operator* SimplifiedOperatorBuilder::ReferenceEqual(Type* type) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400257 return new (zone()) Operator(IrOpcode::kReferenceEqual,
258 Operator::kCommutative | Operator::kPure,
259 "ReferenceEqual", 2, 0, 0, 1, 0, 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000260}
261
262
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000263const Operator* SimplifiedOperatorBuilder::Allocate(PretenureFlag pretenure) {
264 return new (zone())
265 Operator1<PretenureFlag>(IrOpcode::kAllocate, Operator::kNoThrow,
266 "Allocate", 1, 1, 1, 1, 1, 0, pretenure);
267}
268
269
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400270const Operator* SimplifiedOperatorBuilder::LoadBuffer(BufferAccess access) {
271 switch (access.external_array_type()) {
272#define LOAD_BUFFER(Type, type, TYPE, ctype, size) \
273 case kExternal##Type##Array: \
274 return &cache_.kLoadBuffer##Type;
275 TYPED_ARRAYS(LOAD_BUFFER)
276#undef LOAD_BUFFER
277 }
278 UNREACHABLE();
279 return nullptr;
280}
281
282
283const Operator* SimplifiedOperatorBuilder::StoreBuffer(BufferAccess access) {
284 switch (access.external_array_type()) {
285#define STORE_BUFFER(Type, type, TYPE, ctype, size) \
286 case kExternal##Type##Array: \
287 return &cache_.kStoreBuffer##Type;
288 TYPED_ARRAYS(STORE_BUFFER)
289#undef STORE_BUFFER
290 }
291 UNREACHABLE();
292 return nullptr;
293}
294
295
296#define ACCESS_OP_LIST(V) \
297 V(LoadField, FieldAccess, Operator::kNoWrite, 1, 1, 1) \
298 V(StoreField, FieldAccess, Operator::kNoRead, 2, 1, 0) \
299 V(LoadElement, ElementAccess, Operator::kNoWrite, 2, 1, 1) \
300 V(StoreElement, ElementAccess, Operator::kNoRead, 3, 1, 0)
301
302
303#define ACCESS(Name, Type, properties, value_input_count, control_input_count, \
304 output_count) \
305 const Operator* SimplifiedOperatorBuilder::Name(const Type& access) { \
306 return new (zone()) \
307 Operator1<Type>(IrOpcode::k##Name, Operator::kNoThrow | properties, \
308 #Name, value_input_count, 1, control_input_count, \
309 output_count, 1, 0, access); \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000310 }
311ACCESS_OP_LIST(ACCESS)
312#undef ACCESS
313
314} // namespace compiler
315} // namespace internal
316} // namespace v8