• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
3 // found in the LICENSE file.
4 
5 #ifndef V8_INTERPRETER_BYTECODE_TRAITS_H_
6 #define V8_INTERPRETER_BYTECODE_TRAITS_H_
7 
8 #include "src/interpreter/bytecodes.h"
9 
10 namespace v8 {
11 namespace internal {
12 namespace interpreter {
13 
14 template <OperandTypeInfo>
15 struct OperandTypeInfoTraits {
16   static const bool kIsScalable = false;
17   static const bool kIsUnsigned = false;
18   static const OperandSize kUnscaledSize = OperandSize::kNone;
19 };
20 
21 #define DECLARE_OPERAND_TYPE_INFO(Name, Scalable, Unsigned, BaseSize) \
22   template <>                                                         \
23   struct OperandTypeInfoTraits<OperandTypeInfo::k##Name> {            \
24     static const bool kIsScalable = Scalable;                         \
25     static const bool kIsUnsigned = Unsigned;                         \
26     static const OperandSize kUnscaledSize = BaseSize;                \
27   };
28 OPERAND_TYPE_INFO_LIST(DECLARE_OPERAND_TYPE_INFO)
29 #undef DECLARE_OPERAND_TYPE_INFO
30 
31 template <OperandType>
32 struct OperandTraits {
33   typedef OperandTypeInfoTraits<OperandTypeInfo::kNone> TypeInfoTraits;
34   static const OperandTypeInfo kOperandTypeInfo = OperandTypeInfo::kNone;
35 };
36 
37 #define DECLARE_OPERAND_TYPE_TRAITS(Name, InfoType)           \
38   template <>                                                 \
39   struct OperandTraits<OperandType::k##Name> {                \
40     typedef OperandTypeInfoTraits<InfoType> TypeInfoTraits;   \
41     static const OperandTypeInfo kOperandTypeInfo = InfoType; \
42   };
43 OPERAND_TYPE_LIST(DECLARE_OPERAND_TYPE_TRAITS)
44 #undef DECLARE_OPERAND_TYPE_TRAITS
45 
46 template <OperandType operand_type, OperandScale operand_scale>
47 struct OperandScaler {
48   template <bool, OperandSize, OperandScale>
49   struct Helper {
50     static const int kSize = 0;
51   };
52   template <OperandSize size, OperandScale scale>
53   struct Helper<false, size, scale> {
54     static const int kSize = static_cast<int>(size);
55   };
56   template <OperandSize size, OperandScale scale>
57   struct Helper<true, size, scale> {
58     static const int kSize = static_cast<int>(size) * static_cast<int>(scale);
59   };
60 
61   static const int kSize =
62       Helper<OperandTraits<operand_type>::TypeInfoTraits::kIsScalable,
63              OperandTraits<operand_type>::TypeInfoTraits::kUnscaledSize,
64              operand_scale>::kSize;
65   static const OperandSize kOperandSize = static_cast<OperandSize>(kSize);
66 };
67 
68 template <OperandType>
69 struct RegisterOperandTraits {
70   static const int kIsRegisterOperand = 0;
71 };
72 
73 #define DECLARE_REGISTER_OPERAND(Name, _)              \
74   template <>                                          \
75   struct RegisterOperandTraits<OperandType::k##Name> { \
76     static const int kIsRegisterOperand = 1;           \
77   };
78 REGISTER_OPERAND_TYPE_LIST(DECLARE_REGISTER_OPERAND)
79 #undef DECLARE_REGISTER_OPERAND
80 
81 template <AccumulatorUse, OperandType...>
82 struct BytecodeTraits {};
83 
84 template <AccumulatorUse accumulator_use, OperandType operand_0,
85           OperandType operand_1, OperandType operand_2, OperandType operand_3>
86 struct BytecodeTraits<accumulator_use, operand_0, operand_1, operand_2,
87                       operand_3> {
88   static const OperandType* GetOperandTypes() {
89     static const OperandType operand_types[] = {operand_0, operand_1, operand_2,
90                                                 operand_3, OperandType::kNone};
91     return operand_types;
92   }
93 
94   static const OperandTypeInfo* GetOperandTypeInfos() {
95     static const OperandTypeInfo operand_type_infos[] = {
96         OperandTraits<operand_0>::kOperandTypeInfo,
97         OperandTraits<operand_1>::kOperandTypeInfo,
98         OperandTraits<operand_2>::kOperandTypeInfo,
99         OperandTraits<operand_3>::kOperandTypeInfo, OperandTypeInfo::kNone};
100     return operand_type_infos;
101   }
102 
103   static const OperandSize* GetOperandSizes(OperandScale operand_scale) {
104     switch (operand_scale) {
105 #define CASE(Name, _)                                                  \
106   case OperandScale::k##Name: {                                        \
107     static const OperandSize kOperandSizes[] = {                       \
108         OperandScaler<operand_0, OperandScale::k##Name>::kOperandSize, \
109         OperandScaler<operand_1, OperandScale::k##Name>::kOperandSize, \
110         OperandScaler<operand_2, OperandScale::k##Name>::kOperandSize, \
111         OperandScaler<operand_3, OperandScale::k##Name>::kOperandSize, \
112     };                                                                 \
113     return kOperandSizes;                                              \
114   }
115       OPERAND_SCALE_LIST(CASE)
116 #undef CASE
117     }
118     UNREACHABLE();
119     return nullptr;
120   }
121 
122   template <OperandType ot>
123   static inline bool HasAnyOperandsOfType() {
124     return operand_0 == ot || operand_1 == ot || operand_2 == ot ||
125            operand_3 == ot;
126   }
127 
128   static inline bool IsScalable() {
129     return (OperandTraits<operand_0>::TypeInfoTraits::kIsScalable |
130             OperandTraits<operand_1>::TypeInfoTraits::kIsScalable |
131             OperandTraits<operand_2>::TypeInfoTraits::kIsScalable |
132             OperandTraits<operand_3>::TypeInfoTraits::kIsScalable);
133   }
134 
135   static const AccumulatorUse kAccumulatorUse = accumulator_use;
136   static const int kOperandCount = 4;
137   static const int kRegisterOperandCount =
138       RegisterOperandTraits<operand_0>::kIsRegisterOperand +
139       RegisterOperandTraits<operand_1>::kIsRegisterOperand +
140       RegisterOperandTraits<operand_2>::kIsRegisterOperand +
141       RegisterOperandTraits<operand_3>::kIsRegisterOperand;
142   static const int kRegisterOperandBitmap =
143       RegisterOperandTraits<operand_0>::kIsRegisterOperand +
144       (RegisterOperandTraits<operand_1>::kIsRegisterOperand << 1) +
145       (RegisterOperandTraits<operand_2>::kIsRegisterOperand << 2) +
146       (RegisterOperandTraits<operand_3>::kIsRegisterOperand << 3);
147 };
148 
149 template <AccumulatorUse accumulator_use, OperandType operand_0,
150           OperandType operand_1, OperandType operand_2>
151 struct BytecodeTraits<accumulator_use, operand_0, operand_1, operand_2> {
152   static const OperandType* GetOperandTypes() {
153     static const OperandType operand_types[] = {operand_0, operand_1, operand_2,
154                                                 OperandType::kNone};
155     return operand_types;
156   }
157 
158   static const OperandTypeInfo* GetOperandTypeInfos() {
159     static const OperandTypeInfo operand_type_infos[] = {
160         OperandTraits<operand_0>::kOperandTypeInfo,
161         OperandTraits<operand_1>::kOperandTypeInfo,
162         OperandTraits<operand_2>::kOperandTypeInfo, OperandTypeInfo::kNone};
163     return operand_type_infos;
164   }
165 
166   static const OperandSize* GetOperandSizes(OperandScale operand_scale) {
167     switch (operand_scale) {
168 #define CASE(Name, _)                                                  \
169   case OperandScale::k##Name: {                                        \
170     static const OperandSize kOperandSizes[] = {                       \
171         OperandScaler<operand_0, OperandScale::k##Name>::kOperandSize, \
172         OperandScaler<operand_1, OperandScale::k##Name>::kOperandSize, \
173         OperandScaler<operand_2, OperandScale::k##Name>::kOperandSize, \
174     };                                                                 \
175     return kOperandSizes;                                              \
176   }
177       OPERAND_SCALE_LIST(CASE)
178 #undef CASE
179     }
180     UNREACHABLE();
181     return nullptr;
182   }
183 
184   template <OperandType ot>
185   static inline bool HasAnyOperandsOfType() {
186     return operand_0 == ot || operand_1 == ot || operand_2 == ot;
187   }
188 
189   static inline bool IsScalable() {
190     return (OperandTraits<operand_0>::TypeInfoTraits::kIsScalable |
191             OperandTraits<operand_1>::TypeInfoTraits::kIsScalable |
192             OperandTraits<operand_2>::TypeInfoTraits::kIsScalable);
193   }
194 
195   static const AccumulatorUse kAccumulatorUse = accumulator_use;
196   static const int kOperandCount = 3;
197   static const int kRegisterOperandCount =
198       RegisterOperandTraits<operand_0>::kIsRegisterOperand +
199       RegisterOperandTraits<operand_1>::kIsRegisterOperand +
200       RegisterOperandTraits<operand_2>::kIsRegisterOperand;
201   static const int kRegisterOperandBitmap =
202       RegisterOperandTraits<operand_0>::kIsRegisterOperand +
203       (RegisterOperandTraits<operand_1>::kIsRegisterOperand << 1) +
204       (RegisterOperandTraits<operand_2>::kIsRegisterOperand << 2);
205 };
206 
207 template <AccumulatorUse accumulator_use, OperandType operand_0,
208           OperandType operand_1>
209 struct BytecodeTraits<accumulator_use, operand_0, operand_1> {
210   static const OperandType* GetOperandTypes() {
211     static const OperandType operand_types[] = {operand_0, operand_1,
212                                                 OperandType::kNone};
213     return operand_types;
214   }
215 
216   static const OperandTypeInfo* GetOperandTypeInfos() {
217     static const OperandTypeInfo operand_type_infos[] = {
218         OperandTraits<operand_0>::kOperandTypeInfo,
219         OperandTraits<operand_1>::kOperandTypeInfo, OperandTypeInfo::kNone};
220     return operand_type_infos;
221   }
222 
223   static const OperandSize* GetOperandSizes(OperandScale operand_scale) {
224     switch (operand_scale) {
225 #define CASE(Name, _)                                                  \
226   case OperandScale::k##Name: {                                        \
227     static const OperandSize kOperandSizes[] = {                       \
228         OperandScaler<operand_0, OperandScale::k##Name>::kOperandSize, \
229         OperandScaler<operand_1, OperandScale::k##Name>::kOperandSize, \
230     };                                                                 \
231     return kOperandSizes;                                              \
232   }
233       OPERAND_SCALE_LIST(CASE)
234 #undef CASE
235     }
236     UNREACHABLE();
237     return nullptr;
238   }
239 
240   template <OperandType ot>
241   static inline bool HasAnyOperandsOfType() {
242     return operand_0 == ot || operand_1 == ot;
243   }
244 
245   static inline bool IsScalable() {
246     return (OperandTraits<operand_0>::TypeInfoTraits::kIsScalable |
247             OperandTraits<operand_1>::TypeInfoTraits::kIsScalable);
248   }
249 
250   static const AccumulatorUse kAccumulatorUse = accumulator_use;
251   static const int kOperandCount = 2;
252   static const int kRegisterOperandCount =
253       RegisterOperandTraits<operand_0>::kIsRegisterOperand +
254       RegisterOperandTraits<operand_1>::kIsRegisterOperand;
255   static const int kRegisterOperandBitmap =
256       RegisterOperandTraits<operand_0>::kIsRegisterOperand +
257       (RegisterOperandTraits<operand_1>::kIsRegisterOperand << 1);
258 };
259 
260 template <AccumulatorUse accumulator_use, OperandType operand_0>
261 struct BytecodeTraits<accumulator_use, operand_0> {
262   static const OperandType* GetOperandTypes() {
263     static const OperandType operand_types[] = {operand_0, OperandType::kNone};
264     return operand_types;
265   }
266 
267   static const OperandTypeInfo* GetOperandTypeInfos() {
268     static const OperandTypeInfo operand_type_infos[] = {
269         OperandTraits<operand_0>::kOperandTypeInfo, OperandTypeInfo::kNone};
270     return operand_type_infos;
271   }
272 
273   static const OperandSize* GetOperandSizes(OperandScale operand_scale) {
274     switch (operand_scale) {
275 #define CASE(Name, _)                                                  \
276   case OperandScale::k##Name: {                                        \
277     static const OperandSize kOperandSizes[] = {                       \
278         OperandScaler<operand_0, OperandScale::k##Name>::kOperandSize, \
279     };                                                                 \
280     return kOperandSizes;                                              \
281   }
282       OPERAND_SCALE_LIST(CASE)
283 #undef CASE
284     }
285     UNREACHABLE();
286     return nullptr;
287   }
288 
289   template <OperandType ot>
290   static inline bool HasAnyOperandsOfType() {
291     return operand_0 == ot;
292   }
293 
294   static inline bool IsScalable() {
295     return OperandTraits<operand_0>::TypeInfoTraits::kIsScalable;
296   }
297 
298   static const AccumulatorUse kAccumulatorUse = accumulator_use;
299   static const int kOperandCount = 1;
300   static const int kRegisterOperandCount =
301       RegisterOperandTraits<operand_0>::kIsRegisterOperand;
302   static const int kRegisterOperandBitmap =
303       RegisterOperandTraits<operand_0>::kIsRegisterOperand;
304 };
305 
306 template <AccumulatorUse accumulator_use>
307 struct BytecodeTraits<accumulator_use> {
308   static const OperandType* GetOperandTypes() {
309     static const OperandType operand_types[] = {OperandType::kNone};
310     return operand_types;
311   }
312 
313   static const OperandTypeInfo* GetOperandTypeInfos() {
314     static const OperandTypeInfo operand_type_infos[] = {
315         OperandTypeInfo::kNone};
316     return operand_type_infos;
317   }
318 
319   static const OperandSize* GetOperandSizes(OperandScale operand_scale) {
320     return nullptr;
321   }
322 
323   template <OperandType ot>
324   static inline bool HasAnyOperandsOfType() {
325     return false;
326   }
327 
328   static inline bool IsScalable() { return false; }
329 
330   static const AccumulatorUse kAccumulatorUse = accumulator_use;
331   static const int kOperandCount = 0;
332   static const int kRegisterOperandCount = 0;
333   static const int kRegisterOperandBitmap = 0;
334 };
335 
336 static OperandSize ScaledOperandSize(OperandType operand_type,
337                                      OperandScale operand_scale) {
338   STATIC_ASSERT(static_cast<int>(OperandScale::kQuadruple) == 4 &&
339                 OperandScale::kLast == OperandScale::kQuadruple);
340   int index = static_cast<int>(operand_scale) >> 1;
341   switch (operand_type) {
342 #define CASE(Name, TypeInfo)                                    \
343   case OperandType::k##Name: {                                  \
344     static const OperandSize kOperandSizes[] = {                \
345         OperandScaler<OperandType::k##Name,                     \
346                       OperandScale::kSingle>::kOperandSize,     \
347         OperandScaler<OperandType::k##Name,                     \
348                       OperandScale::kDouble>::kOperandSize,     \
349         OperandScaler<OperandType::k##Name,                     \
350                       OperandScale::kQuadruple>::kOperandSize}; \
351     return kOperandSizes[index];                                \
352   }
353     OPERAND_TYPE_LIST(CASE)
354 #undef CASE
355   }
356   UNREACHABLE();
357   return OperandSize::kNone;
358 }
359 
360 }  // namespace interpreter
361 }  // namespace internal
362 }  // namespace v8
363 
364 #endif  // V8_INTERPRETER_BYTECODE_TRAITS_H_
365