Home | History | Annotate | Download | only in interpreter
      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