| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/compiler/simplified-operator.h" | 5 #include "src/compiler/simplified-operator.h" |
| 6 | 6 |
| 7 #include "src/base/lazy-instance.h" | 7 #include "src/base/lazy-instance.h" |
| 8 #include "src/compiler/opcodes.h" | 8 #include "src/compiler/opcodes.h" |
| 9 #include "src/compiler/operator.h" | 9 #include "src/compiler/operator.h" |
| 10 #include "src/types-inl.h" | 10 #include "src/types-inl.h" |
| 11 | 11 |
| 12 namespace v8 { | 12 namespace v8 { |
| 13 namespace internal { | 13 namespace internal { |
| 14 namespace compiler { | 14 namespace compiler { |
| 15 | 15 |
| 16 std::ostream& operator<<(std::ostream& os, BaseTaggedness base_taggedness) { | 16 std::ostream& operator<<(std::ostream& os, BaseTaggedness base_taggedness) { |
| 17 switch (base_taggedness) { | 17 switch (base_taggedness) { |
| 18 case kUntaggedBase: | 18 case kUntaggedBase: |
| 19 return os << "untagged base"; | 19 return os << "untagged base"; |
| 20 case kTaggedBase: | 20 case kTaggedBase: |
| 21 return os << "tagged base"; | 21 return os << "tagged base"; |
| 22 } | 22 } |
| 23 UNREACHABLE(); | 23 UNREACHABLE(); |
| 24 return os; | 24 return os; |
| 25 } | 25 } |
| 26 | 26 |
| 27 | 27 |
| 28 MachineType BufferAccess::machine_type() const { |
| 29 switch (external_array_type_) { |
| 30 case kExternalUint8Array: |
| 31 return kMachUint8; |
| 32 case kExternalInt8Array: |
| 33 return kMachInt8; |
| 34 case kExternalUint16Array: |
| 35 return kMachUint16; |
| 36 case kExternalInt16Array: |
| 37 return kMachInt16; |
| 38 case kExternalUint32Array: |
| 39 return kMachUint32; |
| 40 case kExternalInt32Array: |
| 41 return kMachInt32; |
| 42 case kExternalFloat32Array: |
| 43 return kMachFloat32; |
| 44 case kExternalFloat64Array: |
| 45 return kMachFloat64; |
| 46 case kExternalUint8ClampedArray: |
| 47 break; |
| 48 } |
| 49 UNREACHABLE(); |
| 50 return kMachNone; |
| 51 } |
| 52 |
| 53 |
| 54 bool operator==(BufferAccess lhs, BufferAccess rhs) { |
| 55 return lhs.external_array_type() == rhs.external_array_type(); |
| 56 } |
| 57 |
| 58 |
| 59 bool operator!=(BufferAccess lhs, BufferAccess rhs) { return !(lhs == rhs); } |
| 60 |
| 61 |
| 62 size_t hash_value(BufferAccess access) { |
| 63 return base::hash<ExternalArrayType>()(access.external_array_type()); |
| 64 } |
| 65 |
| 66 |
| 67 std::ostream& operator<<(std::ostream& os, BufferAccess access) { |
| 68 switch (access.external_array_type()) { |
| 69 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ |
| 70 case kExternal##Type##Array: \ |
| 71 return os << #Type; |
| 72 TYPED_ARRAYS(TYPED_ARRAY_CASE) |
| 73 #undef TYPED_ARRAY_CASE |
| 74 } |
| 75 UNREACHABLE(); |
| 76 return os; |
| 77 } |
| 78 |
| 79 |
| 80 BufferAccess const BufferAccessOf(const Operator* op) { |
| 81 DCHECK(op->opcode() == IrOpcode::kLoadBuffer || |
| 82 op->opcode() == IrOpcode::kStoreBuffer); |
| 83 return OpParameter<BufferAccess>(op); |
| 84 } |
| 85 |
| 86 |
| 28 bool operator==(FieldAccess const& lhs, FieldAccess const& rhs) { | 87 bool operator==(FieldAccess const& lhs, FieldAccess const& rhs) { |
| 29 return lhs.base_is_tagged == rhs.base_is_tagged && lhs.offset == rhs.offset && | 88 return lhs.base_is_tagged == rhs.base_is_tagged && lhs.offset == rhs.offset && |
| 30 lhs.machine_type == rhs.machine_type; | 89 lhs.machine_type == rhs.machine_type; |
| 31 } | 90 } |
| 32 | 91 |
| 33 | 92 |
| 34 bool operator!=(FieldAccess const& lhs, FieldAccess const& rhs) { | 93 bool operator!=(FieldAccess const& lhs, FieldAccess const& rhs) { |
| 35 return !(lhs == rhs); | 94 return !(lhs == rhs); |
| 36 } | 95 } |
| 37 | 96 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 50 name->Print(os); | 109 name->Print(os); |
| 51 os << ", "; | 110 os << ", "; |
| 52 } | 111 } |
| 53 #endif | 112 #endif |
| 54 access.type->PrintTo(os); | 113 access.type->PrintTo(os); |
| 55 os << ", " << access.machine_type << "]"; | 114 os << ", " << access.machine_type << "]"; |
| 56 return os; | 115 return os; |
| 57 } | 116 } |
| 58 | 117 |
| 59 | 118 |
| 60 std::ostream& operator<<(std::ostream& os, BoundsCheckMode bounds_check_mode) { | |
| 61 switch (bounds_check_mode) { | |
| 62 case kNoBoundsCheck: | |
| 63 return os << "no bounds check"; | |
| 64 case kTypedArrayBoundsCheck: | |
| 65 return os << "ignore out of bounds"; | |
| 66 } | |
| 67 UNREACHABLE(); | |
| 68 return os; | |
| 69 } | |
| 70 | |
| 71 | |
| 72 bool operator==(ElementAccess const& lhs, ElementAccess const& rhs) { | 119 bool operator==(ElementAccess const& lhs, ElementAccess const& rhs) { |
| 73 return lhs.base_is_tagged == rhs.base_is_tagged && | 120 return lhs.base_is_tagged == rhs.base_is_tagged && |
| 74 lhs.header_size == rhs.header_size && | 121 lhs.header_size == rhs.header_size && |
| 75 lhs.machine_type == rhs.machine_type; | 122 lhs.machine_type == rhs.machine_type; |
| 76 } | 123 } |
| 77 | 124 |
| 78 | 125 |
| 79 bool operator!=(ElementAccess const& lhs, ElementAccess const& rhs) { | 126 bool operator!=(ElementAccess const& lhs, ElementAccess const& rhs) { |
| 80 return !(lhs == rhs); | 127 return !(lhs == rhs); |
| 81 } | 128 } |
| 82 | 129 |
| 83 | 130 |
| 84 size_t hash_value(ElementAccess const& access) { | 131 size_t hash_value(ElementAccess const& access) { |
| 85 return base::hash_combine(access.base_is_tagged, access.header_size, | 132 return base::hash_combine(access.base_is_tagged, access.header_size, |
| 86 access.machine_type); | 133 access.machine_type); |
| 87 } | 134 } |
| 88 | 135 |
| 89 | 136 |
| 90 std::ostream& operator<<(std::ostream& os, ElementAccess const& access) { | 137 std::ostream& operator<<(std::ostream& os, ElementAccess const& access) { |
| 91 os << access.base_is_tagged << ", " << access.header_size << ", "; | 138 os << access.base_is_tagged << ", " << access.header_size << ", "; |
| 92 access.type->PrintTo(os); | 139 access.type->PrintTo(os); |
| 93 os << ", " << access.machine_type << ", " << access.bounds_check; | 140 os << ", " << access.machine_type; |
| 94 return os; | 141 return os; |
| 95 } | 142 } |
| 96 | 143 |
| 97 | 144 |
| 98 const FieldAccess& FieldAccessOf(const Operator* op) { | 145 const FieldAccess& FieldAccessOf(const Operator* op) { |
| 99 DCHECK_NOT_NULL(op); | 146 DCHECK_NOT_NULL(op); |
| 100 DCHECK(op->opcode() == IrOpcode::kLoadField || | 147 DCHECK(op->opcode() == IrOpcode::kLoadField || |
| 101 op->opcode() == IrOpcode::kStoreField); | 148 op->opcode() == IrOpcode::kStoreField); |
| 102 return OpParameter<FieldAccess>(op); | 149 return OpParameter<FieldAccess>(op); |
| 103 } | 150 } |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 143 struct SimplifiedOperatorGlobalCache FINAL { | 190 struct SimplifiedOperatorGlobalCache FINAL { |
| 144 #define PURE(Name, properties, input_count) \ | 191 #define PURE(Name, properties, input_count) \ |
| 145 struct Name##Operator FINAL : public Operator { \ | 192 struct Name##Operator FINAL : public Operator { \ |
| 146 Name##Operator() \ | 193 Name##Operator() \ |
| 147 : Operator(IrOpcode::k##Name, Operator::kPure | properties, #Name, \ | 194 : Operator(IrOpcode::k##Name, Operator::kPure | properties, #Name, \ |
| 148 input_count, 0, 0, 1, 0, 0) {} \ | 195 input_count, 0, 0, 1, 0, 0) {} \ |
| 149 }; \ | 196 }; \ |
| 150 Name##Operator k##Name; | 197 Name##Operator k##Name; |
| 151 PURE_OP_LIST(PURE) | 198 PURE_OP_LIST(PURE) |
| 152 #undef 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 |
| 153 }; | 220 }; |
| 154 | 221 |
| 155 | 222 |
| 156 static base::LazyInstance<SimplifiedOperatorGlobalCache>::type kCache = | 223 static base::LazyInstance<SimplifiedOperatorGlobalCache>::type kCache = |
| 157 LAZY_INSTANCE_INITIALIZER; | 224 LAZY_INSTANCE_INITIALIZER; |
| 158 | 225 |
| 159 | 226 |
| 160 SimplifiedOperatorBuilder::SimplifiedOperatorBuilder(Zone* zone) | 227 SimplifiedOperatorBuilder::SimplifiedOperatorBuilder(Zone* zone) |
| 161 : cache_(kCache.Get()), zone_(zone) {} | 228 : cache_(kCache.Get()), zone_(zone) {} |
| 162 | 229 |
| 163 | 230 |
| 164 #define PURE(Name, properties, input_count) \ | 231 #define PURE(Name, properties, input_count) \ |
| 165 const Operator* SimplifiedOperatorBuilder::Name() { return &cache_.k##Name; } | 232 const Operator* SimplifiedOperatorBuilder::Name() { return &cache_.k##Name; } |
| 166 PURE_OP_LIST(PURE) | 233 PURE_OP_LIST(PURE) |
| 167 #undef PURE | 234 #undef PURE |
| 168 | 235 |
| 169 | 236 |
| 170 const Operator* SimplifiedOperatorBuilder::ReferenceEqual(Type* type) { | 237 const Operator* SimplifiedOperatorBuilder::ReferenceEqual(Type* type) { |
| 171 // TODO(titzer): What about the type parameter? | 238 // TODO(titzer): What about the type parameter? |
| 172 return new (zone()) Operator(IrOpcode::kReferenceEqual, | 239 return new (zone()) Operator(IrOpcode::kReferenceEqual, |
| 173 Operator::kCommutative | Operator::kPure, | 240 Operator::kCommutative | Operator::kPure, |
| 174 "ReferenceEqual", 2, 0, 0, 1, 0, 0); | 241 "ReferenceEqual", 2, 0, 0, 1, 0, 0); |
| 175 } | 242 } |
| 176 | 243 |
| 177 | 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 |
| 178 #define ACCESS_OP_LIST(V) \ | 271 #define ACCESS_OP_LIST(V) \ |
| 179 V(LoadField, FieldAccess, Operator::kNoWrite, 1, 1, 1) \ | 272 V(LoadField, FieldAccess, Operator::kNoWrite, 1, 1, 1) \ |
| 180 V(StoreField, FieldAccess, Operator::kNoRead, 2, 1, 0) \ | 273 V(StoreField, FieldAccess, Operator::kNoRead, 2, 1, 0) \ |
| 181 V(LoadElement, ElementAccess, Operator::kNoWrite, 3, 0, 1) \ | 274 V(LoadElement, ElementAccess, Operator::kNoWrite, 2, 1, 1) \ |
| 182 V(StoreElement, ElementAccess, Operator::kNoRead, 4, 1, 0) | 275 V(StoreElement, ElementAccess, Operator::kNoRead, 3, 1, 0) |
| 183 | 276 |
| 184 | 277 |
| 185 #define ACCESS(Name, Type, properties, value_input_count, control_input_count, \ | 278 #define ACCESS(Name, Type, properties, value_input_count, control_input_count, \ |
| 186 output_count) \ | 279 output_count) \ |
| 187 const Operator* SimplifiedOperatorBuilder::Name(const Type& access) { \ | 280 const Operator* SimplifiedOperatorBuilder::Name(const Type& access) { \ |
| 188 return new (zone()) \ | 281 return new (zone()) \ |
| 189 Operator1<Type>(IrOpcode::k##Name, Operator::kNoThrow | properties, \ | 282 Operator1<Type>(IrOpcode::k##Name, Operator::kNoThrow | properties, \ |
| 190 #Name, value_input_count, 1, control_input_count, \ | 283 #Name, value_input_count, 1, control_input_count, \ |
| 191 output_count, 1, 0, access); \ | 284 output_count, 1, 0, access); \ |
| 192 } | 285 } |
| 193 ACCESS_OP_LIST(ACCESS) | 286 ACCESS_OP_LIST(ACCESS) |
| 194 #undef ACCESS | 287 #undef ACCESS |
| 195 | 288 |
| 196 } // namespace compiler | 289 } // namespace compiler |
| 197 } // namespace internal | 290 } // namespace internal |
| 198 } // namespace v8 | 291 } // namespace v8 |
| OLD | NEW |