From de245613c4205527cc725832f88d7199fc13143c Mon Sep 17 00:00:00 2001 From: konsoletyper Date: Wed, 26 Feb 2014 13:26:33 +0400 Subject: [PATCH] Parser supports try/catch blocks --- .../main/java/org/teavm/model/BasicBlock.java | 6 +-- .../org/teavm/model/util/ListingBuilder.java | 5 +++ .../org/teavm/model/util/ProgramUtils.java | 16 +++++++ .../UnreachableBasicBlockEliminator.java | 4 ++ .../java/org/teavm/parsing/ProgramParser.java | 42 +++++++++++++++---- .../org/teavm/parsing/SSATransformer.java | 3 ++ 6 files changed, 66 insertions(+), 10 deletions(-) diff --git a/teavm-core/src/main/java/org/teavm/model/BasicBlock.java b/teavm-core/src/main/java/org/teavm/model/BasicBlock.java index 238f38461..df88e9327 100644 --- a/teavm-core/src/main/java/org/teavm/model/BasicBlock.java +++ b/teavm-core/src/main/java/org/teavm/model/BasicBlock.java @@ -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 getTryCatchBlocks() { diff --git a/teavm-core/src/main/java/org/teavm/model/util/ListingBuilder.java b/teavm-core/src/main/java/org/teavm/model/util/ListingBuilder.java index 382dd4e8b..51d2f1010 100644 --- a/teavm-core/src/main/java/org/teavm/model/util/ListingBuilder.java +++ b/teavm-core/src/main/java/org/teavm/model/util/ListingBuilder.java @@ -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(); } diff --git a/teavm-core/src/main/java/org/teavm/model/util/ProgramUtils.java b/teavm-core/src/main/java/org/teavm/model/util/ProgramUtils.java index 77a64e668..eacfa586f 100644 --- a/teavm-core/src/main/java/org/teavm/model/util/ProgramUtils.java +++ b/teavm-core/src/main/java/org/teavm/model/util/ProgramUtils.java @@ -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 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; } diff --git a/teavm-core/src/main/java/org/teavm/optimization/UnreachableBasicBlockEliminator.java b/teavm-core/src/main/java/org/teavm/optimization/UnreachableBasicBlockEliminator.java index 7d1950007..90c9f8ceb 100644 --- a/teavm-core/src/main/java/org/teavm/optimization/UnreachableBasicBlockEliminator.java +++ b/teavm-core/src/main/java/org/teavm/optimization/UnreachableBasicBlockEliminator.java @@ -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]) { diff --git a/teavm-core/src/main/java/org/teavm/parsing/ProgramParser.java b/teavm-core/src/main/java/org/teavm/parsing/ProgramParser.java index bcfe257d7..cb07e2b8b 100644 --- a/teavm-core/src/main/java/org/teavm/parsing/ProgramParser.java +++ b/teavm-core/src/main/java/org/teavm/parsing/ProgramParser.java @@ -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.>nCopies( - instructions.size(), null)); + targetInstructions.addAll(Collections.>nCopies(instructions.size(), null)); basicBlocks.addAll(Collections.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 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() { diff --git a/teavm-core/src/main/java/org/teavm/parsing/SSATransformer.java b/teavm-core/src/main/java/org/teavm/parsing/SSATransformer.java index 7b92b234a..7124bfd7b 100644 --- a/teavm-core/src/main/java/org/teavm/parsing/SSATransformer.java +++ b/teavm-core/src/main/java/org/teavm/parsing/SSATransformer.java @@ -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();