// Copyright 2015 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef V8_INTERPRETER_BYTECODE_TRAITS_H_ #define V8_INTERPRETER_BYTECODE_TRAITS_H_ #include "src/interpreter/bytecodes.h" namespace v8 { namespace internal { namespace interpreter { // TODO(rmcilroy): consider simplifying this to avoid the template magic. // Template helpers to deduce the number of operands each bytecode has. #define OPERAND_TERM OperandType::kNone, OperandType::kNone, OperandType::kNone template struct OperandTraits {}; #define DECLARE_OPERAND_SIZE(Name, Size) \ template <> \ struct OperandTraits { \ static const OperandSize kSizeType = Size; \ static const int kSize = static_cast(Size); \ }; OPERAND_TYPE_LIST(DECLARE_OPERAND_SIZE) #undef DECLARE_OPERAND_SIZE template struct RegisterOperandTraits { static const int kIsRegisterOperand = 0; }; #define DECLARE_REGISTER_OPERAND(Name, _) \ template <> \ struct RegisterOperandTraits { \ static const int kIsRegisterOperand = 1; \ }; REGISTER_OPERAND_TYPE_LIST(DECLARE_REGISTER_OPERAND) #undef DECLARE_REGISTER_OPERAND template struct BytecodeTraits {}; template struct BytecodeTraits { static OperandType GetOperandType(int i) { DCHECK(0 <= i && i < kOperandCount); const OperandType kOperands[] = {operand_0, operand_1, operand_2, operand_3}; return kOperands[i]; } static inline OperandSize GetOperandSize(int i) { DCHECK(0 <= i && i < kOperandCount); const OperandSize kOperandSizes[] = {OperandTraits::kSizeType, OperandTraits::kSizeType, OperandTraits::kSizeType, OperandTraits::kSizeType}; return kOperandSizes[i]; } static inline int GetOperandOffset(int i) { DCHECK(0 <= i && i < kOperandCount); const int kOffset0 = 1; const int kOffset1 = kOffset0 + OperandTraits::kSize; const int kOffset2 = kOffset1 + OperandTraits::kSize; const int kOffset3 = kOffset2 + OperandTraits::kSize; const int kOperandOffsets[] = {kOffset0, kOffset1, kOffset2, kOffset3}; return kOperandOffsets[i]; } template static inline bool HasAnyOperandsOfType() { return operand_0 == ot || operand_1 == ot || operand_2 == ot || operand_3 == ot; } static const int kOperandCount = 4; static const int kRegisterOperandCount = RegisterOperandTraits::kIsRegisterOperand + RegisterOperandTraits::kIsRegisterOperand + RegisterOperandTraits::kIsRegisterOperand + RegisterOperandTraits::kIsRegisterOperand; static const int kRegisterOperandBitmap = RegisterOperandTraits::kIsRegisterOperand + (RegisterOperandTraits::kIsRegisterOperand << 1) + (RegisterOperandTraits::kIsRegisterOperand << 2) + (RegisterOperandTraits::kIsRegisterOperand << 3); static const int kSize = 1 + OperandTraits::kSize + OperandTraits::kSize + OperandTraits::kSize + OperandTraits::kSize; }; template struct BytecodeTraits { static inline OperandType GetOperandType(int i) { DCHECK(0 <= i && i <= 2); const OperandType kOperands[] = {operand_0, operand_1, operand_2}; return kOperands[i]; } static inline OperandSize GetOperandSize(int i) { DCHECK(0 <= i && i < kOperandCount); const OperandSize kOperandSizes[] = {OperandTraits::kSizeType, OperandTraits::kSizeType, OperandTraits::kSizeType}; return kOperandSizes[i]; } static inline int GetOperandOffset(int i) { DCHECK(0 <= i && i < kOperandCount); const int kOffset0 = 1; const int kOffset1 = kOffset0 + OperandTraits::kSize; const int kOffset2 = kOffset1 + OperandTraits::kSize; const int kOperandOffsets[] = {kOffset0, kOffset1, kOffset2}; return kOperandOffsets[i]; } template static inline bool HasAnyOperandsOfType() { return operand_0 == ot || operand_1 == ot || operand_2 == ot; } static const int kOperandCount = 3; static const int kRegisterOperandCount = RegisterOperandTraits::kIsRegisterOperand + RegisterOperandTraits::kIsRegisterOperand + RegisterOperandTraits::kIsRegisterOperand; static const int kRegisterOperandBitmap = RegisterOperandTraits::kIsRegisterOperand + (RegisterOperandTraits::kIsRegisterOperand << 1) + (RegisterOperandTraits::kIsRegisterOperand << 2); static const int kSize = 1 + OperandTraits::kSize + OperandTraits::kSize + OperandTraits::kSize; }; template struct BytecodeTraits { static inline OperandType GetOperandType(int i) { DCHECK(0 <= i && i < kOperandCount); const OperandType kOperands[] = {operand_0, operand_1}; return kOperands[i]; } static inline OperandSize GetOperandSize(int i) { DCHECK(0 <= i && i < kOperandCount); const OperandSize kOperandSizes[] = {OperandTraits::kSizeType, OperandTraits::kSizeType}; return kOperandSizes[i]; } static inline int GetOperandOffset(int i) { DCHECK(0 <= i && i < kOperandCount); const int kOffset0 = 1; const int kOffset1 = kOffset0 + OperandTraits::kSize; const int kOperandOffsets[] = {kOffset0, kOffset1}; return kOperandOffsets[i]; } template static inline bool HasAnyOperandsOfType() { return operand_0 == ot || operand_1 == ot; } static const int kOperandCount = 2; static const int kRegisterOperandCount = RegisterOperandTraits::kIsRegisterOperand + RegisterOperandTraits::kIsRegisterOperand; static const int kRegisterOperandBitmap = RegisterOperandTraits::kIsRegisterOperand + (RegisterOperandTraits::kIsRegisterOperand << 1); static const int kSize = 1 + OperandTraits::kSize + OperandTraits::kSize; }; template struct BytecodeTraits { static inline OperandType GetOperandType(int i) { DCHECK(i == 0); return operand_0; } static inline OperandSize GetOperandSize(int i) { DCHECK(i == 0); return OperandTraits::kSizeType; } static inline int GetOperandOffset(int i) { DCHECK(i == 0); return 1; } template static inline bool HasAnyOperandsOfType() { return operand_0 == ot; } static const int kOperandCount = 1; static const int kRegisterOperandCount = RegisterOperandTraits::kIsRegisterOperand; static const int kRegisterOperandBitmap = RegisterOperandTraits::kIsRegisterOperand; static const int kSize = 1 + OperandTraits::kSize; }; template <> struct BytecodeTraits { static inline OperandType GetOperandType(int i) { UNREACHABLE(); return OperandType::kNone; } static inline OperandSize GetOperandSize(int i) { UNREACHABLE(); return OperandSize::kNone; } static inline int GetOperandOffset(int i) { UNREACHABLE(); return 1; } template static inline bool HasAnyOperandsOfType() { return false; } static const int kOperandCount = 0; static const int kRegisterOperandCount = 0; static const int kRegisterOperandBitmap = 0; static const int kSize = 1 + OperandTraits::kSize; }; } // namespace interpreter } // namespace internal } // namespace v8 #endif // V8_INTERPRETER_BYTECODE_TRAITS_H_