Fix bug with capturing phi inputs

This commit is contained in:
Alexey Andreev 2016-03-02 23:14:23 +03:00
parent 5564b47b9f
commit 8df8191dae

View File

@ -17,10 +17,12 @@ package org.teavm.metaprogramming.impl;
import java.lang.reflect.Array; import java.lang.reflect.Array;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.teavm.diagnostics.Diagnostics; import org.teavm.diagnostics.Diagnostics;
import org.teavm.metaprogramming.ReflectClass; import org.teavm.metaprogramming.ReflectClass;
import org.teavm.metaprogramming.Value; import org.teavm.metaprogramming.Value;
@ -126,6 +128,7 @@ public class CompositeMethodGenerator {
location = null; location = null;
resultVar = null; resultVar = null;
resultPhi = null; resultPhi = null;
int startBlock = blockIndex;
AliasFinder aliasFinder = new AliasFinder(); AliasFinder aliasFinder = new AliasFinder();
aliasFinder.findAliases(template); aliasFinder.findAliases(template);
@ -138,6 +141,7 @@ public class CompositeMethodGenerator {
aliasFinder.getArrayElements(), program.basicBlockCount() - 1, aliasFinder.getArrayElements(), program.basicBlockCount() - 1,
program.variableCount() - capturedValues.size()); program.variableCount() - capturedValues.size());
// Pre-create blocks and variables
for (int i = 0; i < template.basicBlockCount(); ++i) { for (int i = 0; i < template.basicBlockCount(); ++i) {
program.createBasicBlock(); program.createBasicBlock();
} }
@ -147,25 +151,39 @@ public class CompositeMethodGenerator {
program.createVariable(); program.createVariable();
} }
int startBlock = blockIndex; // Pre-create phis
// We need this since phi input variables can be captured as well. In thi case
// we must perform capturing in input block rather that phi owner.
List<List<Incoming>> outgoings = Stream.<List<Incoming>>generate(ArrayList::new)
.limit(template.basicBlockCount())
.collect(Collectors.toList());
List<List<VariableReader>> outgoingVars = Stream.<List<VariableReader>>generate(ArrayList::new)
.limit(template.basicBlockCount())
.collect(Collectors.toList());
for (int i = 0; i < template.basicBlockCount(); ++i) { for (int i = 0; i < template.basicBlockCount(); ++i) {
BasicBlockReader templateBlock = template.basicBlockAt(i); BasicBlockReader templateBlock = template.basicBlockAt(i);
if (i > 0) { blockIndex = i == 0 ? startBlock : substitutor.blockOffset + i;
blockIndex = substitutor.blockOffset + i;
}
BasicBlock targetBlock = program.basicBlockAt(blockIndex); BasicBlock targetBlock = program.basicBlockAt(blockIndex);
for (PhiReader templatePhi : templateBlock.readPhis()) { for (PhiReader templatePhi : templateBlock.readPhis()) {
Phi phi = new Phi(); Phi phi = new Phi();
for (IncomingReader templateIncoming : templatePhi.readIncomings()) { for (IncomingReader templateIncoming : templatePhi.readIncomings()) {
Incoming incoming = new Incoming(); Incoming incoming = new Incoming();
incoming.setSource(substitutor.block(templateIncoming.getSource())); incoming.setSource(substitutor.block(templateIncoming.getSource()));
incoming.setValue(substitutor.var(templateIncoming.getValue()));
phi.getIncomings().add(incoming); phi.getIncomings().add(incoming);
int sourceIndex = templateIncoming.getSource().getIndex();
outgoings.get(sourceIndex).add(incoming);
outgoingVars.get(sourceIndex).add(templateIncoming.getValue());
} }
phi.setReceiver(substitutor.var(templatePhi.getReceiver())); phi.setReceiver(substitutor.var(templatePhi.getReceiver()));
targetBlock.getPhis().add(phi); targetBlock.getPhis().add(phi);
} }
}
// Copy program
for (int i = 0; i < template.basicBlockCount(); ++i) {
BasicBlockReader templateBlock = template.basicBlockAt(i);
blockIndex = i == 0 ? startBlock : substitutor.blockOffset + i;
BasicBlock targetBlock = program.basicBlockAt(blockIndex);
for (TryCatchBlockReader templateTryCatch : templateBlock.readTryCatchBlocks()) { for (TryCatchBlockReader templateTryCatch : templateBlock.readTryCatchBlocks()) {
TryCatchBlock tryCatch = new TryCatchBlock(); TryCatchBlock tryCatch = new TryCatchBlock();
@ -176,9 +194,20 @@ public class CompositeMethodGenerator {
} }
templateBlock.readAllInstructions(substitutor); templateBlock.readAllInstructions(substitutor);
// Capture phi inputs of successor blocks
Instruction lastInsn = targetBlock.getInstructions().remove(targetBlock.getInstructions().size() - 1);
List<Incoming> blockOutgoings = outgoings.get(i);
for (int j = 0; j < blockOutgoings.size(); ++j) {
VariableReader outgoingVar = outgoingVars.get(i).get(j);
blockOutgoings.get(j).setValue(substitutor.var(outgoingVar));
}
targetBlock.getInstructions().add(lastInsn);
phiBlockMap.put(targetBlock, currentBlock()); phiBlockMap.put(targetBlock, currentBlock());
} }
// Fix phi input blocks
for (int i = 0; i < template.basicBlockCount(); ++i) { for (int i = 0; i < template.basicBlockCount(); ++i) {
BasicBlock block = program.basicBlockAt(i == 0 ? startBlock : substitutor.blockOffset + i); BasicBlock block = program.basicBlockAt(i == 0 ? startBlock : substitutor.blockOffset + i);
for (Phi phi : block.getPhis()) { for (Phi phi : block.getPhis()) {