• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2013 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef ART_COMPILER_DEX_DATAFLOW_ITERATOR_H_
18 #define ART_COMPILER_DEX_DATAFLOW_ITERATOR_H_
19 
20 #include "compiler_ir.h"
21 #include "mir_graph.h"
22 
23 namespace art {
24 
25   /*
26    * This class supports iterating over lists of basic blocks in various
27    * interesting orders.  Note that for efficiency, the visit orders have been pre-computed.
28    * The order itself will not change during the iteration.  However, for some uses,
29    * auxiliary data associated with the basic blocks may be changed during the iteration,
30    * necessitating another pass over the list.
31    *
32    * To support this usage, we have is_iterative_.  If false, the iteration is a one-shot
33    * pass through the pre-computed list using Next().  If true, the caller must tell the
34    * iterator whether a change has been made that necessitates another pass.  Use
35    * Next(had_change) for this.  The general idea is that the iterative_ use case means
36    * that the iterator will keep repeating the full basic block list until a complete pass
37    * is made through it with no changes.  Note that calling Next(true) does not affect
38    * the iteration order or short-curcuit the current pass - it simply tells the iterator
39    * that once it has finished walking through the block list it should reset and do another
40    * full pass through the list.
41    */
42   class DataflowIterator {
43     public:
~DataflowIterator()44       virtual ~DataflowIterator() {}
45 
46       // Return the next BasicBlock* to visit.
Next()47       BasicBlock* Next() {
48         DCHECK(!is_iterative_);
49         return NextBody(false);
50       }
51 
52       /*
53        * Return the next BasicBlock* to visit, and tell the iterator whether any change
54        * has occurred that requires another full pass over the block list.
55        */
Next(bool had_change)56       BasicBlock* Next(bool had_change) {
57         DCHECK(is_iterative_);
58         return NextBody(had_change);
59       }
60 
61     protected:
DataflowIterator(MIRGraph * mir_graph,bool is_iterative,int start_idx,int end_idx,bool reverse)62       DataflowIterator(MIRGraph* mir_graph, bool is_iterative, int start_idx, int end_idx,
63                        bool reverse)
64           : mir_graph_(mir_graph),
65             is_iterative_(is_iterative),
66             start_idx_(start_idx),
67             end_idx_(end_idx),
68             reverse_(reverse),
69             block_id_list_(NULL),
70             idx_(0),
71             changed_(false) {}
72 
73       virtual BasicBlock* NextBody(bool had_change) ALWAYS_INLINE;
74 
75       MIRGraph* const mir_graph_;
76       const bool is_iterative_;
77       const int start_idx_;
78       const int end_idx_;
79       const bool reverse_;
80       GrowableArray<int>* block_id_list_;
81       int idx_;
82       bool changed_;
83   };  // DataflowIterator
84 
85   class ReachableNodesIterator : public DataflowIterator {
86     public:
ReachableNodesIterator(MIRGraph * mir_graph,bool is_iterative)87       ReachableNodesIterator(MIRGraph* mir_graph, bool is_iterative)
88           : DataflowIterator(mir_graph, is_iterative, 0,
89                              mir_graph->GetNumReachableBlocks(), false) {
90         idx_ = start_idx_;
91         block_id_list_ = mir_graph->GetDfsOrder();
92       }
93   };
94 
95   class PreOrderDfsIterator : public DataflowIterator {
96     public:
PreOrderDfsIterator(MIRGraph * mir_graph,bool is_iterative)97       PreOrderDfsIterator(MIRGraph* mir_graph, bool is_iterative)
98           : DataflowIterator(mir_graph, is_iterative, 0,
99                              mir_graph->GetNumReachableBlocks(), false) {
100         idx_ = start_idx_;
101         block_id_list_ = mir_graph->GetDfsOrder();
102       }
103   };
104 
105   class PostOrderDfsIterator : public DataflowIterator {
106     public:
PostOrderDfsIterator(MIRGraph * mir_graph,bool is_iterative)107       PostOrderDfsIterator(MIRGraph* mir_graph, bool is_iterative)
108           : DataflowIterator(mir_graph, is_iterative, 0,
109                              mir_graph->GetNumReachableBlocks(), false) {
110         idx_ = start_idx_;
111         block_id_list_ = mir_graph->GetDfsPostOrder();
112       }
113   };
114 
115   class ReversePostOrderDfsIterator : public DataflowIterator {
116     public:
ReversePostOrderDfsIterator(MIRGraph * mir_graph,bool is_iterative)117       ReversePostOrderDfsIterator(MIRGraph* mir_graph, bool is_iterative)
118           : DataflowIterator(mir_graph, is_iterative,
119                              mir_graph->GetNumReachableBlocks() -1, 0, true) {
120         idx_ = start_idx_;
121         block_id_list_ = mir_graph->GetDfsPostOrder();
122       }
123   };
124 
125   class PostOrderDOMIterator : public DataflowIterator {
126     public:
PostOrderDOMIterator(MIRGraph * mir_graph,bool is_iterative)127       PostOrderDOMIterator(MIRGraph* mir_graph, bool is_iterative)
128           : DataflowIterator(mir_graph, is_iterative, 0,
129                              mir_graph->GetNumReachableBlocks(), false) {
130         idx_ = start_idx_;
131         block_id_list_ = mir_graph->GetDomPostOrder();
132       }
133   };
134 
135   class AllNodesIterator : public DataflowIterator {
136     public:
AllNodesIterator(MIRGraph * mir_graph,bool is_iterative)137       AllNodesIterator(MIRGraph* mir_graph, bool is_iterative)
138           : DataflowIterator(mir_graph, is_iterative, 0, 0, false) {
139         all_nodes_iterator_ =
140             new (mir_graph->GetArena()) GrowableArray<BasicBlock*>::Iterator(mir_graph->GetBlockList());
141       }
142 
Reset()143       void Reset() {
144         all_nodes_iterator_->Reset();
145       }
146 
147       BasicBlock* NextBody(bool had_change) ALWAYS_INLINE;
148 
149     private:
150       GrowableArray<BasicBlock*>::Iterator* all_nodes_iterator_;
151   };
152 
153 }  // namespace art
154 
155 #endif  // ART_COMPILER_DEX_DATAFLOW_ITERATOR_H_
156