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

View File

@ -48,6 +48,11 @@ public class ListingBuilder {
block.readInstruction(j, stringifier);
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();
}

View File

@ -15,6 +15,8 @@
*/
package org.teavm.model.util;
import java.util.HashMap;
import java.util.Map;
import org.teavm.common.Graph;
import org.teavm.common.GraphBuilder;
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();
}
@ -53,6 +58,7 @@ public class ProgramUtils {
for (int i = 0; i < program.basicBlockCount(); ++i) {
copy.createBasicBlock();
}
Map<TryCatchBlock, TryCatchBlock> tryCatchCopies = new HashMap<>();
for (int i = 0; i < program.basicBlockCount(); ++i) {
BasicBlock block = program.basicBlockAt(i);
BasicBlock blockCopy = copy.basicBlockAt(i);
@ -71,6 +77,16 @@ public class ProgramUtils {
}
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;
}

View File

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

View File

@ -17,10 +17,7 @@ package org.teavm.parsing;
import java.util.*;
import org.objectweb.asm.*;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.LabelNode;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.*;
import org.teavm.model.*;
import org.teavm.model.instructions.*;
import org.teavm.model.util.InstructionTransitionExtractor;
@ -170,8 +167,7 @@ public class ProgramParser {
}
}
targetInstructions = new ArrayList<>(instructions.size());
targetInstructions.addAll(Collections.<List<Instruction>>nCopies(
instructions.size(), null));
targetInstructions.addAll(Collections.<List<Instruction>>nCopies(instructions.size(), null));
basicBlocks.addAll(Collections.<BasicBlock>nCopies(instructions.size(), null));
stackBefore = new StackFrame[instructions.size()];
stackAfter = new StackFrame[instructions.size()];
@ -180,6 +176,10 @@ public class ProgramParser {
private void doAnalyze(MethodNode method) {
InsnList instructions = method.instructions;
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));
while (!workStack.isEmpty()) {
Step step = workStack.pop();
@ -187,7 +187,18 @@ public class ProgramParser {
if (stackBefore[index] != null) {
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;
nextIndexes = new int[] { index + 1 };
instructions.get(index).accept(methodVisitor);
@ -200,6 +211,23 @@ public class ProgramParser {
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() {

View File

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