| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef VM_INTERMEDIATE_LANGUAGE_H_ | 5 #ifndef VM_INTERMEDIATE_LANGUAGE_H_ |
| 6 #define VM_INTERMEDIATE_LANGUAGE_H_ | 6 #define VM_INTERMEDIATE_LANGUAGE_H_ |
| 7 | 7 |
| 8 #include "vm/allocation.h" | 8 #include "vm/allocation.h" |
| 9 #include "vm/ast.h" | 9 #include "vm/ast.h" |
| 10 #include "vm/growable_array.h" | 10 #include "vm/growable_array.h" |
| 11 #include "vm/handles_impl.h" | 11 #include "vm/handles_impl.h" |
| 12 #include "vm/object.h" | 12 #include "vm/object.h" |
| 13 | 13 |
| 14 namespace dart { | 14 namespace dart { |
| 15 | 15 |
| 16 class FlowGraphVisitor; | 16 class FlowGraphVisitor; |
| 17 class LocalVariable; | 17 class LocalVariable; |
| 18 | 18 |
| 19 // Computations and values. | 19 // Computations and values. |
| 20 // | 20 // |
| 21 // <Computation> ::= | 21 // <Computation> ::= |
| 22 // <Value> | 22 // <Value> |
| 23 // | CopyTemp <int> | |
| 24 // | SetTemp <int> | |
| 25 // | AssertAssignable <Value> <AbstractType> | 23 // | AssertAssignable <Value> <AbstractType> |
| 26 // | InstanceCall <AstNode> <String> <Value> ... | 24 // | InstanceCall <AstNode> <String> <Value> ... |
| 27 // | StaticCall <StaticCallNode> <Value> ... | 25 // | StaticCall <StaticCallNode> <Value> ... |
| 28 // | LoadLocal <LocalVariable> | 26 // | LoadLocal <LocalVariable> |
| 29 // | StoreLocal <LocalVariable> <Value> | 27 // | StoreLocal <LocalVariable> <Value> |
| 30 // | StrictCompare <Token::kind> <Value> <Value> | 28 // | StrictCompare <Token::kind> <Value> <Value> |
| 31 // | NativeCall <NativeBodyNode> | 29 // | NativeCall <NativeBodyNode> |
| 32 // | StoreIndexed <StoreIndexedNode> <Value> <Value> <Value> | 30 // | StoreIndexed <StoreIndexedNode> <Value> <Value> <Value> |
| 33 // | InstanceSetter <InstanceSetterNode> <Value> <Value> | 31 // | InstanceSetter <InstanceSetterNode> <Value> <Value> |
| 34 // | LoadInstanceField <LoadInstanceFieldNode> <Value> | 32 // | LoadInstanceField <LoadInstanceFieldNode> <Value> |
| 35 // | StoreInstanceField <StoreInstanceFieldNode> <Value> <Value> | 33 // | StoreInstanceField <StoreInstanceFieldNode> <Value> <Value> |
| 36 // | LoadStaticField <Field> | 34 // | LoadStaticField <Field> |
| 37 // | StoreStaticField <StoreStaticFieldNode> <Value> | 35 // | StoreStaticField <StoreStaticFieldNode> <Value> |
| 38 // | 36 // |
| 39 // <Value> ::= | 37 // <Value> ::= |
| 40 // Temp <int> | 38 // Temp <int> |
| 41 // | Constant <Instance> | 39 // | Constant <Instance> |
| 42 | 40 |
| 43 // M is a two argument macro. It is applied to each concrete value's | 41 // M is a two argument macro. It is applied to each concrete value's |
| 44 // typename and classname. | 42 // typename and classname. |
| 45 #define FOR_EACH_VALUE(M) \ | 43 #define FOR_EACH_VALUE(M) \ |
| 46 M(Temp, TempVal) \ | 44 M(Temp, TempVal) \ |
| 47 M(Constant, ConstantVal) \ | 45 M(Constant, ConstantVal) \ |
| 48 | 46 |
| 49 | 47 |
| 50 // M is a two argument macro. It is applied to each concrete instruction's | 48 // M is a two argument macro. It is applied to each concrete instruction's |
| 51 // (including the values) typename and classname. | 49 // (including the values) typename and classname. |
| 52 #define FOR_EACH_COMPUTATION(M) \ | 50 #define FOR_EACH_COMPUTATION(M) \ |
| 53 FOR_EACH_VALUE(M) \ | 51 FOR_EACH_VALUE(M) \ |
| 54 M(CopyTemp, CopyTempComp) \ | |
| 55 M(SetTemp, SetTempComp) \ | |
| 56 M(AssertAssignable, AssertAssignableComp) \ | 52 M(AssertAssignable, AssertAssignableComp) \ |
| 57 M(InstanceCall, InstanceCallComp) \ | 53 M(InstanceCall, InstanceCallComp) \ |
| 58 M(StaticCall, StaticCallComp) \ | 54 M(StaticCall, StaticCallComp) \ |
| 59 M(LoadLocal, LoadLocalComp) \ | 55 M(LoadLocal, LoadLocalComp) \ |
| 60 M(StoreLocal, StoreLocalComp) \ | 56 M(StoreLocal, StoreLocalComp) \ |
| 61 M(StrictCompare, StrictCompareComp) \ | 57 M(StrictCompare, StrictCompareComp) \ |
| 62 M(NativeCall, NativeCallComp) \ | 58 M(NativeCall, NativeCallComp) \ |
| 63 M(StoreIndexed, StoreIndexedComp) \ | 59 M(StoreIndexed, StoreIndexedComp) \ |
| 64 M(InstanceSetter, InstanceSetterComp) \ | 60 M(InstanceSetter, InstanceSetterComp) \ |
| 65 M(LoadInstanceField, LoadInstanceFieldComp) \ | 61 M(LoadInstanceField, LoadInstanceFieldComp) \ |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 137 | 133 |
| 138 private: | 134 private: |
| 139 const Instance& instance_; | 135 const Instance& instance_; |
| 140 | 136 |
| 141 DISALLOW_COPY_AND_ASSIGN(ConstantVal); | 137 DISALLOW_COPY_AND_ASSIGN(ConstantVal); |
| 142 }; | 138 }; |
| 143 | 139 |
| 144 #undef DECLARE_VALUE | 140 #undef DECLARE_VALUE |
| 145 | 141 |
| 146 | 142 |
| 147 // A computation that produces a copy of a (random-access) temporary. The | |
| 148 // index is relative to the last temporary allocated (e.g., the last | |
| 149 // temporary is index 0, the one before that is -1, etc.). This instruction | |
| 150 // is used in the non-optimizing backend and compiled away in the optimizing | |
| 151 // backend. | |
| 152 class CopyTempComp : public Computation { | |
| 153 public: | |
| 154 explicit CopyTempComp(intptr_t index) : index_(index) { } | |
| 155 | |
| 156 DECLARE_COMPUTATION(CopyTemp) | |
| 157 | |
| 158 intptr_t index() const { return index_; } | |
| 159 | |
| 160 private: | |
| 161 const intptr_t index_; | |
| 162 | |
| 163 DISALLOW_COPY_AND_ASSIGN(CopyTempComp); | |
| 164 }; | |
| 165 | |
| 166 | |
| 167 // A computation that assigns (a duplicate of) the last allocated temporary | |
| 168 // to a random-access already allocated temporary. The index is relative to | |
| 169 // the last temporary allocated (e.g., the last temporary is index 0, the | |
| 170 // one before that is -1, etc.). This instruction is used in the | |
| 171 // non-optimizing backend and compiled away in the optimizing backend. | |
| 172 class SetTempComp : public Computation { | |
| 173 public: | |
| 174 explicit SetTempComp(intptr_t index) : index_(index) { } | |
| 175 | |
| 176 DECLARE_COMPUTATION(SetTemp) | |
| 177 | |
| 178 intptr_t index() const { return index_; } | |
| 179 | |
| 180 private: | |
| 181 const intptr_t index_; | |
| 182 | |
| 183 DISALLOW_COPY_AND_ASSIGN(SetTempComp); | |
| 184 }; | |
| 185 | |
| 186 | |
| 187 class AssertAssignableComp : public Computation { | 143 class AssertAssignableComp : public Computation { |
| 188 public: | 144 public: |
| 189 AssertAssignableComp(Value* value, const AbstractType& type) | 145 AssertAssignableComp(Value* value, const AbstractType& type) |
| 190 : value_(value), type_(type) { } | 146 : value_(value), type_(type) { } |
| 191 | 147 |
| 192 DECLARE_COMPUTATION(AssertAssignable) | 148 DECLARE_COMPUTATION(AssertAssignable) |
| 193 | 149 |
| 194 Value* value() const { return value_; } | 150 Value* value() const { return value_; } |
| 195 const AbstractType& type() const { return type_; } | 151 const AbstractType& type() const { return type_; } |
| 196 | 152 |
| (...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 485 | 441 |
| 486 DISALLOW_COPY_AND_ASSIGN(InstanceSetterComp); | 442 DISALLOW_COPY_AND_ASSIGN(InstanceSetterComp); |
| 487 }; | 443 }; |
| 488 | 444 |
| 489 | 445 |
| 490 #undef DECLARE_COMPUTATION | 446 #undef DECLARE_COMPUTATION |
| 491 | 447 |
| 492 | 448 |
| 493 // Instructions. | 449 // Instructions. |
| 494 // | 450 // |
| 495 // <Instruction> ::= Do <Computation> <Instruction> | 451 // <Instruction> ::= JoinEntry <Instruction> |
| 452 // | TargetEntry <Instruction> |
| 453 // | PickTemp <int> <int> <Instruction> |
| 454 // | TuckTemp <int> <int> <Instruction> |
| 455 // | Do <Computation> <Instruction> |
| 496 // | Bind <int> <Computation> <Instruction> | 456 // | Bind <int> <Computation> <Instruction> |
| 497 // | Return <Value> | 457 // | Return <Value> |
| 498 // | Branch <Value> <Instruction> <Instruction> | 458 // | Branch <Value> <Instruction> <Instruction> |
| 499 // | Empty <Instruction> | |
| 500 | 459 |
| 501 // M is a single argument macro. It is applied to each concrete instruction | 460 // M is a single argument macro. It is applied to each concrete instruction |
| 502 // type name. The concrete instruction classes are the name with Instr | 461 // type name. The concrete instruction classes are the name with Instr |
| 503 // concatenated. | 462 // concatenated. |
| 504 #define FOR_EACH_INSTRUCTION(M) \ | 463 #define FOR_EACH_INSTRUCTION(M) \ |
| 505 M(JoinEntry) \ | 464 M(JoinEntry) \ |
| 506 M(TargetEntry) \ | 465 M(TargetEntry) \ |
| 466 M(PickTemp) \ |
| 467 M(TuckTemp) \ |
| 507 M(Do) \ | 468 M(Do) \ |
| 508 M(Bind) \ | 469 M(Bind) \ |
| 509 M(Return) \ | 470 M(Return) \ |
| 510 M(Branch) | 471 M(Branch) \ |
| 511 | 472 |
| 512 | 473 |
| 513 // Forward declarations for Instruction classes. | 474 // Forward declarations for Instruction classes. |
| 514 class BlockEntryInstr; | 475 class BlockEntryInstr; |
| 515 #define FORWARD_DECLARATION(type) class type##Instr; | 476 #define FORWARD_DECLARATION(type) class type##Instr; |
| 516 FOR_EACH_INSTRUCTION(FORWARD_DECLARATION) | 477 FOR_EACH_INSTRUCTION(FORWARD_DECLARATION) |
| 517 #undef FORWARD_DECLARATION | 478 #undef FORWARD_DECLARATION |
| 518 | 479 |
| 519 | 480 |
| 520 // Functions required in all concrete instruction classes. | 481 // Functions required in all concrete instruction classes. |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 618 | 579 |
| 619 virtual void Postorder(GrowableArray<BlockEntryInstr*>* block_entries); | 580 virtual void Postorder(GrowableArray<BlockEntryInstr*>* block_entries); |
| 620 | 581 |
| 621 private: | 582 private: |
| 622 Instruction* successor_; | 583 Instruction* successor_; |
| 623 | 584 |
| 624 DISALLOW_COPY_AND_ASSIGN(TargetEntryInstr); | 585 DISALLOW_COPY_AND_ASSIGN(TargetEntryInstr); |
| 625 }; | 586 }; |
| 626 | 587 |
| 627 | 588 |
| 589 // The non-optimizing compiler assumes that there is exactly one use of |
| 590 // every temporary so they can be deallocated at their use. Some AST nodes, |
| 591 // e.g., expr0[expr1]++, violate this assumption (there are two uses of each |
| 592 // of the values expr0 and expr1). |
| 593 // |
| 594 // PickTemp is used to name (with 'destination') a copy of a live temporary |
| 595 // (named 'source') without counting as the use of the source. |
| 596 class PickTempInstr : public Instruction { |
| 597 public: |
| 598 PickTempInstr(intptr_t dst, intptr_t src) |
| 599 : Instruction(), destination_(dst), source_(src), successor_(NULL) { } |
| 600 |
| 601 DECLARE_INSTRUCTION(PickTemp) |
| 602 |
| 603 intptr_t destination() const { return destination_; } |
| 604 intptr_t source() const { return source_; } |
| 605 |
| 606 virtual void SetSuccessor(Instruction* instr) { |
| 607 ASSERT(successor_ == NULL && instr != NULL); |
| 608 successor_ = instr; |
| 609 } |
| 610 |
| 611 virtual void Postorder(GrowableArray<BlockEntryInstr*>* block_entries); |
| 612 |
| 613 private: |
| 614 const intptr_t destination_; |
| 615 const intptr_t source_; |
| 616 Instruction* successor_; |
| 617 |
| 618 DISALLOW_COPY_AND_ASSIGN(PickTempInstr); |
| 619 }; |
| 620 |
| 621 |
| 622 // The non-optimizing compiler assumes that temporary definitions and uses |
| 623 // obey a stack discipline, so they can be allocated and deallocated with |
| 624 // push and pop. Some Some AST nodes, e.g., expr++, violate this assumption |
| 625 // (the value expr+1 is produced after the value of expr, and also consumed |
| 626 // after it). |
| 627 // |
| 628 // We 'preallocate' temporaries (named with 'destination') such as the one |
| 629 // for expr+1 and use TuckTemp to mutate them by overwriting them with a |
| 630 // copy of a temporary (named with 'source'). |
| 631 class TuckTempInstr : public Instruction { |
| 632 public: |
| 633 TuckTempInstr(intptr_t dst, intptr_t src) |
| 634 : Instruction(), destination_(dst), source_(src), successor_(NULL) { } |
| 635 |
| 636 DECLARE_INSTRUCTION(TuckTemp) |
| 637 |
| 638 intptr_t destination() const { return destination_; } |
| 639 intptr_t source() const { return source_; } |
| 640 |
| 641 virtual void SetSuccessor(Instruction* instr) { |
| 642 ASSERT(successor_ == NULL && instr != NULL); |
| 643 successor_ = instr; |
| 644 } |
| 645 |
| 646 virtual void Postorder(GrowableArray<BlockEntryInstr*>* block_entries); |
| 647 |
| 648 private: |
| 649 const intptr_t destination_; |
| 650 const intptr_t source_; |
| 651 Instruction* successor_; |
| 652 |
| 653 DISALLOW_COPY_AND_ASSIGN(TuckTempInstr); |
| 654 }; |
| 655 |
| 656 |
| 628 class DoInstr : public Instruction { | 657 class DoInstr : public Instruction { |
| 629 public: | 658 public: |
| 630 explicit DoInstr(Computation* comp) | 659 explicit DoInstr(Computation* comp) |
| 631 : Instruction(), computation_(comp), successor_(NULL) { } | 660 : Instruction(), computation_(comp), successor_(NULL) { } |
| 632 | 661 |
| 633 DECLARE_INSTRUCTION(Do) | 662 DECLARE_INSTRUCTION(Do) |
| 634 | 663 |
| 635 Computation* computation() const { return computation_; } | 664 Computation* computation() const { return computation_; } |
| 636 | 665 |
| 637 virtual void SetSuccessor(Instruction* instr) { | 666 virtual void SetSuccessor(Instruction* instr) { |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 758 #undef DECLARE_VISIT_INSTRUCTION | 787 #undef DECLARE_VISIT_INSTRUCTION |
| 759 | 788 |
| 760 private: | 789 private: |
| 761 DISALLOW_COPY_AND_ASSIGN(FlowGraphVisitor); | 790 DISALLOW_COPY_AND_ASSIGN(FlowGraphVisitor); |
| 762 }; | 791 }; |
| 763 | 792 |
| 764 | 793 |
| 765 } // namespace dart | 794 } // namespace dart |
| 766 | 795 |
| 767 #endif // VM_INTERMEDIATE_LANGUAGE_H_ | 796 #endif // VM_INTERMEDIATE_LANGUAGE_H_ |
| OLD | NEW |