| Index: src/interpreter/bytecodes.cc
|
| diff --git a/src/interpreter/bytecodes.cc b/src/interpreter/bytecodes.cc
|
| index 5f7a9085aec33bdba04bcd4764a8cfac73a6e667..ae5b349a241c7221ea5d1073ad52a005a7bce472 100644
|
| --- a/src/interpreter/bytecodes.cc
|
| +++ b/src/interpreter/bytecodes.cc
|
| @@ -29,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)
|
| @@ -49,6 +49,8 @@ const char* Bytecodes::OperandSizeToString(OperandSize operand_size) {
|
| return "Byte";
|
| case OperandSize::kShort:
|
| return "Short";
|
| + case OperandSize::kQuad:
|
| + return "Quad";
|
| }
|
| UNREACHABLE();
|
| return "";
|
| @@ -71,32 +73,28 @@ Bytecode Bytecodes::FromByte(uint8_t value) {
|
|
|
|
|
| // static
|
| -Bytecode Bytecodes::GetDebugBreak(Bytecode bytecode) {
|
| - switch (Size(bytecode)) {
|
| -#define CASE(Name, ...) \
|
| - case BytecodeTraits<__VA_ARGS__, OPERAND_TERM>::kSize: \
|
| - return Bytecode::k##Name;
|
| - DEBUG_BREAK_BYTECODE_LIST(CASE)
|
| -#undef CASE
|
| - default:
|
| - break;
|
| +Bytecode Bytecodes::GetDebugBreak(Bytecode bytecode, int operand_scale) {
|
| + int bytecode_size = Size(bytecode, operand_scale);
|
| +#define RETURN_IF_DEBUG_BREAK_SIZE_MATCHES(Name, ...) \
|
| + if (bytecode_size == Size(Bytecode::k##Name, operand_scale)) { \
|
| + return Bytecode::k##Name; \
|
| }
|
| + DEBUG_BREAK_BYTECODE_LIST(RETURN_IF_DEBUG_BREAK_SIZE_MATCHES)
|
| +#undef RETURN_IF_DEBUG_BREAK_SIZE_MATCHES
|
| UNREACHABLE();
|
| return static_cast<Bytecode>(-1);
|
| }
|
|
|
| // 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
|
| +int Bytecodes::Size(Bytecode bytecode, int operand_scale) {
|
| + int size = 1;
|
| + for (int i = 0; i < NumberOfOperands(bytecode); i++) {
|
| + OperandSize operand_size = GetOperandSize(bytecode, i, operand_scale);
|
| + int delta = static_cast<int>(operand_size);
|
| + DCHECK(base::bits::IsPowerOfTwo32(static_cast<uint32_t>(delta)));
|
| + size += delta;
|
| }
|
| - UNREACHABLE();
|
| - return 0;
|
| + return size;
|
| }
|
|
|
|
|
| @@ -131,6 +129,18 @@ int Bytecodes::NumberOfRegisterOperands(Bytecode bytecode) {
|
| }
|
|
|
| // static
|
| +int Bytecodes::GetPrefixBytecodeScale(Bytecode bytecode) {
|
| + switch (bytecode) {
|
| + case Bytecode::kExtraWide:
|
| + return 4;
|
| + case Bytecode::kWide:
|
| + return 2;
|
| + default:
|
| + return 1;
|
| + }
|
| +}
|
| +
|
| +// static
|
| OperandType Bytecodes::GetOperandType(Bytecode bytecode, int i) {
|
| DCHECK(bytecode <= Bytecode::kLast);
|
| switch (bytecode) {
|
| @@ -144,23 +154,47 @@ OperandType Bytecodes::GetOperandType(Bytecode bytecode, int i) {
|
| return OperandType::kNone;
|
| }
|
|
|
| +// TODO(oth): TEMPORARY
|
| +namespace {
|
|
|
| -// static
|
| -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)
|
| +template <OperandTypeTrait O>
|
| +struct OperandScaler {
|
| + static int Multiply(int size, int scale) { return 0; }
|
| +};
|
| +
|
| +template <>
|
| +struct OperandScaler<OperandTypeTrait::kFixed> {
|
| + static int Multiply(int size, int scale) { return size; }
|
| +};
|
| +
|
| +template <>
|
| +struct OperandScaler<OperandTypeTrait::kScalable> {
|
| + static int Multiply(int size, int scale) { return size * scale; }
|
| +};
|
| +
|
| +} // namespace
|
| +
|
| +// TODO(oth): TEMPORARY
|
| +static int ScaledOperandSize(OperandType operand_type, int scale) {
|
| + switch (operand_type) {
|
| +#define CASE(Name, Size, Trait) \
|
| + case OperandType::k##Name: \
|
| + return OperandScaler<Trait>::Multiply(static_cast<int>(Size), scale);
|
| + OPERAND_TYPE_LIST(CASE)
|
| #undef CASE
|
| }
|
| UNREACHABLE();
|
| - return OperandSize::kNone;
|
| + return 0;
|
| }
|
|
|
|
|
| // static
|
| +OperandSize Bytecodes::GetOperandSize(Bytecode bytecode, int i, int scale) {
|
| + OperandType op_type = GetOperandType(bytecode, i);
|
| + return static_cast<OperandSize>(ScaledOperandSize(op_type, scale));
|
| +}
|
| +
|
| +// static
|
| int Bytecodes::GetRegisterOperandBitmap(Bytecode bytecode) {
|
| DCHECK(bytecode <= Bytecode::kLast);
|
| switch (bytecode) {
|
| @@ -176,31 +210,18 @@ int Bytecodes::GetRegisterOperandBitmap(Bytecode bytecode) {
|
| }
|
|
|
| // static
|
| -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
|
| +int Bytecodes::GetOperandOffset(Bytecode bytecode, int i, int scale) {
|
| + int offset = 1;
|
| + for (int operand_index = 0; operand_index < i; ++operand_index) {
|
| + OperandSize operand_size = GetOperandSize(bytecode, operand_index, scale);
|
| + offset += static_cast<int>(operand_size);
|
| }
|
| - UNREACHABLE();
|
| - return 0;
|
| + return offset;
|
| }
|
|
|
| -
|
| // static
|
| -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;
|
| +OperandSize Bytecodes::SizeOfOperand(OperandType operand_type, int scale) {
|
| + return static_cast<OperandSize>(ScaledOperandSize(operand_type, scale));
|
| }
|
|
|
|
|
| @@ -227,24 +248,10 @@ bool Bytecodes::IsConditionalJumpConstant(Bytecode bytecode) {
|
| bytecode == Bytecode::kJumpIfUndefinedConstant;
|
| }
|
|
|
| -
|
| -// static
|
| -bool Bytecodes::IsConditionalJumpConstantWide(Bytecode bytecode) {
|
| - return bytecode == Bytecode::kJumpIfTrueConstantWide ||
|
| - bytecode == Bytecode::kJumpIfFalseConstantWide ||
|
| - bytecode == Bytecode::kJumpIfToBooleanTrueConstantWide ||
|
| - bytecode == Bytecode::kJumpIfToBooleanFalseConstantWide ||
|
| - bytecode == Bytecode::kJumpIfNotHoleConstantWide ||
|
| - bytecode == Bytecode::kJumpIfNullConstantWide ||
|
| - bytecode == Bytecode::kJumpIfUndefinedConstantWide;
|
| -}
|
| -
|
| -
|
| // static
|
| bool Bytecodes::IsConditionalJump(Bytecode bytecode) {
|
| return IsConditionalJumpImmediate(bytecode) ||
|
| - IsConditionalJumpConstant(bytecode) ||
|
| - IsConditionalJumpConstantWide(bytecode);
|
| + IsConditionalJumpConstant(bytecode);
|
| }
|
|
|
|
|
| @@ -260,34 +267,22 @@ bool Bytecodes::IsJumpConstant(Bytecode bytecode) {
|
| IsConditionalJumpConstant(bytecode);
|
| }
|
|
|
| -
|
| -// static
|
| -bool Bytecodes::IsJumpConstantWide(Bytecode bytecode) {
|
| - return bytecode == Bytecode::kJumpConstantWide ||
|
| - IsConditionalJumpConstantWide(bytecode);
|
| -}
|
| -
|
| -
|
| // static
|
| bool Bytecodes::IsJump(Bytecode bytecode) {
|
| - return IsJumpImmediate(bytecode) || IsJumpConstant(bytecode) ||
|
| - IsJumpConstantWide(bytecode);
|
| + return IsJumpImmediate(bytecode) || IsJumpConstant(bytecode);
|
| }
|
|
|
|
|
| // static
|
| bool Bytecodes::IsCallOrNew(Bytecode bytecode) {
|
| return bytecode == Bytecode::kCall || bytecode == Bytecode::kTailCall ||
|
| - bytecode == Bytecode::kNew || bytecode == Bytecode::kCallWide ||
|
| - bytecode == Bytecode::kTailCallWide || bytecode == Bytecode::kNewWide;
|
| + bytecode == Bytecode::kNew;
|
| }
|
|
|
| // static
|
| bool Bytecodes::IsCallRuntime(Bytecode bytecode) {
|
| return bytecode == Bytecode::kCallRuntime ||
|
| - bytecode == Bytecode::kCallRuntimeWide ||
|
| - bytecode == Bytecode::kCallRuntimeForPair ||
|
| - bytecode == Bytecode::kCallRuntimeForPairWide;
|
| + bytecode == Bytecode::kCallRuntimeForPair;
|
| }
|
|
|
| // static
|
| @@ -304,42 +299,63 @@ bool Bytecodes::IsDebugBreak(Bytecode bytecode) {
|
| }
|
|
|
| // static
|
| +bool Bytecodes::IsBytecodeWithScalableOperands(Bytecode bytecode) {
|
| + switch (bytecode) {
|
| +#define CASE(Name, ...) \
|
| + case Bytecode::k##Name: \
|
| + typedef BytecodeTraits<__VA_ARGS__, OPERAND_TERM> Name##Trait; \
|
| + return Name##Trait::IsScalable();
|
| + BYTECODE_LIST(CASE)
|
| +#undef CASE
|
| + }
|
| + UNREACHABLE();
|
| + return false;
|
| +}
|
| +
|
| +// static
|
| bool Bytecodes::IsJumpOrReturn(Bytecode bytecode) {
|
| return bytecode == Bytecode::kReturn || IsJump(bytecode);
|
| }
|
|
|
| // static
|
| +bool Bytecodes::IsFlagOperandType(OperandType operand_type) {
|
| + return operand_type == OperandType::kFlag8;
|
| +}
|
| +
|
| +// static
|
| bool Bytecodes::IsIndexOperandType(OperandType operand_type) {
|
| - return operand_type == OperandType::kIdx8 ||
|
| - operand_type == OperandType::kIdx16;
|
| + return operand_type == OperandType::kIdx;
|
| }
|
|
|
| // static
|
| bool Bytecodes::IsImmediateOperandType(OperandType operand_type) {
|
| - return operand_type == OperandType::kImm8;
|
| + return operand_type == OperandType::kImm;
|
| }
|
|
|
| // static
|
| bool Bytecodes::IsRegisterCountOperandType(OperandType operand_type) {
|
| - return (operand_type == OperandType::kRegCount8 ||
|
| - operand_type == OperandType::kRegCount16);
|
| + return operand_type == OperandType::kRegCount;
|
| }
|
|
|
| // static
|
| bool Bytecodes::IsMaybeRegisterOperandType(OperandType operand_type) {
|
| - return (operand_type == OperandType::kMaybeReg8 ||
|
| - operand_type == OperandType::kMaybeReg16);
|
| + return operand_type == OperandType::kMaybeReg;
|
| +}
|
| +
|
| +// static
|
| +bool Bytecodes::IsRuntimeIdOperandType(OperandType operand_type) {
|
| + return operand_type == OperandType::kRuntimeId;
|
| }
|
|
|
| // static
|
| bool Bytecodes::IsRegisterOperandType(OperandType operand_type) {
|
| switch (operand_type) {
|
| -#define CASE(Name, _) \
|
| +#define CASE(Name, _, __) \
|
| case OperandType::k##Name: \
|
| return true;
|
| REGISTER_OPERAND_TYPE_LIST(CASE)
|
| #undef CASE
|
| -#define CASE(Name, _) \
|
| +#define CASE(Name, _, __) \
|
| case OperandType::k##Name: \
|
| break;
|
| NON_REGISTER_OPERAND_TYPE_LIST(CASE)
|
| @@ -351,12 +367,12 @@ bool Bytecodes::IsRegisterOperandType(OperandType operand_type) {
|
| // static
|
| bool Bytecodes::IsRegisterInputOperandType(OperandType operand_type) {
|
| switch (operand_type) {
|
| -#define CASE(Name, _) \
|
| +#define CASE(Name, _, __) \
|
| case OperandType::k##Name: \
|
| return true;
|
| REGISTER_INPUT_OPERAND_TYPE_LIST(CASE)
|
| #undef CASE
|
| -#define CASE(Name, _) \
|
| +#define CASE(Name, _, __) \
|
| case OperandType::k##Name: \
|
| break;
|
| NON_REGISTER_OPERAND_TYPE_LIST(CASE)
|
| @@ -369,12 +385,12 @@ bool Bytecodes::IsRegisterInputOperandType(OperandType operand_type) {
|
| // static
|
| bool Bytecodes::IsRegisterOutputOperandType(OperandType operand_type) {
|
| switch (operand_type) {
|
| -#define CASE(Name, _) \
|
| +#define CASE(Name, _, __) \
|
| case OperandType::k##Name: \
|
| return true;
|
| REGISTER_OUTPUT_OPERAND_TYPE_LIST(CASE)
|
| #undef CASE
|
| -#define CASE(Name, _) \
|
| +#define CASE(Name, _, __) \
|
| case OperandType::k##Name: \
|
| break;
|
| NON_REGISTER_OPERAND_TYPE_LIST(CASE)
|
| @@ -386,18 +402,52 @@ bool Bytecodes::IsRegisterOutputOperandType(OperandType operand_type) {
|
|
|
| namespace {
|
| static Register DecodeRegister(const uint8_t* operand_start,
|
| - OperandType operand_type) {
|
| - switch (Bytecodes::SizeOfOperand(operand_type)) {
|
| + OperandType operand_type, int operand_scale) {
|
| + switch (Bytecodes::SizeOfOperand(operand_type, operand_scale)) {
|
| case OperandSize::kByte:
|
| return Register::FromOperand(*operand_start);
|
| case OperandSize::kShort:
|
| return Register::FromWideOperand(ReadUnalignedUInt16(operand_start));
|
| + case OperandSize::kQuad:
|
| + return Register::FromWideOperand(ReadUnalignedUInt32(operand_start));
|
| case OperandSize::kNone: {
|
| UNREACHABLE();
|
| }
|
| }
|
| return Register();
|
| }
|
| +
|
| +static uint32_t DecodeUnsignedOperand(const uint8_t* operand_start,
|
| + OperandType operand_type,
|
| + int operand_scale) {
|
| + switch (Bytecodes::SizeOfOperand(operand_type, operand_scale)) {
|
| + case OperandSize::kByte:
|
| + return *operand_start;
|
| + case OperandSize::kShort:
|
| + return ReadUnalignedUInt16(operand_start);
|
| + case OperandSize::kQuad:
|
| + return ReadUnalignedUInt32(operand_start);
|
| + case OperandSize::kNone:
|
| + UNREACHABLE();
|
| + }
|
| + return 0;
|
| +}
|
| +
|
| +static int32_t DecodeSignedOperand(const uint8_t* operand_start,
|
| + OperandType operand_type,
|
| + int operand_scale) {
|
| + switch (Bytecodes::SizeOfOperand(operand_type, operand_scale)) {
|
| + case OperandSize::kByte:
|
| + return static_cast<int8_t>(*operand_start);
|
| + case OperandSize::kShort:
|
| + return static_cast<int16_t>(ReadUnalignedUInt16(operand_start));
|
| + case OperandSize::kQuad:
|
| + return static_cast<int32_t>(ReadUnalignedUInt32(operand_start));
|
| + case OperandSize::kNone:
|
| + UNREACHABLE();
|
| + }
|
| + return 0;
|
| +}
|
| } // namespace
|
|
|
|
|
| @@ -407,18 +457,31 @@ std::ostream& Bytecodes::Decode(std::ostream& os, const uint8_t* bytecode_start,
|
| Vector<char> buf = Vector<char>::New(50);
|
|
|
| Bytecode bytecode = Bytecodes::FromByte(bytecode_start[0]);
|
| - int bytecode_size = Bytecodes::Size(bytecode);
|
| + int prefix_offset = 0;
|
| + int operand_scale = Bytecodes::GetPrefixBytecodeScale(bytecode);
|
| + if (operand_scale > 1) {
|
| + prefix_offset += 1;
|
| + bytecode = Bytecodes::FromByte(bytecode_start[1]);
|
| + }
|
|
|
| - for (int i = 0; i < bytecode_size; i++) {
|
| + int bytecode_size = Bytecodes::Size(bytecode, operand_scale);
|
| +
|
| + for (int i = 0; i < prefix_offset + bytecode_size; i++) {
|
| SNPrintF(buf, "%02x ", bytecode_start[i]);
|
| os << buf.start();
|
| }
|
| const int kBytecodeColumnSize = 6;
|
| - for (int i = bytecode_size; i < kBytecodeColumnSize; i++) {
|
| + for (int i = prefix_offset + bytecode_size; i < kBytecodeColumnSize; i++) {
|
| os << " ";
|
| }
|
|
|
| - os << bytecode << " ";
|
| + os << bytecode;
|
| + if (operand_scale == 2) {
|
| + os << "." << Bytecodes::ToString(Bytecode::kWide);
|
| + } else if (operand_scale == 4) {
|
| + os << "." << Bytecodes::ToString(Bytecode::kExtraWide);
|
| + }
|
| + os << " ";
|
|
|
| // Operands for the debug break are from the original instruction.
|
| if (IsDebugBreak(bytecode)) return os;
|
| @@ -428,42 +491,41 @@ std::ostream& Bytecodes::Decode(std::ostream& os, const uint8_t* bytecode_start,
|
| for (int i = 0; i < number_of_operands; i++) {
|
| OperandType op_type = GetOperandType(bytecode, i);
|
| const uint8_t* operand_start =
|
| - &bytecode_start[GetOperandOffset(bytecode, i)];
|
| + &bytecode_start[prefix_offset +
|
| + GetOperandOffset(bytecode, i, operand_scale)];
|
| switch (op_type) {
|
| - case interpreter::OperandType::kRegCount8:
|
| - os << "#" << static_cast<unsigned int>(*operand_start);
|
| - break;
|
| - case interpreter::OperandType::kRegCount16:
|
| - os << '#' << ReadUnalignedUInt16(operand_start);
|
| + case interpreter::OperandType::kRegCount:
|
| + os << "#"
|
| + << DecodeUnsignedOperand(operand_start, op_type, operand_scale);
|
| break;
|
| - case interpreter::OperandType::kIdx8:
|
| - os << "[" << static_cast<unsigned int>(*operand_start) << "]";
|
| + case interpreter::OperandType::kIdx:
|
| + case interpreter::OperandType::kRuntimeId:
|
| + os << "["
|
| + << DecodeUnsignedOperand(operand_start, op_type, operand_scale)
|
| + << "]";
|
| break;
|
| - case interpreter::OperandType::kIdx16:
|
| - os << "[" << ReadUnalignedUInt16(operand_start) << "]";
|
| + case interpreter::OperandType::kImm:
|
| + os << "[" << DecodeSignedOperand(operand_start, op_type, operand_scale)
|
| + << "]";
|
| break;
|
| - case interpreter::OperandType::kImm8:
|
| - os << "#" << static_cast<int>(static_cast<int8_t>(*operand_start));
|
| + case interpreter::OperandType::kFlag8:
|
| + os << "#"
|
| + << DecodeUnsignedOperand(operand_start, op_type, operand_scale);
|
| break;
|
| - case interpreter::OperandType::kMaybeReg8:
|
| - case interpreter::OperandType::kMaybeReg16:
|
| - case interpreter::OperandType::kReg8:
|
| - case interpreter::OperandType::kReg16:
|
| - case interpreter::OperandType::kRegOut8:
|
| - case interpreter::OperandType::kRegOut16: {
|
| - Register reg = DecodeRegister(operand_start, op_type);
|
| + case interpreter::OperandType::kMaybeReg:
|
| + case interpreter::OperandType::kReg:
|
| + case interpreter::OperandType::kRegOut: {
|
| + Register reg = DecodeRegister(operand_start, op_type, operand_scale);
|
| os << reg.ToString(parameter_count);
|
| break;
|
| }
|
| - case interpreter::OperandType::kRegOutTriple8:
|
| - case interpreter::OperandType::kRegOutTriple16:
|
| + case interpreter::OperandType::kRegOutTriple:
|
| range += 1;
|
| - case interpreter::OperandType::kRegOutPair8:
|
| - case interpreter::OperandType::kRegOutPair16:
|
| - case interpreter::OperandType::kRegPair8:
|
| - case interpreter::OperandType::kRegPair16: {
|
| + case interpreter::OperandType::kRegOutPair:
|
| + case interpreter::OperandType::kRegPair: {
|
| range += 1;
|
| - Register first_reg = DecodeRegister(operand_start, op_type);
|
| + Register first_reg =
|
| + DecodeRegister(operand_start, op_type, operand_scale);
|
| Register last_reg = Register(first_reg.index() + range);
|
| os << first_reg.ToString(parameter_count) << "-"
|
| << last_reg.ToString(parameter_count);
|
|
|