Commit 85882a63 authored by oth's avatar oth Committed by Commit bot

[interpreter] Remove OperandScale from front stages of pipeline.

BUG=v8:4280
LOG=N

Review-Url: https://codereview.chromium.org/2041913002
Cr-Commit-Position: refs/heads/master@{#36885}
parent 4ff921bc
This diff is collapsed.
......@@ -275,11 +275,23 @@ class BytecodeArrayBuilder final : public ZoneObject {
void EnsureReturn();
static uint32_t RegisterOperand(Register reg);
static Register RegisterFromOperand(uint32_t operand);
static uint32_t SignedOperand(int value, OperandSize size);
static uint32_t UnsignedOperand(int value);
static uint32_t UnsignedOperand(size_t value);
static uint32_t RegisterOperand(Register reg) {
return static_cast<uint32_t>(reg.ToOperand());
}
static uint32_t SignedOperand(int value) {
return static_cast<uint32_t>(value);
}
static uint32_t UnsignedOperand(int value) {
DCHECK_GE(value, 0);
return static_cast<uint32_t>(value);
}
static uint32_t UnsignedOperand(size_t value) {
DCHECK_LE(value, kMaxUInt32);
return static_cast<uint32_t>(value);
}
private:
friend class BytecodeRegisterAllocator;
......@@ -296,24 +308,21 @@ class BytecodeArrayBuilder final : public ZoneObject {
static Bytecode BytecodeForDelete(LanguageMode language_mode);
static Bytecode BytecodeForCall(TailCallMode tail_call_mode);
void Output(Bytecode bytecode, uint32_t operand0, uint32_t operand1,
uint32_t operand2, uint32_t operand3);
void Output(Bytecode bytecode, uint32_t operand0, uint32_t operand1,
uint32_t operand2);
void Output(Bytecode bytecode, uint32_t operand0, uint32_t operand1);
void Output(Bytecode bytecode, uint32_t operand0);
void Output(Bytecode bytecode);
void OutputScaled(Bytecode bytecode, OperandScale operand_scale,
uint32_t operand0, uint32_t operand1, uint32_t operand2,
uint32_t operand3);
void OutputScaled(Bytecode bytecode, OperandScale operand_scale,
uint32_t operand0, uint32_t operand1, uint32_t operand2);
void OutputScaled(Bytecode bytecode, OperandScale operand_scale,
uint32_t operand0, uint32_t operand1);
void OutputScaled(Bytecode bytecode, OperandScale operand_scale,
uint32_t operand0);
BytecodeArrayBuilder& OutputJump(Bytecode jump_bytecode,
BytecodeLabel* label);
bool OperandIsValid(Bytecode bytecode, OperandScale operand_scale,
int operand_index, uint32_t operand_value) const;
bool RegisterIsValid(Register reg, OperandSize reg_size) const;
bool RegisterIsValid(Register reg) const;
bool OperandsAreValid(Bytecode bytecode, int operand_count,
uint32_t operand0 = 0, uint32_t operand1 = 0,
uint32_t operand2 = 0, uint32_t operand3 = 0) const;
// Attach latest source position to |node|.
void AttachSourceInfo(BytecodeNode* node);
......
......@@ -105,10 +105,64 @@ void BytecodeArrayWriter::UpdateSourcePositionTable(
}
}
namespace {
OperandScale ScaleForScalableByteOperand(OperandSize operand_size) {
STATIC_ASSERT(static_cast<int>(OperandSize::kByte) ==
static_cast<int>(OperandScale::kSingle));
STATIC_ASSERT(static_cast<int>(OperandSize::kShort) ==
static_cast<int>(OperandScale::kDouble));
STATIC_ASSERT(static_cast<int>(OperandSize::kQuad) ==
static_cast<int>(OperandScale::kQuadruple));
return static_cast<OperandScale>(operand_size);
}
OperandScale OperandScaleForScalableSignedByte(uint32_t operand_value) {
int32_t signed_operand = static_cast<int32_t>(operand_value);
OperandSize bytes_required = Bytecodes::SizeForSignedOperand(signed_operand);
return ScaleForScalableByteOperand(bytes_required);
}
OperandScale OperandScaleForScalableUnsignedByte(uint32_t operand_value) {
OperandSize bytes_required = Bytecodes::SizeForUnsignedOperand(operand_value);
return ScaleForScalableByteOperand(bytes_required);
}
OperandScale GetOperandScale(const BytecodeNode* const node) {
const OperandTypeInfo* operand_type_infos =
Bytecodes::GetOperandTypeInfos(node->bytecode());
OperandScale operand_scale = OperandScale::kSingle;
for (int i = 0; i < node->operand_count(); ++i) {
switch (operand_type_infos[i]) {
case OperandTypeInfo::kScalableSignedByte: {
uint32_t operand = node->operand(i);
operand_scale =
std::max(operand_scale, OperandScaleForScalableSignedByte(operand));
break;
}
case OperandTypeInfo::kScalableUnsignedByte: {
uint32_t operand = node->operand(i);
operand_scale = std::max(operand_scale,
OperandScaleForScalableUnsignedByte(operand));
break;
}
case OperandTypeInfo::kFixedUnsignedByte:
case OperandTypeInfo::kFixedUnsignedShort:
break;
case OperandTypeInfo::kNone:
UNREACHABLE();
break;
}
}
return operand_scale;
}
} // namespace
void BytecodeArrayWriter::EmitBytecode(const BytecodeNode* const node) {
DCHECK_NE(node->bytecode(), Bytecode::kIllegal);
OperandScale operand_scale = node->operand_scale();
OperandScale operand_scale = GetOperandScale(node);
if (operand_scale != OperandScale::kSingle) {
Bytecode prefix = Bytecodes::OperandScaleToPrefixBytecode(operand_scale);
bytecodes()->push_back(Bytecodes::ToByte(prefix));
......@@ -160,23 +214,6 @@ void BytecodeArrayWriter::EmitBytecode(const BytecodeNode* const node) {
}
}
// TODO(rmcilroy): This is the same as SignedOperand in BytecodeArrayBuilder.
// Once we move the scalable operand processing here remove the SignedOperand
// in BytecodeArrayBuilder.
static uint32_t SignedOperand(int value, OperandSize size) {
switch (size) {
case OperandSize::kByte:
return static_cast<uint8_t>(value & 0xff);
case OperandSize::kShort:
return static_cast<uint16_t>(value & 0xffff);
case OperandSize::kQuad:
return static_cast<uint32_t>(value);
case OperandSize::kNone:
UNREACHABLE();
}
return 0;
}
// static
Bytecode GetJumpWithConstantOperand(Bytecode jump_bytecode) {
switch (jump_bytecode) {
......@@ -207,7 +244,7 @@ void BytecodeArrayWriter::PatchJumpWith8BitOperand(size_t jump_location,
Bytecode jump_bytecode = Bytecodes::FromByte(bytecodes()->at(jump_location));
DCHECK(Bytecodes::IsJumpImmediate(jump_bytecode));
size_t operand_location = jump_location + 1;
DCHECK_EQ(bytecodes()->at(operand_location), 0);
DCHECK_EQ(bytecodes()->at(operand_location), k8BitJumpPlaceholder);
if (Bytecodes::SizeForSignedOperand(delta) == OperandSize::kByte) {
// The jump fits within the range of an Imm operand, so cancel
// the reservation and jump directly.
......@@ -219,7 +256,9 @@ void BytecodeArrayWriter::PatchJumpWith8BitOperand(size_t jump_location,
// and update the jump instruction and operand.
size_t entry = constant_array_builder()->CommitReservedEntry(
OperandSize::kByte, handle(Smi::FromInt(delta), isolate()));
DCHECK(Bytecodes::SizeForUnsignedOperand(entry) == OperandSize::kByte);
DCHECK_LE(entry, kMaxUInt32);
DCHECK_EQ(Bytecodes::SizeForUnsignedOperand(static_cast<uint32_t>(entry)),
OperandSize::kByte);
jump_bytecode = GetJumpWithConstantOperand(jump_bytecode);
bytecodes()->at(jump_location) = Bytecodes::ToByte(jump_bytecode);
bytecodes()->at(operand_location) = static_cast<uint8_t>(entry);
......@@ -242,8 +281,8 @@ void BytecodeArrayWriter::PatchJumpWith16BitOperand(size_t jump_location,
OperandSize::kShort, handle(Smi::FromInt(delta), isolate()));
WriteUnalignedUInt16(operand_bytes, static_cast<uint16_t>(entry));
}
DCHECK(bytecodes()->at(operand_location) == 0 &&
bytecodes()->at(operand_location + 1) == 0);
DCHECK(bytecodes()->at(operand_location) == k8BitJumpPlaceholder &&
bytecodes()->at(operand_location + 1) == k8BitJumpPlaceholder);
bytecodes()->at(operand_location++) = operand_bytes[0];
bytecodes()->at(operand_location) = operand_bytes[1];
}
......@@ -256,10 +295,10 @@ void BytecodeArrayWriter::PatchJumpWith32BitOperand(size_t jump_location,
uint8_t operand_bytes[4];
WriteUnalignedUInt32(operand_bytes, static_cast<uint32_t>(delta));
size_t operand_location = jump_location + 1;
DCHECK(bytecodes()->at(operand_location) == 0 &&
bytecodes()->at(operand_location + 1) == 0 &&
bytecodes()->at(operand_location + 2) == 0 &&
bytecodes()->at(operand_location + 3) == 0);
DCHECK(bytecodes()->at(operand_location) == k8BitJumpPlaceholder &&
bytecodes()->at(operand_location + 1) == k8BitJumpPlaceholder &&
bytecodes()->at(operand_location + 2) == k8BitJumpPlaceholder &&
bytecodes()->at(operand_location + 3) == k8BitJumpPlaceholder);
bytecodes()->at(operand_location++) = operand_bytes[0];
bytecodes()->at(operand_location++) = operand_bytes[1];
bytecodes()->at(operand_location++) = operand_bytes[2];
......@@ -316,8 +355,7 @@ void BytecodeArrayWriter::EmitJump(BytecodeNode* node, BytecodeLabel* label) {
DCHECK_LE(delta, 0);
delta -= 1;
}
node->set_bytecode(node->bytecode(), SignedOperand(delta, operand_size),
Bytecodes::OperandSizesToScale(operand_size));
node->set_bytecode(node->bytecode(), delta);
} else {
// The label has not yet been bound so this is a forward reference
// that will be patched when the label is bound. We create a
......@@ -329,9 +367,20 @@ void BytecodeArrayWriter::EmitJump(BytecodeNode* node, BytecodeLabel* label) {
label->set_referrer(current_offset);
OperandSize reserved_operand_size =
constant_array_builder()->CreateReservedEntry();
OperandScale operand_scale =
Bytecodes::OperandSizesToScale(reserved_operand_size);
node->set_bytecode(node->bytecode(), 0, operand_scale);
switch (reserved_operand_size) {
case OperandSize::kNone:
UNREACHABLE();
break;
case OperandSize::kByte:
node->set_bytecode(node->bytecode(), k8BitJumpPlaceholder);
break;
case OperandSize::kShort:
node->set_bytecode(node->bytecode(), k16BitJumpPlaceholder);
break;
case OperandSize::kQuad:
node->set_bytecode(node->bytecode(), k32BitJumpPlaceholder);
break;
}
}
EmitBytecode(node);
}
......
......@@ -34,6 +34,15 @@ class BytecodeArrayWriter final : public BytecodePipelineStage {
Handle<FixedArray> handler_table) override;
private:
// Constants that act as placeholders for jump operands to be
// patched. These have operand sizes that match the sizes of
// reserved constant pool entries.
const uint32_t k8BitJumpPlaceholder = 0x7f;
const uint32_t k16BitJumpPlaceholder =
k8BitJumpPlaceholder | (k8BitJumpPlaceholder << 8);
const uint32_t k32BitJumpPlaceholder =
k16BitJumpPlaceholder | (k16BitJumpPlaceholder << 16);
void PatchJump(size_t jump_target, size_t jump_location);
void PatchJumpWith8BitOperand(size_t jump_location, int delta);
void PatchJumpWith16BitOperand(size_t jump_location, int delta);
......
......@@ -184,9 +184,8 @@ void TransformLdaStarToLdrLdar(Bytecode new_bytecode, BytecodeNode* const last,
// accumulator. However, in the second form the Ldar can often be
// peephole optimized away unlike the Star in the first form.
//
last->Transform(new_bytecode, current->operand(0), current->operand_scale());
current->set_bytecode(Bytecode::kLdar, current->operand(0),
current->operand_scale());
last->Transform(new_bytecode, current->operand(0));
current->set_bytecode(Bytecode::kLdar, current->operand(0));
}
} // namespace
......@@ -232,7 +231,7 @@ bool BytecodePeepholeOptimizer::RemoveToBooleanFromJump(
// element can be removed if the previous bytecode put a boolean
// value in the accumulator.
Bytecode jump = Bytecodes::GetJumpWithoutToBoolean(current->bytecode());
current->set_bytecode(jump, current->operand(0), current->operand_scale());
current->set_bytecode(jump, current->operand(0));
}
return can_remove;
}
......
......@@ -34,47 +34,40 @@ void BytecodeSourceInfo::Update(const BytecodeSourceInfo& entry) {
BytecodeNode::BytecodeNode(Bytecode bytecode) {
DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 0);
bytecode_ = bytecode;
operand_scale_ = OperandScale::kSingle;
}
BytecodeNode::BytecodeNode(Bytecode bytecode, uint32_t operand0,
OperandScale operand_scale) {
BytecodeNode::BytecodeNode(Bytecode bytecode, uint32_t operand0) {
DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 1);
bytecode_ = bytecode;
operands_[0] = operand0;
operand_scale_ = operand_scale;
}
BytecodeNode::BytecodeNode(Bytecode bytecode, uint32_t operand0,
uint32_t operand1, OperandScale operand_scale) {
uint32_t operand1) {
DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 2);
bytecode_ = bytecode;
operands_[0] = operand0;
operands_[1] = operand1;
operand_scale_ = operand_scale;
}
BytecodeNode::BytecodeNode(Bytecode bytecode, uint32_t operand0,
uint32_t operand1, uint32_t operand2,
OperandScale operand_scale) {
uint32_t operand1, uint32_t operand2) {
DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 3);
bytecode_ = bytecode;
operands_[0] = operand0;
operands_[1] = operand1;
operands_[2] = operand2;
operand_scale_ = operand_scale;
}
BytecodeNode::BytecodeNode(Bytecode bytecode, uint32_t operand0,
uint32_t operand1, uint32_t operand2,
uint32_t operand3, OperandScale operand_scale) {
uint32_t operand3) {
DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 4);
bytecode_ = bytecode;
operands_[0] = operand0;
operands_[1] = operand1;
operands_[2] = operand2;
operands_[3] = operand3;
operand_scale_ = operand_scale;
}
BytecodeNode::BytecodeNode(const BytecodeNode& other) {
......@@ -89,15 +82,12 @@ BytecodeNode& BytecodeNode::operator=(const BytecodeNode& other) {
void BytecodeNode::set_bytecode(Bytecode bytecode) {
DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 0);
bytecode_ = bytecode;
operand_scale_ = OperandScale::kSingle;
}
void BytecodeNode::set_bytecode(Bytecode bytecode, uint32_t operand0,
OperandScale operand_scale) {
void BytecodeNode::set_bytecode(Bytecode bytecode, uint32_t operand0) {
DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 1);
bytecode_ = bytecode;
operands_[0] = operand0;
operand_scale_ = operand_scale;
}
void BytecodeNode::Clone(const BytecodeNode* const other) {
......@@ -108,13 +98,7 @@ void BytecodeNode::Print(std::ostream& os) const {
#ifdef DEBUG
std::ios saved_state(nullptr);
saved_state.copyfmt(os);
os << Bytecodes::ToString(bytecode_);
if (Bytecodes::OperandScaleRequiresPrefixBytecode(operand_scale_)) {
Bytecode scale_prefix =
Bytecodes::OperandScaleToPrefixBytecode(operand_scale_);
os << '.' << Bytecodes::ToString(scale_prefix);
}
for (int i = 0; i < operand_count(); ++i) {
os << ' ' << std::setw(8) << std::setfill('0') << std::hex << operands_[i];
......@@ -130,16 +114,7 @@ void BytecodeNode::Print(std::ostream& os) const {
#endif // DEBUG
}
size_t BytecodeNode::Size() const {
size_t size = Bytecodes::Size(bytecode_, operand_scale_);
if (Bytecodes::OperandScaleRequiresPrefixBytecode(operand_scale_)) {
size += 1;
}
return size;
}
void BytecodeNode::Transform(Bytecode new_bytecode, uint32_t extra_operand,
OperandScale extra_operand_scale) {
void BytecodeNode::Transform(Bytecode new_bytecode, uint32_t extra_operand) {
DCHECK_EQ(Bytecodes::NumberOfOperands(new_bytecode),
Bytecodes::NumberOfOperands(bytecode()) + 1);
DCHECK(Bytecodes::NumberOfOperands(bytecode()) < 1 ||
......@@ -152,7 +127,6 @@ void BytecodeNode::Transform(Bytecode new_bytecode, uint32_t extra_operand,
Bytecodes::GetOperandType(new_bytecode, 2) ==
Bytecodes::GetOperandType(bytecode(), 2));
DCHECK(Bytecodes::NumberOfOperands(bytecode()) < 4);
operand_scale_ = std::max(extra_operand_scale, operand_scale());
operands_[operand_count()] = extra_operand;
bytecode_ = new_bytecode;
}
......@@ -173,11 +147,6 @@ bool BytecodeNode::operator==(const BytecodeNode& other) const {
return true;
}
std::ostream& operator<<(std::ostream& os, const BytecodeNode& node) {
node.Print(os);
return os;
}
std::ostream& operator<<(std::ostream& os, const BytecodeSourceInfo& info) {
if (info.is_valid()) {
char description = info.is_statement() ? 'S' : 'E';
......@@ -186,6 +155,11 @@ std::ostream& operator<<(std::ostream& os, const BytecodeSourceInfo& info) {
return os;
}
std::ostream& operator<<(std::ostream& os, const BytecodeNode& node) {
node.Print(os);
return os;
}
} // namespace interpreter
} // namespace internal
} // namespace v8
......@@ -91,22 +91,18 @@ class BytecodeSourceInfo final {
class BytecodeNode final : ZoneObject {
public:
explicit BytecodeNode(Bytecode bytecode = Bytecode::kIllegal);
BytecodeNode(Bytecode bytecode, uint32_t operand0,
OperandScale operand_scale);
BytecodeNode(Bytecode bytecode, uint32_t operand0);
BytecodeNode(Bytecode bytecode, uint32_t operand0, uint32_t operand1);
BytecodeNode(Bytecode bytecode, uint32_t operand0, uint32_t operand1,
OperandScale operand_scale);
uint32_t operand2);
BytecodeNode(Bytecode bytecode, uint32_t operand0, uint32_t operand1,
uint32_t operand2, OperandScale operand_scale);
BytecodeNode(Bytecode bytecode, uint32_t operand0, uint32_t operand1,
uint32_t operand2, uint32_t operand3,
OperandScale operand_scale);
uint32_t operand2, uint32_t operand3);
BytecodeNode(const BytecodeNode& other);
BytecodeNode& operator=(const BytecodeNode& other);
void set_bytecode(Bytecode bytecode);
void set_bytecode(Bytecode bytecode, uint32_t operand0,
OperandScale operand_scale);
void set_bytecode(Bytecode bytecode, uint32_t operand0);
// Clone |other|.
void Clone(const BytecodeNode* const other);
......@@ -114,13 +110,9 @@ class BytecodeNode final : ZoneObject {
// Print to stream |os|.
void Print(std::ostream& os) const;
// Return the size when this node is serialized to a bytecode array.
size_t Size() const;
// Transform to a node representing |new_bytecode| which has one
// operand more than the current bytecode.
void Transform(Bytecode new_bytecode, uint32_t extra_operand,
OperandScale extra_operand_scale);
void Transform(Bytecode new_bytecode, uint32_t extra_operand);
Bytecode bytecode() const { return bytecode_; }
......@@ -132,10 +124,6 @@ class BytecodeNode final : ZoneObject {
const uint32_t* operands() const { return operands_; }
int operand_count() const { return Bytecodes::NumberOfOperands(bytecode_); }
OperandScale operand_scale() const { return operand_scale_; }
void set_operand_scale(OperandScale operand_scale) {
operand_scale_ = operand_scale;
}
const BytecodeSourceInfo& source_info() const { return source_info_; }
BytecodeSourceInfo& source_info() { return source_info_; }
......@@ -149,7 +137,6 @@ class BytecodeNode final : ZoneObject {
Bytecode bytecode_;
uint32_t operands_[kMaxOperands];
OperandScale operand_scale_;
BytecodeSourceInfo source_info_;
};
......
......@@ -324,20 +324,16 @@ void BytecodeRegisterOptimizer::OutputRegisterTransfer(
if (input == accumulator_) {
uint32_t operand = static_cast<uint32_t>(output.ToOperand());
OperandScale scale = Bytecodes::OperandSizesToScale(output.SizeOfOperand());
BytecodeNode node(Bytecode::kStar, operand, scale);
BytecodeNode node(Bytecode::kStar, operand);
WriteToNextStage(&node, source_info);
} else if (output == accumulator_) {
uint32_t operand = static_cast<uint32_t>(input.ToOperand());
OperandScale scale = Bytecodes::OperandSizesToScale(input.SizeOfOperand());
BytecodeNode node(Bytecode::kLdar, operand, scale);
BytecodeNode node(Bytecode::kLdar, operand);
WriteToNextStage(&node, source_info);
} else {
uint32_t operand0 = static_cast<uint32_t>(input.ToOperand());
uint32_t operand1 = static_cast<uint32_t>(output.ToOperand());
OperandScale scale = Bytecodes::OperandSizesToScale(input.SizeOfOperand(),
output.SizeOfOperand());
BytecodeNode node(Bytecode::kMov, operand0, operand1, scale);
BytecodeNode node(Bytecode::kMov, operand0, operand1);
WriteToNextStage(&node, source_info);
}
output_info->set_materialized(true);
......@@ -483,12 +479,6 @@ void BytecodeRegisterOptimizer::PrepareRegisterInputOperand(
Register equivalent = GetEquivalentRegisterForInputOperand(reg);
node->operands()[operand_index] =
static_cast<uint32_t>(equivalent.ToOperand());
// Update operand scale as equivalent may be different.
OperandScale operand_scale =
Bytecodes::OperandSizesToScale(equivalent.SizeOfOperand());
if (operand_scale > node->operand_scale()) {
node->set_operand_scale(operand_scale);
}
}
void BytecodeRegisterOptimizer::PrepareRegisterRangeInputOperand(Register start,
......
......@@ -30,13 +30,15 @@ OPERAND_TYPE_INFO_LIST(DECLARE_OPERAND_TYPE_INFO)
template <OperandType>
struct OperandTraits {
typedef OperandTypeInfoTraits<OperandTypeInfo::kNone> TypeInfo;
typedef OperandTypeInfoTraits<OperandTypeInfo::kNone> TypeInfoTraits;
static const OperandTypeInfo kOperandTypeInfo = OperandTypeInfo::kNone;
};
#define DECLARE_OPERAND_TYPE_TRAITS(Name, InfoType) \
template <> \
struct OperandTraits<OperandType::k##Name> { \
typedef OperandTypeInfoTraits<InfoType> TypeInfo; \
#define DECLARE_OPERAND_TYPE_TRAITS(Name, InfoType) \
template <> \
struct OperandTraits<OperandType::k##Name> { \
typedef OperandTypeInfoTraits<InfoType> TypeInfoTraits; \
static const OperandTypeInfo kOperandTypeInfo = InfoType; \
};
OPERAND_TYPE_LIST(DECLARE_OPERAND_TYPE_TRAITS)
#undef DECLARE_OPERAND_TYPE_TRAITS
......@@ -57,8 +59,8 @@ struct OperandScaler {
};
static const int kSize =
Helper<OperandTraits<operand_type>::TypeInfo::kIsScalable,
OperandTraits<operand_type>::TypeInfo::kUnscaledSize,
Helper<OperandTraits<operand_type>::TypeInfoTraits::kIsScalable,
OperandTraits<operand_type>::TypeInfoTraits::kUnscaledSize,
operand_scale>::kSize;
static const OperandSize kOperandSize = static_cast<OperandSize>(kSize);
};
......@@ -89,6 +91,15 @@ struct BytecodeTraits<accumulator_use, operand_0, operand_1, operand_2,
return operand_types;
}
static const OperandTypeInfo* GetOperandTypeInfos() {
static const OperandTypeInfo operand_type_infos[] = {
OperandTraits<operand_0>::kOperandTypeInfo,
OperandTraits<operand_1>::kOperandTypeInfo,
OperandTraits<operand_2>::kOperandTypeInfo,
OperandTraits<operand_3>::kOperandTypeInfo, OperandTypeInfo::kNone};
return operand_type_infos;
}
static const OperandSize* GetOperandSizes(OperandScale operand_scale) {
switch (operand_scale) {
#define CASE(Name, _) \
......@@ -115,10 +126,10 @@ struct BytecodeTraits<accumulator_use, operand_0, operand_1, operand_2,
}
static inline bool IsScalable() {
return (OperandTraits<operand_0>::TypeInfo::kIsScalable |
OperandTraits<operand_1>::TypeInfo::kIsScalable |
OperandTraits<operand_2>::TypeInfo::kIsScalable |
OperandTraits<operand_3>::TypeInfo::kIsScalable);
return (OperandTraits<operand_0>::TypeInfoTraits::kIsScalable |
OperandTraits<operand_1>::TypeInfoTraits::kIsScalable |
OperandTraits<operand_2>::TypeInfoTraits::kIsScalable |
OperandTraits<operand_3>::TypeInfoTraits::kIsScalable);
}
static const AccumulatorUse kAccumulatorUse = accumulator_use;
......@@ -144,6 +155,14 @@ struct BytecodeTraits<accumulator_use, operand_0, operand_1, operand_2> {
return operand_types;
}
static const OperandTypeInfo* GetOperandTypeInfos() {
static const OperandTypeInfo operand_type_infos[] = {
OperandTraits<operand_0>::kOperandTypeInfo,
OperandTraits<operand_1>::kOperandTypeInfo,
OperandTraits<operand_2>::kOperandTypeInfo, OperandTypeInfo::kNone};
return operand_type_infos;
}
static const OperandSize* GetOperandSizes(OperandScale operand_scale) {
switch (operand_scale) {
#define CASE(Name, _) \
......@@ -168,9 +187,9 @@ struct BytecodeTraits<accumulator_use, operand_0, operand_1, operand_2> {
}
static inline bool IsScalable() {
return (OperandTraits<operand_0>::TypeInfo::kIsScalable |
OperandTraits<operand_1>::TypeInfo::kIsScalable |
OperandTraits<operand_2>::TypeInfo::kIsScalable);
return (OperandTraits<operand_0>::TypeInfoTraits::kIsScalable |
OperandTraits<operand_1>::TypeInfoTraits::kIsScalable |
OperandTraits<operand_2>::TypeInfoTraits::kIsScalable);
}
static const AccumulatorUse kAccumulatorUse = accumulator_use;
......@@ -194,6 +213,13 @@ struct BytecodeTraits<accumulator_use, operand_0, operand_1> {
return operand_types;
}
static const OperandTypeInfo* GetOperandTypeInfos() {
static const OperandTypeInfo operand_type_infos[] = {
OperandTraits<operand_0>::kOperandTypeInfo,
OperandTraits<operand_1>::kOperandTypeInfo, OperandTypeInfo::kNone};
return operand_type_infos;
}
static const OperandSize* GetOperandSizes(OperandScale operand_scale) {
switch (operand_scale) {
#define CASE(Name, _) \
......@@ -217,8 +243,8 @@ struct BytecodeTraits<accumulator_use, operand_0, operand_1> {
}
static inline bool IsScalable() {
return (OperandTraits<operand_0>::TypeInfo::kIsScalable |
OperandTraits<operand_1>::TypeInfo::kIsScalable);
return (OperandTraits<operand_0>::TypeInfoTraits::kIsScalable |
OperandTraits<operand_1>::TypeInfoTraits::kIsScalable);
}
static const AccumulatorUse kAccumulatorUse = accumulator_use;
......@@ -238,6 +264,12 @@ struct BytecodeTraits<accumulator_use, operand_0> {
return operand_types;
}
static const OperandTypeInfo* GetOperandTypeInfos() {
static const OperandTypeInfo operand_type_infos[] = {
OperandTraits<operand_0>::kOperandTypeInfo, OperandTypeInfo::kNone};
return operand_type_infos;
}
static const OperandSize* GetOperandSizes(OperandScale operand_scale) {
switch (operand_scale) {
#define CASE(Name, _) \
......@@ -260,7 +292,7 @@ struct BytecodeTraits<accumulator_use, operand_0> {
}
static inline bool IsScalable() {
return OperandTraits<operand_0>::TypeInfo::kIsScalable;
return OperandTraits<operand_0>::TypeInfoTraits::kIsScalable;
}
static const AccumulatorUse kAccumulatorUse = accumulator_use;
......@@ -278,6 +310,12 @@ struct BytecodeTraits<accumulator_use> {
return operand_types;
}
static const OperandTypeInfo* GetOperandTypeInfos() {
static const OperandTypeInfo operand_type_infos[] = {
OperandTypeInfo::kNone};
return operand_type_infos;
}
static const OperandSize* GetOperandSizes(OperandScale operand_scale) {
return nullptr;
}
......
......@@ -6,6 +6,7 @@
#include <iomanip>
#include "src/base/bits.h"
#include "src/frames.h"
#include "src/interpreter/bytecode-traits.h"
#include "src/interpreter/interpreter.h"
......@@ -323,6 +324,20 @@ const OperandType* Bytecodes::GetOperandTypes(Bytecode bytecode) {
return nullptr;
}
// static
const OperandTypeInfo* Bytecodes::GetOperandTypeInfos(Bytecode bytecode) {
DCHECK(bytecode <= Bytecode::kLast);
switch (bytecode) {
#define CASE(Name, ...) \
case Bytecode::k##Name: \
return BytecodeTraits<__VA_ARGS__>::GetOperandTypeInfos();
BYTECODE_LIST(CASE)
#undef CASE
}
UNREACHABLE();
return nullptr;
}
// static
OperandSize Bytecodes::GetOperandSize(Bytecode bytecode, int i,
OperandScale operand_scale) {
......@@ -598,7 +613,7 @@ bool Bytecodes::IsUnsignedOperandType(OperandType operand_type) {
switch (operand_type) {
#define CASE(Name, _) \
case OperandType::k##Name: \
return OperandTraits<OperandType::k##Name>::TypeInfo::kIsUnsigned;
return OperandTraits<OperandType::k##Name>::TypeInfoTraits::kIsUnsigned;
OPERAND_TYPE_LIST(CASE)
#undef CASE
}
......@@ -608,9 +623,9 @@ bool Bytecodes::IsUnsignedOperandType(OperandType operand_type) {
// static
OperandSize Bytecodes::SizeForSignedOperand(int value) {
if (kMinInt8 <= value && value <= kMaxInt8) {
if (value >= kMinInt8 && value <= kMaxInt8) {
return OperandSize::kByte;
} else if (kMinInt16 <= value && value <= kMaxInt16) {
} else if (value >= kMinInt16 && value <= kMaxInt16) {
return OperandSize::kShort;
} else {
return OperandSize::kQuad;
......@@ -618,8 +633,7 @@ OperandSize Bytecodes::SizeForSignedOperand(int value) {
}
// static
OperandSize Bytecodes::SizeForUnsignedOperand(int value) {
DCHECK_GE(value, 0);
OperandSize Bytecodes::SizeForUnsignedOperand(uint32_t value) {
if (value <= kMaxUInt8) {
return OperandSize::kByte;
} else if (value <= kMaxUInt16) {
......@@ -629,69 +643,6 @@ OperandSize Bytecodes::SizeForUnsignedOperand(int value) {
}
}
OperandSize Bytecodes::SizeForUnsignedOperand(size_t value) {
if (value <= static_cast<size_t>(kMaxUInt8)) {
return OperandSize::kByte;
} else if (value <= static_cast<size_t>(kMaxUInt16)) {
return OperandSize::kShort;
} else if (value <= kMaxUInt32) {
return OperandSize::kQuad;
} else {
UNREACHABLE();
return OperandSize::kQuad;
}
}
OperandScale Bytecodes::OperandSizesToScale(OperandSize size0) {
OperandScale operand_scale = static_cast<OperandScale>(size0);
DCHECK(operand_scale == OperandScale::kSingle ||
operand_scale == OperandScale::kDouble ||
operand_scale == OperandScale::kQuadruple);
return operand_scale;
}
OperandScale Bytecodes::OperandSizesToScale(OperandSize size0,
OperandSize size1) {
OperandSize operand_size = std::max(size0, size1);
// Operand sizes have been scaled before calling this function.
// Currently all scalable operands are byte sized at
// OperandScale::kSingle.
STATIC_ASSERT(static_cast<int>(OperandSize::kByte) ==
static_cast<int>(OperandScale::kSingle) &&
static_cast<int>(OperandSize::kShort) ==
static_cast<int>(OperandScale::kDouble) &&
static_cast<int>(OperandSize::kQuad) ==
static_cast<int>(OperandScale::kQuadruple));
OperandScale operand_scale = static_cast<OperandScale>(operand_size);
DCHECK(operand_scale == OperandScale::kSingle ||
operand_scale == OperandScale::kDouble ||
operand_scale == OperandScale::kQuadruple);
return operand_scale;
}
OperandScale Bytecodes::OperandSizesToScale(OperandSize size0,
OperandSize size1,
OperandSize size2,
OperandSize size3) {
OperandSize upper = std::max(size0, size1);
OperandSize lower = std::max(size2, size3);
OperandSize result = std::max(upper, lower);
// Operand sizes have been scaled before calling this function.
// Currently all scalable operands are byte sized at
// OperandScale::kSingle.
STATIC_ASSERT(static_cast<int>(OperandSize::kByte) ==
static_cast<int>(OperandScale::kSingle) &&
static_cast<int>(OperandSize::kShort) ==
static_cast<int>(OperandScale::kDouble) &&
static_cast<int>(OperandSize::kQuad) ==
static_cast<int>(OperandScale::kQuadruple));
OperandScale operand_scale = static_cast<OperandScale>(result);
DCHECK(operand_scale == OperandScale::kSingle ||
operand_scale == OperandScale::kDouble ||
operand_scale == OperandScale::kQuadruple);
return operand_scale;
}
// static
Register Bytecodes::DecodeRegisterOperand(const uint8_t* operand_start,
OperandType operand_type,
......
......@@ -518,6 +518,10 @@ class Bytecodes {
// OperandType::kNone.
static const OperandType* GetOperandTypes(Bytecode bytecode);
// Returns a pointer to an array of operand type info terminated in
// OperandTypeInfo::kNone.
static const OperandTypeInfo* GetOperandTypeInfos(Bytecode bytecode);
// Returns the size of the i-th operand of |bytecode|.
static OperandSize GetOperandSize(Bytecode bytecode, int i,
OperandScale operand_scale);
......@@ -652,18 +656,7 @@ class Bytecodes {
static OperandSize SizeForSignedOperand(int value);
// Return the operand size required to hold an unsigned operand.
static OperandSize SizeForUnsignedOperand(int value);
// Return the operand size required to hold an unsigned operand.
static OperandSize SizeForUnsignedOperand(size_t value);
// Return the OperandScale required for bytecode emission of
// operand sizes.
static OperandScale OperandSizesToScale(OperandSize size0);
static OperandScale OperandSizesToScale(OperandSize size0, OperandSize size1);
static OperandScale OperandSizesToScale(
OperandSize size0, OperandSize size1, OperandSize size2,
OperandSize size3 = OperandSize::kByte);
static OperandSize SizeForUnsignedOperand(uint32_t value);
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(Bytecodes);
......
......@@ -523,11 +523,11 @@ snippet: "
"
frame size: 157
parameter count: 1
bytecode array length: 19
bytecode array length: 17
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 1494 S> */ B(LdaSmi), U8(3),
/* 1501 E> */ B(Wide), B(TestGreaterThan), R16(2),
/* 1501 E> */ B(TestGreaterThan), R(2),
B(JumpIfFalse), U8(7),
/* 1508 S> */ B(Wide), B(Ldar), R16(129),
/* 1536 S> */ B(Return),
......@@ -705,7 +705,7 @@ snippet: "
"
frame size: 157
parameter count: 1
bytecode array length: 36
bytecode array length: 34
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 1503 S> */ B(LdaZero),
......@@ -716,7 +716,7 @@ bytecodes: [
/* 1534 S> */ B(Wide), B(Mov), R16(0), R16(129),
B(Ldar), R(0),
/* 1540 S> */ B(LdaSmi), U8(3),
/* 1547 E> */ B(Wide), B(TestGreaterThan), R16(2),
/* 1547 E> */ B(TestGreaterThan), R(2),
B(JumpIfFalse), U8(5),
/* 1554 S> */ B(Ldar), R(0),
/* 1580 S> */ B(Return),
......@@ -893,7 +893,7 @@ snippet: "
"
frame size: 158
parameter count: 1
bytecode array length: 58
bytecode array length: 56
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 1503 S> */ B(LdaZero),
......@@ -904,10 +904,10 @@ bytecodes: [
B(Wide), B(Star), R16(128),
/* 1538 S> */ B(LdaSmi), U8(64),
/* 1538 E> */ B(Wide), B(TestLessThan), R16(128),
B(JumpIfFalse), U8(35),
B(JumpIfFalse), U8(33),
/* 1518 E> */ B(StackCheck),
/* 1555 S> */ B(Wide), B(Ldar), R16(128),
/* 1561 E> */ B(Wide), B(Add), R16(1),
/* 1561 E> */ B(Add), R(1),
B(Wide), B(Mov), R16(1), R16(157),
B(Star), R(1),
/* 1548 S> */ B(Wide), B(Ldar), R16(128),
......@@ -915,7 +915,7 @@ bytecodes: [
B(Wide), B(Star), R16(157),
B(Inc),
B(Wide), B(Star), R16(128),
B(Jump), U8(-39),
B(Jump), U8(-37),
/* 1567 S> */ B(Wide), B(Ldar), R16(128),
/* 1580 S> */ B(Return),
]
......@@ -1089,7 +1089,7 @@ snippet: "
"
frame size: 163
parameter count: 1
bytecode array length: 84
bytecode array length: 82
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 1503 S> */ B(Wide), B(LdaSmi), U16(1234),
......@@ -1097,26 +1097,26 @@ bytecodes: [
/* 1518 S> */ B(LdaZero),
B(Star), R(1),
/* 1534 S> */ B(Ldar), R(0),
B(JumpIfUndefined), U8(69),
B(JumpIfNull), U8(67),
B(JumpIfUndefined), U8(67),
B(JumpIfNull), U8(65),
B(ToObject),
B(Wide), B(ForInPrepare), R16(158),
B(Wide), B(Star), R16(157),
B(LdaZero),
B(Wide), B(Star), R16(161),
/* 1526 S> */ B(Wide), B(ForInDone), R16(161), R16(160),
B(JumpIfTrue), U8(45),
B(JumpIfTrue), U8(43),
B(Wide), B(ForInNext), R16(157), R16(161), R16(158), U16(1),
B(JumpIfUndefined), U8(23),
B(JumpIfUndefined), U8(21),
B(Wide), B(Star), R16(128),
/* 1521 E> */ B(StackCheck),
/* 1541 S> */ B(Wide), B(Ldar), R16(128),
/* 1547 E> */ B(Wide), B(Add), R16(1),
/* 1547 E> */ B(Add), R(1),
B(Wide), B(Mov), R16(1), R16(162),
B(Star), R(1),
/* 1544 E> */ B(Wide), B(ForInStep), R16(161),
B(Wide), B(Star), R16(161),
B(Jump), U8(-49),
B(Jump), U8(-47),
/* 1553 S> */ B(Ldar), R(1),
/* 1564 S> */ B(Return),
]
......
......@@ -29,20 +29,20 @@ class BytecodeArrayWriterUnittest : public TestWithIsolateAndZone {
void Write(BytecodeNode* node, const BytecodeSourceInfo& info);
void Write(Bytecode bytecode,
const BytecodeSourceInfo& info = BytecodeSourceInfo());
void Write(Bytecode bytecode, uint32_t operand0, OperandScale operand_scale,
void Write(Bytecode bytecode, uint32_t operand0,
const BytecodeSourceInfo& info = BytecodeSourceInfo());
void Write(Bytecode bytecode, uint32_t operand0, uint32_t operand1,
OperandScale operand_scale,
const BytecodeSourceInfo& info = BytecodeSourceInfo());
void Write(Bytecode bytecode, uint32_t operand0, uint32_t operand1,
uint32_t operand2, OperandScale operand_scale,
uint32_t operand2,
const BytecodeSourceInfo& info = BytecodeSourceInfo());
void Write(Bytecode bytecode, uint32_t operand0, uint32_t operand1,
uint32_t operand2, uint32_t operand3, OperandScale operand_scale,
uint32_t operand2, uint32_t operand3,
const BytecodeSourceInfo& info = BytecodeSourceInfo());
void WriteJump(Bytecode bytecode, BytecodeLabel* label,
OperandScale operand_scale,
const BytecodeSourceInfo& info = BytecodeSourceInfo());
BytecodeArrayWriter* writer() { return &bytecode_array_writer_; }
......@@ -72,43 +72,37 @@ void BytecodeArrayWriterUnittest::Write(Bytecode bytecode,
}
void BytecodeArrayWriterUnittest::Write(Bytecode bytecode, uint32_t operand0,
OperandScale operand_scale,
const BytecodeSourceInfo& info) {
BytecodeNode node(bytecode, operand0, operand_scale);
BytecodeNode node(bytecode, operand0);
Write(&node, info);
}
void BytecodeArrayWriterUnittest::Write(Bytecode bytecode, uint32_t operand0,
uint32_t operand1,
OperandScale operand_scale,
const BytecodeSourceInfo& info) {
BytecodeNode node(bytecode, operand0, operand1, operand_scale);
BytecodeNode node(bytecode, operand0, operand1);
Write(&node, info);
}
void BytecodeArrayWriterUnittest::Write(Bytecode bytecode, uint32_t operand0,
uint32_t operand1, uint32_t operand2,
OperandScale operand_scale,
const BytecodeSourceInfo& info) {
BytecodeNode node(bytecode, operand0, operand1, operand2, operand_scale);
BytecodeNode node(bytecode, operand0, operand1, operand2);
Write(&node, info);
}
void BytecodeArrayWriterUnittest::Write(Bytecode bytecode, uint32_t operand0,
uint32_t operand1, uint32_t operand2,
uint32_t operand3,
OperandScale operand_scale,
const BytecodeSourceInfo& info) {
BytecodeNode node(bytecode, operand0, operand1, operand2, operand3,
operand_scale);
BytecodeNode node(bytecode, operand0, operand1, operand2, operand3);
Write(&node, info);
}
void BytecodeArrayWriterUnittest::WriteJump(Bytecode bytecode,
BytecodeLabel* label,
OperandScale operand_scale,
const BytecodeSourceInfo& info) {
BytecodeNode node(bytecode, 0, operand_scale);
BytecodeNode node(bytecode, 0);
if (info.is_valid()) {
node.source_info().Update(info);
}
......@@ -122,20 +116,20 @@ TEST_F(BytecodeArrayWriterUnittest, SimpleExample) {
CHECK_EQ(bytecodes()->size(), 1);
CHECK_EQ(max_register_count(), 0);
Write(Bytecode::kLdaSmi, 0xff, OperandScale::kSingle, {55, true});
Write(Bytecode::kLdaSmi, 127, {55, true});
CHECK_EQ(bytecodes()->size(), 3);
CHECK_EQ(max_register_count(), 0);
Write(Bytecode::kLdar, Register(1).ToOperand(), OperandScale::kDouble);
Write(Bytecode::kLdar, Register(200).ToOperand());
CHECK_EQ(bytecodes()->size(), 7);
CHECK_EQ(max_register_count(), 2);
CHECK_EQ(max_register_count(), 201);
Write(Bytecode::kReturn, {70, true});
CHECK_EQ(bytecodes()->size(), 8);
CHECK_EQ(max_register_count(), 2);
CHECK_EQ(max_register_count(), 201);
static const uint8_t bytes[] = {B(StackCheck), B(LdaSmi), U8(0xff), B(Wide),
B(Ldar), R16(1), B(Return)};
static const uint8_t bytes[] = {B(StackCheck), B(LdaSmi), U8(127), B(Wide),
B(Ldar), R16(200), B(Return)};
CHECK_EQ(bytecodes()->size(), arraysize(bytes));
for (size_t i = 0; i < arraysize(bytes); ++i) {
CHECK_EQ(bytecodes()->at(i), bytes[i]);
......@@ -197,38 +191,37 @@ TEST_F(BytecodeArrayWriterUnittest, ComplexExample) {
#define R(i) static_cast<uint32_t>(Register(i).ToOperand())
Write(Bytecode::kStackCheck, {30, false});
Write(Bytecode::kLdaConstant, U8(0), OperandScale::kSingle, {42, true});
Write(Bytecode::kLdaConstant, U8(0), {42, true});
CHECK_EQ(max_register_count(), 0);
Write(Bytecode::kStar, R(1), OperandScale::kSingle, {42, false});
Write(Bytecode::kStar, R(1), {42, false});
CHECK_EQ(max_register_count(), 2);
WriteJump(Bytecode::kJumpIfUndefined, &jump_end_1, OperandScale::kSingle,
{68, true});
WriteJump(Bytecode::kJumpIfNull, &jump_end_2, OperandScale::kSingle);
WriteJump(Bytecode::kJumpIfUndefined, &jump_end_1, {68, true});
WriteJump(Bytecode::kJumpIfNull, &jump_end_2);
Write(Bytecode::kToObject);
CHECK_EQ(max_register_count(), 2);
Write(Bytecode::kStar, R(3), OperandScale::kSingle);
Write(Bytecode::kStar, R(3));
CHECK_EQ(max_register_count(), 4);
Write(Bytecode::kForInPrepare, R(4), OperandScale::kSingle);
Write(Bytecode::kForInPrepare, R(4));
CHECK_EQ(max_register_count(), 7);
Write(Bytecode::kLdaZero);
CHECK_EQ(max_register_count(), 7);
Write(Bytecode::kStar, R(7), OperandScale::kSingle);
Write(Bytecode::kStar, R(7));
CHECK_EQ(max_register_count(), 8);
writer()->BindLabel(&back_jump);
Write(Bytecode::kForInDone, R(7), R(6), OperandScale::kSingle, {63, true});
Write(Bytecode::kForInDone, R(7), R(6), {63, true});
CHECK_EQ(max_register_count(), 8);
WriteJump(Bytecode::kJumpIfTrue, &jump_end_3, OperandScale::kSingle);
Write(Bytecode::kForInNext, R(3), R(7), R(4), U8(1), OperandScale::kSingle);
WriteJump(Bytecode::kJumpIfUndefined, &jump_for_in, OperandScale::kSingle);
Write(Bytecode::kStar, R(0), OperandScale::kSingle);
WriteJump(Bytecode::kJumpIfTrue, &jump_end_3);
Write(Bytecode::kForInNext, R(3), R(7), R(4), U8(1));
WriteJump(Bytecode::kJumpIfUndefined, &jump_for_in);
Write(Bytecode::kStar, R(0));
Write(Bytecode::kStackCheck, {54, false});
Write(Bytecode::kLdar, R(0), OperandScale::kSingle);
Write(Bytecode::kStar, R(2), OperandScale::kSingle);
Write(Bytecode::kLdar, R(0));
Write(Bytecode::kStar, R(2));
Write(Bytecode::kReturn, {85, true});
writer()->BindLabel(&jump_for_in);
Write(Bytecode::kForInStep, R(7), OperandScale::kSingle);
Write(Bytecode::kStar, R(7), OperandScale::kSingle);
WriteJump(Bytecode::kJump, &back_jump, OperandScale::kSingle);
Write(Bytecode::kForInStep, R(7));
Write(Bytecode::kStar, R(7));
WriteJump(Bytecode::kJump, &back_jump);
writer()->BindLabel(&jump_end_1);
writer()->BindLabel(&jump_end_2);
writer()->BindLabel(&jump_end_3);
......
......@@ -61,82 +61,71 @@ TEST_F(BytecodeNodeTest, Constructor1) {
BytecodeNode node(Bytecode::kLdaZero);
CHECK_EQ(node.bytecode(), Bytecode::kLdaZero);
CHECK_EQ(node.operand_count(), 0);
CHECK_EQ(node.operand_scale(), OperandScale::kSingle);
CHECK(!node.source_info().is_valid());
CHECK_EQ(node.Size(), 1);
}
TEST_F(BytecodeNodeTest, Constructor2) {
uint32_t operands[] = {0x11};
BytecodeNode node(Bytecode::kJumpIfTrue, operands[0], OperandScale::kDouble);
BytecodeNode node(Bytecode::kJumpIfTrue, operands[0]);
CHECK_EQ(node.bytecode(), Bytecode::kJumpIfTrue);
CHECK_EQ(node.operand_count(), 1);
CHECK_EQ(node.operand(0), operands[0]);
CHECK_EQ(node.operand_scale(), OperandScale::kDouble);
CHECK(!node.source_info().is_valid());
CHECK_EQ(node.Size(), 4);
}
TEST_F(BytecodeNodeTest, Constructor3) {
uint32_t operands[] = {0x11, 0x22};
BytecodeNode node(Bytecode::kLdaGlobal, operands[0], operands[1],
OperandScale::kQuadruple);
BytecodeNode node(Bytecode::kLdaGlobal, operands[0], operands[1]);
CHECK_EQ(node.bytecode(), Bytecode::kLdaGlobal);
CHECK_EQ(node.operand_count(), 2);
CHECK_EQ(node.operand(0), operands[0]);
CHECK_EQ(node.operand(1), operands[1]);
CHECK_EQ(node.operand_scale(), OperandScale::kQuadruple);
CHECK(!node.source_info().is_valid());
CHECK_EQ(node.Size(), 10);
}
TEST_F(BytecodeNodeTest, Constructor4) {
uint32_t operands[] = {0x11, 0x22, 0x33};
BytecodeNode node(Bytecode::kLdaNamedProperty, operands[0], operands[1],
operands[2], OperandScale::kSingle);
operands[2]);
CHECK_EQ(node.operand_count(), 3);
CHECK_EQ(node.bytecode(), Bytecode::kLdaNamedProperty);
CHECK_EQ(node.operand(0), operands[0]);
CHECK_EQ(node.operand(1), operands[1]);
CHECK_EQ(node.operand(2), operands[2]);
CHECK_EQ(node.operand_scale(), OperandScale::kSingle);
CHECK(!node.source_info().is_valid());
CHECK_EQ(node.Size(), 4);
}
TEST_F(BytecodeNodeTest, Constructor5) {
uint32_t operands[] = {0x71, 0xa5, 0x5a, 0xfc};
BytecodeNode node(Bytecode::kForInNext, operands[0], operands[1], operands[2],
operands[3], OperandScale::kDouble);
operands[3]);
CHECK_EQ(node.operand_count(), 4);
CHECK_EQ(node.bytecode(), Bytecode::kForInNext);
CHECK_EQ(node.operand(0), operands[0]);
CHECK_EQ(node.operand(1), operands[1]);
CHECK_EQ(node.operand(2), operands[2]);
CHECK_EQ(node.operand(3), operands[3]);
CHECK_EQ(node.operand_scale(), OperandScale::kDouble);
CHECK(!node.source_info().is_valid());
CHECK_EQ(node.Size(), 10);
}
TEST_F(BytecodeNodeTest, Equality) {
uint32_t operands[] = {0x71, 0xa5, 0x5a, 0xfc};
BytecodeNode node(Bytecode::kForInNext, operands[0], operands[1], operands[2],
operands[3], OperandScale::kDouble);
operands[3]);
CHECK_EQ(node, node);
BytecodeNode other(Bytecode::kForInNext, operands[0], operands[1],
operands[2], operands[3], OperandScale::kDouble);
operands[2], operands[3]);
CHECK_EQ(node, other);
}
TEST_F(BytecodeNodeTest, EqualityWithSourceInfo) {
uint32_t operands[] = {0x71, 0xa5, 0x5a, 0xfc};
BytecodeNode node(Bytecode::kForInNext, operands[0], operands[1], operands[2],
operands[3], OperandScale::kDouble);
operands[3]);
node.source_info().Update({3, true});
CHECK_EQ(node, node);
BytecodeNode other(Bytecode::kForInNext, operands[0], operands[1],
operands[2], operands[3], OperandScale::kDouble);
operands[2], operands[3]);
other.source_info().Update({3, true});
CHECK_EQ(node, other);
}
......@@ -144,17 +133,17 @@ TEST_F(BytecodeNodeTest, EqualityWithSourceInfo) {
TEST_F(BytecodeNodeTest, NoEqualityWithDifferentSourceInfo) {
uint32_t operands[] = {0x71, 0xa5, 0x5a, 0xfc};
BytecodeNode node(Bytecode::kForInNext, operands[0], operands[1], operands[2],
operands[3], OperandScale::kDouble);
operands[3]);
node.source_info().Update({3, true});
BytecodeNode other(Bytecode::kForInNext, operands[0], operands[1],
operands[2], operands[3], OperandScale::kDouble);
operands[2], operands[3]);
CHECK_NE(node, other);
}
TEST_F(BytecodeNodeTest, Clone) {
uint32_t operands[] = {0x71, 0xa5, 0x5a, 0xfc};
BytecodeNode node(Bytecode::kForInNext, operands[0], operands[1], operands[2],
operands[3], OperandScale::kDouble);
operands[3]);
BytecodeNode clone;
clone.Clone(&node);
CHECK_EQ(clone, node);
......@@ -163,7 +152,7 @@ TEST_F(BytecodeNodeTest, Clone) {
TEST_F(BytecodeNodeTest, SetBytecode0) {
uint32_t operands[] = {0x71, 0xa5, 0x5a, 0xfc};
BytecodeNode node(Bytecode::kForInNext, operands[0], operands[1], operands[2],
operands[3], OperandScale::kDouble);
operands[3]);
BytecodeSourceInfo source_info(77, false);
node.source_info().Update(source_info);
......@@ -172,24 +161,22 @@ TEST_F(BytecodeNodeTest, SetBytecode0) {
clone.set_bytecode(Bytecode::kNop);
CHECK_EQ(clone.bytecode(), Bytecode::kNop);
CHECK_EQ(clone.operand_count(), 0);
CHECK_EQ(clone.operand_scale(), OperandScale::kSingle);
CHECK_EQ(clone.source_info(), source_info);
}
TEST_F(BytecodeNodeTest, SetBytecode1) {
uint32_t operands[] = {0x71, 0xa5, 0x5a, 0xfc};
BytecodeNode node(Bytecode::kForInNext, operands[0], operands[1], operands[2],
operands[3], OperandScale::kDouble);
operands[3]);
BytecodeSourceInfo source_info(77, false);
node.source_info().Update(source_info);
BytecodeNode clone;
clone.Clone(&node);
clone.set_bytecode(Bytecode::kJump, 0x01aabbcc, OperandScale::kQuadruple);
clone.set_bytecode(Bytecode::kJump, 0x01aabbcc);
CHECK_EQ(clone.bytecode(), Bytecode::kJump);
CHECK_EQ(clone.operand_count(), 1);
CHECK_EQ(clone.operand(0), 0x01aabbcc);
CHECK_EQ(clone.operand_scale(), OperandScale::kQuadruple);
CHECK_EQ(clone.source_info(), source_info);
}
......
......@@ -93,23 +93,22 @@ TEST_F(BytecodeRegisterOptimizerTest, WriteNopStatement) {
TEST_F(BytecodeRegisterOptimizerTest, TemporaryMaterializedForJump) {
Initialize(1, 1);
Register temp = NewTemporary();
BytecodeNode node(Bytecode::kStar, temp.ToOperand(), OperandScale::kSingle);
BytecodeNode node(Bytecode::kStar, temp.ToOperand());
optimizer()->Write(&node);
CHECK_EQ(write_count(), 0);
BytecodeLabel label;
BytecodeNode jump(Bytecode::kJump, 0, OperandScale::kSingle);
BytecodeNode jump(Bytecode::kJump, 0);
optimizer()->WriteJump(&jump, &label);
CHECK_EQ(write_count(), 2);
CHECK_EQ(output()->at(0).bytecode(), Bytecode::kStar);
CHECK_EQ(output()->at(0).operand(0), temp.ToOperand());
CHECK_EQ(output()->at(0).operand_scale(), OperandScale::kSingle);
CHECK_EQ(output()->at(1).bytecode(), Bytecode::kJump);
}
TEST_F(BytecodeRegisterOptimizerTest, TemporaryMaterializedForBind) {
Initialize(1, 1);
Register temp = NewTemporary();
BytecodeNode node(Bytecode::kStar, temp.ToOperand(), OperandScale::kSingle);
BytecodeNode node(Bytecode::kStar, temp.ToOperand());
optimizer()->Write(&node);
CHECK_EQ(write_count(), 0);
BytecodeLabel label;
......@@ -117,7 +116,6 @@ TEST_F(BytecodeRegisterOptimizerTest, TemporaryMaterializedForBind) {
CHECK_EQ(write_count(), 1);
CHECK_EQ(output()->at(0).bytecode(), Bytecode::kStar);
CHECK_EQ(output()->at(0).operand(0), temp.ToOperand());
CHECK_EQ(output()->at(0).operand_scale(), OperandScale::kSingle);
}
// Basic Register Optimizations
......@@ -125,13 +123,11 @@ TEST_F(BytecodeRegisterOptimizerTest, TemporaryMaterializedForBind) {
TEST_F(BytecodeRegisterOptimizerTest, TemporaryNotEmitted) {
Initialize(3, 1);
Register parameter = Register::FromParameterIndex(1, 3);
BytecodeNode node0(Bytecode::kLdar, parameter.ToOperand(),
OperandScale::kSingle);
BytecodeNode node0(Bytecode::kLdar, parameter.ToOperand());
optimizer()->Write(&node0);
CHECK_EQ(write_count(), 0);
Register temp = NewTemporary();
BytecodeNode node1(Bytecode::kStar, NewTemporary().ToOperand(),
OperandScale::kSingle);
BytecodeNode node1(Bytecode::kStar, NewTemporary().ToOperand());
optimizer()->Write(&node1);
CHECK_EQ(write_count(), 0);
KillTemporary(temp);
......@@ -141,32 +137,28 @@ TEST_F(BytecodeRegisterOptimizerTest, TemporaryNotEmitted) {
CHECK_EQ(write_count(), 2);
CHECK_EQ(output()->at(0).bytecode(), Bytecode::kLdar);
CHECK_EQ(output()->at(0).operand(0), parameter.ToOperand());
CHECK_EQ(output()->at(0).operand_scale(), OperandScale::kSingle);
CHECK_EQ(output()->at(1).bytecode(), Bytecode::kReturn);
}
TEST_F(BytecodeRegisterOptimizerTest, StoresToLocalsImmediate) {
Initialize(3, 1);
Register parameter = Register::FromParameterIndex(1, 3);
BytecodeNode node0(Bytecode::kLdar, parameter.ToOperand(),
OperandScale::kSingle);
BytecodeNode node0(Bytecode::kLdar, parameter.ToOperand());
optimizer()->Write(&node0);
CHECK_EQ(write_count(), 0);
Register local = Register(0);
BytecodeNode node1(Bytecode::kStar, local.ToOperand(), OperandScale::kSingle);
BytecodeNode node1(Bytecode::kStar, local.ToOperand());
optimizer()->Write(&node1);
CHECK_EQ(write_count(), 1);
CHECK_EQ(output()->at(0).bytecode(), Bytecode::kMov);
CHECK_EQ(output()->at(0).operand(0), parameter.ToOperand());
CHECK_EQ(output()->at(0).operand(1), local.ToOperand());
CHECK_EQ(output()->at(0).operand_scale(), OperandScale::kSingle);
BytecodeNode node2(Bytecode::kReturn);
optimizer()->Write(&node2);
CHECK_EQ(write_count(), 3);
CHECK_EQ(output()->at(1).bytecode(), Bytecode::kLdar);
CHECK_EQ(output()->at(1).operand(0), local.ToOperand());
CHECK_EQ(output()->at(1).operand_scale(), OperandScale::kSingle);
CHECK_EQ(output()->at(2).bytecode(), Bytecode::kReturn);
}
......@@ -175,22 +167,18 @@ TEST_F(BytecodeRegisterOptimizerTest, TemporaryNotMaterializedForInput) {
Register parameter = Register::FromParameterIndex(1, 3);
Register temp0 = NewTemporary();
Register temp1 = NewTemporary();
BytecodeNode node0(Bytecode::kMov, parameter.ToOperand(), temp0.ToOperand(),
OperandScale::kSingle);
BytecodeNode node0(Bytecode::kMov, parameter.ToOperand(), temp0.ToOperand());
optimizer()->Write(&node0);
BytecodeNode node1(Bytecode::kMov, parameter.ToOperand(), temp1.ToOperand(),
OperandScale::kSingle);
BytecodeNode node1(Bytecode::kMov, parameter.ToOperand(), temp1.ToOperand());
optimizer()->Write(&node1);
CHECK_EQ(write_count(), 0);
BytecodeNode node2(Bytecode::kCallJSRuntime, 0, temp0.ToOperand(), 1,
OperandScale::kSingle);
BytecodeNode node2(Bytecode::kCallJSRuntime, 0, temp0.ToOperand(), 1);
optimizer()->Write(&node2);
CHECK_EQ(write_count(), 1);
CHECK_EQ(output()->at(0).bytecode(), Bytecode::kCallJSRuntime);
CHECK_EQ(output()->at(0).operand(0), 0);
CHECK_EQ(output()->at(0).operand(1), parameter.ToOperand());
CHECK_EQ(output()->at(0).operand(2), 1);
CHECK_EQ(output()->at(0).operand_scale(), OperandScale::kSingle);
}
TEST_F(BytecodeRegisterOptimizerTest, RangeOfTemporariesMaterializedForInput) {
......@@ -198,38 +186,32 @@ TEST_F(BytecodeRegisterOptimizerTest, RangeOfTemporariesMaterializedForInput) {
Register parameter = Register::FromParameterIndex(1, 3);
Register temp0 = NewTemporary();
Register temp1 = NewTemporary();
BytecodeNode node0(Bytecode::kLdaSmi, 3, OperandScale::kSingle);
BytecodeNode node0(Bytecode::kLdaSmi, 3);
optimizer()->Write(&node0);
CHECK_EQ(write_count(), 1);
BytecodeNode node1(Bytecode::kStar, temp0.ToOperand(), OperandScale::kSingle);
BytecodeNode node1(Bytecode::kStar, temp0.ToOperand());
optimizer()->Write(&node1);
BytecodeNode node2(Bytecode::kMov, parameter.ToOperand(), temp1.ToOperand(),
OperandScale::kSingle);
BytecodeNode node2(Bytecode::kMov, parameter.ToOperand(), temp1.ToOperand());
optimizer()->Write(&node2);
CHECK_EQ(write_count(), 1);
BytecodeNode node3(Bytecode::kCallJSRuntime, 0, temp0.ToOperand(), 2,
OperandScale::kSingle);
BytecodeNode node3(Bytecode::kCallJSRuntime, 0, temp0.ToOperand(), 2);
optimizer()->Write(&node3);
CHECK_EQ(write_count(), 4);
CHECK_EQ(output()->at(0).bytecode(), Bytecode::kLdaSmi);
CHECK_EQ(output()->at(0).operand(0), 3);
CHECK_EQ(output()->at(0).operand_scale(), OperandScale::kSingle);
CHECK_EQ(output()->at(1).bytecode(), Bytecode::kStar);
CHECK_EQ(output()->at(1).operand(0), temp0.ToOperand());
CHECK_EQ(output()->at(1).operand_scale(), OperandScale::kSingle);
CHECK_EQ(output()->at(2).bytecode(), Bytecode::kMov);
CHECK_EQ(output()->at(2).operand(0), parameter.ToOperand());
CHECK_EQ(output()->at(2).operand(1), temp1.ToOperand());
CHECK_EQ(output()->at(2).operand_scale(), OperandScale::kSingle);
CHECK_EQ(output()->at(3).bytecode(), Bytecode::kCallJSRuntime);
CHECK_EQ(output()->at(3).operand(0), 0);
CHECK_EQ(output()->at(3).operand(1), temp0.ToOperand());
CHECK_EQ(output()->at(3).operand(2), 2);
CHECK_EQ(output()->at(3).operand_scale(), OperandScale::kSingle);
}
} // namespace interpreter
......
......@@ -254,35 +254,6 @@ TEST(Bytecodes, PrefixMappings) {
}
}
TEST(Bytecodes, OperandScales) {
CHECK_EQ(Bytecodes::OperandSizesToScale(OperandSize::kByte),
OperandScale::kSingle);
CHECK_EQ(Bytecodes::OperandSizesToScale(OperandSize::kShort),
OperandScale::kDouble);
CHECK_EQ(Bytecodes::OperandSizesToScale(OperandSize::kQuad),
OperandScale::kQuadruple);
CHECK_EQ(
Bytecodes::OperandSizesToScale(OperandSize::kShort, OperandSize::kShort,
OperandSize::kShort, OperandSize::kShort),
OperandScale::kDouble);
CHECK_EQ(
Bytecodes::OperandSizesToScale(OperandSize::kQuad, OperandSize::kShort,
OperandSize::kShort, OperandSize::kShort),
OperandScale::kQuadruple);
CHECK_EQ(
Bytecodes::OperandSizesToScale(OperandSize::kShort, OperandSize::kQuad,
OperandSize::kShort, OperandSize::kShort),
OperandScale::kQuadruple);
CHECK_EQ(
Bytecodes::OperandSizesToScale(OperandSize::kShort, OperandSize::kShort,
OperandSize::kQuad, OperandSize::kShort),
OperandScale::kQuadruple);
CHECK_EQ(
Bytecodes::OperandSizesToScale(OperandSize::kShort, OperandSize::kShort,
OperandSize::kShort, OperandSize::kQuad),
OperandScale::kQuadruple);
}
TEST(Bytecodes, SizesForSignedOperands) {
CHECK(Bytecodes::SizeForSignedOperand(0) == OperandSize::kByte);
CHECK(Bytecodes::SizeForSignedOperand(kMaxInt8) == OperandSize::kByte);
......@@ -332,35 +303,6 @@ TEST(OperandScale, PrefixesRequired) {
Bytecode::kExtraWide);
}
TEST(Bytecodes, OperandSizesToScale) {
CHECK_EQ(Bytecodes::OperandSizesToScale(OperandSize::kByte),
OperandScale::kSingle);
CHECK_EQ(Bytecodes::OperandSizesToScale(OperandSize::kShort),
OperandScale::kDouble);
CHECK_EQ(Bytecodes::OperandSizesToScale(OperandSize::kQuad),
OperandScale::kQuadruple);
CHECK_EQ(
Bytecodes::OperandSizesToScale(OperandSize::kShort, OperandSize::kShort,
OperandSize::kShort, OperandSize::kShort),
OperandScale::kDouble);
CHECK_EQ(
Bytecodes::OperandSizesToScale(OperandSize::kQuad, OperandSize::kShort,
OperandSize::kShort, OperandSize::kShort),
OperandScale::kQuadruple);
CHECK_EQ(
Bytecodes::OperandSizesToScale(OperandSize::kShort, OperandSize::kQuad,
OperandSize::kShort, OperandSize::kShort),
OperandScale::kQuadruple);
CHECK_EQ(
Bytecodes::OperandSizesToScale(OperandSize::kShort, OperandSize::kShort,
OperandSize::kQuad, OperandSize::kShort),
OperandScale::kQuadruple);
CHECK_EQ(
Bytecodes::OperandSizesToScale(OperandSize::kShort, OperandSize::kShort,
OperandSize::kShort, OperandSize::kQuad),
OperandScale::kQuadruple);
}
TEST(AccumulatorUse, LogicalOperators) {
CHECK_EQ(AccumulatorUse::kNone | AccumulatorUse::kRead,
AccumulatorUse::kRead);
......
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