Chromium Code Reviews| Index: runtime/vm/flow_graph.cc |
| diff --git a/runtime/vm/flow_graph.cc b/runtime/vm/flow_graph.cc |
| index 1964a81e64331ae42df08de622514a56ad02e065..14a49eb5281d3b8cd5ce8eb2263433cb4bbf0554 100644 |
| --- a/runtime/vm/flow_graph.cc |
| +++ b/runtime/vm/flow_graph.cc |
| @@ -149,22 +149,84 @@ Instruction* FlowGraph::AppendTo(Instruction* prev, |
| } |
| +// A block entry wrapper including an index of the next successor to be read. |
| +class PostorderBlockEntryWrapper { |
| + public: |
| + explicit PostorderBlockEntryWrapper(BlockEntryInstr* block) |
| + : block_(block), |
| + next_successor_ix_(block->last_instruction()->SuccessorCount() - 1) { } |
| + |
| + bool HasNextSuccessor() const { return next_successor_ix_ >= 0; } |
| + BlockEntryInstr* NextSuccessor() { |
| + return block_->last_instruction()->SuccessorAt(next_successor_ix_--); |
| + } |
| + |
| + BlockEntryInstr* block() const { return block_; } |
| + |
| + private: |
| + BlockEntryInstr* block_; |
| + intptr_t next_successor_ix_; |
| + |
| + DISALLOW_ALLOCATION(); |
| +}; |
| + |
| + |
| +// Iterative graph postorder traversal. DiscoverBlocks() must have been called |
| +// before this in order to set up BlockEntryInstr::last_instruction(). |
| +static void BuildPostorder(Isolate* isolate, |
| + BlockEntryInstr* graph_entry, |
| + GrowableArray<BlockEntryInstr*>* postorder, |
| + intptr_t num_blocks) { |
| + GrowableArray<PostorderBlockEntryWrapper> block_stack; |
| + block_stack.Add(PostorderBlockEntryWrapper(graph_entry)); |
| + |
| + BitVector visited(isolate, num_blocks); |
| + while (!block_stack.is_empty()) { |
| + PostorderBlockEntryWrapper &last = block_stack.Last(); |
| + BlockEntryInstr* block = last.block(); |
| + visited.Add(block->preorder_number()); |
| + if (last.HasNextSuccessor()) { |
| + // Process successors one-by-one. |
| + BlockEntryInstr* succ = last.NextSuccessor(); |
| + if (!visited.Contains(succ->preorder_number())) { |
| + block_stack.Add(PostorderBlockEntryWrapper(succ)); |
| + } |
| + } else { |
| + // All successors have been processed, pop the current block entry node |
| + // and add it to the postorder list. |
| + block_stack.RemoveLast(); |
| + block->set_postorder_number(postorder->length()); |
| + postorder->Add(block); |
| + } |
| + } |
| +} |
| + |
| + |
| void FlowGraph::DiscoverBlocks() { |
| // Initialize state. |
| preorder_.Clear(); |
| postorder_.Clear(); |
| reverse_postorder_.Clear(); |
| parent_.Clear(); |
| - // Perform a depth-first traversal of the graph to build preorder and |
| - // postorder block orders. |
| - graph_entry_->DiscoverBlocks(NULL, // Entry block predecessor. |
| + |
| + // Perform an iterative depth-first traversal of the graph to build preorder |
| + // block order, spanning-tree parents, and predecessors for each block entry. |
| + GrowableArray<BlockEntryEdge> block_stack; |
|
Vyacheslav Egorov (Google)
2014/10/07 12:43:17
I would really like to have this block_stack die a
jgruber1
2014/10/08 15:11:29
Done. I didn't realize the array memory sticks aro
|
| + block_stack.Add(BlockEntryEdge(NULL, graph_entry())); |
| + while (!block_stack.is_empty()) { |
| + BlockEntryEdge pair = block_stack.RemoveLast(); |
| + pair.child->DiscoverBlocks(pair.parent, |
| &preorder_, |
| - &postorder_, |
| &parent_, |
| - variable_count(), |
| - num_non_copied_params()); |
| + &block_stack); |
| + } |
| + |
| + // Create an array of blocks in postorder. |
| + const intptr_t block_count = preorder_.length(); |
|
Vyacheslav Egorov (Google)
2014/10/07 12:43:17
Maybe I am missing something but I think you can b
jgruber1
2014/10/08 15:11:29
Good point, done.
|
| + BuildPostorder(isolate(), graph_entry(), &postorder_, block_count); |
| + ASSERT(postorder_.length() == preorder_.length()); |
| + |
| // Create an array of blocks in reverse postorder. |
| - intptr_t block_count = postorder_.length(); |
| for (intptr_t i = 0; i < block_count; ++i) { |
| reverse_postorder_.Add(postorder_[block_count - i - 1]); |
| } |