diff --git a/core/src/main/java/org/teavm/cache/ProgramIO.java b/core/src/main/java/org/teavm/cache/ProgramIO.java index 8f8787f60..dcacdc86b 100644 --- a/core/src/main/java/org/teavm/cache/ProgramIO.java +++ b/core/src/main/java/org/teavm/cache/ProgramIO.java @@ -70,6 +70,14 @@ public class ProgramIO { data.writeShort(tryCatch.getExceptionVariable() != null ? tryCatch.getExceptionVariable().getIndex() : -1); data.writeShort(tryCatch.getHandler().getIndex()); + data.writeShort(tryCatch.getJoints().size()); + for (TryCatchJoint joint : tryCatch.getJoints()) { + data.writeShort(joint.getTargetVariable().getIndex()); + data.writeShort(joint.getSourceVariables().size()); + for (Variable sourceVar : joint.getSourceVariables()) { + data.writeShort(sourceVar.getIndex()); + } + } } InstructionLocation location = null; InstructionWriter insnWriter = new InstructionWriter(data); @@ -138,6 +146,17 @@ public class ProgramIO { } tryCatch.setHandler(program.basicBlockAt(data.readShort())); block.getTryCatchBlocks().add(tryCatch); + + int jointCount = data.readShort(); + for (int k = 0; k < jointCount; ++k) { + TryCatchJoint joint = new TryCatchJoint(); + joint.setTargetVariable(program.variableAt(data.readShort())); + int jointSourceCount = data.readShort(); + for (int m = 0; m < jointSourceCount; ++m) { + joint.getSourceVariables().add(program.variableAt(data.readShort())); + } + tryCatch.getJoints().add(joint); + } } InstructionLocation location = null; insnLoop: while (true) { diff --git a/core/src/main/java/org/teavm/model/Program.java b/core/src/main/java/org/teavm/model/Program.java index da66e3950..e8043b8e6 100644 --- a/core/src/main/java/org/teavm/model/Program.java +++ b/core/src/main/java/org/teavm/model/Program.java @@ -18,10 +18,6 @@ package org.teavm.model; import java.util.ArrayList; import java.util.List; -/** - * - * @author Alexey Andreev - */ public class Program implements ProgramReader { private List basicBlocks = new ArrayList<>(); private List variables = new ArrayList<>(); diff --git a/core/src/main/java/org/teavm/model/TryCatchBlock.java b/core/src/main/java/org/teavm/model/TryCatchBlock.java index cfeecfb7e..ad549c910 100644 --- a/core/src/main/java/org/teavm/model/TryCatchBlock.java +++ b/core/src/main/java/org/teavm/model/TryCatchBlock.java @@ -15,15 +15,17 @@ */ package org.teavm.model; -/** - * - * @author Alexey Andreev - */ +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + public class TryCatchBlock implements TryCatchBlockReader { BasicBlock protectedBlock; private BasicBlock handler; private String exceptionType; private Variable exceptionVariable; + private List joints = new ArrayList<>(); + private List immutableJoints = new ArrayList<>(); @Override public BasicBlock getHandler() { @@ -56,4 +58,16 @@ public class TryCatchBlock implements TryCatchBlockReader { public BasicBlock getProtectedBlock() { return protectedBlock; } + + public List getJoints() { + return joints; + } + + @Override + public List readJoints() { + if (immutableJoints == null) { + immutableJoints = Collections.unmodifiableList(joints); + } + return immutableJoints; + } } diff --git a/core/src/main/java/org/teavm/model/TryCatchBlockReader.java b/core/src/main/java/org/teavm/model/TryCatchBlockReader.java index 564265c0f..226a2c87e 100644 --- a/core/src/main/java/org/teavm/model/TryCatchBlockReader.java +++ b/core/src/main/java/org/teavm/model/TryCatchBlockReader.java @@ -15,10 +15,8 @@ */ package org.teavm.model; -/** - * - * @author Alexey Andreev - */ +import java.util.List; + public interface TryCatchBlockReader { BasicBlockReader getProtectedBlock(); @@ -27,4 +25,6 @@ public interface TryCatchBlockReader { String getExceptionType(); VariableReader getExceptionVariable(); + + List readJoints(); } diff --git a/core/src/main/java/org/teavm/model/TryCatchJoint.java b/core/src/main/java/org/teavm/model/TryCatchJoint.java new file mode 100644 index 000000000..7737a7c02 --- /dev/null +++ b/core/src/main/java/org/teavm/model/TryCatchJoint.java @@ -0,0 +1,47 @@ +/* + * Copyright 2016 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; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class TryCatchJoint implements TryCatchJointReader { + private List sourceVariables = new ArrayList<>(); + private List readonlySourceVariables; + private Variable targetVariable; + + @Override + public List readSourceVariables() { + if (readonlySourceVariables == null) { + readonlySourceVariables = Collections.unmodifiableList(sourceVariables); + } + return readonlySourceVariables; + } + + public List getSourceVariables() { + return sourceVariables; + } + + @Override + public Variable getTargetVariable() { + return targetVariable; + } + + public void setTargetVariable(Variable targetVariable) { + this.targetVariable = targetVariable; + } +} diff --git a/core/src/main/java/org/teavm/model/TryCatchJointReader.java b/core/src/main/java/org/teavm/model/TryCatchJointReader.java new file mode 100644 index 000000000..3c20024c0 --- /dev/null +++ b/core/src/main/java/org/teavm/model/TryCatchJointReader.java @@ -0,0 +1,24 @@ +/* + * Copyright 2016 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; + +import java.util.List; + +public interface TryCatchJointReader { + List readSourceVariables(); + + VariableReader getTargetVariable(); +} diff --git a/core/src/main/java/org/teavm/model/util/GraphColorer.java b/core/src/main/java/org/teavm/model/util/GraphColorer.java index 1234de0c3..ae2ac9c1c 100644 --- a/core/src/main/java/org/teavm/model/util/GraphColorer.java +++ b/core/src/main/java/org/teavm/model/util/GraphColorer.java @@ -21,10 +21,6 @@ import org.teavm.common.IntegerArray; import org.teavm.common.MutableGraphEdge; import org.teavm.common.MutableGraphNode; -/** - * - * @author Alexey Andreev - */ class GraphColorer { public void colorize(List graph, int[] colors) { colorize(graph, colors, new int[graph.size()]); diff --git a/core/src/main/java/org/teavm/model/util/InstructionVariableMapper.java b/core/src/main/java/org/teavm/model/util/InstructionVariableMapper.java index fa6bbd64d..568d537b0 100644 --- a/core/src/main/java/org/teavm/model/util/InstructionVariableMapper.java +++ b/core/src/main/java/org/teavm/model/util/InstructionVariableMapper.java @@ -22,6 +22,7 @@ import org.teavm.model.Instruction; import org.teavm.model.InvokeDynamicInstruction; import org.teavm.model.Phi; import org.teavm.model.TryCatchBlock; +import org.teavm.model.TryCatchJoint; import org.teavm.model.Variable; import org.teavm.model.instructions.*; @@ -58,6 +59,13 @@ public class InstructionVariableMapper implements InstructionVisitor { if (tryCatch.getExceptionVariable() != null) { tryCatch.setExceptionVariable(map(tryCatch.getExceptionVariable())); } + for (TryCatchJoint joint : tryCatch.getJoints()) { + joint.setTargetVariable(map(joint.getTargetVariable())); + for (int i = 0; i < joint.getSourceVariables().size(); ++i) { + Variable var = joint.getSourceVariables().get(i); + joint.getSourceVariables().set(i, map(var)); + } + } } } diff --git a/core/src/main/java/org/teavm/model/util/InterferenceGraphBuilder.java b/core/src/main/java/org/teavm/model/util/InterferenceGraphBuilder.java index c9a596a21..ba1026e75 100644 --- a/core/src/main/java/org/teavm/model/util/InterferenceGraphBuilder.java +++ b/core/src/main/java/org/teavm/model/util/InterferenceGraphBuilder.java @@ -53,11 +53,24 @@ class InterferenceGraphBuilder { if (tryCatch.getExceptionVariable() != null) { nodes.get(tryCatch.getExceptionVariable().getIndex()).connectAll(live); } + for (TryCatchJoint joint : tryCatch.getJoints()) { + nodes.get(joint.getTargetVariable().getIndex()).connectAll(live); + } } for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) { if (tryCatch.getExceptionVariable() != null) { live.remove(nodes.get(tryCatch.getExceptionVariable().getIndex())); } + for (TryCatchJoint joint : tryCatch.getJoints()) { + nodes.get(joint.getTargetVariable().getIndex()).connectAll(live); + } + } + for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) { + for (TryCatchJoint joint : tryCatch.getJoints()) { + for (Variable var : joint.getSourceVariables()) { + live.add(nodes.get(var.getIndex())); + } + } } for (int j = block.getInstructions().size() - 1; j >= 0; --j) { Instruction insn = block.getInstructions().get(j); diff --git a/core/src/main/java/org/teavm/model/util/ListingBuilder.java b/core/src/main/java/org/teavm/model/util/ListingBuilder.java index 416ca2c2f..9fe19aeea 100644 --- a/core/src/main/java/org/teavm/model/util/ListingBuilder.java +++ b/core/src/main/java/org/teavm/model/util/ListingBuilder.java @@ -17,12 +17,9 @@ package org.teavm.model.util; import java.util.List; import java.util.Objects; +import java.util.stream.Collectors; import org.teavm.model.*; -/** - * - * @author Alexey Andreev - */ public class ListingBuilder { public String buildListing(ProgramReader program, String prefix) { StringBuilder sb = new StringBuilder(); @@ -78,7 +75,16 @@ public class ListingBuilder { for (TryCatchBlockReader tryCatch : block.readTryCatchBlocks()) { sb.append(prefix).append(" catch ").append(tryCatch.getExceptionType()).append(" @") .append(tryCatch.getExceptionVariable().getIndex()) - .append(" -> $").append(tryCatch.getHandler().getIndex()).append("\n"); + .append(" -> $").append(tryCatch.getHandler().getIndex()); + if (!tryCatch.readJoints().isEmpty()) { + sb.append(" with "); + for (TryCatchJointReader joint : tryCatch.readJoints()) { + sb.append(" @").append(joint.getTargetVariable().getIndex()).append(" := "); + sb.append(joint.readSourceVariables().stream().map(sourceVar -> "@" + sourceVar.getIndex()) + .collect(Collectors.joining("|"))); + } + } + sb.append("\n"); } } return sb.toString(); diff --git a/core/src/main/java/org/teavm/model/util/LivenessAnalyzer.java b/core/src/main/java/org/teavm/model/util/LivenessAnalyzer.java index 0bb802e65..4f3297215 100644 --- a/core/src/main/java/org/teavm/model/util/LivenessAnalyzer.java +++ b/core/src/main/java/org/teavm/model/util/LivenessAnalyzer.java @@ -23,10 +23,6 @@ import java.util.Deque; import org.teavm.common.Graph; import org.teavm.model.*; -/** - * - * @author Alexey Andreev - */ public class LivenessAnalyzer { private BitSet[] liveVars; @@ -69,6 +65,15 @@ public class LivenessAnalyzer { } } for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) { + for (TryCatchJoint joint : tryCatch.getJoints()) { + definitions[joint.getTargetVariable().getIndex()] = i; + for (Variable sourceVar : joint.getSourceVariables()) { + Task task = new Task(); + task.block = i; + task.var = sourceVar.getIndex(); + stack.push(task); + } + } if (tryCatch.getExceptionVariable() != null) { definitions[tryCatch.getExceptionVariable().getIndex()] = i; } diff --git a/core/src/main/java/org/teavm/model/util/PhiUpdater.java b/core/src/main/java/org/teavm/model/util/PhiUpdater.java index 1ea5e0fc3..0fbd01dc3 100644 --- a/core/src/main/java/org/teavm/model/util/PhiUpdater.java +++ b/core/src/main/java/org/teavm/model/util/PhiUpdater.java @@ -15,6 +15,11 @@ */ package org.teavm.model.util; +import com.carrotsearch.hppc.IntObjectMap; +import com.carrotsearch.hppc.IntObjectOpenHashMap; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -22,12 +27,17 @@ import org.teavm.common.DominatorTree; import org.teavm.common.Graph; import org.teavm.common.GraphUtils; import org.teavm.model.BasicBlock; +import org.teavm.model.ClassHolder; +import org.teavm.model.ClassHolderSource; import org.teavm.model.Incoming; import org.teavm.model.Instruction; import org.teavm.model.InvokeDynamicInstruction; +import org.teavm.model.MethodDescriptor; +import org.teavm.model.MethodHolder; import org.teavm.model.Phi; import org.teavm.model.Program; import org.teavm.model.TryCatchBlock; +import org.teavm.model.TryCatchJoint; import org.teavm.model.Variable; import org.teavm.model.instructions.ArrayLengthInstruction; import org.teavm.model.instructions.AssignInstruction; @@ -66,6 +76,7 @@ import org.teavm.model.instructions.RaiseInstruction; import org.teavm.model.instructions.StringConstantInstruction; import org.teavm.model.instructions.SwitchInstruction; import org.teavm.model.instructions.UnwrapArrayInstruction; +import org.teavm.parsing.ClasspathClassHolderSource; public class PhiUpdater { private Program program; @@ -76,6 +87,7 @@ public class PhiUpdater { private Phi[][] phiMap; private int[][] phiIndexMap; private List> synthesizedPhis = new ArrayList<>(); + private List> outputJoints = new ArrayList<>(); private boolean[] usedDefinitions; public void updatePhis(Program program, Variable[] arguments) { @@ -87,8 +99,10 @@ public class PhiUpdater { DominatorTree domTree = GraphUtils.buildDominatorTree(cfg); domFrontiers = new int[cfg.size()][]; variableMap = new Variable[program.variableCount()]; + usedDefinitions = new boolean[program.variableCount()]; for (int i = 0; i < arguments.length; ++i) { variableMap[i] = arguments[i]; + usedDefinitions[i] = true; } phiMap = new Phi[program.basicBlockCount()][]; phiIndexMap = new int[program.basicBlockCount()][]; @@ -102,7 +116,6 @@ public class PhiUpdater { for (int i = 0; i < program.basicBlockCount(); ++i) { synthesizedPhis.add(new ArrayList<>()); } - usedDefinitions = new boolean[program.variableCount()]; estimatePhis(); renameVariables(); } @@ -111,14 +124,17 @@ public class PhiUpdater { DefinitionExtractor definitionExtractor = new DefinitionExtractor(); for (int i = 0; i < program.basicBlockCount(); ++i) { currentBlock = program.basicBlockAt(i); + for (Phi phi : currentBlock.getPhis()) { + markAssignment(phi.getReceiver()); + } for (Instruction insn : currentBlock.getInstructions()) { insn.acceptVisitor(definitionExtractor); for (Variable var : definitionExtractor.getDefinedVariables()) { markAssignment(var); } } - for (Phi phi : currentBlock.getPhis()) { - markAssignment(phi.getReceiver()); + for (TryCatchBlock tryCatch : currentBlock.getTryCatchBlocks()) { + markAssignment(tryCatch.getExceptionVariable()); } } } @@ -154,6 +170,10 @@ public class PhiUpdater { } processed[index] = true; variableMap = Arrays.copyOf(task.variables, task.variables.length); + outputJoints.clear(); + for (int i = 0; i < currentBlock.getTryCatchBlocks().size(); ++i) { + outputJoints.add(new IntObjectOpenHashMap<>()); + } for (Phi phi : synthesizedPhis.get(index)) { Variable var = program.createVariable(); @@ -161,7 +181,6 @@ public class PhiUpdater { variableMap[phi.getReceiver().getIndex()] = var; phi.setReceiver(var); } - for (Phi phi : currentBlock.getPhis()) { phi.setReceiver(define(phi.getReceiver())); } @@ -169,10 +188,21 @@ public class PhiUpdater { for (Instruction insn : currentBlock.getInstructions()) { insn.acceptVisitor(consumer); } + for (IntObjectMap joints : outputJoints) { + for (int jointVar : joints.keys().toArray()) { + joints.get(jointVar).setTargetVariable(introduce(program.variableAt(jointVar))); + } + } + + IntObjectMap> exceptionVariableMap = new IntObjectOpenHashMap<>(); for (TryCatchBlock tryCatch : currentBlock.getTryCatchBlocks()) { + IntObjectMap tryCatchVariableMap = new IntObjectOpenHashMap<>(); + exceptionVariableMap.put(tryCatch.getHandler().getIndex(), tryCatchVariableMap); Variable var = tryCatch.getExceptionVariable(); if (var != null) { - tryCatch.setExceptionVariable(define(var)); + Variable newVar = introduce(var); + tryCatch.setExceptionVariable(newVar); + tryCatchVariableMap.put(var.getIndex(), newVar); } } for (Incoming output : phiOutputs.get(index)) { @@ -188,11 +218,18 @@ public class PhiUpdater { } successors = cfg.outgoingEdges(index); for (int successor : successors) { + IntObjectMap tryCatchVariableMap = exceptionVariableMap.get(successor); int[] phiIndexes = phiIndexMap[successor]; List phis = synthesizedPhis.get(successor); for (int j = 0; j < phis.size(); ++j) { Phi phi = phis.get(j); - Variable var = variableMap[phiIndexes[j]]; + Variable var = null; + if (tryCatchVariableMap != null) { + var = tryCatchVariableMap.get(phiIndexes[j]); + } + if (var == null) { + var = variableMap[phiIndexes[j]]; + } if (var != null) { Incoming incoming = new Incoming(); incoming.setSource(currentBlock); @@ -202,8 +239,10 @@ public class PhiUpdater { } } } + } - program.basicBlockAt(index).getPhis().addAll(synthesizedPhis.get(index)); + for (int i = 0; i < program.basicBlockCount(); ++i) { + program.basicBlockAt(i).getPhis().addAll(synthesizedPhis.get(i)); } } @@ -219,6 +258,12 @@ public class PhiUpdater { } for (int frontier : frontiers) { BasicBlock frontierBlock = program.basicBlockAt(frontier); + boolean exists = frontierBlock.getPhis().stream() + .flatMap(phi -> phi.getIncomings().stream()) + .anyMatch(incoming -> incoming.getSource() == block && incoming.getValue() == var); + if (exists) { + continue; + } Phi phi = phiMap[frontier][var.getIndex()]; if (phi == null) { phi = new Phi(); @@ -233,16 +278,41 @@ public class PhiUpdater { } private Variable define(Variable var) { - Variable result; - if (!usedDefinitions[var.getIndex()]) { - usedDefinitions[var.getIndex()] = true; - result = var; - } else { - result = program.createVariable(); + Variable original = var; + Variable old = variableMap[var.getIndex()]; + if (old == null) { + old = var; + } + var = introduce(var); + + if (original != var) { + List tryCatches = currentBlock.getTryCatchBlocks(); + for (int i = 0; i < tryCatches.size(); ++i) { + TryCatchBlock tryCatch = tryCatches.get(i); + IntObjectMap jointMap = outputJoints.get(i); + TryCatchJoint joint = jointMap.get(original.getIndex()); + if (joint == null) { + joint = new TryCatchJoint(); + joint.getSourceVariables().add(old); + tryCatch.getJoints().add(joint); + jointMap.put(original.getIndex(), joint); + } + joint.getSourceVariables().add(var); + } } - variableMap[var.getIndex()] = result; - return result; + variableMap[original.getIndex()] = var; + + return var; + } + + private Variable introduce(Variable var) { + if (!usedDefinitions[var.getIndex()]) { + usedDefinitions[var.getIndex()] = true; + } else { + var = program.createVariable(); + } + return var; } private Variable use(Variable var) { @@ -484,4 +554,11 @@ public class PhiUpdater { insn.setObjectRef(use(insn.getObjectRef())); } }; + + public static void main(String[] args) { + ClassHolderSource classSource = new ClasspathClassHolderSource(); + ClassHolder cls = classSource.get(Charset.class.getName()); + MethodHolder method = cls.getMethod(new MethodDescriptor("decode", ByteBuffer.class, CharBuffer.class)); + System.out.println(new ListingBuilder().buildListing(method.getProgram(), "")); + } } diff --git a/core/src/main/java/org/teavm/model/util/ProgramUtils.java b/core/src/main/java/org/teavm/model/util/ProgramUtils.java index 549b72967..27e6a47af 100644 --- a/core/src/main/java/org/teavm/model/util/ProgramUtils.java +++ b/core/src/main/java/org/teavm/model/util/ProgramUtils.java @@ -32,7 +32,10 @@ import org.teavm.model.Program; import org.teavm.model.ProgramReader; import org.teavm.model.TryCatchBlock; import org.teavm.model.TryCatchBlockReader; +import org.teavm.model.TryCatchJoint; +import org.teavm.model.TryCatchJointReader; import org.teavm.model.Variable; +import org.teavm.model.VariableReader; public final class ProgramUtils { private ProgramUtils() { @@ -77,13 +80,7 @@ public final class ProgramUtils { BasicBlock blockCopy = copy.basicBlockAt(i); blockCopy.getInstructions().addAll(copyInstructions(block, 0, block.instructionCount(), copy)); blockCopy.getPhis().addAll(copyPhis(block, copy)); - for (TryCatchBlockReader tryCatch : block.readTryCatchBlocks()) { - TryCatchBlock tryCatchCopy = new TryCatchBlock(); - tryCatchCopy.setExceptionType(tryCatch.getExceptionType()); - tryCatchCopy.setExceptionVariable(copy.variableAt(tryCatch.getExceptionVariable().getIndex())); - tryCatchCopy.setHandler(copy.basicBlockAt(tryCatch.getHandler().getIndex())); - blockCopy.getTryCatchBlocks().add(tryCatchCopy); - } + blockCopy.getTryCatchBlocks().addAll(copyTryCatches(block, copy)); } return copy; } @@ -122,6 +119,14 @@ public final class ProgramUtils { tryCatchCopy.setExceptionVariable(target.variableAt(tryCatch.getExceptionVariable().getIndex())); tryCatchCopy.setHandler(target.basicBlockAt(tryCatch.getHandler().getIndex())); result.add(tryCatchCopy); + for (TryCatchJointReader joint : tryCatch.readJoints()) { + TryCatchJoint jointCopy = new TryCatchJoint(); + jointCopy.setTargetVariable(target.variableAt(joint.getTargetVariable().getIndex())); + for (VariableReader jointSourceVar : joint.readSourceVariables()) { + jointCopy.getSourceVariables().add(target.variableAt(jointSourceVar.getIndex())); + } + tryCatchCopy.getJoints().add(jointCopy); + } } return result; } diff --git a/core/src/main/java/org/teavm/optimization/GlobalValueNumbering.java b/core/src/main/java/org/teavm/optimization/GlobalValueNumbering.java index 791540f94..a49106e95 100644 --- a/core/src/main/java/org/teavm/optimization/GlobalValueNumbering.java +++ b/core/src/main/java/org/teavm/optimization/GlobalValueNumbering.java @@ -100,8 +100,18 @@ public class GlobalValueNumbering implements MethodOptimization { incoming.setValue(program.variableAt(value)); } for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) { - int var = map[tryCatch.getExceptionVariable().getIndex()]; - tryCatch.setExceptionVariable(program.variableAt(var)); + for (TryCatchJoint joint : tryCatch.getJoints()) { + joint.setTargetVariable(program.variableAt(map[joint.getTargetVariable().getIndex()])); + for (int i = 0; i < joint.getSourceVariables().size(); ++i) { + int var = joint.getSourceVariables().get(i).getIndex(); + var = map[var]; + joint.getSourceVariables().set(i, program.variableAt(var)); + } + } + if (tryCatch.getExceptionVariable() != null) { + int var = map[tryCatch.getExceptionVariable().getIndex()]; + tryCatch.setExceptionVariable(program.variableAt(var)); + } } for (int succ : dom.outgoingEdges(v)) { stack[top++] = succ; diff --git a/core/src/main/java/org/teavm/optimization/LoopInversionImpl.java b/core/src/main/java/org/teavm/optimization/LoopInversionImpl.java index a4381fe7e..b5ad75474 100644 --- a/core/src/main/java/org/teavm/optimization/LoopInversionImpl.java +++ b/core/src/main/java/org/teavm/optimization/LoopInversionImpl.java @@ -38,6 +38,7 @@ import org.teavm.model.Instruction; import org.teavm.model.Phi; import org.teavm.model.Program; import org.teavm.model.TryCatchBlock; +import org.teavm.model.TryCatchJoint; import org.teavm.model.Variable; import org.teavm.model.util.BasicBlockMapper; import org.teavm.model.util.InstructionCopyReader; @@ -276,6 +277,27 @@ class LoopInversionImpl { tryCatchCopy.setExceptionVariable(tryCatch.getExceptionVariable()); tryCatchCopy.setHandler(program.basicBlockAt(copiedNodes.getOrDefault(handler, handler))); targetBlock.getTryCatchBlocks().add(tryCatchCopy); + for (TryCatchJoint joint : tryCatch.getJoints()) { + TryCatchJoint jointCopy = new TryCatchJoint(); + jointCopy.setTargetVariable(joint.getTargetVariable()); + jointCopy.getSourceVariables().addAll(joint.getSourceVariables()); + tryCatchCopy.getJoints().add(joint); + } + } + } + + for (int node = 0; node < cfg.size(); ++node) { + BasicBlock block = program.basicBlockAt(node); + for (Phi phi : block.getPhis()) { + for (Incoming incoming : phi.getIncomings().toArray(new Incoming[0])) { + int source = incoming.getSource().getIndex(); + if (copiedNodes.containsKey(source)) { + Incoming incomingCopy = new Incoming(); + incomingCopy.setValue(incoming.getValue()); + incomingCopy.setSource(program.basicBlockAt(copiedNodes.get(source))); + phi.getIncomings().add(incomingCopy); + } + } } } } diff --git a/core/src/main/java/org/teavm/optimization/UnusedVariableElimination.java b/core/src/main/java/org/teavm/optimization/UnusedVariableElimination.java index 7585f8ea4..61fb411ed 100644 --- a/core/src/main/java/org/teavm/optimization/UnusedVariableElimination.java +++ b/core/src/main/java/org/teavm/optimization/UnusedVariableElimination.java @@ -70,6 +70,14 @@ public class UnusedVariableElimination implements MethodOptimization { block.getPhis().remove(j--); } } + for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) { + for (int j = 0; j < tryCatch.getJoints().size(); ++j) { + TryCatchJoint joint = tryCatch.getJoints().get(j); + if (!used[joint.getTargetVariable().getIndex()]) { + tryCatch.getJoints().remove(j--); + } + } + } } } @@ -258,12 +266,10 @@ public class UnusedVariableElimination implements MethodOptimization { @Override public void visit(MonitorEnterInstruction insn) { - } @Override public void visit(MonitorExitInstruction insn) { - } } }