bytecode-traits.h revision f2e3994fa5148cc3d9946666f0b0596290192b0e
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 10namespace v8 { 11namespace internal { 12namespace 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 19template <OperandType> 20struct 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 }; 28OPERAND_TYPE_LIST(DECLARE_OPERAND_SIZE) 29#undef DECLARE_OPERAND_SIZE 30 31 32template <OperandType... Args> 33struct BytecodeTraits {}; 34 35template <OperandType operand_0, OperandType operand_1, OperandType operand_2, 36 OperandType operand_3> 37struct 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 73template <OperandType operand_0, OperandType operand_1, OperandType operand_2> 74struct 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 105template <OperandType operand_0, OperandType operand_1> 106struct 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 134template <OperandType operand_0> 135struct 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 155template <> 156struct 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