| Index: runtime/vm/flow_graph_compiler.cc
|
| diff --git a/runtime/vm/flow_graph_compiler.cc b/runtime/vm/flow_graph_compiler.cc
|
| index 3eb4a4d6e14b653b64521056fb7c409a88be9939..fbe348454530df913347d9f8616048f5d51574b0 100644
|
| --- a/runtime/vm/flow_graph_compiler.cc
|
| +++ b/runtime/vm/flow_graph_compiler.cc
|
| @@ -180,12 +180,15 @@ static bool IsEmptyBlock(BlockEntryInstr* block) {
|
| void FlowGraphCompiler::CompactBlock(BlockEntryInstr* block) {
|
| BlockInfo* block_info = block_info_[block->postorder_number()];
|
|
|
| + // Break out of cycles in the control flow graph.
|
| if (block_info->is_marked()) {
|
| return;
|
| }
|
| block_info->mark();
|
|
|
| if (IsEmptyBlock(block)) {
|
| + // For empty blocks, record a corresponding nonempty target as their
|
| + // jump label.
|
| BlockEntryInstr* target = block->next()->AsGoto()->successor();
|
| CompactBlock(target);
|
| block_info->set_jump_label(GetJumpLabel(target));
|
| @@ -194,7 +197,10 @@ void FlowGraphCompiler::CompactBlock(BlockEntryInstr* block) {
|
|
|
|
|
| void FlowGraphCompiler::CompactBlocks() {
|
| - Label* fallthrough_label = NULL;
|
| + // This algorithm does not garbage collect blocks in place, but merely
|
| + // records forwarding label information. In this way it avoids having to
|
| + // change join and target entries.
|
| + Label* nonempty_label = NULL;
|
| for (intptr_t i = block_order().length() - 1; i >= 1; --i) {
|
| BlockEntryInstr* block = block_order()[i];
|
|
|
| @@ -203,16 +209,19 @@ void FlowGraphCompiler::CompactBlocks() {
|
| CompactBlock(block);
|
| }
|
|
|
| + // For nonempty blocks, record the next nonempty block in the block
|
| + // order. Since no code is emitted for empty blocks, control flow is
|
| + // eligible to fall through to the next nonempty one.
|
| if (!WasCompacted(block)) {
|
| BlockInfo* block_info = block_info_[block->postorder_number()];
|
| - block_info->set_fallthrough_label(fallthrough_label);
|
| - fallthrough_label = GetJumpLabel(block);
|
| + block_info->set_next_nonempty_label(nonempty_label);
|
| + nonempty_label = GetJumpLabel(block);
|
| }
|
| }
|
|
|
| ASSERT(block_order()[0]->IsGraphEntry());
|
| BlockInfo* block_info = block_info_[block_order()[0]->postorder_number()];
|
| - block_info->set_fallthrough_label(fallthrough_label);
|
| + block_info->set_next_nonempty_label(nonempty_label);
|
| }
|
|
|
|
|
| @@ -289,8 +298,8 @@ bool FlowGraphCompiler::WasCompacted(
|
|
|
| bool FlowGraphCompiler::CanFallThroughTo(BlockEntryInstr* block_entry) const {
|
| const intptr_t current_index = current_block()->postorder_number();
|
| - Label* fallthrough_label = block_info_[current_index]->fallthrough_label();
|
| - return fallthrough_label == GetJumpLabel(block_entry);
|
| + Label* next_nonempty = block_info_[current_index]->next_nonempty_label();
|
| + return next_nonempty == GetJumpLabel(block_entry);
|
| }
|
|
|
|
|
|
|