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.
5 #include "src/compiler/simplified-operator.h"
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"
16 std::ostream& operator<<(std::ostream& os, BaseTaggedness base_taggedness) {
17 switch (base_taggedness) {
19 return os << "untagged base";
21 return os << "tagged base";
28 MachineType BufferAccess::machine_type() const {
29 switch (external_array_type_) {
30 case kExternalUint8Array:
31 case kExternalUint8ClampedArray:
33 case kExternalInt8Array:
35 case kExternalUint16Array:
37 case kExternalInt16Array:
39 case kExternalUint32Array:
41 case kExternalInt32Array:
43 case kExternalFloat32Array:
45 case kExternalFloat64Array:
53 bool operator==(BufferAccess lhs, BufferAccess rhs) {
54 return lhs.external_array_type() == rhs.external_array_type();
58 bool operator!=(BufferAccess lhs, BufferAccess rhs) { return !(lhs == rhs); }
61 size_t hash_value(BufferAccess access) {
62 return base::hash<ExternalArrayType>()(access.external_array_type());
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: \
71 TYPED_ARRAYS(TYPED_ARRAY_CASE)
72 #undef TYPED_ARRAY_CASE
79 BufferAccess const BufferAccessOf(const Operator* op) {
80 DCHECK(op->opcode() == IrOpcode::kLoadBuffer ||
81 op->opcode() == IrOpcode::kStoreBuffer);
82 return OpParameter<BufferAccess>(op);
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;
92 bool operator!=(FieldAccess const& lhs, FieldAccess const& rhs) {
97 size_t hash_value(FieldAccess const& access) {
98 return base::hash_combine(access.base_is_tagged, access.offset,
103 std::ostream& operator<<(std::ostream& os, FieldAccess const& access) {
104 os << "[" << access.base_is_tagged << ", " << access.offset << ", ";
107 if (access.name.ToHandle(&name)) {
112 access.type->PrintTo(os);
113 os << ", " << access.machine_type << "]";
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;
125 bool operator!=(ElementAccess const& lhs, ElementAccess const& rhs) {
126 return !(lhs == rhs);
130 size_t hash_value(ElementAccess const& access) {
131 return base::hash_combine(access.base_is_tagged, access.header_size,
132 access.machine_type);
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;
144 const FieldAccess& FieldAccessOf(const Operator* op) {
146 DCHECK(op->opcode() == IrOpcode::kLoadField ||
147 op->opcode() == IrOpcode::kStoreField);
148 return OpParameter<FieldAccess>(op);
152 const ElementAccess& ElementAccessOf(const Operator* op) {
154 DCHECK(op->opcode() == IrOpcode::kLoadElement ||
155 op->opcode() == IrOpcode::kStoreElement);
156 return OpParameter<ElementAccess>(op);
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)
190 struct SimplifiedOperatorGlobalCache FINAL {
191 #define PURE(Name, properties, input_count) \
192 struct Name##Operator FINAL : public Operator { \
194 : Operator(IrOpcode::k##Name, Operator::kPure | properties, #Name, \
195 input_count, 0, 0, 1, 0, 0) {} \
197 Name##Operator k##Name;
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)) {} \
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)) {} \
216 LoadBuffer##Type##Operator kLoadBuffer##Type; \
217 StoreBuffer##Type##Operator kStoreBuffer##Type;
218 TYPED_ARRAYS(BUFFER_ACCESS)
223 static base::LazyInstance<SimplifiedOperatorGlobalCache>::type kCache =
224 LAZY_INSTANCE_INITIALIZER;
227 SimplifiedOperatorBuilder::SimplifiedOperatorBuilder(Zone* zone)
228 : cache_(kCache.Get()), zone_(zone) {}
231 #define PURE(Name, properties, input_count) \
232 const Operator* SimplifiedOperatorBuilder::Name() { return &cache_.k##Name; }
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);
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)
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)
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)
278 #define ACCESS(Name, Type, properties, value_input_count, control_input_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); \
286 ACCESS_OP_LIST(ACCESS)
289 } // namespace compiler
290 } // namespace internal