Parser supports try/catch blocks

This commit is contained in:
konsoletyper 2014-02-26 13:26:33 +04:00
parent d5fac392d3
commit de245613c4
6 changed files with 66 additions and 10 deletions

View File

@ -207,7 +207,7 @@ public class BasicBlock implements BasicBlockReader {
TryCatchBlock tryCatch = tryCatchBlocks.remove(index); TryCatchBlock tryCatch = tryCatchBlocks.remove(index);
tryCatch.protectedBlocks.remove(BasicBlock.this); tryCatch.protectedBlocks.remove(BasicBlock.this);
return tryCatch; return tryCatch;
}; }
@Override public TryCatchBlock set(int index, TryCatchBlock element) { @Override public TryCatchBlock set(int index, TryCatchBlock element) {
TryCatchBlock oldTryCatch = tryCatchBlocks.get(index); TryCatchBlock oldTryCatch = tryCatchBlocks.get(index);
if (oldTryCatch == element) { if (oldTryCatch == element) {
@ -220,13 +220,13 @@ public class BasicBlock implements BasicBlockReader {
element.protectedBlocks.add(BasicBlock.this); element.protectedBlocks.add(BasicBlock.this);
tryCatchBlocks.set(index, element); tryCatchBlocks.set(index, element);
return oldTryCatch; return oldTryCatch;
}; }
@Override public void clear() { @Override public void clear() {
for (TryCatchBlock tryCatch : tryCatchBlocks) { for (TryCatchBlock tryCatch : tryCatchBlocks) {
tryCatch.protectedBlocks.remove(BasicBlock.this); tryCatch.protectedBlocks.remove(BasicBlock.this);
} }
tryCatchBlocks.clear(); tryCatchBlocks.clear();
}; }
}; };
public List<TryCatchBlock> getTryCatchBlocks() { public List<TryCatchBlock> getTryCatchBlocks() {

View File

@ -48,6 +48,11 @@ public class ListingBuilder {
block.readInstruction(j, stringifier); block.readInstruction(j, stringifier);
sb.append("\n"); sb.append("\n");
} }
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");
}
} }
return sb.toString(); return sb.toString();
} }

View File

@ -15,6 +15,8 @@
*/ */
package org.teavm.model.util; package org.teavm.model.util;
import java.util.HashMap;
import java.util.Map;
import org.teavm.common.Graph; import org.teavm.common.Graph;
import org.teavm.common.GraphBuilder; import org.teavm.common.GraphBuilder;
import org.teavm.model.*; import org.teavm.model.*;
@ -39,6 +41,9 @@ public class ProgramUtils {
} }
} }
} }
for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) {
graphBuilder.addEdge(i, tryCatch.getHandler().getIndex());
}
} }
return graphBuilder.build(); return graphBuilder.build();
} }
@ -53,6 +58,7 @@ public class ProgramUtils {
for (int i = 0; i < program.basicBlockCount(); ++i) { for (int i = 0; i < program.basicBlockCount(); ++i) {
copy.createBasicBlock(); copy.createBasicBlock();
} }
Map<TryCatchBlock, TryCatchBlock> tryCatchCopies = new HashMap<>();
for (int i = 0; i < program.basicBlockCount(); ++i) { for (int i = 0; i < program.basicBlockCount(); ++i) {
BasicBlock block = program.basicBlockAt(i); BasicBlock block = program.basicBlockAt(i);
BasicBlock blockCopy = copy.basicBlockAt(i); BasicBlock blockCopy = copy.basicBlockAt(i);
@ -71,6 +77,16 @@ public class ProgramUtils {
} }
blockCopy.getPhis().add(phiCopy); blockCopy.getPhis().add(phiCopy);
} }
for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) {
TryCatchBlock tryCatchCopy = tryCatchCopies.get(tryCatch);
if (tryCatchCopy == null) {
tryCatchCopy = new TryCatchBlock();
tryCatchCopy.setExceptionType(tryCatchCopy.getExceptionType());
tryCatchCopy.setHandler(copy.basicBlockAt(tryCatch.getHandler().getIndex()));
tryCatchCopies.put(tryCatch, tryCatchCopy);
}
blockCopy.getTryCatchBlocks().add(tryCatchCopy);
}
} }
return copy; return copy;
} }

View File

@ -17,6 +17,7 @@ package org.teavm.optimization;
import org.teavm.model.BasicBlock; import org.teavm.model.BasicBlock;
import org.teavm.model.Program; import org.teavm.model.Program;
import org.teavm.model.TryCatchBlock;
import org.teavm.model.util.InstructionTransitionExtractor; import org.teavm.model.util.InstructionTransitionExtractor;
/** /**
@ -44,6 +45,9 @@ public class UnreachableBasicBlockEliminator {
for (BasicBlock successor : transitionExtractor.getTargets()) { for (BasicBlock successor : transitionExtractor.getTargets()) {
stack[top++] = successor.getIndex(); stack[top++] = successor.getIndex();
} }
for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) {
stack[top++] = tryCatch.getHandler().getIndex();
}
} }
for (int i = 0; i < reachable.length; ++i) { for (int i = 0; i < reachable.length; ++i) {
if (!reachable[i]) { if (!reachable[i]) {

View File

@ -17,10 +17,7 @@ package org.teavm.parsing;
import java.util.*; import java.util.*;
import org.objectweb.asm.*; import org.objectweb.asm.*;
import org.objectweb.asm.tree.AbstractInsnNode; import org.objectweb.asm.tree.*;
import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.LabelNode;
import org.objectweb.asm.tree.MethodNode;
import org.teavm.model.*; import org.teavm.model.*;
import org.teavm.model.instructions.*; import org.teavm.model.instructions.*;
import org.teavm.model.util.InstructionTransitionExtractor; import org.teavm.model.util.InstructionTransitionExtractor;
@ -170,8 +167,7 @@ public class ProgramParser {
} }
} }
targetInstructions = new ArrayList<>(instructions.size()); targetInstructions = new ArrayList<>(instructions.size());
targetInstructions.addAll(Collections.<List<Instruction>>nCopies( targetInstructions.addAll(Collections.<List<Instruction>>nCopies(instructions.size(), null));
instructions.size(), null));
basicBlocks.addAll(Collections.<BasicBlock>nCopies(instructions.size(), null)); basicBlocks.addAll(Collections.<BasicBlock>nCopies(instructions.size(), null));
stackBefore = new StackFrame[instructions.size()]; stackBefore = new StackFrame[instructions.size()];
stackAfter = new StackFrame[instructions.size()]; stackAfter = new StackFrame[instructions.size()];
@ -180,6 +176,10 @@ public class ProgramParser {
private void doAnalyze(MethodNode method) { private void doAnalyze(MethodNode method) {
InsnList instructions = method.instructions; InsnList instructions = method.instructions;
Deque<Step> workStack = new ArrayDeque<>(); Deque<Step> workStack = new ArrayDeque<>();
for (Object obj : method.tryCatchBlocks) {
TryCatchBlockNode tryCatchNode = (TryCatchBlockNode)obj;
workStack.push(new Step(-2, labelIndexes.get(tryCatchNode.handler.getLabel())));
}
workStack.push(new Step(-1, 0)); workStack.push(new Step(-1, 0));
while (!workStack.isEmpty()) { while (!workStack.isEmpty()) {
Step step = workStack.pop(); Step step = workStack.pop();
@ -187,7 +187,18 @@ public class ProgramParser {
if (stackBefore[index] != null) { if (stackBefore[index] != null) {
continue; continue;
} }
stack = step.source != -1 ? stackAfter[step.source] : new StackFrame(minLocal + method.maxLocals - 1); switch (step.source) {
case -1:
stack = new StackFrame(minLocal + method.maxLocals - 1);
break;
case -2:
stack = new StackFrame(minLocal + method.maxLocals - 1);
pushSingle();
break;
default:
stack = stackAfter[step.source];
break;
}
stackBefore[index] = stack; stackBefore[index] = stack;
nextIndexes = new int[] { index + 1 }; nextIndexes = new int[] { index + 1 };
instructions.get(index).accept(methodVisitor); instructions.get(index).accept(methodVisitor);
@ -200,6 +211,23 @@ public class ProgramParser {
workStack.push(new Step(index, next)); workStack.push(new Step(index, next));
} }
} }
for (Object obj : method.tryCatchBlocks) {
TryCatchBlockNode tryCatchNode = (TryCatchBlockNode)obj;
TryCatchBlock tryCatch = new TryCatchBlock();
tryCatch.setExceptionType(tryCatchNode.type.replace('/', '.'));
tryCatch.setHandler(getBasicBlock(labelIndexes.get(tryCatchNode.handler.getLabel())));
tryCatch.setExceptionVariable(getVariable(minLocal + method.maxLocals));
int start = labelIndexes.get(tryCatchNode.start.getLabel());
int end = labelIndexes.get(tryCatchNode.end.getLabel());
getBasicBlock(start);
getBasicBlock(end);
for (int i = start; i < end; ++i) {
BasicBlock block = basicBlocks.get(i);
if (block != null) {
block.getTryCatchBlocks().add(tryCatch);
}
}
}
} }
private void assemble() { private void assemble() {

View File

@ -131,6 +131,9 @@ public class SSATransformer {
for (Instruction insn : currentBlock.getInstructions()) { for (Instruction insn : currentBlock.getInstructions()) {
insn.acceptVisitor(consumer); insn.acceptVisitor(consumer);
} }
for (TryCatchBlock tryCatch : currentBlock.getTryCatchBlocks()) {
define(tryCatch.getExceptionVariable());
}
int[] successors = domGraph.outgoingEdges(currentBlock.getIndex()); int[] successors = domGraph.outgoingEdges(currentBlock.getIndex());
for (int i = 0; i < successors.length; ++i) { for (int i = 0; i < successors.length; ++i) {
Task next = new Task(); Task next = new Task();