Chromium Code Reviews| Index: runtime/vm/intermediate_language.h |
| diff --git a/runtime/vm/intermediate_language.h b/runtime/vm/intermediate_language.h |
| index d7b049737417d1294cdbb220144b0a720160805a..97573f3434cf61c98d4fccaacb2e64bf64b21971 100644 |
| --- a/runtime/vm/intermediate_language.h |
| +++ b/runtime/vm/intermediate_language.h |
| @@ -20,6 +20,7 @@ class LocalVariable; |
| // typename and classname. |
| #define FOR_EACH_VALUE(M) \ |
| M(Temp, TempVal) \ |
| + M(Use, UseVal) \ |
| M(Constant, ConstantVal) \ |
| @@ -118,6 +119,24 @@ class TempVal : public Value { |
| }; |
| +// Definitions and uses are mutually recursive. |
| +class Definition; |
| + |
| +class UseVal : public Value { |
| + public: |
| + explicit UseVal(Definition* definition) : definition_(definition) { } |
| + |
| + DECLARE_VALUE(Use) |
| + |
| + Definition* definition() const { return definition_; } |
| + |
| + private: |
| + Definition* const definition_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(UseVal); |
| +}; |
| + |
| + |
| class ConstantVal: public Value { |
| public: |
| explicit ConstantVal(const Object& value) : value_(value) { |
| @@ -1028,12 +1047,12 @@ class CatchEntryComp : public Computation { |
| // |
| // <Instruction> ::= JoinEntry <Instruction> |
| // | TargetEntry <Instruction> |
| -// | PickTemp <int> <int> <Instruction> |
| -// | TuckTemp <int> <int> <Instruction> |
| // | Do <Computation> <Instruction> |
| -// | Bind <int> <Computation> <Instruction> |
| // | Return <Value> |
| // | Branch <Value> <Instruction> <Instruction> |
| +// <Definition> ::= PickTemp <int> <int> <Instruction> |
| +// | TuckTemp <int> <int> <Instruction> |
| +// | Bind <int> <Computation> <Instruction> |
| // M is a single argument macro. It is applied to each concrete instruction |
| // type name. The concrete instruction classes are the name with Instr |
| @@ -1041,10 +1060,10 @@ class CatchEntryComp : public Computation { |
| #define FOR_EACH_INSTRUCTION(M) \ |
| M(JoinEntry) \ |
| M(TargetEntry) \ |
| - M(PickTemp) \ |
| - M(TuckTemp) \ |
| M(Do) \ |
| M(Bind) \ |
| + M(PickTemp) \ |
| + M(TuckTemp) \ |
| M(Return) \ |
| M(Throw) \ |
| M(ReThrow) \ |
| @@ -1244,125 +1263,134 @@ class TargetEntryInstr : public BlockEntryInstr { |
| }; |
| -// The non-optimizing compiler assumes that there is exactly one use of |
| -// every temporary so they can be deallocated at their use. Some AST nodes, |
| -// e.g., expr0[expr1]++, violate this assumption (there are two uses of each |
| -// of the values expr0 and expr1). |
| -// |
| -// PickTemp is used to name (with 'destination') a copy of a live temporary |
| -// (named 'source') without counting as the use of the source. |
| -class PickTempInstr : public Instruction { |
| +class DoInstr : public Instruction { |
| public: |
| - PickTempInstr(intptr_t dst, intptr_t src) |
| - : destination_(dst), source_(src), successor_(NULL) { } |
| + explicit DoInstr(Computation* comp) |
| + : computation_(comp), successor_(NULL) { } |
| - DECLARE_INSTRUCTION(PickTemp) |
| + DECLARE_INSTRUCTION(Do) |
| - intptr_t destination() const { return destination_; } |
| - intptr_t source() const { return source_; } |
| + Computation* computation() const { return computation_; } |
| virtual Instruction* StraightLineSuccessor() const { |
| return successor_; |
| } |
| virtual void SetSuccessor(Instruction* instr) { |
| - ASSERT(successor_ == NULL && instr != NULL); |
| + ASSERT(successor_ == NULL); |
| successor_ = instr; |
| } |
| private: |
| - const intptr_t destination_; |
| - const intptr_t source_; |
| + Computation* computation_; |
| Instruction* successor_; |
| - DISALLOW_COPY_AND_ASSIGN(PickTempInstr); |
| + DISALLOW_COPY_AND_ASSIGN(DoInstr); |
| }; |
| -// The non-optimizing compiler assumes that temporary definitions and uses |
| -// obey a stack discipline, so they can be allocated and deallocated with |
| -// push and pop. Some Some AST nodes, e.g., expr++, violate this assumption |
| -// (the value expr+1 is produced after the value of expr, and also consumed |
| -// after it). |
| -// |
| -// We 'preallocate' temporaries (named with 'destination') such as the one |
| -// for expr+1 and use TuckTemp to mutate them by overwriting them with a |
| -// copy of a temporary (named with 'source'). |
| -class TuckTempInstr : public Instruction { |
| +class Definition : public Instruction { |
| public: |
| - TuckTempInstr(intptr_t dst, intptr_t src) |
| - : destination_(dst), source_(src), successor_(NULL) { } |
| + explicit Definition(intptr_t temp_index) : temp_index_(temp_index) { } |
| - DECLARE_INSTRUCTION(TuckTemp) |
| + intptr_t temp_index() const { return temp_index_; } |
|
srdjan
2012/04/24 22:02:18
Why don't you need DECLARE_INSTRUCTION(Definition)
Kevin Millikin (Google)
2012/04/25 08:50:51
Because it's an abstract, not concrete, instructio
|
| + |
| + private: |
| + const intptr_t temp_index_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(Definition); |
| +}; |
| - intptr_t destination() const { return destination_; } |
| - intptr_t source() const { return source_; } |
| + |
| +class BindInstr : public Definition { |
| + public: |
| + BindInstr(intptr_t temp_index, Computation* computation) |
| + : Definition(temp_index), computation_(computation), successor_(NULL) { } |
| + |
| + DECLARE_INSTRUCTION(Bind) |
| + |
| + Computation* computation() const { return computation_; } |
| virtual Instruction* StraightLineSuccessor() const { |
| return successor_; |
| } |
| virtual void SetSuccessor(Instruction* instr) { |
| - ASSERT(successor_ == NULL && instr != NULL); |
| + ASSERT(successor_ == NULL); |
| successor_ = instr; |
| } |
| private: |
| - const intptr_t destination_; |
| - const intptr_t source_; |
| + Computation* computation_; |
| Instruction* successor_; |
| - DISALLOW_COPY_AND_ASSIGN(TuckTempInstr); |
| + DISALLOW_COPY_AND_ASSIGN(BindInstr); |
| }; |
| -class DoInstr : public Instruction { |
| +// The non-optimizing compiler assumes that there is exactly one use of |
| +// every temporary so they can be deallocated at their use. Some AST nodes, |
| +// e.g., expr0[expr1]++, violate this assumption (there are two uses of each |
| +// of the values expr0 and expr1). |
| +// |
| +// PickTemp is used to name (with 'destination') a copy of a live temporary |
| +// (named 'source') without counting as the use of the source. |
| +class PickTempInstr : public Definition { |
| public: |
| - explicit DoInstr(Computation* comp) |
| - : computation_(comp), successor_(NULL) { } |
| + PickTempInstr(intptr_t temp_index, intptr_t source) |
| + : Definition(temp_index), source_(source), successor_(NULL) { } |
| - DECLARE_INSTRUCTION(Do) |
| + DECLARE_INSTRUCTION(PickTemp) |
| - Computation* computation() const { return computation_; } |
| + intptr_t source() const { return source_; } |
| virtual Instruction* StraightLineSuccessor() const { |
| return successor_; |
| } |
| virtual void SetSuccessor(Instruction* instr) { |
| - ASSERT(successor_ == NULL); |
| + ASSERT(successor_ == NULL && instr != NULL); |
| successor_ = instr; |
| } |
| private: |
| - Computation* computation_; |
| + const intptr_t source_; |
| Instruction* successor_; |
| - DISALLOW_COPY_AND_ASSIGN(DoInstr); |
| + DISALLOW_COPY_AND_ASSIGN(PickTempInstr); |
| }; |
| -class BindInstr : public Instruction { |
| +// The non-optimizing compiler assumes that temporary definitions and uses |
| +// obey a stack discipline, so they can be allocated and deallocated with |
| +// push and pop. Some Some AST nodes, e.g., expr++, violate this assumption |
| +// (the value expr+1 is produced after the value of expr, and also consumed |
| +// after it). |
| +// |
| +// We 'preallocate' temporaries (named with 'destination') such as the one |
| +// for expr+1 and use TuckTemp to mutate them by overwriting them with a |
| +// copy of a temporary (named with 'source'). |
| +class TuckTempInstr : public Instruction { |
| public: |
| - BindInstr(intptr_t temp_index, Computation* computation) |
| - : temp_index_(temp_index), computation_(computation), successor_(NULL) { } |
| + TuckTempInstr(intptr_t destination, intptr_t source) |
| + : destination_(destination), source_(source), successor_(NULL) { } |
| - DECLARE_INSTRUCTION(Bind) |
| + DECLARE_INSTRUCTION(TuckTemp) |
| - intptr_t temp_index() const { return temp_index_; } |
| - Computation* computation() const { return computation_; } |
| + intptr_t destination() const { return destination_; } |
| + intptr_t source() const { return source_; } |
| virtual Instruction* StraightLineSuccessor() const { |
| return successor_; |
| } |
| virtual void SetSuccessor(Instruction* instr) { |
| - ASSERT(successor_ == NULL); |
| + ASSERT(successor_ == NULL && instr != NULL); |
| successor_ = instr; |
| } |
| private: |
| - const intptr_t temp_index_; |
| - Computation* computation_; |
| + const intptr_t destination_; |
| + const intptr_t source_; |
| Instruction* successor_; |
| - DISALLOW_COPY_AND_ASSIGN(BindInstr); |
| + DISALLOW_COPY_AND_ASSIGN(TuckTempInstr); |
| }; |