diff --git a/core/src/main/java/org/teavm/cache/ProgramIO.java b/core/src/main/java/org/teavm/cache/ProgramIO.java index 58be34add..470fc074e 100644 --- a/core/src/main/java/org/teavm/cache/ProgramIO.java +++ b/core/src/main/java/org/teavm/cache/ProgramIO.java @@ -50,6 +50,8 @@ public class ProgramIO { } for (int i = 0; i < program.basicBlockCount(); ++i) { BasicBlock basicBlock = program.basicBlockAt(i); + data.writeShort(basicBlock.getExceptionVariable() != null + ? basicBlock.getExceptionVariable().getIndex() : -1); data.writeShort(basicBlock.getPhis().size()); data.writeShort(basicBlock.getTryCatchBlocks().size()); for (Phi phi : basicBlock.getPhis()) { @@ -63,17 +65,14 @@ public class ProgramIO { for (TryCatchBlock tryCatch : basicBlock.getTryCatchBlocks()) { data.writeInt(tryCatch.getExceptionType() != null ? symbolTable.lookup( tryCatch.getExceptionType()) : -1); - data.writeShort(tryCatch.getExceptionVariable() != null - ? tryCatch.getExceptionVariable().getIndex() : -1); data.writeShort(tryCatch.getHandler().getIndex()); - } - data.writeShort(basicBlock.getTryCatchJoints().size()); - for (TryCatchJoint joint : basicBlock.getTryCatchJoints()) { - data.writeShort(joint.getSource().getIndex()); - data.writeShort(joint.getReceiver().getIndex()); - data.writeShort(joint.getSourceVariables().size()); - for (Variable sourceVar : joint.getSourceVariables()) { - data.writeShort(sourceVar.getIndex()); + data.writeShort(tryCatch.getTryCatchJoints().size()); + for (TryCatchJoint joint : tryCatch.getTryCatchJoints()) { + data.writeShort(joint.getReceiver().getIndex()); + data.writeShort(joint.getSourceVariables().size()); + for (Variable sourceVar : joint.getSourceVariables()) { + data.writeShort(sourceVar.getIndex()); + } } } InstructionLocation location = null; @@ -117,6 +116,12 @@ public class ProgramIO { } for (int i = 0; i < basicBlockCount; ++i) { BasicBlock block = program.basicBlockAt(i); + + short varIndex = data.readShort(); + if (varIndex >= 0) { + block.setExceptionVariable(program.variableAt(varIndex)); + } + int phiCount = data.readShort(); int tryCatchCount = data.readShort(); for (int j = 0; j < phiCount; ++j) { @@ -137,24 +142,20 @@ public class ProgramIO { if (typeIndex >= 0) { tryCatch.setExceptionType(symbolTable.at(typeIndex)); } - short varIndex = data.readShort(); - if (varIndex >= 0) { - tryCatch.setExceptionVariable(program.variableAt(varIndex)); - } tryCatch.setHandler(program.basicBlockAt(data.readShort())); - block.getTryCatchBlocks().add(tryCatch); - } - int jointCount = data.readShort(); - for (int j = 0; j < jointCount; ++j) { - TryCatchJoint joint = new TryCatchJoint(); - joint.setSource(program.basicBlockAt(data.readShort())); - joint.setReceiver(program.variableAt(data.readShort())); - int jointSourceCount = data.readShort(); - for (int k = 0; k < jointSourceCount; ++k) { - joint.getSourceVariables().add(program.variableAt(data.readShort())); + int jointCount = data.readShort(); + for (int k = 0; k < jointCount; ++k) { + TryCatchJoint joint = new TryCatchJoint(); + joint.setReceiver(program.variableAt(data.readShort())); + int jointSourceCount = data.readShort(); + for (int m = 0; m < jointSourceCount; ++m) { + joint.getSourceVariables().add(program.variableAt(data.readShort())); + } + tryCatch.getTryCatchJoints().add(joint); } - block.getTryCatchJoints().add(joint); + + block.getTryCatchBlocks().add(tryCatch); } InstructionLocation location = null; diff --git a/core/src/main/java/org/teavm/dependency/DataFlowGraphBuilder.java b/core/src/main/java/org/teavm/dependency/DataFlowGraphBuilder.java index 84903dfc3..7f2213d5f 100644 --- a/core/src/main/java/org/teavm/dependency/DataFlowGraphBuilder.java +++ b/core/src/main/java/org/teavm/dependency/DataFlowGraphBuilder.java @@ -64,9 +64,11 @@ public class DataFlowGraphBuilder implements InstructionReader { builder.addEdge(from, to); } } - for (TryCatchJointReader joint : block.readTryCatchJoints()) { - for (VariableReader sourceVar : joint.readSourceVariables()) { - builder.addEdge(sourceVar.getIndex(), joint.getReceiver().getIndex()); + for (TryCatchBlockReader tryCatch : block.readTryCatchBlocks()) { + for (TryCatchJointReader joint : tryCatch.readTryCatchJoints()) { + for (VariableReader sourceVar : joint.readSourceVariables()) { + builder.addEdge(sourceVar.getIndex(), joint.getReceiver().getIndex()); + } } } block.readAllInstructions(this); diff --git a/core/src/main/java/org/teavm/dependency/DependencyGraphBuilder.java b/core/src/main/java/org/teavm/dependency/DependencyGraphBuilder.java index d8b839cd5..22c5d404c 100644 --- a/core/src/main/java/org/teavm/dependency/DependencyGraphBuilder.java +++ b/core/src/main/java/org/teavm/dependency/DependencyGraphBuilder.java @@ -137,18 +137,7 @@ class DependencyGraphBuilder { BasicBlockReader block = program.basicBlockAt(i); currentExceptionConsumer = createExceptionConsumer(dep, block); block.readAllInstructions(reader); - for (TryCatchJointReader joint : block.readTryCatchJoints()) { - DependencyNode receiverNode = nodes[joint.getReceiver().getIndex()]; - if (receiverNode == null) { - continue; - } - for (VariableReader source : joint.readSourceVariables()) { - DependencyNode sourceNode = nodes[source.getIndex()]; - if (sourceNode != null) { - sourceNode.connect(receiverNode); - } - } - } + for (PhiReader phi : block.readPhis()) { DependencyNode receiverNode = nodes[phi.getReceiver().getIndex()]; for (IncomingReader incoming : phi.readIncomings()) { @@ -158,10 +147,24 @@ class DependencyGraphBuilder { } } } + for (TryCatchBlockReader tryCatch : block.readTryCatchBlocks()) { if (tryCatch.getExceptionType() != null) { dependencyChecker.linkClass(tryCatch.getExceptionType(), new CallLocation(caller.getMethod())); } + + for (TryCatchJointReader joint : tryCatch.readTryCatchJoints()) { + DependencyNode receiverNode = nodes[joint.getReceiver().getIndex()]; + if (receiverNode == null) { + continue; + } + for (VariableReader source : joint.readSourceVariables()) { + DependencyNode sourceNode = nodes[source.getIndex()]; + if (sourceNode != null) { + sourceNode.connect(receiverNode); + } + } + } } } @@ -286,7 +289,7 @@ class DependencyGraphBuilder { if (tryCatch.getExceptionType() != null) { exceptions[i] = dependencyChecker.getClassSource().get(tryCatch.getExceptionType()); } - vars[i] = methodDep.getVariable(tryCatch.getExceptionVariable().getIndex()); + vars[i] = methodDep.getVariable(tryCatch.getHandler().getExceptionVariable().getIndex()); } return new ExceptionConsumer(dependencyChecker, exceptions, vars, methodDep); } diff --git a/core/src/main/java/org/teavm/javascript/Decompiler.java b/core/src/main/java/org/teavm/javascript/Decompiler.java index f79246ad8..bcfdcdb03 100644 --- a/core/src/main/java/org/teavm/javascript/Decompiler.java +++ b/core/src/main/java/org/teavm/javascript/Decompiler.java @@ -541,8 +541,8 @@ public class Decompiler { bookmark.offset = bookmark.block.body.size(); bookmark.exceptionHandler = tryCatch.getHandler().getIndex(); bookmark.exceptionType = tryCatch.getExceptionType(); - bookmark.exceptionVariable = tryCatch.getExceptionVariable() != null - ? tryCatch.getExceptionVariable().getIndex() : null; + bookmark.exceptionVariable = tryCatch.getHandler().getExceptionVariable() != null + ? tryCatch.getHandler().getExceptionVariable().getIndex() : null; bookmark.block.tryCatches.add(bookmark); tryCatchBookmarks.add(bookmark); } diff --git a/core/src/main/java/org/teavm/javascript/ReadWriteStatsBuilder.java b/core/src/main/java/org/teavm/javascript/ReadWriteStatsBuilder.java index caf99a014..215ff7a3c 100644 --- a/core/src/main/java/org/teavm/javascript/ReadWriteStatsBuilder.java +++ b/core/src/main/java/org/teavm/javascript/ReadWriteStatsBuilder.java @@ -53,6 +53,12 @@ class ReadWriteStatsBuilder { while (!stack.isEmpty()) { int node = stack.pop(); BasicBlock block = program.basicBlockAt(node); + + if (block.getExceptionVariable() != null) { + writes[block.getExceptionVariable().getIndex()]++; + reads[block.getExceptionVariable().getIndex()]++; + } + for (Instruction insn : block.getInstructions()) { insn.acceptVisitor(defExtractor); insn.acceptVisitor(useExtractor); @@ -64,12 +70,6 @@ class ReadWriteStatsBuilder { } } - for (TryCatchJoint joint : block.getTryCatchJoints()) { - writes[joint.getReceiver().getIndex()] += joint.getSourceVariables().size(); - for (Variable var : joint.getSourceVariables()) { - reads[var.getIndex()]++; - } - } for (Phi phi : block.getPhis()) { writes[phi.getReceiver().getIndex()] += phi.getIncomings().size(); for (Incoming incoming : phi.getIncomings()) { @@ -79,8 +79,12 @@ class ReadWriteStatsBuilder { } } for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) { - writes[tryCatch.getExceptionVariable().getIndex()]++; - reads[tryCatch.getExceptionVariable().getIndex()]++; + for (TryCatchJoint joint : tryCatch.getTryCatchJoints()) { + writes[joint.getReceiver().getIndex()] += joint.getSourceVariables().size(); + for (Variable var : joint.getSourceVariables()) { + reads[var.getIndex()]++; + } + } } for (int succ : dom.outgoingEdges(node)) { diff --git a/core/src/main/java/org/teavm/model/BasicBlock.java b/core/src/main/java/org/teavm/model/BasicBlock.java index 6c446db99..e0e52b4aa 100644 --- a/core/src/main/java/org/teavm/model/BasicBlock.java +++ b/core/src/main/java/org/teavm/model/BasicBlock.java @@ -24,8 +24,7 @@ public class BasicBlock implements BasicBlockReader { private List phis = new ArrayList<>(); private List instructions = new ArrayList<>(); private List tryCatchBlocks = new ArrayList<>(); - private List joints = new ArrayList<>(); - private List immutableJoints; + private Variable exceptionVariable; BasicBlock(Program program, int index) { this.program = program; @@ -152,53 +151,6 @@ public class BasicBlock implements BasicBlockReader { } }; - private List safeJoints = new AbstractList() { - @Override - public TryCatchJoint get(int index) { - return joints.get(index); - } - - @Override - public int size() { - return joints.size(); - } - - @Override - public void add(int index, TryCatchJoint e) { - if (e.getBlock() != null) { - throw new IllegalArgumentException("This joint is already in some basic block"); - } - e.block = BasicBlock.this; - joints.add(index, e); - } - - @Override - public TryCatchJoint set(int index, TryCatchJoint element) { - if (element.block != null) { - throw new IllegalArgumentException("This phi is already in some basic block"); - } - TryCatchJoint oldJoint = joints.get(index); - oldJoint.block = null; - element.block = BasicBlock.this; - return joints.set(index, element); - } - - @Override - public TryCatchJoint remove(int index) { - TryCatchJoint joint = joints.remove(index); - joint.block = null; - return joint; - } - - @Override - public void clear() { - for (TryCatchJoint joint : joints) { - joint.block = null; - } - joints.clear(); - } - }; - public List getPhis() { return safePhis; } @@ -244,12 +196,6 @@ public class BasicBlock implements BasicBlockReader { } } } - for (int i = 0; i < joints.size(); ++i) { - TryCatchJoint joint = joints.get(i); - if (joint.getSource() == predecessor) { - joints.remove(i--); - } - } } private List immutableTryCatchBlocks = Collections.unmodifiableList(tryCatchBlocks); @@ -303,15 +249,12 @@ public class BasicBlock implements BasicBlockReader { return safeTryCatchBlocks; } - public List getTryCatchJoints() { - return safeJoints; + @Override + public Variable getExceptionVariable() { + return exceptionVariable; } - @Override - public List readTryCatchJoints() { - if (immutableJoints == null) { - immutableJoints = Collections.unmodifiableList(safeJoints); - } - return immutableJoints; + public void setExceptionVariable(Variable exceptionVariable) { + this.exceptionVariable = exceptionVariable; } } diff --git a/core/src/main/java/org/teavm/model/BasicBlockReader.java b/core/src/main/java/org/teavm/model/BasicBlockReader.java index 8a7f9c09b..64627dbce 100644 --- a/core/src/main/java/org/teavm/model/BasicBlockReader.java +++ b/core/src/main/java/org/teavm/model/BasicBlockReader.java @@ -33,5 +33,5 @@ public interface BasicBlockReader { List readTryCatchBlocks(); - List readTryCatchJoints(); + VariableReader getExceptionVariable(); } diff --git a/core/src/main/java/org/teavm/model/TryCatchBlock.java b/core/src/main/java/org/teavm/model/TryCatchBlock.java index 58bba408a..9ce3d8fe0 100644 --- a/core/src/main/java/org/teavm/model/TryCatchBlock.java +++ b/core/src/main/java/org/teavm/model/TryCatchBlock.java @@ -15,11 +15,64 @@ */ package org.teavm.model; +import java.util.AbstractList; +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; + + private List safeJoints = new AbstractList() { + @Override + public TryCatchJoint get(int index) { + return joints.get(index); + } + + @Override + public int size() { + return joints.size(); + } + + @Override + public void add(int index, TryCatchJoint e) { + if (e.getBlock() != null) { + throw new IllegalArgumentException("This joint is already in some basic block"); + } + e.block = TryCatchBlock.this; + joints.add(index, e); + } + + @Override + public TryCatchJoint set(int index, TryCatchJoint element) { + if (element.block != null) { + throw new IllegalArgumentException("This phi is already in some basic block"); + } + TryCatchJoint oldJoint = joints.get(index); + oldJoint.block = null; + element.block = TryCatchBlock.this; + return joints.set(index, element); + } + + @Override + public TryCatchJoint remove(int index) { + TryCatchJoint joint = joints.remove(index); + joint.block = null; + return joint; + } + + @Override + public void clear() { + for (TryCatchJoint joint : joints) { + joint.block = null; + } + joints.clear(); + } + }; @Override public BasicBlock getHandler() { @@ -39,17 +92,20 @@ public class TryCatchBlock implements TryCatchBlockReader { this.exceptionType = exceptionType; } - @Override - public Variable getExceptionVariable() { - return exceptionVariable; - } - - public void setExceptionVariable(Variable exceptionVariable) { - this.exceptionVariable = exceptionVariable; - } - @Override public BasicBlock getProtectedBlock() { return protectedBlock; } + + public List getTryCatchJoints() { + return safeJoints; + } + + @Override + public List readTryCatchJoints() { + if (immutableJoints == null) { + immutableJoints = Collections.unmodifiableList(safeJoints); + } + 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 125358947..f2c4ed38f 100644 --- a/core/src/main/java/org/teavm/model/TryCatchBlockReader.java +++ b/core/src/main/java/org/teavm/model/TryCatchBlockReader.java @@ -15,6 +15,8 @@ */ package org.teavm.model; +import java.util.List; + public interface TryCatchBlockReader { BasicBlockReader getProtectedBlock(); @@ -22,5 +24,5 @@ public interface TryCatchBlockReader { String getExceptionType(); - VariableReader getExceptionVariable(); + List readTryCatchJoints(); } diff --git a/core/src/main/java/org/teavm/model/TryCatchJoint.java b/core/src/main/java/org/teavm/model/TryCatchJoint.java index b0155f6bc..919d876f6 100644 --- a/core/src/main/java/org/teavm/model/TryCatchJoint.java +++ b/core/src/main/java/org/teavm/model/TryCatchJoint.java @@ -20,11 +20,10 @@ import java.util.Collections; import java.util.List; public class TryCatchJoint implements TryCatchJointReader { - private BasicBlock source; private List sourceVariables = new ArrayList<>(); private List readonlySourceVariables; private Variable receiver; - BasicBlock block; + TryCatchBlock block; @Override public List readSourceVariables() { @@ -47,16 +46,7 @@ public class TryCatchJoint implements TryCatchJointReader { this.receiver = receiver; } - @Override - public BasicBlock getSource() { - return source; - } - - public void setSource(BasicBlock source) { - this.source = source; - } - - public BasicBlock getBlock() { + public TryCatchBlock getBlock() { return block; } } diff --git a/core/src/main/java/org/teavm/model/TryCatchJointReader.java b/core/src/main/java/org/teavm/model/TryCatchJointReader.java index 903c0c5cc..2045d7529 100644 --- a/core/src/main/java/org/teavm/model/TryCatchJointReader.java +++ b/core/src/main/java/org/teavm/model/TryCatchJointReader.java @@ -22,7 +22,5 @@ public interface TryCatchJointReader { VariableReader getReceiver(); - BasicBlockReader getSource(); - - BasicBlockReader getBlock(); + TryCatchBlockReader getBlock(); } diff --git a/core/src/main/java/org/teavm/model/util/BasicBlockMapper.java b/core/src/main/java/org/teavm/model/util/BasicBlockMapper.java index 732b9f796..301696bf9 100644 --- a/core/src/main/java/org/teavm/model/util/BasicBlockMapper.java +++ b/core/src/main/java/org/teavm/model/util/BasicBlockMapper.java @@ -43,9 +43,7 @@ public class BasicBlockMapper implements InstructionVisitor { return; } lastInsn.acceptVisitor(this); - for (TryCatchJoint joint : block.getTryCatchJoints()) { - joint.setSource(map(joint.getSource())); - } + for (Phi phi : block.getPhis()) { for (Incoming incoming : phi.getIncomings()) { incoming.setSource(map(incoming.getSource())); 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 b417daa0d..5f1041b3c 100644 --- a/core/src/main/java/org/teavm/model/util/InstructionVariableMapper.java +++ b/core/src/main/java/org/teavm/model/util/InstructionVariableMapper.java @@ -34,10 +34,13 @@ public class InstructionVariableMapper implements InstructionVisitor { } public void apply(BasicBlock block) { + if (block.getExceptionVariable() != null) { + block.setExceptionVariable(map(block.getExceptionVariable())); + } + applyToInstructions(block); applyToPhis(block); applyToTryCatchBlocks(block); - applyToTryCatchJoints(block); } public void applyToInstructions(BasicBlock block) { @@ -57,18 +60,12 @@ public class InstructionVariableMapper implements InstructionVisitor { public void applyToTryCatchBlocks(BasicBlock block) { for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) { - if (tryCatch.getExceptionVariable() != null) { - tryCatch.setExceptionVariable(map(tryCatch.getExceptionVariable())); - } - } - } - - public void applyToTryCatchJoints(BasicBlock block) { - for (TryCatchJoint joint : block.getTryCatchJoints()) { - joint.setReceiver(map(joint.getReceiver())); - for (int i = 0; i < joint.getSourceVariables().size(); ++i) { - Variable var = joint.getSourceVariables().get(i); - joint.getSourceVariables().set(i, map(var)); + for (TryCatchJoint joint : tryCatch.getTryCatchJoints()) { + joint.setReceiver(map(joint.getReceiver())); + 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 5687d3cf2..b77da9d93 100644 --- a/core/src/main/java/org/teavm/model/util/InterferenceGraphBuilder.java +++ b/core/src/main/java/org/teavm/model/util/InterferenceGraphBuilder.java @@ -29,11 +29,11 @@ class InterferenceGraphBuilder { DefinitionExtractor defExtractor = new DefinitionExtractor(); InstructionTransitionExtractor succExtractor = new InstructionTransitionExtractor(); List> outgoings = ProgramUtils.getPhiOutputs(program); - List> outputJoints = ProgramUtils.getOutputJoints(program); Set live = new HashSet<>(128); for (int i = 0; i < program.basicBlockCount(); ++i) { BasicBlock block = program.basicBlockAt(i); block.getLastInstruction().acceptVisitor(succExtractor); + BitSet liveOut = new BitSet(program.variableCount()); for (BasicBlock succ : succExtractor.getTargets()) { liveOut.or(liveness.liveIn(succ.getIndex())); @@ -47,24 +47,20 @@ class InterferenceGraphBuilder { live.add(nodes.get(j)); } } - for (TryCatchJoint joint : outputJoints.get(i)) { - for (Variable outputVar : joint.getSourceVariables()) { - live.add(nodes.get(outputVar.getIndex())); - } - } + for (Incoming outgoing : outgoings.get(i)) { live.add(nodes.get(outgoing.getValue().getIndex())); } + for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) { - if (tryCatch.getExceptionVariable() != null) { - nodes.get(tryCatch.getExceptionVariable().getIndex()).connectAll(live); - } - } - for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) { - if (tryCatch.getExceptionVariable() != null) { - live.remove(nodes.get(tryCatch.getExceptionVariable().getIndex())); + for (TryCatchJoint joint : tryCatch.getTryCatchJoints()) { + for (Variable sourceVar : joint.getSourceVariables()) { + live.add(nodes.get(sourceVar.getIndex())); + } + live.remove(nodes.get(joint.getReceiver().getIndex())); } } + for (int j = block.getInstructions().size() - 1; j >= 0; --j) { Instruction insn = block.getInstructions().get(j); insn.acceptVisitor(useExtractor); @@ -79,11 +75,16 @@ class InterferenceGraphBuilder { live.add(nodes.get(var.getIndex())); } } + if (block.getExceptionVariable() != null) { + nodes.get(block.getExceptionVariable().getIndex()).connectAll(live); + live.remove(nodes.get(block.getExceptionVariable().getIndex())); + } if (block.getIndex() == 0) { for (int j = 0; j <= paramCount; ++j) { nodes.get(j).connectAll(live); } } + BitSet liveIn = liveness.liveIn(i); live.clear(); for (int j = 0; j < liveOut.length(); ++j) { @@ -92,16 +93,10 @@ class InterferenceGraphBuilder { } } - for (TryCatchJoint joint : block.getTryCatchJoints()) { - live.add(nodes.get(joint.getReceiver().getIndex())); - } for (Phi phi : block.getPhis()) { live.add(nodes.get(phi.getReceiver().getIndex())); } - for (TryCatchJoint joint : block.getTryCatchJoints()) { - nodes.get(joint.getReceiver().getIndex()).connectAll(live); - } for (Phi phi : block.getPhis()) { nodes.get(phi.getReceiver().getIndex()).connectAll(live); } 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 f44b141eb..5a736c8d0 100644 --- a/core/src/main/java/org/teavm/model/util/ListingBuilder.java +++ b/core/src/main/java/org/teavm/model/util/ListingBuilder.java @@ -48,12 +48,10 @@ public class ListingBuilder { continue; } - for (TryCatchJointReader joint : block.readTryCatchJoints()) { - sb.append(" @").append(joint.getReceiver().getIndex()).append(" := e-phi("); - sb.append(joint.readSourceVariables().stream().map(sourceVar -> "@" + sourceVar.getIndex()) - .collect(Collectors.joining(", "))); - sb.append(") from $").append(joint.getSource().getIndex()).append("\n"); + if (block.getExceptionVariable() != null) { + sb.append("@").append(block.getExceptionVariable().getIndex()).append(" = exception"); } + for (PhiReader phi : block.readPhis()) { sb.append(prefix).append(" "); sb.append("@").append(phi.getReceiver().getIndex()).append(" := "); @@ -81,10 +79,15 @@ public class ListingBuilder { sb.append(prefix).append(" ").append(insnSb).append("\n"); } for (TryCatchBlockReader tryCatch : block.readTryCatchBlocks()) { - sb.append(prefix).append(" catch ").append(tryCatch.getExceptionType()).append(" @") - .append(tryCatch.getExceptionVariable().getIndex()) + sb.append(prefix).append(" catch ").append(tryCatch.getExceptionType()) .append(" -> $").append(tryCatch.getHandler().getIndex()); sb.append("\n"); + for (TryCatchJointReader joint : tryCatch.readTryCatchJoints()) { + sb.append(" @").append(joint.getReceiver().getIndex()).append(" := e-phi("); + 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 e73af3fd2..c6ebb7db9 100644 --- a/core/src/main/java/org/teavm/model/util/LivenessAnalyzer.java +++ b/core/src/main/java/org/teavm/model/util/LivenessAnalyzer.java @@ -47,6 +47,11 @@ public class LivenessAnalyzer { int[] definitions = new int[program.variableCount()]; for (int i = 0; i < program.basicBlockCount(); ++i) { BasicBlock block = program.basicBlockAt(i); + + if (block.getExceptionVariable() != null) { + definitions[block.getExceptionVariable().getIndex()] = i; + } + for (Instruction insn : block.getInstructions()) { insn.acceptVisitor(usageExtractor); IntSet usedVars = new IntOpenHashSet(); @@ -64,21 +69,19 @@ public class LivenessAnalyzer { } } } + for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) { - if (tryCatch.getExceptionVariable() != null) { - definitions[tryCatch.getExceptionVariable().getIndex()] = i; + for (TryCatchJoint joint : tryCatch.getTryCatchJoints()) { + definitions[joint.getReceiver().getIndex()] = i; + for (Variable sourceVar : joint.getSourceVariables()) { + Task task = new Task(); + task.block = i; + task.var = sourceVar.getIndex(); + stack.push(task); + } } } - for (TryCatchJoint joint : block.getTryCatchJoints()) { - definitions[joint.getReceiver().getIndex()] = i; - for (Variable sourceVar : joint.getSourceVariables()) { - Task task = new Task(); - task.block = joint.getSource().getIndex(); - task.var = sourceVar.getIndex(); - stack.push(task); - } - } for (Phi phi : block.getPhis()) { definitions[phi.getReceiver().getIndex()] = i; for (Incoming incoming : phi.getIncomings()) { 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 5564fe954..b48c273e4 100644 --- a/core/src/main/java/org/teavm/model/util/PhiUpdater.java +++ b/core/src/main/java/org/teavm/model/util/PhiUpdater.java @@ -17,7 +17,6 @@ package org.teavm.model.util; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -81,7 +80,6 @@ public class PhiUpdater { private int[][] phiIndexMap; private List>> jointMap = new ArrayList<>(); private List> synthesizedPhis = new ArrayList<>(); - private List> synthesizedJoints = new ArrayList<>(); private boolean[] usedDefinitions; public void updatePhis(Program program, Variable[] arguments) { @@ -109,10 +107,8 @@ public class PhiUpdater { domFrontiers = GraphUtils.findDominanceFrontiers(cfg, domTree); synthesizedPhis.clear(); - synthesizedJoints.clear(); for (int i = 0; i < program.basicBlockCount(); ++i) { synthesizedPhis.add(new ArrayList<>()); - synthesizedJoints.add(new ArrayList<>()); } estimatePhis(); renameVariables(); @@ -122,12 +118,15 @@ public class PhiUpdater { DefinitionExtractor definitionExtractor = new DefinitionExtractor(); for (int i = 0; i < program.basicBlockCount(); ++i) { currentBlock = program.basicBlockAt(i); + + if (currentBlock.getExceptionVariable() != null) { + markAssignment(currentBlock.getExceptionVariable()); + } + for (Phi phi : currentBlock.getPhis()) { markAssignment(phi.getReceiver()); } - for (TryCatchJoint joint : currentBlock.getTryCatchJoints()) { - markAssignment(joint.getReceiver()); - } + for (Instruction insn : currentBlock.getInstructions()) { insn.acceptVisitor(definitionExtractor); for (Variable var : definitionExtractor.getDefinedVariables()) { @@ -135,7 +134,9 @@ public class PhiUpdater { } } for (TryCatchBlock tryCatch : currentBlock.getTryCatchBlocks()) { - markAssignment(tryCatch.getExceptionVariable()); + for (TryCatchJoint joint : tryCatch.getTryCatchJoints()) { + markAssignment(joint.getReceiver()); + } } } } @@ -143,6 +144,7 @@ public class PhiUpdater { private static class Task { Variable[] variables; BasicBlock block; + TryCatchBlock tryCatch; } private void renameVariables() { @@ -160,106 +162,66 @@ public class PhiUpdater { } List> phiOutputs = ProgramUtils.getPhiOutputs(program); - List> existingOutputJoints = ProgramUtils.getOutputJoints(program); - boolean[] processed = new boolean[program.basicBlockCount()]; while (head > 0) { Task task = stack[--head]; - currentBlock = task.block; - int index = currentBlock.getIndex(); - if (processed[index]) { - continue; - } - processed[index] = true; - variableMap = Arrays.copyOf(task.variables, task.variables.length); - for (Phi phi : synthesizedPhis.get(index)) { - Variable var = program.createVariable(); - var.getDebugNames().addAll(phi.getReceiver().getDebugNames()); - propagateToTryCatch(phi.getReceiver(), var, null); - variableMap[phi.getReceiver().getIndex()] = var; - phi.setReceiver(var); - } - for (TryCatchJoint joint : synthesizedJoints.get(index)) { - Variable var = program.createVariable(); - var.getDebugNames().addAll(joint.getReceiver().getDebugNames()); - variableMap[joint.getReceiver().getIndex()] = var; - joint.setReceiver(var); - } - for (Phi phi : currentBlock.getPhis()) { - phi.setReceiver(define(phi.getReceiver())); - } - for (TryCatchJoint joint : currentBlock.getTryCatchJoints()) { - joint.setReceiver(define(joint.getReceiver())); - } - - for (Instruction insn : currentBlock.getInstructions()) { - insn.acceptVisitor(consumer); - } - - Map> tryCatchVariableMap = new HashMap<>(); - for (TryCatchBlock tryCatch : currentBlock.getTryCatchBlocks()) { - Map catchVariableMap = new HashMap<>(); - tryCatchVariableMap.put(tryCatch.getHandler(), catchVariableMap); - Variable var = tryCatch.getExceptionVariable(); - if (var != null) { - Variable newVar = introduce(var); - tryCatch.setExceptionVariable(newVar); - catchVariableMap.put(var, newVar); + if (task.tryCatch != null) { + TryCatchBlock tryCatch = task.tryCatch; + if (domTree.dominates(tryCatch.getProtectedBlock().getIndex(), tryCatch.getHandler().getIndex())) { + Task next = new Task(); + next.block = tryCatch.getProtectedBlock(); + next.variables = Arrays.copyOf(variableMap, variableMap.length); + for (TryCatchJoint joint : tryCatch.getTryCatchJoints()) { + Variable mappedReceiver = introduce(joint.getReceiver()); + for (Variable sourceVariable : joint.getSourceVariables()) { + next.variables[sourceVariable.getIndex()] = mappedReceiver; + } + next.variables[joint.getReceiver().getIndex()] = mappedReceiver; + for (int i = 0; i < joint.getSourceVariables().size(); ++i) { + Variable var = joint.getSourceVariables().get(i); + joint.getSourceVariables().set(i, use(var)); + } + joint.setReceiver(mappedReceiver); + } + stack[head++] = next; } - } + renameOutgoingPhis(tryCatch.getHandler().getIndex()); + } else { + currentBlock = task.block; + int index = currentBlock.getIndex(); + variableMap = Arrays.copyOf(task.variables, task.variables.length); - for (Incoming output : phiOutputs.get(index)) { - Variable var = output.getValue(); - Variable exceptionVar = tryCatchVariableMap - .getOrDefault(output.getPhi().getBasicBlock(), Collections.emptyMap()) - .get(var); - output.setValue(exceptionVar != null ? exceptionVar : use(var)); - } - for (TryCatchJoint joint : existingOutputJoints.get(index)) { - for (int i = 0; i < joint.getSourceVariables().size(); ++i) { - Variable var = joint.getSourceVariables().get(i); - Variable exceptionVar = tryCatchVariableMap - .getOrDefault(joint.getBlock(), Collections.emptyMap()) - .get(var); - joint.getSourceVariables().set(i, exceptionVar != null ? exceptionVar : use(var)); + for (Phi phi : synthesizedPhis.get(index)) { + Variable var = program.createVariable(); + var.getDebugNames().addAll(phi.getReceiver().getDebugNames()); + propagateToTryCatch(phi.getReceiver(), var, null); + variableMap[phi.getReceiver().getIndex()] = var; + phi.setReceiver(var); + } + for (Phi phi : currentBlock.getPhis()) { + phi.setReceiver(define(phi.getReceiver())); } - } - int[] successors = domGraph.outgoingEdges(index); - for (int successor : successors) { - Task next = new Task(); - next.variables = Arrays.copyOf(variableMap, variableMap.length); - next.block = program.basicBlockAt(successor); - Map catchVariableMap = tryCatchVariableMap.get(next.block); - if (catchVariableMap != null) { - for (Map.Entry entry : catchVariableMap.entrySet()) { - next.variables[entry.getKey().getIndex()] = entry.getValue(); - } + for (Instruction insn : currentBlock.getInstructions()) { + insn.acceptVisitor(consumer); } - stack[head++] = next; - } - successors = cfg.outgoingEdges(index); - for (int successor : successors) { - int[] phiIndexes = phiIndexMap[successor]; - List phis = synthesizedPhis.get(successor); - Map catchVariableMap = tryCatchVariableMap.get(program.basicBlockAt(successor)); - for (int j = 0; j < phis.size(); ++j) { - Phi phi = phis.get(j); - Variable var = null; - if (catchVariableMap != null) { - var = catchVariableMap.get(program.variableAt(phiIndexes[j])); - } - if (var == null) { - var = variableMap[phiIndexes[j]]; - } - if (var != null) { - Incoming incoming = new Incoming(); - incoming.setSource(currentBlock); - incoming.setValue(var); - phi.getIncomings().add(incoming); - phi.getReceiver().getDebugNames().addAll(var.getDebugNames()); - } + + for (Incoming output : phiOutputs.get(index)) { + Variable var = output.getValue(); + output.setValue(use(var)); + } + + int[] successors = domGraph.outgoingEdges(index); + for (int successor : successors) { + Task next = new Task(); + next.variables = Arrays.copyOf(variableMap, variableMap.length); + next.block = program.basicBlockAt(successor); + stack[head++] = next; + } + successors = cfg.outgoingEdges(index); + for (int successor : successors) { + renameOutgoingPhis(successor); } } } @@ -270,18 +232,27 @@ public class PhiUpdater { program.basicBlockAt(i).getPhis().add(phi); } } - for (TryCatchJoint joint : synthesizedJoints.get(i)) { - if (!joint.getSourceVariables().isEmpty()) { - program.basicBlockAt(i).getTryCatchJoints().add(joint); - } + } + } + + private void renameOutgoingPhis(int 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]]; + if (var != null) { + Incoming incoming = new Incoming(); + incoming.setSource(currentBlock); + incoming.setValue(var); + phi.getIncomings().add(incoming); + phi.getReceiver().getDebugNames().addAll(var.getDebugNames()); } } } private void markAssignment(Variable var) { - boolean fromHandler = currentBlock.getTryCatchBlocks().stream().anyMatch( - tryCatch -> tryCatch.getExceptionVariable() == var); - BasicBlock[] worklist = new BasicBlock[program.basicBlockCount() * 4]; int head = 0; worklist[head++] = currentBlock; @@ -294,9 +265,6 @@ public class PhiUpdater { for (int frontier : frontiers) { BasicBlock frontierBlock = program.basicBlockAt(frontier); - if (!fromHandler && isExceptionHandler(block, frontierBlock)) { - continue; - } boolean exists = frontierBlock.getPhis().stream() .flatMap(phi -> phi.getIncomings().stream()) @@ -315,56 +283,9 @@ public class PhiUpdater { worklist[head++] = frontierBlock; } } - - if (!fromHandler) { - for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) { - if (tryCatch.getExceptionVariable() == var || !hasReassignmentTo(block, var)) { - continue; - } - BasicBlock frontierBlock = tryCatch.getHandler(); - int frontier = frontierBlock.getIndex(); - boolean exists = frontierBlock.getTryCatchJoints().stream() - .anyMatch(joint -> joint.getSourceVariables().contains(var) && joint.getSource() == block); - if (exists) { - continue; - } - - Map jointSubmap = jointMap.get(frontier).get(block); - if (jointSubmap == null) { - jointSubmap = new HashMap<>(); - jointMap.get(frontier).put(block, jointSubmap); - } - TryCatchJoint joint = jointSubmap.get(var); - if (joint == null) { - joint = new TryCatchJoint(); - joint.setSource(block); - joint.setReceiver(var); - synthesizedJoints.get(frontier).add(joint); - jointSubmap.put(var, joint); - worklist[head++] = frontierBlock; - } - } - } } } - private boolean hasReassignmentTo(BasicBlock block, Variable var) { - DefinitionExtractor defExtractor = new DefinitionExtractor(); - for (int i = 0; i < block.instructionCount(); ++i) { - block.getInstructions().get(i).acceptVisitor(defExtractor); - for (Variable definedVar : defExtractor.getDefinedVariables()) { - if (definedVar == var) { - return true; - } - } - } - return false; - } - - private boolean isExceptionHandler(BasicBlock source, BasicBlock target) { - return source.getTryCatchBlocks().stream().anyMatch(tryCatch -> tryCatch.getHandler() == target); - } - private Variable define(Variable var) { Variable old = variableMap[var.getIndex()]; Variable original = var; @@ -376,9 +297,10 @@ public class PhiUpdater { private void propagateToTryCatch(Variable original, Variable var, Variable old) { for (TryCatchBlock tryCatch : currentBlock.getTryCatchBlocks()) { - if (tryCatch.getExceptionVariable() == original) { + if (tryCatch.getHandler().getExceptionVariable() == original) { continue; } + Map joints = jointMap.get(tryCatch.getHandler().getIndex()).get(currentBlock); if (joints == null) { continue; 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 fa2e49d3f..89af3142a 100644 --- a/core/src/main/java/org/teavm/model/util/ProgramUtils.java +++ b/core/src/main/java/org/teavm/model/util/ProgramUtils.java @@ -78,10 +78,12 @@ public final class ProgramUtils { for (int i = 0; i < program.basicBlockCount(); ++i) { BasicBlockReader block = program.basicBlockAt(i); BasicBlock blockCopy = copy.basicBlockAt(i); + if (block.getExceptionVariable() != null) { + blockCopy.setExceptionVariable(copy.variableAt(block.getExceptionVariable().getIndex())); + } blockCopy.getInstructions().addAll(copyInstructions(block, 0, block.instructionCount(), copy)); blockCopy.getPhis().addAll(copyPhis(block, copy)); blockCopy.getTryCatchBlocks().addAll(copyTryCatches(block, copy)); - blockCopy.getTryCatchJoints().addAll(copyTryCatchJoints(block, copy)); } return copy; } @@ -117,18 +119,17 @@ public final class ProgramUtils { for (TryCatchBlockReader tryCatch : block.readTryCatchBlocks()) { TryCatchBlock tryCatchCopy = new TryCatchBlock(); tryCatchCopy.setExceptionType(tryCatch.getExceptionType()); - tryCatchCopy.setExceptionVariable(target.variableAt(tryCatch.getExceptionVariable().getIndex())); tryCatchCopy.setHandler(target.basicBlockAt(tryCatch.getHandler().getIndex())); + tryCatchCopy.getTryCatchJoints().addAll(copyTryCatchJoints(tryCatch, target)); result.add(tryCatchCopy); } return result; } - public static List copyTryCatchJoints(BasicBlockReader block, Program target) { + public static List copyTryCatchJoints(TryCatchBlockReader block, Program target) { List result = new ArrayList<>(); for (TryCatchJointReader joint : block.readTryCatchJoints()) { TryCatchJoint jointCopy = new TryCatchJoint(); - jointCopy.setSource(target.basicBlockAt(joint.getSource().getIndex())); jointCopy.setReceiver(target.variableAt(joint.getReceiver().getIndex())); for (VariableReader sourceVar : joint.readSourceVariables()) { jointCopy.getSourceVariables().add(target.variableAt(sourceVar.getIndex())); @@ -156,43 +157,31 @@ public final class ProgramUtils { return outputs; } - public static List> getOutputJoints(Program program) { - List> outputs = new ArrayList<>(program.basicBlockCount()); - for (int i = 0; i < program.basicBlockCount(); ++i) { - outputs.add(new ArrayList<>()); - } - - for (int i = 0; i < program.basicBlockCount(); ++i) { - BasicBlock block = program.basicBlockAt(i); - for (TryCatchJoint joint : block.getTryCatchJoints()) { - outputs.get(joint.getSource().getIndex()).add(joint); - } - } - - return outputs; - } - public static BasicBlock[] getVariableDefinitionPlaces(Program program) { BasicBlock[] places = new BasicBlock[program.variableCount()]; DefinitionExtractor defExtractor = new DefinitionExtractor(); for (int i = 0; i < program.basicBlockCount(); ++i) { BasicBlock block = program.basicBlockAt(i); + + Variable exceptionVar = block.getExceptionVariable(); + if (exceptionVar != null) { + places[exceptionVar.getIndex()] = block; + } + for (Phi phi : block.getPhis()) { places[phi.getReceiver().getIndex()] = block; } - for (TryCatchJoint joint : block.getTryCatchJoints()) { - places[joint.getReceiver().getIndex()] = block; - } + for (Instruction insn : block.getInstructions()) { insn.acceptVisitor(defExtractor); for (Variable var : defExtractor.getDefinedVariables()) { places[var.getIndex()] = block; } } + for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) { - Variable var = tryCatch.getExceptionVariable(); - if (var != null) { - places[var.getIndex()] = tryCatch.getHandler(); + for (TryCatchJoint joint : tryCatch.getTryCatchJoints()) { + places[joint.getReceiver().getIndex()] = block; } } } diff --git a/core/src/main/java/org/teavm/model/util/RegisterAllocator.java b/core/src/main/java/org/teavm/model/util/RegisterAllocator.java index 833da95ee..70305e3ac 100644 --- a/core/src/main/java/org/teavm/model/util/RegisterAllocator.java +++ b/core/src/main/java/org/teavm/model/util/RegisterAllocator.java @@ -33,6 +33,7 @@ import org.teavm.model.MethodReference; import org.teavm.model.Phi; import org.teavm.model.Program; import org.teavm.model.ProgramReader; +import org.teavm.model.TryCatchBlock; import org.teavm.model.TryCatchJoint; import org.teavm.model.Variable; import org.teavm.model.instructions.AssignInstruction; @@ -77,7 +78,9 @@ public class RegisterAllocator { for (int i = 0; i < program.basicBlockCount(); ++i) { program.basicBlockAt(i).getPhis().clear(); - program.basicBlockAt(i).getTryCatchJoints().clear(); + for (TryCatchBlock tryCatch : program.basicBlockAt(i).getTryCatchBlocks()) { + tryCatch.getTryCatchJoints().clear(); + } } } @@ -116,14 +119,16 @@ public class RegisterAllocator { private void insertJointArgumentsCopies(Program program) { for (int i = 0; i < program.basicBlockCount(); ++i) { BasicBlock block = program.basicBlockAt(i); - block.getTryCatchJoints().forEach(this::insertCopy); + for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) { + tryCatch.getTryCatchJoints().forEach(this::insertCopy); + } } } private void insertCopy(TryCatchJoint joint) { Set variableSet = new HashSet<>(joint.getSourceVariables()); - BasicBlock block = joint.getSource(); + BasicBlock block = joint.getBlock().getProtectedBlock(); DefinitionExtractor defExtractor = new DefinitionExtractor(); for (int i = block.getInstructions().size() - 1; i >= 0; --i) { Instruction insn = block.getInstructions().get(i); @@ -151,16 +156,12 @@ public class RegisterAllocator { Map blockMap = new HashMap<>(); for (Phi phi : program.basicBlockAt(i).getPhis()) { for (Incoming incoming : phi.getIncomings()) { - if (!isExceptionHandler(incoming)) { - insertCopy(incoming, blockMap); - } + insertCopy(incoming, blockMap); } } for (Phi phi : program.basicBlockAt(i).getPhis()) { for (Incoming incoming : phi.getIncomings()) { - if (!isExceptionHandler(incoming)) { - insertCopy(incoming, blockMap); - } + insertCopy(incoming, blockMap); } } } @@ -194,11 +195,6 @@ public class RegisterAllocator { incoming.setValue(copyInstruction.getReceiver()); } - private boolean isExceptionHandler(Incoming incoming) { - return incoming.getSource().getTryCatchJoints().stream().anyMatch( - joint -> joint.getReceiver() == incoming.getValue()); - } - private void removeRedundantCopies(Program program, List interferenceGraph, DisjointSet congruenceClasses) { for (int i = 0; i < program.basicBlockCount(); ++i) { @@ -301,9 +297,11 @@ public class RegisterAllocator { classes.union(phi.getReceiver().getIndex(), incoming.getValue().getIndex()); } } - for (TryCatchJoint joint : block.getTryCatchJoints()) { - for (Variable sourceVar : joint.getSourceVariables()) { - classes.union(sourceVar.getIndex(), joint.getReceiver().getIndex()); + for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) { + for (TryCatchJoint joint : tryCatch.getTryCatchJoints()) { + for (Variable sourceVar : joint.getSourceVariables()) { + classes.union(sourceVar.getIndex(), joint.getReceiver().getIndex()); + } } } } diff --git a/core/src/main/java/org/teavm/model/util/TypeInferer.java b/core/src/main/java/org/teavm/model/util/TypeInferer.java index 0c79aa76a..c62564997 100644 --- a/core/src/main/java/org/teavm/model/util/TypeInferer.java +++ b/core/src/main/java/org/teavm/model/util/TypeInferer.java @@ -22,10 +22,6 @@ import org.teavm.common.IntegerStack; import org.teavm.model.*; import org.teavm.model.instructions.*; -/** - * - * @author Alexey Andreev - */ public class TypeInferer { VariableType[] types; GraphBuilder builder; @@ -45,20 +41,23 @@ public class TypeInferer { arrayElemBuilder = new GraphBuilder(sz); for (int i = 0; i < program.basicBlockCount(); ++i) { BasicBlockReader block = program.basicBlockAt(i); + + if (block.getExceptionVariable() != null) { + types[block.getExceptionVariable().getIndex()] = VariableType.OBJECT; + } + block.readAllInstructions(reader); for (PhiReader phi : block.readPhis()) { for (IncomingReader incoming : phi.readIncomings()) { builder.addEdge(incoming.getValue().getIndex(), phi.getReceiver().getIndex()); } } - for (TryCatchJointReader joint : block.readTryCatchJoints()) { - for (VariableReader sourceVar : joint.readSourceVariables()) { - builder.addEdge(sourceVar.getIndex(), joint.getReceiver().getIndex()); - } - } + for (TryCatchBlockReader tryCatch : block.readTryCatchBlocks()) { - if (tryCatch.getExceptionVariable() != null) { - types[tryCatch.getExceptionVariable().getIndex()] = VariableType.OBJECT; + for (TryCatchJointReader joint : tryCatch.readTryCatchJoints()) { + for (VariableReader sourceVar : joint.readSourceVariables()) { + builder.addEdge(sourceVar.getIndex(), joint.getReceiver().getIndex()); + } } } } diff --git a/core/src/main/java/org/teavm/optimization/EmptyBlockElimination.java b/core/src/main/java/org/teavm/optimization/EmptyBlockElimination.java index 7bac6a37c..77355c90b 100644 --- a/core/src/main/java/org/teavm/optimization/EmptyBlockElimination.java +++ b/core/src/main/java/org/teavm/optimization/EmptyBlockElimination.java @@ -32,8 +32,8 @@ public class EmptyBlockElimination implements MethodOptimization { int lastNonEmpty = program.basicBlockCount() - 1; for (int i = program.basicBlockCount() - 2; i > 0; --i) { BasicBlock block = program.basicBlockAt(i); - if (block.getPhis().isEmpty() && block.getTryCatchJoints().isEmpty() - && block.getInstructions().size() == 1 && block.getLastInstruction() instanceof JumpInstruction) { + if (block.getPhis().isEmpty() && block.getInstructions().size() == 1 + && block.getLastInstruction() instanceof JumpInstruction) { JumpInstruction insn = (JumpInstruction) block.getLastInstruction(); if (insn.getTarget().getIndex() == i + 1) { blockMapping[i] = lastNonEmpty; diff --git a/core/src/main/java/org/teavm/optimization/GlobalValueNumbering.java b/core/src/main/java/org/teavm/optimization/GlobalValueNumbering.java index b3f27af62..0da23278e 100644 --- a/core/src/main/java/org/teavm/optimization/GlobalValueNumbering.java +++ b/core/src/main/java/org/teavm/optimization/GlobalValueNumbering.java @@ -54,7 +54,6 @@ public class GlobalValueNumbering implements MethodOptimization { map[i] = i; } List> outgoings = ProgramUtils.getPhiOutputs(program); - List> outputJoints = ProgramUtils.getOutputJoints(program); int[] stack = new int[cfg.size() * 2]; int top = 0; @@ -89,6 +88,12 @@ public class GlobalValueNumbering implements MethodOptimization { block.getPhis().remove(i--); } }*/ + + if (block.getExceptionVariable() != null) { + int var = map[block.getExceptionVariable().getIndex()]; + block.setExceptionVariable(program.variableAt(var)); + } + for (int i = 0; i < block.getInstructions().size(); ++i) { evaluatedConstant = null; Instruction currentInsn = block.getInstructions().get(i); @@ -127,22 +132,19 @@ public class GlobalValueNumbering implements MethodOptimization { } } } - for (TryCatchJoint joint : outputJoints.get(v)) { - for (int i = 0; i < joint.getSourceVariables().size(); ++i) { - int sourceVar = map[joint.getSourceVariables().get(i).getIndex()]; - joint.getSourceVariables().set(i, program.variableAt(sourceVar)); + for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) { + for (TryCatchJoint joint : tryCatch.getTryCatchJoints()) { + for (int i = 0; i < joint.getSourceVariables().size(); ++i) { + int sourceVar = map[joint.getSourceVariables().get(i).getIndex()]; + joint.getSourceVariables().set(i, program.variableAt(sourceVar)); + } } } for (Incoming incoming : outgoings.get(v)) { int value = map[incoming.getValue().getIndex()]; incoming.setValue(program.variableAt(value)); } - for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) { - 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/Inlining.java b/core/src/main/java/org/teavm/optimization/Inlining.java index 0135d2af5..20273cd5e 100644 --- a/core/src/main/java/org/teavm/optimization/Inlining.java +++ b/core/src/main/java/org/teavm/optimization/Inlining.java @@ -166,6 +166,10 @@ public class Inlining { } private void copyInlinedBlock(BasicBlock source, BasicBlock target) { + if (source.getExceptionVariable() != null) { + target.setExceptionVariable(source.getExceptionVariable()); + } + InstructionCopyReader insnCopier = new InstructionCopyReader(target.getProgram()); for (int i = 0; i < source.instructionCount(); ++i) { source.readInstruction(i, insnCopier); @@ -190,18 +194,15 @@ public class Inlining { TryCatchBlock tryCatchCopy = new TryCatchBlock(); int handler = tryCatch.getHandler().getIndex(); tryCatchCopy.setExceptionType(tryCatch.getExceptionType()); - tryCatchCopy.setExceptionVariable(tryCatch.getExceptionVariable()); tryCatchCopy.setHandler(target.getProgram().basicBlockAt(handler)); target.getTryCatchBlocks().add(tryCatchCopy); - } - for (TryCatchJoint joint : source.getTryCatchJoints()) { - TryCatchJoint jointCopy = new TryCatchJoint(); - jointCopy.setReceiver(joint.getReceiver()); - jointCopy.getSourceVariables().addAll(joint.getSourceVariables()); - int sourceIndex = joint.getSource().getIndex(); - jointCopy.setSource(target.getProgram().basicBlockAt(sourceIndex)); - target.getTryCatchJoints().add(joint); + for (TryCatchJoint joint : tryCatch.getTryCatchJoints()) { + TryCatchJoint jointCopy = new TryCatchJoint(); + jointCopy.setReceiver(joint.getReceiver()); + jointCopy.getSourceVariables().addAll(joint.getSourceVariables()); + tryCatchCopy.getTryCatchJoints().add(joint); + } } } @@ -211,18 +212,6 @@ public class Inlining { TryCatchBlock tryCatchCopy = new TryCatchBlock(); tryCatchCopy.setExceptionType(tryCatch.getExceptionType()); tryCatchCopy.setHandler(tryCatch.getHandler()); - tryCatchCopy.setExceptionVariable(source.getProgram().createVariable()); - List handlerIncomings = tryCatch.getHandler().getPhis().stream() - .flatMap(phi -> phi.getIncomings().stream()) - .filter(incoming -> incoming.getValue() == tryCatch.getExceptionVariable() - && incoming.getSource() == source) - .collect(Collectors.toList()); - for (Incoming incoming : handlerIncomings) { - Incoming incomingCopy = new Incoming(); - incomingCopy.setValue(tryCatchCopy.getExceptionVariable()); - incomingCopy.setSource(target); - incoming.getPhi().getIncomings().add(incomingCopy); - } copiedTryCatches.add(tryCatchCopy); } target.getTryCatchBlocks().addAll(copiedTryCatches); diff --git a/core/src/main/java/org/teavm/optimization/LoopInversionImpl.java b/core/src/main/java/org/teavm/optimization/LoopInversionImpl.java index 2aa2ba880..bedd5843e 100644 --- a/core/src/main/java/org/teavm/optimization/LoopInversionImpl.java +++ b/core/src/main/java/org/teavm/optimization/LoopInversionImpl.java @@ -317,6 +317,9 @@ class LoopInversionImpl { for (int node : copiedNodes.keys().toArray()) { BasicBlock sourceBlock = program.basicBlockAt(node); BasicBlock targetBlock = program.basicBlockAt(copiedNodes.get(node)); + + targetBlock.setExceptionVariable(sourceBlock.getExceptionVariable()); + copier.resetLocation(); for (int i = 0; i < sourceBlock.instructionCount(); ++i) { sourceBlock.readInstruction(i, copier); @@ -342,18 +345,15 @@ class LoopInversionImpl { TryCatchBlock tryCatchCopy = new TryCatchBlock(); int handler = tryCatch.getHandler().getIndex(); tryCatchCopy.setExceptionType(tryCatch.getExceptionType()); - tryCatchCopy.setExceptionVariable(tryCatch.getExceptionVariable()); tryCatchCopy.setHandler(program.basicBlockAt(copiedNodes.getOrDefault(handler, handler))); targetBlock.getTryCatchBlocks().add(tryCatchCopy); - } - for (TryCatchJoint joint : sourceBlock.getTryCatchJoints()) { - TryCatchJoint jointCopy = new TryCatchJoint(); - jointCopy.setReceiver(joint.getReceiver()); - jointCopy.getSourceVariables().addAll(joint.getSourceVariables()); - int source = joint.getSource().getIndex(); - jointCopy.setSource(program.basicBlockAt(copiedNodes.getOrDefault(source, source))); - targetBlock.getTryCatchJoints().add(joint); + for (TryCatchJoint joint : tryCatch.getTryCatchJoints()) { + TryCatchJoint jointCopy = new TryCatchJoint(); + jointCopy.setReceiver(joint.getReceiver()); + jointCopy.getSourceVariables().addAll(joint.getSourceVariables()); + tryCatchCopy.getTryCatchJoints().add(joint); + } } } diff --git a/core/src/main/java/org/teavm/optimization/UnusedVariableElimination.java b/core/src/main/java/org/teavm/optimization/UnusedVariableElimination.java index 5366d96da..01cd5fb50 100644 --- a/core/src/main/java/org/teavm/optimization/UnusedVariableElimination.java +++ b/core/src/main/java/org/teavm/optimization/UnusedVariableElimination.java @@ -60,12 +60,16 @@ public class UnusedVariableElimination implements MethodOptimization { block.getInstructions().remove(j--); } } - for (int j = 0; j < block.getTryCatchJoints().size(); ++j) { - TryCatchJoint joint = block.getTryCatchJoints().get(j); - if (!used[joint.getReceiver().getIndex()]) { - block.getTryCatchJoints().remove(j--); + + for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) { + for (int j = 0; j < tryCatch.getTryCatchJoints().size(); ++j) { + TryCatchJoint joint = tryCatch.getTryCatchJoints().get(j); + if (!used[joint.getReceiver().getIndex()]) { + tryCatch.getTryCatchJoints().remove(j--); + } } } + for (int j = 0; j < block.getPhis().size(); ++j) { Phi phi = block.getPhis().get(j); if (!used[phi.getReceiver().getIndex()]) { diff --git a/core/src/main/java/org/teavm/optimization/VariableUsageGraphBuilder.java b/core/src/main/java/org/teavm/optimization/VariableUsageGraphBuilder.java index 2d640a822..3e58eaba8 100644 --- a/core/src/main/java/org/teavm/optimization/VariableUsageGraphBuilder.java +++ b/core/src/main/java/org/teavm/optimization/VariableUsageGraphBuilder.java @@ -37,9 +37,11 @@ public final class VariableUsageGraphBuilder { builder.addEdge(incoming.getValue().getIndex(), phi.getReceiver().getIndex()); } } - for (TryCatchJoint joint : block.getTryCatchJoints()) { - for (Variable sourceVar : joint.getSourceVariables()) { - builder.addEdge(sourceVar.getIndex(), joint.getReceiver().getIndex()); + for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) { + for (TryCatchJoint joint : tryCatch.getTryCatchJoints()) { + for (Variable sourceVar : joint.getSourceVariables()) { + builder.addEdge(sourceVar.getIndex(), joint.getReceiver().getIndex()); + } } } } diff --git a/core/src/main/java/org/teavm/parsing/ProgramParser.java b/core/src/main/java/org/teavm/parsing/ProgramParser.java index 19c41bd65..73a0c18be 100644 --- a/core/src/main/java/org/teavm/parsing/ProgramParser.java +++ b/core/src/main/java/org/teavm/parsing/ProgramParser.java @@ -240,6 +240,7 @@ public class ProgramParser { workStack.push(new Step(index, next)); } } + for (Object obj : method.tryCatchBlocks) { TryCatchBlockNode tryCatchNode = (TryCatchBlockNode) obj; if (tryCatchNode.start == tryCatchNode.handler) { @@ -257,7 +258,7 @@ public class ProgramParser { tryCatch.setExceptionType(tryCatchNode.type.replace('/', '.')); } tryCatch.setHandler(getBasicBlock(labelIndexes.get(tryCatchNode.handler.getLabel()))); - tryCatch.setExceptionVariable(getVariable(minLocal + method.maxLocals)); + tryCatch.getHandler().setExceptionVariable(program.variableAt(minLocal + method.maxLocals)); block.getTryCatchBlocks().add(tryCatch); } } diff --git a/metaprogramming/impl/src/main/java/org/teavm/metaprogramming/impl/AliasFinder.java b/metaprogramming/impl/src/main/java/org/teavm/metaprogramming/impl/AliasFinder.java index 1c14b2588..1e7303340 100644 --- a/metaprogramming/impl/src/main/java/org/teavm/metaprogramming/impl/AliasFinder.java +++ b/metaprogramming/impl/src/main/java/org/teavm/metaprogramming/impl/AliasFinder.java @@ -29,6 +29,7 @@ import org.teavm.model.MethodReference; import org.teavm.model.PhiReader; import org.teavm.model.ProgramReader; import org.teavm.model.RuntimeConstant; +import org.teavm.model.TryCatchBlockReader; import org.teavm.model.TryCatchJointReader; import org.teavm.model.ValueType; import org.teavm.model.VariableReader; @@ -65,12 +66,14 @@ class AliasFinder { set.union(inputs.iterator().next(), phi.getReceiver().getIndex()); } } - for (TryCatchJointReader joint : block.readTryCatchJoints()) { - Set inputs = joint.readSourceVariables().stream() - .map(sourceVar -> sourceVar.getIndex()) - .collect(Collectors.toSet()); - if (inputs.size() == 1) { - set.union(inputs.iterator().next(), joint.getReceiver().getIndex()); + for (TryCatchBlockReader tryCatch : block.readTryCatchBlocks()) { + for (TryCatchJointReader joint : tryCatch.readTryCatchJoints()) { + Set inputs = joint.readSourceVariables().stream() + .map(sourceVar -> sourceVar.getIndex()) + .collect(Collectors.toSet()); + if (inputs.size() == 1) { + set.union(inputs.iterator().next(), joint.getReceiver().getIndex()); + } } } } diff --git a/metaprogramming/impl/src/main/java/org/teavm/metaprogramming/impl/CompositeMethodGenerator.java b/metaprogramming/impl/src/main/java/org/teavm/metaprogramming/impl/CompositeMethodGenerator.java index 1e4062338..1ad8c2c74 100644 --- a/metaprogramming/impl/src/main/java/org/teavm/metaprogramming/impl/CompositeMethodGenerator.java +++ b/metaprogramming/impl/src/main/java/org/teavm/metaprogramming/impl/CompositeMethodGenerator.java @@ -183,11 +183,13 @@ public class CompositeMethodGenerator { BasicBlockReader templateBlock = template.basicBlockAt(i); blockIndex = i == 0 ? startBlock : substitutor.blockOffset + i; BasicBlock targetBlock = program.basicBlockAt(blockIndex); + if (templateBlock.getExceptionVariable() != null) { + targetBlock.setExceptionVariable(substitutor.var(templateBlock.getExceptionVariable())); + } for (TryCatchBlockReader templateTryCatch : templateBlock.readTryCatchBlocks()) { TryCatchBlock tryCatch = new TryCatchBlock(); tryCatch.setExceptionType(templateTryCatch.getExceptionType()); - tryCatch.setExceptionVariable(substitutor.var(templateTryCatch.getExceptionVariable())); tryCatch.setHandler(substitutor.block(templateTryCatch.getHandler())); targetBlock.getTryCatchBlocks().add(tryCatch); } diff --git a/metaprogramming/impl/src/main/java/org/teavm/metaprogramming/impl/optimization/BoxingElimination.java b/metaprogramming/impl/src/main/java/org/teavm/metaprogramming/impl/optimization/BoxingElimination.java index c0c8d4c07..2e69146f0 100644 --- a/metaprogramming/impl/src/main/java/org/teavm/metaprogramming/impl/optimization/BoxingElimination.java +++ b/metaprogramming/impl/src/main/java/org/teavm/metaprogramming/impl/optimization/BoxingElimination.java @@ -29,6 +29,7 @@ import org.teavm.model.MethodReference; import org.teavm.model.Phi; import org.teavm.model.PrimitiveType; import org.teavm.model.Program; +import org.teavm.model.TryCatchBlock; import org.teavm.model.TryCatchJoint; import org.teavm.model.ValueType; import org.teavm.model.Variable; @@ -111,9 +112,11 @@ public class BoxingElimination { union(phi.getReceiver().getIndex(), incoming.getValue().getIndex()); } } - for (TryCatchJoint joint : block.getTryCatchJoints()) { - for (Variable sourceVar : joint.getSourceVariables()) { - union(sourceVar.getIndex(), joint.getReceiver().getIndex()); + for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) { + for (TryCatchJoint joint : tryCatch.getTryCatchJoints()) { + for (Variable sourceVar : joint.getSourceVariables()) { + union(sourceVar.getIndex(), joint.getReceiver().getIndex()); + } } } } @@ -161,7 +164,7 @@ public class BoxingElimination { Wrapper q = wrappers.get(set.find(b)); int c = set.union(a, b); if (c >= wrappers.size()) { - wrappers.addAll(Collections.nCopies(c - wrappers.size() + 1, (Wrapper) null)); + wrappers.addAll(Collections.nCopies(c - wrappers.size() + 1, null)); } wrappers.set(c, union(p, q)); return c;