Refactor lithium classes to reduce the number of virtual functions.

This reduces the binary size by making the Is* type-test functions non-virtual.

I had to change Gap and Label instructions to have a common abstract superclass because both act as gap-instructions for the register allocator.
Review URL: http://codereview.chromium.org/6880204

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@7691 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 038fa0b4
...@@ -150,7 +150,7 @@ bool LGap::IsRedundant() const { ...@@ -150,7 +150,7 @@ bool LGap::IsRedundant() const {
} }
void LGap::PrintDataTo(StringStream* stream) const { void LGap::PrintDataTo(StringStream* stream) {
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
stream->Add("("); stream->Add("(");
if (parallel_moves_[i] != NULL) { if (parallel_moves_[i] != NULL) {
...@@ -455,7 +455,7 @@ void LChunk::MarkEmptyBlocks() { ...@@ -455,7 +455,7 @@ void LChunk::MarkEmptyBlocks() {
void LChunk::AddInstruction(LInstruction* instr, HBasicBlock* block) { void LChunk::AddInstruction(LInstruction* instr, HBasicBlock* block) {
LGap* gap = new LGap(block); LInstructionGap* gap = new LInstructionGap(block);
int index = -1; int index = -1;
if (instr->IsControl()) { if (instr->IsControl()) {
instructions_.Add(gap); instructions_.Add(gap);
......
...@@ -93,7 +93,6 @@ class LCodeGen; ...@@ -93,7 +93,6 @@ class LCodeGen;
V(ExternalArrayLength) \ V(ExternalArrayLength) \
V(FixedArrayLength) \ V(FixedArrayLength) \
V(FunctionLiteral) \ V(FunctionLiteral) \
V(Gap) \
V(GetCachedArrayIndex) \ V(GetCachedArrayIndex) \
V(GlobalObject) \ V(GlobalObject) \
V(GlobalReceiver) \ V(GlobalReceiver) \
...@@ -106,6 +105,7 @@ class LCodeGen; ...@@ -106,6 +105,7 @@ class LCodeGen;
V(InstanceOf) \ V(InstanceOf) \
V(InstanceOfAndBranch) \ V(InstanceOfAndBranch) \
V(InstanceOfKnownGlobal) \ V(InstanceOfKnownGlobal) \
V(InstructionGap) \
V(Integer32ToDouble) \ V(Integer32ToDouble) \
V(InvokeFunction) \ V(InvokeFunction) \
V(IsNull) \ V(IsNull) \
...@@ -172,20 +172,16 @@ class LCodeGen; ...@@ -172,20 +172,16 @@ class LCodeGen;
V(ValueOf) V(ValueOf)
#define DECLARE_INSTRUCTION(type) \ #define DECLARE_CONCRETE_INSTRUCTION(type, mnemonic) \
virtual bool Is##type() const { return true; } \ virtual Opcode opcode() const { return LInstruction::k##type; } \
static L##type* cast(LInstruction* instr) { \ virtual void CompileToNative(LCodeGen* generator); \
ASSERT(instr->Is##type()); \ virtual const char* Mnemonic() const { return mnemonic; } \
return reinterpret_cast<L##type*>(instr); \ static L##type* cast(LInstruction* instr) { \
ASSERT(instr->Is##type()); \
return reinterpret_cast<L##type*>(instr); \
} }
#define DECLARE_CONCRETE_INSTRUCTION(type, mnemonic) \
virtual void CompileToNative(LCodeGen* generator); \
virtual const char* Mnemonic() const { return mnemonic; } \
DECLARE_INSTRUCTION(type)
#define DECLARE_HYDROGEN_ACCESSOR(type) \ #define DECLARE_HYDROGEN_ACCESSOR(type) \
H##type* hydrogen() const { \ H##type* hydrogen() const { \
return H##type::cast(hydrogen_value()); \ return H##type::cast(hydrogen_value()); \
...@@ -207,10 +203,25 @@ class LInstruction: public ZoneObject { ...@@ -207,10 +203,25 @@ class LInstruction: public ZoneObject {
virtual void PrintDataTo(StringStream* stream) = 0; virtual void PrintDataTo(StringStream* stream) = 0;
virtual void PrintOutputOperandTo(StringStream* stream) = 0; virtual void PrintOutputOperandTo(StringStream* stream) = 0;
// Declare virtual type testers. enum Opcode {
#define DECLARE_DO(type) virtual bool Is##type() const { return false; } // Declare a unique enum value for each instruction.
LITHIUM_ALL_INSTRUCTION_LIST(DECLARE_DO) #define DECLARE_OPCODE(type) k##type,
#undef DECLARE_DO LITHIUM_CONCRETE_INSTRUCTION_LIST(DECLARE_OPCODE)
kNumberOfInstructions
#undef DECLARE_OPCODE
};
virtual Opcode opcode() const = 0;
// Declare non-virtual type testers for all leaf IR classes.
#define DECLARE_PREDICATE(type) \
bool Is##type() const { return opcode() == k##type; }
LITHIUM_CONCRETE_INSTRUCTION_LIST(DECLARE_PREDICATE)
#undef DECLARE_PREDICATE
// Declare virtual predicates for instructions that don't have
// an opcode.
virtual bool IsGap() const { return false; }
virtual bool IsControl() const { return false; } virtual bool IsControl() const { return false; }
virtual void SetBranchTargets(int true_block_id, int false_block_id) { } virtual void SetBranchTargets(int true_block_id, int false_block_id) { }
...@@ -337,8 +348,13 @@ class LGap: public LTemplateInstruction<0, 0, 0> { ...@@ -337,8 +348,13 @@ class LGap: public LTemplateInstruction<0, 0, 0> {
parallel_moves_[AFTER] = NULL; parallel_moves_[AFTER] = NULL;
} }
DECLARE_CONCRETE_INSTRUCTION(Gap, "gap") // Can't use the DECLARE-macro here because of sub-classes.
virtual void PrintDataTo(StringStream* stream) const; virtual bool IsGap() const { return true; }
virtual void PrintDataTo(StringStream* stream);
static LGap* cast(LInstruction* instr) {
ASSERT(instr->IsGap());
return reinterpret_cast<LGap*>(instr);
}
bool IsRedundant() const; bool IsRedundant() const;
...@@ -368,6 +384,14 @@ class LGap: public LTemplateInstruction<0, 0, 0> { ...@@ -368,6 +384,14 @@ class LGap: public LTemplateInstruction<0, 0, 0> {
}; };
class LInstructionGap: public LGap {
public:
explicit LInstructionGap(HBasicBlock* block) : LGap(block) { }
DECLARE_CONCRETE_INSTRUCTION(InstructionGap, "gap")
};
class LGoto: public LTemplateInstruction<0, 0, 0> { class LGoto: public LTemplateInstruction<0, 0, 0> {
public: public:
LGoto(int block_id, bool include_stack_check = false) LGoto(int block_id, bool include_stack_check = false)
...@@ -456,7 +480,6 @@ class LUnknownOSRValue: public LTemplateInstruction<1, 0, 0> { ...@@ -456,7 +480,6 @@ class LUnknownOSRValue: public LTemplateInstruction<1, 0, 0> {
template<int I, int T> template<int I, int T>
class LControlInstruction: public LTemplateInstruction<0, I, T> { class LControlInstruction: public LTemplateInstruction<0, I, T> {
public: public:
DECLARE_INSTRUCTION(ControlInstruction)
virtual bool IsControl() const { return true; } virtual bool IsControl() const { return true; }
int true_block_id() const { return true_block_id_; } int true_block_id() const { return true_block_id_; }
...@@ -1107,6 +1130,7 @@ class LArithmeticD: public LTemplateInstruction<1, 2, 0> { ...@@ -1107,6 +1130,7 @@ class LArithmeticD: public LTemplateInstruction<1, 2, 0> {
Token::Value op() const { return op_; } Token::Value op() const { return op_; }
virtual Opcode opcode() const { return LInstruction::kArithmeticD; }
virtual void CompileToNative(LCodeGen* generator); virtual void CompileToNative(LCodeGen* generator);
virtual const char* Mnemonic() const; virtual const char* Mnemonic() const;
...@@ -1123,6 +1147,7 @@ class LArithmeticT: public LTemplateInstruction<1, 2, 0> { ...@@ -1123,6 +1147,7 @@ class LArithmeticT: public LTemplateInstruction<1, 2, 0> {
inputs_[1] = right; inputs_[1] = right;
} }
virtual Opcode opcode() const { return LInstruction::kArithmeticT; }
virtual void CompileToNative(LCodeGen* generator); virtual void CompileToNative(LCodeGen* generator);
virtual const char* Mnemonic() const; virtual const char* Mnemonic() const;
...@@ -2224,7 +2249,6 @@ class LChunkBuilder BASE_EMBEDDED { ...@@ -2224,7 +2249,6 @@ class LChunkBuilder BASE_EMBEDDED {
}; };
#undef DECLARE_HYDROGEN_ACCESSOR #undef DECLARE_HYDROGEN_ACCESSOR
#undef DECLARE_INSTRUCTION
#undef DECLARE_CONCRETE_INSTRUCTION #undef DECLARE_CONCRETE_INSTRUCTION
} } // namespace v8::internal } } // namespace v8::internal
......
...@@ -739,7 +739,7 @@ void LCodeGen::DoLabel(LLabel* label) { ...@@ -739,7 +739,7 @@ void LCodeGen::DoLabel(LLabel* label) {
} }
__ bind(label->label()); __ bind(label->label());
current_block_ = label->block_id(); current_block_ = label->block_id();
LCodeGen::DoGap(label); DoGap(label);
} }
...@@ -765,6 +765,11 @@ void LCodeGen::DoGap(LGap* gap) { ...@@ -765,6 +765,11 @@ void LCodeGen::DoGap(LGap* gap) {
} }
void LCodeGen::DoInstructionGap(LInstructionGap* instr) {
DoGap(instr);
}
void LCodeGen::DoParameter(LParameter* instr) { void LCodeGen::DoParameter(LParameter* instr) {
// Nothing to do. // Nothing to do.
} }
......
...@@ -115,6 +115,7 @@ class LCodeGen BASE_EMBEDDED { ...@@ -115,6 +115,7 @@ class LCodeGen BASE_EMBEDDED {
// Parallel move support. // Parallel move support.
void DoParallelMove(LParallelMove* move); void DoParallelMove(LParallelMove* move);
void DoGap(LGap* instr);
// Emit frame translation commands for an environment. // Emit frame translation commands for an environment.
void WriteTranslation(LEnvironment* environment, Translation* translation); void WriteTranslation(LEnvironment* environment, Translation* translation);
......
...@@ -689,7 +689,7 @@ void LCodeGen::DoLabel(LLabel* label) { ...@@ -689,7 +689,7 @@ void LCodeGen::DoLabel(LLabel* label) {
} }
__ bind(label->label()); __ bind(label->label());
current_block_ = label->block_id(); current_block_ = label->block_id();
LCodeGen::DoGap(label); DoGap(label);
} }
...@@ -715,6 +715,11 @@ void LCodeGen::DoGap(LGap* gap) { ...@@ -715,6 +715,11 @@ void LCodeGen::DoGap(LGap* gap) {
} }
void LCodeGen::DoInstructionGap(LInstructionGap* instr) {
DoGap(instr);
}
void LCodeGen::DoParameter(LParameter* instr) { void LCodeGen::DoParameter(LParameter* instr) {
// Nothing to do. // Nothing to do.
} }
......
...@@ -105,6 +105,7 @@ class LCodeGen BASE_EMBEDDED { ...@@ -105,6 +105,7 @@ class LCodeGen BASE_EMBEDDED {
// Parallel move support. // Parallel move support.
void DoParallelMove(LParallelMove* move); void DoParallelMove(LParallelMove* move);
void DoGap(LGap* instr);
// Emit frame translation commands for an environment. // Emit frame translation commands for an environment.
void WriteTranslation(LEnvironment* environment, Translation* translation); void WriteTranslation(LEnvironment* environment, Translation* translation);
......
...@@ -449,7 +449,7 @@ void LStoreKeyedGeneric::PrintDataTo(StringStream* stream) { ...@@ -449,7 +449,7 @@ void LStoreKeyedGeneric::PrintDataTo(StringStream* stream) {
void LChunk::AddInstruction(LInstruction* instr, HBasicBlock* block) { void LChunk::AddInstruction(LInstruction* instr, HBasicBlock* block) {
LGap* gap = new LGap(block); LInstructionGap* gap = new LInstructionGap(block);
int index = -1; int index = -1;
if (instr->IsControl()) { if (instr->IsControl()) {
instructions_.Add(gap); instructions_.Add(gap);
......
...@@ -39,13 +39,6 @@ namespace internal { ...@@ -39,13 +39,6 @@ namespace internal {
// Forward declarations. // Forward declarations.
class LCodeGen; class LCodeGen;
#define LITHIUM_ALL_INSTRUCTION_LIST(V) \
V(ControlInstruction) \
V(Call) \
LITHIUM_CONCRETE_INSTRUCTION_LIST(V)
#define LITHIUM_CONCRETE_INSTRUCTION_LIST(V) \ #define LITHIUM_CONCRETE_INSTRUCTION_LIST(V) \
V(AccessArgumentsAt) \ V(AccessArgumentsAt) \
V(AddI) \ V(AddI) \
...@@ -94,7 +87,6 @@ class LCodeGen; ...@@ -94,7 +87,6 @@ class LCodeGen;
V(ExternalArrayLength) \ V(ExternalArrayLength) \
V(FixedArrayLength) \ V(FixedArrayLength) \
V(FunctionLiteral) \ V(FunctionLiteral) \
V(Gap) \
V(GetCachedArrayIndex) \ V(GetCachedArrayIndex) \
V(GlobalObject) \ V(GlobalObject) \
V(GlobalReceiver) \ V(GlobalReceiver) \
...@@ -107,6 +99,7 @@ class LCodeGen; ...@@ -107,6 +99,7 @@ class LCodeGen;
V(InstanceOf) \ V(InstanceOf) \
V(InstanceOfAndBranch) \ V(InstanceOfAndBranch) \
V(InstanceOfKnownGlobal) \ V(InstanceOfKnownGlobal) \
V(InstructionGap) \
V(Integer32ToDouble) \ V(Integer32ToDouble) \
V(InvokeFunction) \ V(InvokeFunction) \
V(IsNull) \ V(IsNull) \
...@@ -173,20 +166,16 @@ class LCodeGen; ...@@ -173,20 +166,16 @@ class LCodeGen;
V(ValueOf) V(ValueOf)
#define DECLARE_INSTRUCTION(type) \ #define DECLARE_CONCRETE_INSTRUCTION(type, mnemonic) \
virtual bool Is##type() const { return true; } \ virtual Opcode opcode() const { return LInstruction::k##type; } \
static L##type* cast(LInstruction* instr) { \ virtual void CompileToNative(LCodeGen* generator); \
ASSERT(instr->Is##type()); \ virtual const char* Mnemonic() const { return mnemonic; } \
return reinterpret_cast<L##type*>(instr); \ static L##type* cast(LInstruction* instr) { \
ASSERT(instr->Is##type()); \
return reinterpret_cast<L##type*>(instr); \
} }
#define DECLARE_CONCRETE_INSTRUCTION(type, mnemonic) \
virtual void CompileToNative(LCodeGen* generator); \
virtual const char* Mnemonic() const { return mnemonic; } \
DECLARE_INSTRUCTION(type)
#define DECLARE_HYDROGEN_ACCESSOR(type) \ #define DECLARE_HYDROGEN_ACCESSOR(type) \
H##type* hydrogen() const { \ H##type* hydrogen() const { \
return H##type::cast(hydrogen_value()); \ return H##type::cast(hydrogen_value()); \
...@@ -208,10 +197,25 @@ class LInstruction: public ZoneObject { ...@@ -208,10 +197,25 @@ class LInstruction: public ZoneObject {
virtual void PrintDataTo(StringStream* stream) = 0; virtual void PrintDataTo(StringStream* stream) = 0;
virtual void PrintOutputOperandTo(StringStream* stream) = 0; virtual void PrintOutputOperandTo(StringStream* stream) = 0;
// Declare virtual type testers. enum Opcode {
#define DECLARE_DO(type) virtual bool Is##type() const { return false; } // Declare a unique enum value for each instruction.
LITHIUM_ALL_INSTRUCTION_LIST(DECLARE_DO) #define DECLARE_OPCODE(type) k##type,
#undef DECLARE_DO LITHIUM_CONCRETE_INSTRUCTION_LIST(DECLARE_OPCODE)
kNumberOfInstructions
#undef DECLARE_OPCODE
};
virtual Opcode opcode() const = 0;
// Declare non-virtual type testers for all leaf IR classes.
#define DECLARE_PREDICATE(type) \
bool Is##type() const { return opcode() == k##type; }
LITHIUM_CONCRETE_INSTRUCTION_LIST(DECLARE_PREDICATE)
#undef DECLARE_PREDICATE
// Declare virtual predicates for instructions that don't have
// an opcode.
virtual bool IsGap() const { return false; }
virtual bool IsControl() const { return false; } virtual bool IsControl() const { return false; }
virtual void SetBranchTargets(int true_block_id, int false_block_id) { } virtual void SetBranchTargets(int true_block_id, int false_block_id) { }
...@@ -331,16 +335,20 @@ class LTemplateInstruction: public LInstruction { ...@@ -331,16 +335,20 @@ class LTemplateInstruction: public LInstruction {
class LGap: public LTemplateInstruction<0, 0, 0> { class LGap: public LTemplateInstruction<0, 0, 0> {
public: public:
explicit LGap(HBasicBlock* block) explicit LGap(HBasicBlock* block) : block_(block) {
: block_(block) {
parallel_moves_[BEFORE] = NULL; parallel_moves_[BEFORE] = NULL;
parallel_moves_[START] = NULL; parallel_moves_[START] = NULL;
parallel_moves_[END] = NULL; parallel_moves_[END] = NULL;
parallel_moves_[AFTER] = NULL; parallel_moves_[AFTER] = NULL;
} }
DECLARE_CONCRETE_INSTRUCTION(Gap, "gap") // Can't use the DECLARE-macro here because of sub-classes.
virtual bool IsGap() const { return true; }
virtual void PrintDataTo(StringStream* stream); virtual void PrintDataTo(StringStream* stream);
static LGap* cast(LInstruction* instr) {
ASSERT(instr->IsGap());
return reinterpret_cast<LGap*>(instr);
}
bool IsRedundant() const; bool IsRedundant() const;
...@@ -370,6 +378,14 @@ class LGap: public LTemplateInstruction<0, 0, 0> { ...@@ -370,6 +378,14 @@ class LGap: public LTemplateInstruction<0, 0, 0> {
}; };
class LInstructionGap: public LGap {
public:
explicit LInstructionGap(HBasicBlock* block) : LGap(block) { }
DECLARE_CONCRETE_INSTRUCTION(InstructionGap, "gap")
};
class LGoto: public LTemplateInstruction<0, 0, 0> { class LGoto: public LTemplateInstruction<0, 0, 0> {
public: public:
LGoto(int block_id, bool include_stack_check = false) LGoto(int block_id, bool include_stack_check = false)
...@@ -464,7 +480,6 @@ class LUnknownOSRValue: public LTemplateInstruction<1, 0, 0> { ...@@ -464,7 +480,6 @@ class LUnknownOSRValue: public LTemplateInstruction<1, 0, 0> {
template<int I, int T> template<int I, int T>
class LControlInstruction: public LTemplateInstruction<0, I, T> { class LControlInstruction: public LTemplateInstruction<0, I, T> {
public: public:
DECLARE_INSTRUCTION(ControlInstruction)
virtual bool IsControl() const { return true; } virtual bool IsControl() const { return true; }
int true_block_id() const { return true_block_id_; } int true_block_id() const { return true_block_id_; }
...@@ -1134,6 +1149,7 @@ class LArithmeticD: public LTemplateInstruction<1, 2, 0> { ...@@ -1134,6 +1149,7 @@ class LArithmeticD: public LTemplateInstruction<1, 2, 0> {
Token::Value op() const { return op_; } Token::Value op() const { return op_; }
virtual Opcode opcode() const { return LInstruction::kArithmeticD; }
virtual void CompileToNative(LCodeGen* generator); virtual void CompileToNative(LCodeGen* generator);
virtual const char* Mnemonic() const; virtual const char* Mnemonic() const;
...@@ -1150,6 +1166,7 @@ class LArithmeticT: public LTemplateInstruction<1, 2, 0> { ...@@ -1150,6 +1166,7 @@ class LArithmeticT: public LTemplateInstruction<1, 2, 0> {
inputs_[1] = right; inputs_[1] = right;
} }
virtual Opcode opcode() const { return LInstruction::kArithmeticT; }
virtual void CompileToNative(LCodeGen* generator); virtual void CompileToNative(LCodeGen* generator);
virtual const char* Mnemonic() const; virtual const char* Mnemonic() const;
...@@ -2283,7 +2300,6 @@ class LChunkBuilder BASE_EMBEDDED { ...@@ -2283,7 +2300,6 @@ class LChunkBuilder BASE_EMBEDDED {
}; };
#undef DECLARE_HYDROGEN_ACCESSOR #undef DECLARE_HYDROGEN_ACCESSOR
#undef DECLARE_INSTRUCTION
#undef DECLARE_CONCRETE_INSTRUCTION #undef DECLARE_CONCRETE_INSTRUCTION
} } // namespace v8::internal } } // namespace v8::internal
......
...@@ -690,7 +690,7 @@ void LCodeGen::DoLabel(LLabel* label) { ...@@ -690,7 +690,7 @@ void LCodeGen::DoLabel(LLabel* label) {
} }
__ bind(label->label()); __ bind(label->label());
current_block_ = label->block_id(); current_block_ = label->block_id();
LCodeGen::DoGap(label); DoGap(label);
} }
...@@ -716,6 +716,11 @@ void LCodeGen::DoGap(LGap* gap) { ...@@ -716,6 +716,11 @@ void LCodeGen::DoGap(LGap* gap) {
} }
void LCodeGen::DoInstructionGap(LInstructionGap* instr) {
DoGap(instr);
}
void LCodeGen::DoParameter(LParameter* instr) { void LCodeGen::DoParameter(LParameter* instr) {
// Nothing to do. // Nothing to do.
} }
......
...@@ -102,6 +102,7 @@ class LCodeGen BASE_EMBEDDED { ...@@ -102,6 +102,7 @@ class LCodeGen BASE_EMBEDDED {
// Parallel move support. // Parallel move support.
void DoParallelMove(LParallelMove* move); void DoParallelMove(LParallelMove* move);
void DoGap(LGap* instr);
// Emit frame translation commands for an environment. // Emit frame translation commands for an environment.
void WriteTranslation(LEnvironment* environment, Translation* translation); void WriteTranslation(LEnvironment* environment, Translation* translation);
......
...@@ -448,7 +448,7 @@ void LStoreKeyedGeneric::PrintDataTo(StringStream* stream) { ...@@ -448,7 +448,7 @@ void LStoreKeyedGeneric::PrintDataTo(StringStream* stream) {
void LChunk::AddInstruction(LInstruction* instr, HBasicBlock* block) { void LChunk::AddInstruction(LInstruction* instr, HBasicBlock* block) {
LGap* gap = new LGap(block); LInstructionGap* gap = new LInstructionGap(block);
int index = -1; int index = -1;
if (instr->IsControl()) { if (instr->IsControl()) {
instructions_.Add(gap); instructions_.Add(gap);
......
...@@ -93,7 +93,6 @@ class LCodeGen; ...@@ -93,7 +93,6 @@ class LCodeGen;
V(ExternalArrayLength) \ V(ExternalArrayLength) \
V(FixedArrayLength) \ V(FixedArrayLength) \
V(FunctionLiteral) \ V(FunctionLiteral) \
V(Gap) \
V(GetCachedArrayIndex) \ V(GetCachedArrayIndex) \
V(GlobalObject) \ V(GlobalObject) \
V(GlobalReceiver) \ V(GlobalReceiver) \
...@@ -106,6 +105,7 @@ class LCodeGen; ...@@ -106,6 +105,7 @@ class LCodeGen;
V(InstanceOf) \ V(InstanceOf) \
V(InstanceOfAndBranch) \ V(InstanceOfAndBranch) \
V(InstanceOfKnownGlobal) \ V(InstanceOfKnownGlobal) \
V(InstructionGap) \
V(Integer32ToDouble) \ V(Integer32ToDouble) \
V(InvokeFunction) \ V(InvokeFunction) \
V(IsNull) \ V(IsNull) \
...@@ -172,20 +172,16 @@ class LCodeGen; ...@@ -172,20 +172,16 @@ class LCodeGen;
V(ValueOf) V(ValueOf)
#define DECLARE_INSTRUCTION(type) \ #define DECLARE_CONCRETE_INSTRUCTION(type, mnemonic) \
virtual bool Is##type() const { return true; } \ virtual Opcode opcode() const { return LInstruction::k##type; } \
static L##type* cast(LInstruction* instr) { \ virtual void CompileToNative(LCodeGen* generator); \
ASSERT(instr->Is##type()); \ virtual const char* Mnemonic() const { return mnemonic; } \
return reinterpret_cast<L##type*>(instr); \ static L##type* cast(LInstruction* instr) { \
ASSERT(instr->Is##type()); \
return reinterpret_cast<L##type*>(instr); \
} }
#define DECLARE_CONCRETE_INSTRUCTION(type, mnemonic) \
virtual void CompileToNative(LCodeGen* generator); \
virtual const char* Mnemonic() const { return mnemonic; } \
DECLARE_INSTRUCTION(type)
#define DECLARE_HYDROGEN_ACCESSOR(type) \ #define DECLARE_HYDROGEN_ACCESSOR(type) \
H##type* hydrogen() const { \ H##type* hydrogen() const { \
return H##type::cast(hydrogen_value()); \ return H##type::cast(hydrogen_value()); \
...@@ -208,10 +204,25 @@ class LInstruction: public ZoneObject { ...@@ -208,10 +204,25 @@ class LInstruction: public ZoneObject {
virtual void PrintDataTo(StringStream* stream) = 0; virtual void PrintDataTo(StringStream* stream) = 0;
virtual void PrintOutputOperandTo(StringStream* stream) = 0; virtual void PrintOutputOperandTo(StringStream* stream) = 0;
// Declare virtual type testers. enum Opcode {
#define DECLARE_DO(type) virtual bool Is##type() const { return false; } // Declare a unique enum value for each instruction.
LITHIUM_ALL_INSTRUCTION_LIST(DECLARE_DO) #define DECLARE_OPCODE(type) k##type,
#undef DECLARE_DO LITHIUM_CONCRETE_INSTRUCTION_LIST(DECLARE_OPCODE)
kNumberOfInstructions
#undef DECLARE_OPCODE
};
virtual Opcode opcode() const = 0;
// Declare non-virtual type testers for all leaf IR classes.
#define DECLARE_PREDICATE(type) \
bool Is##type() const { return opcode() == k##type; }
LITHIUM_CONCRETE_INSTRUCTION_LIST(DECLARE_PREDICATE)
#undef DECLARE_PREDICATE
// Declare virtual predicates for instructions that don't have
// an opcode.
virtual bool IsGap() const { return false; }
virtual bool IsControl() const { return false; } virtual bool IsControl() const { return false; }
virtual void SetBranchTargets(int true_block_id, int false_block_id) { } virtual void SetBranchTargets(int true_block_id, int false_block_id) { }
...@@ -338,8 +349,13 @@ class LGap: public LTemplateInstruction<0, 0, 0> { ...@@ -338,8 +349,13 @@ class LGap: public LTemplateInstruction<0, 0, 0> {
parallel_moves_[AFTER] = NULL; parallel_moves_[AFTER] = NULL;
} }
DECLARE_CONCRETE_INSTRUCTION(Gap, "gap") // Can't use the DECLARE-macro here because of sub-classes.
virtual bool IsGap() const { return true; }
virtual void PrintDataTo(StringStream* stream); virtual void PrintDataTo(StringStream* stream);
static LGap* cast(LInstruction* instr) {
ASSERT(instr->IsGap());
return reinterpret_cast<LGap*>(instr);
}
bool IsRedundant() const; bool IsRedundant() const;
...@@ -369,6 +385,14 @@ class LGap: public LTemplateInstruction<0, 0, 0> { ...@@ -369,6 +385,14 @@ class LGap: public LTemplateInstruction<0, 0, 0> {
}; };
class LInstructionGap: public LGap {
public:
explicit LInstructionGap(HBasicBlock* block) : LGap(block) { }
DECLARE_CONCRETE_INSTRUCTION(InstructionGap, "gap")
};
class LGoto: public LTemplateInstruction<0, 0, 0> { class LGoto: public LTemplateInstruction<0, 0, 0> {
public: public:
LGoto(int block_id, bool include_stack_check = false) LGoto(int block_id, bool include_stack_check = false)
...@@ -457,7 +481,6 @@ class LUnknownOSRValue: public LTemplateInstruction<1, 0, 0> { ...@@ -457,7 +481,6 @@ class LUnknownOSRValue: public LTemplateInstruction<1, 0, 0> {
template<int I, int T> template<int I, int T>
class LControlInstruction: public LTemplateInstruction<0, I, T> { class LControlInstruction: public LTemplateInstruction<0, I, T> {
public: public:
DECLARE_INSTRUCTION(ControlInstruction)
virtual bool IsControl() const { return true; } virtual bool IsControl() const { return true; }
int true_block_id() const { return true_block_id_; } int true_block_id() const { return true_block_id_; }
...@@ -1107,6 +1130,7 @@ class LArithmeticD: public LTemplateInstruction<1, 2, 0> { ...@@ -1107,6 +1130,7 @@ class LArithmeticD: public LTemplateInstruction<1, 2, 0> {
Token::Value op() const { return op_; } Token::Value op() const { return op_; }
virtual Opcode opcode() const { return LInstruction::kArithmeticD; }
virtual void CompileToNative(LCodeGen* generator); virtual void CompileToNative(LCodeGen* generator);
virtual const char* Mnemonic() const; virtual const char* Mnemonic() const;
...@@ -1123,6 +1147,7 @@ class LArithmeticT: public LTemplateInstruction<1, 2, 0> { ...@@ -1123,6 +1147,7 @@ class LArithmeticT: public LTemplateInstruction<1, 2, 0> {
inputs_[1] = right; inputs_[1] = right;
} }
virtual Opcode opcode() const { return LInstruction::kArithmeticT; }
virtual void CompileToNative(LCodeGen* generator); virtual void CompileToNative(LCodeGen* generator);
virtual const char* Mnemonic() const; virtual const char* Mnemonic() const;
...@@ -2206,7 +2231,6 @@ class LChunkBuilder BASE_EMBEDDED { ...@@ -2206,7 +2231,6 @@ class LChunkBuilder BASE_EMBEDDED {
}; };
#undef DECLARE_HYDROGEN_ACCESSOR #undef DECLARE_HYDROGEN_ACCESSOR
#undef DECLARE_INSTRUCTION
#undef DECLARE_CONCRETE_INSTRUCTION #undef DECLARE_CONCRETE_INSTRUCTION
} } // namespace v8::int } } // namespace v8::int
......
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