Commit 479e8f23 authored by rmcilroy's avatar rmcilroy Committed by Commit bot

[Interpreter]: Add kRegList operand type for register list operands.

Also get rid of useless kMaybeReg type.

BUG=v8:4280

Review-Url: https://codereview.chromium.org/2382273002
Cr-Commit-Position: refs/heads/master@{#40001}
parent 99493fea
......@@ -857,19 +857,6 @@ bool BytecodeArrayBuilder::OperandsAreValid(
switch (operand_types[i]) {
case OperandType::kNone:
return false;
case OperandType::kRegCount: {
CHECK_NE(i, 0);
CHECK(operand_types[i - 1] == OperandType::kMaybeReg ||
operand_types[i - 1] == OperandType::kReg);
if (i > 0 && operands[i] > 0) {
Register start = Register::FromOperand(operands[i - 1]);
Register end(start.index() + static_cast<int>(operands[i]) - 1);
if (!RegisterIsValid(start) || !RegisterIsValid(end) || start > end) {
return false;
}
}
break;
}
case OperandType::kFlag8:
case OperandType::kIntrinsicId:
if (Bytecodes::SizeForUnsignedOperand(operands[i]) >
......@@ -890,11 +877,22 @@ bool BytecodeArrayBuilder::OperandsAreValid(
case OperandType::kUImm:
case OperandType::kImm:
break;
case OperandType::kMaybeReg:
if (Register::FromOperand(operands[i]) == Register(0)) {
break;
case OperandType::kRegList: {
CHECK_LT(i, operand_count - 1);
CHECK(operand_types[i + 1] == OperandType::kRegCount);
int reg_count = static_cast<int>(operands[i + 1]);
if (reg_count == 0) {
return Register::FromOperand(operands[i]) == Register(0);
} else {
Register start = Register::FromOperand(operands[i]);
Register end(start.index() + reg_count - 1);
if (!RegisterIsValid(start) || !RegisterIsValid(end) || start > end) {
return false;
}
}
// Fall-through to kReg case.
i++; // Skip past kRegCount operand.
break;
}
case OperandType::kReg:
case OperandType::kRegOut: {
Register reg = Register::FromOperand(operands[i]);
......@@ -922,6 +920,8 @@ bool BytecodeArrayBuilder::OperandsAreValid(
}
break;
}
case OperandType::kRegCount:
UNREACHABLE(); // Dealt with in kRegList above.
}
}
......
......@@ -140,11 +140,11 @@ int BytecodeArrayIterator::GetRegisterOperandRange(int operand_index) const {
DCHECK_LE(operand_index, Bytecodes::NumberOfOperands(current_bytecode()));
const OperandType* operand_types =
Bytecodes::GetOperandTypes(current_bytecode());
DCHECK(Bytecodes::IsRegisterOperandType(operand_types[operand_index]));
if (operand_types[operand_index + 1] == OperandType::kRegCount) {
OperandType operand_type = operand_types[operand_index];
DCHECK(Bytecodes::IsRegisterOperandType(operand_type));
if (operand_type == OperandType::kRegList) {
return GetRegisterCountOperand(operand_index + 1);
} else {
OperandType operand_type = operand_types[operand_index];
return Bytecodes::GetNumberOfRegistersRepresentedBy(operand_type);
}
}
......
......@@ -22,6 +22,15 @@ Register BytecodeDecoder::DecodeRegisterOperand(const uint8_t* operand_start,
return Register::FromOperand(operand);
}
// static
RegisterList BytecodeDecoder::DecodeRegisterListOperand(
const uint8_t* operand_start, uint32_t count, OperandType operand_type,
OperandScale operand_scale) {
Register first_reg =
DecodeRegisterOperand(operand_start, operand_type, operand_scale);
return RegisterList(first_reg.index(), static_cast<int>(count));
}
// static
int32_t BytecodeDecoder::DecodeSignedOperand(const uint8_t* operand_start,
OperandType operand_type,
......@@ -94,7 +103,6 @@ std::ostream& BytecodeDecoder::Decode(std::ostream& os,
if (Bytecodes::IsDebugBreak(bytecode)) return os;
int number_of_operands = Bytecodes::NumberOfOperands(bytecode);
int range = 0;
for (int i = 0; i < number_of_operands; i++) {
OperandType op_type = Bytecodes::GetOperandType(bytecode, i);
int operand_offset =
......@@ -102,10 +110,6 @@ std::ostream& BytecodeDecoder::Decode(std::ostream& os,
const uint8_t* operand_start =
&bytecode_start[prefix_offset + operand_offset];
switch (op_type) {
case interpreter::OperandType::kRegCount:
os << "#"
<< DecodeUnsignedOperand(operand_start, op_type, operand_scale);
break;
case interpreter::OperandType::kIdx:
case interpreter::OperandType::kUImm:
case interpreter::OperandType::kRuntimeId:
......@@ -122,7 +126,6 @@ std::ostream& BytecodeDecoder::Decode(std::ostream& os,
os << "#"
<< DecodeUnsignedOperand(operand_start, op_type, operand_scale);
break;
case interpreter::OperandType::kMaybeReg:
case interpreter::OperandType::kReg:
case interpreter::OperandType::kRegOut: {
Register reg =
......@@ -130,19 +133,40 @@ std::ostream& BytecodeDecoder::Decode(std::ostream& os,
os << reg.ToString(parameter_count);
break;
}
case interpreter::OperandType::kRegOutTriple:
range += 1;
case interpreter::OperandType::kRegOutTriple: {
RegisterList reg_list =
DecodeRegisterListOperand(operand_start, 3, op_type, operand_scale);
os << reg_list.first_register().ToString(parameter_count) << "-"
<< reg_list.last_register().ToString(parameter_count);
break;
}
case interpreter::OperandType::kRegOutPair:
case interpreter::OperandType::kRegPair: {
range += 1;
Register first_reg =
DecodeRegisterOperand(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);
RegisterList reg_list =
DecodeRegisterListOperand(operand_start, 2, op_type, operand_scale);
os << reg_list.first_register().ToString(parameter_count) << "-"
<< reg_list.last_register().ToString(parameter_count);
break;
}
case interpreter::OperandType::kRegList: {
DCHECK_LT(i, number_of_operands - 1);
DCHECK_EQ(Bytecodes::GetOperandType(bytecode, i + 1),
OperandType::kRegCount);
int reg_count_offset =
Bytecodes::GetOperandOffset(bytecode, i + 1, operand_scale);
const uint8_t* reg_count_operand =
&bytecode_start[prefix_offset + reg_count_offset];
uint32_t count = DecodeUnsignedOperand(
reg_count_operand, OperandType::kRegCount, operand_scale);
RegisterList reg_list = DecodeRegisterListOperand(
operand_start, count, op_type, operand_scale);
os << reg_list.first_register().ToString(parameter_count) << "-"
<< reg_list.last_register().ToString(parameter_count);
i++; // Skip kRegCount.
break;
}
case interpreter::OperandType::kNone:
case interpreter::OperandType::kRegCount: // Dealt with in kRegList.
UNREACHABLE();
break;
}
......
......@@ -21,6 +21,12 @@ class BytecodeDecoder final {
OperandType operand_type,
OperandScale operand_scale);
// Decodes a register list operand in a byte array.
static RegisterList DecodeRegisterListOperand(const uint8_t* operand_start,
uint32_t count,
OperandType operand_type,
OperandScale operand_scale);
// Decodes a signed operand in a byte array.
static int32_t DecodeSignedOperand(const uint8_t* operand_start,
OperandType operand_type,
......
......@@ -13,9 +13,9 @@ namespace interpreter {
#define INVALID_OPERAND_TYPE_LIST(V) V(None, OperandTypeInfo::kNone)
#define REGISTER_INPUT_OPERAND_TYPE_LIST(V) \
V(MaybeReg, OperandTypeInfo::kScalableSignedByte) \
V(Reg, OperandTypeInfo::kScalableSignedByte) \
#define REGISTER_INPUT_OPERAND_TYPE_LIST(V) \
V(RegList, OperandTypeInfo::kScalableSignedByte) \
V(Reg, OperandTypeInfo::kScalableSignedByte) \
V(RegPair, OperandTypeInfo::kScalableSignedByte)
#define REGISTER_OUTPUT_OPERAND_TYPE_LIST(V) \
......
......@@ -13,36 +13,6 @@ namespace v8 {
namespace internal {
namespace interpreter {
class RegisterList {
public:
RegisterList() : first_reg_index_(Register().index()), register_count_(0) {}
RegisterList(int first_reg_index, int register_count)
: first_reg_index_(first_reg_index), register_count_(register_count) {}
// Returns a new RegisterList which is a truncated version of this list, with
// |count| registers.
const RegisterList Truncate(int new_count) {
DCHECK_GE(new_count, 0);
DCHECK_LT(new_count, register_count_);
return RegisterList(first_reg_index_, new_count);
}
const Register operator[](size_t i) const {
DCHECK_LT(static_cast<int>(i), register_count_);
return Register(first_reg_index_ + static_cast<int>(i));
}
const Register first_register() const {
return (register_count() == 0) ? Register(0) : (*this)[0];
}
int register_count() const { return register_count_; }
private:
int first_reg_index_;
int register_count_;
};
// A class that allows the allocation of contiguous temporary registers.
class BytecodeRegisterAllocator final {
public:
......
......@@ -533,9 +533,9 @@ void BytecodeRegisterOptimizer::PrepareRegisterOperands(
Bytecodes::GetOperandTypes(node->bytecode());
for (int i = 0; i < operand_count; ++i) {
int count;
// operand_types is terminated by OperandType::kNone so this does not
// go out of bounds.
if (operand_types[i + 1] == OperandType::kRegCount) {
if (operand_types[i] == OperandType::kRegList) {
DCHECK_LT(i, operand_count - 1);
DCHECK(operand_types[i + 1] == OperandType::kRegCount);
count = static_cast<int>(operands[i + 1]);
} else {
count = Bytecodes::GetNumberOfRegistersRepresentedBy(operand_types[i]);
......
......@@ -121,7 +121,7 @@ bool Register::AreContiguous(Register reg1, Register reg2, Register reg3,
return true;
}
std::string Register::ToString(int parameter_count) {
std::string Register::ToString(int parameter_count) const {
if (is_current_context()) {
return std::string("<context>");
} else if (is_function_closure()) {
......
......@@ -66,7 +66,7 @@ class Register final {
Register reg4 = Register(),
Register reg5 = Register());
std::string ToString(int parameter_count);
std::string ToString(int parameter_count) const;
bool operator==(const Register& other) const {
return index() == other.index();
......@@ -98,6 +98,40 @@ class Register final {
int index_;
};
class RegisterList {
public:
RegisterList() : first_reg_index_(Register().index()), register_count_(0) {}
RegisterList(int first_reg_index, int register_count)
: first_reg_index_(first_reg_index), register_count_(register_count) {}
// Returns a new RegisterList which is a truncated version of this list, with
// |count| registers.
const RegisterList Truncate(int new_count) {
DCHECK_GE(new_count, 0);
DCHECK_LT(new_count, register_count_);
return RegisterList(first_reg_index_, new_count);
}
const Register operator[](size_t i) const {
DCHECK_LT(static_cast<int>(i), register_count_);
return Register(first_reg_index_ + static_cast<int>(i));
}
const Register first_register() const {
return (register_count() == 0) ? Register(0) : (*this)[0];
}
const Register last_register() const {
return (register_count() == 0) ? Register(0) : (*this)[register_count_ - 1];
}
int register_count() const { return register_count_; }
private:
int first_reg_index_;
int register_count_;
};
} // namespace interpreter
} // namespace internal
} // namespace v8
......
......@@ -143,24 +143,24 @@ namespace interpreter {
V(DeletePropertySloppy, AccumulatorUse::kReadWrite, OperandType::kReg) \
\
/* Call operations */ \
V(Call, AccumulatorUse::kWrite, OperandType::kReg, OperandType::kReg, \
OperandType::kRegCount, OperandType::kIdx) \
V(TailCall, AccumulatorUse::kWrite, OperandType::kReg, OperandType::kReg, \
V(Call, AccumulatorUse::kWrite, OperandType::kReg, OperandType::kRegList, \
OperandType::kRegCount, OperandType::kIdx) \
V(TailCall, AccumulatorUse::kWrite, OperandType::kReg, \
OperandType::kRegList, OperandType::kRegCount, OperandType::kIdx) \
V(CallRuntime, AccumulatorUse::kWrite, OperandType::kRuntimeId, \
OperandType::kMaybeReg, OperandType::kRegCount) \
OperandType::kRegList, OperandType::kRegCount) \
V(CallRuntimeForPair, AccumulatorUse::kNone, OperandType::kRuntimeId, \
OperandType::kMaybeReg, OperandType::kRegCount, OperandType::kRegOutPair) \
OperandType::kRegList, OperandType::kRegCount, OperandType::kRegOutPair) \
V(CallJSRuntime, AccumulatorUse::kWrite, OperandType::kIdx, \
OperandType::kReg, OperandType::kRegCount) \
OperandType::kRegList, OperandType::kRegCount) \
\
/* Intrinsics */ \
V(InvokeIntrinsic, AccumulatorUse::kWrite, OperandType::kIntrinsicId, \
OperandType::kMaybeReg, OperandType::kRegCount) \
OperandType::kRegList, OperandType::kRegCount) \
\
/* New operator */ \
V(New, AccumulatorUse::kReadWrite, OperandType::kReg, \
OperandType::kMaybeReg, OperandType::kRegCount, OperandType::kIdx) \
V(New, AccumulatorUse::kReadWrite, OperandType::kReg, OperandType::kRegList, \
OperandType::kRegCount, OperandType::kIdx) \
\
/* Test Operators */ \
V(TestEqual, AccumulatorUse::kReadWrite, OperandType::kReg, \
......@@ -648,10 +648,11 @@ class Bytecodes final {
static bool IsStarLookahead(Bytecode bytecode, OperandScale operand_scale);
// Returns the number of registers represented by a register operand. For
// instance, a RegPair represents two registers.
// instance, a RegPair represents two registers. Should not be called for
// kRegList which has a variable number of registers based on the following
// kRegCount operand.
static int GetNumberOfRegistersRepresentedBy(OperandType operand_type) {
switch (operand_type) {
case OperandType::kMaybeReg:
case OperandType::kReg:
case OperandType::kRegOut:
return 1;
......@@ -660,6 +661,9 @@ class Bytecodes final {
return 2;
case OperandType::kRegOutTriple:
return 3;
case OperandType::kRegList:
UNREACHABLE();
return 0;
default:
return 0;
}
......
......@@ -37,10 +37,18 @@ TEST(BytecodeDecoder, DecodeBytecodeAndOperands) {
"LdaSmi.ExtraWide [-100000]"},
{{B(Star), R8(5)}, 2, 0, " Star r5"},
{{B(Wide), B(Star), R16(136)}, 4, 0, " Star.Wide r136"},
{{B(Wide), B(Call), R16(134), R16(135), U16(2), U16(177)},
{{B(Wide), B(Call), R16(134), R16(135), U16(10), U16(177)},
10,
0,
"Call.Wide r134, r135, #2, [177]"},
"Call.Wide r134, r135-r144, [177]"},
{{B(ForInPrepare), R8(10), R8(11)},
3,
0,
" ForInPrepare r10, r11-r13"},
{{B(CallRuntime), U16(134), R8(0), U8(0)},
5,
0,
" CallRuntime [134], r0-r0"},
{{B(Ldar),
static_cast<uint8_t>(Register::FromParameterIndex(2, 3).ToOperand())},
2,
......
......@@ -430,7 +430,7 @@ TARGET_TEST_F(InterpreterAssemblerTest, BytecodeOperand) {
m.IsSignedOperand(offset, operand_size));
break;
}
case interpreter::OperandType::kMaybeReg:
case interpreter::OperandType::kRegList:
case interpreter::OperandType::kReg:
case interpreter::OperandType::kRegOut:
case interpreter::OperandType::kRegOutPair:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment