| 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 #include "vm/intermediate_language.h" | 5 #include "vm/intermediate_language.h" |
| 6 | 6 |
| 7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
| 8 #include "vm/dart_entry.h" | 8 #include "vm/dart_entry.h" |
| 9 #include "vm/flow_graph_allocator.h" | 9 #include "vm/flow_graph_allocator.h" |
| 10 #include "vm/flow_graph_builder.h" | 10 #include "vm/flow_graph_builder.h" |
| (...skipping 684 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 695 GrowableArray<BlockEntryInstr*>* preorder) { | 695 GrowableArray<BlockEntryInstr*>* preorder) { |
| 696 // Detect that a block has been visited as part of the current | 696 // Detect that a block has been visited as part of the current |
| 697 // DiscoverBlocks (we can call DiscoverBlocks multiple times). The block | 697 // DiscoverBlocks (we can call DiscoverBlocks multiple times). The block |
| 698 // will be 'marked' by (1) having a preorder number in the range of the | 698 // will be 'marked' by (1) having a preorder number in the range of the |
| 699 // preorder array and (2) being in the preorder array at that index. | 699 // preorder array and (2) being in the preorder array at that index. |
| 700 intptr_t i = block->preorder_number(); | 700 intptr_t i = block->preorder_number(); |
| 701 return (i >= 0) && (i < preorder->length()) && ((*preorder)[i] == block); | 701 return (i >= 0) && (i < preorder->length()) && ((*preorder)[i] == block); |
| 702 } | 702 } |
| 703 | 703 |
| 704 | 704 |
| 705 void GraphEntryInstr::DiscoverBlocks( | 705 // Base class implementation used for JoinEntry and TargetEntry. |
| 706 BlockEntryInstr* current_block, | 706 void BlockEntryInstr::DiscoverBlocks( |
| 707 BlockEntryInstr* predecessor, |
| 707 GrowableArray<BlockEntryInstr*>* preorder, | 708 GrowableArray<BlockEntryInstr*>* preorder, |
| 708 GrowableArray<BlockEntryInstr*>* postorder, | 709 GrowableArray<BlockEntryInstr*>* postorder, |
| 709 GrowableArray<intptr_t>* parent, | 710 GrowableArray<intptr_t>* parent, |
| 710 GrowableArray<BitVector*>* assigned_vars, | 711 GrowableArray<BitVector*>* assigned_vars, |
| 711 intptr_t variable_count, | 712 intptr_t variable_count, |
| 712 intptr_t fixed_parameter_count) { | 713 intptr_t fixed_parameter_count) { |
| 713 // We only visit this block once, first of all blocks. | 714 // If this block has a predecessor (i.e., is not the graph entry) we can |
| 714 ASSERT(!IsMarked(this, preorder)); | 715 // assume the preorder array is non-empty. |
| 715 ASSERT(current_block == NULL); | 716 ASSERT((predecessor == NULL) || !preorder->is_empty()); |
| 716 ASSERT(preorder->is_empty()); | |
| 717 ASSERT(postorder->is_empty()); | |
| 718 ASSERT(parent->is_empty()); | |
| 719 | |
| 720 // This node has no parent, indicated by -1. The preorder number is 0. | |
| 721 parent->Add(-1); | |
| 722 set_preorder_number(0); | |
| 723 preorder->Add(this); | |
| 724 BitVector* vars = | |
| 725 (variable_count == 0) ? NULL : new BitVector(variable_count); | |
| 726 assigned_vars->Add(vars); | |
| 727 | |
| 728 // The graph entry consists of only one instruction. | |
| 729 set_last_instruction(this); | |
| 730 | |
| 731 // Iteratively traverse all successors. In the unoptimized code, we will | |
| 732 // enter the function at the first successor in reverse postorder, so we | |
| 733 // must visit the normal entry last. | |
| 734 for (intptr_t i = catch_entries_.length() - 1; i >= 0; --i) { | |
| 735 catch_entries_[i]->DiscoverBlocks(this, preorder, postorder, | |
| 736 parent, assigned_vars, | |
| 737 variable_count, fixed_parameter_count); | |
| 738 } | |
| 739 normal_entry_->DiscoverBlocks(this, preorder, postorder, | |
| 740 parent, assigned_vars, | |
| 741 variable_count, fixed_parameter_count); | |
| 742 | |
| 743 // Assign postorder number. | |
| 744 set_postorder_number(postorder->length()); | |
| 745 postorder->Add(this); | |
| 746 } | |
| 747 | |
| 748 | |
| 749 // Base class implementation used for JoinEntry and TargetEntry. | |
| 750 void BlockEntryInstr::DiscoverBlocks( | |
| 751 BlockEntryInstr* current_block, | |
| 752 GrowableArray<BlockEntryInstr*>* preorder, | |
| 753 GrowableArray<BlockEntryInstr*>* postorder, | |
| 754 GrowableArray<intptr_t>* parent, | |
| 755 GrowableArray<BitVector*>* assigned_vars, | |
| 756 intptr_t variable_count, | |
| 757 intptr_t fixed_parameter_count) { | |
| 758 // We have already visited the graph entry, so we can assume current_block | |
| 759 // is non-null and preorder array is non-empty. | |
| 760 ASSERT(current_block != NULL); | |
| 761 ASSERT(!preorder->is_empty()); | |
| 762 // Blocks with a single predecessor cannot have been reached before. | 717 // Blocks with a single predecessor cannot have been reached before. |
| 763 ASSERT(!IsTargetEntry() || !IsMarked(this, preorder)); | 718 ASSERT(IsJoinEntry() || !IsMarked(this, preorder)); |
| 764 | 719 |
| 765 // 1. If the block has already been reached, add current_block as a | 720 // 1. If the block has already been reached, add current_block as a |
| 766 // basic-block predecessor and we are done. | 721 // basic-block predecessor and we are done. |
| 767 if (IsMarked(this, preorder)) { | 722 if (IsMarked(this, preorder)) { |
| 768 AddPredecessor(current_block); | 723 ASSERT(predecessor != NULL); |
| 724 AddPredecessor(predecessor); |
| 769 return; | 725 return; |
| 770 } | 726 } |
| 771 | 727 |
| 772 // 2. Otherwise, clear the predecessors which might have been computed on | 728 // 2. Otherwise, clear the predecessors which might have been computed on |
| 773 // some earlier call to DiscoverBlocks and record this predecessor. For | 729 // some earlier call to DiscoverBlocks and record this predecessor. |
| 774 // joins save the original predecessors, if any, so we can garbage collect | |
| 775 // phi inputs from unreachable predecessors without recomputing SSA. | |
| 776 ClearPredecessors(); | 730 ClearPredecessors(); |
| 777 AddPredecessor(current_block); | 731 if (predecessor != NULL) AddPredecessor(predecessor); |
| 778 | 732 |
| 779 // 3. The current block is the spanning-tree parent. | 733 // 3. The predecessor is the spanning-tree parent. The graph entry has no |
| 780 parent->Add(current_block->preorder_number()); | 734 // parent, indicated by -1. |
| 735 intptr_t parent_number = |
| 736 (predecessor == NULL) ? -1 : predecessor->preorder_number(); |
| 737 parent->Add(parent_number); |
| 781 | 738 |
| 782 // 4. Assign preorder number and add the block entry to the list. | 739 // 4. Assign the preorder number and add the block entry to the list. |
| 783 // Allocate an empty set of assigned variables for the block. | 740 // Allocate an empty set of assigned variables for the block. |
| 784 set_preorder_number(preorder->length()); | 741 set_preorder_number(preorder->length()); |
| 785 preorder->Add(this); | 742 preorder->Add(this); |
| 786 BitVector* vars = | 743 BitVector* vars = |
| 787 (variable_count == 0) ? NULL : new BitVector(variable_count); | 744 (variable_count == 0) ? NULL : new BitVector(variable_count); |
| 788 assigned_vars->Add(vars); | 745 assigned_vars->Add(vars); |
| 789 // The preorder, parent, and assigned_vars arrays are all indexed by | 746 // The preorder, parent, and assigned_vars arrays are all indexed by |
| 790 // preorder block number, so they should stay in lockstep. | 747 // preorder block number, so they should stay in lockstep. |
| 791 ASSERT(preorder->length() == parent->length()); | 748 ASSERT(preorder->length() == parent->length()); |
| 792 ASSERT(preorder->length() == assigned_vars->length()); | 749 ASSERT(preorder->length() == assigned_vars->length()); |
| 793 | 750 |
| 794 // 5. Iterate straight-line successors until a branch instruction or | 751 // 5. Iterate straight-line successors to record assigned variables and |
| 795 // another basic block entry instruction, and visit that instruction. | 752 // find the last instruction in the block. The graph entry block consists |
| 796 ASSERT(next() != NULL); | 753 // of only the entry instruction, so that is the last instruction in the |
| 797 ASSERT(!next()->IsBlockEntry()); | 754 // block. |
| 798 Instruction* next_instr = next(); | 755 Instruction* last = this; |
| 799 while ((next_instr != NULL) && | 756 for (ForwardInstructionIterator it(this); !it.Done(); it.Advance()) { |
| 800 !next_instr->IsBlockEntry() && | 757 last = it.Current(); |
| 801 !next_instr->IsControl()) { | |
| 802 if (vars != NULL) { | 758 if (vars != NULL) { |
| 803 next_instr->RecordAssignedVars(vars, fixed_parameter_count); | 759 last->RecordAssignedVars(vars, fixed_parameter_count); |
| 804 } | 760 } |
| 805 set_last_instruction(next_instr); | |
| 806 GotoInstr* goto_instr = next_instr->AsGoto(); | |
| 807 next_instr = | |
| 808 (goto_instr != NULL) ? goto_instr->successor() : next_instr->next(); | |
| 809 } | 761 } |
| 810 if (next_instr != NULL) { | 762 set_last_instruction(last); |
| 811 next_instr->DiscoverBlocks(this, preorder, postorder, | 763 |
| 812 parent, assigned_vars, | 764 // Visit the block's successors in reverse so that they appear forwards |
| 813 variable_count, fixed_parameter_count); | 765 // the reverse postorder block ordering. |
| 766 for (intptr_t i = last->SuccessorCount() - 1; i >= 0; --i) { |
| 767 last->SuccessorAt(i)->DiscoverBlocks(this, preorder, postorder, |
| 768 parent, assigned_vars, |
| 769 variable_count, fixed_parameter_count); |
| 814 } | 770 } |
| 815 | 771 |
| 816 // 6. Assign postorder number and add the block entry to the list. | 772 // 6. Assign postorder number and add the block entry to the list. |
| 817 set_postorder_number(postorder->length()); | 773 set_postorder_number(postorder->length()); |
| 818 postorder->Add(this); | 774 postorder->Add(this); |
| 819 } | 775 } |
| 820 | 776 |
| 821 | 777 |
| 822 bool BlockEntryInstr::Dominates(BlockEntryInstr* other) const { | 778 bool BlockEntryInstr::Dominates(BlockEntryInstr* other) const { |
| 823 // TODO(fschneider): Make this faster by e.g. storing dominators for each | 779 // TODO(fschneider): Make this faster by e.g. storing dominators for each |
| 824 // block while computing the dominator tree. | 780 // block while computing the dominator tree. |
| 825 ASSERT(other != NULL); | 781 ASSERT(other != NULL); |
| 826 BlockEntryInstr* current = other; | 782 BlockEntryInstr* current = other; |
| 827 while (current != NULL && current != this) { | 783 while (current != NULL && current != this) { |
| 828 current = current->dominator(); | 784 current = current->dominator(); |
| 829 } | 785 } |
| 830 return current == this; | 786 return current == this; |
| 831 } | 787 } |
| 832 | 788 |
| 833 | 789 |
| 834 void ControlInstruction::DiscoverBlocks( | |
| 835 BlockEntryInstr* current_block, | |
| 836 GrowableArray<BlockEntryInstr*>* preorder, | |
| 837 GrowableArray<BlockEntryInstr*>* postorder, | |
| 838 GrowableArray<intptr_t>* parent, | |
| 839 GrowableArray<BitVector*>* assigned_vars, | |
| 840 intptr_t variable_count, | |
| 841 intptr_t fixed_parameter_count) { | |
| 842 current_block->set_last_instruction(this); | |
| 843 // Visit the false successor before the true successor so they appear in | |
| 844 // true/false order in reverse postorder used as the block ordering in the | |
| 845 // nonoptimizing compiler. | |
| 846 ASSERT(true_successor_ != NULL); | |
| 847 ASSERT(false_successor_ != NULL); | |
| 848 false_successor_->DiscoverBlocks(current_block, preorder, postorder, | |
| 849 parent, assigned_vars, | |
| 850 variable_count, fixed_parameter_count); | |
| 851 true_successor_->DiscoverBlocks(current_block, preorder, postorder, | |
| 852 parent, assigned_vars, | |
| 853 variable_count, fixed_parameter_count); | |
| 854 } | |
| 855 | |
| 856 | |
| 857 void JoinEntryInstr::InsertPhi(intptr_t var_index, intptr_t var_count) { | 790 void JoinEntryInstr::InsertPhi(intptr_t var_index, intptr_t var_count) { |
| 858 // Lazily initialize the array of phis. | 791 // Lazily initialize the array of phis. |
| 859 // Currently, phis are stored in a sparse array that holds the phi | 792 // Currently, phis are stored in a sparse array that holds the phi |
| 860 // for variable with index i at position i. | 793 // for variable with index i at position i. |
| 861 // TODO(fschneider): Store phis in a more compact way. | 794 // TODO(fschneider): Store phis in a more compact way. |
| 862 if (phis_ == NULL) { | 795 if (phis_ == NULL) { |
| 863 phis_ = new ZoneGrowableArray<PhiInstr*>(var_count); | 796 phis_ = new ZoneGrowableArray<PhiInstr*>(var_count); |
| 864 for (intptr_t i = 0; i < var_count; i++) { | 797 for (intptr_t i = 0; i < var_count; i++) { |
| 865 phis_->Add(NULL); | 798 phis_->Add(NULL); |
| 866 } | 799 } |
| (...skipping 1905 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2772 default: | 2705 default: |
| 2773 UNREACHABLE(); | 2706 UNREACHABLE(); |
| 2774 return -1; | 2707 return -1; |
| 2775 } | 2708 } |
| 2776 } | 2709 } |
| 2777 | 2710 |
| 2778 | 2711 |
| 2779 #undef __ | 2712 #undef __ |
| 2780 | 2713 |
| 2781 } // namespace dart | 2714 } // namespace dart |
| OLD | NEW |