summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Hewitt <davidmhewitt@gmail.com>2018-04-05 18:09:54 +0100
committerRico Tzschichholz <ricotz@ubuntu.com>2018-04-07 22:16:47 +0200
commite4119fc93c01608e975eecf0587ede3c0d9c596d (patch)
tree3a71660c7ee256a905eb669335d338eb681efa2a
parent94a9765a364db053ee8d4487e1d9f27ce76f9737 (diff)
downloadvala-e4119fc93c01608e975eecf0587ede3c0d9c596d.tar.gz
analyzer: Break cyclic references of BasicBlock
https://bugzilla.gnome.org/show_bug.cgi?id=794979
-rw-r--r--vala/valabasicblock.vala14
-rw-r--r--vala/valaflowanalyzer.vala44
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));
}
}