From e992297781e95a78592a523cf33ce6af9a5fc57d Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Sun, 29 Jan 2017 23:45:48 +0300 Subject: [PATCH] Eliminate unnecessary return statements --- .../teavm/ast/AbstractStatementVisitor.java | 78 +++++++++++++++++++ .../java/org/teavm/ast/StatementVisitor.java | 4 - .../org/teavm/ast/optimization/Optimizer.java | 7 +- .../RedundantReturnElimination.java | 71 +++++++++++++++++ 4 files changed, 154 insertions(+), 6 deletions(-) create mode 100644 core/src/main/java/org/teavm/ast/AbstractStatementVisitor.java create mode 100644 core/src/main/java/org/teavm/ast/optimization/RedundantReturnElimination.java diff --git a/core/src/main/java/org/teavm/ast/AbstractStatementVisitor.java b/core/src/main/java/org/teavm/ast/AbstractStatementVisitor.java new file mode 100644 index 000000000..cdba07226 --- /dev/null +++ b/core/src/main/java/org/teavm/ast/AbstractStatementVisitor.java @@ -0,0 +1,78 @@ +/* + * Copyright 2017 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.ast; + +public class AbstractStatementVisitor implements StatementVisitor { + @Override + public void visit(AssignmentStatement statement) { + } + + @Override + public void visit(SequentialStatement statement) { + } + + @Override + public void visit(ConditionalStatement statement) { + } + + @Override + public void visit(SwitchStatement statement) { + } + + @Override + public void visit(WhileStatement statement) { + } + + @Override + public void visit(BlockStatement statement) { + } + + @Override + public void visit(BreakStatement statement) { + } + + @Override + public void visit(ContinueStatement statement) { + } + + @Override + public void visit(ReturnStatement statement) { + } + + @Override + public void visit(ThrowStatement statement) { + } + + @Override + public void visit(InitClassStatement statement) { + } + + @Override + public void visit(TryCatchStatement statement) { + } + + @Override + public void visit(GotoPartStatement statement) { + } + + @Override + public void visit(MonitorEnterStatement statement) { + } + + @Override + public void visit(MonitorExitStatement statement) { + } +} diff --git a/core/src/main/java/org/teavm/ast/StatementVisitor.java b/core/src/main/java/org/teavm/ast/StatementVisitor.java index bfb8bb22a..304695c45 100644 --- a/core/src/main/java/org/teavm/ast/StatementVisitor.java +++ b/core/src/main/java/org/teavm/ast/StatementVisitor.java @@ -15,10 +15,6 @@ */ package org.teavm.ast; -/** - * - * @author Alexey Andreev - */ public interface StatementVisitor { void visit(AssignmentStatement statement); diff --git a/core/src/main/java/org/teavm/ast/optimization/Optimizer.java b/core/src/main/java/org/teavm/ast/optimization/Optimizer.java index 6be5e4213..40010bcbf 100644 --- a/core/src/main/java/org/teavm/ast/optimization/Optimizer.java +++ b/core/src/main/java/org/teavm/ast/optimization/Optimizer.java @@ -47,8 +47,8 @@ public class Optimizer { method.getVariables().clear(); method.getVariables().addAll(unusedEliminator.getReorderedVariables()); - RedundantLabelEliminator labelEliminator = new RedundantLabelEliminator(); - method.getBody().acceptVisitor(labelEliminator); + method.getBody().acceptVisitor(new RedundantLabelEliminator()); + method.getBody().acceptVisitor(new RedundantReturnElimination()); for (int i = 0; i < method.getVariables().size(); ++i) { method.getVariables().get(i).setIndex(i); @@ -84,9 +84,12 @@ public class Optimizer { method.getVariables().addAll(unusedEliminator.getReorderedVariables()); RedundantLabelEliminator labelEliminator = new RedundantLabelEliminator(); + RedundantReturnElimination returnElimination = new RedundantReturnElimination(); for (AsyncMethodPart part : method.getBody()) { part.getStatement().acceptVisitor(labelEliminator); + part.getStatement().acceptVisitor(returnElimination); } + for (int i = 0; i < method.getVariables().size(); ++i) { method.getVariables().get(i).setIndex(i); } diff --git a/core/src/main/java/org/teavm/ast/optimization/RedundantReturnElimination.java b/core/src/main/java/org/teavm/ast/optimization/RedundantReturnElimination.java new file mode 100644 index 000000000..52d1bf9f6 --- /dev/null +++ b/core/src/main/java/org/teavm/ast/optimization/RedundantReturnElimination.java @@ -0,0 +1,71 @@ +/* + * Copyright 2017 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.ast.optimization; + +import java.util.List; +import org.teavm.ast.AbstractStatementVisitor; +import org.teavm.ast.BlockStatement; +import org.teavm.ast.ConditionalStatement; +import org.teavm.ast.ReturnStatement; +import org.teavm.ast.SequentialStatement; +import org.teavm.ast.Statement; +import org.teavm.ast.SwitchClause; +import org.teavm.ast.SwitchStatement; +import org.teavm.ast.TryCatchStatement; + +class RedundantReturnElimination extends AbstractStatementVisitor { + @Override + public void visit(SequentialStatement statement) { + handleList(statement.getSequence()); + } + + @Override + public void visit(ConditionalStatement statement) { + handleList(statement.getConsequent()); + handleList(statement.getAlternative()); + } + + @Override + public void visit(SwitchStatement statement) { + handleList(statement.getDefaultClause()); + for (SwitchClause clause : statement.getClauses()) { + handleList(clause.getBody()); + } + } + + @Override + public void visit(BlockStatement statement) { + handleList(statement.getBody()); + } + + @Override + public void visit(TryCatchStatement statement) { + handleList(statement.getProtectedBody()); + handleList(statement.getHandler()); + } + + private void handleList(List statements) { + if (statements.isEmpty()) { + return; + } + Statement last = statements.get(statements.size() - 1); + if (last instanceof ReturnStatement && ((ReturnStatement) last).getResult() == null) { + statements.remove(statements.size() - 1); + } else { + last.acceptVisitor(this); + } + } +}