| OLD | NEW |
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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 #ifndef V8_INTERPRETER_BYTECODE_TRAITS_H_ | 5 #ifndef V8_INTERPRETER_BYTECODE_TRAITS_H_ |
| 6 #define V8_INTERPRETER_BYTECODE_TRAITS_H_ | 6 #define V8_INTERPRETER_BYTECODE_TRAITS_H_ |
| 7 | 7 |
| 8 #include "src/interpreter/bytecodes.h" | 8 #include "src/interpreter/bytecodes.h" |
| 9 | 9 |
| 10 namespace v8 { | 10 namespace v8 { |
| (...skipping 23 matching lines...) Expand all Loading... |
| 34 }; | 34 }; |
| 35 | 35 |
| 36 #define DECLARE_OPERAND_TYPE_TRAITS(Name, InfoType) \ | 36 #define DECLARE_OPERAND_TYPE_TRAITS(Name, InfoType) \ |
| 37 template <> \ | 37 template <> \ |
| 38 struct OperandTraits<OperandType::k##Name> { \ | 38 struct OperandTraits<OperandType::k##Name> { \ |
| 39 typedef OperandTypeInfoTraits<InfoType> TypeInfo; \ | 39 typedef OperandTypeInfoTraits<InfoType> TypeInfo; \ |
| 40 }; | 40 }; |
| 41 OPERAND_TYPE_LIST(DECLARE_OPERAND_TYPE_TRAITS) | 41 OPERAND_TYPE_LIST(DECLARE_OPERAND_TYPE_TRAITS) |
| 42 #undef DECLARE_OPERAND_TYPE_TRAITS | 42 #undef DECLARE_OPERAND_TYPE_TRAITS |
| 43 | 43 |
| 44 template <OperandType operand_type, OperandScale operand_scale> |
| 45 struct OperandScaler { |
| 46 template <bool, OperandSize, OperandScale> |
| 47 struct Helper { |
| 48 static const int kSize = 0; |
| 49 }; |
| 50 template <OperandSize size, OperandScale scale> |
| 51 struct Helper<false, size, scale> { |
| 52 static const int kSize = static_cast<int>(size); |
| 53 }; |
| 54 template <OperandSize size, OperandScale scale> |
| 55 struct Helper<true, size, scale> { |
| 56 static const int kSize = static_cast<int>(size) * static_cast<int>(scale); |
| 57 }; |
| 58 |
| 59 static const int kSize = |
| 60 Helper<OperandTraits<operand_type>::TypeInfo::kIsScalable, |
| 61 OperandTraits<operand_type>::TypeInfo::kUnscaledSize, |
| 62 operand_scale>::kSize; |
| 63 static const OperandSize kOperandSize = static_cast<OperandSize>(kSize); |
| 64 }; |
| 65 |
| 44 template <OperandType> | 66 template <OperandType> |
| 45 struct RegisterOperandTraits { | 67 struct RegisterOperandTraits { |
| 46 static const int kIsRegisterOperand = 0; | 68 static const int kIsRegisterOperand = 0; |
| 47 }; | 69 }; |
| 48 | 70 |
| 49 #define DECLARE_REGISTER_OPERAND(Name, _) \ | 71 #define DECLARE_REGISTER_OPERAND(Name, _) \ |
| 50 template <> \ | 72 template <> \ |
| 51 struct RegisterOperandTraits<OperandType::k##Name> { \ | 73 struct RegisterOperandTraits<OperandType::k##Name> { \ |
| 52 static const int kIsRegisterOperand = 1; \ | 74 static const int kIsRegisterOperand = 1; \ |
| 53 }; | 75 }; |
| 54 REGISTER_OPERAND_TYPE_LIST(DECLARE_REGISTER_OPERAND) | 76 REGISTER_OPERAND_TYPE_LIST(DECLARE_REGISTER_OPERAND) |
| 55 #undef DECLARE_REGISTER_OPERAND | 77 #undef DECLARE_REGISTER_OPERAND |
| 56 | 78 |
| 57 template <AccumulatorUse, OperandType...> | 79 template <AccumulatorUse, OperandType...> |
| 58 struct BytecodeTraits {}; | 80 struct BytecodeTraits {}; |
| 59 | 81 |
| 60 template <AccumulatorUse accumulator_use, OperandType operand_0, | 82 template <AccumulatorUse accumulator_use, OperandType operand_0, |
| 61 OperandType operand_1, OperandType operand_2, OperandType operand_3> | 83 OperandType operand_1, OperandType operand_2, OperandType operand_3> |
| 62 struct BytecodeTraits<accumulator_use, operand_0, operand_1, operand_2, | 84 struct BytecodeTraits<accumulator_use, operand_0, operand_1, operand_2, |
| 63 operand_3> { | 85 operand_3> { |
| 64 static OperandType GetOperandType(int i) { | 86 static const OperandType* GetOperandTypes() { |
| 65 DCHECK(0 <= i && i < kOperandCount); | 87 static const OperandType operand_types[] = {operand_0, operand_1, operand_2, |
| 66 const OperandType kOperands[] = {operand_0, operand_1, operand_2, | 88 operand_3, OperandType::kNone}; |
| 67 operand_3}; | 89 return operand_types; |
| 68 return kOperands[i]; | 90 } |
| 91 |
| 92 static OperandSize GetOperandSize(int i, OperandScale operand_scale) { |
| 93 switch (operand_scale) { |
| 94 #define CASE(Name, _) \ |
| 95 case OperandScale::k##Name: { \ |
| 96 static const OperandSize kOperandSizes[] = { \ |
| 97 OperandScaler<operand_0, OperandScale::k##Name>::kOperandSize, \ |
| 98 OperandScaler<operand_1, OperandScale::k##Name>::kOperandSize, \ |
| 99 OperandScaler<operand_2, OperandScale::k##Name>::kOperandSize, \ |
| 100 OperandScaler<operand_3, OperandScale::k##Name>::kOperandSize, \ |
| 101 }; \ |
| 102 DCHECK_LT(static_cast<size_t>(i), arraysize(kOperandSizes)); \ |
| 103 return kOperandSizes[i]; \ |
| 104 } |
| 105 OPERAND_SCALE_LIST(CASE) |
| 106 #undef CASE |
| 107 } |
| 108 UNREACHABLE(); |
| 109 return OperandSize::kNone; |
| 69 } | 110 } |
| 70 | 111 |
| 71 template <OperandType ot> | 112 template <OperandType ot> |
| 72 static inline bool HasAnyOperandsOfType() { | 113 static inline bool HasAnyOperandsOfType() { |
| 73 return operand_0 == ot || operand_1 == ot || operand_2 == ot || | 114 return operand_0 == ot || operand_1 == ot || operand_2 == ot || |
| 74 operand_3 == ot; | 115 operand_3 == ot; |
| 75 } | 116 } |
| 76 | 117 |
| 77 static inline bool IsScalable() { | 118 static inline bool IsScalable() { |
| 78 return (OperandTraits<operand_0>::TypeInfo::kIsScalable | | 119 return (OperandTraits<operand_0>::TypeInfo::kIsScalable | |
| (...skipping 12 matching lines...) Expand all Loading... |
| 91 static const int kRegisterOperandBitmap = | 132 static const int kRegisterOperandBitmap = |
| 92 RegisterOperandTraits<operand_0>::kIsRegisterOperand + | 133 RegisterOperandTraits<operand_0>::kIsRegisterOperand + |
| 93 (RegisterOperandTraits<operand_1>::kIsRegisterOperand << 1) + | 134 (RegisterOperandTraits<operand_1>::kIsRegisterOperand << 1) + |
| 94 (RegisterOperandTraits<operand_2>::kIsRegisterOperand << 2) + | 135 (RegisterOperandTraits<operand_2>::kIsRegisterOperand << 2) + |
| 95 (RegisterOperandTraits<operand_3>::kIsRegisterOperand << 3); | 136 (RegisterOperandTraits<operand_3>::kIsRegisterOperand << 3); |
| 96 }; | 137 }; |
| 97 | 138 |
| 98 template <AccumulatorUse accumulator_use, OperandType operand_0, | 139 template <AccumulatorUse accumulator_use, OperandType operand_0, |
| 99 OperandType operand_1, OperandType operand_2> | 140 OperandType operand_1, OperandType operand_2> |
| 100 struct BytecodeTraits<accumulator_use, operand_0, operand_1, operand_2> { | 141 struct BytecodeTraits<accumulator_use, operand_0, operand_1, operand_2> { |
| 101 static inline OperandType GetOperandType(int i) { | 142 static const OperandType* GetOperandTypes() { |
| 102 DCHECK(0 <= i && i <= 2); | 143 static const OperandType operand_types[] = {operand_0, operand_1, operand_2, |
| 103 const OperandType kOperands[] = {operand_0, operand_1, operand_2}; | 144 OperandType::kNone}; |
| 104 return kOperands[i]; | 145 return operand_types; |
| 146 } |
| 147 |
| 148 static OperandSize GetOperandSize(int i, OperandScale operand_scale) { |
| 149 switch (operand_scale) { |
| 150 #define CASE(Name, _) \ |
| 151 case OperandScale::k##Name: { \ |
| 152 static const OperandSize kOperandSizes[] = { \ |
| 153 OperandScaler<operand_0, OperandScale::k##Name>::kOperandSize, \ |
| 154 OperandScaler<operand_1, OperandScale::k##Name>::kOperandSize, \ |
| 155 OperandScaler<operand_2, OperandScale::k##Name>::kOperandSize, \ |
| 156 }; \ |
| 157 DCHECK_LT(static_cast<size_t>(i), arraysize(kOperandSizes)); \ |
| 158 return kOperandSizes[i]; \ |
| 159 } |
| 160 OPERAND_SCALE_LIST(CASE) |
| 161 #undef CASE |
| 162 } |
| 163 UNREACHABLE(); |
| 164 return OperandSize::kNone; |
| 105 } | 165 } |
| 106 | 166 |
| 107 template <OperandType ot> | 167 template <OperandType ot> |
| 108 static inline bool HasAnyOperandsOfType() { | 168 static inline bool HasAnyOperandsOfType() { |
| 109 return operand_0 == ot || operand_1 == ot || operand_2 == ot; | 169 return operand_0 == ot || operand_1 == ot || operand_2 == ot; |
| 110 } | 170 } |
| 111 | 171 |
| 112 static inline bool IsScalable() { | 172 static inline bool IsScalable() { |
| 113 return (OperandTraits<operand_0>::TypeInfo::kIsScalable | | 173 return (OperandTraits<operand_0>::TypeInfo::kIsScalable | |
| 114 OperandTraits<operand_1>::TypeInfo::kIsScalable | | 174 OperandTraits<operand_1>::TypeInfo::kIsScalable | |
| 115 OperandTraits<operand_2>::TypeInfo::kIsScalable); | 175 OperandTraits<operand_2>::TypeInfo::kIsScalable); |
| 116 } | 176 } |
| 117 | 177 |
| 118 static const AccumulatorUse kAccumulatorUse = accumulator_use; | 178 static const AccumulatorUse kAccumulatorUse = accumulator_use; |
| 119 static const int kOperandCount = 3; | 179 static const int kOperandCount = 3; |
| 120 static const int kRegisterOperandCount = | 180 static const int kRegisterOperandCount = |
| 121 RegisterOperandTraits<operand_0>::kIsRegisterOperand + | 181 RegisterOperandTraits<operand_0>::kIsRegisterOperand + |
| 122 RegisterOperandTraits<operand_1>::kIsRegisterOperand + | 182 RegisterOperandTraits<operand_1>::kIsRegisterOperand + |
| 123 RegisterOperandTraits<operand_2>::kIsRegisterOperand; | 183 RegisterOperandTraits<operand_2>::kIsRegisterOperand; |
| 124 static const int kRegisterOperandBitmap = | 184 static const int kRegisterOperandBitmap = |
| 125 RegisterOperandTraits<operand_0>::kIsRegisterOperand + | 185 RegisterOperandTraits<operand_0>::kIsRegisterOperand + |
| 126 (RegisterOperandTraits<operand_1>::kIsRegisterOperand << 1) + | 186 (RegisterOperandTraits<operand_1>::kIsRegisterOperand << 1) + |
| 127 (RegisterOperandTraits<operand_2>::kIsRegisterOperand << 2); | 187 (RegisterOperandTraits<operand_2>::kIsRegisterOperand << 2); |
| 128 }; | 188 }; |
| 129 | 189 |
| 130 template <AccumulatorUse accumulator_use, OperandType operand_0, | 190 template <AccumulatorUse accumulator_use, OperandType operand_0, |
| 131 OperandType operand_1> | 191 OperandType operand_1> |
| 132 struct BytecodeTraits<accumulator_use, operand_0, operand_1> { | 192 struct BytecodeTraits<accumulator_use, operand_0, operand_1> { |
| 133 static inline OperandType GetOperandType(int i) { | 193 static const OperandType* GetOperandTypes() { |
| 134 DCHECK(0 <= i && i < kOperandCount); | 194 static const OperandType operand_types[] = {operand_0, operand_1, |
| 135 const OperandType kOperands[] = {operand_0, operand_1}; | 195 OperandType::kNone}; |
| 136 return kOperands[i]; | 196 return operand_types; |
| 197 } |
| 198 |
| 199 static OperandSize GetOperandSize(int i, OperandScale operand_scale) { |
| 200 switch (operand_scale) { |
| 201 #define CASE(Name, _) \ |
| 202 case OperandScale::k##Name: { \ |
| 203 static const OperandSize kOperandSizes[] = { \ |
| 204 OperandScaler<operand_0, OperandScale::k##Name>::kOperandSize, \ |
| 205 OperandScaler<operand_1, OperandScale::k##Name>::kOperandSize, \ |
| 206 }; \ |
| 207 DCHECK_LT(static_cast<size_t>(i), arraysize(kOperandSizes)); \ |
| 208 return kOperandSizes[i]; \ |
| 209 } |
| 210 OPERAND_SCALE_LIST(CASE) |
| 211 #undef CASE |
| 212 } |
| 213 UNREACHABLE(); |
| 214 return OperandSize::kNone; |
| 137 } | 215 } |
| 138 | 216 |
| 139 template <OperandType ot> | 217 template <OperandType ot> |
| 140 static inline bool HasAnyOperandsOfType() { | 218 static inline bool HasAnyOperandsOfType() { |
| 141 return operand_0 == ot || operand_1 == ot; | 219 return operand_0 == ot || operand_1 == ot; |
| 142 } | 220 } |
| 143 | 221 |
| 144 static inline bool IsScalable() { | 222 static inline bool IsScalable() { |
| 145 return (OperandTraits<operand_0>::TypeInfo::kIsScalable | | 223 return (OperandTraits<operand_0>::TypeInfo::kIsScalable | |
| 146 OperandTraits<operand_1>::TypeInfo::kIsScalable); | 224 OperandTraits<operand_1>::TypeInfo::kIsScalable); |
| 147 } | 225 } |
| 148 | 226 |
| 149 static const AccumulatorUse kAccumulatorUse = accumulator_use; | 227 static const AccumulatorUse kAccumulatorUse = accumulator_use; |
| 150 static const int kOperandCount = 2; | 228 static const int kOperandCount = 2; |
| 151 static const int kRegisterOperandCount = | 229 static const int kRegisterOperandCount = |
| 152 RegisterOperandTraits<operand_0>::kIsRegisterOperand + | 230 RegisterOperandTraits<operand_0>::kIsRegisterOperand + |
| 153 RegisterOperandTraits<operand_1>::kIsRegisterOperand; | 231 RegisterOperandTraits<operand_1>::kIsRegisterOperand; |
| 154 static const int kRegisterOperandBitmap = | 232 static const int kRegisterOperandBitmap = |
| 155 RegisterOperandTraits<operand_0>::kIsRegisterOperand + | 233 RegisterOperandTraits<operand_0>::kIsRegisterOperand + |
| 156 (RegisterOperandTraits<operand_1>::kIsRegisterOperand << 1); | 234 (RegisterOperandTraits<operand_1>::kIsRegisterOperand << 1); |
| 157 }; | 235 }; |
| 158 | 236 |
| 159 template <AccumulatorUse accumulator_use, OperandType operand_0> | 237 template <AccumulatorUse accumulator_use, OperandType operand_0> |
| 160 struct BytecodeTraits<accumulator_use, operand_0> { | 238 struct BytecodeTraits<accumulator_use, operand_0> { |
| 161 static inline OperandType GetOperandType(int i) { | 239 static const OperandType* GetOperandTypes() { |
| 162 DCHECK(i == 0); | 240 static const OperandType operand_types[] = {operand_0, OperandType::kNone}; |
| 163 return operand_0; | 241 return operand_types; |
| 242 } |
| 243 |
| 244 static OperandSize GetOperandSize(int i, OperandScale operand_scale) { |
| 245 switch (operand_scale) { |
| 246 #define CASE(Name, _) \ |
| 247 case OperandScale::k##Name: { \ |
| 248 static const OperandSize kOperandSizes[] = { \ |
| 249 OperandScaler<operand_0, OperandScale::k##Name>::kOperandSize, \ |
| 250 }; \ |
| 251 DCHECK_LT(static_cast<size_t>(i), arraysize(kOperandSizes)); \ |
| 252 return kOperandSizes[i]; \ |
| 253 } |
| 254 OPERAND_SCALE_LIST(CASE) |
| 255 #undef CASE |
| 256 } |
| 257 UNREACHABLE(); |
| 258 return OperandSize::kNone; |
| 164 } | 259 } |
| 165 | 260 |
| 166 template <OperandType ot> | 261 template <OperandType ot> |
| 167 static inline bool HasAnyOperandsOfType() { | 262 static inline bool HasAnyOperandsOfType() { |
| 168 return operand_0 == ot; | 263 return operand_0 == ot; |
| 169 } | 264 } |
| 170 | 265 |
| 171 static inline bool IsScalable() { | 266 static inline bool IsScalable() { |
| 172 return OperandTraits<operand_0>::TypeInfo::kIsScalable; | 267 return OperandTraits<operand_0>::TypeInfo::kIsScalable; |
| 173 } | 268 } |
| 174 | 269 |
| 175 static const AccumulatorUse kAccumulatorUse = accumulator_use; | 270 static const AccumulatorUse kAccumulatorUse = accumulator_use; |
| 176 static const int kOperandCount = 1; | 271 static const int kOperandCount = 1; |
| 177 static const int kRegisterOperandCount = | 272 static const int kRegisterOperandCount = |
| 178 RegisterOperandTraits<operand_0>::kIsRegisterOperand; | 273 RegisterOperandTraits<operand_0>::kIsRegisterOperand; |
| 179 static const int kRegisterOperandBitmap = | 274 static const int kRegisterOperandBitmap = |
| 180 RegisterOperandTraits<operand_0>::kIsRegisterOperand; | 275 RegisterOperandTraits<operand_0>::kIsRegisterOperand; |
| 181 }; | 276 }; |
| 182 | 277 |
| 183 template <AccumulatorUse accumulator_use> | 278 template <AccumulatorUse accumulator_use> |
| 184 struct BytecodeTraits<accumulator_use> { | 279 struct BytecodeTraits<accumulator_use> { |
| 185 static inline OperandType GetOperandType(int i) { | 280 static const OperandType* GetOperandTypes() { |
| 281 static const OperandType operand_types[] = {OperandType::kNone}; |
| 282 return operand_types; |
| 283 } |
| 284 |
| 285 static OperandSize GetOperandSize(int i, OperandScale operand_scale) { |
| 186 UNREACHABLE(); | 286 UNREACHABLE(); |
| 187 return OperandType::kNone; | 287 return OperandSize::kNone; |
| 188 } | 288 } |
| 189 | 289 |
| 190 template <OperandType ot> | 290 template <OperandType ot> |
| 191 static inline bool HasAnyOperandsOfType() { | 291 static inline bool HasAnyOperandsOfType() { |
| 192 return false; | 292 return false; |
| 193 } | 293 } |
| 194 | 294 |
| 195 static inline bool IsScalable() { return false; } | 295 static inline bool IsScalable() { return false; } |
| 196 | 296 |
| 197 static const AccumulatorUse kAccumulatorUse = accumulator_use; | 297 static const AccumulatorUse kAccumulatorUse = accumulator_use; |
| 198 static const int kOperandCount = 0; | 298 static const int kOperandCount = 0; |
| 199 static const int kRegisterOperandCount = 0; | 299 static const int kRegisterOperandCount = 0; |
| 200 static const int kRegisterOperandBitmap = 0; | 300 static const int kRegisterOperandBitmap = 0; |
| 201 }; | 301 }; |
| 202 | 302 |
| 203 template <bool> | |
| 204 struct OperandScaler { | |
| 205 static int Multiply(int size, int operand_scale) { return 0; } | |
| 206 }; | |
| 207 | |
| 208 template <> | |
| 209 struct OperandScaler<false> { | |
| 210 static int Multiply(int size, int operand_scale) { return size; } | |
| 211 }; | |
| 212 | |
| 213 template <> | |
| 214 struct OperandScaler<true> { | |
| 215 static int Multiply(int size, int operand_scale) { | |
| 216 return size * operand_scale; | |
| 217 } | |
| 218 }; | |
| 219 | |
| 220 static OperandSize ScaledOperandSize(OperandType operand_type, | 303 static OperandSize ScaledOperandSize(OperandType operand_type, |
| 221 OperandScale operand_scale) { | 304 OperandScale operand_scale) { |
| 305 STATIC_ASSERT(static_cast<int>(OperandScale::kQuadruple) == 4 && |
| 306 OperandScale::kLast == OperandScale::kQuadruple); |
| 307 int index = static_cast<int>(operand_scale) >> 1; |
| 222 switch (operand_type) { | 308 switch (operand_type) { |
| 223 #define CASE(Name, TypeInfo) \ | 309 #define CASE(Name, TypeInfo) \ |
| 224 case OperandType::k##Name: { \ | 310 case OperandType::k##Name: { \ |
| 225 OperandSize base_size = OperandTypeInfoTraits<TypeInfo>::kUnscaledSize; \ | 311 static const OperandSize kOperandSizes[] = { \ |
| 226 int size = \ | 312 OperandScaler<OperandType::k##Name, \ |
| 227 OperandScaler<OperandTypeInfoTraits<TypeInfo>::kIsScalable>::Multiply( \ | 313 OperandScale::kSingle>::kOperandSize, \ |
| 228 static_cast<int>(base_size), static_cast<int>(operand_scale)); \ | 314 OperandScaler<OperandType::k##Name, \ |
| 229 OperandSize operand_size = static_cast<OperandSize>(size); \ | 315 OperandScale::kDouble>::kOperandSize, \ |
| 230 DCHECK(operand_size == OperandSize::kByte || \ | 316 OperandScaler<OperandType::k##Name, \ |
| 231 operand_size == OperandSize::kShort || \ | 317 OperandScale::kQuadruple>::kOperandSize}; \ |
| 232 operand_size == OperandSize::kQuad); \ | 318 return kOperandSizes[index]; \ |
| 233 return operand_size; \ | |
| 234 } | 319 } |
| 235 OPERAND_TYPE_LIST(CASE) | 320 OPERAND_TYPE_LIST(CASE) |
| 236 #undef CASE | 321 #undef CASE |
| 237 } | 322 } |
| 238 UNREACHABLE(); | 323 UNREACHABLE(); |
| 239 return OperandSize::kNone; | 324 return OperandSize::kNone; |
| 240 } | 325 } |
| 241 | 326 |
| 242 } // namespace interpreter | 327 } // namespace interpreter |
| 243 } // namespace internal | 328 } // namespace internal |
| 244 } // namespace v8 | 329 } // namespace v8 |
| 245 | 330 |
| 246 #endif // V8_INTERPRETER_BYTECODE_TRAITS_H_ | 331 #endif // V8_INTERPRETER_BYTECODE_TRAITS_H_ |
| OLD | NEW |