blob: 9d88d123015f1c28a9154ec40bbe5942bde08a4b [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"
10#include "src/types-inl.h"
11
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:
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
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 Murdochb8a8cc12014-11-26 15:28:44 +0000160#define PURE_OP_LIST(V) \
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400161 V(AnyToBoolean, Operator::kNoProperties, 1) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000162 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(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) \
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400185 V(ChangeBitToBool, Operator::kNoProperties, 1) \
186 V(ObjectIsSmi, Operator::kNoProperties, 1) \
187 V(ObjectIsNonNegativeSmi, Operator::kNoProperties, 1)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000188
189
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400190struct 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 }; \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000197 Name##Operator k##Name;
198 PURE_OP_LIST(PURE)
199#undef PURE
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400200
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
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000220};
221
222
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400223static base::LazyInstance<SimplifiedOperatorGlobalCache>::type kCache =
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000224 LAZY_INSTANCE_INITIALIZER;
225
226
227SimplifiedOperatorBuilder::SimplifiedOperatorBuilder(Zone* zone)
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400228 : cache_(kCache.Get()), zone_(zone) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000229
230
231#define PURE(Name, properties, input_count) \
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400232 const Operator* SimplifiedOperatorBuilder::Name() { return &cache_.k##Name; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000233PURE_OP_LIST(PURE)
234#undef PURE
235
236
237const Operator* SimplifiedOperatorBuilder::ReferenceEqual(Type* type) {
238 // TODO(titzer): What about the type parameter?
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400239 return new (zone()) Operator(IrOpcode::kReferenceEqual,
240 Operator::kCommutative | Operator::kPure,
241 "ReferenceEqual", 2, 0, 0, 1, 0, 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000242}
243
244
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400245const 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
258const 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); \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000285 }
286ACCESS_OP_LIST(ACCESS)
287#undef ACCESS
288
289} // namespace compiler
290} // namespace internal
291} // namespace v8