Index: src/compiler/instruction.h |
diff --git a/src/compiler/instruction.h b/src/compiler/instruction.h |
index a5616b2a56352eac3961538edb52b2ec667f8d72..3615e37affcc9053f029df2f67b34c36e949d893 100644 |
--- a/src/compiler/instruction.h |
+++ b/src/compiler/instruction.h |
@@ -27,9 +27,7 @@ class Schedule; |
// A couple of reserved opcodes are used for internal use. |
const InstructionCode kSourcePositionInstruction = -1; |
-#define INSTRUCTION_OPERAND_LIST(V) \ |
- V(Constant, CONSTANT) \ |
- V(Immediate, IMMEDIATE) \ |
+#define ALLOCATED_OPERAND_LIST(V) \ |
V(StackSlot, STACK_SLOT) \ |
V(DoubleStackSlot, DOUBLE_STACK_SLOT) \ |
V(Register, REGISTER) \ |
@@ -50,65 +48,50 @@ class InstructionOperand { |
DOUBLE_REGISTER |
}; |
- InstructionOperand() { ConvertTo(INVALID, 0, kInvalidVirtualRegister); } |
- |
- InstructionOperand(Kind kind, int index) { |
- DCHECK(kind != UNALLOCATED && kind != INVALID); |
- ConvertTo(kind, index, kInvalidVirtualRegister); |
- } |
- |
- static InstructionOperand* New(Zone* zone, Kind kind, int index) { |
- return New(zone, InstructionOperand(kind, index)); |
- } |
+ InstructionOperand() |
+ : InstructionOperand(INVALID, 0, kInvalidVirtualRegister) {} |
Kind kind() const { return KindField::decode(value_); } |
- // TODO(dcarney): move this to subkind operand. |
- int index() const { |
- DCHECK(kind() != UNALLOCATED && kind() != INVALID); |
- return static_cast<int64_t>(value_) >> IndexField::kShift; |
- } |
+ |
#define INSTRUCTION_OPERAND_PREDICATE(name, type) \ |
bool Is##name() const { return kind() == type; } |
- INSTRUCTION_OPERAND_LIST(INSTRUCTION_OPERAND_PREDICATE) |
+ ALLOCATED_OPERAND_LIST(INSTRUCTION_OPERAND_PREDICATE) |
+ INSTRUCTION_OPERAND_PREDICATE(Constant, CONSTANT) |
+ INSTRUCTION_OPERAND_PREDICATE(Immediate, IMMEDIATE) |
INSTRUCTION_OPERAND_PREDICATE(Unallocated, UNALLOCATED) |
INSTRUCTION_OPERAND_PREDICATE(Invalid, INVALID) |
#undef INSTRUCTION_OPERAND_PREDICATE |
+ |
bool Equals(const InstructionOperand* other) const { |
return value_ == other->value_; |
} |
- void ConvertTo(Kind kind, int index) { |
- DCHECK(kind != UNALLOCATED && kind != INVALID); |
- ConvertTo(kind, index, kInvalidVirtualRegister); |
- } |
- |
// Useful for map/set keys. |
bool operator<(const InstructionOperand& op) const { |
return value_ < op.value_; |
} |
- protected: |
template <typename SubKindOperand> |
static SubKindOperand* New(Zone* zone, const SubKindOperand& op) { |
void* buffer = zone->New(sizeof(op)); |
return new (buffer) SubKindOperand(op); |
} |
- InstructionOperand(Kind kind, int index, int virtual_register) { |
- ConvertTo(kind, index, virtual_register); |
+ static void ReplaceWith(InstructionOperand* dest, |
+ const InstructionOperand* src) { |
+ *dest = *src; |
} |
- void ConvertTo(Kind kind, int index, int virtual_register) { |
+ protected: |
+ InstructionOperand(Kind kind, int index, int virtual_register) { |
if (kind == REGISTER || kind == DOUBLE_REGISTER) DCHECK(index >= 0); |
- if (kind != UNALLOCATED) { |
+ if (kind != UNALLOCATED && kind != CONSTANT) { |
DCHECK(virtual_register == kInvalidVirtualRegister); |
} |
value_ = KindField::encode(kind); |
value_ |= |
VirtualRegisterField::encode(static_cast<uint32_t>(virtual_register)); |
value_ |= static_cast<int64_t>(index) << IndexField::kShift; |
- DCHECK(((kind == UNALLOCATED || kind == INVALID) && index == 0) || |
- this->index() == index); |
} |
typedef BitField64<Kind, 0, 3> KindField; |
@@ -317,6 +300,138 @@ class UnallocatedOperand : public InstructionOperand { |
}; |
+class ConstantOperand : public InstructionOperand { |
+ public: |
+ explicit ConstantOperand(int virtual_register) |
+ : InstructionOperand(CONSTANT, 0, virtual_register) {} |
+ |
+ int32_t virtual_register() const { |
+ return static_cast<int32_t>(VirtualRegisterField::decode(value_)); |
+ } |
+ |
+ static ConstantOperand* New(Zone* zone, int virtual_register) { |
+ return InstructionOperand::New(zone, ConstantOperand(virtual_register)); |
+ } |
+ |
+ static ConstantOperand* cast(InstructionOperand* op) { |
+ DCHECK(op->kind() == CONSTANT); |
+ return static_cast<ConstantOperand*>(op); |
+ } |
+ |
+ static const ConstantOperand* cast(const InstructionOperand* op) { |
+ DCHECK(op->kind() == CONSTANT); |
+ return static_cast<const ConstantOperand*>(op); |
+ } |
+ |
+ static ConstantOperand cast(const InstructionOperand& op) { |
+ DCHECK(op.kind() == CONSTANT); |
+ return *static_cast<const ConstantOperand*>(&op); |
+ } |
+}; |
+ |
+ |
+class ImmediateOperand : public InstructionOperand { |
+ public: |
+ explicit ImmediateOperand(int index) |
+ : InstructionOperand(IMMEDIATE, index, kInvalidVirtualRegister) {} |
+ |
+ int index() const { |
+ return static_cast<int64_t>(value_) >> IndexField::kShift; |
+ } |
+ |
+ static ImmediateOperand* New(Zone* zone, int index) { |
+ return InstructionOperand::New(zone, ImmediateOperand(index)); |
+ } |
+ |
+ static ImmediateOperand* cast(InstructionOperand* op) { |
+ DCHECK(op->kind() == IMMEDIATE); |
+ return static_cast<ImmediateOperand*>(op); |
+ } |
+ |
+ static const ImmediateOperand* cast(const InstructionOperand* op) { |
+ DCHECK(op->kind() == IMMEDIATE); |
+ return static_cast<const ImmediateOperand*>(op); |
+ } |
+ |
+ static ImmediateOperand cast(const InstructionOperand& op) { |
+ DCHECK(op.kind() == IMMEDIATE); |
+ return *static_cast<const ImmediateOperand*>(&op); |
+ } |
+}; |
+ |
+ |
+class AllocatedOperand : public InstructionOperand { |
+#define ALLOCATED_OPERAND_CHECK(Name, Kind) || kind == Kind |
+#define CHECK_ALLOCATED_KIND() \ |
+ DCHECK(false ALLOCATED_OPERAND_LIST(ALLOCATED_OPERAND_CHECK)); \ |
+ USE(kind); |
+ |
+ public: |
+ int index() const { |
+ return static_cast<int64_t>(value_) >> IndexField::kShift; |
+ } |
+ |
+ AllocatedOperand(Kind kind, int index) |
+ : InstructionOperand(kind, index, kInvalidVirtualRegister) { |
+ CHECK_ALLOCATED_KIND(); |
+ } |
+ |
+ static AllocatedOperand* New(Zone* zone, Kind kind, int index) { |
+ return InstructionOperand::New(zone, AllocatedOperand(kind, index)); |
+ } |
+ |
+ static AllocatedOperand* cast(InstructionOperand* op) { |
+ Kind kind = op->kind(); |
+ CHECK_ALLOCATED_KIND(); |
+ return static_cast<AllocatedOperand*>(op); |
+ } |
+ |
+ static const AllocatedOperand* cast(const InstructionOperand* op) { |
+ Kind kind = op->kind(); |
+ CHECK_ALLOCATED_KIND(); |
+ return static_cast<const AllocatedOperand*>(op); |
+ } |
+ |
+ static AllocatedOperand cast(const InstructionOperand& op) { |
+ Kind kind = op.kind(); |
+ CHECK_ALLOCATED_KIND(); |
+ return *static_cast<const AllocatedOperand*>(&op); |
+ } |
+ |
+#undef CHECK_ALLOCATED_KIND |
+#undef ALLOCATED_OPERAND_CAST_CHECK |
+}; |
+ |
+ |
+#define INSTRUCTION_SUBKIND_OPERAND_CLASS(SubKind, kOperandKind) \ |
+ class SubKind##Operand FINAL : public AllocatedOperand { \ |
+ public: \ |
+ explicit SubKind##Operand(int index) \ |
+ : AllocatedOperand(kOperandKind, index) {} \ |
+ \ |
+ static SubKind##Operand* New(Zone* zone, int index) { \ |
+ return InstructionOperand::New(zone, SubKind##Operand(index)); \ |
+ } \ |
+ \ |
+ static SubKind##Operand* cast(InstructionOperand* op) { \ |
+ DCHECK(op->kind() == kOperandKind); \ |
+ return reinterpret_cast<SubKind##Operand*>(op); \ |
+ } \ |
+ \ |
+ static const SubKind##Operand* cast(const InstructionOperand* op) { \ |
+ DCHECK(op->kind() == kOperandKind); \ |
+ return reinterpret_cast<const SubKind##Operand*>(op); \ |
+ } \ |
+ \ |
+ static SubKind##Operand cast(const InstructionOperand& op) { \ |
+ DCHECK(op.kind() == kOperandKind); \ |
+ return *static_cast<const SubKind##Operand*>(&op); \ |
+ } \ |
+ }; |
+ALLOCATED_OPERAND_LIST(INSTRUCTION_SUBKIND_OPERAND_CLASS) |
+#undef INSTRUCTION_SUBKIND_OPERAND_CLASS |
+ |
+ |
class MoveOperands FINAL { |
public: |
MoveOperands(InstructionOperand* source, InstructionOperand* destination) |
@@ -337,11 +452,11 @@ class MoveOperands FINAL { |
return !IsEliminated() && source()->Equals(operand); |
} |
- // A move is redundant if it's been eliminated, if its source and |
- // destination are the same, or if its destination is constant. |
+ // A move is redundant if it's been eliminated or if its source and |
+ // destination are the same. |
bool IsRedundant() const { |
- return IsEliminated() || source_->Equals(destination_) || |
- (destination_ != NULL && destination_->IsConstant()); |
+ DCHECK_IMPLIES(destination_ != nullptr, !destination_->IsConstant()); |
+ return IsEliminated() || source_->Equals(destination_); |
} |
// We clear both operands to indicate move that's been eliminated. |
@@ -366,35 +481,6 @@ struct PrintableMoveOperands { |
std::ostream& operator<<(std::ostream& os, const PrintableMoveOperands& mo); |
-#define INSTRUCTION_SUBKIND_OPERAND_CLASS(SubKind, kOperandKind) \ |
- class SubKind##Operand FINAL : public InstructionOperand { \ |
- public: \ |
- explicit SubKind##Operand(int index) \ |
- : InstructionOperand(kOperandKind, index) {} \ |
- \ |
- static SubKind##Operand* New(int index, Zone* zone) { \ |
- return InstructionOperand::New(zone, SubKind##Operand(index)); \ |
- } \ |
- \ |
- static SubKind##Operand* cast(InstructionOperand* op) { \ |
- DCHECK(op->kind() == kOperandKind); \ |
- return reinterpret_cast<SubKind##Operand*>(op); \ |
- } \ |
- \ |
- static const SubKind##Operand* cast(const InstructionOperand* op) { \ |
- DCHECK(op->kind() == kOperandKind); \ |
- return reinterpret_cast<const SubKind##Operand*>(op); \ |
- } \ |
- \ |
- static SubKind##Operand cast(const InstructionOperand& op) { \ |
- DCHECK(op.kind() == kOperandKind); \ |
- return *static_cast<const SubKind##Operand*>(&op); \ |
- } \ |
- }; |
-INSTRUCTION_OPERAND_LIST(INSTRUCTION_SUBKIND_OPERAND_CLASS) |
-#undef INSTRUCTION_SUBKIND_OPERAND_CLASS |
- |
- |
class ParallelMove FINAL : public ZoneObject { |
public: |
explicit ParallelMove(Zone* zone) : move_operands_(4, zone) {} |
@@ -1016,12 +1102,7 @@ class InstructionSequence FINAL : public ZoneObject { |
FrameStateDescriptor* GetFrameStateDescriptor(StateId deoptimization_id); |
int GetFrameStateDescriptorCount(); |
- RpoNumber InputRpo(Instruction* instr, size_t index) { |
- InstructionOperand* operand = instr->InputAt(index); |
- Constant constant = operand->IsImmediate() ? GetImmediate(operand->index()) |
- : GetConstant(operand->index()); |
- return constant.ToRpoNumber(); |
- } |
+ RpoNumber InputRpo(Instruction* instr, size_t index); |
private: |
friend std::ostream& operator<<(std::ostream& os, |