From: David Hewitt Date: Thu, 5 Apr 2018 17:09:54 +0000 (+0100) Subject: analyzer: Break cyclic references of BasicBlock X-Git-Tag: 0.41.90~195 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e4119fc93c01608e975eecf0587ede3c0d9c596d;p=thirdparty%2Fvala.git analyzer: Break cyclic references of BasicBlock https://bugzilla.gnome.org/show_bug.cgi?id=794979 --- 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 predecessors = new ArrayList (); - private List successors = new ArrayList (); + private List successors = new ArrayList (); // dominator tree - public BasicBlock parent { get; private set; } - List children = new ArrayList (); - Set df = new HashSet (); + public weak BasicBlock parent { get; private set; } + List children = new ArrayList (); + Set df = new HashSet (); Set phi_functions = new HashSet (); @@ -73,7 +73,7 @@ public class Vala.BasicBlock { return predecessors; } - public List get_successors () { + public List get_successors () { return successors; } @@ -82,7 +82,7 @@ public class Vala.BasicBlock { block.parent = this; } - public List get_children () { + public List get_children () { return children; } @@ -90,7 +90,7 @@ public class Vala.BasicBlock { df.add (block); } - public Set get_dominator_frontier () { + public Set 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 jump_stack = new ArrayList (); + private Set all_basic_blocks; // check_variables Map> var_map; @@ -105,6 +106,7 @@ public class Vala.FlowAnalyzer : CodeVisitor { */ public void analyze (CodeContext context) { this.context = context; + all_basic_blocks = new HashSet (); /* 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)); } }