From 4b6193baca0789045f2051cbf9c9beab4e51814f Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Mon, 8 May 2017 18:44:58 +0300 Subject: [PATCH] Fix bug in escape analysis. See #271 --- .../teavm/model/analysis/EscapeAnalysis.java | 8 ++--- .../test/ScalarReplacementTest.java | 5 +++ .../reachabilityByClasses.expected.txt | 31 +++++++++++++++++++ .../reachabilityByClasses.original.txt | 31 +++++++++++++++++++ 4 files changed, 71 insertions(+), 4 deletions(-) create mode 100644 core/src/test/resources/model/optimization/scalar-replacement/reachabilityByClasses.expected.txt create mode 100644 core/src/test/resources/model/optimization/scalar-replacement/reachabilityByClasses.original.txt diff --git a/core/src/main/java/org/teavm/model/analysis/EscapeAnalysis.java b/core/src/main/java/org/teavm/model/analysis/EscapeAnalysis.java index 8fa0bbc31..4869b2ad8 100644 --- a/core/src/main/java/org/teavm/model/analysis/EscapeAnalysis.java +++ b/core/src/main/java/org/teavm/model/analysis/EscapeAnalysis.java @@ -126,13 +126,13 @@ public class EscapeAnalysis { BitSet usedVars = getUsedVarsInBlock(livenessAnalyzer, block); for (Phi phi : block.getPhis()) { if (escapes(phi.getReceiver().getIndex())) { - queue.addLast(phi.getReceiver().getIndex()); + queue.addLast(definitionClasses[phi.getReceiver().getIndex()]); } for (Incoming incoming : phi.getIncomings()) { int var = incoming.getValue().getIndex(); - graphBuilder.addEdge(var, phi.getReceiver().getIndex()); + graphBuilder.addEdge(definitionClasses[var], definitionClasses[phi.getReceiver().getIndex()]); if (escapes(var) || !sharedIncomingVars.add(var) || usedVars.get(var)) { - queue.addLast(var); + queue.addLast(definitionClasses[var]); } } } @@ -143,7 +143,7 @@ public class EscapeAnalysis { while (!queue.isEmpty()) { int var = queue.removeFirst(); if (visited.add(var)) { - escapingVars[definitionClasses[var]] = true; + escapingVars[var] = true; for (int successor : graph.outgoingEdges(var)) { queue.addLast(successor); } diff --git a/core/src/test/java/org/teavm/model/optimization/test/ScalarReplacementTest.java b/core/src/test/java/org/teavm/model/optimization/test/ScalarReplacementTest.java index 4118bffc2..bbdd3fbc3 100644 --- a/core/src/test/java/org/teavm/model/optimization/test/ScalarReplacementTest.java +++ b/core/src/test/java/org/teavm/model/optimization/test/ScalarReplacementTest.java @@ -72,6 +72,11 @@ public class ScalarReplacementTest { doTest(); } + @Test + public void reachabilityByClasses() { + doTest(); + } + private void doTest() { String originalPath = PREFIX + name.getMethodName() + ".original.txt"; String expectedPath = PREFIX + name.getMethodName() + ".expected.txt"; diff --git a/core/src/test/resources/model/optimization/scalar-replacement/reachabilityByClasses.expected.txt b/core/src/test/resources/model/optimization/scalar-replacement/reachabilityByClasses.expected.txt new file mode 100644 index 000000000..fc4c693df --- /dev/null +++ b/core/src/test/resources/model/optimization/scalar-replacement/reachabilityByClasses.expected.txt @@ -0,0 +1,31 @@ +var @this as this + +$start + @cond := invokeStatic `Foo.cond()I` + if @cond == 0 then goto $then1 else goto $else1 +$then1 + @a1_then := new A + @foo1 := 23 + field A.foo @a1_then := @foo1 as I + goto $joint1 +$else1 + @a1_else := new A + @foo2 := 42 + field A.foo @a1_else := @foo2 as I + goto $joint1 + +$joint1 + @a1 := phi @a1_then from $then1, @a1_else from $else1 + @a2 := @a1 + if @cond == 0 then goto $then2 else goto $else2 +$then2 + @a3_then := new A + goto $joint2 +$else2 + @a3_else := @a2 + goto $joint2 + +$joint2 + @a3 := phi @a3_then from $then2, @a3_else from $else2 + invokeStatic `Foo.accept(LA;)V` @a3 + return \ No newline at end of file diff --git a/core/src/test/resources/model/optimization/scalar-replacement/reachabilityByClasses.original.txt b/core/src/test/resources/model/optimization/scalar-replacement/reachabilityByClasses.original.txt new file mode 100644 index 000000000..fc4c693df --- /dev/null +++ b/core/src/test/resources/model/optimization/scalar-replacement/reachabilityByClasses.original.txt @@ -0,0 +1,31 @@ +var @this as this + +$start + @cond := invokeStatic `Foo.cond()I` + if @cond == 0 then goto $then1 else goto $else1 +$then1 + @a1_then := new A + @foo1 := 23 + field A.foo @a1_then := @foo1 as I + goto $joint1 +$else1 + @a1_else := new A + @foo2 := 42 + field A.foo @a1_else := @foo2 as I + goto $joint1 + +$joint1 + @a1 := phi @a1_then from $then1, @a1_else from $else1 + @a2 := @a1 + if @cond == 0 then goto $then2 else goto $else2 +$then2 + @a3_then := new A + goto $joint2 +$else2 + @a3_else := @a2 + goto $joint2 + +$joint2 + @a3 := phi @a3_then from $then2, @a3_else from $else2 + invokeStatic `Foo.accept(LA;)V` @a3 + return \ No newline at end of file