mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
Add tests for phi updater
This commit is contained in:
parent
727c831467
commit
a5eb9ac800
|
@ -786,7 +786,7 @@ public class ListingParser {
|
|||
|
||||
private void parseCatch() throws IOException, ListingParseException {
|
||||
TryCatchBlock tryCatch = new TryCatchBlock();
|
||||
if (lexer.getToken() == ListingToken.IDENTIFIER) {
|
||||
if (lexer.getToken() == ListingToken.IDENTIFIER && !lexer.getTokenValue().equals("goto")) {
|
||||
tryCatch.setExceptionType((String) lexer.getTokenValue());
|
||||
lexer.nextToken();
|
||||
}
|
||||
|
|
|
@ -220,7 +220,6 @@ public class PhiUpdater {
|
|||
}
|
||||
|
||||
List<List<Incoming>> phiOutputs = ProgramUtils.getPhiOutputs(program);
|
||||
List<List<TryCatchJoint>> inputJoints = getInputJoints(program);
|
||||
|
||||
while (head > 0) {
|
||||
Task task = stack[--head];
|
||||
|
@ -244,29 +243,31 @@ public class PhiUpdater {
|
|||
for (Phi phi : currentBlock.getPhis()) {
|
||||
phi.setReceiver(define(phi.getReceiver()));
|
||||
}
|
||||
for (TryCatchJoint joint : inputJoints.get(index)) {
|
||||
joint.setReceiver(define(joint.getReceiver()));
|
||||
}
|
||||
|
||||
for (Instruction insn : currentBlock) {
|
||||
insn.acceptVisitor(consumer);
|
||||
}
|
||||
|
||||
for (Incoming output : phiOutputs.get(index)) {
|
||||
Variable var = output.getValue();
|
||||
output.setValue(use(var));
|
||||
}
|
||||
|
||||
for (TryCatchBlock tryCatch : currentBlock.getTryCatchBlocks()) {
|
||||
for (TryCatchJoint joint : tryCatch.getJoints()) {
|
||||
for (int i = 0; i < joint.getSourceVariables().size(); ++i) {
|
||||
joint.getSourceVariables().set(i, use(joint.getSourceVariables().get(i)));
|
||||
}
|
||||
joint.setReceiver(define(joint.getReceiver()));
|
||||
}
|
||||
}
|
||||
|
||||
IntSet catchSuccessors = new IntOpenHashSet();
|
||||
for (TryCatchBlock tryCatch : currentBlock.getTryCatchBlocks()) {
|
||||
catchSuccessors.add(tryCatch.getHandler().getIndex());
|
||||
}
|
||||
|
||||
for (Incoming output : phiOutputs.get(index)) {
|
||||
if (!catchSuccessors.contains(output.getPhi().getBasicBlock().getIndex())) {
|
||||
Variable var = output.getValue();
|
||||
output.setValue(use(var));
|
||||
}
|
||||
}
|
||||
|
||||
Variable[] regularVariableMap = variableMap;
|
||||
Variable[] catchVariableMap = variableMap.clone();
|
||||
|
||||
|
@ -296,7 +297,7 @@ public class PhiUpdater {
|
|||
|
||||
successors = cfg.outgoingEdges(index);
|
||||
for (int successor : successors) {
|
||||
variableMap = catchSuccessors.contains(successor) ? catchVariableMap : variableMap;
|
||||
variableMap = catchSuccessors.contains(successor) ? catchVariableMap : regularVariableMap;
|
||||
renameOutgoingPhis(successor);
|
||||
}
|
||||
}
|
||||
|
@ -393,6 +394,21 @@ public class PhiUpdater {
|
|||
BasicBlock[] worklist = new BasicBlock[program.basicBlockCount() * 4];
|
||||
int head = 0;
|
||||
worklist[head++] = currentBlock;
|
||||
|
||||
BasicBlock startBlock = currentBlock;
|
||||
List<TryCatchBlock> tryCatchBlocks = startBlock.getTryCatchBlocks();
|
||||
for (int i = 0; i < tryCatchBlocks.size(); i++) {
|
||||
TryCatchBlock tryCatch = tryCatchBlocks.get(i);
|
||||
TryCatchJoint joint = jointMap.computeIfAbsent(tryCatch, k -> new HashMap<>()).get(var);
|
||||
if (joint == null) {
|
||||
joint = new TryCatchJoint();
|
||||
joint.setReceiver(var);
|
||||
synthesizedJointsByBlock.get(startBlock.getIndex()).get(i).add(joint);
|
||||
jointMap.get(tryCatch).put(var, joint);
|
||||
worklist[head++] = tryCatch.getHandler();
|
||||
}
|
||||
}
|
||||
|
||||
while (head > 0) {
|
||||
BasicBlock block = worklist[--head];
|
||||
int[] frontiers = domFrontiers[block.getIndex()];
|
||||
|
@ -422,19 +438,6 @@ public class PhiUpdater {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<TryCatchBlock> tryCatchBlocks = block.getTryCatchBlocks();
|
||||
for (int i = 0; i < tryCatchBlocks.size(); i++) {
|
||||
TryCatchBlock tryCatch = tryCatchBlocks.get(i);
|
||||
TryCatchJoint joint = jointMap.computeIfAbsent(tryCatch, k -> new HashMap<>()).get(var);
|
||||
if (joint == null) {
|
||||
joint = new TryCatchJoint();
|
||||
joint.setReceiver(var);
|
||||
synthesizedJointsByBlock.get(block.getIndex()).get(i).add(joint);
|
||||
jointMap.get(tryCatch).put(var, joint);
|
||||
worklist[head++] = tryCatch.getHandler();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -501,21 +504,6 @@ public class PhiUpdater {
|
|||
return mappedVar;
|
||||
}
|
||||
|
||||
private static List<List<TryCatchJoint>> getInputJoints(Program program) {
|
||||
List<List<TryCatchJoint>> inputJoints = new ArrayList<>();
|
||||
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
||||
inputJoints.add(new ArrayList<>());
|
||||
}
|
||||
for (BasicBlock block : program.getBasicBlocks()) {
|
||||
for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) {
|
||||
for (TryCatchJoint joint : tryCatch.getJoints()) {
|
||||
inputJoints.get(tryCatch.getHandler().getIndex()).add(joint);
|
||||
}
|
||||
}
|
||||
}
|
||||
return inputJoints;
|
||||
}
|
||||
|
||||
private InstructionVisitor consumer = new InstructionVisitor() {
|
||||
@Override
|
||||
public void visit(EmptyInstruction insn) {
|
||||
|
@ -748,3 +736,4 @@ public class PhiUpdater {
|
|||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Copyright 2017 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.model.util.test;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TestName;
|
||||
import org.teavm.model.ListingParseUtils;
|
||||
import org.teavm.model.Program;
|
||||
import org.teavm.model.Variable;
|
||||
import org.teavm.model.text.ListingBuilder;
|
||||
import org.teavm.model.util.PhiUpdater;
|
||||
|
||||
public class PhiUpdaterTest {
|
||||
private static final String PREFIX = "model/util/phi-updater/";
|
||||
@Rule
|
||||
public TestName name = new TestName();
|
||||
|
||||
@Test
|
||||
public void exceptionPhi() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void exceptionPhiMultiple() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void exceptionPhiFromSinglePhi() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void existingExceptionPhi() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
private void doTest() {
|
||||
String originalPath = PREFIX + name.getMethodName() + ".original.txt";
|
||||
String expectedPath = PREFIX + name.getMethodName() + ".expected.txt";
|
||||
Program original = ListingParseUtils.parseFromResource(originalPath);
|
||||
Program expected = ListingParseUtils.parseFromResource(expectedPath);
|
||||
|
||||
new PhiUpdater().updatePhis(original, new Variable[0]);
|
||||
|
||||
String originalText = new ListingBuilder().buildListing(original, "");
|
||||
String expectedText = new ListingBuilder().buildListing(expected, "");
|
||||
Assert.assertEquals(expectedText, originalText);
|
||||
|
||||
new PhiUpdater().updatePhis(original, new Variable[0]);
|
||||
String repeatedText = new ListingBuilder().buildListing(original, "");
|
||||
Assert.assertEquals("Repeated update", originalText, repeatedText);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
$start
|
||||
@a := invokeStatic `Foo.bar()I`
|
||||
@a_1 := invokeStatic `Foo.baz()I`
|
||||
goto $end
|
||||
catch java.lang.RuntimeException goto $catch
|
||||
@a_2 := ephi @a, @a_1
|
||||
$catch
|
||||
@b := 1
|
||||
@a_4 := @a_2 + @b as int
|
||||
goto $end
|
||||
$end
|
||||
@a_3 := phi @a_1 from $start, @a_4 from $catch
|
||||
return @a_3
|
|
@ -0,0 +1,11 @@
|
|||
$start
|
||||
@a := invokeStatic `Foo.bar()I`
|
||||
@a := invokeStatic `Foo.baz()I`
|
||||
goto $end
|
||||
catch java.lang.RuntimeException goto $catch
|
||||
$catch
|
||||
@b := 1
|
||||
@a := @a + @b as int
|
||||
goto $end
|
||||
$end
|
||||
return @a
|
|
@ -0,0 +1,17 @@
|
|||
$start
|
||||
@cond := invokeStatic `Foo.cond()I`
|
||||
if @cond == 0 then goto $zero else goto $nonzero
|
||||
$zero
|
||||
@a := 23
|
||||
goto $joint
|
||||
$nonzero
|
||||
@a_1 := 42
|
||||
goto $joint
|
||||
$joint
|
||||
@a_2 := phi @a from $zero, @a_1 from $nonzero
|
||||
goto $exit
|
||||
catch goto $catch
|
||||
$catch
|
||||
goto $exit
|
||||
$exit
|
||||
return @a_2
|
|
@ -0,0 +1,16 @@
|
|||
$start
|
||||
@cond := invokeStatic `Foo.cond()I`
|
||||
if @cond == 0 then goto $zero else goto $nonzero
|
||||
$zero
|
||||
@a := 23
|
||||
goto $joint
|
||||
$nonzero
|
||||
@a := 42
|
||||
goto $joint
|
||||
$joint
|
||||
goto $exit
|
||||
catch goto $catch
|
||||
$catch
|
||||
goto $exit
|
||||
$exit
|
||||
return @a
|
|
@ -0,0 +1,19 @@
|
|||
$start
|
||||
@a := invokeStatic `Foo.bar()I`
|
||||
@a_1 := invokeStatic `Foo.baz()I`
|
||||
goto $second
|
||||
catch java.lang.RuntimeException goto $catch
|
||||
@a_2 := ephi @a, @a_1
|
||||
$second
|
||||
@a_3 := invokeStatic `Foo.boo()I`
|
||||
goto $end
|
||||
catch java.lang.RuntimeException goto $catch
|
||||
@a_4 := ephi @a_1, @a_3
|
||||
$catch
|
||||
@a_5 := phi @a_2 from $start, @a_4 from $second
|
||||
@b := 1
|
||||
@a_6 := @a_5 + @b as int
|
||||
goto $end
|
||||
$end
|
||||
@a_7 := phi @a_3 from $second, @a_6 from $catch
|
||||
return @a_7
|
|
@ -0,0 +1,15 @@
|
|||
$start
|
||||
@a := invokeStatic `Foo.bar()I`
|
||||
@a := invokeStatic `Foo.baz()I`
|
||||
goto $second
|
||||
catch java.lang.RuntimeException goto $catch
|
||||
$second
|
||||
@a := invokeStatic `Foo.boo()I`
|
||||
goto $end
|
||||
catch java.lang.RuntimeException goto $catch
|
||||
$catch
|
||||
@b := 1
|
||||
@a := @a + @b as int
|
||||
goto $end
|
||||
$end
|
||||
return @a
|
|
@ -0,0 +1,18 @@
|
|||
$start
|
||||
@a := invokeStatic `Foo.bar()I`
|
||||
@a_1 := invokeStatic `Foo.baz()I`
|
||||
goto $second
|
||||
catch goto $catch
|
||||
@a_2 := ephi @a, @a_1
|
||||
$second
|
||||
@a_3 := invokeStatic `Foo.bar2()I`
|
||||
@a_4 := invokeStatic `Foo.baz2()I`
|
||||
goto $end
|
||||
catch goto $catch
|
||||
@a_5 := ephi @a_1, @a_3, @a_4
|
||||
$catch
|
||||
@a_6 := phi @a_2 from $start, @a_5 from $second
|
||||
goto $end
|
||||
$end
|
||||
@a_7 := phi @a_4 from $second, @a_6 from $catch
|
||||
return @a_7
|
|
@ -0,0 +1,18 @@
|
|||
$start
|
||||
@a := invokeStatic `Foo.bar()I`
|
||||
@a_1 := invokeStatic `Foo.baz()I`
|
||||
goto $second
|
||||
catch goto $catch
|
||||
@a_2 := ephi @a, @a_1
|
||||
$second
|
||||
@a_3 := invokeStatic `Foo.bar2()I`
|
||||
@a_4 := invokeStatic `Foo.baz2()I`
|
||||
goto $end
|
||||
catch goto $catch
|
||||
@a_5 := ephi @a_1, @a_3, @a_4
|
||||
$catch
|
||||
@a_6 := phi @a_2 from $start, @a_5 from $second
|
||||
goto $end
|
||||
$end
|
||||
@a_7 := phi @a_4 from $second, @a_6 from $catch
|
||||
return @a_7
|
|
@ -34,7 +34,7 @@ interface TeaVMTestConfiguration {
|
|||
|
||||
@Override
|
||||
public void apply(TeaVM vm) {
|
||||
vm.setOptimizationLevel(TeaVMOptimizationLevel.SIMPLE);
|
||||
vm.setOptimizationLevel(TeaVMOptimizationLevel.FULL);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
Loading…
Reference in New Issue
Block a user