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