Prevent PhiUpdater from placing e-phis with source variable equal to receiver

This commit is contained in:
Alexey Andreev 2016-12-03 13:46:02 +03:00
parent 10bb4ef3da
commit ad39024795
5 changed files with 91 additions and 46 deletions

View File

@ -152,14 +152,10 @@ class LoopInversionImpl {
}
private LoopWithExits getLoopWithExits(Map<Loop, LoopWithExits> cache, Loop loop) {
LoopWithExits result = cache.get(loop);
if (result == null) {
result = new LoopWithExits(loop.getHead(), loop.getParent() != null
return cache.computeIfAbsent(loop, k ->
new LoopWithExits(loop.getHead(), loop.getParent() != null
? getLoopWithExits(cache, loop.getParent())
: null);
cache.put(loop, result);
}
return result;
: null));
}
private void sortLoops(LoopWithExits loop, Set<LoopWithExits> visited, List<LoopWithExits> target) {
@ -179,7 +175,6 @@ class LoopInversionImpl {
final IntSet nodesAndCopies = new IntOpenHashSet();
final IntSet exits = new IntOpenHashSet();
int bodyStart;
int copyStart;
int headCopy;
final IntIntMap copiedNodes = new IntIntOpenHashMap();
boolean shouldSkip;
@ -352,7 +347,7 @@ class LoopInversionImpl {
TryCatchJoint jointCopy = new TryCatchJoint();
jointCopy.setReceiver(joint.getReceiver());
jointCopy.getSourceVariables().addAll(joint.getSourceVariables());
tryCatchCopy.getJoints().add(joint);
tryCatchCopy.getJoints().add(jointCopy);
}
}
}

View File

@ -244,7 +244,7 @@ public class PhiUpdater {
TryCatchBlock tryCatch = currentBlock.getTryCatchBlocks().get(i);
catchSuccessors.add(tryCatch.getHandler().getIndex());
for (TryCatchJoint joint : synthesizedJoints.get(index).get(i)) {
joint.setReceiver(define(joint.getReceiver()));
joint.setReceiver(defineForExceptionPhi(joint.getReceiver()));
}
}
variableMap = regularVariableMap;
@ -308,10 +308,8 @@ public class PhiUpdater {
while (head > 0) {
BasicBlock block = worklist[--head];
int[] frontiers = domFrontiers[block.getIndex()];
if (frontiers == null) {
continue;
}
if (frontiers != null) {
for (int frontier : frontiers) {
BasicBlock frontierBlock = program.basicBlockAt(frontier);
if (frontierBlock.getExceptionVariable() == var) {
@ -336,6 +334,27 @@ 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);
synthesizedJoints.get(block.getIndex()).get(i).add(joint);
jointMap.get(tryCatch).put(var, joint);
worklist[head++] = tryCatch.getHandler();
}
}
}
}
private Variable defineForExceptionPhi(Variable var) {
Variable original = var;
var = introduce(var);
mapVariable(original.getIndex(), var);
return var;
}
private Variable define(Variable var) {
@ -354,15 +373,13 @@ public class PhiUpdater {
continue;
}
Map<Variable, TryCatchJoint> joints = jointMap.computeIfAbsent(tryCatch, k -> new HashMap<>());
Map<Variable, TryCatchJoint> joints = jointMap.get(tryCatch);
if (joints == null) {
continue;
}
TryCatchJoint joint = joints.get(original);
if (joint == null) {
joint = new TryCatchJoint();
joint.setReceiver(original);
joints.put(original, joint);
synthesizedJoints.get(currentBlock.getIndex()).get(i).add(joint);
}
if (joint.getReceiver() == var) {
continue;
}

View File

@ -18,6 +18,8 @@ package org.teavm.vm;
import static org.junit.Assert.*;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.teavm.jso.JSBody;
import org.teavm.junit.SkipJVM;
import org.teavm.junit.TeaVMTestRunner;
@RunWith(TeaVMTestRunner.class)
@ -132,6 +134,27 @@ public class VMTest {
assertEquals("ok", AsyncClinitClass.state);
}
@Test
@SkipJVM
public void loopAndExceptionPhi() {
int[] a = createArray();
int s = 0;
for (int i = 0; i < 10; ++i) {
int x = 0;
try {
x += 2;
x += 3;
} catch (RuntimeException e) {
fail("Unexpected exception caught: " + x);
}
s += a[0] + a[1];
}
assertEquals(30, s);
}
@JSBody(params = {}, script = "return [1, 2]")
private static native int[] createArray();
static int initCount = 0;
private static class AsyncClinitClass {

View File

@ -15,7 +15,9 @@
<root url="jar://$MODULE_DIR$/lib/teavm-all.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
<SOURCES>
<root url="file://$MODULE_DIR$/../../core/src/main/java" />
</SOURCES>
</library>
</orderEntry>
</component>

View File

@ -228,11 +228,19 @@ public class TeaVMTestRunner extends Runner implements Filterable {
});
for (TeaVMTestConfiguration configuration : configurations) {
try {
TestRun run = compileByTeaVM(child, notifier, expectedExceptions, configuration, onSuccess.get(0));
if (run != null) {
runs.add(run);
} else {
notifier.fireTestFinished(description);
latch.countDown();
return;
}
} catch (Throwable e) {
notifier.fireTestFailure(new Failure(description, e));
notifier.fireTestFinished(description);
latch.countDown();
return;
}
}