blob: 658a9b1c4671d07c954545fbc0fcfb7a600e6ad5 [file] [log] [blame]
buzbee311ca162013-02-28 15:56:43 -08001/*
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
Brian Carlstromfc0e3212013-07-17 14:40:12 -070017#ifndef ART_COMPILER_DEX_DATAFLOW_ITERATOR_H_
18#define ART_COMPILER_DEX_DATAFLOW_ITERATOR_H_
buzbee311ca162013-02-28 15:56:43 -080019
20#include "compiler_ir.h"
21#include "mir_graph.h"
22
23namespace art {
24
buzbee0665fe02013-03-21 12:32:21 -070025 /*
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,
buzbee56c71782013-09-05 17:13:19 -070030 * necessitating another pass over the list. If this behavior is required, use the
31 * "Repeating" variant. For the repeating variant, the caller must tell the iterator
32 * whether a change has been made that necessitates another pass. Note that calling Next(true)
33 * does not affect the iteration order or short-circuit the current pass - it simply tells
34 * the iterator that once it has finished walking through the block list it should reset and
35 * do another full pass through the list.
buzbee0665fe02013-03-21 12:32:21 -070036 */
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -080037 /**
38 * @class DataflowIterator
39 * @brief The main iterator class, all other iterators derive of this one to define an iteration order.
40 */
buzbee311ca162013-02-28 15:56:43 -080041 class DataflowIterator {
42 public:
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070043 virtual ~DataflowIterator() {}
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -080044
45 /**
46 * @brief How many times have we repeated the iterator across the BasicBlocks?
47 * @return the number of iteration repetitions.
48 */
buzbee1da1e2f2013-11-15 13:37:01 -080049 int32_t GetRepeatCount() { return repeats_; }
buzbee311ca162013-02-28 15:56:43 -080050
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -080051 /**
52 * @brief Has the user of the iterator reported a change yet?
53 * @details Does not mean there was or not a change, it is only whether the user passed a true to the Next function call.
54 * @return whether the user of the iterator reported a change yet.
55 */
56 int32_t GetChanged() { return changed_; }
57
58 /**
59 * @brief Get the next BasicBlock depending on iteration order.
60 * @param had_change did the user of the iteration change the previous BasicBlock.
61 * @return the next BasicBlock following the iteration order, 0 if finished.
62 */
63 virtual BasicBlock* Next(bool had_change = false) = 0;
64
buzbee0665fe02013-03-21 12:32:21 -070065 protected:
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -080066 /**
67 * @param mir_graph the MIRGraph we are interested in.
68 * @param start_idx the first index we want to iterate across.
69 * @param end_idx the last index we want to iterate (not included).
70 */
buzbee0d829482013-10-11 15:24:55 -070071 DataflowIterator(MIRGraph* mir_graph, int32_t start_idx, int32_t end_idx)
buzbee0665fe02013-03-21 12:32:21 -070072 : mir_graph_(mir_graph),
buzbee0665fe02013-03-21 12:32:21 -070073 start_idx_(start_idx),
74 end_idx_(end_idx),
Ian Rogerse7a5b7d2013-04-18 20:09:02 -070075 block_id_list_(NULL),
76 idx_(0),
buzbee1da1e2f2013-11-15 13:37:01 -080077 repeats_(0),
Ian Rogerse7a5b7d2013-04-18 20:09:02 -070078 changed_(false) {}
buzbee0665fe02013-03-21 12:32:21 -070079
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -080080 /**
81 * @brief Get the next BasicBlock iterating forward.
82 * @return the next BasicBlock iterating forward.
83 */
buzbee56c71782013-09-05 17:13:19 -070084 virtual BasicBlock* ForwardSingleNext() ALWAYS_INLINE;
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -080085
86 /**
87 * @brief Get the next BasicBlock iterating backward.
88 * @return the next BasicBlock iterating backward.
89 */
buzbee56c71782013-09-05 17:13:19 -070090 virtual BasicBlock* ReverseSingleNext() ALWAYS_INLINE;
buzbee0665fe02013-03-21 12:32:21 -070091
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -080092 /**
93 * @brief Get the next BasicBlock iterating forward, restart if a BasicBlock was reported changed during the last iteration.
94 * @return the next BasicBlock iterating forward, with chance of repeating the iteration.
95 */
96 virtual BasicBlock* ForwardRepeatNext() ALWAYS_INLINE;
buzbee1da1e2f2013-11-15 13:37:01 -080097
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -080098 /**
99 * @brief Get the next BasicBlock iterating backward, restart if a BasicBlock was reported changed during the last iteration.
100 * @return the next BasicBlock iterating backward, with chance of repeating the iteration.
101 */
102 virtual BasicBlock* ReverseRepeatNext() ALWAYS_INLINE;
103
104 MIRGraph* const mir_graph_; /**< @brief the MIRGraph */
105 const int32_t start_idx_; /**< @brief the start index for the iteration */
106 const int32_t end_idx_; /**< @brief the last index for the iteration */
107 GrowableArray<BasicBlockId>* block_id_list_; /**< @brief the list of BasicBlocks we want to iterate on */
108 int32_t idx_; /**< @brief Current index for the iterator */
109 int32_t repeats_; /**< @brief Number of repeats over the iteration */
110 bool changed_; /**< @brief Has something changed during the current iteration? */
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700111 }; // DataflowIterator
buzbee0665fe02013-03-21 12:32:21 -0700112
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -0800113 /**
114 * @class PreOrderDfsIterator
115 * @brief Used to perform a Pre-order Depth-First-Search Iteration of a MIRGraph.
116 */
buzbee0665fe02013-03-21 12:32:21 -0700117 class PreOrderDfsIterator : public DataflowIterator {
118 public:
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -0800119 /**
120 * @brief The constructor, using all of the reachable blocks of the MIRGraph.
121 * @param mir_graph The MIRGraph considered.
122 */
buzbee56c71782013-09-05 17:13:19 -0700123 explicit PreOrderDfsIterator(MIRGraph* mir_graph)
124 : DataflowIterator(mir_graph, 0, mir_graph->GetNumReachableBlocks()) {
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -0800125 // Extra setup for the PreOrderDfsIterator.
buzbee0665fe02013-03-21 12:32:21 -0700126 idx_ = start_idx_;
127 block_id_list_ = mir_graph->GetDfsOrder();
128 }
buzbee56c71782013-09-05 17:13:19 -0700129
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -0800130 /**
131 * @brief Get the next BasicBlock depending on iteration order.
132 * @param had_change did the user of the iteration change the previous BasicBlock.
133 * @return the next BasicBlock following the iteration order, 0 if finished.
134 */
135 virtual BasicBlock* Next(bool had_change = false) {
136 // Update changed: if had_changed is true, we remember it for the whole iteration.
137 changed_ |= had_change;
138
buzbee56c71782013-09-05 17:13:19 -0700139 return ForwardSingleNext();
140 }
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800141
142 /**
143 * @brief Redefine the new operator to use the arena
144 * @param size actually unused, we use our own class size
145 * @param arena the arena to perform the actual allocation
146 * @return the pointer to the newly allocated object
147 */
148 static void* operator new(size_t size, ArenaAllocator* arena) {
149 return arena->Alloc(sizeof(PreOrderDfsIterator), ArenaAllocator::kAllocGrowableBitMap);
150 }
151
152 /**
153 * @brief Redefine delete to not actually delete anything since we are using the arena
154 */
155 static void operator delete(void* p) {}
buzbee0665fe02013-03-21 12:32:21 -0700156 };
157
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -0800158 /**
159 * @class RepeatingPreOrderDfsIterator
160 * @brief Used to perform a Repeating Pre-order Depth-First-Search Iteration of a MIRGraph.
161 * @details If there is a change during an iteration, the iteration starts over at the end of the iteration.
162 */
buzbee56c71782013-09-05 17:13:19 -0700163 class RepeatingPreOrderDfsIterator : public DataflowIterator {
buzbee0665fe02013-03-21 12:32:21 -0700164 public:
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -0800165 /**
166 * @brief The constructor, using all of the reachable blocks of the MIRGraph.
167 * @param mir_graph The MIRGraph considered.
168 */
buzbee56c71782013-09-05 17:13:19 -0700169 explicit RepeatingPreOrderDfsIterator(MIRGraph* mir_graph)
170 : DataflowIterator(mir_graph, 0, mir_graph->GetNumReachableBlocks()) {
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -0800171 // Extra setup for the RepeatingPreOrderDfsIterator.
buzbee56c71782013-09-05 17:13:19 -0700172 idx_ = start_idx_;
173 block_id_list_ = mir_graph->GetDfsOrder();
174 }
175
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -0800176 /**
177 * @brief Get the next BasicBlock depending on iteration order.
178 * @param had_change did the user of the iteration change the previous BasicBlock.
179 * @return the next BasicBlock following the iteration order, 0 if finished.
180 */
181 virtual BasicBlock* Next(bool had_change = false) {
182 // Update changed: if had_changed is true, we remember it for the whole iteration.
183 changed_ |= had_change;
184
185 return ForwardRepeatNext();
buzbee56c71782013-09-05 17:13:19 -0700186 }
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800187
188 /**
189 * @brief Redefine the new operator to use the arena
190 * @param size actually unused, we use our own class size
191 * @param arena the arena to perform the actual allocation
192 * @return the pointer to the newly allocated object
193 */
194 static void* operator new(size_t size, ArenaAllocator* arena) {
195 return arena->Alloc(sizeof(RepeatingPreOrderDfsIterator), ArenaAllocator::kAllocGrowableBitMap);
196 }
197
198 /**
199 * @brief Redefine delete to not actually delete anything since we are using the arena
200 */
201 static void operator delete(void* p) {}
buzbee56c71782013-09-05 17:13:19 -0700202 };
203
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -0800204 /**
205 * @class RepeatingPostOrderDfsIterator
206 * @brief Used to perform a Repeating Post-order Depth-First-Search Iteration of a MIRGraph.
207 * @details If there is a change during an iteration, the iteration starts over at the end of the iteration.
208 */
buzbee56c71782013-09-05 17:13:19 -0700209 class RepeatingPostOrderDfsIterator : public DataflowIterator {
210 public:
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -0800211 /**
212 * @brief The constructor, using all of the reachable blocks of the MIRGraph.
213 * @param mir_graph The MIRGraph considered.
214 */
buzbee56c71782013-09-05 17:13:19 -0700215 explicit RepeatingPostOrderDfsIterator(MIRGraph* mir_graph)
216 : DataflowIterator(mir_graph, 0, mir_graph->GetNumReachableBlocks()) {
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -0800217 // Extra setup for the RepeatingPostOrderDfsIterator.
buzbee0665fe02013-03-21 12:32:21 -0700218 idx_ = start_idx_;
219 block_id_list_ = mir_graph->GetDfsPostOrder();
220 }
buzbee56c71782013-09-05 17:13:19 -0700221
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -0800222 /**
223 * @brief Get the next BasicBlock depending on iteration order.
224 * @param had_change did the user of the iteration change the previous BasicBlock.
225 * @return the next BasicBlock following the iteration order, 0 if finished.
226 */
227 virtual BasicBlock* Next(bool had_change = false) {
228 // Update changed: if had_changed is true, we remember it for the whole iteration.
229 changed_ |= had_change;
230
231 return ForwardRepeatNext();
buzbee56c71782013-09-05 17:13:19 -0700232 }
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800233
234 /**
235 * @brief Redefine the new operator to use the arena
236 * @param size actually unused, we use our own class size
237 * @param arena the arena to perform the actual allocation
238 * @return the pointer to the newly allocated object
239 */
240 static void* operator new(size_t size, ArenaAllocator* arena) {
241 return arena->Alloc(sizeof(RepeatingPostOrderDfsIterator), ArenaAllocator::kAllocGrowableBitMap);
242 }
243
244 /**
245 * @brief Redefine delete to not actually delete anything since we are using the arena
246 */
247 static void operator delete(void* p) {}
buzbee0665fe02013-03-21 12:32:21 -0700248 };
249
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -0800250 /**
251 * @class ReversePostOrderDfsIterator
252 * @brief Used to perform a Reverse Post-order Depth-First-Search Iteration of a MIRGraph.
253 */
buzbee0665fe02013-03-21 12:32:21 -0700254 class ReversePostOrderDfsIterator : public DataflowIterator {
255 public:
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -0800256 /**
257 * @brief The constructor, using all of the reachable blocks of the MIRGraph.
258 * @param mir_graph The MIRGraph considered.
259 */
buzbee56c71782013-09-05 17:13:19 -0700260 explicit ReversePostOrderDfsIterator(MIRGraph* mir_graph)
261 : DataflowIterator(mir_graph, mir_graph->GetNumReachableBlocks() -1, 0) {
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -0800262 // Extra setup for the ReversePostOrderDfsIterator.
buzbee0665fe02013-03-21 12:32:21 -0700263 idx_ = start_idx_;
264 block_id_list_ = mir_graph->GetDfsPostOrder();
265 }
buzbee56c71782013-09-05 17:13:19 -0700266
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -0800267 /**
268 * @brief Get the next BasicBlock depending on iteration order.
269 * @param had_change did the user of the iteration change the previous BasicBlock.
270 * @return the next BasicBlock following the iteration order, 0 if finished.
271 */
272 virtual BasicBlock* Next(bool had_change = false) {
273 // Update changed: if had_changed is true, we remember it for the whole iteration.
274 changed_ |= had_change;
275
buzbee56c71782013-09-05 17:13:19 -0700276 return ReverseSingleNext();
277 }
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800278
279 /**
280 * @brief Redefine the new operator to use the arena
281 * @param size actually unused, we use our own class size
282 * @param arena the arena to perform the actual allocation
283 * @return the pointer to the newly allocated object
284 */
285 static void* operator new(size_t size, ArenaAllocator* arena) {
286 return arena->Alloc(sizeof(ReversePostOrderDfsIterator), ArenaAllocator::kAllocGrowableBitMap);
287 }
288
289 /**
290 * @brief Redefine delete to not actually delete anything since we are using the arena
291 */
292 static void operator delete(void* p) {}
buzbee56c71782013-09-05 17:13:19 -0700293 };
294
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -0800295 /**
296 * @class ReversePostOrderDfsIterator
297 * @brief Used to perform a Repeating Reverse Post-order Depth-First-Search Iteration of a MIRGraph.
298 * @details If there is a change during an iteration, the iteration starts over at the end of the iteration.
299 */
buzbee56c71782013-09-05 17:13:19 -0700300 class RepeatingReversePostOrderDfsIterator : public DataflowIterator {
301 public:
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -0800302 /**
303 * @brief The constructor, using all of the reachable blocks of the MIRGraph.
304 * @param mir_graph The MIRGraph considered.
305 */
buzbee56c71782013-09-05 17:13:19 -0700306 explicit RepeatingReversePostOrderDfsIterator(MIRGraph* mir_graph)
307 : DataflowIterator(mir_graph, mir_graph->GetNumReachableBlocks() -1, 0) {
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -0800308 // Extra setup for the RepeatingReversePostOrderDfsIterator
buzbee56c71782013-09-05 17:13:19 -0700309 idx_ = start_idx_;
310 block_id_list_ = mir_graph->GetDfsPostOrder();
311 }
312
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -0800313 /**
314 * @brief Get the next BasicBlock depending on iteration order.
315 * @param had_change did the user of the iteration change the previous BasicBlock.
316 * @return the next BasicBlock following the iteration order, 0 if finished.
317 */
318 virtual BasicBlock* Next(bool had_change = false) {
319 // Update changed: if had_changed is true, we remember it for the whole iteration.
320 changed_ |= had_change;
321
322 return ReverseRepeatNext();
buzbee56c71782013-09-05 17:13:19 -0700323 }
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800324
325 /**
326 * @brief Redefine the new operator to use the arena
327 * @param size actually unused, we use our own class size
328 * @param arena the arena to perform the actual allocation
329 * @return the pointer to the newly allocated object
330 */
331 static void* operator new(size_t size, ArenaAllocator* arena) {
332 return arena->Alloc(sizeof(RepeatingReversePostOrderDfsIterator), ArenaAllocator::kAllocGrowableBitMap);
333 }
334
335 /**
336 * @brief Redefine delete to not actually delete anything since we are using the arena
337 */
338 static void operator delete(void* p) {}
buzbee0665fe02013-03-21 12:32:21 -0700339 };
340
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -0800341 /**
342 * @class PostOrderDOMIterator
343 * @brief Used to perform a Post-order Domination Iteration of a MIRGraph.
344 */
buzbee0665fe02013-03-21 12:32:21 -0700345 class PostOrderDOMIterator : public DataflowIterator {
346 public:
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -0800347 /**
348 * @brief The constructor, using all of the reachable blocks of the MIRGraph.
349 * @param mir_graph The MIRGraph considered.
350 */
buzbee56c71782013-09-05 17:13:19 -0700351 explicit PostOrderDOMIterator(MIRGraph* mir_graph)
352 : DataflowIterator(mir_graph, 0, mir_graph->GetNumReachableBlocks()) {
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -0800353 // Extra setup for thePostOrderDOMIterator.
buzbee0665fe02013-03-21 12:32:21 -0700354 idx_ = start_idx_;
355 block_id_list_ = mir_graph->GetDomPostOrder();
356 }
buzbee56c71782013-09-05 17:13:19 -0700357
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -0800358 /**
359 * @brief Get the next BasicBlock depending on iteration order.
360 * @param had_change did the user of the iteration change the previous BasicBlock.
361 * @return the next BasicBlock following the iteration order, 0 if finished.
362 */
363 virtual BasicBlock* Next(bool had_change = false) {
364 // Update changed: if had_changed is true, we remember it for the whole iteration.
365 changed_ |= had_change;
366
buzbee56c71782013-09-05 17:13:19 -0700367 return ForwardSingleNext();
368 }
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800369
370 /**
371 * @brief Redefine the new operator to use the arena
372 * @param size actually unused, we use our own class size
373 * @param arena the arena to perform the actual allocation
374 * @return the pointer to the newly allocated object
375 */
376 static void* operator new(size_t size, ArenaAllocator* arena) {
377 return arena->Alloc(sizeof(PostOrderDOMIterator), ArenaAllocator::kAllocGrowableBitMap);
378 }
379
380 /**
381 * @brief Redefine delete to not actually delete anything since we are using the arena
382 */
383 static void operator delete(void* p) {}
buzbee0665fe02013-03-21 12:32:21 -0700384 };
385
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -0800386 /**
387 * @class AllNodesIterator
388 * @brief Used to perform an iteration on all the BasicBlocks a MIRGraph.
389 */
buzbee0665fe02013-03-21 12:32:21 -0700390 class AllNodesIterator : public DataflowIterator {
391 public:
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -0800392 /**
393 * @brief The constructor, using all of the reachable blocks of the MIRGraph.
394 * @param mir_graph The MIRGraph considered.
395 */
buzbee56c71782013-09-05 17:13:19 -0700396 explicit AllNodesIterator(MIRGraph* mir_graph)
397 : DataflowIterator(mir_graph, 0, 0) {
398 all_nodes_iterator_ = new
399 (mir_graph->GetArena()) GrowableArray<BasicBlock*>::Iterator(mir_graph->GetBlockList());
buzbee862a7602013-04-05 10:58:54 -0700400 }
401
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -0800402 /**
403 * @brief Resetting the iterator.
404 */
Ian Rogers8d3a1172013-06-04 01:13:28 -0700405 void Reset() {
buzbee862a7602013-04-05 10:58:54 -0700406 all_nodes_iterator_->Reset();
buzbee0665fe02013-03-21 12:32:21 -0700407 }
408
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -0800409 /**
410 * @brief Get the next BasicBlock depending on iteration order.
411 * @param had_change did the user of the iteration change the previous BasicBlock.
412 * @return the next BasicBlock following the iteration order, 0 if finished.
413 */
414 virtual BasicBlock* Next(bool had_change = false) ALWAYS_INLINE;
buzbee862a7602013-04-05 10:58:54 -0700415
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800416 /**
417 * @brief Redefine the new operator to use the arena
418 * @param size actually unused, we use our own class size
419 * @param arena the arena to perform the actual allocation
420 * @return the pointer to the newly allocated object
421 */
422 static void* operator new(size_t size, ArenaAllocator* arena) {
423 return arena->Alloc(sizeof(AllNodesIterator), ArenaAllocator::kAllocGrowableBitMap);
424 }
425
426 /**
427 * @brief Redefine delete to not actually delete anything since we are using the arena
428 */
429 static void operator delete(void* p) {}
430
buzbee862a7602013-04-05 10:58:54 -0700431 private:
Jean Christophe Beyler6e3cb662013-12-20 15:47:52 -0800432 GrowableArray<BasicBlock*>::Iterator* all_nodes_iterator_; /**< @brief The list of all the nodes */
buzbee0665fe02013-03-21 12:32:21 -0700433 };
434
buzbee311ca162013-02-28 15:56:43 -0800435} // namespace art
436
Brian Carlstromfc0e3212013-07-17 14:40:12 -0700437#endif // ART_COMPILER_DEX_DATAFLOW_ITERATOR_H_