diff options
author | David Hewitt <davidmhewitt@gmail.com> | 2018-04-05 18:09:54 +0100 |
---|---|---|
committer | Rico Tzschichholz <ricotz@ubuntu.com> | 2018-04-07 22:16:47 +0200 |
commit | e4119fc93c01608e975eecf0587ede3c0d9c596d (patch) | |
tree | 3a71660c7ee256a905eb669335d338eb681efa2a | |
parent | 94a9765a364db053ee8d4487e1d9f27ce76f9737 (diff) | |
download | vala-e4119fc93c01608e975eecf0587ede3c0d9c596d.tar.gz |
analyzer: Break cyclic references of BasicBlock
https://bugzilla.gnome.org/show_bug.cgi?id=794979
-rw-r--r-- | vala/valabasicblock.vala | 14 | ||||
-rw-r--r-- | vala/valaflowanalyzer.vala | 44 |
2 files changed, 41 insertions, 17 deletions
diff --git a/vala/valabasicblock.vala b/vala/valabasicblock.vala index f1c3ea810..759bb9ce0 100644 --- a/vala/valabasicblock.vala +++ b/vala/valabasicblock.vala @@ -31,12 +31,12 @@ public class Vala.BasicBlock { // control flow graph private List<weak BasicBlock> predecessors = new ArrayList<weak BasicBlock> (); - private List<BasicBlock> successors = new ArrayList<BasicBlock> (); + private List<weak BasicBlock> successors = new ArrayList<weak BasicBlock> (); // dominator tree - public BasicBlock parent { get; private set; } - List<BasicBlock> children = new ArrayList<BasicBlock> (); - Set<BasicBlock> df = new HashSet<BasicBlock> (); + public weak BasicBlock parent { get; private set; } + List<weak BasicBlock> children = new ArrayList<weak BasicBlock> (); + Set<weak BasicBlock> df = new HashSet<weak BasicBlock> (); Set<PhiFunction> phi_functions = new HashSet<PhiFunction> (); @@ -73,7 +73,7 @@ public class Vala.BasicBlock { return predecessors; } - public List<BasicBlock> get_successors () { + public List<weak BasicBlock> get_successors () { return successors; } @@ -82,7 +82,7 @@ public class Vala.BasicBlock { block.parent = this; } - public List<BasicBlock> get_children () { + public List<weak BasicBlock> get_children () { return children; } @@ -90,7 +90,7 @@ public class Vala.BasicBlock { df.add (block); } - public Set<BasicBlock> get_dominator_frontier () { + public Set<weak BasicBlock> get_dominator_frontier () { return df; } diff --git a/vala/valaflowanalyzer.vala b/vala/valaflowanalyzer.vala index 7f362783e..ff7c03edc 100644 --- a/vala/valaflowanalyzer.vala +++ b/vala/valaflowanalyzer.vala @@ -89,6 +89,7 @@ public class Vala.FlowAnalyzer : CodeVisitor { private BasicBlock current_block; private bool unreachable_reported; private List<JumpTarget> jump_stack = new ArrayList<JumpTarget> (); + private Set<BasicBlock> all_basic_blocks; // check_variables Map<Symbol, List<Variable>> var_map; @@ -105,6 +106,7 @@ public class Vala.FlowAnalyzer : CodeVisitor { */ public void analyze (CodeContext context) { this.context = context; + all_basic_blocks = new HashSet<BasicBlock> (); /* we're only interested in non-pkg source files */ var source_files = context.get_source_files (); @@ -114,6 +116,7 @@ public class Vala.FlowAnalyzer : CodeVisitor { } } + all_basic_blocks = null; this.context = null; } @@ -194,8 +197,11 @@ public class Vala.FlowAnalyzer : CodeVisitor { } m.entry_block = new BasicBlock.entry (); + all_basic_blocks.add (m.entry_block); m.return_block = new BasicBlock (); + all_basic_blocks.add (m.return_block); m.exit_block = new BasicBlock.exit (); + all_basic_blocks.add (m.exit_block); m.return_block.connect (m.exit_block); @@ -211,6 +217,8 @@ public class Vala.FlowAnalyzer : CodeVisitor { } current_block = new BasicBlock (); + all_basic_blocks.add (current_block); + m.entry_block.connect (current_block); current_block.add_node (m); @@ -256,7 +264,7 @@ public class Vala.FlowAnalyzer : CodeVisitor { return; } current.postorder_visited = true; - foreach (BasicBlock succ in current.get_successors ()) { + foreach (weak BasicBlock succ in current.get_successors ()) { depth_first_traverse (succ, list); } current.postorder_number = list.size; @@ -279,7 +287,7 @@ public class Vala.FlowAnalyzer : CodeVisitor { // new immediate dominator BasicBlock new_idom = null; bool first = true; - foreach (BasicBlock pred in block.get_predecessors ()) { + foreach (weak BasicBlock pred in block.get_predecessors ()) { if (idoms[pred.postorder_number] != null) { if (first) { new_idom = pred; @@ -322,15 +330,15 @@ public class Vala.FlowAnalyzer : CodeVisitor { for (int i = block_list.size - 1; i >= 0; i--) { var block = block_list[i]; - foreach (BasicBlock succ in block.get_successors ()) { + foreach (weak BasicBlock succ in block.get_successors ()) { // if idom(succ) != block if (succ.parent != block) { block.add_dominator_frontier (succ); } } - foreach (BasicBlock child in block.get_children ()) { - foreach (BasicBlock child_frontier in child.get_dominator_frontier ()) { + foreach (weak BasicBlock child in block.get_children ()) { + foreach (weak BasicBlock child_frontier in child.get_dominator_frontier ()) { // if idom(child_frontier) != block if (child_frontier.parent != block) { block.add_dominator_frontier (child_frontier); @@ -475,9 +483,9 @@ public class Vala.FlowAnalyzer : CodeVisitor { } } - foreach (BasicBlock succ in block.get_successors ()) { + foreach (weak BasicBlock succ in block.get_successors ()) { int j = 0; - foreach (BasicBlock pred in succ.get_predecessors ()) { + foreach (weak BasicBlock pred in succ.get_predecessors ()) { if (pred == block) { break; } @@ -492,7 +500,7 @@ public class Vala.FlowAnalyzer : CodeVisitor { } } - foreach (BasicBlock child in block.get_children ()) { + foreach (weak BasicBlock child in block.get_children ()) { check_block_variables (child); } @@ -620,6 +628,7 @@ public class Vala.FlowAnalyzer : CodeVisitor { mark_unreachable (); } else { current_block = new BasicBlock (); + all_basic_blocks.add (current_block); last_block.connect (current_block); } stmt.true_statement.accept (this); @@ -630,6 +639,7 @@ public class Vala.FlowAnalyzer : CodeVisitor { mark_unreachable (); } else { current_block = new BasicBlock (); + all_basic_blocks.add (current_block); last_block.connect (current_block); } if (stmt.false_statement != null) { @@ -641,6 +651,7 @@ public class Vala.FlowAnalyzer : CodeVisitor { // reachable? if (last_true_block != null || last_false_block != null) { current_block = new BasicBlock (); + all_basic_blocks.add (current_block); if (last_true_block != null) { last_true_block.connect (current_block); } @@ -656,6 +667,7 @@ public class Vala.FlowAnalyzer : CodeVisitor { } var after_switch_block = new BasicBlock (); + all_basic_blocks.add (after_switch_block); jump_stack.add (new JumpTarget.break_target (after_switch_block)); // condition @@ -668,6 +680,7 @@ public class Vala.FlowAnalyzer : CodeVisitor { foreach (SwitchSection section in stmt.get_sections ()) { current_block = new BasicBlock (); + all_basic_blocks.add (current_block); condition_block.connect (current_block); foreach (Statement section_stmt in section.get_statements ()) { section_stmt.accept (this); @@ -709,8 +722,10 @@ public class Vala.FlowAnalyzer : CodeVisitor { } var loop_block = new BasicBlock (); + all_basic_blocks.add (loop_block); jump_stack.add (new JumpTarget.continue_target (loop_block)); var after_loop_block = new BasicBlock (); + all_basic_blocks.add (after_loop_block); jump_stack.add (new JumpTarget.break_target (after_loop_block)); // loop block @@ -748,8 +763,10 @@ public class Vala.FlowAnalyzer : CodeVisitor { handle_errors (stmt.collection); var loop_block = new BasicBlock (); + all_basic_blocks.add (loop_block); jump_stack.add (new JumpTarget.continue_target (loop_block)); var after_loop_block = new BasicBlock (); + all_basic_blocks.add (after_loop_block); jump_stack.add (new JumpTarget.break_target (after_loop_block)); // loop block @@ -893,6 +910,7 @@ public class Vala.FlowAnalyzer : CodeVisitor { // normal control flow if (!always_fail) { current_block = new BasicBlock (); + all_basic_blocks.add (current_block); last_block.connect (current_block); } } @@ -922,14 +940,17 @@ public class Vala.FlowAnalyzer : CodeVisitor { var before_try_block = current_block; var after_try_block = new BasicBlock (); + all_basic_blocks.add (after_try_block); BasicBlock finally_block = null; if (stmt.finally_body != null) { finally_block = new BasicBlock (); + all_basic_blocks.add (finally_block); current_block = finally_block; // trap all forbidden jumps var invalid_block = new BasicBlock (); + all_basic_blocks.add (invalid_block); jump_stack.add (new JumpTarget.any_target (invalid_block)); stmt.finally_body.accept (this); @@ -950,11 +971,14 @@ public class Vala.FlowAnalyzer : CodeVisitor { var catch_clauses = stmt.get_catch_clauses (); for (int i = catch_clauses.size - 1; i >= 0; i--) { var catch_clause = catch_clauses[i]; + var error_block = new BasicBlock (); + all_basic_blocks.add (error_block); + if (catch_clause.error_type != null) { var error_type = (ErrorType) catch_clause.error_type; - jump_stack.add (new JumpTarget.error_target (new BasicBlock (), catch_clause, catch_clause.error_type.data_type as ErrorDomain, error_type.error_code, null)); + jump_stack.add (new JumpTarget.error_target (error_block, catch_clause, catch_clause.error_type.data_type as ErrorDomain, error_type.error_code, null)); } else { - jump_stack.add (new JumpTarget.error_target (new BasicBlock (), catch_clause, null, null, null)); + jump_stack.add (new JumpTarget.error_target (error_block, catch_clause, null, null, null)); } } |