mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
Adds try/catch support in simple cases
This commit is contained in:
parent
de245613c4
commit
62686878c6
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.classlib.java.lang;
|
package org.teavm.classlib.java.lang;
|
||||||
|
|
||||||
|
import org.teavm.classlib.java.io.TPrintStream;
|
||||||
import org.teavm.javascript.ni.Remove;
|
import org.teavm.javascript.ni.Remove;
|
||||||
import org.teavm.javascript.ni.Rename;
|
import org.teavm.javascript.ni.Rename;
|
||||||
import org.teavm.javascript.ni.Superclass;
|
import org.teavm.javascript.ni.Superclass;
|
||||||
|
@ -107,4 +108,13 @@ public class TThrowable extends RuntimeException {
|
||||||
this.cause = cause;
|
this.cause = cause;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void printStackTrace() {
|
||||||
|
printStackTrace(TSystem.err);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void printStackTrace(TPrintStream stream) {
|
||||||
|
stream.println(TString.wrap(getClass().getName() + ": " + getMessage()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -105,4 +105,14 @@ class BlockRefCountVisitor implements StatementVisitor {
|
||||||
@Override
|
@Override
|
||||||
public void visit(InitClassStatement statement) {
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,4 +111,9 @@ class BreakToContinueReplacer implements StatementVisitor {
|
||||||
public void visit(InitClassStatement statement) {
|
public void visit(InitClassStatement statement) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(TryCatchStatement statement) {
|
||||||
|
visitSequence(statement.getProtectedBody());
|
||||||
|
visitSequence(statement.getHandler());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -171,7 +171,8 @@ public class Decompiler {
|
||||||
|
|
||||||
public RegularMethodNode decompileRegular(MethodHolder method) {
|
public RegularMethodNode decompileRegular(MethodHolder method) {
|
||||||
lastBlockId = 1;
|
lastBlockId = 1;
|
||||||
indexer = new GraphIndexer(ProgramUtils.buildControlFlowGraph(method.getProgram()));
|
graph = ProgramUtils.buildControlFlowGraph(method.getProgram());
|
||||||
|
indexer = new GraphIndexer(graph);
|
||||||
graph = indexer.getGraph();
|
graph = indexer.getGraph();
|
||||||
loopGraph = new LoopGraph(this.graph);
|
loopGraph = new LoopGraph(this.graph);
|
||||||
unflatCode();
|
unflatCode();
|
||||||
|
@ -218,6 +219,18 @@ public class Decompiler {
|
||||||
insn.acceptVisitor(generator);
|
insn.acceptVisitor(generator);
|
||||||
}
|
}
|
||||||
block.body.addAll(generator.statements);
|
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();
|
SequentialStatement result = new SequentialStatement();
|
||||||
|
|
|
@ -548,4 +548,11 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor {
|
||||||
public void visit(InitClassStatement statement) {
|
public void visit(InitClassStatement statement) {
|
||||||
resultStmt = statement;
|
resultStmt = statement;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(TryCatchStatement statement) {
|
||||||
|
processSequence(statement.getProtectedBody());
|
||||||
|
processSequence(statement.getHandler());
|
||||||
|
resultStmt = statement;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -119,4 +119,10 @@ class RedundantLabelEliminator implements StatementVisitor {
|
||||||
@Override
|
@Override
|
||||||
public void visit(InitClassStatement statement) {
|
public void visit(InitClassStatement statement) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(TryCatchStatement statement) {
|
||||||
|
visitSequence(statement.getProtectedBody());
|
||||||
|
visitSequence(statement.getHandler());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,4 +109,14 @@ class ReferenceCountingVisitor implements StatementVisitor {
|
||||||
@Override
|
@Override
|
||||||
public void visit(InitClassStatement statement) {
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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<TryCatchStatement> sequence = new ArrayList<>();
|
||||||
|
sequence.add(statement);
|
||||||
|
List<Statement> 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) {
|
private Injector getInjector(MethodReference ref) {
|
||||||
InjectorHolder holder = injectorMap.get(ref);
|
InjectorHolder holder = injectorMap.get(ref);
|
||||||
if (holder == null) {
|
if (holder == null) {
|
||||||
|
|
|
@ -573,7 +573,7 @@ class StatementGenerator implements InstructionVisitor {
|
||||||
assign(castToInteger(Expr.binary(op, Expr.var(first), Expr.var(second))), result);
|
assign(castToInteger(Expr.binary(op, Expr.var(first), Expr.var(second))), result);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Statement generateJumpStatement(BasicBlock target) {
|
Statement generateJumpStatement(BasicBlock target) {
|
||||||
if (nextBlock == target) {
|
if (nextBlock == target) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -215,4 +215,14 @@ class UnusedVariableEliminator implements ExprVisitor, StatementVisitor {
|
||||||
@Override
|
@Override
|
||||||
public void visit(InitClassStatement statement) {
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -189,4 +189,15 @@ public class RenamingVisitor implements StatementVisitor, ExprVisitor {
|
||||||
@Override
|
@Override
|
||||||
public void visit(InitClassStatement statement) {
|
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()]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,4 +45,6 @@ public interface StatementVisitor {
|
||||||
void visit(IncrementStatement statement);
|
void visit(IncrementStatement statement);
|
||||||
|
|
||||||
void visit(InitClassStatement statement);
|
void visit(InitClassStatement statement);
|
||||||
|
|
||||||
|
void visit(TryCatchStatement statement);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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<Statement> protectedBody = new ArrayList<>();
|
||||||
|
private List<Statement> handler = new ArrayList<>();
|
||||||
|
private String exceptionType;
|
||||||
|
private int exceptionVariable;
|
||||||
|
|
||||||
|
public List<Statement> getProtectedBody() {
|
||||||
|
return protectedBody;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Statement> 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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -198,14 +198,15 @@ public class BasicBlock implements BasicBlockReader {
|
||||||
return tryCatchBlocks.size();
|
return tryCatchBlocks.size();
|
||||||
}
|
}
|
||||||
@Override public void add(int index, TryCatchBlock element) {
|
@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");
|
throw new IllegalStateException("This try/catch block is already added to basic block");
|
||||||
}
|
}
|
||||||
|
element.protectedBlock = BasicBlock.this;
|
||||||
tryCatchBlocks.add(index, element);
|
tryCatchBlocks.add(index, element);
|
||||||
}
|
}
|
||||||
@Override public TryCatchBlock remove(int index) {
|
@Override public TryCatchBlock remove(int index) {
|
||||||
TryCatchBlock tryCatch = tryCatchBlocks.remove(index);
|
TryCatchBlock tryCatch = tryCatchBlocks.remove(index);
|
||||||
tryCatch.protectedBlocks.remove(BasicBlock.this);
|
tryCatch.protectedBlock = null;
|
||||||
return tryCatch;
|
return tryCatch;
|
||||||
}
|
}
|
||||||
@Override public TryCatchBlock set(int index, TryCatchBlock element) {
|
@Override public TryCatchBlock set(int index, TryCatchBlock element) {
|
||||||
|
@ -213,17 +214,17 @@ public class BasicBlock implements BasicBlockReader {
|
||||||
if (oldTryCatch == element) {
|
if (oldTryCatch == element) {
|
||||||
return oldTryCatch;
|
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");
|
throw new IllegalStateException("This try/catch block is already added to basic block");
|
||||||
}
|
}
|
||||||
oldTryCatch.protectedBlocks.remove(BasicBlock.this);
|
oldTryCatch.protectedBlock = null;
|
||||||
element.protectedBlocks.add(BasicBlock.this);
|
element.protectedBlock = 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.protectedBlock = null;
|
||||||
}
|
}
|
||||||
tryCatchBlocks.clear();
|
tryCatchBlocks.clear();
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,16 +15,12 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.model;
|
package org.teavm.model;
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||||
*/
|
*/
|
||||||
public class TryCatchBlock implements TryCatchBlockReader {
|
public class TryCatchBlock implements TryCatchBlockReader {
|
||||||
Set<BasicBlock> protectedBlocks = new HashSet<>();
|
BasicBlock protectedBlock;
|
||||||
private BasicBlock handler;
|
private BasicBlock handler;
|
||||||
private String exceptionType;
|
private String exceptionType;
|
||||||
private Variable exceptionVariable;
|
private Variable exceptionVariable;
|
||||||
|
@ -56,10 +52,8 @@ public class TryCatchBlock implements TryCatchBlockReader {
|
||||||
this.exceptionVariable = exceptionVariable;
|
this.exceptionVariable = exceptionVariable;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Set<BasicBlock> immutableProtectedBLocks = Collections.unmodifiableSet(protectedBlocks);
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<BasicBlock> readProtectedBlocks() {
|
public BasicBlock getProtectedBlock() {
|
||||||
return immutableProtectedBLocks;
|
return protectedBlock;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,14 +15,12 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.model;
|
package org.teavm.model;
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||||
*/
|
*/
|
||||||
public interface TryCatchBlockReader {
|
public interface TryCatchBlockReader {
|
||||||
Set<? extends BasicBlockReader> readProtectedBlocks();
|
BasicBlockReader getProtectedBlock();
|
||||||
|
|
||||||
BasicBlockReader getHandler();
|
BasicBlockReader getHandler();
|
||||||
|
|
||||||
|
|
|
@ -15,10 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.model.util;
|
package org.teavm.model.util;
|
||||||
|
|
||||||
import org.teavm.model.BasicBlock;
|
import org.teavm.model.*;
|
||||||
import org.teavm.model.Incoming;
|
|
||||||
import org.teavm.model.Phi;
|
|
||||||
import org.teavm.model.Program;
|
|
||||||
import org.teavm.model.instructions.*;
|
import org.teavm.model.instructions.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -37,6 +34,9 @@ public abstract class BasicBlockMapper implements InstructionVisitor {
|
||||||
incoming.setSource(map(incoming.getSource()));
|
incoming.setSource(map(incoming.getSource()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) {
|
||||||
|
tryCatch.setHandler(map(tryCatch.getHandler()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,8 +15,6 @@
|
||||||
*/
|
*/
|
||||||
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.*;
|
||||||
|
@ -58,7 +56,6 @@ 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);
|
||||||
|
@ -78,13 +75,10 @@ public class ProgramUtils {
|
||||||
blockCopy.getPhis().add(phiCopy);
|
blockCopy.getPhis().add(phiCopy);
|
||||||
}
|
}
|
||||||
for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) {
|
for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) {
|
||||||
TryCatchBlock tryCatchCopy = tryCatchCopies.get(tryCatch);
|
TryCatchBlock tryCatchCopy = new TryCatchBlock();
|
||||||
if (tryCatchCopy == null) {
|
tryCatchCopy.setExceptionType(tryCatch.getExceptionType());
|
||||||
tryCatchCopy = new TryCatchBlock();
|
tryCatchCopy.setExceptionVariable(copy.variableAt(tryCatch.getExceptionVariable().getIndex()));
|
||||||
tryCatchCopy.setExceptionType(tryCatchCopy.getExceptionType());
|
tryCatchCopy.setHandler(copy.basicBlockAt(tryCatch.getHandler().getIndex()));
|
||||||
tryCatchCopy.setHandler(copy.basicBlockAt(tryCatch.getHandler().getIndex()));
|
|
||||||
tryCatchCopies.put(tryCatch, tryCatchCopy);
|
|
||||||
}
|
|
||||||
blockCopy.getTryCatchBlocks().add(tryCatchCopy);
|
blockCopy.getTryCatchBlocks().add(tryCatchCopy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,12 +76,16 @@ public class RegisterAllocator {
|
||||||
Map<BasicBlock, BasicBlock> blockMap = new HashMap<>();
|
Map<BasicBlock, BasicBlock> blockMap = new HashMap<>();
|
||||||
for (Phi phi : program.basicBlockAt(i).getPhis()) {
|
for (Phi phi : program.basicBlockAt(i).getPhis()) {
|
||||||
for (Incoming incoming : phi.getIncomings()) {
|
for (Incoming incoming : phi.getIncomings()) {
|
||||||
insertCopy(incoming, blockMap);
|
if (!isExceptionHandler(incoming)) {
|
||||||
|
insertCopy(incoming, blockMap);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (Phi phi : program.basicBlockAt(i).getPhis()) {
|
for (Phi phi : program.basicBlockAt(i).getPhis()) {
|
||||||
for (Incoming incoming : phi.getIncomings()) {
|
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());
|
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<MutableGraphNode> interferenceGraph,
|
private void removeRedundantCopies(Program program, List<MutableGraphNode> interferenceGraph,
|
||||||
DisjointSet congruenceClasses) {
|
DisjointSet congruenceClasses) {
|
||||||
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
||||||
|
@ -187,6 +200,10 @@ public class RegisterAllocator {
|
||||||
incoming.setValue(program.variableAt(varMap[incoming.getValue().getIndex()]));
|
incoming.setValue(program.variableAt(varMap[incoming.getValue().getIndex()]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) {
|
||||||
|
tryCatch.setExceptionVariable(program.variableAt(
|
||||||
|
varMap[tryCatch.getExceptionVariable().getIndex()]));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -101,6 +101,10 @@ public class CommonSubexpressionElimination implements MethodOptimization {
|
||||||
int value = map[incoming.getValue().getIndex()];
|
int value = map[incoming.getValue().getIndex()];
|
||||||
incoming.setValue(program.variableAt(value));
|
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)) {
|
for (int succ : dom.outgoingEdges(v)) {
|
||||||
stack[top++] = succ;
|
stack[top++] = succ;
|
||||||
}
|
}
|
||||||
|
|
|
@ -213,10 +213,6 @@ public class ProgramParser {
|
||||||
}
|
}
|
||||||
for (Object obj : method.tryCatchBlocks) {
|
for (Object obj : method.tryCatchBlocks) {
|
||||||
TryCatchBlockNode tryCatchNode = (TryCatchBlockNode)obj;
|
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 start = labelIndexes.get(tryCatchNode.start.getLabel());
|
||||||
int end = labelIndexes.get(tryCatchNode.end.getLabel());
|
int end = labelIndexes.get(tryCatchNode.end.getLabel());
|
||||||
getBasicBlock(start);
|
getBasicBlock(start);
|
||||||
|
@ -224,6 +220,12 @@ public class ProgramParser {
|
||||||
for (int i = start; i < end; ++i) {
|
for (int i = start; i < end; ++i) {
|
||||||
BasicBlock block = basicBlocks.get(i);
|
BasicBlock block = basicBlocks.get(i);
|
||||||
if (block != null) {
|
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);
|
block.getTryCatchBlocks().add(tryCatch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,9 +15,10 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.parsing;
|
package org.teavm.parsing;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.*;
|
||||||
import java.util.List;
|
import org.teavm.common.DominatorTree;
|
||||||
import org.teavm.common.*;
|
import org.teavm.common.Graph;
|
||||||
|
import org.teavm.common.GraphUtils;
|
||||||
import org.teavm.model.*;
|
import org.teavm.model.*;
|
||||||
import org.teavm.model.instructions.*;
|
import org.teavm.model.instructions.*;
|
||||||
import org.teavm.model.util.DefinitionExtractor;
|
import org.teavm.model.util.DefinitionExtractor;
|
||||||
|
@ -114,6 +115,17 @@ public class SSATransformer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<List<TryCatchBlock>> caughtBlocks = new ArrayList<>();
|
||||||
|
List<List<Phi>> specialPhis = new ArrayList<>();
|
||||||
|
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
||||||
|
caughtBlocks.add(new ArrayList<TryCatchBlock>());
|
||||||
|
specialPhis.add(new ArrayList<Phi>());
|
||||||
|
}
|
||||||
|
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()];
|
boolean[] processed = new boolean[program.basicBlockCount()];
|
||||||
while (head > 0) {
|
while (head > 0) {
|
||||||
Task task = stack[--head];
|
Task task = stack[--head];
|
||||||
|
@ -128,12 +140,22 @@ public class SSATransformer {
|
||||||
variableMap[phi.getReceiver().getIndex()] = var;
|
variableMap[phi.getReceiver().getIndex()] = var;
|
||||||
phi.setReceiver(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()) {
|
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();
|
||||||
|
@ -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) {
|
private void markAssignment(Variable var) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user