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 // TODO(rmcilroy): consider simplifying this to avoid the template magic.
15 
16 // Template helpers to deduce the number of operands each bytecode has.
17 #define OPERAND_TERM OperandType::kNone, OperandType::kNone, OperandType::kNone
18 
19 template <OperandType>
20 struct OperandTraits {};
21 
22 #define DECLARE_OPERAND_SIZE(Name, Size)             \
23   template <>                                        \
24   struct OperandTraits<OperandType::k##Name> {       \
25     static const OperandSize kSizeType = Size;       \
26     static const int kSize = static_cast<int>(Size); \
27   };
28 OPERAND_TYPE_LIST(DECLARE_OPERAND_SIZE)
29 #undef DECLARE_OPERAND_SIZE
30 
31 
32 template <OperandType... Args>
33 struct BytecodeTraits {};
34 
35 template <OperandType operand_0, OperandType operand_1, OperandType operand_2,
36           OperandType operand_3>
37 struct BytecodeTraits<operand_0, operand_1, operand_2, operand_3,
38                       OPERAND_TERM> {
39   static OperandType GetOperandType(int i) {
40     DCHECK(0 <= i && i < kOperandCount);
41     const OperandType kOperands[] = {operand_0, operand_1, operand_2,
42                                      operand_3};
43     return kOperands[i];
44   }
45 
46   static inline OperandSize GetOperandSize(int i) {
47     DCHECK(0 <= i && i < kOperandCount);
48     const OperandSize kOperandSizes[] =
49         {OperandTraits<operand_0>::kSizeType,
50          OperandTraits<operand_1>::kSizeType,
51          OperandTraits<operand_2>::kSizeType,
52          OperandTraits<operand_3>::kSizeType};
53     return kOperandSizes[i];
54   }
55 
56   static inline int GetOperandOffset(int i) {
57     DCHECK(0 <= i && i < kOperandCount);
58     const int kOffset0 = 1;
59     const int kOffset1 = kOffset0 + OperandTraits<operand_0>::kSize;
60     const int kOffset2 = kOffset1 + OperandTraits<operand_1>::kSize;
61     const int kOffset3 = kOffset2 + OperandTraits<operand_2>::kSize;
62     const int kOperandOffsets[] = {kOffset0, kOffset1, kOffset2, kOffset3};
63     return kOperandOffsets[i];
64   }
65 
66   static const int kOperandCount = 4;
67   static const int kSize =
68       1 + OperandTraits<operand_0>::kSize + OperandTraits<operand_1>::kSize +
69       OperandTraits<operand_2>::kSize + OperandTraits<operand_3>::kSize;
70 };
71 
72 
73 template <OperandType operand_0, OperandType operand_1, OperandType operand_2>
74 struct BytecodeTraits<operand_0, operand_1, operand_2, OPERAND_TERM> {
75   static inline OperandType GetOperandType(int i) {
76     DCHECK(0 <= i && i <= 2);
77     const OperandType kOperands[] = {operand_0, operand_1, operand_2};
78     return kOperands[i];
79   }
80 
81   static inline OperandSize GetOperandSize(int i) {
82     DCHECK(0 <= i && i < kOperandCount);
83     const OperandSize kOperandSizes[] =
84         {OperandTraits<operand_0>::kSizeType,
85          OperandTraits<operand_1>::kSizeType,
86          OperandTraits<operand_2>::kSizeType};
87     return kOperandSizes[i];
88   }
89 
90   static inline int GetOperandOffset(int i) {
91     DCHECK(0 <= i && i < kOperandCount);
92     const int kOffset0 = 1;
93     const int kOffset1 = kOffset0 + OperandTraits<operand_0>::kSize;
94     const int kOffset2 = kOffset1 + OperandTraits<operand_1>::kSize;
95     const int kOperandOffsets[] = {kOffset0, kOffset1, kOffset2};
96     return kOperandOffsets[i];
97   }
98 
99   static const int kOperandCount = 3;
100   static const int kSize =
101       1 + OperandTraits<operand_0>::kSize + OperandTraits<operand_1>::kSize +
102       OperandTraits<operand_2>::kSize;
103 };
104 
105 template <OperandType operand_0, OperandType operand_1>
106 struct BytecodeTraits<operand_0, operand_1, OPERAND_TERM> {
107   static inline OperandType GetOperandType(int i) {
108     DCHECK(0 <= i && i < kOperandCount);
109     const OperandType kOperands[] = {operand_0, operand_1};
110     return kOperands[i];
111   }
112 
113   static inline OperandSize GetOperandSize(int i) {
114     DCHECK(0 <= i && i < kOperandCount);
115     const OperandSize kOperandSizes[] =
116         {OperandTraits<operand_0>::kSizeType,
117          OperandTraits<operand_1>::kSizeType};
118     return kOperandSizes[i];
119   }
120 
121   static inline int GetOperandOffset(int i) {
122     DCHECK(0 <= i && i < kOperandCount);
123     const int kOffset0 = 1;
124     const int kOffset1 = kOffset0 + OperandTraits<operand_0>::kSize;
125     const int kOperandOffsets[] = {kOffset0, kOffset1};
126     return kOperandOffsets[i];
127   }
128 
129   static const int kOperandCount = 2;
130   static const int kSize =
131       1 + OperandTraits<operand_0>::kSize + OperandTraits<operand_1>::kSize;
132 };
133 
134 template <OperandType operand_0>
135 struct BytecodeTraits<operand_0, OPERAND_TERM> {
136   static inline OperandType GetOperandType(int i) {
137     DCHECK(i == 0);
138     return operand_0;
139   }
140 
141   static inline OperandSize GetOperandSize(int i) {
142     DCHECK(i == 0);
143     return OperandTraits<operand_0>::kSizeType;
144   }
145 
146   static inline int GetOperandOffset(int i) {
147     DCHECK(i == 0);
148     return 1;
149   }
150 
151   static const int kOperandCount = 1;
152   static const int kSize = 1 + OperandTraits<operand_0>::kSize;
153 };
154 
155 template <>
156 struct BytecodeTraits<OperandType::kNone, OPERAND_TERM> {
157   static inline OperandType GetOperandType(int i) {
158     UNREACHABLE();
159     return OperandType::kNone;
160   }
161 
162   static inline OperandSize GetOperandSize(int i) {
163     UNREACHABLE();
164     return OperandSize::kNone;
165   }
166 
167   static inline int GetOperandOffset(int i) {
168     UNREACHABLE();
169     return 1;
170   }
171 
172   static const int kOperandCount = 0;
173   static const int kSize = 1 + OperandTraits<OperandType::kNone>::kSize;
174 };
175 
176 }  // namespace interpreter
177 }  // namespace internal
178 }  // namespace v8
179 
180 #endif  // V8_INTERPRETER_BYTECODE_TRAITS_H_
181