From 62686878c6d1ebbc7e470cfc90bff75c0d650360 Mon Sep 17 00:00:00 2001 From: konsoletyper Date: Wed, 26 Feb 2014 16:42:31 +0400 Subject: [PATCH] Adds try/catch support in simple cases --- .../teavm/classlib/java/lang/TThrowable.java | 10 ++++ .../javascript/BlockRefCountVisitor.java | 10 ++++ .../javascript/BreakToContinueReplacer.java | 5 ++ .../java/org/teavm/javascript/Decompiler.java | 15 ++++- .../teavm/javascript/OptimizingVisitor.java | 7 +++ .../javascript/RedundantLabelEliminator.java | 6 ++ .../javascript/ReferenceCountingVisitor.java | 10 ++++ .../java/org/teavm/javascript/Renderer.java | 40 +++++++++++++ .../teavm/javascript/StatementGenerator.java | 2 +- .../javascript/UnusedVariableEliminator.java | 10 ++++ .../teavm/javascript/ast/RenamingVisitor.java | 11 ++++ .../javascript/ast/StatementVisitor.java | 2 + .../javascript/ast/TryCatchStatement.java | 59 +++++++++++++++++++ .../main/java/org/teavm/model/BasicBlock.java | 13 ++-- .../java/org/teavm/model/TryCatchBlock.java | 12 +--- .../org/teavm/model/TryCatchBlockReader.java | 4 +- .../teavm/model/util/BasicBlockMapper.java | 8 +-- .../org/teavm/model/util/ProgramUtils.java | 14 ++--- .../teavm/model/util/RegisterAllocator.java | 21 ++++++- .../CommonSubexpressionElimination.java | 4 ++ .../java/org/teavm/parsing/ProgramParser.java | 10 ++-- .../org/teavm/parsing/SSATransformer.java | 37 ++++++++++-- 22 files changed, 264 insertions(+), 46 deletions(-) create mode 100644 teavm-core/src/main/java/org/teavm/javascript/ast/TryCatchStatement.java diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TThrowable.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TThrowable.java index 6e2860107..426718b42 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TThrowable.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TThrowable.java @@ -15,6 +15,7 @@ */ package org.teavm.classlib.java.lang; +import org.teavm.classlib.java.io.TPrintStream; import org.teavm.javascript.ni.Remove; import org.teavm.javascript.ni.Rename; import org.teavm.javascript.ni.Superclass; @@ -107,4 +108,13 @@ public class TThrowable extends RuntimeException { this.cause = cause; return this; } + + @Override + public void printStackTrace() { + printStackTrace(TSystem.err); + } + + public void printStackTrace(TPrintStream stream) { + stream.println(TString.wrap(getClass().getName() + ": " + getMessage())); + } } diff --git a/teavm-core/src/main/java/org/teavm/javascript/BlockRefCountVisitor.java b/teavm-core/src/main/java/org/teavm/javascript/BlockRefCountVisitor.java index aebe0b162..08f3f5467 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/BlockRefCountVisitor.java +++ b/teavm-core/src/main/java/org/teavm/javascript/BlockRefCountVisitor.java @@ -105,4 +105,14 @@ class BlockRefCountVisitor implements StatementVisitor { @Override public void visit(InitClassStatement statement) { } + + @Override + public void visit(TryCatchStatement statement) { + for (Statement part : statement.getProtectedBody()) { + part.acceptVisitor(this); + } + for (Statement part : statement.getHandler()) { + part.acceptVisitor(this); + } + } } diff --git a/teavm-core/src/main/java/org/teavm/javascript/BreakToContinueReplacer.java b/teavm-core/src/main/java/org/teavm/javascript/BreakToContinueReplacer.java index c5b766b93..ba5f12c60 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/BreakToContinueReplacer.java +++ b/teavm-core/src/main/java/org/teavm/javascript/BreakToContinueReplacer.java @@ -111,4 +111,9 @@ class BreakToContinueReplacer implements StatementVisitor { public void visit(InitClassStatement statement) { } + @Override + public void visit(TryCatchStatement statement) { + visitSequence(statement.getProtectedBody()); + visitSequence(statement.getHandler()); + } } diff --git a/teavm-core/src/main/java/org/teavm/javascript/Decompiler.java b/teavm-core/src/main/java/org/teavm/javascript/Decompiler.java index 80377fd47..88bc98e86 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/Decompiler.java +++ b/teavm-core/src/main/java/org/teavm/javascript/Decompiler.java @@ -171,7 +171,8 @@ public class Decompiler { public RegularMethodNode decompileRegular(MethodHolder method) { lastBlockId = 1; - indexer = new GraphIndexer(ProgramUtils.buildControlFlowGraph(method.getProgram())); + graph = ProgramUtils.buildControlFlowGraph(method.getProgram()); + indexer = new GraphIndexer(graph); graph = indexer.getGraph(); loopGraph = new LoopGraph(this.graph); unflatCode(); @@ -218,6 +219,18 @@ public class Decompiler { insn.acceptVisitor(generator); } block.body.addAll(generator.statements); + for (TryCatchBlock tryCatch : generator.currentBlock.getTryCatchBlocks()) { + TryCatchStatement tryCatchStmt = new TryCatchStatement(); + tryCatchStmt.setExceptionType(tryCatch.getExceptionType()); + tryCatchStmt.setExceptionVariable(tryCatch.getExceptionVariable().getIndex()); + tryCatchStmt.getProtectedBody().addAll(block.body); + block.body.clear(); + block.body.add(tryCatchStmt); + Statement handlerStmt = generator.generateJumpStatement(tryCatch.getHandler()); + if (handlerStmt != null) { + tryCatchStmt.getHandler().add(handlerStmt); + } + } } } SequentialStatement result = new SequentialStatement(); diff --git a/teavm-core/src/main/java/org/teavm/javascript/OptimizingVisitor.java b/teavm-core/src/main/java/org/teavm/javascript/OptimizingVisitor.java index cfb3c819d..60e720691 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/OptimizingVisitor.java +++ b/teavm-core/src/main/java/org/teavm/javascript/OptimizingVisitor.java @@ -548,4 +548,11 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor { public void visit(InitClassStatement statement) { resultStmt = statement; } + + @Override + public void visit(TryCatchStatement statement) { + processSequence(statement.getProtectedBody()); + processSequence(statement.getHandler()); + resultStmt = statement; + } } diff --git a/teavm-core/src/main/java/org/teavm/javascript/RedundantLabelEliminator.java b/teavm-core/src/main/java/org/teavm/javascript/RedundantLabelEliminator.java index 235d8f1e4..1e2b7fdc1 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/RedundantLabelEliminator.java +++ b/teavm-core/src/main/java/org/teavm/javascript/RedundantLabelEliminator.java @@ -119,4 +119,10 @@ class RedundantLabelEliminator implements StatementVisitor { @Override public void visit(InitClassStatement statement) { } + + @Override + public void visit(TryCatchStatement statement) { + visitSequence(statement.getProtectedBody()); + visitSequence(statement.getHandler()); + } } diff --git a/teavm-core/src/main/java/org/teavm/javascript/ReferenceCountingVisitor.java b/teavm-core/src/main/java/org/teavm/javascript/ReferenceCountingVisitor.java index ff6dcde4e..2683e1efd 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/ReferenceCountingVisitor.java +++ b/teavm-core/src/main/java/org/teavm/javascript/ReferenceCountingVisitor.java @@ -109,4 +109,14 @@ class ReferenceCountingVisitor implements StatementVisitor { @Override public void visit(InitClassStatement statement) { } + + @Override + public void visit(TryCatchStatement statement) { + for (Statement part : statement.getProtectedBody()) { + part.acceptVisitor(this); + } + for (Statement part : statement.getHandler()) { + part.acceptVisitor(this); + } + } } diff --git a/teavm-core/src/main/java/org/teavm/javascript/Renderer.java b/teavm-core/src/main/java/org/teavm/javascript/Renderer.java index ad8a97633..38dcf2649 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/Renderer.java +++ b/teavm-core/src/main/java/org/teavm/javascript/Renderer.java @@ -1249,6 +1249,46 @@ public class Renderer implements ExprVisitor, StatementVisitor { } } + @Override + public void visit(TryCatchStatement statement) { + try { + writer.append("try").ws().append("{").softNewLine().indent(); + List sequence = new ArrayList<>(); + sequence.add(statement); + List protectedBody = statement.getProtectedBody(); + while (protectedBody.size() == 1 && protectedBody.get(0) instanceof TryCatchStatement) { + TryCatchStatement nextStatement = (TryCatchStatement)protectedBody.get(0); + sequence.add(nextStatement); + protectedBody = nextStatement.getProtectedBody(); + } + for (Statement part : protectedBody) { + part.acceptVisitor(this); + } + String var = variableName(statement.getExceptionVariable()); + writer.outdent().append("}").ws().append("catch").ws().append("(").append(var).append(")") + .ws().append("{").indent().softNewLine(); + for (TryCatchStatement catchClause : sequence) { + writer.append("if").ws().append("(").append(var).append(" instanceof ") + .appendClass(catchClause.getExceptionType()).append(")").ws().append("{") + .indent().softNewLine(); + if (statement.getExceptionVariable() != catchClause.getExceptionVariable()) { + writer.append(variableName(catchClause.getExceptionVariable())).ws().append("=").ws() + .append(var).append(";").softNewLine(); + } + for (Statement part : statement.getHandler()) { + part.acceptVisitor(this); + } + writer.outdent().append("}").ws().append("else "); + } + writer.append("{").indent().softNewLine(); + writer.append("throw ").append(var).append(";").softNewLine(); + writer.outdent().append("}").softNewLine(); + writer.outdent().append("}").softNewLine(); + } catch (IOException e) { + throw new RenderingException("IO error occured", e); + } + } + private Injector getInjector(MethodReference ref) { InjectorHolder holder = injectorMap.get(ref); if (holder == null) { diff --git a/teavm-core/src/main/java/org/teavm/javascript/StatementGenerator.java b/teavm-core/src/main/java/org/teavm/javascript/StatementGenerator.java index 943fe0e03..f0b98e317 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/StatementGenerator.java +++ b/teavm-core/src/main/java/org/teavm/javascript/StatementGenerator.java @@ -573,7 +573,7 @@ class StatementGenerator implements InstructionVisitor { assign(castToInteger(Expr.binary(op, Expr.var(first), Expr.var(second))), result); } - private Statement generateJumpStatement(BasicBlock target) { + Statement generateJumpStatement(BasicBlock target) { if (nextBlock == target) { return null; } diff --git a/teavm-core/src/main/java/org/teavm/javascript/UnusedVariableEliminator.java b/teavm-core/src/main/java/org/teavm/javascript/UnusedVariableEliminator.java index d61066b21..61232073e 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/UnusedVariableEliminator.java +++ b/teavm-core/src/main/java/org/teavm/javascript/UnusedVariableEliminator.java @@ -215,4 +215,14 @@ class UnusedVariableEliminator implements ExprVisitor, StatementVisitor { @Override public void visit(InitClassStatement statement) { } + + @Override + public void visit(TryCatchStatement statement) { + for (Statement part : statement.getProtectedBody()) { + part.acceptVisitor(this); + } + for (Statement part : statement.getHandler()) { + part.acceptVisitor(this); + } + } } diff --git a/teavm-core/src/main/java/org/teavm/javascript/ast/RenamingVisitor.java b/teavm-core/src/main/java/org/teavm/javascript/ast/RenamingVisitor.java index 01779e0f2..ff7378a3f 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/ast/RenamingVisitor.java +++ b/teavm-core/src/main/java/org/teavm/javascript/ast/RenamingVisitor.java @@ -189,4 +189,15 @@ public class RenamingVisitor implements StatementVisitor, ExprVisitor { @Override public void visit(InitClassStatement statement) { } + + @Override + public void visit(TryCatchStatement statement) { + for (Statement part : statement.getProtectedBody()) { + part.acceptVisitor(this); + } + for (Statement part : statement.getHandler()) { + part.acceptVisitor(this); + } + statement.setExceptionVariable(varNames[statement.getExceptionVariable()]); + } } diff --git a/teavm-core/src/main/java/org/teavm/javascript/ast/StatementVisitor.java b/teavm-core/src/main/java/org/teavm/javascript/ast/StatementVisitor.java index 67136506a..8f4f910f7 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/ast/StatementVisitor.java +++ b/teavm-core/src/main/java/org/teavm/javascript/ast/StatementVisitor.java @@ -45,4 +45,6 @@ public interface StatementVisitor { void visit(IncrementStatement statement); void visit(InitClassStatement statement); + + void visit(TryCatchStatement statement); } diff --git a/teavm-core/src/main/java/org/teavm/javascript/ast/TryCatchStatement.java b/teavm-core/src/main/java/org/teavm/javascript/ast/TryCatchStatement.java new file mode 100644 index 000000000..90e13a312 --- /dev/null +++ b/teavm-core/src/main/java/org/teavm/javascript/ast/TryCatchStatement.java @@ -0,0 +1,59 @@ +/* + * Copyright 2014 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.javascript.ast; + +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author Alexey Andreev + */ +public class TryCatchStatement extends Statement { + private List protectedBody = new ArrayList<>(); + private List handler = new ArrayList<>(); + private String exceptionType; + private int exceptionVariable; + + public List getProtectedBody() { + return protectedBody; + } + + public List getHandler() { + return handler; + } + + public String getExceptionType() { + return exceptionType; + } + + public void setExceptionType(String exceptionType) { + this.exceptionType = exceptionType; + } + + public int getExceptionVariable() { + return exceptionVariable; + } + + public void setExceptionVariable(int exceptionVariable) { + this.exceptionVariable = exceptionVariable; + } + + @Override + public void acceptVisitor(StatementVisitor visitor) { + visitor.visit(this); + } +} 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 df88e9327..62d493133 100644 --- a/teavm-core/src/main/java/org/teavm/model/BasicBlock.java +++ b/teavm-core/src/main/java/org/teavm/model/BasicBlock.java @@ -198,14 +198,15 @@ public class BasicBlock implements BasicBlockReader { return tryCatchBlocks.size(); } @Override public void add(int index, TryCatchBlock element) { - if (!element.protectedBlocks.add(BasicBlock.this)) { + if (element.protectedBlock == BasicBlock.this) { throw new IllegalStateException("This try/catch block is already added to basic block"); } + element.protectedBlock = BasicBlock.this; tryCatchBlocks.add(index, element); } @Override public TryCatchBlock remove(int index) { TryCatchBlock tryCatch = tryCatchBlocks.remove(index); - tryCatch.protectedBlocks.remove(BasicBlock.this); + tryCatch.protectedBlock = null; return tryCatch; } @Override public TryCatchBlock set(int index, TryCatchBlock element) { @@ -213,17 +214,17 @@ public class BasicBlock implements BasicBlockReader { if (oldTryCatch == element) { return oldTryCatch; } - if (element.protectedBlocks.contains(BasicBlock.this)) { + if (element.protectedBlock == BasicBlock.this) { throw new IllegalStateException("This try/catch block is already added to basic block"); } - oldTryCatch.protectedBlocks.remove(BasicBlock.this); - element.protectedBlocks.add(BasicBlock.this); + oldTryCatch.protectedBlock = null; + element.protectedBlock = BasicBlock.this; tryCatchBlocks.set(index, element); return oldTryCatch; } @Override public void clear() { for (TryCatchBlock tryCatch : tryCatchBlocks) { - tryCatch.protectedBlocks.remove(BasicBlock.this); + tryCatch.protectedBlock = null; } tryCatchBlocks.clear(); } diff --git a/teavm-core/src/main/java/org/teavm/model/TryCatchBlock.java b/teavm-core/src/main/java/org/teavm/model/TryCatchBlock.java index ec9f4cab7..1a8430fac 100644 --- a/teavm-core/src/main/java/org/teavm/model/TryCatchBlock.java +++ b/teavm-core/src/main/java/org/teavm/model/TryCatchBlock.java @@ -15,16 +15,12 @@ */ package org.teavm.model; -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; - /** * * @author Alexey Andreev */ public class TryCatchBlock implements TryCatchBlockReader { - Set protectedBlocks = new HashSet<>(); + BasicBlock protectedBlock; private BasicBlock handler; private String exceptionType; private Variable exceptionVariable; @@ -56,10 +52,8 @@ public class TryCatchBlock implements TryCatchBlockReader { this.exceptionVariable = exceptionVariable; } - private Set immutableProtectedBLocks = Collections.unmodifiableSet(protectedBlocks); - @Override - public Set readProtectedBlocks() { - return immutableProtectedBLocks; + public BasicBlock getProtectedBlock() { + return protectedBlock; } } diff --git a/teavm-core/src/main/java/org/teavm/model/TryCatchBlockReader.java b/teavm-core/src/main/java/org/teavm/model/TryCatchBlockReader.java index f9b84ca1b..13c5938ff 100644 --- a/teavm-core/src/main/java/org/teavm/model/TryCatchBlockReader.java +++ b/teavm-core/src/main/java/org/teavm/model/TryCatchBlockReader.java @@ -15,14 +15,12 @@ */ package org.teavm.model; -import java.util.Set; - /** * * @author Alexey Andreev */ public interface TryCatchBlockReader { - Set readProtectedBlocks(); + BasicBlockReader getProtectedBlock(); BasicBlockReader getHandler(); diff --git a/teavm-core/src/main/java/org/teavm/model/util/BasicBlockMapper.java b/teavm-core/src/main/java/org/teavm/model/util/BasicBlockMapper.java index 064c668b9..3c99cd1af 100644 --- a/teavm-core/src/main/java/org/teavm/model/util/BasicBlockMapper.java +++ b/teavm-core/src/main/java/org/teavm/model/util/BasicBlockMapper.java @@ -15,10 +15,7 @@ */ package org.teavm.model.util; -import org.teavm.model.BasicBlock; -import org.teavm.model.Incoming; -import org.teavm.model.Phi; -import org.teavm.model.Program; +import org.teavm.model.*; import org.teavm.model.instructions.*; /** @@ -37,6 +34,9 @@ public abstract class BasicBlockMapper implements InstructionVisitor { incoming.setSource(map(incoming.getSource())); } } + for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) { + tryCatch.setHandler(map(tryCatch.getHandler())); + } } } 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 eacfa586f..9c25eeaa1 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,8 +15,6 @@ */ 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.*; @@ -58,7 +56,6 @@ 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); @@ -78,13 +75,10 @@ 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); - } + 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); } } diff --git a/teavm-core/src/main/java/org/teavm/model/util/RegisterAllocator.java b/teavm-core/src/main/java/org/teavm/model/util/RegisterAllocator.java index fb431144b..709affd0a 100644 --- a/teavm-core/src/main/java/org/teavm/model/util/RegisterAllocator.java +++ b/teavm-core/src/main/java/org/teavm/model/util/RegisterAllocator.java @@ -76,12 +76,16 @@ public class RegisterAllocator { Map blockMap = new HashMap<>(); for (Phi phi : program.basicBlockAt(i).getPhis()) { for (Incoming incoming : phi.getIncomings()) { - insertCopy(incoming, blockMap); + if (!isExceptionHandler(incoming)) { + insertCopy(incoming, blockMap); + } } } for (Phi phi : program.basicBlockAt(i).getPhis()) { for (Incoming incoming : phi.getIncomings()) { - insertCopy(incoming, blockMap); + if (!isExceptionHandler(incoming)) { + insertCopy(incoming, blockMap); + } } } } @@ -122,6 +126,15 @@ public class RegisterAllocator { incoming.setValue(copyInstruction.getReceiver()); } + private boolean isExceptionHandler(Incoming incoming) { + for (TryCatchBlock tryCatch : incoming.getSource().getTryCatchBlocks()) { + if (tryCatch.getExceptionVariable() == incoming.getValue()) { + return true; + } + } + return false; + } + private void removeRedundantCopies(Program program, List interferenceGraph, DisjointSet congruenceClasses) { for (int i = 0; i < program.basicBlockCount(); ++i) { @@ -187,6 +200,10 @@ public class RegisterAllocator { incoming.setValue(program.variableAt(varMap[incoming.getValue().getIndex()])); } } + for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) { + tryCatch.setExceptionVariable(program.variableAt( + varMap[tryCatch.getExceptionVariable().getIndex()])); + } } } diff --git a/teavm-core/src/main/java/org/teavm/optimization/CommonSubexpressionElimination.java b/teavm-core/src/main/java/org/teavm/optimization/CommonSubexpressionElimination.java index 397621e90..be916f7a8 100644 --- a/teavm-core/src/main/java/org/teavm/optimization/CommonSubexpressionElimination.java +++ b/teavm-core/src/main/java/org/teavm/optimization/CommonSubexpressionElimination.java @@ -101,6 +101,10 @@ public class CommonSubexpressionElimination implements MethodOptimization { int value = map[incoming.getValue().getIndex()]; incoming.setValue(program.variableAt(value)); } + for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) { + int var = map[tryCatch.getExceptionVariable().getIndex()]; + tryCatch.setExceptionVariable(program.variableAt(var)); + } for (int succ : dom.outgoingEdges(v)) { stack[top++] = succ; } 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 cb07e2b8b..b697c0c14 100644 --- a/teavm-core/src/main/java/org/teavm/parsing/ProgramParser.java +++ b/teavm-core/src/main/java/org/teavm/parsing/ProgramParser.java @@ -213,10 +213,6 @@ public class ProgramParser { } 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); @@ -224,6 +220,12 @@ public class ProgramParser { for (int i = start; i < end; ++i) { BasicBlock block = basicBlocks.get(i); if (block != null) { + TryCatchBlock tryCatch = new TryCatchBlock(); + if (tryCatchNode.type != null) { + tryCatch.setExceptionType(tryCatchNode.type.replace('/', '.')); + } + tryCatch.setHandler(getBasicBlock(labelIndexes.get(tryCatchNode.handler.getLabel()))); + tryCatch.setExceptionVariable(getVariable(minLocal + method.maxLocals)); block.getTryCatchBlocks().add(tryCatch); } } 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 7124bfd7b..4dc4224ab 100644 --- a/teavm-core/src/main/java/org/teavm/parsing/SSATransformer.java +++ b/teavm-core/src/main/java/org/teavm/parsing/SSATransformer.java @@ -15,9 +15,10 @@ */ package org.teavm.parsing; -import java.util.Arrays; -import java.util.List; -import org.teavm.common.*; +import java.util.*; +import org.teavm.common.DominatorTree; +import org.teavm.common.Graph; +import org.teavm.common.GraphUtils; import org.teavm.model.*; import org.teavm.model.instructions.*; import org.teavm.model.util.DefinitionExtractor; @@ -114,6 +115,17 @@ public class SSATransformer { } } + List> caughtBlocks = new ArrayList<>(); + List> specialPhis = new ArrayList<>(); + for (int i = 0; i < program.basicBlockCount(); ++i) { + caughtBlocks.add(new ArrayList()); + specialPhis.add(new ArrayList()); + } + for (int i = 0; i < program.basicBlockCount(); ++i) { + for (TryCatchBlock tryCatch : program.basicBlockAt(i).getTryCatchBlocks()) { + caughtBlocks.get(tryCatch.getHandler().getIndex()).add(tryCatch); + } + } boolean[] processed = new boolean[program.basicBlockCount()]; while (head > 0) { Task task = stack[--head]; @@ -128,12 +140,22 @@ public class SSATransformer { variableMap[phi.getReceiver().getIndex()] = var; phi.setReceiver(var); } + if (!caughtBlocks.get(currentBlock.getIndex()).isEmpty()) { + Phi phi = new Phi(); + phi.setReceiver(program.createVariable()); + for (TryCatchBlock tryCatch : caughtBlocks.get(currentBlock.getIndex())) { + variableMap[tryCatch.getExceptionVariable().getIndex()] = phi.getReceiver(); + tryCatch.setExceptionVariable(program.createVariable()); + Incoming incoming = new Incoming(); + incoming.setSource(tryCatch.getProtectedBlock()); + incoming.setValue(tryCatch.getExceptionVariable()); + phi.getIncomings().add(incoming); + } + specialPhis.get(currentBlock.getIndex()).add(phi); + } 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(); @@ -157,6 +179,9 @@ public class SSATransformer { } } } + for (int i = 0; i < specialPhis.size(); ++i) { + program.basicBlockAt(i).getPhis().addAll(specialPhis.get(i)); + } } private void markAssignment(Variable var) {