| Index: src/interpreter/bytecodes.cc | 
| diff --git a/src/interpreter/bytecodes.cc b/src/interpreter/bytecodes.cc | 
| index 281a883e847b7d928b334ac4c432bc5f8c834dd7..5f43ea3370f46619c25f8ac3b065a46f5adb0207 100644 | 
| --- a/src/interpreter/bytecodes.cc | 
| +++ b/src/interpreter/bytecodes.cc | 
| @@ -5,25 +5,12 @@ | 
| #include "src/interpreter/bytecodes.h" | 
|  | 
| #include "src/frames.h" | 
| +#include "src/interpreter/bytecode-traits.h" | 
|  | 
| namespace v8 { | 
| namespace internal { | 
| namespace interpreter { | 
|  | 
| -// Maximum number of operands a bytecode may have. | 
| -static const int kMaxOperands = 3; | 
| - | 
| -// kBytecodeTable relies on kNone being the same as zero to detect length. | 
| -STATIC_ASSERT(static_cast<int>(OperandType::kNone) == 0); | 
| - | 
| -static const OperandType kBytecodeTable[][kMaxOperands] = { | 
| -#define DECLARE_OPERAND(_, ...) \ | 
| -  { __VA_ARGS__ }               \ | 
| -  , | 
| -    BYTECODE_LIST(DECLARE_OPERAND) | 
| -#undef DECLARE_OPERAND | 
| -}; | 
| - | 
|  | 
| // static | 
| const char* Bytecodes::ToString(Bytecode bytecode) { | 
| @@ -42,7 +29,7 @@ const char* Bytecodes::ToString(Bytecode bytecode) { | 
| // static | 
| const char* Bytecodes::OperandTypeToString(OperandType operand_type) { | 
| switch (operand_type) { | 
| -#define CASE(Name)           \ | 
| +#define CASE(Name, _)        \ | 
| case OperandType::k##Name: \ | 
| return #Name; | 
| OPERAND_TYPE_LIST(CASE) | 
| @@ -54,6 +41,21 @@ const char* Bytecodes::OperandTypeToString(OperandType operand_type) { | 
|  | 
|  | 
| // static | 
| +const char* Bytecodes::OperandSizeToString(OperandSize operand_size) { | 
| +  switch (operand_size) { | 
| +    case OperandSize::kNone: | 
| +      return "None"; | 
| +    case OperandSize::kByte: | 
| +      return "Byte"; | 
| +    case OperandSize::kShort: | 
| +      return "Short"; | 
| +  } | 
| +  UNREACHABLE(); | 
| +  return ""; | 
| +} | 
| + | 
| + | 
| +// static | 
| uint8_t Bytecodes::ToByte(Bytecode bytecode) { | 
| return static_cast<uint8_t>(bytecode); | 
| } | 
| @@ -68,38 +70,92 @@ Bytecode Bytecodes::FromByte(uint8_t value) { | 
|  | 
|  | 
| // static | 
| +int Bytecodes::Size(Bytecode bytecode) { | 
| +  DCHECK(bytecode <= Bytecode::kLast); | 
| +  switch (bytecode) { | 
| +#define CASE(Name, ...)   \ | 
| +  case Bytecode::k##Name: \ | 
| +    return BytecodeTraits<__VA_ARGS__, OPERAND_TERM>::kSize; | 
| +    BYTECODE_LIST(CASE) | 
| +#undef CASE | 
| +  } | 
| +  UNREACHABLE(); | 
| +  return 0; | 
| +} | 
| + | 
| + | 
| +// static | 
| int Bytecodes::NumberOfOperands(Bytecode bytecode) { | 
| DCHECK(bytecode <= Bytecode::kLast); | 
| -  int count; | 
| -  uint8_t row = ToByte(bytecode); | 
| -  for (count = 0; count < kMaxOperands; count++) { | 
| -    if (kBytecodeTable[row][count] == OperandType::kNone) { | 
| -      break; | 
| -    } | 
| +  switch (bytecode) { | 
| +#define CASE(Name, ...)   \ | 
| +  case Bytecode::k##Name: \ | 
| +    return BytecodeTraits<__VA_ARGS__, OPERAND_TERM>::kOperandCount; | 
| +    BYTECODE_LIST(CASE) | 
| +#undef CASE | 
| } | 
| -  return count; | 
| +  UNREACHABLE(); | 
| +  return 0; | 
| } | 
|  | 
|  | 
| // static | 
| OperandType Bytecodes::GetOperandType(Bytecode bytecode, int i) { | 
| -  DCHECK(bytecode <= Bytecode::kLast && i < NumberOfOperands(bytecode)); | 
| -  return kBytecodeTable[ToByte(bytecode)][i]; | 
| +  DCHECK(bytecode <= Bytecode::kLast); | 
| +  switch (bytecode) { | 
| +#define CASE(Name, ...)   \ | 
| +  case Bytecode::k##Name: \ | 
| +    return BytecodeTraits<__VA_ARGS__, OPERAND_TERM>::GetOperandType(i); | 
| +    BYTECODE_LIST(CASE) | 
| +#undef CASE | 
| +  } | 
| +  UNREACHABLE(); | 
| +  return OperandType::kNone; | 
| } | 
|  | 
|  | 
| // static | 
| -int Bytecodes::Size(Bytecode bytecode) { | 
| -  return 1 + NumberOfOperands(bytecode); | 
| +OperandSize Bytecodes::GetOperandSize(Bytecode bytecode, int i) { | 
| +  DCHECK(bytecode <= Bytecode::kLast); | 
| +  switch (bytecode) { | 
| +#define CASE(Name, ...)   \ | 
| +  case Bytecode::k##Name: \ | 
| +    return BytecodeTraits<__VA_ARGS__, OPERAND_TERM>::GetOperandSize(i); | 
| +    BYTECODE_LIST(CASE) | 
| +#undef CASE | 
| +  } | 
| +  UNREACHABLE(); | 
| +  return OperandSize::kNone; | 
| } | 
|  | 
|  | 
| // static | 
| -int Bytecodes::MaximumNumberOfOperands() { return kMaxOperands; } | 
| +int Bytecodes::GetOperandOffset(Bytecode bytecode, int i) { | 
| +  DCHECK(bytecode <= Bytecode::kLast); | 
| +  switch (bytecode) { | 
| +#define CASE(Name, ...)   \ | 
| +  case Bytecode::k##Name: \ | 
| +    return BytecodeTraits<__VA_ARGS__, OPERAND_TERM>::GetOperandOffset(i); | 
| +    BYTECODE_LIST(CASE) | 
| +#undef CASE | 
| +  } | 
| +  UNREACHABLE(); | 
| +  return 0; | 
| +} | 
|  | 
|  | 
| // static | 
| -int Bytecodes::MaximumSize() { return 1 + kMaxOperands; } | 
| +OperandSize Bytecodes::SizeOfOperand(OperandType operand_type) { | 
| +  switch (operand_type) { | 
| +#define CASE(Name, Size)     \ | 
| +  case OperandType::k##Name: \ | 
| +    return Size; | 
| +    OPERAND_TYPE_LIST(CASE) | 
| +#undef CASE | 
| +  } | 
| +  UNREACHABLE(); | 
| +  return OperandSize::kNone; | 
| +} | 
|  | 
|  | 
| // static | 
| @@ -118,6 +174,18 @@ bool Bytecodes::IsJumpConstant(Bytecode bytecode) { | 
|  | 
|  | 
| // static | 
| +uint16_t Bytecodes::ShortOperandFromBytes(const uint8_t* bytes) { | 
| +  return *reinterpret_cast<const uint16_t*>(bytes); | 
| +} | 
| + | 
| + | 
| +// static | 
| +void Bytecodes::ShortOperandToBytes(uint16_t operand, uint8_t* bytes_out) { | 
| +  *reinterpret_cast<uint16_t*>(bytes_out) = operand; | 
| +} | 
| + | 
| + | 
| +// static | 
| std::ostream& Bytecodes::Decode(std::ostream& os, const uint8_t* bytecode_start, | 
| int parameter_count) { | 
| Vector<char> buf = Vector<char>::New(50); | 
| @@ -129,29 +197,34 @@ std::ostream& Bytecodes::Decode(std::ostream& os, const uint8_t* bytecode_start, | 
| SNPrintF(buf, "%02x ", bytecode_start[i]); | 
| os << buf.start(); | 
| } | 
| -  for (int i = bytecode_size; i < Bytecodes::MaximumSize(); i++) { | 
| +  const int kBytecodeColumnSize = 6; | 
| +  for (int i = bytecode_size; i < kBytecodeColumnSize; i++) { | 
| os << "   "; | 
| } | 
|  | 
| os << bytecode << " "; | 
|  | 
| -  const uint8_t* operands_start = bytecode_start + 1; | 
| -  int operands_size = bytecode_size - 1; | 
| -  for (int i = 0; i < operands_size; i++) { | 
| +  int number_of_operands = NumberOfOperands(bytecode); | 
| +  for (int i = 0; i < number_of_operands; i++) { | 
| OperandType op_type = GetOperandType(bytecode, i); | 
| -    uint8_t operand = operands_start[i]; | 
| +    const uint8_t* operand_start = | 
| +        &bytecode_start[GetOperandOffset(bytecode, i)]; | 
| switch (op_type) { | 
| -      case interpreter::OperandType::kCount: | 
| -        os << "#" << static_cast<unsigned int>(operand); | 
| +      case interpreter::OperandType::kCount8: | 
| +        os << "#" << static_cast<unsigned int>(*operand_start); | 
| +        break; | 
| +      case interpreter::OperandType::kIdx8: | 
| +        os << "[" << static_cast<unsigned int>(*operand_start) << "]"; | 
| break; | 
| -      case interpreter::OperandType::kIdx: | 
| -        os << "[" << static_cast<unsigned int>(operand) << "]"; | 
| +      case interpreter::OperandType::kIdx16: { | 
| +        os << "[" << Bytecodes::ShortOperandFromBytes(operand_start) << "]"; | 
| break; | 
| +      } | 
| case interpreter::OperandType::kImm8: | 
| -        os << "#" << static_cast<int>(static_cast<int8_t>(operand)); | 
| +        os << "#" << static_cast<int>(static_cast<int8_t>(*operand_start)); | 
| break; | 
| -      case interpreter::OperandType::kReg: { | 
| -        Register reg = Register::FromOperand(operand); | 
| +      case interpreter::OperandType::kReg8: { | 
| +        Register reg = Register::FromOperand(*operand_start); | 
| if (reg.is_parameter()) { | 
| int parameter_index = reg.ToParameterIndex(parameter_count); | 
| if (parameter_index == 0) { | 
| @@ -168,7 +241,7 @@ std::ostream& Bytecodes::Decode(std::ostream& os, const uint8_t* bytecode_start, | 
| UNREACHABLE(); | 
| break; | 
| } | 
| -    if (i != operands_size - 1) { | 
| +    if (i != number_of_operands - 1) { | 
| os << ", "; | 
| } | 
| } | 
| @@ -186,6 +259,11 @@ std::ostream& operator<<(std::ostream& os, const OperandType& operand_type) { | 
| } | 
|  | 
|  | 
| +std::ostream& operator<<(std::ostream& os, const OperandSize& operand_size) { | 
| +  return os << Bytecodes::OperandSizeToString(operand_size); | 
| +} | 
| + | 
| + | 
| static const int kLastParamRegisterIndex = | 
| -InterpreterFrameConstants::kLastParamFromRegisterPointer / kPointerSize; | 
|  | 
|  |