| 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;
|
|
|
|
|